This commit is contained in:
Tamara Hogenhout 2015-09-02 14:31:21 +02:00
commit de8dbb4856
37 changed files with 843 additions and 1100 deletions

View File

@ -10,6 +10,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Math.Vector import Vector from UM.Math.Vector import Vector
from UM.Math.Color import Color from UM.Math.Color import Color
from UM.Math.AxisAlignedBox import AxisAlignedBox from UM.Math.AxisAlignedBox import AxisAlignedBox
from UM.Math.Polygon import Polygon
import numpy import numpy
@ -33,6 +34,9 @@ class BuildVolume(SceneNode):
self.setCalculateBoundingBox(False) self.setCalculateBoundingBox(False)
self._active_instance = None
Application.getInstance().getMachineManager().activeMachineInstanceChanged.connect(self._onActiveInstanceChanged)
self._onActiveInstanceChanged()
def setWidth(self, width): def setWidth(self, width):
self._width = width self._width = width
@ -55,12 +59,12 @@ class BuildVolume(SceneNode):
if not self._material: if not self._material:
self._material = renderer.createMaterial( self._material = renderer.createMaterial(
Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.Shaders, "basic.vert"),
Resources.getPath(Resources.ShadersLocation, "vertexcolor.frag") Resources.getPath(Resources.Shaders, "vertexcolor.frag")
) )
self._grid_material = renderer.createMaterial( self._grid_material = renderer.createMaterial(
Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.Shaders, "basic.vert"),
Resources.getPath(Resources.ShadersLocation, "grid.frag") Resources.getPath(Resources.Shaders, "grid.frag")
) )
self._grid_material.setUniformValue("u_gridColor0", Color(245, 245, 245, 255)) self._grid_material.setUniformValue("u_gridColor0", Color(245, 245, 245, 255))
self._grid_material.setUniformValue("u_gridColor1", Color(205, 202, 201, 255)) self._grid_material.setUniformValue("u_gridColor1", Color(205, 202, 201, 255))
@ -135,17 +139,18 @@ class BuildVolume(SceneNode):
self._aabb = AxisAlignedBox(minimum = Vector(minW, minH - 1.0, minD), maximum = Vector(maxW, maxH, maxD)) self._aabb = AxisAlignedBox(minimum = Vector(minW, minH - 1.0, minD), maximum = Vector(maxW, maxH, maxD))
settings = Application.getInstance().getActiveMachine()
skirt_size = 0.0 skirt_size = 0.0
if settings.getSettingValueByKey("adhesion_type") == "None":
skirt_size = settings.getSettingValueByKey("skirt_line_count") * settings.getSettingValueByKey("skirt_line_width") + settings.getSettingValueByKey("skirt_gap")
elif settings.getSettingValueByKey("adhesion_type") == "Brim":
skirt_size = settings.getSettingValueByKey("brim_line_count") * settings.getSettingValueByKey("skirt_line_width")
else:
skirt_size = settings.getSettingValueByKey("skirt_line_width")
skirt_size += settings.getSettingValueByKey("skirt_line_width") #profile = Application.getInstance().getMachineManager().getActiveProfile()
#if profile:
#if profile.getSettingValue("adhesion_type") == "skirt":
#skirt_size = profile.getSettingValue("skirt_line_count") * profile.getSettingValue("skirt_line_width") + profile.getSettingValue("skirt_gap")
#elif profile.getSettingValue("adhesion_type") == "brim":
#skirt_size = profile.getSettingValue("brim_line_count") * profile.getSettingValue("skirt_line_width")
#else:
#skirt_size = profile.getSettingValue("skirt_line_width")
#skirt_size += profile.getSettingValue("skirt_line_width")
scale_to_max_bounds = AxisAlignedBox( scale_to_max_bounds = AxisAlignedBox(
minimum = Vector(minW + skirt_size, minH, minD + skirt_size + disallowed_area_size), minimum = Vector(minW + skirt_size, minH, minD + skirt_size + disallowed_area_size),
@ -153,3 +158,21 @@ class BuildVolume(SceneNode):
) )
Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
def _onActiveInstanceChanged(self):
self._active_instance = Application.getInstance().getMachineManager().getActiveMachineInstance()
if self._active_instance:
self._width = self._active_instance.getMachineSettingValue("machine_width")
self._height = self._active_instance.getMachineSettingValue("machine_height")
self._depth = self._active_instance.getMachineSettingValue("machine_depth")
disallowed_areas = self._active_instance.getMachineSettingValue("machine_disallowed_areas")
areas = []
if disallowed_areas:
for area in disallowed_areas:
areas.append(Polygon(numpy.array(area, numpy.float32)))
self._disallowed_areas = areas
self.rebuild()

View File

@ -14,18 +14,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
self._convex_hull_node = None self._convex_hull_node = None
self._convex_hull_job = None self._convex_hull_job = None
settings = Application.getInstance().getActiveMachine()
print_sequence_setting = settings.getSettingByKey("print_sequence") self._profile = None
if print_sequence_setting: Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onActiveProfileChanged)
print_sequence_setting.valueChanged.connect(self._onPrintSequenceSettingChanged) self._onActiveProfileChanged()
def _onPrintSequenceSettingChanged(self, setting):
if self._convex_hull_job:
self._convex_hull_job.cancel()
self.setConvexHull(None)
if self._convex_hull_node:
self._convex_hull_node.setParent(None)
self._convex_hull_node = None
def getConvexHull(self): def getConvexHull(self):
return self._convex_hull return self._convex_hull
@ -61,4 +53,20 @@ class ConvexHullDecorator(SceneNodeDecorator):
def setConvexHullNode(self, node): def setConvexHullNode(self, node):
self._convex_hull_node = node self._convex_hull_node = node
def _onActiveProfileChanged(self):
if self._profile:
self._profile.settingValueChanged.disconnect(self._onSettingValueChanged)
self._profile = Application.getInstance().getMachineManager().getActiveProfile()
if self._profile:
self._profile.settingValueChanged.connect(self._onSettingValueChanged)
def _onSettingValueChanged(self, setting):
if setting == "print_sequence":
if self._convex_hull_job:
self._convex_hull_job.cancel()
self.setConvexHull(None)
if self._convex_hull_node:
self._convex_hull_node.setParent(None)
self._convex_hull_node = None

View File

@ -46,14 +46,14 @@ class ConvexHullJob(Job):
# Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull. # Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
# This is done because of rounding errors. # This is done because of rounding errors.
hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32))) hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32)))
settings = Application.getInstance().getActiveMachine()
profile = Application.getInstance().getMachineManager().getActiveProfile()
if settings.getSettingValueByKey("print_sequence") == "One at a time" and not self._node.getParent().callDecoration("isGroup"): if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
# Printing one at a time and it's not an object in a group # Printing one at a time and it's not an object in a group
self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull)) self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
head_hull = hull.getMinkowskiHull(Polygon(numpy.array(settings.getSettingValueByKey("machine_head_with_fans_polygon"),numpy.float32))) head_hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"),numpy.float32)))
self._node.callDecoration("setConvexHullHead", head_hull) self._node.callDecoration("setConvexHullHead", head_hull)
hull = hull.getMinkowskiHull(Polygon(numpy.array(settings.getSettingValueByKey("machine_head_polygon"),numpy.float32))) hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot()) hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
self._node.callDecoration("setConvexHullNode", hull_node) self._node.callDecoration("setConvexHullNode", hull_node)
self._node.callDecoration("setConvexHull", hull) self._node.callDecoration("setConvexHull", hull)
@ -67,4 +67,3 @@ class ConvexHullJob(Job):
hull_node = self._node.getParent().callDecoration("getConvexHullNode") hull_node = self._node.getParent().callDecoration("getConvexHullNode")
if hull_node: if hull_node:
hull_node.setParent(None) hull_node.setParent(None)

View File

@ -22,10 +22,13 @@ class ConvexHullNode(SceneNode):
self._inherit_orientation = False self._inherit_orientation = False
self._inherit_scale = False self._inherit_scale = False
self._color = Color(35, 35, 35, 0.5)
self._node = node self._node = node
self._node.transformationChanged.connect(self._onNodePositionChanged) self._node.transformationChanged.connect(self._onNodePositionChanged)
self._node.parentChanged.connect(self._onNodeParentChanged) self._node.parentChanged.connect(self._onNodeParentChanged)
#self._onNodePositionChanged(self._node) self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged)
self._onNodeDecoratorsChanged(self._node)
self._hull = hull self._hull = hull
@ -53,27 +56,34 @@ class ConvexHullNode(SceneNode):
def render(self, renderer): def render(self, renderer):
if not self._material: if not self._material:
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag")) self._material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag"))
self._material.setUniformValue("u_color", Color(35, 35, 35, 128))
if self.getParent(): if self.getParent():
self._material.setUniformValue("u_color", self._color)
renderer.queueNode(self, material = self._material, transparent = True) renderer.queueNode(self, material = self._material, transparent = True)
return True return True
def _onNodePositionChanged(self, node): def _onNodePositionChanged(self, node):
#self.setPosition(node.getWorldPosition())
if node.callDecoration("getConvexHull"): if node.callDecoration("getConvexHull"):
node.callDecoration("setConvexHull", None) node.callDecoration("setConvexHull", None)
node.callDecoration("setConvexHullNode", None) node.callDecoration("setConvexHullNode", None)
self.setParent(None) self.setParent(None)
#self._node.transformationChanged.disconnect(self._onNodePositionChanged)
#self._node.parentChanged.disconnect(self._onNodeParentChanged)
def _onNodeParentChanged(self, node): def _onNodeParentChanged(self, node):
if node.getParent(): if node.getParent():
self.setParent(self._original_parent) self.setParent(self._original_parent)
else: else:
self.setParent(None) self.setParent(None)
def _onNodeDecoratorsChanged(self, node):
self._color = Color(35, 35, 35, 0.5)
if not node:
return
if node.hasDecoration("getProfile"):
self._color.setR(0.75)
if node.hasDecoration("getSetting"):
self._color.setG(0.75)

View File

@ -7,9 +7,11 @@ from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit
def show(type, value, tb): def show(type, value, tb):
if not hasattr(sys, "frozen"):
traceback.print_exception(type, value, tb)
application = QCoreApplication.instance() application = QCoreApplication.instance()
if not application: if not application:
traceback.print_exception(type, value, tb)
sys.exit(1) sys.exit(1)
dialog = QDialog() dialog = QDialog()

View File

@ -38,8 +38,9 @@ from . import PrintInformation
from . import CuraActions from . import CuraActions
from . import MultiMaterialDecorator from . import MultiMaterialDecorator
from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty, QEvent from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
from PyQt5.QtGui import QColor, QIcon from PyQt5.QtGui import QColor, QIcon
from PyQt5.QtQml import qmlRegisterUncreatableType
import platform import platform
import sys import sys
@ -49,14 +50,19 @@ import numpy
numpy.seterr(all="ignore") numpy.seterr(all="ignore")
class CuraApplication(QtApplication): class CuraApplication(QtApplication):
class ResourceTypes:
QmlFiles = Resources.UserType + 1
Firmware = Resources.UserType + 2
Q_ENUMS(ResourceTypes)
def __init__(self): def __init__(self):
Resources.addResourcePath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura")) Resources.addSearchPath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura"))
if not hasattr(sys, "frozen"): if not hasattr(sys, "frozen"):
Resources.addResourcePath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..")) Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))
super().__init__(name = "cura", version = "master") super().__init__(name = "cura", version = "master")
self.setWindowIcon(QIcon(Resources.getPath(Resources.ImagesLocation, "cura-icon.png"))) self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
self.setRequiredPlugins([ self.setRequiredPlugins([
"CuraEngineBackend", "CuraEngineBackend",
@ -77,9 +83,13 @@ class CuraApplication(QtApplication):
self._previous_active_tool = None self._previous_active_tool = None
self._platform_activity = False self._platform_activity = False
self.activeMachineChanged.connect(self._onActiveMachineChanged) self.getMachineManager().activeMachineInstanceChanged.connect(self._onActiveMachineChanged)
self.getMachineManager().addMachineRequested.connect(self._onAddMachineRequested)
self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity) self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
Resources.addType(self.ResourceTypes.QmlFiles, "qml")
Resources.addType(self.ResourceTypes.Firmware, "firmware")
Preferences.getInstance().addPreference("cura/active_machine", "") Preferences.getInstance().addPreference("cura/active_machine", "")
Preferences.getInstance().addPreference("cura/active_mode", "simple") Preferences.getInstance().addPreference("cura/active_mode", "simple")
Preferences.getInstance().addPreference("cura/recent_files", "") Preferences.getInstance().addPreference("cura/recent_files", "")
@ -158,21 +168,14 @@ class CuraApplication(QtApplication):
self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Loading interface...")) self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Loading interface..."))
self.setMainQml(Resources.getPath(Resources.QmlFilesLocation, "Cura.qml")) self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
self.initializeEngine() self.initializeEngine()
if self.getMachines(): manager = self.getMachineManager()
active_machine_pref = Preferences.getInstance().getValue("cura/active_machine") if not self.getMachineManager().getMachineInstances():
if active_machine_pref:
for machine in self.getMachines():
if machine.getName() == active_machine_pref:
self.setActiveMachine(machine)
if not self.getActiveMachine():
self.setActiveMachine(self.getMachines()[0])
else:
self.requestAddPrinter.emit() self.requestAddPrinter.emit()
if self._engine.rootObjects: if self._engine.rootObjects:
self.closeSplash() self.closeSplash()
@ -198,6 +201,8 @@ class CuraApplication(QtApplication):
self._cura_actions = CuraActions.CuraActions(self) self._cura_actions = CuraActions.CuraActions(self)
engine.rootContext().setContextProperty("CuraActions", self._cura_actions) engine.rootContext().setContextProperty("CuraActions", self._cura_actions)
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
def onSelectionChanged(self): def onSelectionChanged(self):
if Selection.hasSelection(): if Selection.hasSelection():
if not self.getController().getActiveTool(): if not self.getController().getActiveTool():
@ -393,18 +398,18 @@ class CuraApplication(QtApplication):
@pyqtSlot(str, result = "QVariant") @pyqtSlot(str, result = "QVariant")
def getSettingValue(self, key): def getSettingValue(self, key):
if not self.getActiveMachine(): if not self.getMachineManager().getActiveProfile():
return None return None
return self.getMachineManager().getActiveProfile().getSettingValue(key)
return self.getActiveMachine().getSettingValueByKey(key) #return self.getActiveMachine().getSettingValueByKey(key)
## Change setting by key value pair ## Change setting by key value pair
@pyqtSlot(str, "QVariant") @pyqtSlot(str, "QVariant")
def setSettingValue(self, key, value): def setSettingValue(self, key, value):
if not self.getActiveMachine(): if not self.getMachineManager().getActiveProfile():
return return
self.getActiveMachine().setSettingValueByKey(key, value) self.getMachineManager().getActiveProfile().setSettingValue(key, value)
@pyqtSlot() @pyqtSlot()
def mergeSelected(self): def mergeSelected(self):
@ -460,29 +465,30 @@ class CuraApplication(QtApplication):
Selection.remove(node) Selection.remove(node)
def _onActiveMachineChanged(self): def _onActiveMachineChanged(self):
machine = self.getActiveMachine() machine = self.getMachineManager().getActiveMachineInstance()
if machine: if machine:
Preferences.getInstance().setValue("cura/active_machine", machine.getName()) pass
#Preferences.getInstance().setValue("cura/active_machine", machine.getName())
self._volume.setWidth(machine.getSettingValueByKey("machine_width")) #self._volume.setWidth(machine.getSettingValueByKey("machine_width"))
self._volume.setHeight(machine.getSettingValueByKey("machine_height")) #self._volume.setHeight(machine.getSettingValueByKey("machine_height"))
self._volume.setDepth(machine.getSettingValueByKey("machine_depth")) #self._volume.setDepth(machine.getSettingValueByKey("machine_depth"))
disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas") #disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas")
areas = [] #areas = []
if disallowed_areas: #if disallowed_areas:
for area in disallowed_areas: #for area in disallowed_areas:
areas.append(Polygon(numpy.array(area, numpy.float32))) #areas.append(Polygon(numpy.array(area, numpy.float32)))
self._volume.setDisallowedAreas(areas) #self._volume.setDisallowedAreas(areas)
self._volume.rebuild() #self._volume.rebuild()
offset = machine.getSettingValueByKey("machine_platform_offset") #offset = machine.getSettingValueByKey("machine_platform_offset")
if offset: #if offset:
self._platform.setPosition(Vector(offset[0], offset[1], offset[2])) #self._platform.setPosition(Vector(offset[0], offset[1], offset[2]))
else: #else:
self._platform.setPosition(Vector(0.0, 0.0, 0.0)) #self._platform.setPosition(Vector(0.0, 0.0, 0.0))
def _onFileLoaded(self, job): def _onFileLoaded(self, job):
node = job.getResult() node = job.getResult()
@ -520,3 +526,5 @@ class CuraApplication(QtApplication):
job.finished.connect(self._onFileLoaded) job.finished.connect(self._onFileLoaded)
job.start() job.start()
def _onAddMachineRequested(self):
self.requestAddPrinter.emit()

View File

@ -17,7 +17,7 @@ class OneAtATimeIterator(Iterator.Iterator):
def _fillStack(self): def _fillStack(self):
node_list = [] node_list = []
for node in self._scene_node.getChildren(): for node in self._scene_node.getChildren():
if node.getBoundingBox().height > Application.getInstance().getActiveMachine().getSettingValueByKey("gantry_height"): if node.getBoundingBox().height > Application.getInstance().getMachineManager().getActiveProfile().getSettingValue("gantry_height"):
return return
if node.callDecoration("getConvexHull"): if node.callDecoration("getConvexHull"):
node_list.append(node) node_list.append(node)
@ -103,4 +103,4 @@ class _objectOrder():
""" """
self.order = order self.order = order
self.todo = todo self.todo = todo

View File

@ -40,48 +40,13 @@ class PrintInformation(QObject):
def __init__(self, parent = None): def __init__(self, parent = None):
super().__init__(parent) super().__init__(parent)
self._enabled = False
self._minimum_print_time = Duration(None, self)
self._current_print_time = Duration(None, self) self._current_print_time = Duration(None, self)
self._maximum_print_time = Duration(None, self)
self._material_amount = -1 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", "precision": 2 },
"fill_sparse_density": { "minimum": "low", "maximum": "high", "curve": "linear", "precision": 0 }
}
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() self._backend = Application.getInstance().getBackend()
if self._backend: if self._backend:
self._backend.printDurationMessage.connect(self._onPrintDurationMessage) self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
self._backend.slicingStarted.connect(self._onSlicingStarted)
self._backend.slicingCancelled.connect(self._onSlicingCancelled)
minimumPrintTimeChanged = pyqtSignal()
@pyqtProperty(Duration, notify = minimumPrintTimeChanged)
def minimumPrintTime(self):
return self._minimum_print_time
currentPrintTimeChanged = pyqtSignal() currentPrintTimeChanged = pyqtSignal()
@ -89,145 +54,18 @@ class PrintInformation(QObject):
def currentPrintTime(self): def currentPrintTime(self):
return self._current_print_time return self._current_print_time
maximumPrintTimeChanged = pyqtSignal()
@pyqtProperty(Duration, notify = maximumPrintTimeChanged)
def maximumPrintTime(self):
return self._maximum_print_time
materialAmountChanged = pyqtSignal() materialAmountChanged = pyqtSignal()
@pyqtProperty(float, notify = materialAmountChanged) @pyqtProperty(float, notify = materialAmountChanged)
def materialAmount(self): def materialAmount(self):
return self._material_amount return self._material_amount
timeQualityValueChanged = pyqtSignal()
@pyqtProperty(int, notify = timeQualityValueChanged)
def timeQualityValue(self):
return self._time_quality_value
def setEnabled(self, enabled):
if enabled != self._enabled:
self._enabled = enabled
if self._enabled:
self._updateTimeQualitySettings()
self._onSlicingStarted()
self.enabledChanged.emit()
enabledChanged = pyqtSignal()
@pyqtProperty(bool, fset = setEnabled, notify = enabledChanged)
def enabled(self):
return self._enabled
@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
if self._slice_pass == self.SlicePass.CurrentSettings and self._slice_reason != self.SliceReason.SettingChanged:
self._minimum_print_time.setDuration(-1)
self.minimumPrintTimeChanged.emit()
self._maximum_print_time.setDuration(-1)
self.maximumPrintTimeChanged.emit()
def _onPrintDurationMessage(self, time, amount): def _onPrintDurationMessage(self, time, amount):
if self._slice_pass == self.SlicePass.CurrentSettings: #if self._slice_pass == self.SlicePass.CurrentSettings:
self._current_print_time.setDuration(time) self._current_print_time.setDuration(time)
self.currentPrintTimeChanged.emit() self.currentPrintTimeChanged.emit()
# Material amount is sent as an amount of mm^3, so calculate length from that # Material amount is sent as an amount of mm^3, so calculate length from that
r = self._current_settings.getSettingValueByKey("material_diameter") / 2 r = Application.getInstance().getMachineManager().getActiveProfile().getSettingValue("material_diameter") / 2
self._material_amount = round((amount / (math.pi * r ** 2)) / 1000, 2) self._material_amount = round((amount / (math.pi * r ** 2)) / 1000, 2)
self.materialAmountChanged.emit() self.materialAmountChanged.emit()
if not self._enabled:
return
if self._slice_reason != self.SliceReason.SettingChanged or not self._minimum_print_time.valid or not self._maximum_print_time.valid:
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.setDuration(time)
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.setDuration(time)
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 or not self._enabled:
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 = round(minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100), options["precision"])
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
def _onSlicingCancelled(self):
self._slice_pass = None

View File

@ -10,6 +10,7 @@ from UM.Math.Vector import Vector
from UM.Signal import Signal from UM.Signal import Signal
from UM.Logger import Logger from UM.Logger import Logger
from UM.Resources import Resources from UM.Resources import Resources
from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator
from cura.OneAtATimeIterator import OneAtATimeIterator from cura.OneAtATimeIterator import OneAtATimeIterator
from . import Cura_pb2 from . import Cura_pb2
@ -44,9 +45,10 @@ class CuraEngineBackend(Backend):
self._onActiveViewChanged() self._onActiveViewChanged()
self._stored_layer_data = None self._stored_layer_data = None
self._settings = None
Application.getInstance().activeMachineChanged.connect(self._onActiveMachineChanged) self._profile = None
self._onActiveMachineChanged() Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onActiveProfileChanged)
self._onActiveProfileChanged()
self._change_timer = QTimer() self._change_timer = QTimer()
self._change_timer.setInterval(500) self._change_timer.setInterval(500)
@ -71,7 +73,7 @@ class CuraEngineBackend(Backend):
self.backendConnected.connect(self._onBackendConnected) self.backendConnected.connect(self._onBackendConnected)
def getEngineCommand(self): def getEngineCommand(self):
return [Preferences.getInstance().getValue("backend/location"),"connect", "127.0.0.1:{0}".format(self._port), "-j", Resources.getPath(Resources.SettingsLocation, "fdmprinter.json"), "-vv"] return [Preferences.getInstance().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", Resources.getPath(Resources.MachineDefinitions, "fdmprinter.json"), "-vv"]
## Emitted when we get a message containing print duration and material amount. This also implies the slicing has finished. ## Emitted when we get a message containing print duration and material amount. This also implies the slicing has finished.
# \param time The amount of time the print will take. # \param time The amount of time the print will take.
@ -114,7 +116,7 @@ class CuraEngineBackend(Backend):
return return
object_groups = [] object_groups = []
if self._settings.getSettingValueByKey("print_sequence") == "One at a time": if self._profile.getSettingValue("print_sequence") == "one_at_a_time":
for node in OneAtATimeIterator(self._scene.getRoot()): for node in OneAtATimeIterator(self._scene.getRoot()):
temp_list = [] temp_list = []
children = node.getAllChildren() children = node.getAllChildren()
@ -141,7 +143,8 @@ class CuraEngineBackend(Backend):
if len(object_groups) == 0: if len(object_groups) == 0:
return #No point in slicing an empty build plate return #No point in slicing an empty build plate
if kwargs.get("settings", self._settings).hasErrorValue(): if kwargs.get("profile", self._profile).hasErrorValue():
Logger.log('w', "Profile has error values. Aborting slicing")
return #No slicing if we have error values since those are by definition illegal values. return #No slicing if we have error values since those are by definition illegal values.
self._slicing = True self._slicing = True
@ -151,7 +154,7 @@ class CuraEngineBackend(Backend):
if self._report_progress: if self._report_progress:
self.processingProgress.emit(0.0) self.processingProgress.emit(0.0)
self._sendSettings(kwargs.get("settings", self._settings)) self._sendSettings(kwargs.get("profile", self._profile))
self._scene.acquireLock() self._scene.acquireLock()
@ -179,6 +182,12 @@ class CuraEngineBackend(Backend):
verts[:,1] *= -1 verts[:,1] *= -1
obj.vertices = verts.tostring() obj.vertices = verts.tostring()
self._handlePerObjectSettings(object, obj)
# Hack to add per-object settings also to the "MeshGroup" in CuraEngine
# We really should come up with a better solution for this.
self._handlePerObjectSettings(group[0], group_message)
self._scene.releaseLock() self._scene.releaseLock()
self._socket.sendMessage(slice_message) self._socket.sendMessage(slice_message)
@ -191,13 +200,14 @@ class CuraEngineBackend(Backend):
self._onChanged() self._onChanged()
def _onActiveMachineChanged(self):
if self._settings:
self._settings.settingChanged.disconnect(self._onSettingChanged)
self._settings = Application.getInstance().getActiveMachine() def _onActiveProfileChanged(self):
if self._settings: if self._profile:
self._settings.settingChanged.connect(self._onSettingChanged) self._profile.settingValueChanged.disconnect(self._onSettingChanged)
self._profile = Application.getInstance().getMachineManager().getActiveProfile()
if self._profile:
self._profile.settingValueChanged.connect(self._onSettingChanged)
self._onChanged() self._onChanged()
def _onSettingChanged(self, setting): def _onSettingChanged(self, setting):
@ -247,17 +257,17 @@ class CuraEngineBackend(Backend):
self._change_timer.start() self._change_timer.start()
def _onChanged(self): def _onChanged(self):
if not self._settings: if not self._profile:
return return
self._change_timer.start() self._change_timer.start()
def _sendSettings(self, settings): def _sendSettings(self, profile):
msg = Cura_pb2.SettingList() msg = Cura_pb2.SettingList()
for setting in settings.getAllSettings(include_machine=True): for key, value in profile.getAllSettingValues(include_machine = True).items():
s = msg.settings.add() s = msg.settings.add()
s.name = setting.getKey() s.name = key
s.value = str(setting.getValue()).encode("utf-8") s.value = str(value).encode("utf-8")
self._socket.sendMessage(msg) self._socket.sendMessage(msg)
@ -283,3 +293,20 @@ class CuraEngineBackend(Backend):
job.start() job.start()
else: else:
self._layer_view_active = False self._layer_view_active = False
def _handlePerObjectSettings(self, node, message):
profile = node.callDecoration("getProfile")
if profile:
for key, value in profile.getChangedSettings().items():
setting = message.settings.add()
setting.name = key
setting.value = str(value).encode()
object_settings = node.callDecoration("getAllSettingValues")
if not object_settings:
return
for key, value in object_settings.items():
setting = message.settings.add()
setting.name = key
setting.value = str(value).encode()

View File

@ -18,7 +18,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name='Cura.proto', name='Cura.proto',
package='cura.proto', package='cura.proto',
serialized_pb=_b('\n\nCura.proto\x12\ncura.proto\"1\n\nObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.cura.proto.Object\"5\n\x05Slice\x12,\n\x0cobject_lists\x18\x01 \x03(\x0b\x32\x16.cura.proto.ObjectList\"o\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12%\n\x08settings\x18\x05 \x03(\x0b\x32\x13.cura.proto.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"=\n\x10SlicedObjectList\x12)\n\x07objects\x18\x01 \x03(\x0b\x32\x18.cura.proto.SlicedObject\"=\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12!\n\x06layers\x18\x02 \x03(\x0b\x32\x11.cura.proto.Layer\"]\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x02\x12\x11\n\tthickness\x18\x03 \x01(\x02\x12%\n\x08polygons\x18\x04 \x03(\x0b\x32\x13.cura.proto.Polygon\"\xe1\x01\n\x07Polygon\x12&\n\x04type\x18\x01 \x01(\x0e\x32\x18.cura.proto.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\x12\x12\n\nline_width\x18\x03 \x01(\x02\"\x89\x01\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\x12\x0e\n\nInfillType\x10\x06\x12\x15\n\x11SupportInfillType\x10\x07\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\"4\n\x0bSettingList\x12%\n\x08settings\x18\x01 \x03(\x0b\x32\x13.cura.proto.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3') serialized_pb=_b('\n\nCura.proto\x12\ncura.proto\"X\n\nObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.cura.proto.Object\x12%\n\x08settings\x18\x02 \x03(\x0b\x32\x13.cura.proto.Setting\"5\n\x05Slice\x12,\n\x0cobject_lists\x18\x01 \x03(\x0b\x32\x16.cura.proto.ObjectList\"o\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12%\n\x08settings\x18\x05 \x03(\x0b\x32\x13.cura.proto.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"=\n\x10SlicedObjectList\x12)\n\x07objects\x18\x01 \x03(\x0b\x32\x18.cura.proto.SlicedObject\"=\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12!\n\x06layers\x18\x02 \x03(\x0b\x32\x11.cura.proto.Layer\"]\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x02\x12\x11\n\tthickness\x18\x03 \x01(\x02\x12%\n\x08polygons\x18\x04 \x03(\x0b\x32\x13.cura.proto.Polygon\"\xe1\x01\n\x07Polygon\x12&\n\x04type\x18\x01 \x01(\x0e\x32\x18.cura.proto.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\x12\x12\n\nline_width\x18\x03 \x01(\x02\"\x89\x01\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\x12\x0e\n\nInfillType\x10\x06\x12\x15\n\x11SupportInfillType\x10\x07\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\"4\n\x0bSettingList\x12%\n\x08settings\x18\x01 \x03(\x0b\x32\x13.cura.proto.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3')
) )
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
@ -65,8 +65,8 @@ _POLYGON_TYPE = _descriptor.EnumDescriptor(
], ],
containing_type=None, containing_type=None,
options=None, options=None,
serialized_start=583, serialized_start=622,
serialized_end=720, serialized_end=759,
) )
_sym_db.RegisterEnumDescriptor(_POLYGON_TYPE) _sym_db.RegisterEnumDescriptor(_POLYGON_TYPE)
@ -85,6 +85,13 @@ _OBJECTLIST = _descriptor.Descriptor(
message_type=None, enum_type=None, containing_type=None, message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None, is_extension=False, extension_scope=None,
options=None), options=None),
_descriptor.FieldDescriptor(
name='settings', full_name='cura.proto.ObjectList.settings', index=1,
number=2, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
], ],
extensions=[ extensions=[
], ],
@ -97,7 +104,7 @@ _OBJECTLIST = _descriptor.Descriptor(
oneofs=[ oneofs=[
], ],
serialized_start=26, serialized_start=26,
serialized_end=75, serialized_end=114,
) )
@ -126,8 +133,8 @@ _SLICE = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=77, serialized_start=116,
serialized_end=130, serialized_end=169,
) )
@ -184,8 +191,8 @@ _OBJECT = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=132, serialized_start=171,
serialized_end=243, serialized_end=282,
) )
@ -214,8 +221,8 @@ _PROGRESS = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=245, serialized_start=284,
serialized_end=271, serialized_end=310,
) )
@ -244,8 +251,8 @@ _SLICEDOBJECTLIST = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=273, serialized_start=312,
serialized_end=334, serialized_end=373,
) )
@ -281,8 +288,8 @@ _SLICEDOBJECT = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=336, serialized_start=375,
serialized_end=397, serialized_end=436,
) )
@ -332,8 +339,8 @@ _LAYER = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=399, serialized_start=438,
serialized_end=492, serialized_end=531,
) )
@ -377,8 +384,8 @@ _POLYGON = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=495, serialized_start=534,
serialized_end=720, serialized_end=759,
) )
@ -414,8 +421,8 @@ _GCODELAYER = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=722, serialized_start=761,
serialized_end=760, serialized_end=799,
) )
@ -458,8 +465,8 @@ _OBJECTPRINTTIME = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=762, serialized_start=801,
serialized_end=830, serialized_end=869,
) )
@ -488,8 +495,8 @@ _SETTINGLIST = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=832, serialized_start=871,
serialized_end=884, serialized_end=923,
) )
@ -525,8 +532,8 @@ _SETTING = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=886, serialized_start=925,
serialized_end=924, serialized_end=963,
) )
@ -555,11 +562,12 @@ _GCODEPREFIX = _descriptor.Descriptor(
extension_ranges=[], extension_ranges=[],
oneofs=[ oneofs=[
], ],
serialized_start=926, serialized_start=965,
serialized_end=953, serialized_end=992,
) )
_OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT _OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT
_OBJECTLIST.fields_by_name['settings'].message_type = _SETTING
_SLICE.fields_by_name['object_lists'].message_type = _OBJECTLIST _SLICE.fields_by_name['object_lists'].message_type = _OBJECTLIST
_OBJECT.fields_by_name['settings'].message_type = _SETTING _OBJECT.fields_by_name['settings'].message_type = _SETTING
_SLICEDOBJECTLIST.fields_by_name['objects'].message_type = _SLICEDOBJECT _SLICEDOBJECTLIST.fields_by_name['objects'].message_type = _SLICEDOBJECT

View File

@ -43,12 +43,12 @@ class ProcessSlicedObjectListJob(Job):
else: else:
objectIdMap[id(node)] = node objectIdMap[id(node)] = node
settings = Application.getInstance().getActiveMachine() settings = Application.getInstance().getMachineManager().getActiveProfile()
layerHeight = settings.getSettingValueByKey("layer_height") layerHeight = settings.getSettingValue("layer_height")
center = None center = None
if not settings.getSettingValueByKey("machine_center_is_zero"): if not settings.getSettingValue("machine_center_is_zero"):
center = numpy.array([settings.getSettingValueByKey("machine_width") / 2, 0.0, -settings.getSettingValueByKey("machine_depth") / 2]) center = numpy.array([settings.getSettingValue("machine_width") / 2, 0.0, -settings.getSettingValue("machine_depth") / 2])
else: else:
center = numpy.array([0.0, 0.0, 0.0]) center = numpy.array([0.0, 0.0, 0.0])

View File

@ -52,10 +52,10 @@ class LayerView(View):
renderer.setRenderSelection(False) renderer.setRenderSelection(False)
if not self._material: if not self._material:
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "vertexcolor.frag")) self._material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag"))
self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0]) self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0])
self._selection_material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag")) self._selection_material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag"))
self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128)) self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128))
for node in DepthFirstIterator(scene.getRoot()): for node in DepthFirstIterator(scene.getRoot()):

View File

@ -1,8 +1,12 @@
{ {
"version": 1, "version": 1,
"id": "dual_extrusion",
"name": "Dual Extrusion Base File",
"inherits": "fdmprinter.json", "inherits": "fdmprinter.json",
"visible": false,
"machine_settings": { "machine_settings": {
"extruder_nr": { "extruder_nr": {
"label": "Extruder", "label": "Extruder",
@ -285,4 +289,4 @@
} }
} }
} }
} }

View File

@ -78,9 +78,9 @@
}, },
"overrides": { "overrides": {
"material_print_temperature": { "visible": false }, "material_print_temperature": { "enabled": "False" },
"material_bed_temperature": { "visible": false }, "material_bed_temperature": { "enabled": "False" },
"material_diameter": { "visible": false }, "material_diameter": { "enabled": "False" },
"material_flow": { "visible": false } "material_flow": { "enabled": "False" }
} }
} }

View File

@ -10,6 +10,13 @@
"inherits": "ultimaker_original.json", "inherits": "ultimaker_original.json",
"pages": [
"SelectUpgradedParts",
"UpgradeFirmware",
"UltimakerCheckup",
"BedLeveling"
],
"machine_settings": { "machine_settings": {
"machine_heated_bed": { "default": true } "machine_heated_bed": { "default": true }
} }

View File

@ -0,0 +1,6 @@
[general]
version = 1
name = High Quality
[settings]
layer_height = 0.06

View File

@ -0,0 +1,6 @@
[general]
version = 1
name = Normal Quality
[settings]
layer_height = 0.1

View File

@ -7,24 +7,26 @@ import QtQuick.Layouts 1.1
import QtQuick.Window 2.1 import QtQuick.Window 2.1
import UM 1.1 as UM import UM 1.1 as UM
import Cura 1.0 as Cura
import "WizardPages"
UM.Wizard UM.Wizard
{ {
//: Add Printer dialog title id: base;
wizardTitle: catalog.i18nc("@title:wizard","Add Printer")
wizardPages: [ title: catalog.i18nc("@title:window", "Add Printer")
{
title: "Add Printer",
page: "AddMachine.qml"
}
]
Item
{
UM.I18nCatalog{id: catalog; name:"cura"}
}
// This part is optional // This part is optional
// This part checks whether there is a printer -> if not: some of the functions (delete for example) are disabled // This part checks whether there is a printer -> if not: some of the functions (delete for example) are disabled
property bool printer: true firstRun: false
firstRun: printer ? false : true
Component.onCompleted: {
base.appendPage(UM.Resources.getPath(Cura.ResourceTypes.QmlFiles, "WizardPages/AddMachine.qml"), catalog.i18nc("@title", "Add Printer"));
base.currentPage = 0;
}
Item {
UM.I18nCatalog { id: catalog; name: "cura"; }
}
} }

View File

@ -80,7 +80,7 @@ UM.MainWindow
id: saveAllMenu id: saveAllMenu
title: catalog.i18nc("@title:menu","Save All") title: catalog.i18nc("@title:menu","Save All")
iconName: "document-save"; iconName: "document-save";
enabled: devicesModel.count > 0 && UM.Backend.progress > 0.99; enabled: devicesModel.rowCount() > 0 && UM.Backend.progress > 0.99;
Instantiator Instantiator
{ {
@ -131,6 +131,10 @@ UM.MainWindow
onObjectRemoved: top_view_menu.removeItem(object) onObjectRemoved: top_view_menu.removeItem(object)
} }
ExclusiveGroup { id: view_menu_top_group; } ExclusiveGroup { id: view_menu_top_group; }
MenuSeparator { }
MenuItem { action: actions.toggleFullScreen; }
} }
Menu Menu
{ {
@ -140,14 +144,14 @@ UM.MainWindow
Instantiator Instantiator
{ {
model: UM.Models.machinesModel model: UM.MachineInstancesModel { }
MenuItem MenuItem
{ {
text: model.name; text: model.name;
checkable: true; checkable: true;
checked: model.active; checked: model.active;
exclusiveGroup: machineMenuGroup; exclusiveGroup: machineMenuGroup;
onTriggered: UM.Models.machinesModel.setActive(index) onTriggered: UM.MachineManager.setActiveMachineInstance(model.name)
} }
onObjectAdded: machineMenu.insertItem(index, object) onObjectAdded: machineMenu.insertItem(index, object)
onObjectRemoved: machineMenu.removeItem(object) onObjectRemoved: machineMenu.removeItem(object)
@ -157,6 +161,24 @@ UM.MainWindow
MenuSeparator { } MenuSeparator { }
Instantiator
{
model: UM.MachineVariantsModel { }
MenuItem {
text: model.name;
checkable: true;
checked: model.active;
exclusiveGroup: machineVariantsGroup;
onTriggered: UM.MachineManager.setActiveMachineVariant(model.name)
}
onObjectAdded: machineMenu.insertItem(index, object)
onObjectRemoved: machineMenu.removeItem(object)
}
ExclusiveGroup { id: machineVariantsGroup; }
MenuSeparator { visible: UM.MachineManager.hasVariants; }
MenuItem { action: actions.addMachine; } MenuItem { action: actions.addMachine; }
MenuItem { action: actions.configureMachines; } MenuItem { action: actions.configureMachines; }
} }
@ -586,10 +608,10 @@ UM.MainWindow
onRequestAddPrinter: onRequestAddPrinter:
{ {
addMachineWizard.visible = true addMachineWizard.visible = true
addMachineWizard.printer = false addMachineWizard.firstRun = true
} }
} }
Component.onCompleted: UM.Theme.load(UM.Resources.getPath(UM.Resources.ThemesLocation, "cura")) Component.onCompleted: UM.Theme.load(UM.Resources.getPath(UM.Resources.Themes, "cura"))
} }

View File

@ -63,10 +63,93 @@ Rectangle
onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex); onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex);
} }
Loader{ Item
{
id: variantItem;
anchors.top: header.bottom;
height: UM.Theme.sizes.setting.height;
visible: UM.MachineManager.hasVariants;
Row
{
spacing: UM.Theme.sizes.default_margin.width;
Label
{
anchors.verticalCenter: parent.verticalCenter;
text: catalog.i18nc("@label","Variant");
}
ComboBox {
anchors.verticalCenter: parent.verticalCenter;
model: UM.MachineVariantsModel { }
textRole: "name"
onActivated: UM.MachineManager.setActiveMachineVariant(model.getItem(index).name);
currentIndex:
{
for(var i = 0; i < model.rowCount(); ++i)
{
if(model.getItem(i).name == UM.MachineManager.activeMachineVariant)
{
return i;
}
}
return 0;
}
}
}
}
Item
{
id: profileItem;
anchors.top: variantItem.bottom;
height: UM.Theme.sizes.setting.height;
Row
{
spacing: UM.Theme.sizes.default_margin.width;
Label
{
anchors.verticalCenter: parent.verticalCenter;
text: catalog.i18nc("@label","Global Profile");
}
ComboBox
{
anchors.verticalCenter: parent.verticalCenter;
model: UM.ProfilesModel { }
textRole: "name"
onActivated: UM.MachineManager.setActiveProfile(model.getItem(index).name)
currentIndex:
{
for(var i = 0; i < model.rowCount(); ++i)
{
if(model.getItem(i).name == UM.MachineManager.activeProfile)
return i;
}
UM.MachineManager.setActiveProfile(model.getItem(0).name)
return 0;
}
}
Button
{
text: catalog.i18nc("@action:button", "Save");
}
}
}
Loader
{
id: sidebarContents; id: sidebarContents;
anchors.bottom: saveButton.top anchors.bottom: saveButton.top
anchors.top: header.bottom anchors.top: profileItem.bottom
anchors.left: base.left anchors.left: base.left
anchors.right: base.right anchors.right: base.right
@ -91,7 +174,8 @@ Rectangle
} }
} }
SaveButton { SaveButton
{
id: saveButton; id: saveButton;
implicitWidth: base.width implicitWidth: base.width
implicitHeight: totalHeight implicitHeight: totalHeight

View File

@ -103,10 +103,11 @@ Item
ToolButton { ToolButton {
id: machineSelection id: machineSelection
text: UM.Application.machineName; text: UM.MachineManager.activeMachineInstance;
width: parent.width/100*55 width: parent.width/100*55
height: UM.Theme.sizes.setting_control.height height: UM.Theme.sizes.setting_control.height
tooltip: UM.Application.machineName; tooltip: UM.MachineManager.activeMachineInstance;
//style: UM.Theme.styles.sidebar_header_button;
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: UM.Theme.sizes.default_margin.width anchors.rightMargin: UM.Theme.sizes.default_margin.width
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -117,17 +118,17 @@ Item
id: machineSelectionMenu id: machineSelectionMenu
Instantiator Instantiator
{ {
model: UM.Models.machinesModel model: UM.MachineInstancesModel { }
MenuItem MenuItem
{ {
text: model.name; text: model.name;
checkable: true; checkable: true;
checked: model.active; checked: model.active;
exclusiveGroup: machineMenuGroup; exclusiveGroup: machineSelectionMenuGroup;
onTriggered: UM.Models.machinesModel.setActive(index) onTriggered: UM.MachineManager.setActiveMachineInstance(model.name);
} }
onObjectAdded: machineMenu.insertItem(index, object) onObjectAdded: machineSelectionMenu.insertItem(index, object)
onObjectRemoved: machineMenu.removeItem(object) onObjectRemoved: machineSelectionMenu.removeItem(object)
} }
ExclusiveGroup { id: machineSelectionMenuGroup; } ExclusiveGroup { id: machineSelectionMenuGroup; }

View File

@ -8,43 +8,33 @@ import QtQuick.Window 2.1
import QtQuick.Controls.Styles 1.1 import QtQuick.Controls.Styles 1.1
import UM 1.1 as UM import UM 1.1 as UM
import Cura 1.0 as Cura
import ".." import ".."
ColumnLayout Item
{ {
id: wizardPage id: base
property string title
property int pageWidth
property int pageHeight
property var manufacturers: wizardPage.lineManufacturers()
property int manufacturerIndex: 0
SystemPalette {id: palette} property string activeManufacturer: "Ultimaker";
signal reloadModel(var newModel)
property variant wizard: null;
width: wizardPage.pageWidth
height: wizardPage.pageHeight
UM.I18nCatalog { id: catalog; name: "cura"}
Connections Connections
{ {
target: elementRoot target: base.wizard
onNextClicked: //You can add functions here that get triggered when the final button is clicked in the wizard-element onNextClicked: //You can add functions here that get triggered when the final button is clicked in the wizard-element
{ {
saveMachine() saveMachine()
} }
} onBackClicked:
function lineManufacturers(manufacturer)
{
var manufacturers = []
for (var i = 0; i < UM.Models.availableMachinesModel.rowCount(); i++)
{ {
if (UM.Models.availableMachinesModel.getItem(i).manufacturer != manufacturers[manufacturers.length - 1]) var old_page_count = base.wizard.getPageCount()
// Delete old pages (if any)
for (var i = old_page_count - 1; i > 0; i--)
{ {
manufacturers.push(UM.Models.availableMachinesModel.getItem(i).manufacturer) base.wizard.removePage(i)
} }
} }
return manufacturers
} }
Label Label
@ -52,7 +42,7 @@ ColumnLayout
id: title id: title
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
text: parent.title text: catalog.i18nc("@title", "Add Printer")
font.pointSize: 18; font.pointSize: 18;
} }
@ -61,164 +51,121 @@ ColumnLayout
id: subTitle id: subTitle
anchors.left: parent.left anchors.left: parent.left
anchors.top: title.bottom anchors.top: title.bottom
//: Add Printer wizard page description text: catalog.i18nc("@label", "Please select the type of printer:");
text: catalog.i18nc("@label","Please select the type of printer:");
} }
ScrollView ScrollView
{ {
id: machinesHolder id: machinesHolder
anchors.left: parent.left
anchors.top: subTitle.bottom
implicitWidth: wizardPage.width- UM.Theme.sizes.default_margin.width
implicitHeight: wizardPage.height - subTitle.height - title.height - (machineNameHolder.height * 2)
Component anchors{
{ left: parent.left;
id: machineDelegate top: subTitle.bottom;
ColumnLayout right: parent.right;
{ bottom: machineNameHolder.top;
id: machineLayout
spacing: 0
anchors.left: parent.left
anchors.leftMargin: UM.Theme.sizes.standard_list_lineheight.width
function showManufacturer()
{
if (model.manufacturer == UM.Models.availableMachinesModel.getItem(index - 1).manufacturer){
return false
}
else{
return true
}
}
height:
{
if (machineLayout.showManufacturer() & wizardPage.manufacturers[wizardPage.manufacturerIndex] == model.manufacturer)
return UM.Theme.sizes.standard_list_lineheight.height * 2
if (wizardPage.manufacturers[wizardPage.manufacturerIndex] == model.manufacturer | machineLayout.showManufacturer())
return UM.Theme.sizes.standard_list_lineheight.height * 1
else
return 0
}
Behavior on height
{
NumberAnimation { target: machineLayout; property: "height"; duration: 200}
}
Button
{
id: manufacturer
property color backgroundColor: "transparent"
height: UM.Theme.sizes.standard_list_lineheight.height
visible: machineLayout.showManufacturer()
anchors.top: machineLayout.top
anchors.topMargin: 0
text:
{
if (wizardPage.manufacturers[wizardPage.manufacturerIndex] == model.manufacturer)
return model.manufacturer + " ▼"
else
return model.manufacturer + " ►"
}
style: ButtonStyle
{
background: Rectangle
{
id: manufacturerBackground
opacity: 0.3
border.width: 0
color: manufacturer.backgroundColor
height: UM.Theme.sizes.standard_list_lineheight.height
}
label: Text
{
renderType: Text.NativeRendering
horizontalAlignment: Text.AlignLeft
text: control.text
color: palette.windowText
font.bold: true
}
}
MouseArea
{
id: mousearea
hoverEnabled: true
anchors.fill: parent
onEntered: manufacturer.backgroundColor = palette.light
onExited: manufacturer.backgroundColor = "transparent"
onClicked:
{
wizardPage.manufacturerIndex = wizardPage.manufacturers.indexOf(model.manufacturer)
machineList.currentIndex = index
}
}
}
RadioButton
{
id: machineButton
opacity: wizardPage.manufacturers[wizardPage.manufacturerIndex] == model.manufacturer ? 1 : 0
height: wizardPage.manufacturers[wizardPage.manufacturerIndex] == model.manufacturer ? UM.Theme.sizes.standard_list_lineheight.height : 0
anchors.top: parent.top
anchors.topMargin: machineLayout.showManufacturer() ? manufacturer.height - 5 : 0
anchors.left: parent.left
anchors.leftMargin: UM.Theme.sizes.standard_list_lineheight.width
checked: machineList.currentIndex == index ? true : false
exclusiveGroup: printerGroup;
text: model.name
onClicked: machineList.currentIndex = index;
function getAnimationTime(time)
{
if (machineButton.opacity == 0)
return time
else
return 0
}
Label
{
id: author
visible: model.author != "Ultimaker" ? true : false
height: wizardPage.manufacturers[wizardPage.manufacturerIndex] == model.manufacturer ? UM.Theme.sizes.standard_list_lineheight.height : 0
//: Printer profile caption meaning: this profile is supported by the community
text: catalog.i18nc("@label","community supported profile");
opacity: wizardPage.manufacturers[wizardPage.manufacturerIndex] == model.manufacturer ? 1 : 0
anchors.left: machineButton.right
anchors.leftMargin: UM.Theme.sizes.standard_list_lineheight.height/2
anchors.verticalCenter: machineButton.verticalCenter
anchors.verticalCenterOffset: UM.Theme.sizes.standard_list_lineheight.height / 4
font: UM.Theme.fonts.caption;
color: palette.mid
}
Behavior on opacity
{
SequentialAnimation
{
PauseAnimation { duration: machineButton.getAnimationTime(100) }
NumberAnimation { properties:"opacity"; duration: machineButton.getAnimationTime(200) }
}
}
}
}
} }
ListView ListView
{ {
id: machineList id: machineList
property int currentIndex: 0
property int otherMachinesIndex: model: UM.MachineDefinitionsModel { id: machineDefinitionsModel; showVariants: false; }
{ focus: true
for (var i = 0; i < UM.Models.availableMachinesModel.rowCount(); i++)
{ section.property: "manufacturer"
if (UM.Models.availableMachinesModel.getItem(i).manufacturer != "Ultimaker") section.delegate: Button {
{ text: {
return i if (base,activeManufacturer == section)
return section + " ▼"
else
return section + " ►"
}
style: ButtonStyle {
background: Rectangle {
id: manufacturerBackground
opacity: 0.3
border.width: 0
color: control.hovered ? palette.light : "transparent";
height: UM.Theme.sizes.standard_list_lineheight.height
}
label: Text {
horizontalAlignment: Text.AlignLeft
text: control.text
color: palette.windowText
font.bold: true
} }
} }
onClicked: {
base.activeManufacturer = section;
machineList.currentIndex = machineList.model.find("manufacturer", section)
}
}
delegate: RadioButton {
id: machineButton
anchors.left: parent.left
anchors.leftMargin: UM.Theme.sizes.standard_list_lineheight.width
opacity: 1;
height: UM.Theme.sizes.standard_list_lineheight.height;
checked: ListView.isCurrentItem;
exclusiveGroup: printerGroup;
text: model.name
onClicked: {
ListView.view.currentIndex = index;
if(model.pages.length > 0) {
base.wizard.nextAvailable = true;
} else {
base.wizard.nextAvailable = false;
}
}
Label
{
id: author
// visible: model.author != "Ultimaker" ? true : false
//: Printer profile caption meaning: this profile is supported by the community
// text: qsTr("community supported profile");
text: model.author;
anchors.left: machineButton.right
anchors.leftMargin: UM.Theme.sizes.standard_list_lineheight.height/2
anchors.verticalCenter: machineButton.verticalCenter
anchors.verticalCenterOffset: UM.Theme.sizes.standard_list_lineheight.height / 4
font: UM.Theme.fonts.caption;
color: palette.mid
}
states: State {
name: "collapsed";
when: base.activeManufacturer != model.manufacturer;
PropertyChanges { target: machineButton; opacity: 0; height: 0; }
}
transitions: [
Transition {
to: "collapsed";
SequentialAnimation {
NumberAnimation { property: "opacity"; duration: 75; }
NumberAnimation { property: "height"; duration: 75; }
}
},
Transition {
from: "collapsed";
SequentialAnimation {
NumberAnimation { property: "height"; duration: 75; }
NumberAnimation { property: "opacity"; duration: 75; }
}
}
]
} }
anchors.fill: parent
model: UM.Models.availableMachinesModel
delegate: machineDelegate
focus: true
} }
} }
@ -226,12 +173,11 @@ ColumnLayout
{ {
id: machineNameHolder id: machineNameHolder
height: childrenRect.height height: childrenRect.height
anchors.top: machinesHolder.bottom anchors.bottom: parent.bottom;
Label Label
{ {
id: insertNameLabel id: insertNameLabel
//: Add Printer wizard field label text: catalog.i18nc("@label", "Printer Name:");
text: catalog.i18nc("@label","Printer Name:");
} }
TextField TextField
{ {
@ -242,44 +188,40 @@ ColumnLayout
} }
} }
ExclusiveGroup { id: printerGroup; }
function saveMachine() function saveMachine()
{ {
if(machineList.currentIndex != -1) if(machineList.currentIndex != -1)
{ {
UM.Models.availableMachinesModel.createMachine(machineList.currentIndex, machineName.text) var item = machineList.model.getItem(machineList.currentIndex);
var pages = UM.Models.availableMachinesModel.getItem(machineList.currentIndex).pages machineList.model.createInstance(machineName.text, item.id)
var old_page_count = elementRoot.getPageCount()
for(var i = 0; i < UM.Models.count; i++) var pages = machineList.model.getItem(machineList.currentIndex).pages
{
print(UM.Models.getItem(i))
}
// Delete old pages (if any)
for (var i = old_page_count - 1; i > 0; i--)
{
elementRoot.removePage(i)
elementRoot.currentPage = 0
}
// Insert new pages (if any) // Insert new pages (if any)
for(var i = 0; i < pages.count; i++) for(var i = 0; i < pages.length; i++)
{ {
elementRoot.insertPage(pages.getItem(i).page + ".qml",pages.getItem(i).title,i + 1) console.log(pages[i])
} switch(pages[i]) {
case "SelectUpgradedParts":
// Hack to ensure the current page is set correctly base.wizard.appendPage(UM.Resources.getPath(Cura.ResourceTypes.QmlFiles, "WizardPages/SelectUpgradedParts.qml"), catalog.i18nc("@title", "Select Upgraded Parts"));
if(old_page_count == 1) break;
{ case "UpgradeFirmware":
elementRoot.currentPage += 1 base.wizard.appendPage(UM.Resources.getPath(Cura.ResourceTypes.QmlFiles, "WizardPages/UpgradeFirmware.qml"), catalog.i18nc("@title", "Upgrade Firmware"));
} break;
case "UltimakerCheckup":
if (elementRoot.getPageCount() == elementRoot.currentPage) base.wizard.appendPage(UM.Resources.getPath(Cura.ResourceTypes.QmlFiles, "WizardPages/UltimakerCheckup.qml"), catalog.i18nc("@title", "Check Printer"));
{ break;
elementRoot.visible = false case "BedLeveling":
base.wizard.appendPage(UM.Resources.getPath(Cura.ResourceTypes.QmlFiles, "WizardPages/Bedleveling.qml"), catalog.i18nc("@title", "Bed Levelling"));
break;
default:
break;
}
} }
} }
} }
}
ExclusiveGroup { id: printerGroup; }
UM.I18nCatalog { id: catalog; name: "cura"; }
SystemPalette { id: palette }
}

View File

@ -13,8 +13,8 @@ Column
id: wizardPage id: wizardPage
property int leveling_state: 0 property int leveling_state: 0
property bool three_point_leveling: true property bool three_point_leveling: true
property int platform_width: UM.Models.settingsModel.getMachineSetting("machine_width") property int platform_width: UM.MachineManager.getSettingValue("machine_width")
property int platform_height: UM.Models.settingsModel.getMachineSetting("machine_depth") property int platform_height: UM.MachineManager.getSettingValue("machine_depth")
anchors.fill: parent; anchors.fill: parent;
property variant printer_connection: UM.USBPrinterManager.connectedPrinterList.getItem(0).printer property variant printer_connection: UM.USBPrinterManager.connectedPrinterList.getItem(0).printer
Component.onCompleted: printer_connection.homeHead() Component.onCompleted: printer_connection.homeHead()
@ -51,4 +51,4 @@ Column
} }
} }