mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-21 21:58:01 -06:00
Merge branch '2.1'
This commit is contained in:
commit
8a48791a0b
83 changed files with 14784 additions and 9510 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
|||
*.pyc
|
||||
*kdev*
|
||||
*.kate-swp
|
||||
__pycache__
|
||||
docs/html
|
||||
*.lprof
|
||||
|
|
|
@ -9,6 +9,20 @@ set(URANIUM_SCRIPTS_DIR "${CMAKE_SOURCE_DIR}/../uranium/scripts" CACHE DIRECTORY
|
|||
set(CURA_VERSION "master" CACHE STRING "Version name of Cura")
|
||||
configure_file(cura/CuraVersion.py.in CuraVersion.py @ONLY)
|
||||
|
||||
# Macro needed to list all sub-directory of a directory.
|
||||
# There is no function in cmake as far as I know.
|
||||
# Found at: http://stackoverflow.com/a/7788165
|
||||
MACRO(SUBDIRLIST result curdir)
|
||||
FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
|
||||
SET(dirlist "")
|
||||
FOREACH(child ${children})
|
||||
IF(IS_DIRECTORY ${curdir}/${child})
|
||||
LIST(APPEND dirlist ${child})
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
SET(${result} ${dirlist})
|
||||
ENDMACRO()
|
||||
|
||||
if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
|
||||
# Extract Strings
|
||||
add_custom_target(extract-messages ${URANIUM_SCRIPTS_DIR}/extract-messages ${CMAKE_SOURCE_DIR} cura)
|
||||
|
@ -24,36 +38,16 @@ if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
|
|||
# build directory to the source resources directory. This is mostly a convenience
|
||||
# during development, normally you want to simply use the install target to install
|
||||
# the files along side the rest of the application.
|
||||
add_custom_target(copy-translations)
|
||||
|
||||
#TODO: Properly install the built files. This should be done after we move the applications out of the Uranium repo.
|
||||
set(languages
|
||||
en
|
||||
x-test
|
||||
ru
|
||||
fr
|
||||
de
|
||||
it
|
||||
es
|
||||
fi
|
||||
pl
|
||||
cs
|
||||
bg
|
||||
)
|
||||
SUBDIRLIST(languages ${CMAKE_SOURCE_DIR}/resources/i18n/)
|
||||
foreach(lang ${languages})
|
||||
file(GLOB po_files resources/i18n/${lang}/*.po)
|
||||
foreach(file ${po_files})
|
||||
string(REGEX REPLACE ".*/(.*).po" "${lang}/\\1.mo" mofile ${file})
|
||||
add_custom_command(TARGET translations POST_BUILD COMMAND mkdir ARGS -p ${lang} COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ARGS ${file} -o ${mofile})
|
||||
file(GLOB po_files ${CMAKE_SOURCE_DIR}/resources/i18n/${lang}/*.po)
|
||||
foreach(po_file ${po_files})
|
||||
string(REGEX REPLACE ".*/(.*).po" "${CMAKE_BINARY_DIR}/resources/i18n/${lang}/LC_MESSAGES/\\1.mo" mo_file ${po_file})
|
||||
add_custom_command(TARGET translations POST_BUILD COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/resources/i18n/${lang}/LC_MESSAGES/ COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ARGS ${po_file} -o ${mo_file})
|
||||
endforeach()
|
||||
|
||||
file(GLOB mo_files ${CMAKE_BINARY_DIR}/${lang}/*.mo)
|
||||
foreach(file ${mo_files})
|
||||
add_custom_command(TARGET copy-translations POST_BUILD COMMAND mkdir ARGS -p ${CMAKE_SOURCE_DIR}/resources/i18n/${lang}/LC_MESSAGES/ COMMAND cp ARGS ${file} ${CMAKE_SOURCE_DIR}/resources/i18n/${lang}/LC_MESSAGES/ COMMENT "Copying ${file}...")
|
||||
endforeach()
|
||||
|
||||
install(FILES ${mo_files} DESTINATION ${CMAKE_INSTALL_DATADIR}/uranium/resources/i18n/${lang}/LC_MESSAGES/)
|
||||
endforeach()
|
||||
install(DIRECTORY ${CMAKE_BINARY_DIR}/resources DESTINATION ${CMAKE_INSTALL_DATADIR}/cura)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
[Desktop Entry]
|
||||
Version=15.06.01
|
||||
Name=Cura
|
||||
Name[de]=Cura
|
||||
GenericName=3D Printing Software
|
||||
GenericName[de]=3D-Druck-Software
|
||||
Comment=
|
||||
Exec=/usr/bin/cura_app.py
|
||||
TryExec=/usr/bin/cura_app.py
|
||||
Icon=/usr/share/cura/resources/images/cura-icon.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
MimeType=application/sla
|
||||
MimeType=application/sla;image/bmp;image/gif;image/jpeg;image/png
|
||||
Categories=Graphics;
|
||||
Keywords=3D;Printing;
|
||||
|
|
|
@ -129,9 +129,13 @@ class BuildVolume(SceneNode):
|
|||
new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d))
|
||||
mb.addFace(first, previous_point, new_point, color = color)
|
||||
previous_point = new_point
|
||||
|
||||
# Find the largest disallowed area to exclude it from the maximum scale bounds
|
||||
size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
|
||||
# Find the largest disallowed area to exclude it from the maximum scale bounds.
|
||||
# This is a very nasty hack. This pretty much only works for UM machines. This disallowed area_size needs
|
||||
# A -lot- of rework at some point in the future: TODO
|
||||
if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
|
||||
size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
|
||||
else:
|
||||
size = 0
|
||||
disallowed_area_size = max(size, disallowed_area_size)
|
||||
|
||||
self._disallowed_area_mesh = mb.getData()
|
||||
|
@ -146,9 +150,12 @@ class BuildVolume(SceneNode):
|
|||
if profile:
|
||||
skirt_size = self._getSkirtSize(profile)
|
||||
|
||||
# As this works better for UM machines, we only add the dissallowed_area_size for the z direction.
|
||||
# This is probably wrong in all other cases. TODO!
|
||||
# The +1 and -1 is added as there is always a bit of extra room required to work properly.
|
||||
scale_to_max_bounds = AxisAlignedBox(
|
||||
minimum = Vector(min_w + skirt_size, min_h, min_d + skirt_size + disallowed_area_size),
|
||||
maximum = Vector(max_w - skirt_size, max_h, max_d - skirt_size - disallowed_area_size)
|
||||
minimum = Vector(min_w + skirt_size + 1, min_h, min_d + disallowed_area_size - skirt_size + 1),
|
||||
maximum = Vector(max_w - skirt_size - 1, max_h, max_d - disallowed_area_size + skirt_size - 1)
|
||||
)
|
||||
|
||||
Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
|
||||
|
@ -192,6 +199,7 @@ class BuildVolume(SceneNode):
|
|||
skirt_size = self._getSkirtSize(self._active_profile)
|
||||
|
||||
if disallowed_areas:
|
||||
# Extend every area already in the disallowed_areas with the skirt size.
|
||||
for area in disallowed_areas:
|
||||
poly = Polygon(numpy.array(area, numpy.float32))
|
||||
poly = poly.getMinkowskiHull(Polygon(numpy.array([
|
||||
|
@ -207,6 +215,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
areas.append(poly)
|
||||
|
||||
# Add the skirt areas arround the borders of the build plate.
|
||||
if skirt_size > 0:
|
||||
half_machine_width = self._active_instance.getMachineSettingValue("machine_width") / 2
|
||||
half_machine_depth = self._active_instance.getMachineSettingValue("machine_depth") / 2
|
||||
|
@ -257,7 +266,8 @@ class BuildVolume(SceneNode):
|
|||
if profile.getSettingValue("draft_shield_enabled"):
|
||||
skirt_size += profile.getSettingValue("draft_shield_dist")
|
||||
|
||||
skirt_size += profile.getSettingValue("xy_offset")
|
||||
if profile.getSettingValue("xy_offset"):
|
||||
skirt_size += profile.getSettingValue("xy_offset")
|
||||
|
||||
return skirt_size
|
||||
|
||||
|
|
|
@ -19,6 +19,11 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onActiveProfileChanged)
|
||||
self._onActiveProfileChanged()
|
||||
|
||||
## Force that a new (empty) object is created upon copy.
|
||||
def __deepcopy__(self, memo):
|
||||
copy = ConvexHullDecorator()
|
||||
return copy
|
||||
|
||||
def getConvexHull(self):
|
||||
return self._convex_hull
|
||||
|
||||
|
|
|
@ -54,7 +54,12 @@ class ConvexHullJob(Job):
|
|||
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
|
||||
self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
|
||||
head_hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"),numpy.float32)))
|
||||
head_and_fans = Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"), numpy.float32))
|
||||
mirrored = copy.deepcopy(head_and_fans)
|
||||
mirrored.mirror([0, 0], [0, 1]) #Mirror horizontally.
|
||||
mirrored.mirror([0, 0], [1, 0]) #Mirror vertically.
|
||||
head_and_fans = head_and_fans.intersectionConvexHulls(mirrored)
|
||||
head_hull = hull.getMinkowskiHull(head_and_fans)
|
||||
self._node.callDecoration("setConvexHullHead", head_hull)
|
||||
hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
|
||||
else:
|
||||
|
|
|
@ -5,7 +5,7 @@ from UM.Scene.SceneNode import SceneNode
|
|||
from UM.Resources import Resources
|
||||
from UM.Math.Color import Color
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Mesh.MeshData import MeshData
|
||||
from UM.Mesh.MeshBuilder import MeshBuilder #To create a mesh to display the convex hull with.
|
||||
|
||||
from UM.View.GL.OpenGL import OpenGL
|
||||
|
||||
|
@ -25,6 +25,7 @@ class ConvexHullNode(SceneNode):
|
|||
self._inherit_scale = False
|
||||
|
||||
self._color = Color(35, 35, 35, 128)
|
||||
self._mesh_height = 0.1 #The y-coordinate of the convex hull mesh. Must not be 0, to prevent z-fighting.
|
||||
|
||||
self._node = node
|
||||
self._node.transformationChanged.connect(self._onNodePositionChanged)
|
||||
|
@ -43,22 +44,19 @@ class ConvexHullNode(SceneNode):
|
|||
self._convex_hull_head_mesh = self.createHullMesh(convex_hull_head.getPoints())
|
||||
|
||||
def createHullMesh(self, hull_points):
|
||||
mesh = MeshData()
|
||||
if len(hull_points) > 3:
|
||||
center = (hull_points.min(0) + hull_points.max(0)) / 2.0
|
||||
mesh.addVertex(center[0], -0.1, center[1])
|
||||
else:
|
||||
#Input checking.
|
||||
if len(hull_points) < 3:
|
||||
return None
|
||||
for point in hull_points:
|
||||
mesh.addVertex(point[0], -0.1, point[1])
|
||||
indices = []
|
||||
for i in range(len(hull_points) - 1):
|
||||
indices.append([0, i + 1, i + 2])
|
||||
|
||||
indices.append([0, mesh.getVertexCount() - 1, 1])
|
||||
mesh_builder = MeshBuilder()
|
||||
point_first = Vector(hull_points[0][0], self._mesh_height, hull_points[0][1])
|
||||
point_previous = Vector(hull_points[1][0], self._mesh_height, hull_points[1][1])
|
||||
for point in hull_points[2:]: #Add the faces in the order of a triangle fan.
|
||||
point_new = Vector(point[0], self._mesh_height, point[1])
|
||||
mesh_builder.addFace(point_first, point_previous, point_new, color = self._color)
|
||||
point_previous = point_new #Prepare point_previous for the next triangle.
|
||||
|
||||
mesh.addIndices(numpy.array(indices, numpy.int32))
|
||||
return mesh
|
||||
return mesh_builder.getData()
|
||||
|
||||
def getWatchedNode(self):
|
||||
return self._node
|
||||
|
|
|
@ -114,6 +114,7 @@ class CuraApplication(QtApplication):
|
|||
Preferences.getInstance().addPreference("cura/categories_expanded", "")
|
||||
Preferences.getInstance().addPreference("view/center_on_select", True)
|
||||
Preferences.getInstance().addPreference("mesh/scale_to_fit", True)
|
||||
Preferences.getInstance().setDefault("local_file/last_used_type", "text/x-gcode")
|
||||
|
||||
JobQueue.getInstance().jobFinished.connect(self._onJobFinished)
|
||||
|
||||
|
@ -132,6 +133,7 @@ class CuraApplication(QtApplication):
|
|||
if not hasattr(sys, "frozen"):
|
||||
self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins"))
|
||||
self._plugin_registry.loadPlugin("ConsoleLogger")
|
||||
self._plugin_registry.loadPlugin("CuraEngineBackend")
|
||||
|
||||
self._plugin_registry.loadPlugins()
|
||||
|
||||
|
@ -249,17 +251,23 @@ class CuraApplication(QtApplication):
|
|||
|
||||
@pyqtProperty(str, notify = sceneBoundingBoxChanged)
|
||||
def getSceneBoundingBoxString(self):
|
||||
return self._i18n_catalog.i18nc("@info", "%.1f x %.1f x %.1f mm") % (self._scene_boundingbox.width.item(), self._scene_boundingbox.depth.item(), self._scene_boundingbox.height.item())
|
||||
return self._i18n_catalog.i18nc("@info", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_boundingbox.width.item(), 'depth': self._scene_boundingbox.depth.item(), 'height' : self._scene_boundingbox.height.item()}
|
||||
|
||||
def updatePlatformActivity(self, node = None):
|
||||
count = 0
|
||||
scene_boundingbox = AxisAlignedBox()
|
||||
scene_boundingbox = None
|
||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||
if type(node) is not SceneNode or not node.getMeshData():
|
||||
continue
|
||||
|
||||
count += 1
|
||||
scene_boundingbox += node.getBoundingBox()
|
||||
if not scene_boundingbox:
|
||||
scene_boundingbox = node.getBoundingBox()
|
||||
else:
|
||||
scene_boundingbox += node.getBoundingBox()
|
||||
|
||||
if not scene_boundingbox:
|
||||
scene_boundingbox = AxisAlignedBox()
|
||||
|
||||
if repr(self._scene_boundingbox) != repr(scene_boundingbox):
|
||||
self._scene_boundingbox = scene_boundingbox
|
||||
|
@ -270,6 +278,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
@pyqtSlot(str)
|
||||
def setJobName(self, name):
|
||||
name = os.path.splitext(name)[0] #when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its extension. This cuts the extension off if nescessary.
|
||||
if self._job_name != name:
|
||||
self._job_name = name
|
||||
self.jobNameChanged.emit()
|
||||
|
@ -280,9 +289,28 @@ class CuraApplication(QtApplication):
|
|||
def jobName(self):
|
||||
return self._job_name
|
||||
|
||||
## Remove an object from the scene
|
||||
# Remove all selected objects from the scene.
|
||||
@pyqtSlot()
|
||||
def deleteSelection(self):
|
||||
if not self.getController().getToolsEnabled():
|
||||
return
|
||||
|
||||
op = GroupedOperation()
|
||||
nodes = Selection.getAllSelectedObjects()
|
||||
for node in nodes:
|
||||
op.addOperation(RemoveSceneNodeOperation(node))
|
||||
|
||||
op.push()
|
||||
|
||||
pass
|
||||
|
||||
## Remove an object from the scene.
|
||||
# Note that this only removes an object if it is selected.
|
||||
@pyqtSlot("quint64")
|
||||
def deleteObject(self, object_id):
|
||||
if not self.getController().getToolsEnabled():
|
||||
return
|
||||
|
||||
node = self.getController().getScene().findObject(object_id)
|
||||
|
||||
if not node and object_id != 0: #Workaround for tool handles overlapping the selected object
|
||||
|
@ -342,6 +370,9 @@ class CuraApplication(QtApplication):
|
|||
## Delete all mesh data on the scene.
|
||||
@pyqtSlot()
|
||||
def deleteAll(self):
|
||||
if not self.getController().getToolsEnabled():
|
||||
return
|
||||
|
||||
nodes = []
|
||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||
if type(node) is not SceneNode:
|
||||
|
@ -570,9 +601,9 @@ class CuraApplication(QtApplication):
|
|||
def _onFileLoaded(self, job):
|
||||
node = job.getResult()
|
||||
if node != None:
|
||||
self.setJobName(os.path.basename(job.getFileName()))
|
||||
node.setSelectable(True)
|
||||
node.setName(os.path.basename(job.getFileName()))
|
||||
|
||||
op = AddSceneNodeOperation(node, self.getController().getScene().getRoot())
|
||||
op.push()
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QPixmap, QColor, QFont
|
||||
from PyQt5.QtCore import Qt, QCoreApplication
|
||||
from PyQt5.QtGui import QPixmap, QColor, QFont, QFontMetrics
|
||||
from PyQt5.QtWidgets import QSplashScreen
|
||||
|
||||
from UM.Resources import Resources
|
||||
|
@ -11,7 +11,10 @@ from UM.Application import Application
|
|||
class CuraSplashScreen(QSplashScreen):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setPixmap(QPixmap(Resources.getPath(Resources.Images, "cura.png")))
|
||||
self._scale = round(QFontMetrics(QCoreApplication.instance().font()).ascent() / 12)
|
||||
|
||||
splash_image = QPixmap(Resources.getPath(Resources.Images, "cura.png"))
|
||||
self.setPixmap(splash_image.scaled(splash_image.size() * self._scale))
|
||||
|
||||
def drawContents(self, painter):
|
||||
painter.save()
|
||||
|
@ -19,11 +22,11 @@ class CuraSplashScreen(QSplashScreen):
|
|||
|
||||
version = Application.getInstance().getVersion().split("-")
|
||||
|
||||
painter.setFont(QFont("Proxima Nova Rg", 20))
|
||||
painter.drawText(0, 0, 203, 230, Qt.AlignRight | Qt.AlignBottom, version[0])
|
||||
painter.setFont(QFont("Proxima Nova Rg", 20 ))
|
||||
painter.drawText(0, 0, 330 * self._scale, 230 * self._scale, Qt.AlignHCenter | Qt.AlignBottom, version[0])
|
||||
if len(version) > 1:
|
||||
painter.setFont(QFont("Proxima Nova Rg", 12))
|
||||
painter.drawText(0, 0, 203, 255, Qt.AlignRight | Qt.AlignBottom, version[1])
|
||||
painter.setFont(QFont("Proxima Nova Rg", 12 ))
|
||||
painter.drawText(0, 0, 330 * self._scale, 255 * self._scale, Qt.AlignHCenter | Qt.AlignBottom, version[1])
|
||||
|
||||
painter.restore()
|
||||
super().drawContents(painter)
|
||||
|
|
|
@ -24,7 +24,7 @@ import xml.etree.ElementTree as ET
|
|||
class ThreeMFReader(MeshReader):
|
||||
def __init__(self):
|
||||
super(ThreeMFReader, self).__init__()
|
||||
self._supported_extension = ".3mf"
|
||||
self._supported_extensions = [".3mf"]
|
||||
|
||||
self._namespaces = {
|
||||
"3mf": "http://schemas.microsoft.com/3dmanufacturing/core/2015/02",
|
||||
|
@ -33,102 +33,102 @@ class ThreeMFReader(MeshReader):
|
|||
|
||||
def read(self, file_name):
|
||||
result = None
|
||||
extension = os.path.splitext(file_name)[1]
|
||||
if extension.lower() == self._supported_extension:
|
||||
result = SceneNode()
|
||||
# The base object of 3mf is a zipped archive.
|
||||
archive = zipfile.ZipFile(file_name, "r")
|
||||
try:
|
||||
root = ET.parse(archive.open("3D/3dmodel.model"))
|
||||
|
||||
# There can be multiple objects, try to load all of them.
|
||||
objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
|
||||
if len(objects) == 0:
|
||||
Logger.log("w", "No objects found in 3MF file %s, either the file is corrupt or you are using an outdated format", file_name)
|
||||
return None
|
||||
result = SceneNode()
|
||||
# The base object of 3mf is a zipped archive.
|
||||
archive = zipfile.ZipFile(file_name, "r")
|
||||
try:
|
||||
root = ET.parse(archive.open("3D/3dmodel.model"))
|
||||
|
||||
for object in objects:
|
||||
mesh = MeshData()
|
||||
node = SceneNode()
|
||||
vertex_list = []
|
||||
#for vertex in object.mesh.vertices.vertex:
|
||||
for vertex in object.findall(".//3mf:vertex", self._namespaces):
|
||||
vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
|
||||
Job.yieldThread()
|
||||
|
||||
triangles = object.findall(".//3mf:triangle", self._namespaces)
|
||||
|
||||
mesh.reserveFaceCount(len(triangles))
|
||||
|
||||
#for triangle in object.mesh.triangles.triangle:
|
||||
for triangle in triangles:
|
||||
v1 = int(triangle.get("v1"))
|
||||
v2 = int(triangle.get("v2"))
|
||||
v3 = int(triangle.get("v3"))
|
||||
mesh.addFace(vertex_list[v1][0],vertex_list[v1][1],vertex_list[v1][2],vertex_list[v2][0],vertex_list[v2][1],vertex_list[v2][2],vertex_list[v3][0],vertex_list[v3][1],vertex_list[v3][2])
|
||||
Job.yieldThread()
|
||||
|
||||
#TODO: We currently do not check for normals and simply recalculate them.
|
||||
mesh.calculateNormals()
|
||||
node.setMeshData(mesh)
|
||||
node.setSelectable(True)
|
||||
|
||||
transformation = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(object.get("id")), self._namespaces)
|
||||
if transformation:
|
||||
transformation = transformation[0]
|
||||
|
||||
if transformation.get("transform"):
|
||||
splitted_transformation = transformation.get("transform").split()
|
||||
## Transformation is saved as:
|
||||
## M00 M01 M02 0.0
|
||||
## M10 M11 M12 0.0
|
||||
## M20 M21 M22 0.0
|
||||
## M30 M31 M32 1.0
|
||||
## We switch the row & cols as that is how everyone else uses matrices!
|
||||
temp_mat = Matrix()
|
||||
# Rotation & Scale
|
||||
temp_mat._data[0,0] = splitted_transformation[0]
|
||||
temp_mat._data[1,0] = splitted_transformation[1]
|
||||
temp_mat._data[2,0] = splitted_transformation[2]
|
||||
temp_mat._data[0,1] = splitted_transformation[3]
|
||||
temp_mat._data[1,1] = splitted_transformation[4]
|
||||
temp_mat._data[2,1] = splitted_transformation[5]
|
||||
temp_mat._data[0,2] = splitted_transformation[6]
|
||||
temp_mat._data[1,2] = splitted_transformation[7]
|
||||
temp_mat._data[2,2] = splitted_transformation[8]
|
||||
|
||||
# Translation
|
||||
temp_mat._data[0,3] = splitted_transformation[9]
|
||||
temp_mat._data[1,3] = splitted_transformation[10]
|
||||
temp_mat._data[2,3] = splitted_transformation[11]
|
||||
|
||||
node.setPosition(Vector(temp_mat.at(0,3), temp_mat.at(1,3), temp_mat.at(2,3)))
|
||||
|
||||
temp_quaternion = Quaternion()
|
||||
temp_quaternion.setByMatrix(temp_mat)
|
||||
node.setOrientation(temp_quaternion)
|
||||
|
||||
# Magical scale extraction
|
||||
scale = temp_mat.getTransposed().multiply(temp_mat)
|
||||
scale_x = math.sqrt(scale.at(0,0))
|
||||
scale_y = math.sqrt(scale.at(1,1))
|
||||
scale_z = math.sqrt(scale.at(2,2))
|
||||
node.setScale(Vector(scale_x,scale_y,scale_z))
|
||||
|
||||
# We use a different coordinate frame, so rotate.
|
||||
#rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0))
|
||||
#node.rotate(rotation)
|
||||
result.addChild(node)
|
||||
# There can be multiple objects, try to load all of them.
|
||||
objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
|
||||
if len(objects) == 0:
|
||||
Logger.log("w", "No objects found in 3MF file %s, either the file is corrupt or you are using an outdated format", file_name)
|
||||
return None
|
||||
|
||||
for object in objects:
|
||||
mesh = MeshData()
|
||||
node = SceneNode()
|
||||
vertex_list = []
|
||||
#for vertex in object.mesh.vertices.vertex:
|
||||
for vertex in object.findall(".//3mf:vertex", self._namespaces):
|
||||
vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
|
||||
Job.yieldThread()
|
||||
|
||||
#If there is more then one object, group them.
|
||||
try:
|
||||
if len(objects) > 1:
|
||||
group_decorator = GroupDecorator()
|
||||
result.addDecorator(group_decorator)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
Logger.log("e" ,"exception occured in 3mf reader: %s" , e)
|
||||
triangles = object.findall(".//3mf:triangle", self._namespaces)
|
||||
|
||||
mesh.reserveFaceCount(len(triangles))
|
||||
|
||||
#for triangle in object.mesh.triangles.triangle:
|
||||
for triangle in triangles:
|
||||
v1 = int(triangle.get("v1"))
|
||||
v2 = int(triangle.get("v2"))
|
||||
v3 = int(triangle.get("v3"))
|
||||
mesh.addFace(vertex_list[v1][0],vertex_list[v1][1],vertex_list[v1][2],vertex_list[v2][0],vertex_list[v2][1],vertex_list[v2][2],vertex_list[v3][0],vertex_list[v3][1],vertex_list[v3][2])
|
||||
Job.yieldThread()
|
||||
|
||||
#TODO: We currently do not check for normals and simply recalculate them.
|
||||
mesh.calculateNormals()
|
||||
node.setMeshData(mesh)
|
||||
node.setSelectable(True)
|
||||
|
||||
transformation = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(object.get("id")), self._namespaces)
|
||||
if transformation:
|
||||
transformation = transformation[0]
|
||||
|
||||
if transformation.get("transform"):
|
||||
splitted_transformation = transformation.get("transform").split()
|
||||
## Transformation is saved as:
|
||||
## M00 M01 M02 0.0
|
||||
## M10 M11 M12 0.0
|
||||
## M20 M21 M22 0.0
|
||||
## M30 M31 M32 1.0
|
||||
## We switch the row & cols as that is how everyone else uses matrices!
|
||||
temp_mat = Matrix()
|
||||
# Rotation & Scale
|
||||
temp_mat._data[0,0] = splitted_transformation[0]
|
||||
temp_mat._data[1,0] = splitted_transformation[1]
|
||||
temp_mat._data[2,0] = splitted_transformation[2]
|
||||
temp_mat._data[0,1] = splitted_transformation[3]
|
||||
temp_mat._data[1,1] = splitted_transformation[4]
|
||||
temp_mat._data[2,1] = splitted_transformation[5]
|
||||
temp_mat._data[0,2] = splitted_transformation[6]
|
||||
temp_mat._data[1,2] = splitted_transformation[7]
|
||||
temp_mat._data[2,2] = splitted_transformation[8]
|
||||
|
||||
# Translation
|
||||
temp_mat._data[0,3] = splitted_transformation[9]
|
||||
temp_mat._data[1,3] = splitted_transformation[10]
|
||||
temp_mat._data[2,3] = splitted_transformation[11]
|
||||
|
||||
node.setPosition(Vector(temp_mat.at(0,3), temp_mat.at(1,3), temp_mat.at(2,3)))
|
||||
|
||||
temp_quaternion = Quaternion()
|
||||
temp_quaternion.setByMatrix(temp_mat)
|
||||
node.setOrientation(temp_quaternion)
|
||||
|
||||
# Magical scale extraction
|
||||
scale = temp_mat.getTransposed().multiply(temp_mat)
|
||||
scale_x = math.sqrt(scale.at(0,0))
|
||||
scale_y = math.sqrt(scale.at(1,1))
|
||||
scale_z = math.sqrt(scale.at(2,2))
|
||||
node.setScale(Vector(scale_x,scale_y,scale_z))
|
||||
|
||||
# We use a different coordinate frame, so rotate.
|
||||
#rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0))
|
||||
#node.rotate(rotation)
|
||||
result.addChild(node)
|
||||
|
||||
Job.yieldThread()
|
||||
|
||||
#If there is more then one object, group them.
|
||||
try:
|
||||
if len(objects) > 1:
|
||||
group_decorator = GroupDecorator()
|
||||
result.addDecorator(group_decorator)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
Logger.log("e" ,"exception occured in 3mf reader: %s" , e)
|
||||
|
||||
return result
|
||||
|
|
|
@ -15,10 +15,12 @@ def getMetaData():
|
|||
"description": catalog.i18nc("@info:whatsthis", "Provides support for reading 3MF files."),
|
||||
"api": 2
|
||||
},
|
||||
"mesh_reader": {
|
||||
"extension": "3mf",
|
||||
"description": catalog.i18nc("@item:inlistbox", "3MF File")
|
||||
}
|
||||
"mesh_reader": [
|
||||
{
|
||||
"extension": "3mf",
|
||||
"description": catalog.i18nc("@item:inlistbox", "3MF File")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def register(app):
|
||||
|
|
80
plugins/AutoSave/AutoSave.py
Normal file
80
plugins/AutoSave/AutoSave.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from PyQt5.QtCore import QTimer
|
||||
|
||||
from UM.Extension import Extension
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Application import Application
|
||||
from UM.Resources import Resources
|
||||
from UM.Logger import Logger
|
||||
|
||||
class AutoSave(Extension):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
Preferences.getInstance().preferenceChanged.connect(self._onPreferenceChanged)
|
||||
|
||||
machine_manager = Application.getInstance().getMachineManager()
|
||||
|
||||
self._profile = None
|
||||
machine_manager.activeProfileChanged.connect(self._onActiveProfileChanged)
|
||||
machine_manager.profileNameChanged.connect(self._onProfilesChanged)
|
||||
machine_manager.profilesChanged.connect(self._onProfilesChanged)
|
||||
machine_manager.machineInstanceNameChanged.connect(self._onInstanceNameChanged)
|
||||
machine_manager.machineInstancesChanged.connect(self._onInstancesChanged)
|
||||
Application
|
||||
self._onActiveProfileChanged()
|
||||
|
||||
self._change_timer = QTimer()
|
||||
self._change_timer.setInterval(1000 * 60)
|
||||
self._change_timer.setSingleShot(True)
|
||||
self._change_timer.timeout.connect(self._onTimeout)
|
||||
|
||||
self._save_preferences = False
|
||||
self._save_profiles = False
|
||||
self._save_instances = False
|
||||
|
||||
def _onPreferenceChanged(self, preference):
|
||||
self._save_preferences = True
|
||||
self._change_timer.start()
|
||||
|
||||
def _onSettingValueChanged(self, setting):
|
||||
self._save_profiles = True
|
||||
self._change_timer.start()
|
||||
|
||||
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 _onProfilesChanged(self):
|
||||
self._save_profiles = True
|
||||
self._change_timer.start()
|
||||
|
||||
def _onInstanceNameChanged(self, name):
|
||||
self._onInstancesChanged()
|
||||
|
||||
def _onInstancesChanged(self):
|
||||
self._save_instances = True
|
||||
self._change_timer.start()
|
||||
|
||||
def _onTimeout(self):
|
||||
Logger.log("d", "Autosaving preferences, instances and profiles")
|
||||
|
||||
if self._save_preferences:
|
||||
Preferences.getInstance().writeToFile(Resources.getStoragePath(Resources.Preferences, Application.getInstance().getApplicationName() + ".cfg"))
|
||||
|
||||
if self._save_instances:
|
||||
Application.getInstance().getMachineManager().saveMachineInstances()
|
||||
|
||||
if self._save_profiles:
|
||||
Application.getInstance().getMachineManager().saveProfiles()
|
||||
|
||||
self._save_preferences = False
|
||||
self._save_instances = False
|
||||
self._save_profiles = False
|
21
plugins/AutoSave/__init__.py
Normal file
21
plugins/AutoSave/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Copyright (c) 2016 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import AutoSave
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"plugin": {
|
||||
"name": catalog.i18nc("@label", "Auto Save"),
|
||||
"author": "Ultimaker",
|
||||
"version": "1.0",
|
||||
"description": catalog.i18nc("@info:whatsthis", "Automatically saves Preferences, Machines and Profiles after changes."),
|
||||
"api": 2
|
||||
},
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return { "extension": AutoSave.AutoSave() }
|
|
@ -107,15 +107,7 @@ class CuraEngineBackend(Backend):
|
|||
return
|
||||
|
||||
if self._slicing:
|
||||
self._slicing = False
|
||||
self._restart = True
|
||||
if self._process is not None:
|
||||
Logger.log("d", "Killing engine process")
|
||||
try:
|
||||
self._process.terminate()
|
||||
except: # terminating a process that is already terminating causes an exception, silently ignore this.
|
||||
pass
|
||||
|
||||
self._terminate()
|
||||
|
||||
if self._message:
|
||||
self._message.hide()
|
||||
|
@ -142,11 +134,23 @@ class CuraEngineBackend(Backend):
|
|||
|
||||
self._scene.gcode_list = []
|
||||
self._slicing = True
|
||||
self.slicingStarted.emit()
|
||||
|
||||
job = StartSliceJob.StartSliceJob(self._profile, self._socket)
|
||||
job.start()
|
||||
job.finished.connect(self._onStartSliceCompleted)
|
||||
|
||||
def _terminate(self):
|
||||
self._slicing = False
|
||||
self._restart = True
|
||||
self.slicingCancelled.emit()
|
||||
if self._process is not None:
|
||||
Logger.log("d", "Killing engine process")
|
||||
try:
|
||||
self._process.terminate()
|
||||
except: # terminating a process that is already terminating causes an exception, silently ignore this.
|
||||
pass
|
||||
|
||||
def _onStartSliceCompleted(self, job):
|
||||
if job.getError() or job.getResult() != True:
|
||||
if self._message:
|
||||
|
@ -245,6 +249,7 @@ class CuraEngineBackend(Backend):
|
|||
self._restart = False
|
||||
|
||||
def _onToolOperationStarted(self, tool):
|
||||
self._terminate() # Do not continue slicing once a tool has started
|
||||
self._enabled = False # Do not reslice when a tool is doing it's 'thing'
|
||||
|
||||
def _onToolOperationStopped(self, tool):
|
||||
|
@ -256,7 +261,9 @@ class CuraEngineBackend(Backend):
|
|||
view = Application.getInstance().getController().getActiveView()
|
||||
if view.getPluginId() == "LayerView":
|
||||
self._layer_view_active = True
|
||||
if self._stored_layer_data:
|
||||
# There is data and we're not slicing at the moment
|
||||
# if we are slicing, there is no need to re-calculate the data as it will be invalid in a moment.
|
||||
if self._stored_layer_data and not self._slicing:
|
||||
job = ProcessSlicedObjectListJob.ProcessSlicedObjectListJob(self._stored_layer_data)
|
||||
job.start()
|
||||
self._stored_layer_data = None
|
||||
|
@ -265,12 +272,5 @@ class CuraEngineBackend(Backend):
|
|||
|
||||
|
||||
def _onInstanceChanged(self):
|
||||
self._slicing = False
|
||||
self._restart = True
|
||||
if self._process is not None:
|
||||
Logger.log("d", "Killing engine process")
|
||||
try:
|
||||
self._process.terminate()
|
||||
except: # terminating a process that is already terminating causes an exception, silently ignore this.
|
||||
pass
|
||||
self._terminate()
|
||||
self.slicingCancelled.emit()
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: Cura.proto
|
||||
|
||||
import sys
|
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
|
@ -17,7 +19,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
|
|||
name='Cura.proto',
|
||||
package='cura.proto',
|
||||
syntax='proto3',
|
||||
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\"\x8e\x02\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\"\xb6\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\x12\x13\n\x0fMoveCombingType\x10\x08\x12\x16\n\x12MoveRetractionType\x10\t\"&\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\"\x8e\x02\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\"\xb6\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\x12\x13\n\x0fMoveCombingType\x10\x08\x12\x16\n\x12MoveRetractionType\x10\t\"&\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\"\x11\n\x0fSlicingFinishedb\x06proto3')
|
||||
)
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
|
@ -164,21 +166,21 @@ _OBJECT = _descriptor.Descriptor(
|
|||
_descriptor.FieldDescriptor(
|
||||
name='vertices', full_name='cura.proto.Object.vertices', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='normals', full_name='cura.proto.Object.normals', index=2,
|
||||
number=3, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='indices', full_name='cura.proto.Object.indices', index=3,
|
||||
number=4, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
|
@ -375,7 +377,7 @@ _POLYGON = _descriptor.Descriptor(
|
|||
_descriptor.FieldDescriptor(
|
||||
name='points', full_name='cura.proto.Polygon.points', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
|
@ -421,7 +423,7 @@ _GCODELAYER = _descriptor.Descriptor(
|
|||
_descriptor.FieldDescriptor(
|
||||
name='data', full_name='cura.proto.GCodeLayer.data', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
|
@ -528,14 +530,14 @@ _SETTING = _descriptor.Descriptor(
|
|||
_descriptor.FieldDescriptor(
|
||||
name='name', full_name='cura.proto.Setting.name', index=0,
|
||||
number=1, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='cura.proto.Setting.value', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
|
@ -566,7 +568,7 @@ _GCODEPREFIX = _descriptor.Descriptor(
|
|||
_descriptor.FieldDescriptor(
|
||||
name='data', full_name='cura.proto.GCodePrefix.data', index=0,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"",
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
|
@ -586,6 +588,30 @@ _GCODEPREFIX = _descriptor.Descriptor(
|
|||
serialized_end=1037,
|
||||
)
|
||||
|
||||
|
||||
_SLICINGFINISHED = _descriptor.Descriptor(
|
||||
name='SlicingFinished',
|
||||
full_name='cura.proto.SlicingFinished',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1039,
|
||||
serialized_end=1056,
|
||||
)
|
||||
|
||||
_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
|
||||
|
@ -609,6 +635,7 @@ DESCRIPTOR.message_types_by_name['ObjectPrintTime'] = _OBJECTPRINTTIME
|
|||
DESCRIPTOR.message_types_by_name['SettingList'] = _SETTINGLIST
|
||||
DESCRIPTOR.message_types_by_name['Setting'] = _SETTING
|
||||
DESCRIPTOR.message_types_by_name['GCodePrefix'] = _GCODEPREFIX
|
||||
DESCRIPTOR.message_types_by_name['SlicingFinished'] = _SLICINGFINISHED
|
||||
|
||||
ObjectList = _reflection.GeneratedProtocolMessageType('ObjectList', (_message.Message,), dict(
|
||||
DESCRIPTOR = _OBJECTLIST,
|
||||
|
@ -701,5 +728,12 @@ GCodePrefix = _reflection.GeneratedProtocolMessageType('GCodePrefix', (_message.
|
|||
))
|
||||
_sym_db.RegisterMessage(GCodePrefix)
|
||||
|
||||
SlicingFinished = _reflection.GeneratedProtocolMessageType('SlicingFinished', (_message.Message,), dict(
|
||||
DESCRIPTOR = _SLICINGFINISHED,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:cura.proto.SlicingFinished)
|
||||
))
|
||||
_sym_db.RegisterMessage(SlicingFinished)
|
||||
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
|
@ -29,6 +29,7 @@ class ProcessSlicedObjectListJob(Job):
|
|||
if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView":
|
||||
self._progress = Message(catalog.i18nc("@info:status", "Processing Layers"), 0, False, -1)
|
||||
self._progress.show()
|
||||
Job.yieldThread()
|
||||
|
||||
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
|
||||
|
||||
|
|
39
plugins/CuraProfileReader/CuraProfileReader.py
Normal file
39
plugins/CuraProfileReader/CuraProfileReader.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from UM.Application import Application #To get the machine manager to create the new profile in.
|
||||
from UM.Settings.Profile import Profile
|
||||
from UM.Settings.ProfileReader import ProfileReader
|
||||
|
||||
## A plugin that reads profile data from Cura profile files.
|
||||
#
|
||||
# It reads a profile from a .curaprofile file, and returns it as a profile
|
||||
# instance.
|
||||
class CuraProfileReader(ProfileReader):
|
||||
## Initialises the cura profile reader.
|
||||
#
|
||||
# This does nothing since the only other function is basically stateless.
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
## Reads a cura profile from a file and returns it.
|
||||
#
|
||||
# \param file_name The file to read the cura profile from.
|
||||
# \return The cura profile that was in the file, if any. If the file could
|
||||
# not be read or didn't contain a valid profile, \code None \endcode is
|
||||
# returned.
|
||||
def read(self, file_name):
|
||||
profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) #Create an empty profile.
|
||||
serialised = ""
|
||||
try:
|
||||
with open(file_name) as f: #Open file for reading.
|
||||
serialised = f.read()
|
||||
except IOError as e:
|
||||
Logger.log("e", "Unable to open file %s for reading: %s", file_name, str(e))
|
||||
return None
|
||||
|
||||
try:
|
||||
profile.unserialise(serialised)
|
||||
except Exception as e: #Parsing error. This is not a (valid) Cura profile then.
|
||||
return None
|
||||
return profile
|
27
plugins/CuraProfileReader/__init__.py
Normal file
27
plugins/CuraProfileReader/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import CuraProfileReader
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"plugin": {
|
||||
"name": catalog.i18nc("@label", "Cura Profile Reader"),
|
||||
"author": "Ultimaker",
|
||||
"version": "1.0",
|
||||
"description": catalog.i18nc("@info:whatsthis", "Provides support for importing Cura profiles."),
|
||||
"api": 2
|
||||
},
|
||||
"profile_reader": [
|
||||
{
|
||||
"extension": "curaprofile",
|
||||
"description": catalog.i18nc("@item:inlistbox", "Cura Profile")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return { "profile_reader": CuraProfileReader.CuraProfileReader() }
|
26
plugins/CuraProfileWriter/CuraProfileWriter.py
Normal file
26
plugins/CuraProfileWriter/CuraProfileWriter.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Copyright (c) 2013 David Braam
|
||||
# Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.SaveFile import SaveFile
|
||||
from UM.Settings.Profile import Profile
|
||||
from UM.Settings.ProfileWriter import ProfileWriter
|
||||
|
||||
## Writes profiles to Cura's own profile format with config files.
|
||||
class CuraProfileWriter(ProfileWriter):
|
||||
## Writes a profile to the specified file path.
|
||||
#
|
||||
# \param path \type{string} The file to output to.
|
||||
# \param profile \type{Profile} The profile to write to that file.
|
||||
# \return \code True \endcode if the writing was successful, or \code
|
||||
# False \endcode if it wasn't.
|
||||
def write(self, path, profile):
|
||||
serialised = profile.serialise()
|
||||
try:
|
||||
with SaveFile(path, "wt", -1, "utf-8") as f: #Open the specified file.
|
||||
f.write(serialised)
|
||||
except Exception as e:
|
||||
Logger.log("e", "Failed to write profile to %s: %s", path, str(e))
|
||||
return False
|
||||
return True
|
27
plugins/CuraProfileWriter/__init__.py
Normal file
27
plugins/CuraProfileWriter/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Uranium is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import CuraProfileWriter
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"plugin": {
|
||||
"name": catalog.i18nc("@label", "Cura Profile Writer"),
|
||||
"author": "Ultimaker",
|
||||
"version": "1.0",
|
||||
"description": catalog.i18nc("@info:whatsthis", "Provides support for exporting Cura profiles."),
|
||||
"api": 2
|
||||
},
|
||||
"profile_writer": [
|
||||
{
|
||||
"extension": "curaprofile",
|
||||
"description": catalog.i18nc("@item:inlistbox", "Cura Profile")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return { "profile_writer": CuraProfileWriter.CuraProfileWriter() }
|
67
plugins/GCodeProfileReader/GCodeProfileReader.py
Normal file
67
plugins/GCodeProfileReader/GCodeProfileReader.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from UM.Application import Application #To get the machine manager to create the new profile in.
|
||||
from UM.Settings.Profile import Profile
|
||||
from UM.Settings.ProfileReader import ProfileReader
|
||||
import re #Regular expressions for parsing escape characters in the settings.
|
||||
|
||||
## A class that reads profile data from g-code files.
|
||||
#
|
||||
# It reads the profile data from g-code files and stores it in a new profile.
|
||||
# This class currently does not process the rest of the g-code in any way.
|
||||
class GCodeProfileReader(ProfileReader):
|
||||
## The file format version of the serialised g-code.
|
||||
#
|
||||
# It can only read settings with the same version as the version it was
|
||||
# written with. If the file format is changed in a way that breaks reverse
|
||||
# compatibility, increment this version number!
|
||||
version = 1
|
||||
|
||||
## Dictionary that defines how characters are escaped when embedded in
|
||||
# g-code.
|
||||
#
|
||||
# Note that the keys of this dictionary are regex strings. The values are
|
||||
# not.
|
||||
escape_characters = {
|
||||
re.escape("\\\\"): "\\", #The escape character.
|
||||
re.escape("\\n"): "\n", #Newlines. They break off the comment.
|
||||
re.escape("\\r"): "\r" #Carriage return. Windows users may need this for visualisation in their editors.
|
||||
}
|
||||
|
||||
## Initialises the g-code reader as a profile reader.
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
## Reads a g-code file, loading the profile from it.
|
||||
#
|
||||
# \param file_name The name of the file to read the profile from.
|
||||
# \return The profile that was in the specified file, if any. If the
|
||||
# specified file was no g-code or contained no parsable profile, \code
|
||||
# None \endcode is returned.
|
||||
def read(self, file_name):
|
||||
prefix = ";SETTING_" + str(GCodeProfileReader.version) + " "
|
||||
prefix_length = len(prefix)
|
||||
|
||||
#Loading all settings from the file. They are all at the end, but Python has no reverse seek any more since Python3. TODO: Consider moving settings to the start?
|
||||
serialised = "" #Will be filled with the serialised profile.
|
||||
try:
|
||||
with open(file_name) as f:
|
||||
for line in f:
|
||||
if line.startswith(prefix):
|
||||
serialised += line[prefix_length : -1] #Remove the prefix and the newline from the line, and add it to the rest.
|
||||
except IOError as e:
|
||||
Logger.log("e", "Unable to open file %s for reading: %s", file_name, str(e))
|
||||
return None
|
||||
|
||||
#Unescape the serialised profile.
|
||||
pattern = re.compile("|".join(GCodeProfileReader.escape_characters.keys()))
|
||||
serialised = pattern.sub(lambda m: GCodeProfileReader.escape_characters[re.escape(m.group(0))], serialised) #Perform the replacement with a regular expression.
|
||||
|
||||
#Apply the changes to the current profile.
|
||||
profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False)
|
||||
try:
|
||||
profile.unserialise(serialised)
|
||||
except Exception as e: #Not a valid g-code file.
|
||||
return None
|
||||
return profile
|
27
plugins/GCodeProfileReader/__init__.py
Normal file
27
plugins/GCodeProfileReader/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import GCodeProfileReader
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"plugin": {
|
||||
"name": catalog.i18nc("@label", "GCode Profile Reader"),
|
||||
"author": "Ultimaker",
|
||||
"version": "1.0",
|
||||
"description": catalog.i18nc("@info:whatsthis", "Provides support for importing profiles from g-code files."),
|
||||
"api": 2
|
||||
},
|
||||
"profile_reader": [
|
||||
{
|
||||
"extension": "gcode",
|
||||
"description": catalog.i18nc("@item:inlistbox", "G-code File")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return { "profile_reader": GCodeProfileReader.GCodeProfileReader() }
|
|
@ -1,110 +0,0 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from UM.Mesh.MeshReader import MeshReader
|
||||
from UM.Application import Application
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Mesh.MeshData import MeshData
|
||||
|
||||
from cura.LayerData import LayerData
|
||||
from cura.LayerDataDecorator import LayerDataDecorator
|
||||
|
||||
import os
|
||||
import numpy
|
||||
|
||||
class GCodeReader(MeshReader):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._supported_extension = ".gcode"
|
||||
self._scene = Application.getInstance().getController().getScene()
|
||||
|
||||
def read(self, file_name):
|
||||
extension = os.path.splitext(file_name)[1]
|
||||
if extension.lower() == self._supported_extension:
|
||||
layer_data = LayerData()
|
||||
with open (file_name,"rt") as f:
|
||||
layer = ""
|
||||
current_path_type = ""
|
||||
|
||||
current_layer_nr = 0
|
||||
poly_list = []
|
||||
old_position = [0,0,0]
|
||||
current_z = 0
|
||||
for line in f:
|
||||
if line.startswith(';TYPE:'):
|
||||
current_path_type = line[6:].strip()
|
||||
#layer_data.addPolygon(current_layer_nr,3 ,None ,5 )
|
||||
elif line.startswith(';LAYER:'):
|
||||
current_layer_nr = int(line[7:].strip())
|
||||
layer_data.addLayer(int(line[7:].strip()))
|
||||
elif line.startswith(';'):
|
||||
pass # Ignore comments
|
||||
else:
|
||||
command_type = self.getCodeInt(line, 'G')
|
||||
if command_type == 0 or command_type == 1: #Move command
|
||||
x = self.getCodeFloat(line, 'X')
|
||||
y = self.getCodeFloat(line, 'Y')
|
||||
z = self.getCodeFloat(line, 'Z')
|
||||
if z:
|
||||
current_z = z
|
||||
if x and y:
|
||||
polygon_data = numpy.zeros((4,3)) #Square :)
|
||||
polygon_data[0,:] = old_position
|
||||
polygon_data[1,:] = old_position
|
||||
polygon_data[2,:] = [x,current_z,y]
|
||||
polygon_data[3,:] = [x,current_z,y]
|
||||
old_position = [x,current_z,y]
|
||||
if current_path_type == "SKIRT":
|
||||
layer_data.addPolygon(current_layer_nr,5 ,polygon_data ,5 )
|
||||
elif current_path_type == "WALL-INNER":
|
||||
layer_data.addPolygon(current_layer_nr,3 ,polygon_data ,5 )
|
||||
elif current_path_type == "WALL-OUTER":
|
||||
layer_data.addPolygon(current_layer_nr,1 ,polygon_data ,5 )
|
||||
else:
|
||||
layer_data.addPolygon(current_layer_nr,2 ,polygon_data ,5 )
|
||||
#e = self.getCodeFloat(line, 'E')
|
||||
#print(x , " ", y , " ", z, " " , e)
|
||||
pass
|
||||
layer_data.build()
|
||||
decorator = LayerDataDecorator()
|
||||
decorator.setLayerData(layer_data)
|
||||
new_node = SceneNode()
|
||||
new_node.setMeshData(MeshData())
|
||||
new_node.addDecorator(decorator)
|
||||
new_node.setParent(self._scene.getRoot())
|
||||
|
||||
|
||||
## Gets the value after the 'code' as int
|
||||
# example: line = "G50" and code is "G" this function will return 50
|
||||
# \param line string containing g-code.
|
||||
# \param code string Letter to look for.
|
||||
# \sa getCodeFloat
|
||||
# \returns int
|
||||
def getCodeInt(self, line, code):
|
||||
n = line.find(code) + 1
|
||||
if n < 1:
|
||||
return None
|
||||
m = line.find(' ', n)
|
||||
try:
|
||||
if m < 0:
|
||||
return int(line[n:])
|
||||
return int(line[n:m])
|
||||
except:
|
||||
return None
|
||||
## Gets the value after the 'code' as float
|
||||
# example: line = "G50" and code is "G" this function will return 50
|
||||
# \param line string containing g-code.
|
||||
# \param code string Letter to look for.
|
||||
# \sa getCodeInt
|
||||
# \returns float
|
||||
def getCodeFloat(self, line, code):
|
||||
n = line.find(code) + 1
|
||||
if n < 1:
|
||||
return None
|
||||
m = line.find(' ', n)
|
||||
try:
|
||||
if m < 0:
|
||||
return float(line[n:])
|
||||
return float(line[n:m])
|
||||
except:
|
||||
return None
|
|
@ -1,25 +0,0 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import GCodeReader
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"plugin": {
|
||||
"name": catalog.i18nc("@label", "GCode Reader"),
|
||||
"author": "Ultimaker",
|
||||
"version": "1.0",
|
||||
"description": catalog.i18nc("@info:whatsthis", "Provides support for reading GCode files."),
|
||||
"api": 2
|
||||
},
|
||||
"mesh_reader": {
|
||||
"extension": "gcode",
|
||||
"description": catalog.i18nc("@item:inlistbox", "Gcode File")
|
||||
}
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return { "mesh_reader": GCodeReader.GCodeReader() }
|
|
@ -5,9 +5,28 @@ from UM.Mesh.MeshWriter import MeshWriter
|
|||
from UM.Logger import Logger
|
||||
from UM.Application import Application
|
||||
import io
|
||||
import re #For escaping characters in the settings.
|
||||
|
||||
|
||||
class GCodeWriter(MeshWriter):
|
||||
## The file format version of the serialised g-code.
|
||||
#
|
||||
# It can only read settings with the same version as the version it was
|
||||
# written with. If the file format is changed in a way that breaks reverse
|
||||
# compatibility, increment this version number!
|
||||
version = 1
|
||||
|
||||
## Dictionary that defines how characters are escaped when embedded in
|
||||
# g-code.
|
||||
#
|
||||
# Note that the keys of this dictionary are regex strings. The values are
|
||||
# not.
|
||||
escape_characters = {
|
||||
re.escape("\\"): "\\\\", #The escape character.
|
||||
re.escape("\n"): "\\n", #Newlines. They break off the comment.
|
||||
re.escape("\r"): "\\r" #Carriage return. Windows users may need this for visualisation in their editors.
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
|
@ -21,6 +40,33 @@ class GCodeWriter(MeshWriter):
|
|||
if gcode_list:
|
||||
for gcode in gcode_list:
|
||||
stream.write(gcode)
|
||||
profile = self._serialiseProfile(Application.getInstance().getMachineManager().getActiveProfile()) #Serialise the profile and put them at the end of the file.
|
||||
stream.write(profile)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
## Serialises the profile to prepare it for saving in the g-code.
|
||||
#
|
||||
# The profile are serialised, and special characters (including newline)
|
||||
# are escaped.
|
||||
#
|
||||
# \param profile The profile to serialise.
|
||||
# \return A serialised string of the profile.
|
||||
def _serialiseProfile(self, profile):
|
||||
prefix = ";SETTING_" + str(GCodeWriter.version) + " " #The prefix to put before each line.
|
||||
prefix_length = len(prefix)
|
||||
|
||||
serialised = profile.serialise()
|
||||
|
||||
#Escape characters that have a special meaning in g-code comments.
|
||||
pattern = re.compile("|".join(GCodeWriter.escape_characters.keys()))
|
||||
serialised = pattern.sub(lambda m: GCodeWriter.escape_characters[re.escape(m.group(0))], serialised) #Perform the replacement with a regular expression.
|
||||
|
||||
#Introduce line breaks so that each comment is no longer than 80 characters. Prepend each line with the prefix.
|
||||
result = ""
|
||||
for pos in range(0, len(serialised), 80 - prefix_length): #Lines have 80 characters, so the payload of each line is 80 - prefix.
|
||||
result += prefix + serialised[pos : pos + 80 - prefix_length] + "\n"
|
||||
serialised = result
|
||||
|
||||
return serialised
|
205
plugins/ImageReader/ConfigUI.qml
Normal file
205
plugins/ImageReader/ConfigUI.qml
Normal file
|
@ -0,0 +1,205 @@
|
|||
// Copyright (c) 2015 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.1
|
||||
|
||||
import UM 1.1 as UM
|
||||
|
||||
UM.Dialog
|
||||
{
|
||||
width: 350*Screen.devicePixelRatio;
|
||||
minimumWidth: 350*Screen.devicePixelRatio;
|
||||
maximumWidth: 350*Screen.devicePixelRatio;
|
||||
|
||||
height: 220*Screen.devicePixelRatio;
|
||||
minimumHeight: 220*Screen.devicePixelRatio;
|
||||
maximumHeight: 220*Screen.devicePixelRatio;
|
||||
|
||||
|
||||
modality: Qt.Modal
|
||||
|
||||
title: catalog.i18nc("@title:window", "Convert Image...")
|
||||
|
||||
GridLayout
|
||||
{
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
anchors.fill: parent;
|
||||
Layout.fillWidth: true
|
||||
columnSpacing: 16
|
||||
rowSpacing: 4
|
||||
columns: 1
|
||||
|
||||
UM.TooltipArea {
|
||||
Layout.fillWidth:true
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","The maximum distance of each pixel from \"Base.\"")
|
||||
Row {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
Text {
|
||||
text: catalog.i18nc("@action:label","Height (mm)")
|
||||
width: 150
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: peak_height
|
||||
objectName: "Peak_Height"
|
||||
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: -500; top: 500;}
|
||||
width: 180
|
||||
onTextChanged: { manager.onPeakHeightChanged(text) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UM.TooltipArea {
|
||||
Layout.fillWidth:true
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","The base height from the build plate in millimeters.")
|
||||
Row {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
Text {
|
||||
text: catalog.i18nc("@action:label","Base (mm)")
|
||||
width: 150
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: base_height
|
||||
objectName: "Base_Height"
|
||||
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 0; top: 500;}
|
||||
width: 180
|
||||
onTextChanged: { manager.onBaseHeightChanged(text) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UM.TooltipArea {
|
||||
Layout.fillWidth:true
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","The width in millimeters on the build plate.")
|
||||
Row {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
Text {
|
||||
text: catalog.i18nc("@action:label","Width (mm)")
|
||||
width: 150
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: width
|
||||
objectName: "Width"
|
||||
focus: true
|
||||
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 1; top: 500;}
|
||||
width: 180
|
||||
onTextChanged: { manager.onWidthChanged(text) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UM.TooltipArea {
|
||||
Layout.fillWidth:true
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","The depth in millimeters on the build plate")
|
||||
Row {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
Text {
|
||||
text: catalog.i18nc("@action:label","Depth (mm)")
|
||||
width: 150
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
TextField {
|
||||
id: depth
|
||||
objectName: "Depth"
|
||||
focus: true
|
||||
validator: DoubleValidator {notation: DoubleValidator.StandardNotation; bottom: 1; top: 500;}
|
||||
width: 180
|
||||
onTextChanged: { manager.onDepthChanged(text) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UM.TooltipArea {
|
||||
Layout.fillWidth:true
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","By default, white pixels represent high points on the mesh and black pixels represent low points on the mesh. Change this option to reverse the behavior such that black pixels represent high points on the mesh and white pixels represent low points on the mesh.")
|
||||
Row {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
//Empty label so 2 column layout works.
|
||||
Text {
|
||||
text: ""
|
||||
width: 150
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
ComboBox {
|
||||
id: image_color_invert
|
||||
objectName: "Image_Color_Invert"
|
||||
model: [ catalog.i18nc("@item:inlistbox","Lighter is higher"), catalog.i18nc("@item:inlistbox","Darker is higher") ]
|
||||
width: 180
|
||||
onCurrentIndexChanged: { manager.onImageColorInvertChanged(currentIndex) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UM.TooltipArea {
|
||||
Layout.fillWidth:true
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","The amount of smoothing to apply to the image.")
|
||||
Row {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
Text {
|
||||
text: catalog.i18nc("@action:label","Smoothing")
|
||||
width: 150
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 180
|
||||
height: 20
|
||||
Layout.fillWidth:true
|
||||
color: "transparent"
|
||||
|
||||
Slider {
|
||||
id: smoothing
|
||||
objectName: "Smoothing"
|
||||
maximumValue: 100.0
|
||||
stepSize: 1.0
|
||||
width: 180
|
||||
onValueChanged: { manager.onSmoothingChanged(value) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightButtons: [
|
||||
Button
|
||||
{
|
||||
id:ok_button
|
||||
text: catalog.i18nc("@action:button","OK");
|
||||
onClicked: { manager.onOkButtonClicked() }
|
||||
enabled: true
|
||||
},
|
||||
Button
|
||||
{
|
||||
id:cancel_button
|
||||
text: catalog.i18nc("@action:button","Cancel");
|
||||
onClicked: { manager.onCancelButtonClicked() }
|
||||
enabled: true
|
||||
}
|
||||
]
|
||||
}
|
216
plugins/ImageReader/ImageReader.py
Normal file
216
plugins/ImageReader/ImageReader.py
Normal file
|
@ -0,0 +1,216 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import os
|
||||
import numpy
|
||||
|
||||
from PyQt5.QtGui import QImage, qRed, qGreen, qBlue
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from UM.Mesh.MeshReader import MeshReader
|
||||
from UM.Mesh.MeshData import MeshData
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Job import Job
|
||||
from UM.Logger import Logger
|
||||
from .ImageReaderUI import ImageReaderUI
|
||||
|
||||
|
||||
class ImageReader(MeshReader):
|
||||
def __init__(self):
|
||||
super(ImageReader, self).__init__()
|
||||
self._supported_extensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"]
|
||||
self._ui = ImageReaderUI(self)
|
||||
|
||||
def preRead(self, file_name):
|
||||
img = QImage(file_name)
|
||||
|
||||
if img.isNull():
|
||||
Logger.log("e", "Image is corrupt.")
|
||||
return MeshReader.PreReadResult.failed
|
||||
|
||||
width = img.width()
|
||||
depth = img.height()
|
||||
|
||||
largest = max(width, depth)
|
||||
width = width / largest * self._ui.defaultWidth
|
||||
depth = depth / largest * self._ui.defaultDepth
|
||||
|
||||
self._ui.setWidthAndDepth(width, depth)
|
||||
self._ui.showConfigUI()
|
||||
self._ui.waitForUIToClose()
|
||||
|
||||
if self._ui.getCancelled():
|
||||
return MeshReader.PreReadResult.cancelled
|
||||
return MeshReader.PreReadResult.accepted
|
||||
|
||||
def read(self, file_name):
|
||||
size = max(self._ui.getWidth(), self._ui.getDepth())
|
||||
return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.image_color_invert)
|
||||
|
||||
def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, image_color_invert):
|
||||
mesh = None
|
||||
scene_node = None
|
||||
|
||||
scene_node = SceneNode()
|
||||
|
||||
mesh = MeshData()
|
||||
scene_node.setMeshData(mesh)
|
||||
|
||||
img = QImage(file_name)
|
||||
|
||||
if img.isNull():
|
||||
Logger.log("e", "Image is corrupt.")
|
||||
return None
|
||||
|
||||
width = max(img.width(), 2)
|
||||
height = max(img.height(), 2)
|
||||
aspect = height / width
|
||||
|
||||
if img.width() < 2 or img.height() < 2:
|
||||
img = img.scaled(width, height, Qt.IgnoreAspectRatio)
|
||||
|
||||
base_height = max(base_height, 0)
|
||||
peak_height = max(peak_height, -base_height)
|
||||
|
||||
xz_size = max(xz_size, 1)
|
||||
scale_vector = Vector(xz_size, peak_height, xz_size)
|
||||
|
||||
if width > height:
|
||||
scale_vector.setZ(scale_vector.z * aspect)
|
||||
elif height > width:
|
||||
scale_vector.setX(scale_vector.x / aspect)
|
||||
|
||||
if width > max_size or height > max_size:
|
||||
scale_factor = max_size / width
|
||||
if height > width:
|
||||
scale_factor = max_size / height
|
||||
|
||||
width = int(max(round(width * scale_factor), 2))
|
||||
height = int(max(round(height * scale_factor), 2))
|
||||
img = img.scaled(width, height, Qt.IgnoreAspectRatio)
|
||||
|
||||
width_minus_one = width - 1
|
||||
height_minus_one = height - 1
|
||||
|
||||
Job.yieldThread()
|
||||
|
||||
texel_width = 1.0 / (width_minus_one) * scale_vector.x
|
||||
texel_height = 1.0 / (height_minus_one) * scale_vector.z
|
||||
|
||||
height_data = numpy.zeros((height, width), dtype=numpy.float32)
|
||||
|
||||
for x in range(0, width):
|
||||
for y in range(0, height):
|
||||
qrgb = img.pixel(x, y)
|
||||
avg = float(qRed(qrgb) + qGreen(qrgb) + qBlue(qrgb)) / (3 * 255)
|
||||
height_data[y, x] = avg
|
||||
|
||||
Job.yieldThread()
|
||||
|
||||
if image_color_invert:
|
||||
height_data = 1 - height_data
|
||||
|
||||
for i in range(0, blur_iterations):
|
||||
copy = numpy.pad(height_data, ((1, 1), (1, 1)), mode='edge')
|
||||
|
||||
height_data += copy[1:-1, 2:]
|
||||
height_data += copy[1:-1, :-2]
|
||||
height_data += copy[2:, 1:-1]
|
||||
height_data += copy[:-2, 1:-1]
|
||||
|
||||
height_data += copy[2:, 2:]
|
||||
height_data += copy[:-2, 2:]
|
||||
height_data += copy[2:, :-2]
|
||||
height_data += copy[:-2, :-2]
|
||||
|
||||
height_data /= 9
|
||||
|
||||
Job.yieldThread()
|
||||
|
||||
height_data *= scale_vector.y
|
||||
height_data += base_height
|
||||
|
||||
heightmap_face_count = 2 * height_minus_one * width_minus_one
|
||||
total_face_count = heightmap_face_count + (width_minus_one * 2) * (height_minus_one * 2) + 2
|
||||
|
||||
mesh.reserveFaceCount(total_face_count)
|
||||
|
||||
# initialize to texel space vertex offsets.
|
||||
# 6 is for 6 vertices for each texel quad.
|
||||
heightmap_vertices = numpy.zeros((width_minus_one * height_minus_one, 6, 3), dtype=numpy.float32)
|
||||
heightmap_vertices = heightmap_vertices + numpy.array([[
|
||||
[0, base_height, 0],
|
||||
[0, base_height, texel_height],
|
||||
[texel_width, base_height, texel_height],
|
||||
[texel_width, base_height, texel_height],
|
||||
[texel_width, base_height, 0],
|
||||
[0, base_height, 0]
|
||||
]], dtype=numpy.float32)
|
||||
|
||||
offsetsz, offsetsx = numpy.mgrid[0:height_minus_one, 0:width-1]
|
||||
offsetsx = numpy.array(offsetsx, numpy.float32).reshape(-1, 1) * texel_width
|
||||
offsetsz = numpy.array(offsetsz, numpy.float32).reshape(-1, 1) * texel_height
|
||||
|
||||
# offsets for each texel quad
|
||||
heightmap_vertex_offsets = numpy.concatenate([offsetsx, numpy.zeros((offsetsx.shape[0], offsetsx.shape[1]), dtype=numpy.float32), offsetsz], 1)
|
||||
heightmap_vertices += heightmap_vertex_offsets.repeat(6, 0).reshape(-1, 6, 3)
|
||||
|
||||
# apply height data to y values
|
||||
heightmap_vertices[:, 0, 1] = heightmap_vertices[:, 5, 1] = height_data[:-1, :-1].reshape(-1)
|
||||
heightmap_vertices[:, 1, 1] = height_data[1:, :-1].reshape(-1)
|
||||
heightmap_vertices[:, 2, 1] = heightmap_vertices[:, 3, 1] = height_data[1:, 1:].reshape(-1)
|
||||
heightmap_vertices[:, 4, 1] = height_data[:-1, 1:].reshape(-1)
|
||||
|
||||
heightmap_indices = numpy.array(numpy.mgrid[0:heightmap_face_count * 3], dtype=numpy.int32).reshape(-1, 3)
|
||||
|
||||
mesh._vertices[0:(heightmap_vertices.size // 3), :] = heightmap_vertices.reshape(-1, 3)
|
||||
mesh._indices[0:(heightmap_indices.size // 3), :] = heightmap_indices
|
||||
|
||||
mesh._vertex_count = heightmap_vertices.size // 3
|
||||
mesh._face_count = heightmap_indices.size // 3
|
||||
|
||||
geo_width = width_minus_one * texel_width
|
||||
geo_height = height_minus_one * texel_height
|
||||
|
||||
# bottom
|
||||
mesh.addFace(0, 0, 0, 0, 0, geo_height, geo_width, 0, geo_height)
|
||||
mesh.addFace(geo_width, 0, geo_height, geo_width, 0, 0, 0, 0, 0)
|
||||
|
||||
# north and south walls
|
||||
for n in range(0, width_minus_one):
|
||||
x = n * texel_width
|
||||
nx = (n + 1) * texel_width
|
||||
|
||||
hn0 = height_data[0, n]
|
||||
hn1 = height_data[0, n + 1]
|
||||
|
||||
hs0 = height_data[height_minus_one, n]
|
||||
hs1 = height_data[height_minus_one, n + 1]
|
||||
|
||||
mesh.addFace(x, 0, 0, nx, 0, 0, nx, hn1, 0)
|
||||
mesh.addFace(nx, hn1, 0, x, hn0, 0, x, 0, 0)
|
||||
|
||||
mesh.addFace(x, 0, geo_height, nx, 0, geo_height, nx, hs1, geo_height)
|
||||
mesh.addFace(nx, hs1, geo_height, x, hs0, geo_height, x, 0, geo_height)
|
||||
|
||||
# west and east walls
|
||||
for n in range(0, height_minus_one):
|
||||
y = n * texel_height
|
||||
ny = (n + 1) * texel_height
|
||||
|
||||
hw0 = height_data[n, 0]
|
||||
hw1 = height_data[n + 1, 0]
|
||||
|
||||
he0 = height_data[n, width_minus_one]
|
||||
he1 = height_data[n + 1, width_minus_one]
|
||||
|
||||
mesh.addFace(0, 0, y, 0, 0, ny, 0, hw1, ny)
|
||||
mesh.addFace(0, hw1, ny, 0, hw0, y, 0, 0, y)
|
||||
|
||||
mesh.addFace(geo_width, 0, y, geo_width, 0, ny, geo_width, he1, ny)
|
||||
mesh.addFace(geo_width, he1, ny, geo_width, he0, y, geo_width, 0, y)
|
||||
|
||||
mesh.calculateNormals(fast=True)
|
||||
|
||||
return scene_node
|
155
plugins/ImageReader/ImageReaderUI.py
Normal file
155
plugins/ImageReader/ImageReaderUI.py
Normal file
|
@ -0,0 +1,155 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import os
|
||||
import threading
|
||||
|
||||
from PyQt5.QtCore import Qt, QUrl, pyqtSignal, pyqtSlot, QObject
|
||||
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Logger import Logger
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
class ImageReaderUI(QObject):
|
||||
show_config_ui_trigger = pyqtSignal()
|
||||
|
||||
def __init__(self, image_reader):
|
||||
super(ImageReaderUI, self).__init__()
|
||||
self.image_reader = image_reader
|
||||
self._ui_view = None
|
||||
self.show_config_ui_trigger.connect(self._actualShowConfigUI)
|
||||
|
||||
self.defaultWidth = 120
|
||||
self.defaultDepth = 120
|
||||
|
||||
self._aspect = 1
|
||||
self._width = self.defaultWidth
|
||||
self._depth = self.defaultDepth
|
||||
|
||||
self.base_height = 1
|
||||
self.peak_height = 10
|
||||
self.smoothing = 1
|
||||
self.image_color_invert = False;
|
||||
|
||||
self._ui_lock = threading.Lock()
|
||||
self._cancelled = False
|
||||
self._disable_size_callbacks = False
|
||||
|
||||
def setWidthAndDepth(self, width, depth):
|
||||
self._aspect = width / depth
|
||||
self._width = width
|
||||
self._depth = depth
|
||||
|
||||
def getWidth(self):
|
||||
return self._width
|
||||
|
||||
def getDepth(self):
|
||||
return self._depth
|
||||
|
||||
def getCancelled(self):
|
||||
return self._cancelled
|
||||
|
||||
def waitForUIToClose(self):
|
||||
self._ui_lock.acquire()
|
||||
self._ui_lock.release()
|
||||
|
||||
def showConfigUI(self):
|
||||
self._ui_lock.acquire()
|
||||
self._cancelled = False
|
||||
self.show_config_ui_trigger.emit()
|
||||
|
||||
def _actualShowConfigUI(self):
|
||||
self._disable_size_callbacks = True
|
||||
|
||||
if self._ui_view is None:
|
||||
self._createConfigUI()
|
||||
self._ui_view.show()
|
||||
|
||||
self._ui_view.findChild(QObject, "Width").setProperty("text", str(self._width))
|
||||
self._ui_view.findChild(QObject, "Depth").setProperty("text", str(self._depth))
|
||||
self._disable_size_callbacks = False
|
||||
|
||||
self._ui_view.findChild(QObject, "Base_Height").setProperty("text", str(self.base_height))
|
||||
self._ui_view.findChild(QObject, "Peak_Height").setProperty("text", str(self.peak_height))
|
||||
self._ui_view.findChild(QObject, "Smoothing").setProperty("value", self.smoothing)
|
||||
|
||||
def _createConfigUI(self):
|
||||
if self._ui_view is None:
|
||||
Logger.log("d", "Creating ImageReader config UI")
|
||||
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("ImageReader"), "ConfigUI.qml"))
|
||||
component = QQmlComponent(Application.getInstance()._engine, path)
|
||||
self._ui_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
||||
self._ui_context.setContextProperty("manager", self)
|
||||
self._ui_view = component.create(self._ui_context)
|
||||
|
||||
self._ui_view.setFlags(self._ui_view.flags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowMinimizeButtonHint & ~Qt.WindowMaximizeButtonHint);
|
||||
|
||||
self._disable_size_callbacks = False
|
||||
|
||||
@pyqtSlot()
|
||||
def onOkButtonClicked(self):
|
||||
self._cancelled = False
|
||||
self._ui_view.close()
|
||||
self._ui_lock.release()
|
||||
|
||||
@pyqtSlot()
|
||||
def onCancelButtonClicked(self):
|
||||
self._cancelled = True
|
||||
self._ui_view.close()
|
||||
self._ui_lock.release()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def onWidthChanged(self, value):
|
||||
if self._ui_view and not self._disable_size_callbacks:
|
||||
if len(value) > 0:
|
||||
self._width = float(value)
|
||||
else:
|
||||
self._width = 0
|
||||
|
||||
self._depth = self._width / self._aspect
|
||||
self._disable_size_callbacks = True
|
||||
self._ui_view.findChild(QObject, "Depth").setProperty("text", str(self._depth))
|
||||
self._disable_size_callbacks = False
|
||||
|
||||
@pyqtSlot(str)
|
||||
def onDepthChanged(self, value):
|
||||
if self._ui_view and not self._disable_size_callbacks:
|
||||
if len(value) > 0:
|
||||
self._depth = float(value)
|
||||
else:
|
||||
self._depth = 0
|
||||
|
||||
self._width = self._depth * self._aspect
|
||||
self._disable_size_callbacks = True
|
||||
self._ui_view.findChild(QObject, "Width").setProperty("text", str(self._width))
|
||||
self._disable_size_callbacks = False
|
||||
|
||||
@pyqtSlot(str)
|
||||
def onBaseHeightChanged(self, value):
|
||||
if (len(value) > 0):
|
||||
self.base_height = float(value)
|
||||
else:
|
||||
self.base_height = 0
|
||||
|
||||
@pyqtSlot(str)
|
||||
def onPeakHeightChanged(self, value):
|
||||
if (len(value) > 0):
|
||||
self.peak_height = float(value)
|
||||
else:
|
||||
self.peak_height = 0
|
||||
|
||||
@pyqtSlot(float)
|
||||
def onSmoothingChanged(self, value):
|
||||
self.smoothing = int(value)
|
||||
|
||||
@pyqtSlot(int)
|
||||
def onImageColorInvertChanged(self, value):
|
||||
if (value == 1):
|
||||
self.image_color_invert = True
|
||||
else:
|
||||
self.image_color_invert = False
|
43
plugins/ImageReader/__init__.py
Normal file
43
plugins/ImageReader/__init__.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import ImageReader
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"plugin": {
|
||||
"name": i18n_catalog.i18nc("@label", "Image Reader"),
|
||||
"author": "Ultimaker",
|
||||
"version": "1.0",
|
||||
"description": i18n_catalog.i18nc("@info:whatsthis", "Enables ability to generate printable geometry from 2D image files."),
|
||||
"api": 2
|
||||
},
|
||||
"mesh_reader": [
|
||||
{
|
||||
"extension": "jpg",
|
||||
"description": i18n_catalog.i18nc("@item:inlistbox", "JPG Image")
|
||||
},
|
||||
{
|
||||
"extension": "jpeg",
|
||||
"description": i18n_catalog.i18nc("@item:inlistbox", "JPEG Image")
|
||||
},
|
||||
{
|
||||
"extension": "png",
|
||||
"description": i18n_catalog.i18nc("@item:inlistbox", "PNG Image")
|
||||
},
|
||||
{
|
||||
"extension": "bmp",
|
||||
"description": i18n_catalog.i18nc("@item:inlistbox", "BMP Image")
|
||||
},
|
||||
{
|
||||
"extension": "gif",
|
||||
"description": i18n_catalog.i18nc("@item:inlistbox", "GIF Image")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return { "mesh_reader": ImageReader.ImageReader() }
|
|
@ -59,7 +59,7 @@ class LayerView(View):
|
|||
renderer = self.getRenderer()
|
||||
|
||||
if not self._selection_shader:
|
||||
self._selection_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader"))
|
||||
self._selection_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader"))
|
||||
self._selection_shader.setUniformValue("u_color", Color(32, 32, 32, 128))
|
||||
|
||||
for node in DepthFirstIterator(scene.getRoot()):
|
||||
|
|
|
@ -18,7 +18,8 @@ def getMetaData():
|
|||
},
|
||||
"view": {
|
||||
"name": catalog.i18nc("@item:inlistbox", "Layers"),
|
||||
"view_panel": "LayerView.qml"
|
||||
"view_panel": "LayerView.qml",
|
||||
"weight": 2
|
||||
}
|
||||
}
|
||||
|
||||
|
|
157
plugins/LegacyProfileReader/DictionaryOfDoom.json
Normal file
157
plugins/LegacyProfileReader/DictionaryOfDoom.json
Normal file
|
@ -0,0 +1,157 @@
|
|||
{
|
||||
"source_version": "15.04",
|
||||
"target_version": 1,
|
||||
|
||||
"translation": {
|
||||
"machine_nozzle_size": "nozzle_size",
|
||||
"line_width": "wall_thickness if (spiralize == \"True\" or simple_mode == \"True\") else (nozzle_size if (float(wall_thickness) < 0.01) else (wall_thickness if (float(wall_thickness) < float(nozzle_size)) else (nozzle_size if ((int(float(wall_thickness) / (float(nozzle_size) - 0.0001))) == 0) else ((float(wall_thickness) / ((int(float(wall_thickness) / (float(nozzle_size) - 0.0001))) + 1)) if ((float(wall_thickness) / (int(float(wall_thickness) / (float(nozzle_size) - 0.0001)))) > float(nozzle_size) * 1.5) else ((float(wall_thickness) / (int(float(wall_thickness) / (float(nozzle_size) - 0.0001)))))))))",
|
||||
"layer_height": "layer_height",
|
||||
"layer_height_0": "bottom_thickness",
|
||||
"wall_thickness": "wall_thickness",
|
||||
"top_bottom_thickness": "solid_layer_thickness",
|
||||
"top_thickness": "0 if (solid_top == \"False\") else solid_layer_thickness",
|
||||
"bottom_thickness": "0 if (solid_bottom == \"False\") else solid_layer_thickness",
|
||||
"infill_sparse_density": "fill_density",
|
||||
"infill_overlap": "fill_overlap",
|
||||
"infill_before_walls": "False if (perimeter_before_infill == \"True\") else True",
|
||||
"material_print_temperature": "print_temperature",
|
||||
"material_bed_temperature": "print_bed_temperature",
|
||||
"material_diameter": "filament_diameter",
|
||||
"material_flow": "filament_flow",
|
||||
"retraction_enable": "retraction_enable",
|
||||
"retraction_amount": "retraction_amount",
|
||||
"retraction_speed": "retraction_speed",
|
||||
"retraction_min_travel": "retraction_min_travel",
|
||||
"retraction_hop": "retraction_hop",
|
||||
"speed_print": "print_speed",
|
||||
"speed_infill": "infill_speed if (float(infill_speed) != 0) else print_speed",
|
||||
"speed_wall_0": "inset0_speed if (float(inset0_speed) != 0) else print_speed",
|
||||
"speed_wall_x": "insetx_speed if (float(insetx_speed) != 0) else print_speed",
|
||||
"speed_topbottom": "solidarea_speed if (float(solidarea_speed) != 0) else print_speed",
|
||||
"speed_travel": "travel_speed if (float(travel_speed) != 0) else travel_speed",
|
||||
"speed_layer_0": "bottom_layer_speed",
|
||||
"retraction_combing": "True if (retraction_combing == \"All\" or retraction_combing == \"No Skin\") else False",
|
||||
"cool_fan_enabled": "fan_enabled",
|
||||
"cool_fan_speed_min": "fan_speed",
|
||||
"cool_fan_speed_max": "fan_speed_max",
|
||||
"cool_fan_full_at_height": "fan_full_height",
|
||||
"cool_min_layer_time": "cool_min_layer_time",
|
||||
"cool_min_speed": "cool_min_feedrate",
|
||||
"cool_lift_head": "cool_head_lift",
|
||||
"support_enable": "False if (support == \"None\") else True",
|
||||
"support_type": "\"buildplate\" if (support == \"Touching buildplate\") else \"everywhere\"",
|
||||
"support_angle": "support_angle",
|
||||
"support_xy_distance": "support_xy_distance",
|
||||
"support_z_distance": "support_z_distance",
|
||||
"support_pattern": "support_type.lower()",
|
||||
"support_infill_rate": "support_fill_rate",
|
||||
"adhesion_type": "\"skirt\" if (platform_adhesion == \"None\") else platform_adhesion.lower()",
|
||||
"skirt_line_count": "skirt_line_count",
|
||||
"skirt_gap": "skirt_gap",
|
||||
"skirt_minimal_length": "skirt_minimal_length",
|
||||
"brim_line_count": "brim_line_count",
|
||||
"raft_margin": "raft_margin",
|
||||
"raft_airgap": "raft_airgap_all",
|
||||
"raft_surface_layers": "raft_surface_layers",
|
||||
"raft_surface_thickness": "raft_surface_thickness",
|
||||
"raft_surface_line_width": "raft_surface_linewidth",
|
||||
"raft_surface_line_spacing": "raft_line_spacing",
|
||||
"raft_interface_thickness": "raft_interface_thickness",
|
||||
"raft_interface_line_width": "raft_interface_linewidth",
|
||||
"raft_interface_line_spacing": "raft_line_spacing",
|
||||
"raft_base_thickness": "raft_base_thickness",
|
||||
"raft_base_line_width": "raft_base_linewidth",
|
||||
"raft_base_line_spacing": "raft_line_spacing",
|
||||
"meshfix_union_all": "fix_horrible_union_all_type_a",
|
||||
"meshfix_union_all_remove_holes": "fix_horrible_union_all_type_b",
|
||||
"meshfix_extensive_stitching": "fix_horrible_extensive_stitching",
|
||||
"meshfix_keep_open_polygons": "fix_horrible_use_open_bits",
|
||||
"magic_mesh_surface_mode": "simple_mode",
|
||||
"magic_spiralize": "spiralize",
|
||||
"prime_tower_enable": "wipe_tower",
|
||||
"prime_tower_size": "math.sqrt(float(wipe_tower_volume) / float(layer_height))",
|
||||
"ooze_shield_enabled": "ooze_shield"
|
||||
},
|
||||
|
||||
"defaults": {
|
||||
"bottom_layer_speed": "20",
|
||||
"bottom_thickness": "0.3",
|
||||
"brim_line_count": "20",
|
||||
"cool_head_lift": "False",
|
||||
"cool_min_feedrate": "10",
|
||||
"cool_min_layer_time": "5",
|
||||
"fan_enabled": "True",
|
||||
"fan_full_height": "0.5",
|
||||
"fan_speed": "100",
|
||||
"fan_speed_max": "100",
|
||||
"filament_diameter": "2.85",
|
||||
"filament_diameter2": "0",
|
||||
"filament_diameter3": "0",
|
||||
"filament_diameter4": "0",
|
||||
"filament_diameter5": "0",
|
||||
"filament_flow": "100.0",
|
||||
"fill_density": "20",
|
||||
"fill_overlap": "15",
|
||||
"fix_horrible_extensive_stitching": "False",
|
||||
"fix_horrible_union_all_type_a": "True",
|
||||
"fix_horrible_union_all_type_b": "False",
|
||||
"fix_horrible_use_open_bits": "False",
|
||||
"infill_speed": "0.0",
|
||||
"inset0_speed": "0.0",
|
||||
"insetx_speed": "0.0",
|
||||
"layer_height": "0.1",
|
||||
"layer0_width_factor": "100",
|
||||
"nozzle_size": "0.4",
|
||||
"object_sink": "0.0",
|
||||
"ooze_shield": "False",
|
||||
"overlap_dual": "0.15",
|
||||
"perimeter_before_infill": "False",
|
||||
"platform_adhesion": "None",
|
||||
"print_bed_temperature": "70",
|
||||
"print_speed": "50",
|
||||
"print_temperature": "210",
|
||||
"print_temperature2": "0",
|
||||
"print_temperature3": "0",
|
||||
"print_temperature4": "0",
|
||||
"print_temperature5": "0",
|
||||
"raft_airgap": "0.22",
|
||||
"raft_airgap_all": "0.0",
|
||||
"raft_base_linewidth": "1.0",
|
||||
"raft_base_thickness": "0.3",
|
||||
"raft_interface_linewidth": "0.4",
|
||||
"raft_interface_thickness": "0.27",
|
||||
"raft_line_spacing": "3.0",
|
||||
"raft_margin": "5.0",
|
||||
"raft_surface_layers": "2",
|
||||
"raft_surface_linewidth": "0.4",
|
||||
"raft_surface_thickness": "0.27",
|
||||
"retraction_amount": "4.5",
|
||||
"retraction_combing": "All",
|
||||
"retraction_dual_amount": "16.5",
|
||||
"retraction_enable": "True",
|
||||
"retraction_hop": "0.0",
|
||||
"retraction_min_travel": "1.5",
|
||||
"retraction_minimal_extrusion": "0.02",
|
||||
"retraction_speed": "40.0",
|
||||
"simple_mode": "False",
|
||||
"skirt_gap": "3.0",
|
||||
"skirt_line_count": "1",
|
||||
"skirt_minimal_length": "150.0",
|
||||
"solid_bottom": "True",
|
||||
"solid_layer_thickness": "0.6",
|
||||
"solid_top": "True",
|
||||
"solidarea_speed": "0.0",
|
||||
"spiralize": "False",
|
||||
"support": "None",
|
||||
"support_angle": "60",
|
||||
"support_dual_extrusion": "Both",
|
||||
"support_fill_rate": "15",
|
||||
"support_type": "Lines",
|
||||
"support_xy_distance": "0.7",
|
||||
"support_z_distance": "0.15",
|
||||
"travel_speed": "150.0",
|
||||
"wall_thickness": "0.8",
|
||||
"wipe_tower": "False",
|
||||
"wipe_tower_volume": "15"
|
||||
}
|
||||
}
|
127
plugins/LegacyProfileReader/LegacyProfileReader.py
Normal file
127
plugins/LegacyProfileReader/LegacyProfileReader.py
Normal file
|
@ -0,0 +1,127 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import configparser #For reading the legacy profile INI files.
|
||||
import json #For reading the Dictionary of Doom.
|
||||
import math #For mathematical operations included in the Dictionary of Doom.
|
||||
import os.path #For concatenating the path to the plugin and the relative path to the Dictionary of Doom.
|
||||
|
||||
from UM.Application import Application #To get the machine manager to create the new profile in.
|
||||
from UM.Logger import Logger #Logging errors.
|
||||
from UM.PluginRegistry import PluginRegistry #For getting the path to this plugin's directory.
|
||||
from UM.Settings.Profile import Profile
|
||||
from UM.Settings.ProfileReader import ProfileReader
|
||||
|
||||
## A plugin that reads profile data from legacy Cura versions.
|
||||
#
|
||||
# It reads a profile from an .ini file, and performs some translations on it.
|
||||
# Not all translations are correct, mind you, but it is a best effort.
|
||||
class LegacyProfileReader(ProfileReader):
|
||||
## Initialises the legacy profile reader.
|
||||
#
|
||||
# This does nothing since the only other function is basically stateless.
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
## Prepares the default values of all legacy settings.
|
||||
#
|
||||
# These are loaded from the Dictionary of Doom.
|
||||
#
|
||||
# \param json The JSON file to load the default setting values from. This
|
||||
# should not be a URL but a pre-loaded JSON handle.
|
||||
# \return A dictionary of the default values of the legacy Cura version.
|
||||
def prepareDefaults(self, json):
|
||||
defaults = {}
|
||||
for key in json["defaults"]: #We have to copy over all defaults from the JSON handle to a normal dict.
|
||||
defaults[key] = json["defaults"][key]
|
||||
return defaults
|
||||
|
||||
## Prepares the local variables that can be used in evaluation of computing
|
||||
# new setting values from the old ones.
|
||||
#
|
||||
# This fills a dictionary with all settings from the legacy Cura version
|
||||
# and their values, so that they can be used in evaluating the new setting
|
||||
# values as Python code.
|
||||
#
|
||||
# \param config_parser The ConfigParser that finds the settings in the
|
||||
# legacy profile.
|
||||
# \param config_section The section in the profile where the settings
|
||||
# should be found.
|
||||
# \param defaults The default values for all settings in the legacy Cura.
|
||||
# \return A set of local variables, one for each setting in the legacy
|
||||
# profile.
|
||||
def prepareLocals(self, config_parser, config_section, defaults):
|
||||
locals = defaults.copy() #Don't edit the original!
|
||||
for option in config_parser.options(config_section):
|
||||
locals[option] = config_parser.get(config_section, option)
|
||||
return locals
|
||||
|
||||
## Reads a legacy Cura profile from a file and returns it.
|
||||
#
|
||||
# \param file_name The file to read the legacy Cura profile from.
|
||||
# \return The legacy Cura profile that was in the file, if any. If the
|
||||
# file could not be read or didn't contain a valid profile, \code None
|
||||
# \endcode is returned.
|
||||
def read(self, file_name):
|
||||
Logger.log("i", "Importing legacy profile from file " + file_name + ".")
|
||||
profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) #Create an empty profile.
|
||||
profile.setName("Imported Legacy Profile")
|
||||
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
try:
|
||||
with open(file_name) as f:
|
||||
parser.readfp(f) #Parse the INI file.
|
||||
except Exception as e:
|
||||
Logger.log("e", "Unable to open legacy profile %s: %s", file_name, str(e))
|
||||
return None
|
||||
|
||||
#Legacy Cura saved the profile under the section "profile_N" where N is the ID of a machine, except when you export in which case it saves it in the section "profile".
|
||||
#Since importing multiple machine profiles is out of scope, just import the first section we find.
|
||||
section = ""
|
||||
for found_section in parser.sections():
|
||||
if found_section.startswith("profile"):
|
||||
section = found_section
|
||||
break
|
||||
if not section: #No section starting with "profile" was found. Probably not a proper INI file.
|
||||
return None
|
||||
|
||||
try:
|
||||
with open(os.path.join(PluginRegistry.getInstance().getPluginPath("LegacyProfileReader"), "DictionaryOfDoom.json"), "r", -1, "utf-8") as f:
|
||||
dict_of_doom = json.load(f) #Parse the Dictionary of Doom.
|
||||
except IOError as e:
|
||||
Logger.log("e", "Could not open DictionaryOfDoom.json for reading: %s", str(e))
|
||||
return None
|
||||
except Exception as e:
|
||||
Logger.log("e", "Could not parse DictionaryOfDoom.json: %s", str(e))
|
||||
return None
|
||||
|
||||
defaults = self.prepareDefaults(dict_of_doom)
|
||||
legacy_settings = self.prepareLocals(parser, section, defaults) #Gets the settings from the legacy profile.
|
||||
|
||||
#Check the target version in the Dictionary of Doom with this application version.
|
||||
if "target_version" not in dict_of_doom:
|
||||
Logger.log("e", "Dictionary of Doom has no target version. Is it the correct JSON file?")
|
||||
return None
|
||||
if Profile.ProfileVersion != dict_of_doom["target_version"]:
|
||||
Logger.log("e", "Dictionary of Doom of legacy profile reader (version %s) is not in sync with the profile version (version %s)!", dict_of_doom["target_version"], str(Profile.ProfileVersion))
|
||||
return None
|
||||
|
||||
if "translation" not in dict_of_doom:
|
||||
Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?")
|
||||
return None
|
||||
for new_setting in dict_of_doom["translation"]: #Evaluate all new settings that would get a value from the translations.
|
||||
old_setting_expression = dict_of_doom["translation"][new_setting]
|
||||
compiled = compile(old_setting_expression, new_setting, "eval")
|
||||
try:
|
||||
new_value = eval(compiled, {"math": math}, legacy_settings) #Pass the legacy settings as local variables to allow access to in the evaluation.
|
||||
value_using_defaults = eval(compiled, {"math": math}, defaults) #Evaluate again using only the default values to try to see if they are default.
|
||||
except Exception as e: #Probably some setting name that was missing or something else that went wrong in the ini file.
|
||||
Logger.log("w", "Setting " + new_setting + " could not be set because the evaluation failed. Something is probably missing from the imported legacy profile.")
|
||||
continue
|
||||
if new_value != value_using_defaults and profile.getSettingValue(new_setting) != new_value: #Not equal to the default in the new Cura OR the default in the legacy Cura.
|
||||
profile.setSettingValue(new_setting, new_value) #Store the setting in the profile!
|
||||
|
||||
if len(profile.getChangedSettings()) == 0:
|
||||
Logger.log("i", "A legacy profile was imported but everything evaluates to the defaults, creating an empty profile.")
|
||||
|
||||
return profile
|
27
plugins/LegacyProfileReader/__init__.py
Normal file
27
plugins/LegacyProfileReader/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from . import LegacyProfileReader
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
"plugin": {
|
||||
"name": catalog.i18nc("@label", "Legacy Cura Profile Reader"),
|
||||
"author": "Ultimaker",
|
||||
"version": "1.0",
|
||||
"description": catalog.i18nc("@info:whatsthis", "Provides support for importing profiles from legacy Cura versions."),
|
||||
"api": 2
|
||||
},
|
||||
"profile_reader": [
|
||||
{
|
||||
"extension": "ini",
|
||||
"description": catalog.i18nc("@item:inlistbox", "Cura 15.04 profiles")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return { "profile_reader": LegacyProfileReader.LegacyProfileReader() }
|
|
@ -13,6 +13,8 @@ Item {
|
|||
property int currentIndex: UM.ActiveTool.properties.SelectedIndex;
|
||||
property string printSequence: UM.ActiveTool.properties.PrintSequence;
|
||||
|
||||
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||
|
||||
width: childrenRect.width;
|
||||
height: childrenRect.height;
|
||||
|
||||
|
@ -104,7 +106,7 @@ Item {
|
|||
height: parent.height/2
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: UM.Theme.colors.setting_control_revert
|
||||
color: control.hovered ? UM.Theme.colors.setting_control_button_hover : UM.Theme.colors.setting_control_button
|
||||
source: UM.Theme.icons.cross1
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +159,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
UM.I18nCatalog { id: catalog; name: "uranium"; }
|
||||
|
||||
UM.Dialog {
|
||||
id: settingPickDialog
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
from . import PerObjectSettingsTool
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
i18n_catalog = i18nCatalog("uranium")
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
|
|
|
@ -8,6 +8,7 @@ from UM.Mesh.MeshWriter import MeshWriter
|
|||
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
||||
from UM.OutputDevice.OutputDevice import OutputDevice
|
||||
from UM.OutputDevice import OutputDeviceError
|
||||
from UM.Preferences import Preferences
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
catalog = i18nCatalog("cura")
|
||||
|
@ -22,15 +23,18 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||
self.setIconName("save_sd")
|
||||
self.setPriority(1)
|
||||
|
||||
Preferences.getInstance().addPreference("removable_drive/file_type", "text/x-gcode") #Add a preference that says in what file type we should store the file.
|
||||
|
||||
self._writing = False
|
||||
|
||||
def requestWrite(self, node, file_name = None):
|
||||
if self._writing:
|
||||
raise OutputDeviceError.DeviceBusyError()
|
||||
|
||||
gcode_writer = Application.getInstance().getMeshFileHandler().getWriterByMimeType("text/x-gcode")
|
||||
file_type = Preferences.getInstance().getValue("removable_drive/file_type")
|
||||
gcode_writer = Application.getInstance().getMeshFileHandler().getWriterByMimeType(file_type)
|
||||
if not gcode_writer:
|
||||
Logger.log("e", "Could not find GCode writer, not writing to removable drive %s", self.getName())
|
||||
Logger.log("e", "Could not find writer for MIME type %s, not writing to removable drive %s", file_type, self.getName())
|
||||
raise OutputDeviceError.WriteRequestFailedError()
|
||||
|
||||
if file_name == None:
|
||||
|
|
|
@ -16,7 +16,8 @@ def getMetaData():
|
|||
"api": 2
|
||||
},
|
||||
"view": {
|
||||
"name": i18n_catalog.i18nc("@item:inmenu", "Solid")
|
||||
"name": i18n_catalog.i18nc("@item:inmenu", "Solid"),
|
||||
"weight": 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
|||
@pyqtSlot()
|
||||
def updateAllFirmware(self):
|
||||
if not self._printer_connections:
|
||||
Message("Cannot update firmware, there were no connected printers found.").show()
|
||||
Message(i18n_catalog.i18nc("@info","Cannot update firmware, there were no connected printers found.")).show()
|
||||
return
|
||||
|
||||
self.spawnFirmwareInterface("")
|
||||
|
|
|
@ -16,7 +16,8 @@ def getMetaData():
|
|||
"api": 2
|
||||
},
|
||||
"view": {
|
||||
"name": catalog.i18nc("@item:inlistbox", "X-Ray")
|
||||
"name": catalog.i18nc("@item:inlistbox", "X-Ray"),
|
||||
"weight": 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1373
resources/i18n/en/cura.po
Normal file
1373
resources/i18n/en/cura.po
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: Uranium json setting files\n"
|
||||
"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
|
||||
"POT-Creation-Date: 2015-09-12 20:10+0000\n"
|
||||
"POT-Creation-Date: 2016-01-18 11:54+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE\n"
|
||||
|
@ -11,6 +11,21 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "machine label"
|
||||
msgid "Machine"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "machine_nozzle_size label"
|
||||
msgid "Nozzle Diameter"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "machine_nozzle_size description"
|
||||
msgid "The inner diameter of the nozzle."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "resolution label"
|
||||
msgid "Quality"
|
||||
|
@ -184,8 +199,8 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "wall_line_count description"
|
||||
msgid ""
|
||||
"Number of shell lines. This these lines are called perimeter lines in other "
|
||||
"tools and impact the strength and structural integrity of your print."
|
||||
"Number of shell lines. These lines are called perimeter lines in other tools "
|
||||
"and impact the strength and structural integrity of your print."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -209,9 +224,9 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "top_bottom_thickness description"
|
||||
msgid ""
|
||||
"This controls the thickness of the bottom and top layers, the amount of "
|
||||
"solid layers put down is calculated by the layer thickness and this value. "
|
||||
"Having this value a multiple of the layer thickness makes sense. And keep it "
|
||||
"This controls the thickness of the bottom and top layers. The number of "
|
||||
"solid layers put down is calculated from the layer thickness and this value. "
|
||||
"Having this value a multiple of the layer thickness makes sense. Keep it "
|
||||
"near your wall thickness to make an evenly strong part."
|
||||
msgstr ""
|
||||
|
||||
|
@ -225,8 +240,8 @@ msgctxt "top_thickness description"
|
|||
msgid ""
|
||||
"This controls the thickness of the top layers. The number of solid layers "
|
||||
"printed is calculated from the layer thickness and this value. Having this "
|
||||
"value be a multiple of the layer thickness makes sense. And keep it nearto "
|
||||
"your wall thickness to make an evenly strong part."
|
||||
"value be a multiple of the layer thickness makes sense. Keep it near your "
|
||||
"wall thickness to make an evenly strong part."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -236,7 +251,7 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "top_layers description"
|
||||
msgid "This controls the amount of top layers."
|
||||
msgid "This controls the number of top layers."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -351,7 +366,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "top_bottom_pattern description"
|
||||
msgid ""
|
||||
"Pattern of the top/bottom solid fill. This normally is done with lines to "
|
||||
"Pattern of the top/bottom solid fill. This is normally done with lines to "
|
||||
"get the best possible finish, but in some cases a concentric fill gives a "
|
||||
"nicer end result."
|
||||
msgstr ""
|
||||
|
@ -373,13 +388,13 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "skin_no_small_gaps_heuristic label"
|
||||
msgid "Ingore small Z gaps"
|
||||
msgid "Ignore small Z gaps"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "skin_no_small_gaps_heuristic description"
|
||||
msgid ""
|
||||
"When the model has small vertical gaps about 5% extra computation time can "
|
||||
"When the model has small vertical gaps, about 5% extra computation time can "
|
||||
"be spent on generating top and bottom skin in these narrow spaces. In such a "
|
||||
"case set this setting to false."
|
||||
msgstr ""
|
||||
|
@ -394,19 +409,19 @@ msgctxt "skin_alternate_rotation description"
|
|||
msgid ""
|
||||
"Alternate between diagonal skin fill and horizontal + vertical skin fill. "
|
||||
"Although the diagonal directions can print quicker, this option can improve "
|
||||
"on the printing quality by reducing the pillowing effect."
|
||||
"the printing quality by reducing the pillowing effect."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "skin_outline_count label"
|
||||
msgid "Skin Perimeter Line Count"
|
||||
msgid "Extra Skin Wall Count"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "skin_outline_count description"
|
||||
msgid ""
|
||||
"Number of lines around skin regions. Using one or two skin perimeter lines "
|
||||
"can greatly improve on roofs which would start in the middle of infill cells."
|
||||
"can greatly improve roofs which would start in the middle of infill cells."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -417,7 +432,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "xy_offset description"
|
||||
msgid ""
|
||||
"Amount of offset applied all polygons in each layer. Positive values can "
|
||||
"Amount of offset applied to all polygons in each layer. Positive values can "
|
||||
"compensate for too big holes; negative values can compensate for too small "
|
||||
"holes."
|
||||
msgstr ""
|
||||
|
@ -430,11 +445,11 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "z_seam_type description"
|
||||
msgid ""
|
||||
"Starting point of each part in a layer. When parts in consecutive layers "
|
||||
"Starting point of each path in a layer. When paths in consecutive layers "
|
||||
"start at the same point a vertical seam may show on the print. When aligning "
|
||||
"these at the back, the seam is easiest to remove. When placed randomly the "
|
||||
"inaccuracies at the part start will be less noticable. When taking the "
|
||||
"shortest path the print will be more quick."
|
||||
"inaccuracies at the paths' start will be less noticeable. When taking the "
|
||||
"shortest path the print will be quicker."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -466,8 +481,8 @@ msgstr ""
|
|||
msgctxt "infill_sparse_density description"
|
||||
msgid ""
|
||||
"This controls how densely filled the insides of your print will be. For a "
|
||||
"solid part use 100%, for an hollow part use 0%. A value around 20% is "
|
||||
"usually enough. This won't affect the outside of the print and only adjusts "
|
||||
"solid part use 100%, for a hollow part use 0%. A value around 20% is usually "
|
||||
"enough. This setting won't affect the outside of the print and only adjusts "
|
||||
"how strong the part becomes."
|
||||
msgstr ""
|
||||
|
||||
|
@ -489,7 +504,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "infill_pattern description"
|
||||
msgid ""
|
||||
"Cura defaults to switching between grid and line infill. But with this "
|
||||
"Cura defaults to switching between grid and line infill, but with this "
|
||||
"setting visible you can control this yourself. The line infill swaps "
|
||||
"direction on alternate layers of infill, while the grid prints the full "
|
||||
"cross-hatching on each layer of infill."
|
||||
|
@ -505,6 +520,11 @@ msgctxt "infill_pattern option lines"
|
|||
msgid "Lines"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "infill_pattern option triangles"
|
||||
msgid "Triangles"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "infill_pattern option concentric"
|
||||
msgid "Concentric"
|
||||
|
@ -536,7 +556,7 @@ msgstr ""
|
|||
msgctxt "infill_wipe_dist description"
|
||||
msgid ""
|
||||
"Distance of a travel move inserted after every infill line, to make the "
|
||||
"infill stick to the walls better. This option is imilar to infill overlap, "
|
||||
"infill stick to the walls better. This option is similar to infill overlap, "
|
||||
"but without extrusion and only on one end of the infill line."
|
||||
msgstr ""
|
||||
|
||||
|
@ -553,16 +573,6 @@ msgid ""
|
|||
"save printing time."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "infill_sparse_combine label"
|
||||
msgid "Infill Layers"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "infill_sparse_combine description"
|
||||
msgid "Amount of layers that are combined together to form sparse infill."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "infill_before_walls label"
|
||||
msgid "Infill Before Walls"
|
||||
|
@ -582,6 +592,18 @@ msgctxt "material label"
|
|||
msgid "Material"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_flow_dependent_temperature label"
|
||||
msgid "Auto Temperature"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_flow_dependent_temperature description"
|
||||
msgid ""
|
||||
"Change the temperature for each layer automatically with the average flow "
|
||||
"speed of that layer."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_print_temperature label"
|
||||
msgid "Printing Temperature"
|
||||
|
@ -595,6 +617,42 @@ msgid ""
|
|||
"For ABS a value of 230C or higher is required."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_flow_temp_graph label"
|
||||
msgid "Flow Temperature Graph"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_flow_temp_graph description"
|
||||
msgid ""
|
||||
"Data linking material flow (in mm3 per second) to temperature (degrees "
|
||||
"Celsius)."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_standby_temperature label"
|
||||
msgid "Standby Temperature"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_standby_temperature description"
|
||||
msgid ""
|
||||
"The temperature of the nozzle when another nozzle is currently used for "
|
||||
"printing."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_extrusion_cool_down_speed label"
|
||||
msgid "Extrusion Cool Down Speed Modifier"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_extrusion_cool_down_speed description"
|
||||
msgid ""
|
||||
"The extra speed by which the nozzle cools while extruding. The same value is "
|
||||
"used to signify the heat up speed lost when heating up while extruding."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "material_bed_temperature label"
|
||||
msgid "Bed Temperature"
|
||||
|
@ -617,7 +675,7 @@ msgctxt "material_diameter description"
|
|||
msgid ""
|
||||
"The diameter of your filament needs to be measured as accurately as "
|
||||
"possible.\n"
|
||||
"If you cannot measure this value you will have to calibrate it, a higher "
|
||||
"If you cannot measure this value you will have to calibrate it; a higher "
|
||||
"number means less extrusion, a smaller number generates more extrusion."
|
||||
msgstr ""
|
||||
|
||||
|
@ -654,7 +712,7 @@ msgstr ""
|
|||
msgctxt "retraction_amount description"
|
||||
msgid ""
|
||||
"The amount of retraction: Set at 0 for no retraction at all. A value of "
|
||||
"4.5mm seems to generate good results for 3mm filament in Bowden-tube fed "
|
||||
"4.5mm seems to generate good results for 3mm filament in bowden tube fed "
|
||||
"printers."
|
||||
msgstr ""
|
||||
|
||||
|
@ -700,8 +758,8 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "retraction_extra_prime_amount description"
|
||||
msgid ""
|
||||
"The amount of material extruded after unretracting. During a retracted "
|
||||
"travel material might get lost and so we need to compensate for this."
|
||||
"The amount of material extruded after a retraction. During a travel move, "
|
||||
"some material might get lost and so we need to compensate for this."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -713,33 +771,33 @@ msgstr ""
|
|||
msgctxt "retraction_min_travel description"
|
||||
msgid ""
|
||||
"The minimum distance of travel needed for a retraction to happen at all. "
|
||||
"This helps ensure you do not get a lot of retractions in a small area."
|
||||
"This helps to get fewer retractions in a small area."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "retraction_count_max label"
|
||||
msgid "Maximal Retraction Count"
|
||||
msgid "Maximum Retraction Count"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "retraction_count_max description"
|
||||
msgid ""
|
||||
"This settings limits the number of retractions occuring within the Minimal "
|
||||
"This setting limits the number of retractions occurring within the Minimum "
|
||||
"Extrusion Distance Window. Further retractions within this window will be "
|
||||
"ignored. This avoids retracting repeatedly on the same piece of filament as "
|
||||
"ignored. This avoids retracting repeatedly on the same piece of filament, as "
|
||||
"that can flatten the filament and cause grinding issues."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "retraction_extrusion_window label"
|
||||
msgid "Minimal Extrusion Distance Window"
|
||||
msgid "Minimum Extrusion Distance Window"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "retraction_extrusion_window description"
|
||||
msgid ""
|
||||
"The window in which the Maximal Retraction Count is enforced. This window "
|
||||
"should be approximately the size of the Retraction distance, so that "
|
||||
"The window in which the Maximum Retraction Count is enforced. This value "
|
||||
"should be approximately the same as the Retraction distance, so that "
|
||||
"effectively the number of times a retraction passes the same patch of "
|
||||
"material is limited."
|
||||
msgstr ""
|
||||
|
@ -753,7 +811,7 @@ msgstr ""
|
|||
msgctxt "retraction_hop description"
|
||||
msgid ""
|
||||
"Whenever a retraction is done, the head is lifted by this amount to travel "
|
||||
"over the print. A value of 0.075 works well. This feature has a lot of "
|
||||
"over the print. A value of 0.075 works well. This feature has a large "
|
||||
"positive effect on delta towers."
|
||||
msgstr ""
|
||||
|
||||
|
@ -796,7 +854,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "speed_wall description"
|
||||
msgid ""
|
||||
"The speed at which shell is printed. Printing the outer shell at a lower "
|
||||
"The speed at which the shell is printed. Printing the outer shell at a lower "
|
||||
"speed improves the final skin quality."
|
||||
msgstr ""
|
||||
|
||||
|
@ -808,7 +866,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "speed_wall_0 description"
|
||||
msgid ""
|
||||
"The speed at which outer shell is printed. Printing the outer shell at a "
|
||||
"The speed at which the outer shell is printed. Printing the outer shell at a "
|
||||
"lower speed improves the final skin quality. However, having a large "
|
||||
"difference between the inner shell speed and the outer shell speed will "
|
||||
"effect quality in a negative way."
|
||||
|
@ -822,8 +880,8 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "speed_wall_x description"
|
||||
msgid ""
|
||||
"The speed at which all inner shells are printed. Printing the inner shell "
|
||||
"fasster than the outer shell will reduce printing time. It is good to set "
|
||||
"The speed at which all inner shells are printed. Printing the inner shell "
|
||||
"faster than the outer shell will reduce printing time. It works well to set "
|
||||
"this in between the outer shell speed and the infill speed."
|
||||
msgstr ""
|
||||
|
||||
|
@ -849,8 +907,9 @@ msgstr ""
|
|||
msgctxt "speed_support description"
|
||||
msgid ""
|
||||
"The speed at which exterior support is printed. Printing exterior supports "
|
||||
"at higher speeds can greatly improve printing time. And the surface quality "
|
||||
"of exterior support is usually not important, so higher speeds can be used."
|
||||
"at higher speeds can greatly improve printing time. The surface quality of "
|
||||
"exterior support is usually not important anyway, so higher speeds can be "
|
||||
"used."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -862,7 +921,7 @@ msgstr ""
|
|||
msgctxt "speed_support_lines description"
|
||||
msgid ""
|
||||
"The speed at which the walls of exterior support are printed. Printing the "
|
||||
"walls at higher speeds can improve on the overall duration. "
|
||||
"walls at higher speeds can improve the overall duration."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -874,7 +933,7 @@ msgstr ""
|
|||
msgctxt "speed_support_roof description"
|
||||
msgid ""
|
||||
"The speed at which the roofs of exterior support are printed. Printing the "
|
||||
"support roof at lower speeds can improve on overhang quality. "
|
||||
"support roof at lower speeds can improve overhang quality."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -886,7 +945,7 @@ msgstr ""
|
|||
msgctxt "speed_travel description"
|
||||
msgid ""
|
||||
"The speed at which travel moves are done. A well-built Ultimaker can reach "
|
||||
"speeds of 250mm/s. But some machines might have misaligned layers then."
|
||||
"speeds of 250mm/s, but some machines might have misaligned layers then."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -898,7 +957,7 @@ msgstr ""
|
|||
msgctxt "speed_layer_0 description"
|
||||
msgid ""
|
||||
"The print speed for the bottom layer: You want to print the first layer "
|
||||
"slower so it sticks to the printer bed better."
|
||||
"slower so it sticks better to the printer bed."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -910,19 +969,19 @@ msgstr ""
|
|||
msgctxt "skirt_speed description"
|
||||
msgid ""
|
||||
"The speed at which the skirt and brim are printed. Normally this is done at "
|
||||
"the initial layer speed. But sometimes you want to print the skirt at a "
|
||||
"different speed."
|
||||
"the initial layer speed, but sometimes you might want to print the skirt at "
|
||||
"a different speed."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "speed_slowdown_layers label"
|
||||
msgid "Amount of Slower Layers"
|
||||
msgid "Number of Slower Layers"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "speed_slowdown_layers description"
|
||||
msgid ""
|
||||
"The first few layers are printed slower then the rest of the object, this to "
|
||||
"The first few layers are printed slower than the rest of the object, this to "
|
||||
"get better adhesion to the printer bed and improve the overall success rate "
|
||||
"of prints. The speed is gradually increased over these layers. 4 layers of "
|
||||
"speed-up is generally right for most materials and printers."
|
||||
|
@ -942,8 +1001,8 @@ msgstr ""
|
|||
msgctxt "retraction_combing description"
|
||||
msgid ""
|
||||
"Combing keeps the head within the interior of the print whenever possible "
|
||||
"when traveling from one part of the print to another, and does not use "
|
||||
"retraction. If combing is disabled the printer head moves straight from the "
|
||||
"when traveling from one part of the print to another and does not use "
|
||||
"retraction. If combing is disabled, the print head moves straight from the "
|
||||
"start point to the end point and it will always retract."
|
||||
msgstr ""
|
||||
|
||||
|
@ -992,26 +1051,6 @@ msgid ""
|
|||
"nozzle diameter cubed."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_volume_retract label"
|
||||
msgid "Retract-Coasting Volume"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_volume_retract description"
|
||||
msgid "The volume otherwise oozed in a travel move with retraction."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_volume_move label"
|
||||
msgid "Move-Coasting Volume"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_volume_move description"
|
||||
msgid "The volume otherwise oozed in a travel move without retraction."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_min_volume label"
|
||||
msgid "Minimal Volume Before Coasting"
|
||||
|
@ -1022,31 +1061,8 @@ msgctxt "coasting_min_volume description"
|
|||
msgid ""
|
||||
"The least volume an extrusion path should have to coast the full amount. For "
|
||||
"smaller extrusion paths, less pressure has been built up in the bowden tube "
|
||||
"and so the coasted volume is scaled linearly."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_min_volume_retract label"
|
||||
msgid "Min Volume Retract-Coasting"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_min_volume_retract description"
|
||||
msgid ""
|
||||
"The minimal volume an extrusion path must have in order to coast the full "
|
||||
"amount before doing a retraction."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_min_volume_move label"
|
||||
msgid "Min Volume Move-Coasting"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_min_volume_move description"
|
||||
msgid ""
|
||||
"The minimal volume an extrusion path must have in order to coast the full "
|
||||
"amount before doing a travel move without retraction."
|
||||
"and so the coasted volume is scaled linearly. This value should always be "
|
||||
"larger than the Coasting Volume."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1059,31 +1075,7 @@ msgctxt "coasting_speed description"
|
|||
msgid ""
|
||||
"The speed by which to move during coasting, relative to the speed of the "
|
||||
"extrusion path. A value slightly under 100% is advised, since during the "
|
||||
"coasting move, the pressure in the bowden tube drops."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_speed_retract label"
|
||||
msgid "Retract-Coasting Speed"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_speed_retract description"
|
||||
msgid ""
|
||||
"The speed by which to move during coasting before a retraction, relative to "
|
||||
"the speed of the extrusion path."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_speed_move label"
|
||||
msgid "Move-Coasting Speed"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "coasting_speed_move description"
|
||||
msgid ""
|
||||
"The speed by which to move during coasting before a travel move without "
|
||||
"retraction, relative to the speed of the extrusion path."
|
||||
"coasting move the pressure in the bowden tube drops."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1166,7 +1158,7 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "cool_min_layer_time label"
|
||||
msgid "Minimal Layer Time"
|
||||
msgid "Minimum Layer Time"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1180,16 +1172,16 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "cool_min_layer_time_fan_speed_max label"
|
||||
msgid "Minimal Layer Time Full Fan Speed"
|
||||
msgid "Minimum Layer Time Full Fan Speed"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "cool_min_layer_time_fan_speed_max description"
|
||||
msgid ""
|
||||
"The minimum time spent in a layer which will cause the fan to be at maximum "
|
||||
"speed. The fan speed increases linearly from minimal fan speed for layers "
|
||||
"taking minimal layer time to maximum fan speed for layers taking the time "
|
||||
"specified here."
|
||||
"speed. The fan speed increases linearly from minimum fan speed for layers "
|
||||
"taking the minimum layer time to maximum fan speed for layers taking the "
|
||||
"time specified here."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1243,7 +1235,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "support_type description"
|
||||
msgid ""
|
||||
"Where to place support structures. The placement can be restricted such that "
|
||||
"Where to place support structures. The placement can be restricted so that "
|
||||
"the support structures won't rest on the model, which could otherwise cause "
|
||||
"scarring."
|
||||
msgstr ""
|
||||
|
@ -1279,7 +1271,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "support_xy_distance description"
|
||||
msgid ""
|
||||
"Distance of the support structure from the print, in the X/Y directions. "
|
||||
"Distance of the support structure from the print in the X/Y directions. "
|
||||
"0.7mm typically gives a nice distance from the print so the support does not "
|
||||
"stick to the surface."
|
||||
msgstr ""
|
||||
|
@ -1352,7 +1344,7 @@ msgstr ""
|
|||
msgctxt "support_conical_min_width description"
|
||||
msgid ""
|
||||
"Minimal width to which conical support reduces the support areas. Small "
|
||||
"widths can cause the base of the support to not act well as fundament for "
|
||||
"widths can cause the base of the support to not act well as foundation for "
|
||||
"support above."
|
||||
msgstr ""
|
||||
|
||||
|
@ -1377,8 +1369,8 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "support_join_distance description"
|
||||
msgid ""
|
||||
"The maximum distance between support blocks, in the X/Y directions, such "
|
||||
"that the blocks will merge into a single block."
|
||||
"The maximum distance between support blocks in the X/Y directions, so that "
|
||||
"the blocks will merge into a single block."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1401,7 +1393,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "support_area_smoothing description"
|
||||
msgid ""
|
||||
"Maximal distance in the X/Y directions of a line segment which is to be "
|
||||
"Maximum distance in the X/Y directions of a line segment which is to be "
|
||||
"smoothed out. Ragged lines are introduced by the join distance and support "
|
||||
"bridge, which cause the machine to resonate. Smoothing the support areas "
|
||||
"won't cause them to break with the constraints, except it might change the "
|
||||
|
@ -1426,7 +1418,7 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "support_roof_height description"
|
||||
msgid "The height of the support roofs. "
|
||||
msgid "The height of the support roofs."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1438,7 +1430,8 @@ msgstr ""
|
|||
msgctxt "support_roof_density description"
|
||||
msgid ""
|
||||
"This controls how densely filled the roofs of the support will be. A higher "
|
||||
"percentage results in better overhangs, which are more difficult to remove."
|
||||
"percentage results in better overhangs, but makes the support more difficult "
|
||||
"to remove."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1488,7 +1481,7 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "support_use_towers label"
|
||||
msgid "Use towers."
|
||||
msgid "Use towers"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1501,14 +1494,14 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "support_minimal_diameter label"
|
||||
msgid "Minimal Diameter"
|
||||
msgid "Minimum Diameter"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "support_minimal_diameter description"
|
||||
msgid ""
|
||||
"Maximal diameter in the X/Y directions of a small area which is to be "
|
||||
"supported by a specialized support tower. "
|
||||
"Minimum diameter in the X/Y directions of a small area which is to be "
|
||||
"supported by a specialized support tower."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1518,7 +1511,7 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "support_tower_diameter description"
|
||||
msgid "The diameter of a special tower. "
|
||||
msgid "The diameter of a special tower."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1529,7 +1522,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "support_tower_roof_angle description"
|
||||
msgid ""
|
||||
"The angle of the rooftop of a tower. Larger angles mean more pointy towers. "
|
||||
"The angle of the rooftop of a tower. Larger angles mean more pointy towers."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1540,11 +1533,11 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "support_pattern description"
|
||||
msgid ""
|
||||
"Cura supports 3 distinct types of support structure. First is a grid based "
|
||||
"support structure which is quite solid and can be removed as 1 piece. The "
|
||||
"second is a line based support structure which has to be peeled off line by "
|
||||
"line. The third is a structure in between the other two; it consists of "
|
||||
"lines which are connected in an accordeon fashion."
|
||||
"Cura can generate 3 distinct types of support structure. First is a grid "
|
||||
"based support structure which is quite solid and can be removed in one "
|
||||
"piece. The second is a line based support structure which has to be peeled "
|
||||
"off line by line. The third is a structure in between the other two; it "
|
||||
"consists of lines which are connected in an accordion fashion."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1592,7 +1585,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "support_infill_rate description"
|
||||
msgid ""
|
||||
"The amount of infill structure in the support, less infill gives weaker "
|
||||
"The amount of infill structure in the support; less infill gives weaker "
|
||||
"support which is easier to remove."
|
||||
msgstr ""
|
||||
|
||||
|
@ -1619,11 +1612,14 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "adhesion_type description"
|
||||
msgid ""
|
||||
"Different options that help in preventing corners from lifting due to "
|
||||
"warping. Brim adds a single-layer-thick flat area around your object which "
|
||||
"is easy to cut off afterwards, and it is the recommended option. Raft adds a "
|
||||
"thick grid below the object and a thin interface between this and your "
|
||||
"object. (Note that enabling the brim or raft disables the skirt.)"
|
||||
"Different options that help to improve priming your extrusion.\n"
|
||||
"Brim and Raft help in preventing corners from lifting due to warping. Brim "
|
||||
"adds a single-layer-thick flat area around your object which is easy to cut "
|
||||
"off afterwards, and it is the recommended option.\n"
|
||||
"Raft adds a thick grid below the object and a thin interface between this "
|
||||
"and your object.\n"
|
||||
"The skirt is a line drawn around the first layer of the print, this helps to "
|
||||
"prime your extrusion and to see if the object fits on your platform."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1649,10 +1645,8 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "skirt_line_count description"
|
||||
msgid ""
|
||||
"The skirt is a line drawn around the first layer of the. This helps to prime "
|
||||
"your extruder, and to see if the object fits on your platform. Setting this "
|
||||
"to 0 will disable the skirt. Multiple skirt lines can help to prime your "
|
||||
"extruder better for small objects."
|
||||
"Multiple skirt lines help to prime your extrusion better for small objects. "
|
||||
"Setting this to 0 will disable the skirt."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1681,6 +1675,19 @@ msgid ""
|
|||
"count is set to 0 this is ignored."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "brim_width label"
|
||||
msgid "Brim Width"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "brim_width description"
|
||||
msgid ""
|
||||
"The distance from the model to the end of the brim. A larger brim sticks "
|
||||
"better to the build platform, but also makes your effective print area "
|
||||
"smaller."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "brim_line_count label"
|
||||
msgid "Brim Line Count"
|
||||
|
@ -1689,8 +1696,9 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "brim_line_count description"
|
||||
msgid ""
|
||||
"The amount of lines used for a brim: More lines means a larger brim which "
|
||||
"sticks better, but this also makes your effective print area smaller."
|
||||
"The number of lines used for a brim. More lines means a larger brim which "
|
||||
"sticks better to the build plate, but this also makes your effective print "
|
||||
"area smaller."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1721,84 +1729,84 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_layers label"
|
||||
msgid "Raft Surface Layers"
|
||||
msgid "Raft Top Layers"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_layers description"
|
||||
msgid ""
|
||||
"The number of surface layers on top of the 2nd raft layer. These are fully "
|
||||
"filled layers that the object sits on. 2 layers usually works fine."
|
||||
"The number of top layers on top of the 2nd raft layer. These are fully "
|
||||
"filled layers that the object sits on. 2 layers result in a smoother top "
|
||||
"surface than 1."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_thickness label"
|
||||
msgid "Raft Surface Thickness"
|
||||
msgid "Raft Top Layer Thickness"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_thickness description"
|
||||
msgid "Layer thickness of the surface raft layers."
|
||||
msgid "Layer thickness of the top raft layers."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_line_width label"
|
||||
msgid "Raft Surface Line Width"
|
||||
msgid "Raft Top Line Width"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_line_width description"
|
||||
msgid ""
|
||||
"Width of the lines in the surface raft layers. These can be thin lines so "
|
||||
"that the top of the raft becomes smooth."
|
||||
"Width of the lines in the top surface of the raft. These can be thin lines "
|
||||
"so that the top of the raft becomes smooth."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_line_spacing label"
|
||||
msgid "Raft Surface Spacing"
|
||||
msgid "Raft Top Spacing"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_line_spacing description"
|
||||
msgid ""
|
||||
"The distance between the raft lines for the surface raft layers. The spacing "
|
||||
"of the interface should be equal to the line width, so that the surface is "
|
||||
"solid."
|
||||
"The distance between the raft lines for the top raft layers. The spacing "
|
||||
"should be equal to the line width, so that the surface is solid."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_interface_thickness label"
|
||||
msgid "Raft Interface Thickness"
|
||||
msgid "Raft Middle Thickness"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_interface_thickness description"
|
||||
msgid "Layer thickness of the interface raft layer."
|
||||
msgid "Layer thickness of the middle raft layer."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_interface_line_width label"
|
||||
msgid "Raft Interface Line Width"
|
||||
msgid "Raft Middle Line Width"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_interface_line_width description"
|
||||
msgid ""
|
||||
"Width of the lines in the interface raft layer. Making the second layer "
|
||||
"extrude more causes the lines to stick to the bed."
|
||||
"Width of the lines in the middle raft layer. Making the second layer extrude "
|
||||
"more causes the lines to stick to the bed."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_interface_line_spacing label"
|
||||
msgid "Raft Interface Spacing"
|
||||
msgid "Raft Middle Spacing"
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
msgctxt "raft_interface_line_spacing description"
|
||||
msgid ""
|
||||
"The distance between the raft lines for the interface raft layer. The "
|
||||
"spacing of the interface should be quite wide, while being dense enough to "
|
||||
"support the surface raft layers."
|
||||
"The distance between the raft lines for the middle raft layer. The spacing "
|
||||
"of the middle should be quite wide, while being dense enough to support the "
|
||||
"top raft layers."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1855,7 +1863,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "raft_surface_speed description"
|
||||
msgid ""
|
||||
"The speed at which the surface raft layers are printed. This should be "
|
||||
"The speed at which the surface raft layers are printed. These should be "
|
||||
"printed a bit slower, so that the nozzle can slowly smooth out adjacent "
|
||||
"surface lines."
|
||||
msgstr ""
|
||||
|
@ -1869,7 +1877,7 @@ msgstr ""
|
|||
msgctxt "raft_interface_speed description"
|
||||
msgid ""
|
||||
"The speed at which the interface raft layer is printed. This should be "
|
||||
"printed quite slowly, as the amount of material coming out of the nozzle is "
|
||||
"printed quite slowly, as the volume of material coming out of the nozzle is "
|
||||
"quite high."
|
||||
msgstr ""
|
||||
|
||||
|
@ -1882,7 +1890,7 @@ msgstr ""
|
|||
msgctxt "raft_base_speed description"
|
||||
msgid ""
|
||||
"The speed at which the base raft layer is printed. This should be printed "
|
||||
"quite slowly, as the amount of material coming out of the nozzle is quite "
|
||||
"quite slowly, as the volume of material coming out of the nozzle is quite "
|
||||
"high."
|
||||
msgstr ""
|
||||
|
||||
|
@ -1956,7 +1964,7 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "draft_shield_height_limitation description"
|
||||
msgid "Whether to limit the height of the draft shield"
|
||||
msgid "Whether or not to limit the height of the draft shield."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -1995,7 +2003,7 @@ msgstr ""
|
|||
msgctxt "meshfix_union_all description"
|
||||
msgid ""
|
||||
"Ignore the internal geometry arising from overlapping volumes and print the "
|
||||
"volumes as one. This may cause internal cavaties to disappear."
|
||||
"volumes as one. This may cause internal cavities to disappear."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -2034,8 +2042,8 @@ msgctxt "meshfix_keep_open_polygons description"
|
|||
msgid ""
|
||||
"Normally Cura tries to stitch up small holes in the mesh and remove parts of "
|
||||
"a layer with big holes. Enabling this option keeps those parts which cannot "
|
||||
"be stitched. This option should be used as a last resort option when all "
|
||||
"else doesn produce proper GCode."
|
||||
"be stitched. This option should be used as a last resort option when "
|
||||
"everything else fails to produce proper GCode."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -2053,9 +2061,9 @@ msgctxt "print_sequence description"
|
|||
msgid ""
|
||||
"Whether to print all objects one layer at a time or to wait for one object "
|
||||
"to finish, before moving on to the next. One at a time mode is only possible "
|
||||
"if all models are separated such that the whole print head can move between "
|
||||
"and all models are lower than the distance between the nozzle and the X/Y "
|
||||
"axles."
|
||||
"if all models are separated in such a way that the whole print head can move "
|
||||
"in between and all models are lower than the distance between the nozzle and "
|
||||
"the X/Y axes."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -2108,7 +2116,7 @@ msgid ""
|
|||
"Spiralize smooths out the Z move of the outer edge. This will create a "
|
||||
"steady Z increase over the whole print. This feature turns a solid object "
|
||||
"into a single walled print with a solid bottom. This feature used to be "
|
||||
"called ‘Joris’ in older versions."
|
||||
"called Joris in older versions."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -2311,9 +2319,7 @@ msgstr ""
|
|||
|
||||
#: fdmprinter.json
|
||||
msgctxt "wireframe_bottom_delay description"
|
||||
msgid ""
|
||||
"Delay time after a downward move. Only applies to Wire Printing. Only "
|
||||
"applies to Wire Printing."
|
||||
msgid "Delay time after a downward move. Only applies to Wire Printing."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -2326,7 +2332,7 @@ msgctxt "wireframe_flat_delay description"
|
|||
msgid ""
|
||||
"Delay time between two horizontal segments. Introducing such a delay can "
|
||||
"cause better adhesion to previous layers at the connection points, while too "
|
||||
"large delay times cause sagging. Only applies to Wire Printing."
|
||||
"long delays cause sagging. Only applies to Wire Printing."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -2391,10 +2397,10 @@ msgid ""
|
|||
"Strategy for making sure two consecutive layers connect at each connection "
|
||||
"point. Retraction lets the upward lines harden in the right position, but "
|
||||
"may cause filament grinding. A knot can be made at the end of an upward line "
|
||||
"to heighten the chance of connecting to it and to let the line cool; however "
|
||||
"it may require slow printing speeds. Another strategy is to compensate for "
|
||||
"the sagging of the top of an upward line; however, the lines won't always "
|
||||
"fall down as predicted."
|
||||
"to heighten the chance of connecting to it and to let the line cool; "
|
||||
"however, it may require slow printing speeds. Another strategy is to "
|
||||
"compensate for the sagging of the top of an upward line; however, the lines "
|
||||
"won't always fall down as predicted."
|
||||
msgstr ""
|
||||
|
||||
#: fdmprinter.json
|
||||
|
@ -2459,7 +2465,7 @@ msgstr ""
|
|||
#: fdmprinter.json
|
||||
msgctxt "wireframe_roof_outer_delay description"
|
||||
msgid ""
|
||||
"Time spent at the outer perimeters of hole which is to become a roof. Larger "
|
||||
"Time spent at the outer perimeters of hole which is to become a roof. Longer "
|
||||
"times can ensure a better connection. Only applies to Wire Printing."
|
||||
msgstr ""
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
BIN
resources/images/ultimaker2plus_backplate.png
Normal file
BIN
resources/images/ultimaker2plus_backplate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -33,7 +33,7 @@
|
|||
"default": "RepRap"
|
||||
},
|
||||
"machine_platform_offset": {
|
||||
"default": [-6, 1320, 0]
|
||||
"default": [6, 1320, 0]
|
||||
}
|
||||
"material_print_temperature": { "default": 210.0, "visible": true },
|
||||
"material_bed_temperature": { "default": 0 },
|
||||
|
|
|
@ -153,6 +153,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 200,
|
||||
"min_value_warning": "-1000",
|
||||
"max_value_warning": "1000",
|
||||
"enabled": "prime_tower_enable"
|
||||
},
|
||||
"prime_tower_position_y": {
|
||||
|
@ -162,6 +164,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 200,
|
||||
"min_value_warning": "-1000",
|
||||
"max_value_warning": "1000",
|
||||
"enabled": "prime_tower_enable"
|
||||
},
|
||||
"prime_tower_flow": {
|
||||
|
@ -231,6 +235,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 16,
|
||||
"min_value_warning": "0",
|
||||
"max_value_warning": "100",
|
||||
"visible": false,
|
||||
"inherit_function": "machine_heat_zone_length",
|
||||
"enabled": "retraction_enable"
|
||||
|
@ -241,6 +247,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 20,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "300",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "retraction_enable",
|
||||
|
@ -251,6 +259,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 20,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "300",
|
||||
"visible": false,
|
||||
"enabled": "retraction_enable"
|
||||
},
|
||||
|
@ -260,6 +270,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 20,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "300",
|
||||
"visible": false,
|
||||
"enabled": "retraction_enable"
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
"type": "float",
|
||||
"default": 0.4,
|
||||
"min_value": "0.001",
|
||||
"max_value_warning": "10",
|
||||
"visible": false
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +287,8 @@
|
|||
"description": "Width of a single support roof line, used to fill the top of the support.",
|
||||
"unit": "mm",
|
||||
"default": 0.4,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "machine_nozzle_size * 2",
|
||||
"type": "float",
|
||||
"visible": false,
|
||||
"enabled": "support_roof_enable"
|
||||
|
@ -323,8 +326,8 @@
|
|||
"wall_line_count": {
|
||||
"label": "Wall Line Count",
|
||||
"description": "Number of shell lines. These lines are called perimeter lines in other tools and impact the strength and structural integrity of your print.",
|
||||
"min_value": "0",
|
||||
"default": 2,
|
||||
"min_value": "0",
|
||||
"type": "int",
|
||||
"visible": false,
|
||||
"inherit_function": "max(1, round((wall_thickness - wall_line_width_0) / wall_line_width_x) + 1)"
|
||||
|
@ -354,16 +357,18 @@
|
|||
"label": "Top Thickness",
|
||||
"description": "This controls the thickness of the top layers. The number of solid layers printed is calculated from the layer thickness and this value. Having this value be a multiple of the layer thickness makes sense. Keep it near your wall thickness to make an evenly strong part.",
|
||||
"unit": "mm",
|
||||
"min_value": "0",
|
||||
"default": 0.8,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"type": "float",
|
||||
"visible": false,
|
||||
"children": {
|
||||
"top_layers": {
|
||||
"label": "Top Layers",
|
||||
"description": "This controls the number of top layers.",
|
||||
"min_value": "0",
|
||||
"default": 8,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"type": "int",
|
||||
"visible": false,
|
||||
"inherit_function": "0 if infill_sparse_density == 100 else math.ceil(parent_value / layer_height)"
|
||||
|
@ -374,8 +379,8 @@
|
|||
"label": "Bottom Thickness",
|
||||
"description": "This controls the thickness of the bottom layers. The number of solid layers printed is calculated from the layer thickness and this value. Having this value be a multiple of the layer thickness makes sense. And keep it near to your wall thickness to make an evenly strong part.",
|
||||
"unit": "mm",
|
||||
"min_value": "0",
|
||||
"default": 0.6,
|
||||
"min_value": "0",
|
||||
"type": "float",
|
||||
"visible": false,
|
||||
"children": {
|
||||
|
@ -469,6 +474,8 @@
|
|||
"label": "Extra Skin Wall Count",
|
||||
"description": "Number of lines around skin regions. Using one or two skin perimeter lines can greatly improve roofs which would start in the middle of infill cells.",
|
||||
"default": 0,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10",
|
||||
"type": "int",
|
||||
"visible": false
|
||||
},
|
||||
|
@ -477,6 +484,8 @@
|
|||
"description": "Amount of offset applied to all polygons in each layer. Positive values can compensate for too big holes; negative values can compensate for too small holes.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"min_value_warning": "-10",
|
||||
"max_value_warning": "10",
|
||||
"default": 0,
|
||||
"visible": false
|
||||
},
|
||||
|
@ -506,7 +515,7 @@
|
|||
"type": "float",
|
||||
"default": 20,
|
||||
"min_value": "0",
|
||||
"max_value": "100",
|
||||
"max_value_warning": "100",
|
||||
"children": {
|
||||
"infill_line_distance": {
|
||||
"label": "Line distance",
|
||||
|
@ -514,6 +523,7 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 2,
|
||||
"min_value": "0",
|
||||
"visible": false,
|
||||
"inherit_function": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density"
|
||||
}
|
||||
|
@ -541,7 +551,7 @@
|
|||
"type": "float",
|
||||
"default": 10,
|
||||
"min_value": "0",
|
||||
"max_value": "100",
|
||||
"max_value_warning": "100",
|
||||
"inherit_function": "10 if infill_sparse_density < 95 else 0",
|
||||
"visible": false
|
||||
},
|
||||
|
@ -551,6 +561,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.04,
|
||||
"min_value_warning": "0",
|
||||
"max_value_warning": "machine_nozzle_size",
|
||||
"visible": false
|
||||
},
|
||||
"infill_sparse_thickness": {
|
||||
|
@ -559,6 +571,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.1,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "0.32",
|
||||
"visible": false,
|
||||
"inherit_function": "layer_height"
|
||||
},
|
||||
|
@ -595,7 +609,7 @@
|
|||
},
|
||||
"material_flow_temp_graph": {
|
||||
"label": "Flow Temperature Graph",
|
||||
"description": "Data linking material flow (in mm³/s) to temperature (°C).",
|
||||
"description": "Data linking material flow (in mm3 per second) to temperature (degrees Celsius).",
|
||||
"unit": "",
|
||||
"type": "string",
|
||||
"default": "[[3.5,200],[7.0,240]]",
|
||||
|
@ -635,6 +649,7 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 2.85,
|
||||
"min_value": "0.0001",
|
||||
"min_value_warning": "0.4",
|
||||
"max_value_warning": "3.5"
|
||||
},
|
||||
|
@ -661,6 +676,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 4.5,
|
||||
"min_value_warning": "-0.0001",
|
||||
"max_value_warning": "10.0",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "retraction_enable"
|
||||
|
@ -671,6 +688,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 25,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "retraction_enable",
|
||||
|
@ -681,6 +700,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 25,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"visible": false,
|
||||
"enabled": "retraction_enable"
|
||||
},
|
||||
|
@ -690,6 +711,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 25,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"visible": false,
|
||||
"enabled": "retraction_enable"
|
||||
}
|
||||
|
@ -701,6 +724,8 @@
|
|||
"unit": "mm³",
|
||||
"type": "float",
|
||||
"default": 0,
|
||||
"min_value_warning": "-0.0001",
|
||||
"max_value_warning": "5.0",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "retraction_enable"
|
||||
|
@ -711,6 +736,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1.5,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "retraction_enable"
|
||||
|
@ -719,6 +746,8 @@
|
|||
"label": "Maximum Retraction Count",
|
||||
"description": "This setting limits the number of retractions occurring within the Minimum Extrusion Distance Window. Further retractions within this window will be ignored. This avoids retracting repeatedly on the same piece of filament, as that can flatten the filament and cause grinding issues.",
|
||||
"default": 8,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "20",
|
||||
"type": "int",
|
||||
"min_value": "1",
|
||||
"visible": false,
|
||||
|
@ -732,6 +761,7 @@
|
|||
"type": "float",
|
||||
"default": 4.5,
|
||||
"min_value": "0.0",
|
||||
"max_value_warning": "retraction_amount * 2",
|
||||
"visible": false,
|
||||
"inherit_function": "retraction_amount",
|
||||
"enabled": "retraction_enable"
|
||||
|
@ -742,6 +772,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0,
|
||||
"min_value_warning": "-0.0001",
|
||||
"max_value_warning": "10",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "retraction_enable"
|
||||
|
@ -835,6 +867,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 60,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "150",
|
||||
"visible": false,
|
||||
"inherit": true,
|
||||
"enabled": "support_roof_enable"
|
||||
|
@ -845,6 +879,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 40,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "150",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "support_roof_enable",
|
||||
|
@ -859,9 +895,9 @@
|
|||
"description": "The speed at which travel moves are done. A well-built Ultimaker can reach speeds of 250mm/s, but some machines might have misaligned layers then.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 120,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "300",
|
||||
"default": 120,
|
||||
"inherit_function": "speed_print if magic_spiralize else 120"
|
||||
},
|
||||
"speed_layer_0": {
|
||||
|
@ -869,8 +905,9 @@
|
|||
"description": "The print speed for the bottom layer: You want to print the first layer slower so it sticks better to the printer bed.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"min_value": "0.1",
|
||||
"default": 30,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "300",
|
||||
"visible": false
|
||||
},
|
||||
"skirt_speed": {
|
||||
|
@ -878,8 +915,9 @@
|
|||
"description": "The speed at which the skirt and brim are printed. Normally this is done at the initial layer speed, but sometimes you might want to print the skirt at a different speed.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"min_value": "0.1",
|
||||
"default": 30,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "300",
|
||||
"visible": false,
|
||||
"inherit_function": "speed_layer_0"
|
||||
},
|
||||
|
@ -887,8 +925,9 @@
|
|||
"label": "Number of Slower Layers",
|
||||
"description": "The first few layers are printed slower than the rest of the object, this to get better adhesion to the printer bed and improve the overall success rate of prints. The speed is gradually increased over these layers. 4 layers of speed-up is generally right for most materials and printers.",
|
||||
"type": "int",
|
||||
"min_value": "0",
|
||||
"default": 4,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "300",
|
||||
"visible": false
|
||||
}
|
||||
}
|
||||
|
@ -919,6 +958,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1.5,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "machine_nozzle_tip_outer_diameter * 5",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "retraction_combing"
|
||||
|
@ -938,6 +979,8 @@
|
|||
"unit": "mm³",
|
||||
"type": "float",
|
||||
"default": 0.064,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "2.0",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "coasting_enable"
|
||||
|
@ -949,6 +992,7 @@
|
|||
"type": "float",
|
||||
"default": 0.8,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10.0",
|
||||
"visible": false,
|
||||
"enabled": "coasting_enable"
|
||||
},
|
||||
|
@ -958,6 +1002,8 @@
|
|||
"unit": "%",
|
||||
"type": "float",
|
||||
"default": 90,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "100",
|
||||
"visible": false,
|
||||
"inherit": false,
|
||||
"enabled": "coasting_enable"
|
||||
|
@ -1015,16 +1061,18 @@
|
|||
"description": "The height at which the fan is turned on completely. For the layers below this the fan speed is scaled linearly with the fan off for the first layer.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"default": 0.5,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10.0",
|
||||
"visible": false,
|
||||
"children": {
|
||||
"cool_fan_full_layer": {
|
||||
"label": "Fan Full on at Layer",
|
||||
"description": "The layer number at which the fan is turned on completely. For the layers below this the fan speed is scaled linearly with the fan off for the first layer.",
|
||||
"type": "int",
|
||||
"min_value": "0",
|
||||
"default": 4,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"visible": false,
|
||||
"inherit_function": "int((parent_value - layer_height_0 + 0.001) / layer_height)"
|
||||
}
|
||||
|
@ -1035,8 +1083,9 @@
|
|||
"description": "The minimum time spent in a layer: Gives the layer time to cool down before the next one is put on top. If a layer would print in less time, then the printer will slow down to make sure it has spent at least this many seconds printing the layer.",
|
||||
"unit": "sec",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"default": 5,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "600",
|
||||
"visible": false
|
||||
},
|
||||
"cool_min_layer_time_fan_speed_max": {
|
||||
|
@ -1044,8 +1093,9 @@
|
|||
"description": "The minimum time spent in a layer which will cause the fan to be at maximum speed. The fan speed increases linearly from minimum fan speed for layers taking the minimum layer time to maximum fan speed for layers taking the time specified here.",
|
||||
"unit": "sec",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"default": 10,
|
||||
"min_value": "cool_min_layer_time",
|
||||
"max_value_warning": "600",
|
||||
"visible": false
|
||||
},
|
||||
"cool_min_speed": {
|
||||
|
@ -1054,6 +1104,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 10,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"visible": false
|
||||
},
|
||||
"cool_lift_head": {
|
||||
|
@ -1062,6 +1114,47 @@
|
|||
"type": "boolean",
|
||||
"default": false,
|
||||
"visible": false
|
||||
},
|
||||
"draft_shield_enabled": {
|
||||
"label": "Enable Draft Shield",
|
||||
"description": "Enable exterior draft shield. This will create a wall around the object which traps (hot) air and shields against gusts of wind. Especially useful for materials which warp easily.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"draft_shield_dist": {
|
||||
"label": "Draft Shield X/Y Distance",
|
||||
"description": "Distance of the draft shield from the print, in the X/Y directions.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"default": 10,
|
||||
"visible": false,
|
||||
"enabled": "draft_shield_enabled"
|
||||
},
|
||||
"draft_shield_height_limitation": {
|
||||
"label": "Draft Shield Limitation",
|
||||
"description": "Whether or not to limit the height of the draft shield.",
|
||||
"type": "enum",
|
||||
"options": {
|
||||
"full": "Full",
|
||||
"limited": "Limited"
|
||||
},
|
||||
"default": "full",
|
||||
"visible": false,
|
||||
"enabled": "draft_shield_enabled"
|
||||
},
|
||||
"draft_shield_height": {
|
||||
"label": "Draft Shield Height",
|
||||
"description": "Height limitation on the draft shield. Above this height no draft shield will be printed.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"max_value_warning": "30",
|
||||
"default": 0,
|
||||
"inherit_function": "9999 if draft_shield_height_limitation == 'full' and draft_shield_enabled else 0.0",
|
||||
"visible": false,
|
||||
"enabled": "draft_shield_height_limitation == \"limited\""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1162,14 +1255,16 @@
|
|||
"max_value": "90",
|
||||
"default": 30,
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
"enabled": "support_conical_enabled and support_enable"
|
||||
},
|
||||
"support_conical_min_width": {
|
||||
"label": "Minimal Width",
|
||||
"description": "Minimal width to which conical support reduces the support areas. Small widths can cause the base of the support to not act well as foundation for support above.",
|
||||
"unit": "mm",
|
||||
"min_value": "0",
|
||||
"default": 3.0,
|
||||
"min_value": "0",
|
||||
"min_value_warning": "machine_nozzle_size * 3",
|
||||
"max_value_warning": "100.0",
|
||||
"type": "float",
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
|
@ -1180,6 +1275,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.3,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "1.0",
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
},
|
||||
|
@ -1188,7 +1285,9 @@
|
|||
"description": "The maximum distance between support blocks in the X/Y directions, so that the blocks will merge into a single block.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 2,
|
||||
"default": 2.0,
|
||||
"min_value_warning": "0",
|
||||
"max_value_warning": "10",
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
},
|
||||
|
@ -1198,6 +1297,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.2,
|
||||
"min_value_warning": "-0.5",
|
||||
"max_value_warning": "5.0",
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
},
|
||||
|
@ -1207,6 +1308,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.6,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "1.0",
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
},
|
||||
|
@ -1224,6 +1327,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10",
|
||||
"visible": false,
|
||||
"enabled": "support_roof_enable"
|
||||
},
|
||||
|
@ -1233,6 +1338,8 @@
|
|||
"unit": "%",
|
||||
"type": "float",
|
||||
"default": 100,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"enabled":"support_roof_enable",
|
||||
"children": {
|
||||
"support_roof_line_distance": {
|
||||
|
@ -1241,6 +1348,7 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.4,
|
||||
"min_value": "0",
|
||||
"visible": false,
|
||||
"inherit_function": "0 if parent_value == 0 else (support_roof_line_width * 100) / parent_value",
|
||||
"enabled": "support_roof_enable"
|
||||
|
@ -1276,6 +1384,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10",
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
},
|
||||
|
@ -1285,6 +1395,9 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1,
|
||||
"min_value": "0",
|
||||
"min_value_warning": "support_minimal_diameter",
|
||||
"max_value_warning": "10",
|
||||
"visible": false,
|
||||
"enabled": "support_enable"
|
||||
},
|
||||
|
@ -1328,7 +1441,7 @@
|
|||
"unit": "%",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"max_value": "100",
|
||||
"max_value_warning": "100",
|
||||
"default": 15,
|
||||
"visible": false,
|
||||
"enabled": "support_enable",
|
||||
|
@ -1370,6 +1483,8 @@
|
|||
"description": "Multiple skirt lines help to prime your extrusion better for small objects. Setting this to 0 will disable the skirt.",
|
||||
"type": "int",
|
||||
"default": 1,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10",
|
||||
"enabled": "adhesion_type == \"skirt\""
|
||||
},
|
||||
"skirt_gap": {
|
||||
|
@ -1378,6 +1493,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 3,
|
||||
"min_value_warning": "0",
|
||||
"max_value_warning": "100",
|
||||
"enabled": "adhesion_type == \"skirt\""
|
||||
},
|
||||
"skirt_minimal_length": {
|
||||
|
@ -1386,6 +1503,9 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 250,
|
||||
"min_value": "0",
|
||||
"min_value_warning": "25",
|
||||
"max_value_warning": "2500",
|
||||
"enabled": "adhesion_type == \"skirt\""
|
||||
},
|
||||
"brim_width": {
|
||||
|
@ -1394,6 +1514,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 5.0,
|
||||
"min_value": "0.0",
|
||||
"max_value_warning": "100.0",
|
||||
"enabled": "adhesion_type == \"brim\"",
|
||||
"children": {
|
||||
"brim_line_count": {
|
||||
|
@ -1401,6 +1523,8 @@
|
|||
"description": "The number of lines used for a brim. More lines means a larger brim which sticks better to the build plate, but this also makes your effective print area smaller.",
|
||||
"type": "int",
|
||||
"default": 13,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "300",
|
||||
"inherit_function": "math.ceil(parent_value / skirt_line_width)",
|
||||
"enabled": "adhesion_type == \"brim\""
|
||||
}
|
||||
|
@ -1412,6 +1536,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 5,
|
||||
"min_value_warning": "0",
|
||||
"max_value_warning": "10",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_airgap": {
|
||||
|
@ -1420,6 +1546,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.35,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "1.0",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_surface_layers": {
|
||||
|
@ -1427,6 +1555,8 @@
|
|||
"description": "The number of top layers on top of the 2nd raft layer. These are fully filled layers that the object sits on. 2 layers result in a smoother top surface than 1.",
|
||||
"type": "int",
|
||||
"default": 2,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "20",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_surface_thickness": {
|
||||
|
@ -1435,6 +1565,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.1,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "2.0",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_surface_line_width": {
|
||||
|
@ -1443,6 +1575,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.3,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "machine_nozzle_size * 2",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_surface_line_spacing": {
|
||||
|
@ -1451,6 +1585,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.3,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "5.0",
|
||||
"enabled": "adhesion_type == \"raft\"",
|
||||
"inherit_function": "raft_surface_line_width"
|
||||
},
|
||||
|
@ -1460,6 +1596,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.27,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "5.0",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_interface_line_width": {
|
||||
|
@ -1468,6 +1606,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "machine_nozzle_size * 2",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_interface_line_spacing": {
|
||||
|
@ -1476,6 +1616,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1.0,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "15.0",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_base_thickness": {
|
||||
|
@ -1484,6 +1626,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 0.3,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "5.0",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_base_line_width": {
|
||||
|
@ -1492,6 +1636,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 1,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "machine_nozzle_size * 2",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_base_line_spacing": {
|
||||
|
@ -1500,6 +1646,8 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default": 3.0,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "100",
|
||||
"enabled": "adhesion_type == \"raft\""
|
||||
},
|
||||
"raft_speed": {
|
||||
|
@ -1508,6 +1656,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 30,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "200",
|
||||
"enabled": "adhesion_type == \"raft\"",
|
||||
"inherit_function": "speed_print / 60 * 30",
|
||||
"children": {
|
||||
|
@ -1517,6 +1667,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 30,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "100",
|
||||
"enabled": "adhesion_type == \"raft\"",
|
||||
"inherit_function": "parent_value"
|
||||
},
|
||||
|
@ -1526,6 +1678,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 15,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "150",
|
||||
"enabled": "adhesion_type == \"raft\"",
|
||||
"inherit_function": "0.5 * parent_value"
|
||||
},
|
||||
|
@ -1535,6 +1689,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 15,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "200",
|
||||
"enabled": "adhesion_type == \"raft\"",
|
||||
"inherit_function": "0.5 * parent_value"
|
||||
}
|
||||
|
@ -1588,47 +1744,6 @@
|
|||
"enabled": "adhesion_type == \"raft\""
|
||||
}
|
||||
}
|
||||
},
|
||||
"draft_shield_enabled": {
|
||||
"label": "Enable Draft Shield",
|
||||
"description": "Enable exterior draft shield. This will create a wall around the object which traps (hot) air and shields against gusts of wind. Especially useful for materials which warp easily.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"draft_shield_dist": {
|
||||
"label": "Draft Shield X/Y Distance",
|
||||
"description": "Distance of the draft shield from the print, in the X/Y directions.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"default": 10,
|
||||
"visible": false,
|
||||
"enabled": "draft_shield_enabled"
|
||||
},
|
||||
"draft_shield_height_limitation": {
|
||||
"label": "Draft Shield Limitation",
|
||||
"description": "Whether or not to limit the height of the draft shield.",
|
||||
"type": "enum",
|
||||
"options": {
|
||||
"full": "Full",
|
||||
"limited": "Limited"
|
||||
},
|
||||
"default": "full",
|
||||
"visible": false,
|
||||
"enabled": "draft_shield_enabled"
|
||||
},
|
||||
"draft_shield_height": {
|
||||
"label": "Draft Shield Height",
|
||||
"description": "Height limitation on the draft shield. Above this height no draft shield will be printed.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"min_value": "0",
|
||||
"max_value_warning": "30",
|
||||
"default": 0,
|
||||
"inherit_function": "9999 if draft_shield_height_limitation == 'full' and draft_shield_enabled else 0.0",
|
||||
"visible": false,
|
||||
"enabled": "draft_shield_height_limitation == \"limited\""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1698,7 +1813,7 @@
|
|||
},
|
||||
"magic_spiralize": {
|
||||
"label": "Spiralize Outer Contour",
|
||||
"description": "Spiralize smooths out the Z move of the outer edge. This will create a steady Z increase over the whole print. This feature turns a solid object into a single walled print with a solid bottom. This feature used to be called ‘Joris’ in older versions.",
|
||||
"description": "Spiralize smooths out the Z move of the outer edge. This will create a steady Z increase over the whole print. This feature turns a solid object into a single walled print with a solid bottom. This feature used to be called Joris in older versions.",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"visible": false
|
||||
|
@ -1716,6 +1831,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 0.3,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "wall_line_width_0",
|
||||
"visible": false,
|
||||
"enabled": "magic_fuzzy_skin_enabled"
|
||||
},
|
||||
|
@ -1725,6 +1842,9 @@
|
|||
"type": "float",
|
||||
"unit": "1/mm",
|
||||
"default": 1.25,
|
||||
"min_value_warning": "0.1",
|
||||
"max_value_warning": "10",
|
||||
"max_value": "10000",
|
||||
"visible": false,
|
||||
"enabled": "magic_fuzzy_skin_enabled",
|
||||
"children": {
|
||||
|
@ -1734,6 +1854,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 0.8,
|
||||
"min_value_warning": "0.0001",
|
||||
"max_value_warning": "10",
|
||||
"inherit_function": "1/parent_value",
|
||||
"visible": false,
|
||||
"enabled": "magic_fuzzy_skin_enabled"
|
||||
|
@ -1753,6 +1875,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 3,
|
||||
"min_value": "0.0001",
|
||||
"max_value_warning": "20",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1762,6 +1886,9 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 3,
|
||||
"min_value": "0",
|
||||
"min_value_warning": "machine_nozzle_size",
|
||||
"max_value_warning": "20",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled",
|
||||
"inherit_function": "wireframe_height"
|
||||
|
@ -1772,6 +1899,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 5,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "50",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled",
|
||||
"children": {
|
||||
|
@ -1781,6 +1910,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 5,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "50",
|
||||
"visible": false,
|
||||
"inherit": true,
|
||||
"enabled": "wireframe_enabled"
|
||||
|
@ -1791,6 +1922,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 5,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "50",
|
||||
"visible": false,
|
||||
"inherit": true,
|
||||
"enabled": "wireframe_enabled"
|
||||
|
@ -1801,6 +1934,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 5,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "50",
|
||||
"visible": false,
|
||||
"inherit": true,
|
||||
"enabled": "wireframe_enabled"
|
||||
|
@ -1811,6 +1946,8 @@
|
|||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default": 5,
|
||||
"min_value": "0.1",
|
||||
"max_value_warning": "100",
|
||||
"visible": false,
|
||||
"inherit": true,
|
||||
"enabled": "wireframe_enabled"
|
||||
|
@ -1823,7 +1960,7 @@
|
|||
"unit": "%",
|
||||
"default": 100,
|
||||
"min_value": "0",
|
||||
"max_value": "100",
|
||||
"max_value_warning": "100",
|
||||
"type": "float",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled",
|
||||
|
@ -1833,6 +1970,8 @@
|
|||
"description": "Flow compensation when going up or down. Only applies to Wire Printing.",
|
||||
"unit": "%",
|
||||
"default": 100,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"type": "float",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
|
@ -1842,6 +1981,8 @@
|
|||
"description": "Flow compensation when printing flat lines. Only applies to Wire Printing.",
|
||||
"unit": "%",
|
||||
"default": 100,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "100",
|
||||
"type": "float",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
|
@ -1854,6 +1995,8 @@
|
|||
"unit": "sec",
|
||||
"type": "float",
|
||||
"default": 0,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "1",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1863,6 +2006,8 @@
|
|||
"unit": "sec",
|
||||
"type": "float",
|
||||
"default": 0,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "1",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1872,6 +2017,8 @@
|
|||
"unit": "sec",
|
||||
"type": "float",
|
||||
"default": 0.1,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "0.5",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1881,6 +2028,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 0.3,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "5.0",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1890,6 +2039,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 0.6,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "2.0",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1899,6 +2050,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 0.5,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "wireframe_height",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1908,6 +2061,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 0.6,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "wireframe_height",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1929,9 +2084,9 @@
|
|||
"description": "Percentage of a diagonally downward line which is covered by a horizontal line piece. This can prevent sagging of the top most point of upward lines. Only applies to Wire Printing.",
|
||||
"type": "float",
|
||||
"unit": "%",
|
||||
"min_value": "0",
|
||||
"max_value": "100",
|
||||
"default": 20,
|
||||
"min_value": "0",
|
||||
"max_value": "100",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1941,6 +2096,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 2,
|
||||
"min_value_warning": "0",
|
||||
"max_value_warning": "wireframe_roof_inset",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1950,6 +2107,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 0.8,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "10",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1959,6 +2118,8 @@
|
|||
"type": "float",
|
||||
"unit": "sec",
|
||||
"default": 0.2,
|
||||
"min_value": "0",
|
||||
"max_value_warning": "2.0",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
},
|
||||
|
@ -1968,6 +2129,8 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default": 1,
|
||||
"min_value_warning": "0",
|
||||
"max_value_warning": "10.0",
|
||||
"visible": false,
|
||||
"enabled": "wireframe_enabled"
|
||||
}
|
||||
|
|
38
resources/machines/m180.json
Normal file
38
resources/machines/m180.json
Normal file
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"id": "m180",
|
||||
"version": 1,
|
||||
"name": "Malyan M180",
|
||||
"manufacturer": "Other",
|
||||
"icon": "icon_ultimaker.png",
|
||||
"platform": "",
|
||||
"inherits": "fdmprinter.json",
|
||||
|
||||
"machine_settings": {
|
||||
"machine_width": { "default": 230 },
|
||||
"machine_height": { "default": 165 },
|
||||
"machine_depth": { "default": 145 },
|
||||
"machine_center_is_zero": { "default": true },
|
||||
"machine_nozzle_size": { "default": 0.4, "min_value": "0.001" },
|
||||
"machine_head_with_fans_polygon": {
|
||||
"default": [
|
||||
[ -75, 35 ],
|
||||
[ -75, -18 ],
|
||||
[ 18, -18 ],
|
||||
[ 18, 35 ]
|
||||
]
|
||||
},
|
||||
"gantry_height": { "default": 55 },
|
||||
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
||||
"machine_start_gcode": { "default": "M136\nM73 P0\nM103\nG21\nG90\nM320\n;(**** begin homing ****)\nG162 X Y F4000\nG161 Z F3500\nG92 Z-5\nG1 Z0.0\nG161 Z F100\nM132 X Y Z A B\n;(**** end homing ****)\nG92 X147 Y66 Z5\nG1 X105 Y-60 Z10 F4000.0\nG130 X127 Y127 A127 B127\nG0 X105 Y-60\nG1 Z0.3 F300\nG92 E0\nG1 X100 E10 F300\nG92 E0\nG1 Z0.0 F300\nM320" },
|
||||
"machine_end_gcode": { "default": "G92 Z0\nG1 Z10 F400\nM18\nM109 S0 T0\nM104 S0 T0\nM73 P100 (end build progress)\nG162 X Y F3000\nM18" }
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"material_bed_temperature": { "visible": "True" },
|
||||
"material_diameter": {
|
||||
"default": 1.75,
|
||||
"min_value_warning": "1.5",
|
||||
"max_value_warning": "2.0"
|
||||
}
|
||||
}
|
||||
}
|
19
resources/machines/ultimaker2_extended_plus.json
Normal file
19
resources/machines/ultimaker2_extended_plus.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"id": "ultimaker2_extended_plus_base",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2 Extended+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
"visible": false,
|
||||
"inherits": "ultimaker2plus.json",
|
||||
|
||||
"machine_settings": {
|
||||
"machine_width": { "default": 230 },
|
||||
"machine_depth": { "default": 225 },
|
||||
"machine_height": { "default": 310 },
|
||||
"machine_show_variants": { "default": true },
|
||||
"gantry_height": { "default": 50 }
|
||||
}
|
||||
}
|
14
resources/machines/ultimaker2_extended_plus_025.json
Normal file
14
resources/machines/ultimaker2_extended_plus_025.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": "ultimaker2_extended_plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2 Extended+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
"inherits": "ultimaker2_extended_plus.json",
|
||||
"variant": "0.25mm Nozzle",
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.25 }
|
||||
}
|
||||
}
|
14
resources/machines/ultimaker2_extended_plus_040.json
Normal file
14
resources/machines/ultimaker2_extended_plus_040.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": "ultimaker2_extended_plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2 Extended+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
"inherits": "ultimaker2_extended_plus.json",
|
||||
"variant": "0.40mm Nozzle",
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.40 }
|
||||
}
|
||||
}
|
14
resources/machines/ultimaker2_extended_plus_060.json
Normal file
14
resources/machines/ultimaker2_extended_plus_060.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": "ultimaker2_extended_plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2 Extended+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
"inherits": "ultimaker2_extended_plus.json",
|
||||
"variant": "0.60mm Nozzle",
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.60 }
|
||||
}
|
||||
}
|
14
resources/machines/ultimaker2_extended_plus_080.json
Normal file
14
resources/machines/ultimaker2_extended_plus_080.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": "ultimaker2_extended_plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2 Extended+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
"inherits": "ultimaker2_extended_plus.json",
|
||||
"variant": "0.80mm Nozzle",
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.80 }
|
||||
}
|
||||
}
|
46
resources/machines/ultimaker2plus.json
Normal file
46
resources/machines/ultimaker2plus.json
Normal file
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"id": "ultimaker2plus_base",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
"visible": false,
|
||||
|
||||
"inherits": "ultimaker2.json",
|
||||
|
||||
"machine_settings": {
|
||||
"machine_width": { "default": 230 },
|
||||
"machine_depth": { "default": 225 },
|
||||
"machine_height": { "default": 200 },
|
||||
"machine_show_variants": { "default": true },
|
||||
"gantry_height": { "default": 50 }
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"shell_thickness": { "default": 1.2 },
|
||||
"top_bottom_thickness": { "inherit_function": "(parent_value / 3) * 2" },
|
||||
"travel_compensate_overlapping_walls_enabled": { "default": true },
|
||||
"skin_alternate_rotation": { "default": true },
|
||||
"skin_outline_count": { "default": 2 },
|
||||
"infill_sparse_density": { "default": 10 },
|
||||
"infill_overlap": { "default": 14, "inherit_function": "14 if infill_sparse_density < 95 else 0" },
|
||||
"infill_wipe_dist": { "default": 0.35, "inherit_function": "wall_line_width_0" },
|
||||
"retraction_amount": { "default": 6 },
|
||||
"retraction_min_travel": { "default": 4.5 },
|
||||
"retraction_count_max": { "default": 6 },
|
||||
"retraction_extrusion_window": { "default": 6.0 },
|
||||
"speed_print": { "default": 50 },
|
||||
"speed_wall": { "inherit_function": "parent_value / 50 * 30" },
|
||||
"speed_wall_x": { "inherit_function": "speed_print / 50 * 40" },
|
||||
"speed_topbottom": { "inherit_function": "parent_value / 50 * 20" },
|
||||
"speed_layer_0": { "default": 20 },
|
||||
"skirt_speed": { "default": 20 },
|
||||
"travel_avoid_distance": { "default": 1.0 },
|
||||
"coasting_enable": { "default": true },
|
||||
"coasting_volume": { "default": 0.4 },
|
||||
"support_angle": { "default": 50 },
|
||||
"adhesion_type": { "default": "brim" }
|
||||
}
|
||||
}
|
31
resources/machines/ultimaker2plus_025.json
Normal file
31
resources/machines/ultimaker2plus_025.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"id": "ultimaker2plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
|
||||
"inherits": "ultimaker2plus.json",
|
||||
|
||||
"variant": "0.25mm Nozzle",
|
||||
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.25 }
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"layer_height": { "default": 0.06 },
|
||||
"layer_height_0": { "default": 0.15 },
|
||||
|
||||
"infill_sparse_density": { "default": 12 },
|
||||
"speed_print": { "default": 30 },
|
||||
"speed_wall": { "inherit_function": "parent_value / 30 * 20" },
|
||||
"speed_wall_x": { "inherit_function": "speed_print / 30 * 25" },
|
||||
"speed_topbottom": { "inherit_function": "parent_value / 30 * 20" },
|
||||
|
||||
"coasting_volume": { "default": 0.1 },
|
||||
"coasting_min_volume": { "default": 0.17 }
|
||||
}
|
||||
}
|
22
resources/machines/ultimaker2plus_040.json
Normal file
22
resources/machines/ultimaker2plus_040.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"id": "ultimaker2plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
|
||||
"inherits": "ultimaker2plus.json",
|
||||
|
||||
"variant": "0.40mm Nozzle",
|
||||
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.40 }
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"wall_line_width_0": { "inherit_function": "parent_value * 0.875" },
|
||||
"skin_line_width": { "inherit_function": "parent_value * 0.875" }
|
||||
}
|
||||
}
|
32
resources/machines/ultimaker2plus_060.json
Normal file
32
resources/machines/ultimaker2plus_060.json
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"id": "ultimaker2plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
|
||||
"inherits": "ultimaker2plus.json",
|
||||
|
||||
"variant": "0.60mm Nozzle",
|
||||
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.60 }
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"layer_height": { "default": 0.15 },
|
||||
"layer_height_0": { "default": 0.4 },
|
||||
|
||||
"shell_thickness": { "default": 1.8 },
|
||||
|
||||
"infill_sparse_density": { "default": 15 },
|
||||
"speed_print": { "default": 55 },
|
||||
"speed_wall": { "inherit_function": "parent_value / 55 * 25" },
|
||||
"speed_wall_x": { "inherit_function": "speed_print / 55 * 40" },
|
||||
"speed_topbottom": { "inherit_function": "parent_value / 55 * 20" },
|
||||
|
||||
"coasting_volume": { "default": 1.36 }
|
||||
}
|
||||
}
|
33
resources/machines/ultimaker2plus_080.json
Normal file
33
resources/machines/ultimaker2plus_080.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"id": "ultimaker2plus",
|
||||
"version": 1,
|
||||
"name": "Ultimaker 2+",
|
||||
"manufacturer": "Ultimaker",
|
||||
"author": "Ultimaker",
|
||||
"platform": "ultimaker2_platform.obj",
|
||||
"platform_texture": "ultimaker2plus_backplate.png",
|
||||
|
||||
"inherits": "ultimaker2plus.json",
|
||||
|
||||
"variant": "0.80mm Nozzle",
|
||||
|
||||
"machine_settings": {
|
||||
"machine_nozzle_size": { "default": 0.80 }
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"layer_height": { "default": 0.2 },
|
||||
"layer_height_0": { "default": 0.5 },
|
||||
|
||||
"shell_thickness": { "default": 2.4 },
|
||||
"top_bottom_thickness": { "inherit_function": "parent_value / 2" },
|
||||
|
||||
"infill_sparse_density": { "default": 16 },
|
||||
"speed_print": { "default": 40 },
|
||||
"speed_wall": { "inherit_function": "parent_value / 40 * 20" },
|
||||
"speed_wall_x": { "inherit_function": "speed_print / 40 * 30" },
|
||||
"speed_topbottom": { "inherit_function": "parent_value / 40 * 20" },
|
||||
|
||||
"coasting_volume": { "default": 3.22 }
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -54,7 +54,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: undoAction;
|
||||
text: catalog.i18nc("@action:inmenu","&Undo");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","&Undo");
|
||||
iconName: "edit-undo";
|
||||
shortcut: StandardKey.Undo;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: redoAction;
|
||||
text: catalog.i18nc("@action:inmenu","&Redo");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","&Redo");
|
||||
iconName: "edit-redo";
|
||||
shortcut: StandardKey.Redo;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: quitAction;
|
||||
text: catalog.i18nc("@action:inmenu","&Quit");
|
||||
text: catalog.i18nc("@action:inmenu menubar:file","&Quit");
|
||||
iconName: "application-exit";
|
||||
shortcut: StandardKey.Quit;
|
||||
}
|
||||
|
@ -78,55 +78,56 @@ Item
|
|||
Action
|
||||
{
|
||||
id: preferencesAction;
|
||||
text: catalog.i18nc("@action:inmenu","&Preferences...");
|
||||
text: catalog.i18nc("@action:inmenu menubar:settings","&Preferences...");
|
||||
iconName: "configure";
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: addMachineAction;
|
||||
text: catalog.i18nc("@action:inmenu","&Add Printer...");
|
||||
text: catalog.i18nc("@action:inmenu menubar:printer","&Add Printer...");
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: settingsAction;
|
||||
text: catalog.i18nc("@action:inmenu","Manage Pr&inters...");
|
||||
text: catalog.i18nc("@action:inmenu menubar:printer","Manage Pr&inters...");
|
||||
iconName: "configure";
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: manageProfilesAction;
|
||||
text: catalog.i18nc("@action:inmenu","Manage Profiles...");
|
||||
text: catalog.i18nc("@action:inmenu menubar:profile","Manage Profiles...");
|
||||
iconName: "configure";
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: documentationAction;
|
||||
text: catalog.i18nc("@action:inmenu","Show Online &Documentation");
|
||||
text: catalog.i18nc("@action:inmenu menubar:help","Show Online &Documentation");
|
||||
iconName: "help-contents";
|
||||
shortcut: StandardKey.Help;
|
||||
}
|
||||
|
||||
Action {
|
||||
id: reportBugAction;
|
||||
text: catalog.i18nc("@action:inmenu","Report a &Bug");
|
||||
text: catalog.i18nc("@action:inmenu menubar:help","Report a &Bug");
|
||||
iconName: "tools-report-bug";
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: aboutAction;
|
||||
text: catalog.i18nc("@action:inmenu","&About...");
|
||||
text: catalog.i18nc("@action:inmenu menubar:help","&About...");
|
||||
iconName: "help-about";
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: deleteSelectionAction;
|
||||
text: catalog.i18nc("@action:inmenu","Delete &Selection");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","Delete &Selection");
|
||||
enabled: UM.Controller.toolsEnabled;
|
||||
iconName: "edit-delete";
|
||||
shortcut: StandardKey.Delete;
|
||||
}
|
||||
|
@ -135,6 +136,7 @@ Item
|
|||
{
|
||||
id: deleteObjectAction;
|
||||
text: catalog.i18nc("@action:inmenu","Delete Object");
|
||||
enabled: UM.Controller.toolsEnabled;
|
||||
iconName: "edit-delete";
|
||||
}
|
||||
|
||||
|
@ -147,7 +149,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: groupObjectsAction
|
||||
text: catalog.i18nc("@action:inmenu","&Group Objects");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","&Group Objects");
|
||||
enabled: UM.Scene.numObjectsSelected > 1 ? true: false
|
||||
iconName: "object-group"
|
||||
}
|
||||
|
@ -155,7 +157,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: unGroupObjectsAction
|
||||
text: catalog.i18nc("@action:inmenu","Ungroup Objects");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","Ungroup Objects");
|
||||
enabled: UM.Scene.isGroupSelected
|
||||
iconName: "object-ungroup"
|
||||
}
|
||||
|
@ -163,7 +165,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: mergeObjectsAction
|
||||
text: catalog.i18nc("@action:inmenu","&Merge Objects");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","&Merge Objects");
|
||||
enabled: UM.Scene.numObjectsSelected > 1 ? true: false
|
||||
iconName: "merge";
|
||||
}
|
||||
|
@ -178,7 +180,8 @@ Item
|
|||
Action
|
||||
{
|
||||
id: deleteAllAction;
|
||||
text: catalog.i18nc("@action:inmenu","&Clear Build Platform");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","&Clear Build Platform");
|
||||
enabled: UM.Controller.toolsEnabled;
|
||||
iconName: "edit-delete";
|
||||
shortcut: "Ctrl+D";
|
||||
}
|
||||
|
@ -186,26 +189,26 @@ Item
|
|||
Action
|
||||
{
|
||||
id: reloadAllAction;
|
||||
text: catalog.i18nc("@action:inmenu","Re&load All Objects");
|
||||
text: catalog.i18nc("@action:inmenu menubar:file","Re&load All Objects");
|
||||
iconName: "document-revert";
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: resetAllTranslationAction;
|
||||
text: catalog.i18nc("@action:inmenu","Reset All Object Positions");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","Reset All Object Positions");
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: resetAllAction;
|
||||
text: catalog.i18nc("@action:inmenu","Reset All Object &Transformations");
|
||||
text: catalog.i18nc("@action:inmenu menubar:edit","Reset All Object &Transformations");
|
||||
}
|
||||
|
||||
Action
|
||||
{
|
||||
id: openAction;
|
||||
text: catalog.i18nc("@action:inmenu","&Open File...");
|
||||
text: catalog.i18nc("@action:inmenu menubar:file","&Open File...");
|
||||
iconName: "document-open";
|
||||
shortcut: StandardKey.Open;
|
||||
}
|
||||
|
@ -213,7 +216,7 @@ Item
|
|||
Action
|
||||
{
|
||||
id: showEngineLogAction;
|
||||
text: catalog.i18nc("@action:inmenu","Show Engine &Log...");
|
||||
text: catalog.i18nc("@action:inmenu menubar:help","Show Engine &Log...");
|
||||
iconName: "view-list-text";
|
||||
shortcut: StandardKey.WhatsThis;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ UM.MainWindow
|
|||
id: base
|
||||
//: Cura application window title
|
||||
title: catalog.i18nc("@title:window","Cura");
|
||||
|
||||
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
|
||||
|
||||
Item
|
||||
|
@ -23,6 +22,14 @@ UM.MainWindow
|
|||
anchors.fill: parent;
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
|
||||
signal hasMesh(string name) //this signal sends the filebase name so it can be used for the JobSpecs.qml
|
||||
function getMeshName(path){
|
||||
//takes the path the complete path of the meshname and returns only the filebase
|
||||
var fileName = path.slice(path.lastIndexOf("/") + 1)
|
||||
var fileBase = fileName.slice(0, fileName.lastIndexOf("."))
|
||||
return fileBase
|
||||
}
|
||||
|
||||
//DeleteSelection on the keypress backspace event
|
||||
Keys.onPressed: {
|
||||
if (event.key == Qt.Key_Backspace)
|
||||
|
@ -34,7 +41,6 @@ UM.MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
UM.ApplicationMenu
|
||||
{
|
||||
id: menu
|
||||
|
@ -44,7 +50,7 @@ UM.MainWindow
|
|||
{
|
||||
id: fileMenu
|
||||
//: File menu
|
||||
title: catalog.i18nc("@title:menu","&File");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&File");
|
||||
|
||||
MenuItem {
|
||||
action: actions.open;
|
||||
|
@ -53,7 +59,7 @@ UM.MainWindow
|
|||
Menu
|
||||
{
|
||||
id: recentFilesMenu;
|
||||
title: catalog.i18nc("@title:menu", "Open &Recent")
|
||||
title: catalog.i18nc("@title:menu menubar:file", "Open &Recent")
|
||||
iconName: "document-open-recent";
|
||||
|
||||
enabled: Printer.recentFiles.length > 0;
|
||||
|
@ -70,7 +76,8 @@ UM.MainWindow
|
|||
}
|
||||
onTriggered: {
|
||||
UM.MeshFileHandler.readLocalFile(modelData);
|
||||
openDialog.sendMeshName(modelData.toString())
|
||||
var meshName = backgroundItem.getMeshName(modelData.toString())
|
||||
backgroundItem.hasMesh(meshName)
|
||||
}
|
||||
}
|
||||
onObjectAdded: recentFilesMenu.insertItem(index, object)
|
||||
|
@ -82,7 +89,7 @@ UM.MainWindow
|
|||
|
||||
MenuItem
|
||||
{
|
||||
text: catalog.i18nc("@action:inmenu", "&Save Selection to File");
|
||||
text: catalog.i18nc("@action:inmenu menubar:file", "&Save Selection to File");
|
||||
enabled: UM.Selection.hasSelection;
|
||||
iconName: "document-save-as";
|
||||
onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file", Printer.jobName);
|
||||
|
@ -90,7 +97,7 @@ UM.MainWindow
|
|||
Menu
|
||||
{
|
||||
id: saveAllMenu
|
||||
title: catalog.i18nc("@title:menu","Save &All")
|
||||
title: catalog.i18nc("@title:menu menubar:file","Save &All")
|
||||
iconName: "document-save-all";
|
||||
enabled: devicesModel.rowCount() > 0 && UM.Backend.progress > 0.99;
|
||||
|
||||
|
@ -118,7 +125,7 @@ UM.MainWindow
|
|||
Menu
|
||||
{
|
||||
//: Edit menu
|
||||
title: catalog.i18nc("@title:menu","&Edit");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Edit");
|
||||
|
||||
MenuItem { action: actions.undo; }
|
||||
MenuItem { action: actions.redo; }
|
||||
|
@ -135,7 +142,7 @@ UM.MainWindow
|
|||
|
||||
Menu
|
||||
{
|
||||
title: catalog.i18nc("@title:menu","&View");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&View");
|
||||
id: top_view_menu
|
||||
Instantiator
|
||||
{
|
||||
|
@ -157,7 +164,7 @@ UM.MainWindow
|
|||
{
|
||||
id: machineMenu;
|
||||
//: Machine menu
|
||||
title: catalog.i18nc("@title:menu","&Machine");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Printer");
|
||||
|
||||
Instantiator
|
||||
{
|
||||
|
@ -203,7 +210,7 @@ UM.MainWindow
|
|||
Menu
|
||||
{
|
||||
id: profileMenu
|
||||
title: catalog.i18nc("@title:menu", "&Profile")
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel", "P&rofile")
|
||||
|
||||
Instantiator
|
||||
{
|
||||
|
@ -230,7 +237,7 @@ UM.MainWindow
|
|||
{
|
||||
id: extension_menu
|
||||
//: Extensions menu
|
||||
title: catalog.i18nc("@title:menu","E&xtensions");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","E&xtensions");
|
||||
|
||||
Instantiator
|
||||
{
|
||||
|
@ -263,7 +270,7 @@ UM.MainWindow
|
|||
Menu
|
||||
{
|
||||
//: Settings menu
|
||||
title: catalog.i18nc("@title:menu","&Settings");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Settings");
|
||||
|
||||
MenuItem { action: actions.preferences; }
|
||||
}
|
||||
|
@ -271,7 +278,7 @@ UM.MainWindow
|
|||
Menu
|
||||
{
|
||||
//: Help menu
|
||||
title: catalog.i18nc("@title:menu","&Help");
|
||||
title: catalog.i18nc("@title:menu menubar:toplevel","&Help");
|
||||
|
||||
MenuItem { action: actions.showEngineLog; }
|
||||
MenuItem { action: actions.documentation; }
|
||||
|
@ -303,7 +310,8 @@ UM.MainWindow
|
|||
UM.MeshFileHandler.readLocalFile(drop.urls[i]);
|
||||
if (i == drop.urls.length - 1)
|
||||
{
|
||||
openDialog.sendMeshName(drop.urls[i].toString())
|
||||
var meshName = backgroundItem.getMeshName(drop.urls[i].toString())
|
||||
backgroundItem.hasMesh(meshName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -312,6 +320,7 @@ UM.MainWindow
|
|||
|
||||
JobSpecs
|
||||
{
|
||||
id: jobSpecs
|
||||
anchors
|
||||
{
|
||||
bottom: parent.bottom;
|
||||
|
@ -327,7 +336,8 @@ UM.MainWindow
|
|||
{
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
horizontalCenterOffset: -(UM.Theme.sizes.sidebar.width/ 2)
|
||||
verticalCenter: parent.verticalCenter;
|
||||
top: parent.verticalCenter;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -517,10 +527,7 @@ UM.MainWindow
|
|||
|
||||
deleteSelection.onTriggered:
|
||||
{
|
||||
if(objectContextMenu.objectId != 0)
|
||||
{
|
||||
Printer.deleteObject(objectContextMenu.objectId);
|
||||
}
|
||||
Printer.deleteSelection()
|
||||
}
|
||||
|
||||
deleteObject.onTriggered:
|
||||
|
@ -638,14 +645,6 @@ UM.MainWindow
|
|||
modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
|
||||
//TODO: Support multiple file selection, workaround bug in KDE file dialog
|
||||
//selectMultiple: true
|
||||
|
||||
signal hasMesh(string name)
|
||||
|
||||
function sendMeshName(path){
|
||||
var fileName = path.slice(path.lastIndexOf("/") + 1)
|
||||
var fileBase = fileName.slice(0, fileName.lastIndexOf("."))
|
||||
openDialog.hasMesh(fileBase)
|
||||
}
|
||||
nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
|
||||
|
||||
onAccepted:
|
||||
|
@ -656,7 +655,8 @@ UM.MainWindow
|
|||
folder = f;
|
||||
|
||||
UM.MeshFileHandler.readLocalFile(fileUrl)
|
||||
openDialog.sendMeshName(fileUrl.toString())
|
||||
var meshName = backgroundItem.getMeshName(fileUrl.toString())
|
||||
backgroundItem.hasMesh(meshName)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import UM 1.1 as UM
|
|||
UM.PreferencesPage
|
||||
{
|
||||
//: General configuration page title
|
||||
title: catalog.i18nc("@title:tab","General");
|
||||
title: catalog.i18nc("@title:tab","General")
|
||||
|
||||
function setDefaultLanguage(languageCode)
|
||||
{
|
||||
|
@ -38,74 +38,72 @@ UM.PreferencesPage
|
|||
setDefaultLanguage(defaultLanguage)
|
||||
}
|
||||
|
||||
GridLayout
|
||||
ColumnLayout
|
||||
{
|
||||
columns: 2;
|
||||
//: Language selection label
|
||||
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||
Label
|
||||
{
|
||||
id: languageLabel
|
||||
text: catalog.i18nc("@label","Language")
|
||||
}
|
||||
|
||||
ComboBox
|
||||
RowLayout
|
||||
{
|
||||
id: languageComboBox
|
||||
model: ListModel
|
||||
Label
|
||||
{
|
||||
id: languageList
|
||||
|
||||
Component.onCompleted: {
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Bulgarian"), code: "bg" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Czech"), code: "cs" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "English"), code: "en" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "Finnish"), code: "fi" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "French"), code: "fr" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "German"), code: "de" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Italian"), code: "it" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "Polish"), code: "pl" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Russian"), code: "ru" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Spanish"), code: "es" })
|
||||
}
|
||||
id: languageLabel
|
||||
text: catalog.i18nc("@label","Language:")
|
||||
}
|
||||
|
||||
currentIndex:
|
||||
ComboBox
|
||||
{
|
||||
var code = UM.Preferences.getValue("general/language");
|
||||
for(var i = 0; i < languageList.count; ++i)
|
||||
id: languageComboBox
|
||||
model: ListModel
|
||||
{
|
||||
if(model.get(i).code == code)
|
||||
{
|
||||
return i
|
||||
id: languageList
|
||||
|
||||
Component.onCompleted: {
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Bulgarian"), code: "bg" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Czech"), code: "cs" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "English"), code: "en" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "Finnish"), code: "fi" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "French"), code: "fr" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "German"), code: "de" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Italian"), code: "it" })
|
||||
append({ text: catalog.i18nc("@item:inlistbox", "Polish"), code: "pl" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Russian"), code: "ru" })
|
||||
// append({ text: catalog.i18nc("@item:inlistbox", "Spanish"), code: "es" })
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: UM.Preferences.setValue("general/language", model.get(index).code)
|
||||
|
||||
anchors.left: languageLabel.right
|
||||
anchors.top: languageLabel.top
|
||||
anchors.leftMargin: 20
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
// Because ListModel is stupid and does not allow using qsTr() for values.
|
||||
for(var i = 0; i < languageList.count; ++i)
|
||||
currentIndex:
|
||||
{
|
||||
languageList.setProperty(i, "text", catalog.i18n(languageList.get(i).text));
|
||||
var code = UM.Preferences.getValue("general/language");
|
||||
for(var i = 0; i < languageList.count; ++i)
|
||||
{
|
||||
if(model.get(i).code == code)
|
||||
{
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: UM.Preferences.setValue("general/language", model.get(index).code)
|
||||
|
||||
// Glorious hack time. ComboBox does not update the text properly after changing the
|
||||
// model. So change the indices around to force it to update.
|
||||
currentIndex += 1;
|
||||
currentIndex -= 1;
|
||||
Component.onCompleted:
|
||||
{
|
||||
// Because ListModel is stupid and does not allow using qsTr() for values.
|
||||
for(var i = 0; i < languageList.count; ++i)
|
||||
{
|
||||
languageList.setProperty(i, "text", catalog.i18n(languageList.get(i).text));
|
||||
}
|
||||
|
||||
// Glorious hack time. ComboBox does not update the text properly after changing the
|
||||
// model. So change the indices around to force it to update.
|
||||
currentIndex += 1;
|
||||
currentIndex -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: languageCaption;
|
||||
Layout.columnSpan: 2
|
||||
id: languageCaption
|
||||
|
||||
//: Language change warning
|
||||
text: catalog.i18nc("@label", "You will need to restart the application for language changes to have effect.")
|
||||
|
@ -113,103 +111,46 @@ UM.PreferencesPage
|
|||
font.italic: true
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: pushFreeCheckbox
|
||||
checked: boolCheck(UM.Preferences.getValue("physics/automatic_push_free"))
|
||||
onCheckedChanged: UM.Preferences.setValue("physics/automatic_push_free", checked)
|
||||
}
|
||||
Button
|
||||
{
|
||||
id: pushFreeText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||
UM.TooltipArea {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip", "Should objects on the platform be moved so that they no longer intersect.")
|
||||
|
||||
//: Display Overhang preference checkbox
|
||||
text: catalog.i18nc("@option:check", "Ensure objects are kept apart");
|
||||
onClicked: pushFreeCheckbox.checked = !pushFreeCheckbox.checked
|
||||
|
||||
//: Display Overhang preference tooltip
|
||||
tooltip: catalog.i18nc("@info:tooltip", "Should objects on the platform be moved so that they no longer intersect.")
|
||||
|
||||
style: ButtonStyle
|
||||
CheckBox
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
border.width: 0
|
||||
color: "transparent"
|
||||
}
|
||||
label: Text
|
||||
{
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: control.text
|
||||
}
|
||||
id: pushFreeCheckbox
|
||||
text: catalog.i18nc("@option:check", "Ensure objects are kept apart")
|
||||
checked: boolCheck(UM.Preferences.getValue("physics/automatic_push_free"))
|
||||
onCheckedChanged: UM.Preferences.setValue("physics/automatic_push_free", checked)
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox
|
||||
{
|
||||
id: sendDataCheckbox
|
||||
checked: boolCheck(UM.Preferences.getValue("info/send_slice_info"))
|
||||
onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked)
|
||||
}
|
||||
Button
|
||||
{
|
||||
id: sendDataText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||
UM.TooltipArea {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","Should opened files be scaled to the build volume if they are too large?")
|
||||
|
||||
//: Display Overhang preference checkbox
|
||||
text: catalog.i18nc("@option:check","Send (Anonymous) Print Information");
|
||||
onClicked: sendDataCheckbox.checked = !sendDataCheckbox.checked
|
||||
|
||||
//: Display Overhang preference tooltip
|
||||
tooltip: catalog.i18nc("@info:tooltip","Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored.")
|
||||
|
||||
style: ButtonStyle
|
||||
CheckBox
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
border.width: 0
|
||||
color: "transparent"
|
||||
}
|
||||
label: Text
|
||||
{
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: control.text
|
||||
}
|
||||
id: scaleToFitCheckbox
|
||||
text: catalog.i18nc("@option:check","Scale large files")
|
||||
checked: boolCheck(UM.Preferences.getValue("mesh/scale_to_fit"))
|
||||
onCheckedChanged: UM.Preferences.setValue("mesh/scale_to_fit", checked)
|
||||
}
|
||||
}
|
||||
CheckBox
|
||||
{
|
||||
id: scaleToFitCheckbox
|
||||
checked: boolCheck(UM.Preferences.getValue("mesh/scale_to_fit"))
|
||||
onCheckedChanged: UM.Preferences.setValue("mesh/scale_to_fit", checked)
|
||||
}
|
||||
Button
|
||||
{
|
||||
id: scaleToFitText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||
|
||||
//: Display Overhang preference checkbox
|
||||
text: catalog.i18nc("@option:check","Scale Too Large Files");
|
||||
onClicked: scaleToFitCheckbox.checked = !scaleToFitCheckbox.checked
|
||||
UM.TooltipArea {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
text: catalog.i18nc("@info:tooltip","Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored.")
|
||||
|
||||
//: Display Overhang preference tooltip
|
||||
tooltip: catalog.i18nc("@info:tooltip","Should opened files be scaled to the build volume when they are too large?")
|
||||
|
||||
style: ButtonStyle
|
||||
CheckBox
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
border.width: 0
|
||||
color: "transparent"
|
||||
}
|
||||
label: Text
|
||||
{
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: control.text
|
||||
}
|
||||
id: sendDataCheckbox
|
||||
text: catalog.i18nc("@option:check","Send (anonymous) print information")
|
||||
checked: boolCheck(UM.Preferences.getValue("info/send_slice_info"))
|
||||
onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked)
|
||||
}
|
||||
}
|
||||
Item { Layout.fillHeight: true; Layout.columnSpan: 2 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,54 +53,111 @@ Rectangle {
|
|||
}
|
||||
|
||||
Connections {
|
||||
target: openDialog
|
||||
target: backgroundItem
|
||||
onHasMesh: {
|
||||
if(base.fileBaseName == ''){
|
||||
base.fileBaseName = name
|
||||
base.createFileName()
|
||||
}
|
||||
base.fileBaseName = name
|
||||
}
|
||||
}
|
||||
|
||||
onActivityChanged: {
|
||||
if (activity == false){
|
||||
base.fileBaseName = ''
|
||||
if (activity == true && base.fileBaseName == ''){
|
||||
//this only runs when you open a file from the terminal (or something that works the same way; for example when you drag a file on the icon in MacOS or use 'open with' on Windows)
|
||||
base.fileBaseName = Printer.jobName //it gets the fileBaseName from CuraApplication.py because this saves the filebase when the file is opened using the terminal (or something alike)
|
||||
base.createFileName()
|
||||
}
|
||||
if (activity == true && base.fileBaseName != ''){
|
||||
//this runs in all other cases where there is a mesh on the buildplate (activity == true). It uses the fileBaseName from the hasMesh signal
|
||||
base.createFileName()
|
||||
}
|
||||
if (activity == false){
|
||||
//When there is no mesh in the buildplate; the printJobTextField is set to an empty string so it doesn't set an empty string as a jobName (which is later used for saving the file)
|
||||
printJobTextfield.text = ''
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextField {
|
||||
id: printJobTextfield
|
||||
Rectangle
|
||||
{
|
||||
id: jobNameRow
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
height: UM.Theme.sizes.jobspecs_line.height
|
||||
width: base.width
|
||||
property int unremovableSpacing: 5
|
||||
text: ''
|
||||
horizontalAlignment: TextInput.AlignRight
|
||||
onTextChanged: Printer.setJobName(text)
|
||||
visible: base.activity
|
||||
onEditingFinished: {
|
||||
if (printJobTextfield.text != ''){
|
||||
printJobTextfield.focus = false
|
||||
|
||||
Item
|
||||
{
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
Button
|
||||
{
|
||||
id: printJobPencilIcon
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: UM.Theme.sizes.save_button_specs_icons.width
|
||||
height: UM.Theme.sizes.save_button_specs_icons.height
|
||||
|
||||
onClicked:
|
||||
{
|
||||
printJobTextfield.selectAll()
|
||||
printJobTextfield.focus = true
|
||||
}
|
||||
style: ButtonStyle
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
color: "transparent"
|
||||
UM.RecolorImage
|
||||
{
|
||||
width: UM.Theme.sizes.save_button_specs_icons.width
|
||||
height: UM.Theme.sizes.save_button_specs_icons.height
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: control.hovered ? UM.Theme.colors.setting_control_button_hover : UM.Theme.colors.text
|
||||
source: UM.Theme.icons.pencil;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
validator: RegExpValidator {
|
||||
regExp: /^[^\\ \/ \.]*$/
|
||||
}
|
||||
style: TextFieldStyle{
|
||||
textColor: UM.Theme.colors.setting_control_text;
|
||||
font: UM.Theme.fonts.default;
|
||||
background: Rectangle {
|
||||
opacity: 0
|
||||
border.width: 0
|
||||
|
||||
TextField
|
||||
{
|
||||
id: printJobTextfield
|
||||
anchors.right: printJobPencilIcon.left
|
||||
anchors.rightMargin: UM.Theme.sizes.default_margin.width/2
|
||||
height: UM.Theme.sizes.jobspecs_line.height
|
||||
width: base.width
|
||||
property int unremovableSpacing: 5
|
||||
text: ''
|
||||
horizontalAlignment: TextInput.AlignRight
|
||||
onTextChanged: {
|
||||
if(text != ''){
|
||||
//this prevent that is sets an empty string as jobname
|
||||
Printer.setJobName(text)
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
if (printJobTextfield.text != ''){
|
||||
printJobTextfield.focus = false
|
||||
}
|
||||
}
|
||||
validator: RegExpValidator {
|
||||
regExp: /^[^\\ \/ \.]*$/
|
||||
}
|
||||
style: TextFieldStyle{
|
||||
textColor: UM.Theme.colors.setting_control_text;
|
||||
font: UM.Theme.fonts.default_bold;
|
||||
background: Rectangle {
|
||||
opacity: 0
|
||||
border.width: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label{
|
||||
id: boundingSpec
|
||||
anchors.top: printJobTextfield.bottom
|
||||
anchors.top: jobNameRow.bottom
|
||||
anchors.right: parent.right
|
||||
height: UM.Theme.sizes.jobspecs_line.height
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
@ -138,7 +195,7 @@ Rectangle {
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
font: UM.Theme.fonts.small
|
||||
color: UM.Theme.colors.text_subtext
|
||||
text: (!base.printDuration || !base.printDuration.valid) ? "00h 00min" : base.printDuration.getDisplayString(UM.DurationFormat.Short)
|
||||
text: (!base.printDuration || !base.printDuration.valid) ? catalog.i18nc("@label", "00h 00min") : base.printDuration.getDisplayString(UM.DurationFormat.Short)
|
||||
}
|
||||
UM.RecolorImage {
|
||||
id: lengthIcon
|
||||
|
@ -158,7 +215,7 @@ Rectangle {
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
font: UM.Theme.fonts.small
|
||||
color: UM.Theme.colors.text_subtext
|
||||
text: base.printMaterialAmount <= 0 ? "0.0 m" : catalog.i18nc("@label %1 is length of filament","%1 m").arg(base.printMaterialAmount)
|
||||
text: base.printMaterialAmount <= 0 ? catalog.i18nc("@label", "0.0 m") : catalog.i18nc("@label", "%1 m").arg(base.printMaterialAmount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
64
resources/qml/LoadProfileDialog.qml
Normal file
64
resources/qml/LoadProfileDialog.qml
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2015 Ultimaker B.V.
|
||||
// Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.1
|
||||
import QtQuick.Window 2.1
|
||||
|
||||
import UM 1.1 as UM
|
||||
|
||||
UM.Dialog
|
||||
{
|
||||
id: base
|
||||
|
||||
//: About dialog title
|
||||
title: catalog.i18nc("@title:window","Load profile")
|
||||
width: 400
|
||||
height: childrenRect.height
|
||||
|
||||
Label
|
||||
{
|
||||
id: body
|
||||
|
||||
//: About dialog application description
|
||||
text: catalog.i18nc("@label","Selecting this profile overwrites some of your customised settings. Do you want to merge the new settings into your current profile or do you want to load a clean copy of the profile?")
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
anchors.top: parent.top
|
||||
anchors.margins: UM.Theme.sizes.default_margin.height
|
||||
|
||||
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: show_details
|
||||
|
||||
//: About dialog application author note
|
||||
text: catalog.i18nc("@label","Show details.")
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.top: body.bottom
|
||||
anchors.topMargin: UM.Theme.sizes.default_margin.height
|
||||
}
|
||||
|
||||
rightButtons: Row
|
||||
{
|
||||
spacing: UM.Theme.sizes.default_margin.width
|
||||
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button","Merge settings");
|
||||
}
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button","Reset profile");
|
||||
}
|
||||
Button
|
||||
{
|
||||
text: catalog.i18nc("@action:button","Cancel");
|
||||
|
||||
onClicked: base.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,62 +14,9 @@ Item{
|
|||
property int totalHeightProfileSetup: childrenRect.height
|
||||
property Action manageProfilesAction
|
||||
|
||||
Rectangle {
|
||||
id: variantRow
|
||||
anchors.top: base.top
|
||||
width: base.width
|
||||
height: UM.Theme.sizes.sidebar_setup.height
|
||||
//visible: UM.MachineManager.hasVariants;
|
||||
visible: true
|
||||
|
||||
Label{
|
||||
id: variantLabel
|
||||
text: catalog.i18nc("@label","Variant:");
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width/100*45
|
||||
font: UM.Theme.fonts.default;
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: variantSelection
|
||||
text: UM.MachineManager.activeMachineVariant
|
||||
width: parent.width/100*55
|
||||
height: UM.Theme.sizes.setting_control.height
|
||||
tooltip: UM.MachineManager.activeMachineInstance;
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: UM.Theme.sizes.default_margin.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
style: UM.Theme.styles.sidebar_header_button
|
||||
|
||||
menu: Menu
|
||||
{
|
||||
id: variantsSelectionMenu
|
||||
Instantiator
|
||||
{
|
||||
model: UM.MachineVariantsModel { id: variantsModel }
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.active;
|
||||
exclusiveGroup: variantSelectionMenuGroup;
|
||||
onTriggered: UM.MachineManager.setActiveMachineVariant(variantsModel.getItem(index).name)
|
||||
}
|
||||
onObjectAdded: variantsSelectionMenu.insertItem(index, object)
|
||||
onObjectRemoved: variantsSelectionMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: variantSelectionMenuGroup; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id: globalProfileRow;
|
||||
anchors.top: UM.MachineManager.hasVariants ? variantRow.bottom : base.top
|
||||
//anchors.top: variantRow.bottom
|
||||
id: globalProfileRow
|
||||
anchors.top: base.top
|
||||
height: UM.Theme.sizes.sidebar_setup.height
|
||||
width: base.width
|
||||
|
||||
|
@ -78,7 +25,7 @@ Item{
|
|||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: catalog.i18nc("@label","Global Profile:");
|
||||
text: catalog.i18nc("@label","Profile:");
|
||||
width: parent.width/100*45
|
||||
font: UM.Theme.fonts.default;
|
||||
color: UM.Theme.colors.text;
|
||||
|
|
|
@ -74,7 +74,7 @@ Rectangle {
|
|||
Button {
|
||||
id: saveToButton
|
||||
property int resizedWidth
|
||||
x: base.width - saveToButton.resizedWidth - UM.Theme.sizes.default_margin.width - UM.Theme.sizes.save_button_save_to_button.height + 3
|
||||
x: base.width - saveToButton.resizedWidth - UM.Theme.sizes.default_margin.width - UM.Theme.sizes.save_button_save_to_button.height + UM.Theme.sizes.save_button_save_to_button.width
|
||||
tooltip: UM.OutputDeviceManager.activeDeviceDescription;
|
||||
enabled: base.progress > 0.99 && base.activity == true
|
||||
height: UM.Theme.sizes.save_button_save_to_button.height
|
||||
|
@ -90,6 +90,7 @@ Rectangle {
|
|||
background: Rectangle {
|
||||
//opacity: control.enabled ? 1.0 : 0.5
|
||||
//Behavior on opacity { NumberAnimation { duration: 50; } }
|
||||
border.width: UM.Theme.sizes.default_lining.width
|
||||
border.color: !control.enabled ? UM.Theme.colors.action_button_disabled_border :
|
||||
control.pressed ? UM.Theme.colors.action_button_active_border :
|
||||
control.hovered ? UM.Theme.colors.action_button_hovered_border : UM.Theme.colors.action_button_border
|
||||
|
@ -130,6 +131,7 @@ Rectangle {
|
|||
style: ButtonStyle {
|
||||
background: Rectangle {
|
||||
id: deviceSelectionIcon
|
||||
border.width: UM.Theme.sizes.default_lining.width
|
||||
border.color: !control.enabled ? UM.Theme.colors.action_button_disabled_border :
|
||||
control.pressed ? UM.Theme.colors.action_button_active_border :
|
||||
control.hovered ? UM.Theme.colors.action_button_hovered_border : UM.Theme.colors.action_button_border
|
||||
|
|
|
@ -120,6 +120,7 @@ Rectangle
|
|||
|
||||
style: ButtonStyle {
|
||||
background: Rectangle {
|
||||
border.width: UM.Theme.sizes.default_lining.width
|
||||
border.color: control.checked ? UM.Theme.colors.toggle_checked_border :
|
||||
control.pressed ? UM.Theme.colors.toggle_active_border :
|
||||
control.hovered ? UM.Theme.colors.toggle_hovered_border : UM.Theme.colors.toggle_unchecked_border
|
||||
|
|
|
@ -17,7 +17,7 @@ Item
|
|||
property int totalHeightHeader: childrenRect.height
|
||||
|
||||
Rectangle {
|
||||
id: settingsModeRow
|
||||
id: sidebarTabRow
|
||||
width: base.width
|
||||
height: 0
|
||||
anchors.top: parent.top
|
||||
|
@ -29,7 +29,7 @@ Item
|
|||
text: catalog.i18nc("@label:listbox","Print Job");
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||
anchors.top: settingsModeRow.bottom
|
||||
anchors.top: sidebarTabRow.bottom
|
||||
anchors.topMargin: UM.Theme.sizes.default_margin.height
|
||||
width: parent.width/100*45
|
||||
font: UM.Theme.fonts.large;
|
||||
|
@ -47,7 +47,7 @@ Item
|
|||
Label{
|
||||
id: machineSelectionLabel
|
||||
//: Machine selection label
|
||||
text: catalog.i18nc("@label:listbox","Machine:");
|
||||
text: catalog.i18nc("@label:listbox","Printer:");
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
@ -93,4 +93,57 @@ Item
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: variantRow
|
||||
anchors.top: machineSelectionRow.bottom
|
||||
anchors.topMargin: UM.MachineManager.hasVariants ? UM.Theme.sizes.default_margin.height : 0
|
||||
width: base.width
|
||||
height: UM.MachineManager.hasVariants ? UM.Theme.sizes.sidebar_setup.height : 0
|
||||
visible: UM.MachineManager.hasVariants
|
||||
|
||||
Label{
|
||||
id: variantLabel
|
||||
text: catalog.i18nc("@label","Nozzle:");
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width/100*45
|
||||
font: UM.Theme.fonts.default;
|
||||
color: UM.Theme.colors.text;
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: variantSelection
|
||||
text: UM.MachineManager.activeMachineVariant
|
||||
width: parent.width/100*55
|
||||
height: UM.Theme.sizes.setting_control.height
|
||||
tooltip: UM.MachineManager.activeMachineVariant;
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: UM.Theme.sizes.default_margin.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
style: UM.Theme.styles.sidebar_header_button
|
||||
|
||||
menu: Menu
|
||||
{
|
||||
id: variantsSelectionMenu
|
||||
Instantiator
|
||||
{
|
||||
model: UM.MachineVariantsModel { id: variantsModel }
|
||||
MenuItem
|
||||
{
|
||||
text: model.name;
|
||||
checkable: true;
|
||||
checked: model.active;
|
||||
exclusiveGroup: variantSelectionMenuGroup;
|
||||
onTriggered: UM.MachineManager.setActiveMachineVariant(variantsModel.getItem(index).name)
|
||||
}
|
||||
onObjectAdded: variantsSelectionMenu.insertItem(index, object)
|
||||
onObjectRemoved: variantsSelectionMenu.removeItem(object)
|
||||
}
|
||||
|
||||
ExclusiveGroup { id: variantSelectionMenuGroup; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ Item
|
|||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: base.width/100* 35 - UM.Theme.sizes.default_margin.width
|
||||
height: childrenRect.height < UM.Theme.sizes.simple_mode_infill_caption.height ? UM.Theme.sizes.simple_mode_infill_caption.height : childrenRect.height
|
||||
height: childrenRect.height
|
||||
|
||||
Label{
|
||||
id: infillLabel
|
||||
|
@ -140,17 +140,6 @@ Item
|
|||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width
|
||||
}
|
||||
/* Label{
|
||||
id: infillCaption
|
||||
width: infillCellLeft.width - UM.Theme.sizes.default_margin.width * 2
|
||||
text: infillModel.count > 0 && infillListView.activeIndex != -1 ? infillModel.get(infillListView.activeIndex).text : ""
|
||||
font: UM.Theme.fonts.caption
|
||||
wrapMode: Text.Wrap
|
||||
color: UM.Theme.colors.text_subtext
|
||||
anchors.top: infillLabel.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width
|
||||
} */
|
||||
}
|
||||
|
||||
Flow {
|
||||
|
@ -162,7 +151,6 @@ Item
|
|||
|
||||
anchors.left: infillCellLeft.right
|
||||
anchors.top: infillCellLeft.top
|
||||
anchors.topMargin: UM.Theme.sizes.default_margin.height
|
||||
|
||||
Repeater {
|
||||
id: infillListView
|
||||
|
@ -335,7 +323,7 @@ Item
|
|||
property bool hovered_ex: false
|
||||
|
||||
anchors.top: brimCheckBox.bottom
|
||||
anchors.topMargin: UM.Theme.sizes.default_lining.height
|
||||
anchors.topMargin: UM.Theme.sizes.default_margin.height
|
||||
anchors.left: parent.left
|
||||
|
||||
//: Setting enable support checkbox
|
||||
|
|
|
@ -33,7 +33,7 @@ Item {
|
|||
|
||||
checkable: true;
|
||||
checked: model.active;
|
||||
enabled: UM.Selection.hasSelection;
|
||||
enabled: UM.Selection.hasSelection && UM.Controller.toolsEnabled;
|
||||
|
||||
style: UM.Theme.styles.tool_button;
|
||||
|
||||
|
@ -97,6 +97,7 @@ Item {
|
|||
y: UM.Theme.sizes.default_margin.height;
|
||||
|
||||
source: UM.ActiveTool.valid ? UM.ActiveTool.activeToolPanel : "";
|
||||
enabled: UM.Controller.toolsEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ UM.PreferencesPage
|
|||
checked: boolCheck(UM.Preferences.getValue("view/show_overhang"))
|
||||
onClicked: UM.Preferences.setValue("view/show_overhang", checked)
|
||||
|
||||
text: catalog.i18nc("@option:check","Display Overhang");
|
||||
text: catalog.i18nc("@option:check","Display overhang");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,30 +129,31 @@ Item
|
|||
|
||||
section.property: "manufacturer"
|
||||
section.delegate: Button {
|
||||
text: section + " "
|
||||
text: section
|
||||
style: ButtonStyle {
|
||||
background: Rectangle {
|
||||
id: manufacturerBackground
|
||||
opacity: 0.3
|
||||
border.width: 0
|
||||
color: control.hovered ? palette.light : "transparent";
|
||||
color: "transparent";
|
||||
height: UM.Theme.sizes.standard_list_lineheight.height
|
||||
width: machineList.width
|
||||
}
|
||||
label: Text {
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.standard_arrow.width + UM.Theme.sizes.default_margin.width
|
||||
text: control.text
|
||||
color: palette.windowText
|
||||
font.bold: true
|
||||
UM.RecolorImage {
|
||||
id: downArrow
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.right
|
||||
anchors.right: parent.left
|
||||
anchors.rightMargin: UM.Theme.sizes.default_margin.width
|
||||
width: UM.Theme.sizes.standard_arrow.width
|
||||
height: UM.Theme.sizes.standard_arrow.height
|
||||
sourceSize.width: width
|
||||
sourceSize.height: width
|
||||
color: palette.windowText
|
||||
source: base,activeManufacturer == section ? UM.Theme.icons.arrow_bottom : UM.Theme.icons.arrow_right
|
||||
source: base.activeManufacturer == section ? UM.Theme.icons.arrow_bottom : UM.Theme.icons.arrow_right
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,18 +185,6 @@ Item
|
|||
machineName.text = getMachineName()
|
||||
}
|
||||
|
||||
Label
|
||||
{
|
||||
id: author
|
||||
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;
|
||||
|
|
16
resources/themes/cura/icons/pencil.svg
Normal file
16
resources/themes/cura/icons/pencil.svg
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" viewBox="0 -256 1792 1792" id="svg3001" version="1.1" inkscape:version="0.48.3.1 r9886" width="100%" height="100%" sodipodi:docname="pencil_font_awesome.svg">
|
||||
<metadata id="metadata3011">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs id="defs3009"/>
|
||||
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview3007" showgrid="false" inkscape:zoom="0.13169643" inkscape:cx="896" inkscape:cy="896" inkscape:window-x="0" inkscape:window-y="25" inkscape:window-maximized="0" inkscape:current-layer="svg3001"/>
|
||||
<g transform="matrix(1,0,0,-1,121.49153,1270.2373)" id="g3003">
|
||||
<path d="M 363,0 454,91 219,326 128,235 V 128 H 256 V 0 h 107 z m 523,928 q 0,22 -22,22 -10,0 -17,-7 L 305,401 q -7,-7 -7,-17 0,-22 22,-22 10,0 17,7 l 542,542 q 7,7 7,17 z M 832,1120 1248,704 416,-128 H 0 v 416 z m 683,-96 q 0,-53 -37,-90 l -166,-166 -416,416 166,165 q 36,38 90,38 53,0 91,-38 l 235,-234 q 37,-39 37,-91 z" id="path3005" inkscape:connector-curvature="0" style="fill:currentColor"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -12,7 +12,7 @@ QtObject {
|
|||
ButtonStyle {
|
||||
background: Rectangle {
|
||||
color: UM.Theme.colors.setting_control
|
||||
border.width: 1
|
||||
border.width: UM.Theme.sizes.default_lining.width
|
||||
border.color: control.hovered ? UM.Theme.colors.setting_control_border_highlight : UM.Theme.colors.setting_control_border
|
||||
UM.RecolorImage {
|
||||
id: downArrow
|
||||
|
@ -331,7 +331,8 @@ QtObject {
|
|||
width: UM.Theme.sizes.section_icon_column.width
|
||||
UM.RecolorImage {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width
|
||||
color: UM.Theme.colors.setting_category_text
|
||||
source: control.iconSource;
|
||||
width: UM.Theme.sizes.section_icon.width;
|
||||
|
@ -344,6 +345,7 @@ QtObject {
|
|||
Label {
|
||||
anchors {
|
||||
left: icon.right;
|
||||
leftMargin: UM.Theme.sizes.default_lining.width;
|
||||
right: parent.right;
|
||||
verticalCenter: parent.verticalCenter;
|
||||
}
|
||||
|
@ -493,7 +495,7 @@ QtObject {
|
|||
radius: width/2;
|
||||
|
||||
color: UM.Theme.colors.slider_groove;
|
||||
border.width: UM.Theme.sizes.default_lining;
|
||||
border.width: UM.Theme.sizes.default_lining.width;
|
||||
border.color: UM.Theme.colors.slider_groove_border;
|
||||
Rectangle {
|
||||
anchors {
|
||||
|
@ -515,26 +517,24 @@ QtObject {
|
|||
TextField {
|
||||
id: valueLabel
|
||||
property string maxValue: control.maximumValue + 1
|
||||
placeholderText: control.value + 1
|
||||
text: control.value + 1
|
||||
horizontalAlignment: TextInput.AlignHCenter
|
||||
onEditingFinished: {
|
||||
if (valueLabel.text != ''){
|
||||
control.value = valueLabel.text - 1
|
||||
valueLabel.text = ''
|
||||
valueLabel.focus = false
|
||||
}
|
||||
|
||||
}
|
||||
validator: IntValidator {bottom: 1; top: control.maximumValue + 1;}
|
||||
visible: UM.LayerView.getLayerActivity && Printer.getPlatformActivity ? true : false
|
||||
anchors.top: layerSliderControl.bottom
|
||||
anchors.topMargin: UM.Theme.sizes.default_margin.width
|
||||
anchors.topMargin: width/2 - UM.Theme.sizes.default_margin.width/2
|
||||
anchors.horizontalCenter: layerSliderControl.horizontalCenter
|
||||
rotation: 90
|
||||
style: TextFieldStyle{
|
||||
textColor: UM.Theme.colors.setting_control_text;
|
||||
font: UM.Theme.fonts.default;
|
||||
background: Rectangle {
|
||||
implicitWidth: control.maxValue.length * valueLabel.font.pixelSize
|
||||
implicitWidth: control.maxValue.length * valueLabel.font.pixelSize + UM.Theme.sizes.default_margin.width
|
||||
implicitHeight: UM.Theme.sizes.slider_handle.height + UM.Theme.sizes.default_margin.width
|
||||
border.width: UM.Theme.sizes.default_lining.width;
|
||||
border.color: UM.Theme.colors.slider_groove_border;
|
||||
|
|
|
@ -9,10 +9,19 @@
|
|||
"size": 1.15,
|
||||
"family": "Proxima Nova Rg"
|
||||
},
|
||||
"default_bold": {
|
||||
"size": 1.15,
|
||||
"bold": true,
|
||||
"family": "Proxima Nova Rg"
|
||||
},
|
||||
"small": {
|
||||
"size": 1.0,
|
||||
"family": "Proxima Nova Rg"
|
||||
},
|
||||
"very_small": {
|
||||
"size": 0.75,
|
||||
"family": "Proxima Nova Rg"
|
||||
},
|
||||
"caption": {
|
||||
"size": 1.0,
|
||||
"family": "Proxima Nova Rg"
|
||||
|
@ -55,7 +64,7 @@
|
|||
|
||||
"text": [24, 41, 77, 255],
|
||||
"text_inactive": [174, 174, 174, 255],
|
||||
"text_hover": [35, 35, 35, 255],
|
||||
"text_hover": [70, 84, 113, 255],
|
||||
"text_pressed": [12, 169, 227, 255],
|
||||
"text_white": [255, 255, 255, 255],
|
||||
"text_subtext": [127, 127, 127, 255],
|
||||
|
@ -100,24 +109,24 @@
|
|||
"action_button_active_border": [12, 169, 227, 255],
|
||||
"action_button_disabled": [245, 245, 245, 255],
|
||||
"action_button_disabled_text": [127, 127, 127, 255],
|
||||
"action_button_disabled_border": [127, 127, 127, 255],
|
||||
"action_button_disabled_border": [245, 245, 245, 255],
|
||||
|
||||
"scrollbar_background": [255, 255, 255, 255],
|
||||
"scrollbar_handle": [24, 41, 77, 255],
|
||||
"scrollbar_handle_hover": [12, 159, 227, 255],
|
||||
"scrollbar_handle_down": [12, 159, 227, 255],
|
||||
|
||||
"setting_category": [255, 255, 255, 255],
|
||||
"setting_category": [245, 245, 245, 255],
|
||||
"setting_category_disabled": [255, 255, 255, 255],
|
||||
"setting_category_hover": [245, 245, 245, 255],
|
||||
"setting_category_active": [255, 255, 255, 255],
|
||||
"setting_category_active": [245, 245, 245, 255],
|
||||
"setting_category_active_hover": [245, 245, 245, 255],
|
||||
"setting_category_text": [24, 41, 77, 255],
|
||||
"setting_category_border": [127, 127, 127, 255],
|
||||
"setting_category_disabled_border": [127, 127, 127, 255],
|
||||
"setting_category_border": [245, 245, 245, 255],
|
||||
"setting_category_disabled_border": [245, 245, 245, 255],
|
||||
"setting_category_hover_border": [12, 159, 227, 255],
|
||||
"setting_category_active_border": [245, 245, 245, 255],
|
||||
"setting_category_active_hover_border": [245, 245, 245, 255],
|
||||
"setting_category_active_hover_border": [12, 159, 227, 255],
|
||||
|
||||
"setting_control": [255, 255, 255, 255],
|
||||
"setting_control_selected": [24, 41, 77, 255],
|
||||
|
@ -126,7 +135,8 @@
|
|||
"setting_control_border_highlight": [12, 169, 227, 255],
|
||||
"setting_control_text": [24, 41, 77, 255],
|
||||
"setting_control_depth_line": [127, 127, 127, 255],
|
||||
"setting_control_revert": [127, 127, 127, 255],
|
||||
"setting_control_button": [127, 127, 127, 255],
|
||||
"setting_control_button_hover": [70, 84, 113, 255],
|
||||
"setting_unit": [127, 127, 127, 255],
|
||||
"setting_validation_error": [255, 57, 14, 255],
|
||||
"setting_validation_warning": [255, 186, 15, 255],
|
||||
|
@ -227,7 +237,7 @@
|
|||
"save_button_save_to_button": [0.3, 2.7],
|
||||
"save_button_specs_icons": [1.4, 1.4],
|
||||
|
||||
"modal_window_minimum": [30.0, 30.0],
|
||||
"modal_window_minimum": [60.0, 45],
|
||||
"wizard_progress": [10.0, 0.0],
|
||||
|
||||
"message": [30.0, 5.0],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue