mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-05 23:04:30 +08:00
191 lines
8.2 KiB
Python
191 lines
8.2 KiB
Python
from PyQt5.QtCore import QObject, QDateTime, QTimer, pyqtSignal, pyqtSlot, pyqtProperty
|
|
|
|
from UM.Application import Application
|
|
from UM.Settings.MachineSettings import MachineSettings
|
|
from UM.Resources import Resources
|
|
from UM.Scene.SceneNode import SceneNode
|
|
|
|
## A class for processing and calculating minimum, currrent and maximum print time.
|
|
#
|
|
# This class contains all the logic relating to calculation and slicing for the
|
|
# time/quality slider concept. It is a rather tricky combination of event handling
|
|
# and state management. The logic behind this is as follows:
|
|
#
|
|
# - A scene change or settting change event happens.
|
|
# We track what the source was of the change, either a scene change, a setting change, an active machine change or something else.
|
|
# - This triggers a new slice with the current settings - this is the "current settings pass".
|
|
# - When the slice is done, we update the current print time and material amount.
|
|
# - If the source of the slice was not a Setting change, we start the second slice pass, the "low quality settings pass". Otherwise we stop here.
|
|
# - When that is done, we update the minimum print time and start the final slcice pass, the "high quality settings pass".
|
|
# - When the high quality pass is done, we update the maximum print time.
|
|
#
|
|
class PrintInformation(QObject):
|
|
class SlicePass:
|
|
CurrentSettings = 1
|
|
LowQualitySettings = 2
|
|
HighQualitySettings = 3
|
|
|
|
class SliceReason:
|
|
SceneChanged = 1
|
|
SettingChanged = 2
|
|
ActiveMachineChanged = 3
|
|
Other = 4
|
|
|
|
def __init__(self, parent = None):
|
|
super().__init__(parent)
|
|
|
|
self._minimum_print_time = QDateTime()
|
|
self._current_print_time = QDateTime()
|
|
self._maximum_print_time = QDateTime()
|
|
|
|
self._material_amount = -1
|
|
|
|
self._time_quality_value = 50
|
|
self._time_quality_changed_timer = QTimer()
|
|
self._time_quality_changed_timer.setInterval(500)
|
|
self._time_quality_changed_timer.setSingleShot(True)
|
|
self._time_quality_changed_timer.timeout.connect(self._updateTimeQualitySettings)
|
|
|
|
self._interpolation_settings = {
|
|
"layer_height": { "minimum": "low", "maximum": "high", "curve": "linear" }
|
|
}
|
|
|
|
self._low_quality_settings = None
|
|
self._current_settings = None
|
|
self._high_quality_settings = None
|
|
|
|
self._slice_pass = None
|
|
self._slice_reason = None
|
|
|
|
Application.getInstance().activeMachineChanged.connect(self._onActiveMachineChanged)
|
|
self._onActiveMachineChanged()
|
|
|
|
Application.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged)
|
|
|
|
self._backend = Application.getInstance().getBackend()
|
|
if self._backend:
|
|
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
|
self._backend.slicingStarted.connect(self._onSlicingStarted)
|
|
|
|
minimumPrintTimeChanged = pyqtSignal()
|
|
@pyqtProperty(QDateTime, notify = minimumPrintTimeChanged)
|
|
def minimumPrintTime(self):
|
|
return self._minimum_print_time
|
|
|
|
currentPrintTimeChanged = pyqtSignal()
|
|
@pyqtProperty(QDateTime, notify = currentPrintTimeChanged)
|
|
def currentPrintTime(self):
|
|
return self._current_print_time
|
|
|
|
maximumPrintTimeChanged = pyqtSignal()
|
|
@pyqtProperty(QDateTime, notify = maximumPrintTimeChanged)
|
|
def maximumPrintTime(self):
|
|
return self._maximum_print_time
|
|
|
|
materialAmountChanged = pyqtSignal()
|
|
@pyqtProperty(float, notify = materialAmountChanged)
|
|
def materialAmount(self):
|
|
return self._material_amount
|
|
|
|
timeQualityValueChanged = pyqtSignal()
|
|
@pyqtProperty(int, notify = timeQualityValueChanged)
|
|
def timeQualityValue(self):
|
|
return self._time_quality_value
|
|
|
|
@pyqtSlot(int)
|
|
def setTimeQualityValue(self, value):
|
|
if value != self._time_quality_value:
|
|
self._time_quality_value = value
|
|
self.timeQualityValueChanged.emit()
|
|
|
|
self._time_quality_changed_timer.start()
|
|
|
|
def _onSlicingStarted(self):
|
|
if self._slice_pass is None:
|
|
self._slice_pass = self.SlicePass.CurrentSettings
|
|
|
|
if self._slice_reason is None:
|
|
self._slice_reason = self.SliceReason.Other
|
|
|
|
def _onPrintDurationMessage(self, time, amount):
|
|
if self._slice_pass == self.SlicePass.CurrentSettings:
|
|
self._current_print_time = QDateTime.fromMSecsSinceEpoch(round(time * 1000))
|
|
self.currentPrintTimeChanged.emit()
|
|
|
|
self._material_amount = round(amount / 10) / 100
|
|
self.materialAmountChanged.emit()
|
|
|
|
if self._slice_reason != self.SliceReason.SettingChanged:
|
|
self._slice_pass = self.SlicePass.LowQualitySettings
|
|
self._backend.slice(settings = self._low_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False)
|
|
else:
|
|
self._slice_pass = None
|
|
self._slice_reason = None
|
|
|
|
elif self._slice_pass == self.SlicePass.LowQualitySettings:
|
|
self._minimum_print_time = QDateTime.fromMSecsSinceEpoch(round(time * 1000))
|
|
self.minimumPrintTimeChanged.emit()
|
|
|
|
self._slice_pass = self.SlicePass.HighQualitySettings
|
|
self._backend.slice(settings = self._high_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False)
|
|
elif self._slice_pass == self.SlicePass.HighQualitySettings:
|
|
self._maximum_print_time = QDateTime.fromMSecsSinceEpoch(round(time * 1000))
|
|
self.maximumPrintTimeChanged.emit()
|
|
|
|
self._slice_pass = None
|
|
self._slice_reason = None
|
|
|
|
def _onActiveMachineChanged(self):
|
|
if self._current_settings:
|
|
self._current_settings.settingChanged.disconnect(self._onSettingChanged)
|
|
|
|
self._current_settings = Application.getInstance().getActiveMachine()
|
|
|
|
if self._current_settings:
|
|
self._current_settings.settingChanged.connect(self._onSettingChanged)
|
|
self._low_quality_settings = None
|
|
self._high_quality_settings = None
|
|
self._updateTimeQualitySettings()
|
|
|
|
self._slice_reason = self.SliceReason.ActiveMachineChanged
|
|
|
|
def _updateTimeQualitySettings(self):
|
|
if not self._current_settings:
|
|
return
|
|
|
|
if not self._low_quality_settings:
|
|
self._low_quality_settings = MachineSettings()
|
|
self._low_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + '.json'))
|
|
self._low_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, 'profiles', 'low_quality.conf'))
|
|
|
|
if not self._high_quality_settings:
|
|
self._high_quality_settings = MachineSettings()
|
|
self._high_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + '.json'))
|
|
self._high_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, 'profiles', 'high_quality.conf'))
|
|
|
|
for key, options in self._interpolation_settings.items():
|
|
minimum_value = None
|
|
if options['minimum'] == 'low':
|
|
minimum_value = self._low_quality_settings.getSettingValueByKey(key)
|
|
elif options['minimum'] == 'high':
|
|
minimum_value = self._high_quality_settings.getSettingValueByKey(key)
|
|
else:
|
|
continue
|
|
|
|
maximum_value = None
|
|
if options['maximum'] == 'low':
|
|
maximum_value = self._low_quality_settings.getSettingValueByKey(key)
|
|
elif options['maximum'] == 'high':
|
|
maximum_value = self._high_quality_settings.getSettingValueByKey(key)
|
|
else:
|
|
continue
|
|
|
|
setting_value = minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100)
|
|
self._current_settings.setSettingValueByKey(key, setting_value)
|
|
|
|
def _onSceneChanged(self, source):
|
|
self._slice_reason = self.SliceReason.SceneChanged
|
|
|
|
def _onSettingChanged(self, source):
|
|
self._slice_reason = self.SliceReason.SettingChanged
|