Merge branch 'master' into CURA-8081_shrinkage_plate_duplicate

# Conflicts:
#	resources/definitions/fdmprinter.def.json
This commit is contained in:
casper 2021-12-16 23:14:20 +01:00
commit 411252bcef
4386 changed files with 102400 additions and 94608 deletions

5
.gitignore vendored
View File

@ -56,6 +56,11 @@ plugins/SettingsGuide
plugins/SettingsGuide2 plugins/SettingsGuide2
plugins/SVGToolpathReader plugins/SVGToolpathReader
plugins/X3GWriter plugins/X3GWriter
plugins/CuraFlatPack
plugins/CuraRemoteSupport
plugins/ModelCutter
plugins/PrintProfileCreator
plugins/MultiPrintPlugin
#Build stuff #Build stuff
CMakeCache.txt CMakeCache.txt

View File

@ -1,15 +1,15 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from datetime import datetime
from typing import Any, Optional, Dict, TYPE_CHECKING, Callable
from datetime import datetime
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QTimer, Q_ENUMS from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QTimer, Q_ENUMS
from typing import Any, Optional, Dict, TYPE_CHECKING, Callable
from UM.Logger import Logger from UM.Logger import Logger
from UM.Message import Message from UM.Message import Message
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from cura.OAuth2.AuthorizationService import AuthorizationService from cura.OAuth2.AuthorizationService import AuthorizationService
from cura.OAuth2.Models import OAuth2Settings from cura.OAuth2.Models import OAuth2Settings, UserProfile
from cura.UltimakerCloud import UltimakerCloudConstants from cura.UltimakerCloud import UltimakerCloudConstants
if TYPE_CHECKING: if TYPE_CHECKING:
@ -46,6 +46,9 @@ class Account(QObject):
loginStateChanged = pyqtSignal(bool) loginStateChanged = pyqtSignal(bool)
"""Signal emitted when user logged in or out""" """Signal emitted when user logged in or out"""
userProfileChanged = pyqtSignal()
"""Signal emitted when new account information is available."""
additionalRightsChanged = pyqtSignal("QVariantMap") additionalRightsChanged = pyqtSignal("QVariantMap")
"""Signal emitted when a users additional rights change""" """Signal emitted when a users additional rights change"""
@ -71,13 +74,14 @@ class Account(QObject):
self._application = application self._application = application
self._new_cloud_printers_detected = False self._new_cloud_printers_detected = False
self._error_message = None # type: Optional[Message] self._error_message: Optional[Message] = None
self._logged_in = False self._logged_in = False
self._user_profile: Optional[UserProfile] = None
self._additional_rights: Dict[str, Any] = {} self._additional_rights: Dict[str, Any] = {}
self._sync_state = SyncState.IDLE self._sync_state = SyncState.IDLE
self._manual_sync_enabled = False self._manual_sync_enabled = False
self._update_packages_enabled = False self._update_packages_enabled = False
self._update_packages_action = None # type: Optional[Callable] self._update_packages_action: Optional[Callable] = None
self._last_sync_str = "-" self._last_sync_str = "-"
self._callback_port = 32118 self._callback_port = 32118
@ -103,7 +107,7 @@ class Account(QObject):
self._update_timer.setSingleShot(True) self._update_timer.setSingleShot(True)
self._update_timer.timeout.connect(self.sync) self._update_timer.timeout.connect(self.sync)
self._sync_services = {} # type: Dict[str, int] self._sync_services: Dict[str, int] = {}
"""contains entries "service_name" : SyncState""" """contains entries "service_name" : SyncState"""
def initialize(self) -> None: def initialize(self) -> None:
@ -196,12 +200,17 @@ class Account(QObject):
self._logged_in = logged_in self._logged_in = logged_in
self.loginStateChanged.emit(logged_in) self.loginStateChanged.emit(logged_in)
if logged_in: if logged_in:
self._authorization_service.getUserProfile(self._onProfileChanged)
self._setManualSyncEnabled(False) self._setManualSyncEnabled(False)
self._sync() self._sync()
else: else:
if self._update_timer.isActive(): if self._update_timer.isActive():
self._update_timer.stop() self._update_timer.stop()
def _onProfileChanged(self, profile: Optional[UserProfile]) -> None:
self._user_profile = profile
self.userProfileChanged.emit()
def _sync(self) -> None: def _sync(self) -> None:
"""Signals all sync services to start syncing """Signals all sync services to start syncing
@ -243,32 +252,28 @@ class Account(QObject):
return return
self._authorization_service.startAuthorizationFlow(force_logout_before_login) self._authorization_service.startAuthorizationFlow(force_logout_before_login)
@pyqtProperty(str, notify=loginStateChanged) @pyqtProperty(str, notify = userProfileChanged)
def userName(self): def userName(self):
user_profile = self._authorization_service.getUserProfile() if not self._user_profile:
if not user_profile: return ""
return None return self._user_profile.username
return user_profile.username
@pyqtProperty(str, notify = loginStateChanged) @pyqtProperty(str, notify = userProfileChanged)
def profileImageUrl(self): def profileImageUrl(self):
user_profile = self._authorization_service.getUserProfile() if not self._user_profile:
if not user_profile: return ""
return None return self._user_profile.profile_image_url
return user_profile.profile_image_url
@pyqtProperty(str, notify=accessTokenChanged) @pyqtProperty(str, notify=accessTokenChanged)
def accessToken(self) -> Optional[str]: def accessToken(self) -> Optional[str]:
return self._authorization_service.getAccessToken() return self._authorization_service.getAccessToken()
@pyqtProperty("QVariantMap", notify = loginStateChanged) @pyqtProperty("QVariantMap", notify = userProfileChanged)
def userProfile(self) -> Optional[Dict[str, Optional[str]]]: def userProfile(self) -> Optional[Dict[str, Optional[str]]]:
"""None if no user is logged in otherwise the logged in user as a dict containing containing user_id, username and profile_image_url """ """None if no user is logged in otherwise the logged in user as a dict containing containing user_id, username and profile_image_url """
if not self._user_profile:
user_profile = self._authorization_service.getUserProfile()
if not user_profile:
return None return None
return user_profile.__dict__ return self._user_profile.__dict__
@pyqtProperty(str, notify=lastSyncDateTimeChanged) @pyqtProperty(str, notify=lastSyncDateTimeChanged)
def lastSyncDateTime(self) -> str: def lastSyncDateTime(self) -> str:

View File

@ -1,4 +1,4 @@
# Copyright (c) 2020 Ultimaker B.V. # Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
# --------- # ---------
@ -13,7 +13,7 @@ DEFAULT_CURA_DEBUG_MODE = False
# Each release has a fixed SDK version coupled with it. It doesn't make sense to make it configurable because, for # Each release has a fixed SDK version coupled with it. It doesn't make sense to make it configurable because, for
# example Cura 3.2 with SDK version 6.1 will not work. So the SDK version is hard-coded here and left out of the # example Cura 3.2 with SDK version 6.1 will not work. So the SDK version is hard-coded here and left out of the
# CuraVersion.py.in template. # CuraVersion.py.in template.
CuraSDKVersion = "7.8.0" CuraSDKVersion = "7.9.0"
try: try:
from cura.CuraVersion import CuraAppName # type: ignore from cura.CuraVersion import CuraAppName # type: ignore

View File

@ -91,7 +91,7 @@ def findNodePlacement(nodes_to_arrange: List["SceneNode"], build_volume: "BuildV
if hull_polygon is not None and hull_polygon.getPoints() is not None and len(hull_polygon.getPoints()) > 2: # numpy array has to be explicitly checked against None if hull_polygon is not None and hull_polygon.getPoints() is not None and len(hull_polygon.getPoints()) > 2: # numpy array has to be explicitly checked against None
for point in hull_polygon.getPoints(): for point in hull_polygon.getPoints():
converted_points.append(Point(point[0] * factor, point[1] * factor)) converted_points.append(Point(int(point[0] * factor), int(point[1] * factor)))
item = Item(converted_points) item = Item(converted_points)
item.markAsFixedInBin(0) item.markAsFixedInBin(0)
node_items.append(item) node_items.append(item)

View File

@ -181,8 +181,7 @@ class Backup:
return extracted return extracted
@staticmethod def _extractArchive(self, archive: "ZipFile", target_path: str) -> bool:
def _extractArchive(archive: "ZipFile", target_path: str) -> bool:
"""Extract the whole archive to the given target path. """Extract the whole archive to the given target path.
:param archive: The archive as ZipFile. :param archive: The archive as ZipFile.
@ -201,7 +200,11 @@ class Backup:
Resources.factoryReset() Resources.factoryReset()
Logger.log("d", "Extracting backup to location: %s", target_path) Logger.log("d", "Extracting backup to location: %s", target_path)
name_list = archive.namelist() name_list = archive.namelist()
ignore_string = re.compile("|".join(self.IGNORED_FILES + self.IGNORED_FOLDERS))
for archive_filename in name_list: for archive_filename in name_list:
if ignore_string.search(archive_filename):
Logger.warning(f"File ({archive_filename}) in archive that doesn't fit current backup policy; ignored.")
continue
try: try:
archive.extract(archive_filename, target_path) archive.extract(archive_filename, target_path)
except (PermissionError, EnvironmentError): except (PermissionError, EnvironmentError):

View File

@ -66,6 +66,7 @@ class BuildVolume(SceneNode):
self._height = 0 # type: float self._height = 0 # type: float
self._depth = 0 # type: float self._depth = 0 # type: float
self._shape = "" # type: str self._shape = "" # type: str
self._scale_vector = Vector(1.0, 1.0, 1.0)
self._shader = None self._shader = None
@ -513,6 +514,13 @@ class BuildVolume(SceneNode):
self._disallowed_area_size = max(size, self._disallowed_area_size) self._disallowed_area_size = max(size, self._disallowed_area_size)
return mb.build() return mb.build()
def _updateScaleFactor(self) -> None:
if not self._global_container_stack:
return
scale_xy = 100.0 / max(100.0, self._global_container_stack.getProperty("material_shrinkage_percentage_xy", "value"))
scale_z = 100.0 / max(100.0, self._global_container_stack.getProperty("material_shrinkage_percentage_z" , "value"))
self._scale_vector = Vector(scale_xy, scale_xy, scale_z)
def rebuild(self) -> None: def rebuild(self) -> None:
"""Recalculates the build volume & disallowed areas.""" """Recalculates the build volume & disallowed areas."""
@ -554,9 +562,12 @@ class BuildVolume(SceneNode):
self._error_mesh = self._buildErrorMesh(min_w, max_w, min_h, max_h, min_d, max_d, disallowed_area_height) self._error_mesh = self._buildErrorMesh(min_w, max_w, min_h, max_h, min_d, max_d, disallowed_area_height)
self._updateScaleFactor()
self._volume_aabb = AxisAlignedBox( self._volume_aabb = AxisAlignedBox(
minimum = Vector(min_w, min_h - 1.0, min_d), minimum = Vector(min_w, min_h - 1.0, min_d).scale(self._scale_vector),
maximum = Vector(max_w, max_h - self._raft_thickness - self._extra_z_clearance, max_d)) maximum = Vector(max_w, max_h - self._raft_thickness - self._extra_z_clearance, max_d).scale(self._scale_vector)
)
bed_adhesion_size = self.getEdgeDisallowedSize() bed_adhesion_size = self.getEdgeDisallowedSize()
@ -564,15 +575,15 @@ class BuildVolume(SceneNode):
# This is probably wrong in all other cases. TODO! # 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. # The +1 and -1 is added as there is always a bit of extra room required to work properly.
scale_to_max_bounds = AxisAlignedBox( scale_to_max_bounds = AxisAlignedBox(
minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + self._disallowed_area_size - bed_adhesion_size + 1), minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + self._disallowed_area_size - bed_adhesion_size + 1).scale(self._scale_vector),
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - self._disallowed_area_size + bed_adhesion_size - 1) maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - self._disallowed_area_size + bed_adhesion_size - 1).scale(self._scale_vector)
) )
self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds # type: ignore self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds # type: ignore
self.updateNodeBoundaryCheck() self.updateNodeBoundaryCheck()
def getBoundingBox(self): def getBoundingBox(self) -> Optional[AxisAlignedBox]:
return self._volume_aabb return self._volume_aabb
def getRaftThickness(self) -> float: def getRaftThickness(self) -> float:
@ -633,18 +644,18 @@ class BuildVolume(SceneNode):
for extruder in extruders: for extruder in extruders:
extruder.propertyChanged.connect(self._onSettingPropertyChanged) extruder.propertyChanged.connect(self._onSettingPropertyChanged)
self._width = self._global_container_stack.getProperty("machine_width", "value") self._width = self._global_container_stack.getProperty("machine_width", "value") * self._scale_vector.x
machine_height = self._global_container_stack.getProperty("machine_height", "value") machine_height = self._global_container_stack.getProperty("machine_height", "value")
if self._global_container_stack.getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1: if self._global_container_stack.getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1:
self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height) self._height = min(self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height)
if self._height < machine_height: if self._height < (machine_height * self._scale_vector.z):
self._build_volume_message.show() self._build_volume_message.show()
else: else:
self._build_volume_message.hide() self._build_volume_message.hide()
else: else:
self._height = self._global_container_stack.getProperty("machine_height", "value") self._height = self._global_container_stack.getProperty("machine_height", "value")
self._build_volume_message.hide() self._build_volume_message.hide()
self._depth = self._global_container_stack.getProperty("machine_depth", "value") self._depth = self._global_container_stack.getProperty("machine_depth", "value") * self._scale_vector.y
self._shape = self._global_container_stack.getProperty("machine_shape", "value") self._shape = self._global_container_stack.getProperty("machine_shape", "value")
self._updateDisallowedAreas() self._updateDisallowedAreas()
@ -678,18 +689,18 @@ class BuildVolume(SceneNode):
if setting_key == "print_sequence": if setting_key == "print_sequence":
machine_height = self._global_container_stack.getProperty("machine_height", "value") machine_height = self._global_container_stack.getProperty("machine_height", "value")
if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1: if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1:
self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height) self._height = min(self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height)
if self._height < machine_height: if self._height < (machine_height * self._scale_vector.z):
self._build_volume_message.show() self._build_volume_message.show()
else: else:
self._build_volume_message.hide() self._build_volume_message.hide()
else: else:
self._height = self._global_container_stack.getProperty("machine_height", "value") self._height = self._global_container_stack.getProperty("machine_height", "value") * self._scale_vector.z
self._build_volume_message.hide() self._build_volume_message.hide()
update_disallowed_areas = True update_disallowed_areas = True
# sometimes the machine size or shape settings are adjusted on the active machine, we should reflect this # sometimes the machine size or shape settings are adjusted on the active machine, we should reflect this
if setting_key in self._machine_settings: if setting_key in self._machine_settings or setting_key in self._material_size_settings:
self._updateMachineSizeProperties() self._updateMachineSizeProperties()
update_extra_z_clearance = True update_extra_z_clearance = True
update_disallowed_areas = True update_disallowed_areas = True
@ -738,9 +749,10 @@ class BuildVolume(SceneNode):
def _updateMachineSizeProperties(self) -> None: def _updateMachineSizeProperties(self) -> None:
if not self._global_container_stack: if not self._global_container_stack:
return return
self._height = self._global_container_stack.getProperty("machine_height", "value") self._updateScaleFactor()
self._width = self._global_container_stack.getProperty("machine_width", "value") self._height = self._global_container_stack.getProperty("machine_height", "value") * self._scale_vector.z
self._depth = self._global_container_stack.getProperty("machine_depth", "value") self._width = self._global_container_stack.getProperty("machine_width", "value") * self._scale_vector.x
self._depth = self._global_container_stack.getProperty("machine_depth", "value") * self._scale_vector.y
self._shape = self._global_container_stack.getProperty("machine_shape", "value") self._shape = self._global_container_stack.getProperty("machine_shape", "value")
def _updateDisallowedAreasAndRebuild(self): def _updateDisallowedAreasAndRebuild(self):
@ -757,6 +769,14 @@ class BuildVolume(SceneNode):
self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks()) self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
self.rebuild() self.rebuild()
def _scaleAreas(self, result_areas: List[Polygon]) -> None:
if self._global_container_stack is None:
return
for i, polygon in enumerate(result_areas):
result_areas[i] = polygon.scale(
100.0 / max(100.0, self._global_container_stack.getProperty("material_shrinkage_percentage_xy", "value"))
)
def _updateDisallowedAreas(self) -> None: def _updateDisallowedAreas(self) -> None:
if not self._global_container_stack: if not self._global_container_stack:
return return
@ -812,9 +832,11 @@ class BuildVolume(SceneNode):
self._disallowed_areas = [] self._disallowed_areas = []
for extruder_id in result_areas: for extruder_id in result_areas:
self._scaleAreas(result_areas[extruder_id])
self._disallowed_areas.extend(result_areas[extruder_id]) self._disallowed_areas.extend(result_areas[extruder_id])
self._disallowed_areas_no_brim = [] self._disallowed_areas_no_brim = []
for extruder_id in result_areas_no_brim: for extruder_id in result_areas_no_brim:
self._scaleAreas(result_areas_no_brim[extruder_id])
self._disallowed_areas_no_brim.extend(result_areas_no_brim[extruder_id]) self._disallowed_areas_no_brim.extend(result_areas_no_brim[extruder_id])
def _computeDisallowedAreasPrinted(self, used_extruders): def _computeDisallowedAreasPrinted(self, used_extruders):
@ -1200,4 +1222,5 @@ class BuildVolume(SceneNode):
_distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts", "travel_avoid_supports", "wall_line_count", "wall_line_width_0", "wall_line_width_x"] _distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts", "travel_avoid_supports", "wall_line_count", "wall_line_width_0", "wall_line_width_x"]
_extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used. _extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used.
_limit_to_extruder_settings = ["wall_extruder_nr", "wall_0_extruder_nr", "wall_x_extruder_nr", "top_bottom_extruder_nr", "infill_extruder_nr", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "adhesion_extruder_nr"] _limit_to_extruder_settings = ["wall_extruder_nr", "wall_0_extruder_nr", "wall_x_extruder_nr", "top_bottom_extruder_nr", "infill_extruder_nr", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "adhesion_extruder_nr"]
_disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings _material_size_settings = ["material_shrinkage_percentage", "material_shrinkage_percentage_xy", "material_shrinkage_percentage_z"]
_disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings + _material_size_settings

View File

@ -129,7 +129,7 @@ class CuraApplication(QtApplication):
# SettingVersion represents the set of settings available in the machine/extruder definitions. # SettingVersion represents the set of settings available in the machine/extruder definitions.
# You need to make sure that this version number needs to be increased if there is any non-backwards-compatible # You need to make sure that this version number needs to be increased if there is any non-backwards-compatible
# changes of the settings. # changes of the settings.
SettingVersion = 18 SettingVersion = 19
Created = False Created = False

View File

@ -15,7 +15,6 @@ class Layer:
self._height = 0.0 self._height = 0.0
self._thickness = 0.0 self._thickness = 0.0
self._polygons = [] # type: List[LayerPolygon] self._polygons = [] # type: List[LayerPolygon]
self._vertex_count = 0
self._element_count = 0 self._element_count = 0
@property @property
@ -30,10 +29,6 @@ class Layer:
def polygons(self) -> List[LayerPolygon]: def polygons(self) -> List[LayerPolygon]:
return self._polygons return self._polygons
@property
def vertexCount(self):
return self._vertex_count
@property @property
def elementCount(self): def elementCount(self):
return self._element_count return self._element_count
@ -48,40 +43,24 @@ class Layer:
result = 0 result = 0
for polygon in self._polygons: for polygon in self._polygons:
result += polygon.lineMeshVertexCount() result += polygon.lineMeshVertexCount()
return result return result
def lineMeshElementCount(self) -> int: def lineMeshElementCount(self) -> int:
result = 0 result = 0
for polygon in self._polygons: for polygon in self._polygons:
result += polygon.lineMeshElementCount() result += polygon.lineMeshElementCount()
return result
def lineMeshCumulativeTypeChangeCount(self, path: int) -> int:
""" The number of line-type changes in this layer up until #path.
See also LayerPolygon::cumulativeTypeChangeCounts.
:param path: The path-index up until which the cumulative changes are counted.
:return: The cumulative number of line-type changes up until this path.
"""
result = 0
for polygon in self._polygons:
num_counts = len(polygon.cumulativeTypeChangeCounts)
if path < num_counts:
return result + polygon.cumulativeTypeChangeCounts[path]
path -= num_counts
result += polygon.cumulativeTypeChangeCounts[num_counts - 1]
return result return result
def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices): def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices):
result_vertex_offset = vertex_offset result_vertex_offset = vertex_offset
result_index_offset = index_offset result_index_offset = index_offset
self._vertex_count = 0
self._element_count = 0 self._element_count = 0
for polygon in self._polygons: for polygon in self._polygons:
polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices) polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices)
result_vertex_offset += polygon.lineMeshVertexCount() result_vertex_offset += polygon.lineMeshVertexCount()
result_index_offset += polygon.lineMeshElementCount() result_index_offset += polygon.lineMeshElementCount()
self._vertex_count += polygon.vertexCount
self._element_count += polygon.elementCount self._element_count += polygon.elementCount
return result_vertex_offset, result_index_offset return result_vertex_offset, result_index_offset

View File

@ -63,7 +63,6 @@ class LayerDataBuilder(MeshBuilder):
feedrates = numpy.empty((vertex_count), numpy.float32) feedrates = numpy.empty((vertex_count), numpy.float32)
extruders = numpy.empty((vertex_count), numpy.float32) extruders = numpy.empty((vertex_count), numpy.float32)
line_types = numpy.empty((vertex_count), numpy.float32) line_types = numpy.empty((vertex_count), numpy.float32)
vertex_indices = numpy.arange(0, vertex_count, 1, dtype = numpy.float32)
vertex_offset = 0 vertex_offset = 0
index_offset = 0 index_offset = 0
@ -110,12 +109,6 @@ class LayerDataBuilder(MeshBuilder):
"value": feedrates, "value": feedrates,
"opengl_name": "a_feedrate", "opengl_name": "a_feedrate",
"opengl_type": "float" "opengl_type": "float"
},
# Can't use glDrawElements to index (due to oversight in (Py)Qt), can't use gl_PrimitiveID (due to legacy support):
"vertex_indices": {
"value": vertex_indices,
"opengl_name": "a_vertex_index",
"opengl_type": "float"
} }
} }

View File

@ -55,14 +55,6 @@ class LayerPolygon:
self._jump_mask = self.__jump_map[self._types] self._jump_mask = self.__jump_map[self._types]
self._jump_count = numpy.sum(self._jump_mask) self._jump_count = numpy.sum(self._jump_mask)
self._cumulative_type_change_counts = numpy.zeros(len(self._types)) # See the comment on the 'cumulativeTypeChangeCounts' property below.
last_type = self.types[0]
current_type_count = 0
for i in range(0, len(self._cumulative_type_change_counts)):
if last_type != self.types[i]:
current_type_count += 1
last_type = self.types[i]
self._cumulative_type_change_counts[i] = current_type_count
self._mesh_line_count = len(self._types) - self._jump_count self._mesh_line_count = len(self._types) - self._jump_count
self._vertex_count = self._mesh_line_count + numpy.sum(self._types[1:] == self._types[:-1]) self._vertex_count = self._mesh_line_count + numpy.sum(self._types[1:] == self._types[:-1])
@ -187,10 +179,6 @@ class LayerPolygon:
def data(self): def data(self):
return self._data return self._data
@property
def vertexCount(self):
return self._vertex_end - self._vertex_begin
@property @property
def elementCount(self): def elementCount(self):
return (self._index_end - self._index_begin) * 2 # The range of vertices multiplied by 2 since each vertex is used twice return (self._index_end - self._index_begin) * 2 # The range of vertices multiplied by 2 since each vertex is used twice
@ -219,17 +207,6 @@ class LayerPolygon:
def jumpCount(self): def jumpCount(self):
return self._jump_count return self._jump_count
@property
def cumulativeTypeChangeCounts(self):
""" This polygon class stores with a vertex the type of the line to the next vertex. However, in other contexts,
other ways of representing this might be more suited to the task (for example, when a vertex can possibly only
have _one_ type, it's unavoidable to duplicate vertices when the type is changed). In such situations it's might
be useful to know how many times the type has changed, in order to keep the various vertex-indices aligned.
:return: The total times the line-type changes from one type to another within this LayerPolygon.
"""
return self._cumulative_type_change_counts
def getNormals(self) -> numpy.ndarray: def getNormals(self) -> numpy.ndarray:
"""Calculate normals for the entire polygon using numpy. """Calculate normals for the entire polygon using numpy.

View File

@ -2,7 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import Qt, QTimer, pyqtProperty, pyqtSignal from PyQt5.QtCore import Qt, QTimer, pyqtProperty, pyqtSignal
from typing import Optional from typing import List, Optional
from UM.Qt.ListModel import ListModel from UM.Qt.ListModel import ListModel
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
@ -11,6 +11,7 @@ from UM.Util import parseBool
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.GlobalStack import GlobalStack from cura.Settings.GlobalStack import GlobalStack
from cura.UltimakerCloud.UltimakerCloudConstants import META_CAPABILITIES # To filter on the printer's capabilities.
class GlobalStacksModel(ListModel): class GlobalStacksModel(ListModel):
@ -42,6 +43,7 @@ class GlobalStacksModel(ListModel):
self._filter_connection_type = None # type: Optional[ConnectionType] self._filter_connection_type = None # type: Optional[ConnectionType]
self._filter_online_only = False self._filter_online_only = False
self._filter_capabilities: List[str] = [] # Required capabilities that all listed printers must have.
# Listen to changes # Listen to changes
CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged) CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
@ -50,8 +52,13 @@ class GlobalStacksModel(ListModel):
self._updateDelayed() self._updateDelayed()
filterConnectionTypeChanged = pyqtSignal() filterConnectionTypeChanged = pyqtSignal()
filterCapabilitiesChanged = pyqtSignal()
filterOnlineOnlyChanged = pyqtSignal()
def setFilterConnectionType(self, new_filter: Optional[ConnectionType]) -> None: def setFilterConnectionType(self, new_filter: Optional[ConnectionType]) -> None:
self._filter_connection_type = new_filter if self._filter_connection_type != new_filter:
self._filter_connection_type = new_filter
self.filterConnectionTypeChanged.emit()
@pyqtProperty(int, fset = setFilterConnectionType, notify = filterConnectionTypeChanged) @pyqtProperty(int, fset = setFilterConnectionType, notify = filterConnectionTypeChanged)
def filterConnectionType(self) -> int: def filterConnectionType(self) -> int:
@ -65,9 +72,10 @@ class GlobalStacksModel(ListModel):
return -1 return -1
return self._filter_connection_type.value return self._filter_connection_type.value
filterOnlineOnlyChanged = pyqtSignal()
def setFilterOnlineOnly(self, new_filter: bool) -> None: def setFilterOnlineOnly(self, new_filter: bool) -> None:
self._filter_online_only = new_filter if self._filter_online_only != new_filter:
self._filter_online_only = new_filter
self.filterOnlineOnlyChanged.emit()
@pyqtProperty(bool, fset = setFilterOnlineOnly, notify = filterOnlineOnlyChanged) @pyqtProperty(bool, fset = setFilterOnlineOnly, notify = filterOnlineOnlyChanged)
def filterOnlineOnly(self) -> bool: def filterOnlineOnly(self) -> bool:
@ -76,6 +84,20 @@ class GlobalStacksModel(ListModel):
""" """
return self._filter_online_only return self._filter_online_only
def setFilterCapabilities(self, new_filter: List[str]) -> None:
if self._filter_capabilities != new_filter:
self._filter_capabilities = new_filter
self.filterCapabilitiesChanged.emit()
@pyqtProperty("QStringList", fset = setFilterCapabilities, notify = filterCapabilitiesChanged)
def filterCapabilities(self) -> List[str]:
"""
Capabilities to require on the list of printers.
Only printers that have all of these capabilities will be shown in this model.
"""
return self._filter_capabilities
def _onContainerChanged(self, container) -> None: def _onContainerChanged(self, container) -> None:
"""Handler for container added/removed events from registry""" """Handler for container added/removed events from registry"""
@ -108,6 +130,10 @@ class GlobalStacksModel(ListModel):
if self._filter_online_only and not is_online: if self._filter_online_only and not is_online:
continue continue
capabilities = set(container_stack.getMetaDataEntry(META_CAPABILITIES, "").split(","))
if set(self._filter_capabilities) - capabilities: # Not all required capabilities are met.
continue
device_name = container_stack.getMetaDataEntry("group_name", container_stack.getName()) device_name = container_stack.getMetaDataEntry("group_name", container_stack.getName())
section_name = "Connected printers" if has_remote_connection else "Preset printers" section_name = "Connected printers" if has_remote_connection else "Preset printers"
section_name = self._catalog.i18nc("@info:title", section_name) section_name = self._catalog.i18nc("@info:title", section_name)

View File

@ -106,11 +106,15 @@ class IntentCategoryModel(ListModel):
for category in available_categories: for category in available_categories:
qualities = IntentModel() qualities = IntentModel()
qualities.setIntentCategory(category) qualities.setIntentCategory(category)
try:
weight = list(IntentCategoryModel._get_translations().keys()).index(category)
except ValueError:
weight = 99
result.append({ result.append({
"name": IntentCategoryModel.translation(category, "name", category), "name": IntentCategoryModel.translation(category, "name", category),
"description": IntentCategoryModel.translation(category, "description", None), "description": IntentCategoryModel.translation(category, "description", None),
"intent_category": category, "intent_category": category,
"weight": list(IntentCategoryModel._get_translations().keys()).index(category), "weight": weight,
"qualities": qualities "qualities": qualities
}) })
result.sort(key = lambda k: k["weight"]) result.sort(key = lambda k: k["weight"])

View File

@ -361,8 +361,15 @@ class QualityManagementModel(ListModel):
"section_name": catalog.i18nc("@label", intent_translations.get(intent_category, {}).get("name", catalog.i18nc("@label", "Unknown"))), "section_name": catalog.i18nc("@label", intent_translations.get(intent_category, {}).get("name", catalog.i18nc("@label", "Unknown"))),
}) })
# Sort by quality_type for each intent category # Sort by quality_type for each intent category
intent_translations_list = list(intent_translations)
result = sorted(result, key = lambda x: (list(intent_translations).index(x["intent_category"]), x["quality_type"])) def getIntentWeight(intent_category):
try:
return intent_translations_list.index(intent_category)
except ValueError:
return 99
result = sorted(result, key = lambda x: (getIntentWeight(x["intent_category"]), x["quality_type"]))
item_list += result item_list += result
# Create quality_changes group items # Create quality_changes group items

View File

@ -1,18 +1,19 @@
# Copyright (c) 2021 Ultimaker B.V. # Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from datetime import datetime
import json
import secrets
from hashlib import sha512
from base64 import b64encode from base64 import b64encode
from typing import Optional from datetime import datetime
import requests from hashlib import sha512
from PyQt5.QtNetwork import QNetworkReply
from UM.i18n import i18nCatalog import secrets
from UM.Logger import Logger from typing import Callable, Optional
import urllib.parse
from cura.OAuth2.Models import AuthenticationResponse, UserProfile, OAuth2Settings from cura.OAuth2.Models import AuthenticationResponse, UserProfile, OAuth2Settings
from UM.i18n import i18nCatalog
from UM.Logger import Logger
from UM.TaskManagement.HttpRequestManager import HttpRequestManager # To download log-in tokens.
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S" TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
@ -30,14 +31,13 @@ class AuthorizationHelpers:
return self._settings return self._settings
def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str) -> "AuthenticationResponse": def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str, callback: Callable[[AuthenticationResponse], None]) -> None:
"""Request the access token from the authorization server. """
Request the access token from the authorization server.
:param authorization_code: The authorization code from the 1st step. :param authorization_code: The authorization code from the 1st step.
:param verification_code: The verification code needed for the PKCE extension. :param verification_code: The verification code needed for the PKCE extension.
:return: An AuthenticationResponse object. :param callback: Once the token has been obtained, this function will be called with the response.
""" """
data = { data = {
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "", "client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
"redirect_uri": self._settings.CALLBACK_URL if self._settings.CALLBACK_URL is not None else "", "redirect_uri": self._settings.CALLBACK_URL if self._settings.CALLBACK_URL is not None else "",
@ -46,18 +46,21 @@ class AuthorizationHelpers:
"code_verifier": verification_code, "code_verifier": verification_code,
"scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "", "scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "",
} }
try: headers = {"Content-type": "application/x-www-form-urlencoded"}
return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore HttpRequestManager.getInstance().post(
except requests.exceptions.ConnectionError as connection_error: self._token_url,
return AuthenticationResponse(success = False, err_message = f"Unable to connect to remote server: {connection_error}") data = urllib.parse.urlencode(data).encode("UTF-8"),
headers_dict = headers,
callback = lambda response: self.parseTokenResponse(response, callback),
error_callback = lambda response, _: self.parseTokenResponse(response, callback)
)
def getAccessTokenUsingRefreshToken(self, refresh_token: str) -> "AuthenticationResponse": def getAccessTokenUsingRefreshToken(self, refresh_token: str, callback: Callable[[AuthenticationResponse], None]) -> None:
"""Request the access token from the authorization server using a refresh token. """
Request the access token from the authorization server using a refresh token.
:param refresh_token: :param refresh_token: A long-lived token used to refresh the authentication token.
:return: An AuthenticationResponse object. :param callback: Once the token has been obtained, this function will be called with the response.
""" """
Logger.log("d", "Refreshing the access token for [%s]", self._settings.OAUTH_SERVER_URL) Logger.log("d", "Refreshing the access token for [%s]", self._settings.OAUTH_SERVER_URL)
data = { data = {
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "", "client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
@ -66,75 +69,99 @@ class AuthorizationHelpers:
"refresh_token": refresh_token, "refresh_token": refresh_token,
"scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "", "scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "",
} }
try: headers = {"Content-type": "application/x-www-form-urlencoded"}
return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore HttpRequestManager.getInstance().post(
except requests.exceptions.ConnectionError: self._token_url,
return AuthenticationResponse(success = False, err_message = "Unable to connect to remote server") data = urllib.parse.urlencode(data).encode("UTF-8"),
except OSError as e: headers_dict = headers,
return AuthenticationResponse(success = False, err_message = "Operating system is unable to set up a secure connection: {err}".format(err = str(e))) callback = lambda response: self.parseTokenResponse(response, callback),
error_callback = lambda response, _: self.parseTokenResponse(response, callback)
)
@staticmethod def parseTokenResponse(self, token_response: QNetworkReply, callback: Callable[[AuthenticationResponse], None]) -> None:
def parseTokenResponse(token_response: requests.models.Response) -> "AuthenticationResponse":
"""Parse the token response from the authorization server into an AuthenticationResponse object. """Parse the token response from the authorization server into an AuthenticationResponse object.
:param token_response: The JSON string data response from the authorization server. :param token_response: The JSON string data response from the authorization server.
:return: An AuthenticationResponse object. :return: An AuthenticationResponse object.
""" """
token_data = HttpRequestManager.readJSON(token_response)
token_data = None
try:
token_data = json.loads(token_response.text)
except ValueError:
Logger.log("w", "Could not parse token response data: %s", token_response.text)
if not token_data: if not token_data:
return AuthenticationResponse(success = False, err_message = catalog.i18nc("@message", "Could not read response.")) callback(AuthenticationResponse(success = False, err_message = catalog.i18nc("@message", "Could not read response.")))
return
if token_response.status_code not in (200, 201): if token_response.error() != QNetworkReply.NetworkError.NoError:
return AuthenticationResponse(success = False, err_message = token_data["error_description"]) callback(AuthenticationResponse(success = False, err_message = token_data["error_description"]))
return
return AuthenticationResponse(success=True, callback(AuthenticationResponse(success = True,
token_type=token_data["token_type"], token_type = token_data["token_type"],
access_token=token_data["access_token"], access_token = token_data["access_token"],
refresh_token=token_data["refresh_token"], refresh_token = token_data["refresh_token"],
expires_in=token_data["expires_in"], expires_in = token_data["expires_in"],
scope=token_data["scope"], scope = token_data["scope"],
received_at=datetime.now().strftime(TOKEN_TIMESTAMP_FORMAT)) received_at = datetime.now().strftime(TOKEN_TIMESTAMP_FORMAT)))
return
def parseJWT(self, access_token: str) -> Optional["UserProfile"]: def checkToken(self, access_token: str, success_callback: Optional[Callable[[UserProfile], None]] = None, failed_callback: Optional[Callable[[], None]] = None) -> None:
"""Calls the authentication API endpoint to get the token data. """Calls the authentication API endpoint to get the token data.
The API is called asynchronously. When a response is given, the callback is called with the user's profile.
:param access_token: The encoded JWT token. :param access_token: The encoded JWT token.
:return: Dict containing some profile data. :param success_callback: When a response is given, this function will be called with a user profile. If None,
there will not be a callback.
:param failed_callback: When the request failed or the response didn't parse, this function will be called.
""" """
check_token_url = "{}/check-token".format(self._settings.OAUTH_SERVER_URL)
try: Logger.log("d", "Checking the access token for [%s]", check_token_url)
check_token_url = "{}/check-token".format(self._settings.OAUTH_SERVER_URL) headers = {
Logger.log("d", "Checking the access token for [%s]", check_token_url) "Authorization": f"Bearer {access_token}"
token_request = requests.get(check_token_url, headers = { }
"Authorization": "Bearer {}".format(access_token) HttpRequestManager.getInstance().get(
}) check_token_url,
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout): headers_dict = headers,
# Connection was suddenly dropped. Nothing we can do about that. callback = lambda reply: self._parseUserProfile(reply, success_callback, failed_callback),
Logger.logException("w", "Something failed while attempting to parse the JWT token") error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None
return None
if token_request.status_code not in (200, 201):
Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text)
return None
user_data = token_request.json().get("data")
if not user_data or not isinstance(user_data, dict):
Logger.log("w", "Could not parse user data from token: %s", user_data)
return None
return UserProfile(
user_id = user_data["user_id"],
username = user_data["username"],
profile_image_url = user_data.get("profile_image_url", ""),
organization_id = user_data.get("organization", {}).get("organization_id"),
subscriptions = user_data.get("subscriptions", [])
) )
def _parseUserProfile(self, reply: QNetworkReply, success_callback: Optional[Callable[[UserProfile], None]], failed_callback: Optional[Callable[[], None]] = None) -> None:
"""
Parses the user profile from a reply to /check-token.
If the response is valid, the callback will be called to return the user profile to the caller.
:param reply: A network reply to a request to the /check-token URL.
:param success_callback: A function to call once a user profile was successfully obtained.
:param failed_callback: A function to call if parsing the profile failed.
"""
if reply.error() != QNetworkReply.NetworkError.NoError:
Logger.warning(f"Could not access account information. QNetworkError {reply.errorString()}")
if failed_callback is not None:
failed_callback()
return
profile_data = HttpRequestManager.getInstance().readJSON(reply)
if profile_data is None or "data" not in profile_data:
Logger.warning("Could not parse user data from token.")
if failed_callback is not None:
failed_callback()
return
profile_data = profile_data["data"]
required_fields = {"user_id", "username"}
if "user_id" not in profile_data or "username" not in profile_data:
Logger.warning(f"User data missing required field(s): {required_fields - set(profile_data.keys())}")
if failed_callback is not None:
failed_callback()
return
if success_callback is not None:
success_callback(UserProfile(
user_id = profile_data["user_id"],
username = profile_data["username"],
profile_image_url = profile_data.get("profile_image_url", ""),
organization_id = profile_data.get("organization", {}).get("organization_id"),
subscriptions = profile_data.get("subscriptions", [])
))
@staticmethod @staticmethod
def generateVerificationCode(code_length: int = 32) -> str: def generateVerificationCode(code_length: int = 32) -> str:
"""Generate a verification code of arbitrary length. """Generate a verification code of arbitrary length.

View File

@ -2,6 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from http.server import BaseHTTPRequestHandler from http.server import BaseHTTPRequestHandler
from threading import Lock # To turn an asynchronous call synchronous.
from typing import Optional, Callable, Tuple, Dict, Any, List, TYPE_CHECKING from typing import Optional, Callable, Tuple, Dict, Any, List, TYPE_CHECKING
from urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse
@ -14,6 +15,7 @@ if TYPE_CHECKING:
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
class AuthorizationRequestHandler(BaseHTTPRequestHandler): class AuthorizationRequestHandler(BaseHTTPRequestHandler):
"""This handler handles all HTTP requests on the local web server. """This handler handles all HTTP requests on the local web server.
@ -24,11 +26,11 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
super().__init__(request, client_address, server) super().__init__(request, client_address, server)
# These values will be injected by the HTTPServer that this handler belongs to. # These values will be injected by the HTTPServer that this handler belongs to.
self.authorization_helpers = None # type: Optional[AuthorizationHelpers] self.authorization_helpers: Optional[AuthorizationHelpers] = None
self.authorization_callback = None # type: Optional[Callable[[AuthenticationResponse], None]] self.authorization_callback: Optional[Callable[[AuthenticationResponse], None]] = None
self.verification_code = None # type: Optional[str] self.verification_code: Optional[str] = None
self.state = None # type: Optional[str] self.state: Optional[str] = None
# CURA-6609: Some browser seems to issue a HEAD instead of GET request as the callback. # CURA-6609: Some browser seems to issue a HEAD instead of GET request as the callback.
def do_HEAD(self) -> None: def do_HEAD(self) -> None:
@ -70,13 +72,23 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
if state != self.state: if state != self.state:
token_response = AuthenticationResponse( token_response = AuthenticationResponse(
success = False, success = False,
err_message=catalog.i18nc("@message", err_message = catalog.i18nc("@message", "The provided state is not correct.")
"The provided state is not correct.")
) )
elif code and self.authorization_helpers is not None and self.verification_code is not None: elif code and self.authorization_helpers is not None and self.verification_code is not None:
token_response = AuthenticationResponse(
success = False,
err_message = catalog.i18nc("@message", "Timeout when authenticating with the account server.")
)
# If the code was returned we get the access token. # If the code was returned we get the access token.
token_response = self.authorization_helpers.getAccessTokenUsingAuthorizationCode( lock = Lock()
code, self.verification_code) lock.acquire()
def callback(response: AuthenticationResponse) -> None:
nonlocal token_response
token_response = response
lock.release()
self.authorization_helpers.getAccessTokenUsingAuthorizationCode(code, self.verification_code, callback)
lock.acquire(timeout = 60) # Block thread until request is completed (which releases the lock). If not acquired, the timeout message stays.
elif self._queryGet(query, "error_code") == "user_denied": elif self._queryGet(query, "error_code") == "user_denied":
# Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog). # Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog).

View File

@ -3,10 +3,9 @@
import json import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Optional, TYPE_CHECKING, Dict from typing import Callable, Dict, Optional, TYPE_CHECKING, Union
from urllib.parse import urlencode, quote_plus from urllib.parse import urlencode, quote_plus
import requests.exceptions
from PyQt5.QtCore import QUrl from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices from PyQt5.QtGui import QDesktopServices
@ -16,7 +15,7 @@ from UM.Signal import Signal
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT
from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer
from cura.OAuth2.Models import AuthenticationResponse from cura.OAuth2.Models import AuthenticationResponse, BaseModel
i18n_catalog = i18nCatalog("cura") i18n_catalog = i18nCatalog("cura")
@ -26,6 +25,7 @@ if TYPE_CHECKING:
MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers" MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers"
class AuthorizationService: class AuthorizationService:
"""The authorization service is responsible for handling the login flow, storing user credentials and providing """The authorization service is responsible for handling the login flow, storing user credentials and providing
account information. account information.
@ -43,12 +43,13 @@ class AuthorizationService:
self._settings = settings self._settings = settings
self._auth_helpers = AuthorizationHelpers(settings) self._auth_helpers = AuthorizationHelpers(settings)
self._auth_url = "{}/authorize".format(self._settings.OAUTH_SERVER_URL) self._auth_url = "{}/authorize".format(self._settings.OAUTH_SERVER_URL)
self._auth_data = None # type: Optional[AuthenticationResponse] self._auth_data: Optional[AuthenticationResponse] = None
self._user_profile = None # type: Optional["UserProfile"] self._user_profile: Optional["UserProfile"] = None
self._preferences = preferences self._preferences = preferences
self._server = LocalAuthorizationServer(self._auth_helpers, self._onAuthStateChanged, daemon=True) self._server = LocalAuthorizationServer(self._auth_helpers, self._onAuthStateChanged, daemon=True)
self._currently_refreshing_token = False # Whether we are currently in the process of refreshing auth. Don't make new requests while busy.
self._unable_to_get_data_message = None # type: Optional[Message] self._unable_to_get_data_message: Optional[Message] = None
self.onAuthStateChanged.connect(self._authChanged) self.onAuthStateChanged.connect(self._authChanged)
@ -62,69 +63,80 @@ class AuthorizationService:
if self._preferences: if self._preferences:
self._preferences.addPreference(self._settings.AUTH_DATA_PREFERENCE_KEY, "{}") self._preferences.addPreference(self._settings.AUTH_DATA_PREFERENCE_KEY, "{}")
def getUserProfile(self) -> Optional["UserProfile"]: def getUserProfile(self, callback: Optional[Callable[[Optional["UserProfile"]], None]] = None) -> None:
"""Get the user profile as obtained from the JWT (JSON Web Token). """
Get the user profile as obtained from the JWT (JSON Web Token).
If the JWT is not yet parsed, calling this will take care of that. If the JWT is not yet checked and parsed, calling this will take care of that.
:param callback: Once the user profile is obtained, this function will be called with the given user profile. If
:return: UserProfile if a user is logged in, None otherwise. the profile fails to be obtained, this function will be called with None.
See also: :py:method:`cura.OAuth2.AuthorizationService.AuthorizationService._parseJWT` See also: :py:method:`cura.OAuth2.AuthorizationService.AuthorizationService._parseJWT`
""" """
if self._user_profile:
# We already obtained the profile. No need to make another request for it.
if callback is not None:
callback(self._user_profile)
return
if not self._user_profile: # If no user profile was stored locally, we try to get it from JWT.
# If no user profile was stored locally, we try to get it from JWT. def store_profile(profile: Optional["UserProfile"]) -> None:
try: if profile is not None:
self._user_profile = self._parseJWT() self._user_profile = profile
except requests.exceptions.ConnectionError: if callback is not None:
# Unable to get connection, can't login. callback(profile)
Logger.logException("w", "Unable to validate user data with the remote server.") elif self._auth_data:
return None # If there is no user profile from the JWT, we have to log in again.
Logger.warning("The user profile could not be loaded. The user must log in again!")
self.deleteAuthData()
if callback is not None:
callback(None)
else:
if callback is not None:
callback(None)
if not self._user_profile and self._auth_data: self._parseJWT(callback = store_profile)
# If there is still no user profile from the JWT, we have to log in again.
Logger.log("w", "The user profile could not be loaded. The user must log in again!")
self.deleteAuthData()
return None
return self._user_profile def _parseJWT(self, callback: Callable[[Optional["UserProfile"]], None]) -> None:
"""
def _parseJWT(self) -> Optional["UserProfile"]: Tries to parse the JWT (JSON Web Token) data, which it does if all the needed data is there.
"""Tries to parse the JWT (JSON Web Token) data, which it does if all the needed data is there. :param callback: A function to call asynchronously once the user profile has been obtained. It will be called
with `None` if it failed to obtain a user profile.
:return: UserProfile if it was able to parse, None otherwise.
""" """
if not self._auth_data or self._auth_data.access_token is None: if not self._auth_data or self._auth_data.access_token is None:
# If no auth data exists, we should always log in again. # If no auth data exists, we should always log in again.
Logger.log("d", "There was no auth data or access token") Logger.debug("There was no auth data or access token")
return None callback(None)
return
try: # When we checked the token we may get a user profile. This callback checks if that is a valid one and tries to refresh the token if it's not.
user_data = self._auth_helpers.parseJWT(self._auth_data.access_token) def check_user_profile(user_profile: Optional["UserProfile"]) -> None:
except AttributeError: if user_profile:
# THis might seem a bit double, but we get crash reports about this (CURA-2N2 in sentry) # If the profile was found, we call it back immediately.
Logger.log("d", "There was no auth data or access token") callback(user_profile)
return None return
# The JWT was expired or invalid and we should request a new one.
if self._auth_data is None or self._auth_data.refresh_token is None:
Logger.warning("There was no refresh token in the auth data.")
callback(None)
return
if user_data: def process_auth_data(auth_data: AuthenticationResponse) -> None:
# If the profile was found, we return it immediately. if auth_data.access_token is None:
return user_data Logger.warning("Unable to use the refresh token to get a new access token.")
# The JWT was expired or invalid and we should request a new one. callback(None)
if self._auth_data.refresh_token is None: return
Logger.log("w", "There was no refresh token in the auth data.") # Ensure it gets stored as otherwise we only have it in memory. The stored refresh token has been
return None # deleted from the server already. Do not store the auth_data if we could not get new auth_data (e.g.
self._auth_data = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token) # due to a network error), since this would cause an infinite loop trying to get new auth-data.
if not self._auth_data or self._auth_data.access_token is None: if auth_data.success:
Logger.log("w", "Unable to use the refresh token to get a new access token.") self._storeAuthData(auth_data)
# The token could not be refreshed using the refresh token. We should login again. self._auth_helpers.checkToken(auth_data.access_token, callback, lambda: callback(None))
return None
# Ensure it gets stored as otherwise we only have it in memory. The stored refresh token has been deleted self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token, process_auth_data)
# from the server already. Do not store the auth_data if we could not get new auth_data (eg due to a
# network error), since this would cause an infinite loop trying to get new auth-data self._auth_helpers.checkToken(self._auth_data.access_token, check_user_profile, lambda: check_user_profile(None))
if self._auth_data.success:
self._storeAuthData(self._auth_data)
return self._auth_helpers.parseJWT(self._auth_data.access_token)
def getAccessToken(self) -> Optional[str]: def getAccessToken(self) -> Optional[str]:
"""Get the access token as provided by the response data.""" """Get the access token as provided by the response data."""
@ -149,13 +161,20 @@ class AuthorizationService:
if self._auth_data is None or self._auth_data.refresh_token is None: if self._auth_data is None or self._auth_data.refresh_token is None:
Logger.log("w", "Unable to refresh access token, since there is no refresh token.") Logger.log("w", "Unable to refresh access token, since there is no refresh token.")
return return
response = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token)
if response.success: def process_auth_data(response: AuthenticationResponse) -> None:
self._storeAuthData(response) if response.success:
self.onAuthStateChanged.emit(logged_in = True) self._storeAuthData(response)
else: self.onAuthStateChanged.emit(logged_in = True)
Logger.log("w", "Failed to get a new access token from the server.") else:
self.onAuthStateChanged.emit(logged_in = False) Logger.warning("Failed to get a new access token from the server.")
self.onAuthStateChanged.emit(logged_in = False)
if self._currently_refreshing_token:
Logger.debug("Was already busy refreshing token. Do not start a new request.")
return
self._currently_refreshing_token = True
self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token, process_auth_data)
def deleteAuthData(self) -> None: def deleteAuthData(self) -> None:
"""Delete the authentication data that we have stored locally (eg; logout)""" """Delete the authentication data that we have stored locally (eg; logout)"""
@ -244,21 +263,23 @@ class AuthorizationService:
preferences_data = json.loads(self._preferences.getValue(self._settings.AUTH_DATA_PREFERENCE_KEY)) preferences_data = json.loads(self._preferences.getValue(self._settings.AUTH_DATA_PREFERENCE_KEY))
if preferences_data: if preferences_data:
self._auth_data = AuthenticationResponse(**preferences_data) self._auth_data = AuthenticationResponse(**preferences_data)
# Also check if we can actually get the user profile information.
user_profile = self.getUserProfile()
if user_profile is not None:
self.onAuthStateChanged.emit(logged_in = True)
Logger.log("d", "Auth data was successfully loaded")
else:
if self._unable_to_get_data_message is not None:
self._unable_to_get_data_message.hide()
self._unable_to_get_data_message = Message(i18n_catalog.i18nc("@info", # Also check if we can actually get the user profile information.
"Unable to reach the Ultimaker account server."), def callback(profile: Optional["UserProfile"]) -> None:
title = i18n_catalog.i18nc("@info:title", "Warning"), if profile is not None:
message_type = Message.MessageType.ERROR) self.onAuthStateChanged.emit(logged_in = True)
Logger.log("w", "Unable to load auth data from preferences") Logger.debug("Auth data was successfully loaded")
self._unable_to_get_data_message.show() else:
if self._unable_to_get_data_message is not None:
self._unable_to_get_data_message.show()
else:
self._unable_to_get_data_message = Message(i18n_catalog.i18nc("@info",
"Unable to reach the Ultimaker account server."),
title = i18n_catalog.i18nc("@info:title", "Log-in failed"),
message_type = Message.MessageType.ERROR)
Logger.warning("Unable to get user profile using auth data from preferences.")
self._unable_to_get_data_message.show()
self.getUserProfile(callback)
except (ValueError, TypeError): except (ValueError, TypeError):
Logger.logException("w", "Could not load auth data from preferences") Logger.logException("w", "Could not load auth data from preferences")
@ -271,8 +292,9 @@ class AuthorizationService:
return return
self._auth_data = auth_data self._auth_data = auth_data
self._currently_refreshing_token = False
if auth_data: if auth_data:
self._user_profile = self.getUserProfile() self.getUserProfile()
self._preferences.setValue(self._settings.AUTH_DATA_PREFERENCE_KEY, json.dumps(auth_data.dump())) self._preferences.setValue(self._settings.AUTH_DATA_PREFERENCE_KEY, json.dumps(auth_data.dump()))
else: else:
Logger.log("d", "Clearing the user profile") Logger.log("d", "Clearing the user profile")

View File

@ -2,9 +2,10 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from typing import Type, TYPE_CHECKING, Optional, List from typing import Type, TYPE_CHECKING, Optional, List
from io import BlockingIOError
import keyring import keyring
from keyring.backend import KeyringBackend from keyring.backend import KeyringBackend
from keyring.errors import NoKeyringError, PasswordSetError, KeyringLocked from keyring.errors import NoKeyringError, PasswordSetError, KeyringLocked, KeyringError
from UM.Logger import Logger from UM.Logger import Logger
@ -44,7 +45,7 @@ class KeyringAttribute:
self._store_secure = False self._store_secure = False
Logger.logException("w", "No keyring backend present") Logger.logException("w", "No keyring backend present")
return getattr(instance, self._name) return getattr(instance, self._name)
except KeyringLocked: except (KeyringLocked, BlockingIOError):
self._store_secure = False self._store_secure = False
Logger.log("i", "Access to the keyring was denied.") Logger.log("i", "Access to the keyring was denied.")
return getattr(instance, self._name) return getattr(instance, self._name)
@ -52,6 +53,10 @@ class KeyringAttribute:
self._store_secure = False self._store_secure = False
Logger.log("w", "The password retrieved from the keyring cannot be used because it contains characters that cannot be decoded.") Logger.log("w", "The password retrieved from the keyring cannot be used because it contains characters that cannot be decoded.")
return getattr(instance, self._name) return getattr(instance, self._name)
except KeyringError:
self._store_secure = False
Logger.logException("w", "Unknown keyring error.")
return getattr(instance, self._name)
else: else:
return getattr(instance, self._name) return getattr(instance, self._name)

View File

@ -72,8 +72,8 @@ class PickingPass(RenderPass):
window_size = self._renderer.getWindowSize() window_size = self._renderer.getWindowSize()
px = (0.5 + x / 2.0) * window_size[0] px = int((0.5 + x / 2.0) * window_size[0])
py = (0.5 + y / 2.0) * window_size[1] py = int((0.5 + y / 2.0) * window_size[1])
if px < 0 or px > (output.width() - 1) or py < 0 or py > (output.height() - 1): if px < 0 or px > (output.width() - 1) or py < 0 or py > (output.height() - 1):
return -1 return -1

View File

@ -42,7 +42,7 @@ class PrintJobOutputModel(QObject):
self._preview_image = None # type: Optional[QImage] self._preview_image = None # type: Optional[QImage]
@pyqtProperty("QStringList", notify=compatibleMachineFamiliesChanged) @pyqtProperty("QStringList", notify=compatibleMachineFamiliesChanged)
def compatibleMachineFamilies(self): def compatibleMachineFamilies(self) -> List[str]:
# Hack; Some versions of cluster will return a family more than once... # Hack; Some versions of cluster will return a family more than once...
return list(set(self._compatible_machine_families)) return list(set(self._compatible_machine_families))
@ -77,11 +77,11 @@ class PrintJobOutputModel(QObject):
self._configuration = configuration self._configuration = configuration
self.configurationChanged.emit() self.configurationChanged.emit()
@pyqtProperty(str, notify=ownerChanged) @pyqtProperty(str, notify = ownerChanged)
def owner(self): def owner(self) -> str:
return self._owner return self._owner
def updateOwner(self, owner): def updateOwner(self, owner: str) -> None:
if self._owner != owner: if self._owner != owner:
self._owner = owner self._owner = owner
self.ownerChanged.emit() self.ownerChanged.emit()
@ -132,7 +132,7 @@ class PrintJobOutputModel(QObject):
@pyqtProperty(float, notify = timeElapsedChanged) @pyqtProperty(float, notify = timeElapsedChanged)
def progress(self) -> float: def progress(self) -> float:
result = float(self.timeElapsed) / max(self.timeTotal, 1.0) # Prevent a division by zero exception. result = float(self.timeElapsed) / max(self.timeTotal, 1.0) # Prevent a division by zero exception.
return min(result, 1.0) # Never get a progress past 1.0 return min(result, 1.0) # Never get a progress past 1.0
@pyqtProperty(str, notify=stateChanged) @pyqtProperty(str, notify=stateChanged)
@ -151,12 +151,12 @@ class PrintJobOutputModel(QObject):
return False return False
return True return True
def updateTimeTotal(self, new_time_total): def updateTimeTotal(self, new_time_total: int) -> None:
if self._time_total != new_time_total: if self._time_total != new_time_total:
self._time_total = new_time_total self._time_total = new_time_total
self.timeTotalChanged.emit() self.timeTotalChanged.emit()
def updateTimeElapsed(self, new_time_elapsed): def updateTimeElapsed(self, new_time_elapsed: int) -> None:
if self._time_elapsed != new_time_elapsed: if self._time_elapsed != new_time_elapsed:
self._time_elapsed = new_time_elapsed self._time_elapsed = new_time_elapsed
self.timeElapsedChanged.emit() self.timeElapsedChanged.emit()

View File

@ -83,6 +83,14 @@ class UploadMaterialsJob(Job):
host_guid = "*", # Required metadata field. Otherwise we get a KeyError. host_guid = "*", # Required metadata field. Otherwise we get a KeyError.
um_cloud_cluster_id = "*" # Required metadata field. Otherwise we get a KeyError. um_cloud_cluster_id = "*" # Required metadata field. Otherwise we get a KeyError.
) )
# Filter out any printer not capable of the 'import_material' capability. Needs FW 7.0.1-RC at the least!
self._printer_metadata = [ printer_data for printer_data in self._printer_metadata if (
UltimakerCloudConstants.META_CAPABILITIES in printer_data and
"import_material" in printer_data[UltimakerCloudConstants.META_CAPABILITIES]
)
]
for printer in self._printer_metadata: for printer in self._printer_metadata:
self._printer_sync_status[printer["host_guid"]] = self.PrinterStatus.UPLOADING.value self._printer_sync_status[printer["host_guid"]] = self.PrinterStatus.UPLOADING.value

View File

@ -12,6 +12,7 @@ from UM.Scene.SceneNode import SceneNode
from UM.Scene.Selection import Selection from UM.Scene.Selection import Selection
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.Settings.ContainerRegistry import ContainerRegistry # Finding containers by ID. from UM.Settings.ContainerRegistry import ContainerRegistry # Finding containers by ID.
from cura.Machines.ContainerTree import ContainerTree
from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING, Union from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING, Union
@ -403,6 +404,32 @@ class ExtruderManager(QObject):
raise IndexError(msg) raise IndexError(msg)
extruder_stack_0.definition = extruder_definition extruder_stack_0.definition = extruder_definition
@pyqtSlot("QVariant", result = bool)
def getExtruderHasQualityForMaterial(self, extruder_stack: "ExtruderStack") -> bool:
"""Checks if quality nodes exist for the variant/material combination."""
application = cura.CuraApplication.CuraApplication.getInstance()
global_stack = application.getGlobalContainerStack()
if not global_stack or not extruder_stack:
return False
if not global_stack.getMetaDataEntry("has_materials"):
return True
machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
active_variant_name = extruder_stack.variant.getMetaDataEntry("name")
if active_variant_name not in machine_node.variants:
Logger.log("w", "Could not find the variant %s", active_variant_name)
return True
active_variant_node = machine_node.variants[active_variant_name]
active_material_node = active_variant_node.materials[extruder_stack.material.getMetaDataEntry("base_file")]
active_material_node_qualities = active_material_node.qualities
if not active_material_node_qualities:
return False
return list(active_material_node_qualities.keys())[0] != "empty_quality"
@pyqtSlot(str, result="QVariant") @pyqtSlot(str, result="QVariant")
def getInstanceExtruderValues(self, key: str) -> List: def getInstanceExtruderValues(self, key: str) -> List:
"""Get all extruder values for a certain setting. """Get all extruder values for a certain setting.

View File

@ -1535,7 +1535,7 @@ class MachineManager(QObject):
machine_node = ContainerTree.getInstance().machines.get(machine_definition_id) machine_node = ContainerTree.getInstance().machines.get(machine_definition_id)
variant_node = machine_node.variants.get(variant_name) variant_node = machine_node.variants.get(variant_name)
if variant_node is None: if variant_node is None:
Logger.error("There is no variant with the name {variant_name}.") Logger.error(f"There is no variant with the name {variant_name}.")
return return
self.setVariant(position, variant_node) self.setVariant(position, variant_node)

View File

@ -3,6 +3,7 @@
import numpy import numpy
from PyQt5 import QtCore from PyQt5 import QtCore
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QImage from PyQt5.QtGui import QImage
from cura.PreviewPass import PreviewPass from cura.PreviewPass import PreviewPass
@ -46,6 +47,7 @@ class Snapshot:
render_width, render_height = (width, height) if active_camera is None else active_camera.getWindowSize() render_width, render_height = (width, height) if active_camera is None else active_camera.getWindowSize()
render_width = int(render_width) render_width = int(render_width)
render_height = int(render_height) render_height = int(render_height)
QCoreApplication.processEvents() # This ensures that the opengl context is correctly available
preview_pass = PreviewPass(render_width, render_height) preview_pass = PreviewPass(render_width, render_height)
root = scene.getRoot() root = scene.getRoot()

View File

@ -1,7 +1,9 @@
# Copyright (c) 2019 Ultimaker B.V. # Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from collections import deque
import os import os
from collections import deque
from typing import TYPE_CHECKING, Optional, List, Dict, Any from typing import TYPE_CHECKING, Optional, List, Dict, Any
from PyQt5.QtCore import QUrl, Qt, pyqtSlot, pyqtProperty, pyqtSignal from PyQt5.QtCore import QUrl, Qt, pyqtSlot, pyqtProperty, pyqtSignal
@ -16,24 +18,23 @@ if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
#
# This is the Qt ListModel that contains all welcome pages data. Each page is a page that can be shown as a step in the
# welcome wizard dialog. Each item in this ListModel represents a page, which contains the following fields:
#
# - id : A unique page_id which can be used in function goToPage(page_id)
# - page_url : The QUrl to the QML file that contains the content of this page
# - next_page_id : (OPTIONAL) The next page ID to go to when this page finished. This is optional. If this is not
# provided, it will go to the page with the current index + 1
# - next_page_button_text: (OPTIONAL) The text to show for the "next" button, by default it's the translated text of
# "Next". Note that each step QML can decide whether to use this text or not, so it's not
# mandatory.
# - should_show_function : (OPTIONAL) An optional function that returns True/False indicating if this page should be
# shown. By default all pages should be shown. If a function returns False, that page will
# be skipped and its next page will be shown.
#
# Note that in any case, a page that has its "should_show_function" == False will ALWAYS be skipped.
#
class WelcomePagesModel(ListModel): class WelcomePagesModel(ListModel):
"""
This is the Qt ListModel that contains all welcome pages data. Each page is a page that can be shown as a step in
the welcome wizard dialog. Each item in this ListModel represents a page, which contains the following fields:
- id : A unique page_id which can be used in function goToPage(page_id)
- page_url : The QUrl to the QML file that contains the content of this page
- next_page_id : (OPTIONAL) The next page ID to go to when this page finished. This is optional. If this is
not provided, it will go to the page with the current index + 1
- next_page_button_text : (OPTIONAL) The text to show for the "next" button, by default it's the translated text of
"Next". Note that each step QML can decide whether to use this text or not, so it's not
mandatory.
- should_show_function : (OPTIONAL) An optional function that returns True/False indicating if this page should be
shown. By default all pages should be shown. If a function returns False, that page will
be skipped and its next page will be shown.
Note that in any case, a page that has its "should_show_function" == False will ALWAYS be skipped.
"""
IdRole = Qt.UserRole + 1 # Page ID IdRole = Qt.UserRole + 1 # Page ID
PageUrlRole = Qt.UserRole + 2 # URL to the page's QML file PageUrlRole = Qt.UserRole + 2 # URL to the page's QML file
@ -55,11 +56,11 @@ class WelcomePagesModel(ListModel):
self._default_next_button_text = self._catalog.i18nc("@action:button", "Next") self._default_next_button_text = self._catalog.i18nc("@action:button", "Next")
self._pages = [] # type: List[Dict[str, Any]] self._pages: List[Dict[str, Any]] = []
self._current_page_index = 0 self._current_page_index = 0
# Store all the previous page indices so it can go back. # Store all the previous page indices so it can go back.
self._previous_page_indices_stack = deque() # type: deque self._previous_page_indices_stack: deque = deque()
# If the welcome flow should be shown. It can show the complete flow or just the changelog depending on the # If the welcome flow should be shown. It can show the complete flow or just the changelog depending on the
# specific case. See initialize() for how this variable is set. # specific case. See initialize() for how this variable is set.
@ -72,17 +73,21 @@ class WelcomePagesModel(ListModel):
def currentPageIndex(self) -> int: def currentPageIndex(self) -> int:
return self._current_page_index return self._current_page_index
# Returns a float number in [0, 1] which indicates the current progress.
@pyqtProperty(float, notify = currentPageIndexChanged) @pyqtProperty(float, notify = currentPageIndexChanged)
def currentProgress(self) -> float: def currentProgress(self) -> float:
"""
Returns a float number in [0, 1] which indicates the current progress.
"""
if len(self._items) == 0: if len(self._items) == 0:
return 0 return 0
else: else:
return self._current_page_index / len(self._items) return self._current_page_index / len(self._items)
# Indicates if the current page is the last page.
@pyqtProperty(bool, notify = currentPageIndexChanged) @pyqtProperty(bool, notify = currentPageIndexChanged)
def isCurrentPageLast(self) -> bool: def isCurrentPageLast(self) -> bool:
"""
Indicates if the current page is the last page.
"""
return self._current_page_index == len(self._items) - 1 return self._current_page_index == len(self._items) - 1
def _setCurrentPageIndex(self, page_index: int) -> None: def _setCurrentPageIndex(self, page_index: int) -> None:
@ -91,17 +96,22 @@ class WelcomePagesModel(ListModel):
self._current_page_index = page_index self._current_page_index = page_index
self.currentPageIndexChanged.emit() self.currentPageIndexChanged.emit()
# Ends the Welcome-Pages. Put as a separate function for cases like the 'decline' in the User-Agreement.
@pyqtSlot() @pyqtSlot()
def atEnd(self) -> None: def atEnd(self) -> None:
"""
Ends the Welcome-Pages. Put as a separate function for cases like the 'decline' in the User-Agreement.
"""
self.allFinished.emit() self.allFinished.emit()
self.resetState() self.resetState()
# Goes to the next page.
# If "from_index" is given, it will look for the next page to show starting from the "from_index" page instead of
# the "self._current_page_index".
@pyqtSlot() @pyqtSlot()
def goToNextPage(self, from_index: Optional[int] = None) -> None: def goToNextPage(self, from_index: Optional[int] = None) -> None:
"""
Goes to the next page.
If "from_index" is given, it will look for the next page to show starting from the "from_index" page instead of
the "self._current_page_index".
"""
# Look for the next page that should be shown # Look for the next page that should be shown
current_index = self._current_page_index if from_index is None else from_index current_index = self._current_page_index if from_index is None else from_index
while True: while True:
@ -137,9 +147,11 @@ class WelcomePagesModel(ListModel):
# Move to the next page # Move to the next page
self._setCurrentPageIndex(next_page_index) self._setCurrentPageIndex(next_page_index)
# Goes to the previous page. If there's no previous page, do nothing.
@pyqtSlot() @pyqtSlot()
def goToPreviousPage(self) -> None: def goToPreviousPage(self) -> None:
"""
Goes to the previous page. If there's no previous page, do nothing.
"""
if len(self._previous_page_indices_stack) == 0: if len(self._previous_page_indices_stack) == 0:
Logger.log("i", "No previous page, do nothing") Logger.log("i", "No previous page, do nothing")
return return
@ -148,9 +160,9 @@ class WelcomePagesModel(ListModel):
self._current_page_index = previous_page_index self._current_page_index = previous_page_index
self.currentPageIndexChanged.emit() self.currentPageIndexChanged.emit()
# Sets the current page to the given page ID. If the page ID is not found, do nothing.
@pyqtSlot(str) @pyqtSlot(str)
def goToPage(self, page_id: str) -> None: def goToPage(self, page_id: str) -> None:
"""Sets the current page to the given page ID. If the page ID is not found, do nothing."""
page_index = self.getPageIndexById(page_id) page_index = self.getPageIndexById(page_id)
if page_index is None: if page_index is None:
# FIXME: If we cannot find the next page, we cannot do anything here. # FIXME: If we cannot find the next page, we cannot do anything here.
@ -165,18 +177,22 @@ class WelcomePagesModel(ListModel):
# Find the next page to show starting from the "page_index" # Find the next page to show starting from the "page_index"
self.goToNextPage(from_index = page_index) self.goToNextPage(from_index = page_index)
# Checks if the page with the given index should be shown by calling the "should_show_function" associated with it.
# If the function is not present, returns True (show page by default).
def _shouldPageBeShown(self, page_index: int) -> bool: def _shouldPageBeShown(self, page_index: int) -> bool:
"""
Checks if the page with the given index should be shown by calling the "should_show_function" associated with
it. If the function is not present, returns True (show page by default).
"""
next_page_item = self.getItem(page_index) next_page_item = self.getItem(page_index)
should_show_function = next_page_item.get("should_show_function", lambda: True) should_show_function = next_page_item.get("should_show_function", lambda: True)
return should_show_function() return should_show_function()
# Resets the state of the WelcomePagesModel. This functions does the following:
# - Resets current_page_index to 0
# - Clears the previous page indices stack
@pyqtSlot() @pyqtSlot()
def resetState(self) -> None: def resetState(self) -> None:
"""
Resets the state of the WelcomePagesModel. This functions does the following:
- Resets current_page_index to 0
- Clears the previous page indices stack
"""
self._current_page_index = 0 self._current_page_index = 0
self._previous_page_indices_stack.clear() self._previous_page_indices_stack.clear()
@ -188,8 +204,8 @@ class WelcomePagesModel(ListModel):
def shouldShowWelcomeFlow(self) -> bool: def shouldShowWelcomeFlow(self) -> bool:
return self._should_show_welcome_flow return self._should_show_welcome_flow
# Gets the page index with the given page ID. If the page ID doesn't exist, returns None.
def getPageIndexById(self, page_id: str) -> Optional[int]: def getPageIndexById(self, page_id: str) -> Optional[int]:
"""Gets the page index with the given page ID. If the page ID doesn't exist, returns None."""
page_idx = None page_idx = None
for idx, page_item in enumerate(self._items): for idx, page_item in enumerate(self._items):
if page_item["id"] == page_id: if page_item["id"] == page_id:
@ -197,8 +213,9 @@ class WelcomePagesModel(ListModel):
break break
return page_idx return page_idx
# Convenience function to get QUrl path to pages that's located in "resources/qml/WelcomePages". @staticmethod
def _getBuiltinWelcomePagePath(self, page_filename: str) -> "QUrl": def _getBuiltinWelcomePagePath(page_filename: str) -> QUrl:
"""Convenience function to get QUrl path to pages that's located in "resources/qml/WelcomePages"."""
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles,
os.path.join("WelcomePages", page_filename))) os.path.join("WelcomePages", page_filename)))
@ -213,21 +230,22 @@ class WelcomePagesModel(ListModel):
self._initialize() self._initialize()
def _initialize(self, update_should_show_flag: bool = True) -> None: def _initialize(self, update_should_show_flag: bool = True) -> None:
show_whatsnew_only = False show_whats_new_only = False
if update_should_show_flag: if update_should_show_flag:
has_active_machine = self._application.getMachineManager().activeMachine is not None has_active_machine = self._application.getMachineManager().activeMachine is not None
has_app_just_upgraded = self._application.hasJustUpdatedFromOldVersion() has_app_just_upgraded = self._application.hasJustUpdatedFromOldVersion()
# Only show the what's new dialog if there's no machine and we have just upgraded # Only show the what's new dialog if there's no machine and we have just upgraded
show_complete_flow = not has_active_machine show_complete_flow = not has_active_machine
show_whatsnew_only = has_active_machine and has_app_just_upgraded show_whats_new_only = has_active_machine and has_app_just_upgraded
# FIXME: This is a hack. Because of the circular dependency between MachineManager, ExtruderManager, and # FIXME: This is a hack. Because of the circular dependency between MachineManager, ExtruderManager, and
# possibly some others, setting the initial active machine is not done when the MachineManager gets initialized. # possibly some others, setting the initial active machine is not done when the MachineManager gets
# So at this point, we don't know if there will be an active machine or not. It could be that the active machine # initialized. So at this point, we don't know if there will be an active machine or not. It could be that
# files are corrupted so we cannot rely on Preferences either. This makes sure that once the active machine # the active machine files are corrupted so we cannot rely on Preferences either. This makes sure that once
# gets changed, this model updates the flags, so it can decide whether to show the welcome flow or not. # the active machine gets changed, this model updates the flags, so it can decide whether to show the
should_show_welcome_flow = show_complete_flow or show_whatsnew_only # welcome flow or not.
should_show_welcome_flow = show_complete_flow or show_whats_new_only
if should_show_welcome_flow != self._should_show_welcome_flow: if should_show_welcome_flow != self._should_show_welcome_flow:
self._should_show_welcome_flow = should_show_welcome_flow self._should_show_welcome_flow = should_show_welcome_flow
self.shouldShowWelcomeFlowChanged.emit() self.shouldShowWelcomeFlowChanged.emit()
@ -274,23 +292,25 @@ class WelcomePagesModel(ListModel):
] ]
pages_to_show = all_pages_list pages_to_show = all_pages_list
if show_whatsnew_only: if show_whats_new_only:
pages_to_show = list(filter(lambda x: x["id"] == "whats_new", all_pages_list)) pages_to_show = list(filter(lambda x: x["id"] == "whats_new", all_pages_list))
self._pages = pages_to_show self._pages = pages_to_show
self.setItems(self._pages) self.setItems(self._pages)
# For convenience, inject the default "next" button text to each item if it's not present.
def setItems(self, items: List[Dict[str, Any]]) -> None: def setItems(self, items: List[Dict[str, Any]]) -> None:
# For convenience, inject the default "next" button text to each item if it's not present.
for item in items: for item in items:
if "next_page_button_text" not in item: if "next_page_button_text" not in item:
item["next_page_button_text"] = self._default_next_button_text item["next_page_button_text"] = self._default_next_button_text
super().setItems(items) super().setItems(items)
# Indicates if the machine action panel should be shown by checking if there's any first start machine actions
# available.
def shouldShowMachineActions(self) -> bool: def shouldShowMachineActions(self) -> bool:
"""
Indicates if the machine action panel should be shown by checking if there's any first start machine actions
available.
"""
global_stack = self._application.getMachineManager().activeMachine global_stack = self._application.getMachineManager().activeMachine
if global_stack is None: if global_stack is None:
return False return False
@ -312,6 +332,3 @@ class WelcomePagesModel(ListModel):
def addPage(self) -> None: def addPage(self) -> None:
pass pass
__all__ = ["WelcomePagesModel"]

View File

@ -1,27 +1,39 @@
# Copyright (c) 2021 Ultimaker B.V. # Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from .WelcomePagesModel import WelcomePagesModel
import os import os
from typing import Optional, Dict, List, Tuple from typing import Optional, Dict, List, Tuple, TYPE_CHECKING
from PyQt5.QtCore import pyqtProperty, pyqtSlot from PyQt5.QtCore import pyqtProperty, pyqtSlot
from UM.Logger import Logger from UM.Logger import Logger
from UM.Resources import Resources from UM.Resources import Resources
# from cura.UI.WelcomePagesModel import WelcomePagesModel
# This Qt ListModel is more or less the same the WelcomePagesModel, except that this model is only for showing the
# "what's new" page. This is also used in the "Help" menu to show the changes log. if TYPE_CHECKING:
# from PyQt5.QtCore import QObject
from cura.CuraApplication import CuraApplication
class WhatsNewPagesModel(WelcomePagesModel): class WhatsNewPagesModel(WelcomePagesModel):
"""
This Qt ListModel is more or less the same the WelcomePagesModel, except that this model is only for showing the
"what's new" page. This is also used in the "Help" menu to show the changes log.
"""
image_formats = [".png", ".jpg", ".jpeg", ".gif", ".svg"] image_formats = [".png", ".jpg", ".jpeg", ".gif", ".svg"]
text_formats = [".txt", ".htm", ".html"] text_formats = [".txt", ".htm", ".html"]
image_key = "image" image_key = "image"
text_key = "text" text_key = "text"
def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
super().__init__(application, parent)
self._subpages: List[Dict[str, Optional[str]]] = []
@staticmethod @staticmethod
def _collectOrdinalFiles(resource_type: int, include: List[str]) -> Tuple[Dict[int, str], int]: def _collectOrdinalFiles(resource_type: int, include: List[str]) -> Tuple[Dict[int, str], int]:
result = {} #type: Dict[int, str] result = {} # type: Dict[int, str]
highest = -1 highest = -1
try: try:
folder_path = Resources.getPath(resource_type, "whats_new") folder_path = Resources.getPath(resource_type, "whats_new")
@ -65,7 +77,7 @@ class WhatsNewPagesModel(WelcomePagesModel):
texts, max_text = WhatsNewPagesModel._collectOrdinalFiles(Resources.Texts, WhatsNewPagesModel.text_formats) texts, max_text = WhatsNewPagesModel._collectOrdinalFiles(Resources.Texts, WhatsNewPagesModel.text_formats)
highest = max(max_image, max_text) highest = max(max_image, max_text)
self._subpages = [] #type: List[Dict[str, Optional[str]]] self._subpages = []
for n in range(0, highest + 1): for n in range(0, highest + 1):
self._subpages.append({ self._subpages.append({
WhatsNewPagesModel.image_key: None if n not in images else images[n], WhatsNewPagesModel.image_key: None if n not in images else images[n],
@ -93,5 +105,3 @@ class WhatsNewPagesModel(WelcomePagesModel):
def getSubpageText(self, page: int) -> str: def getSubpageText(self, page: int) -> str:
result = self._getSubpageItem(page, WhatsNewPagesModel.text_key) result = self._getSubpageItem(page, WhatsNewPagesModel.text_key)
return result if result else "* * *" return result if result else "* * *"
__all__ = ["WhatsNewPagesModel"]

View File

@ -57,6 +57,7 @@ class CloudMaterialSync(QObject):
self.sync_all_dialog.setProperty("syncModel", self) self.sync_all_dialog.setProperty("syncModel", self)
self.sync_all_dialog.setProperty("pageIndex", 0) # Return to first page. self.sync_all_dialog.setProperty("pageIndex", 0) # Return to first page.
self.sync_all_dialog.setProperty("hasExportedUsb", False) # If the user exported USB before, reset that page. self.sync_all_dialog.setProperty("hasExportedUsb", False) # If the user exported USB before, reset that page.
self.sync_all_dialog.setProperty("syncStatusText", "") # Reset any previous error messages.
self.sync_all_dialog.show() self.sync_all_dialog.show()
def _showSyncNewMaterialsMessage(self) -> None: def _showSyncNewMaterialsMessage(self) -> None:

View File

@ -13,6 +13,9 @@ DEFAULT_DIGITAL_FACTORY_URL = "https://digitalfactory.ultimaker.com" # type: st
META_UM_LINKED_TO_ACCOUNT = "um_linked_to_account" META_UM_LINKED_TO_ACCOUNT = "um_linked_to_account"
"""(bool) Whether a cloud printer is linked to an Ultimaker account""" """(bool) Whether a cloud printer is linked to an Ultimaker account"""
META_CAPABILITIES = "capabilities"
"""(list[str]) a list of capabilities this printer supports"""
try: try:
from cura.CuraVersion import CuraCloudAPIRoot # type: ignore from cura.CuraVersion import CuraCloudAPIRoot # type: ignore
if CuraCloudAPIRoot == "": if CuraCloudAPIRoot == "":

View File

@ -49,7 +49,9 @@ _ignored_machine_network_metadata = {
"removal_warning", "removal_warning",
"group_name", "group_name",
"group_size", "group_size",
"connection_type" "connection_type",
"capabilities",
"octoprint_api_key",
} # type: Set[str] } # type: Set[str]

View File

@ -32,6 +32,12 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
Logger.error("3MF Writer class is unavailable. Can't write workspace.") Logger.error("3MF Writer class is unavailable. Can't write workspace.")
return False return False
global_stack = machine_manager.activeMachine
if global_stack is None:
self.setInformation(catalog.i18nc("@error", "There is no workspace yet to write. Please add a printer first."))
Logger.error("Tried to write a 3MF workspace before there was a global stack.")
return False
# Indicate that the 3mf mesh writer should not close the archive just yet (we still need to add stuff to it). # Indicate that the 3mf mesh writer should not close the archive just yet (we still need to add stuff to it).
mesh_writer.setStoreArchive(True) mesh_writer.setStoreArchive(True)
mesh_writer.write(stream, nodes, mode) mesh_writer.write(stream, nodes, mode)
@ -40,7 +46,6 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
if archive is None: # This happens if there was no mesh data to write. if archive is None: # This happens if there was no mesh data to write.
archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED) archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED)
global_stack = machine_manager.activeMachine
try: try:
# Add global container stack data to the archive. # Add global container stack data to the archive.
@ -149,7 +154,8 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
"group_name", "group_name",
"group_size", "group_size",
"connection_type", "connection_type",
"octoprint_api_key" "capabilities",
"octoprint_api_key",
} }
serialized_data = container.serialize(ignored_metadata_keys = ignore_keys) serialized_data = container.serialize(ignored_metadata_keys = ignore_keys)

View File

@ -10,6 +10,10 @@ from UM.Application import Application
from UM.Scene.SceneNode import SceneNode from UM.Scene.SceneNode import SceneNode
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.Utils.Threading import call_on_qt_thread
from cura.Snapshot import Snapshot
from PyQt5.QtCore import QBuffer
import Savitar import Savitar
@ -149,6 +153,22 @@ class ThreeMFWriter(MeshWriter):
relations_element = ET.Element("Relationships", xmlns = self._namespaces["relationships"]) relations_element = ET.Element("Relationships", xmlns = self._namespaces["relationships"])
model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/3D/3dmodel.model", Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel") model_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/3D/3dmodel.model", Id = "rel0", Type = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel")
# Attempt to add a thumbnail
snapshot = self._createSnapshot()
if snapshot:
thumbnail_buffer = QBuffer()
thumbnail_buffer.open(QBuffer.ReadWrite)
snapshot.save(thumbnail_buffer, "PNG")
thumbnail_file = zipfile.ZipInfo("Metadata/thumbnail.png")
# Don't try to compress snapshot file, because the PNG is pretty much as compact as it will get
archive.writestr(thumbnail_file, thumbnail_buffer.data())
# Add PNG to content types file
thumbnail_type = ET.SubElement(content_types, "Default", Extension = "png", ContentType = "image/png")
# Add thumbnail relation to _rels/.rels file
thumbnail_relation_element = ET.SubElement(relations_element, "Relationship", Target = "/Metadata/thumbnail.png", Id = "rel1", Type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail")
savitar_scene = Savitar.Scene() savitar_scene = Savitar.Scene()
metadata_to_store = CuraApplication.getInstance().getController().getScene().getMetaData() metadata_to_store = CuraApplication.getInstance().getController().getScene().getMetaData()
@ -212,3 +232,17 @@ class ThreeMFWriter(MeshWriter):
self._archive = archive self._archive = archive
return True return True
@call_on_qt_thread # must be called from the main thread because of OpenGL
def _createSnapshot(self):
Logger.log("d", "Creating thumbnail image...")
if not CuraApplication.getInstance().isVisible:
Logger.log("w", "Can't create snapshot when renderer not initialized.")
return None
try:
snapshot = Snapshot.snapshot(width = 300, height = 300)
except:
Logger.logException("w", "Failed to create snapshot image")
return None
return snapshot

View File

@ -261,7 +261,10 @@ class DigitalFactoryController(QObject):
""" """
Error function, called whenever the retrieval of the files in a library project fails. Error function, called whenever the retrieval of the files in a library project fails.
""" """
Logger.log("w", "Failed to retrieve the list of files in project '{}' from the Digital Library".format(self._project_model._projects[self._selected_project_idx])) try:
Logger.warning(f"Failed to retrieve the list of files in project '{self._project_model._projects[self._selected_project_idx]}' from the Digital Library")
except IndexError:
Logger.warning(f"Failed to retrieve the list of files in a project from the Digital Library. And failed to get the project too.")
self.setRetrievingFilesStatus(RetrievalStatus.Failed) self.setRetrievingFilesStatus(RetrievalStatus.Failed)
@pyqtSlot() @pyqtSlot()

View File

@ -1,4 +1,4 @@
# Copyright (c) 2020 Ultimaker B.V. # Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from UM.Math.Color import Color from UM.Math.Color import Color
@ -142,7 +142,6 @@ class SimulationPass(RenderPass):
if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())): if self._layer_view._current_layer_num > -1 and ((not self._layer_view._only_show_top_layers) or (not self._layer_view.getCompatibilityMode())):
start = 0 start = 0
end = 0 end = 0
current_polygon_offset = 0
element_counts = layer_data.getElementCounts() element_counts = layer_data.getElementCounts()
for layer in sorted(element_counts.keys()): for layer in sorted(element_counts.keys()):
# In the current layer, we show just the indicated paths # In the current layer, we show just the indicated paths
@ -156,26 +155,18 @@ class SimulationPass(RenderPass):
if index >= polygon.data.size // 3 - offset: if index >= polygon.data.size // 3 - offset:
index -= polygon.data.size // 3 - offset index -= polygon.data.size // 3 - offset
offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon offset = 1 # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon
current_polygon_offset += 1
continue continue
# The head position is calculated and translated # The head position is calculated and translated
head_position = Vector(polygon.data[index+offset][0], polygon.data[index+offset][1], polygon.data[index+offset][2]) + node.getWorldPosition() head_position = Vector(polygon.data[index+offset][0], polygon.data[index+offset][1], polygon.data[index+offset][2]) + node.getWorldPosition()
break break
break break
end += layer_data.getLayer(layer).vertexCount if self._layer_view._minimum_layer_num > layer:
if layer < self._layer_view._minimum_layer_num: start += element_counts[layer]
start = end end += element_counts[layer]
# Calculate the range of paths in the last layer. -- The type-change count is needed to keep the # Calculate the range of paths in the last layer
# vertex-indices aligned between the two different ways we represent polygons here.
# Since there is one type per line, that could give a vertex two different types, if it's a vertex
# where a type-chage occurs. However, the shader expects vertices to have only one type. In order to
# fix this, those vertices are duplicated. This introduces a discrepancy that we have to take into
# account, which is done by the type-change-count.
layer = layer_data.getLayer(self._layer_view._current_layer_num)
type_change_count = 0 if layer is None else layer.lineMeshCumulativeTypeChangeCount(max(self._layer_view._current_path_num - 1, 0))
current_layer_start = end current_layer_start = end
current_layer_end = current_layer_start + self._layer_view._current_path_num + current_polygon_offset + type_change_count current_layer_end = end + self._layer_view._current_path_num * 2 # Because each point is used twice
# This uses glDrawRangeElements internally to only draw a certain range of lines. # This uses glDrawRangeElements internally to only draw a certain range of lines.
# All the layers but the current selected layer are rendered first # All the layers but the current selected layer are rendered first

View File

@ -13,11 +13,9 @@ vertex =
attribute highp vec4 a_vertex; attribute highp vec4 a_vertex;
attribute lowp vec4 a_color; attribute lowp vec4 a_color;
attribute lowp vec4 a_material_color; attribute lowp vec4 a_material_color;
attribute highp float a_vertex_index;
varying lowp vec4 v_color; varying lowp vec4 v_color;
varying float v_line_type; varying float v_line_type;
varying highp float v_vertex_index;
void main() void main()
{ {
@ -30,7 +28,6 @@ vertex =
} }
v_line_type = a_line_type; v_line_type = a_line_type;
v_vertex_index = a_vertex_index;
} }
fragment = fragment =
@ -43,21 +40,14 @@ fragment =
#endif // GL_ES #endif // GL_ES
varying lowp vec4 v_color; varying lowp vec4 v_color;
varying float v_line_type; varying float v_line_type;
varying highp float v_vertex_index;
uniform int u_show_travel_moves; uniform int u_show_travel_moves;
uniform int u_show_helpers; uniform int u_show_helpers;
uniform int u_show_skin; uniform int u_show_skin;
uniform int u_show_infill; uniform int u_show_infill;
uniform highp vec2 u_drawRange;
void main() void main()
{ {
if (u_drawRange.x >= 0.0 && u_drawRange.y >= 0.0 && (v_vertex_index < u_drawRange.x || v_vertex_index > u_drawRange.y))
{
discard;
}
if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9
// discard movements // discard movements
discard; discard;
@ -87,6 +77,77 @@ fragment =
gl_FragColor = v_color; gl_FragColor = v_color;
} }
vertex41core =
#version 410
uniform highp mat4 u_modelMatrix;
uniform highp mat4 u_viewMatrix;
uniform highp mat4 u_projectionMatrix;
uniform lowp float u_active_extruder;
uniform lowp float u_shade_factor;
uniform highp int u_layer_view_type;
in highp float a_extruder;
in highp float a_line_type;
in highp vec4 a_vertex;
in lowp vec4 a_color;
in lowp vec4 a_material_color;
out lowp vec4 v_color;
out float v_line_type;
void main()
{
gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
v_color = a_color;
if ((a_line_type != 8) && (a_line_type != 9)) {
v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a);
}
v_line_type = a_line_type;
}
fragment41core =
#version 410
in lowp vec4 v_color;
in float v_line_type;
out vec4 frag_color;
uniform int u_show_travel_moves;
uniform int u_show_helpers;
uniform int u_show_skin;
uniform int u_show_infill;
void main()
{
if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9
// discard movements
discard;
}
// helpers: 4, 5, 7, 10
if ((u_show_helpers == 0) && (
((v_line_type >= 3.5) && (v_line_type <= 4.5)) ||
((v_line_type >= 6.5) && (v_line_type <= 7.5)) ||
((v_line_type >= 9.5) && (v_line_type <= 10.5)) ||
((v_line_type >= 4.5) && (v_line_type <= 5.5))
)) {
discard;
}
// skin: 1, 2, 3
if ((u_show_skin == 0) && (
(v_line_type >= 0.5) && (v_line_type <= 3.5)
)) {
discard;
}
// infill:
if ((u_show_infill == 0) && (v_line_type >= 5.5) && (v_line_type <= 6.5)) {
// discard movements
discard;
}
frag_color = v_color;
}
[defaults] [defaults]
u_active_extruder = 0.0 u_active_extruder = 0.0
u_shade_factor = 0.60 u_shade_factor = 0.60
@ -98,13 +159,10 @@ u_show_helpers = 1
u_show_skin = 1 u_show_skin = 1
u_show_infill = 1 u_show_infill = 1
u_drawRange = [-1.0, -1.0]
[bindings] [bindings]
u_modelMatrix = model_matrix u_modelMatrix = model_matrix
u_viewMatrix = view_matrix u_viewMatrix = view_matrix
u_projectionMatrix = projection_matrix u_projectionMatrix = projection_matrix
u_drawRange = draw_range
[attributes] [attributes]
a_vertex = vertex a_vertex = vertex
@ -112,4 +170,3 @@ a_color = color
a_extruder = extruder a_extruder = extruder
a_line_type = line_type a_line_type = line_type
a_material_color = material_color a_material_color = material_color
a_vertex_index = vertex_index

View File

@ -27,7 +27,6 @@ vertex41core =
in highp float a_extruder; in highp float a_extruder;
in highp float a_prev_line_type; in highp float a_prev_line_type;
in highp float a_line_type; in highp float a_line_type;
in highp float a_vertex_index;
in highp float a_feedrate; in highp float a_feedrate;
in highp float a_thickness; in highp float a_thickness;
@ -38,9 +37,8 @@ vertex41core =
out lowp vec2 v_line_dim; out lowp vec2 v_line_dim;
out highp int v_extruder; out highp int v_extruder;
out highp mat4 v_extruder_opacity; out highp mat4 v_extruder_opacity;
out highp float v_prev_line_type; out float v_prev_line_type;
out highp float v_line_type; out float v_line_type;
out highp float v_index;
out lowp vec4 f_color; out lowp vec4 f_color;
out highp vec3 f_vertex; out highp vec3 f_vertex;
@ -58,12 +56,12 @@ vertex41core =
value = (abs_value - min_value) / (max_value - min_value); value = (abs_value - min_value) / (max_value - min_value);
} }
float red = value; float red = value;
float green = 1-abs(1-4*value); float green = 1.0 - abs(1.0 - 4.0 * value);
if (value > 0.375) if (value > 0.375)
{ {
green = 0.5; green = 0.5;
} }
float blue = max(1-4*value, 0); float blue = max(1.0 - 4.0 * value, 0.0);
return vec4(red, green, blue, 1.0); return vec4(red, green, blue, 1.0);
} }
@ -78,7 +76,7 @@ vertex41core =
{ {
value = (abs_value - min_value) / (max_value - min_value); value = (abs_value - min_value) / (max_value - min_value);
} }
float red = min(max(4*value-2, 0), 1); float red = min(max(4.0 * value - 2.0, 0.0), 1.0);
float green = min(1.5*value, 0.75); float green = min(1.5*value, 0.75);
if (value > 0.75) if (value > 0.75)
{ {
@ -100,18 +98,18 @@ vertex41core =
value = (abs_value - min_value) / (max_value - min_value); value = (abs_value - min_value) / (max_value - min_value);
} }
float red = value; float red = value;
float green = 1 - abs(1 - 4 * value); float green = 1.0 - abs(1.0 - 4.0 * value);
if(value > 0.375) if(value > 0.375)
{ {
green = 0.5; green = 0.5;
} }
float blue = max(1 - 4 * value, 0); float blue = max(1.0 - 4.0 * value, 0.0);
return vec4(red, green, blue, 1.0); return vec4(red, green, blue, 1.0);
} }
float clamp(float v) float clamp(float v)
{ {
float t = v < 0 ? 0 : v; float t = v < 0.0 ? 0.0 : v;
return t > 1.0 ? 1.0 : t; return t > 1.0 ? 1.0 : t;
} }
@ -170,7 +168,6 @@ vertex41core =
v_extruder = int(a_extruder); v_extruder = int(a_extruder);
v_prev_line_type = a_prev_line_type; v_prev_line_type = a_prev_line_type;
v_line_type = a_line_type; v_line_type = a_line_type;
v_index = a_vertex_index;
v_extruder_opacity = u_extruder_opacity; v_extruder_opacity = u_extruder_opacity;
// for testing without geometry shader // for testing without geometry shader
@ -194,8 +191,6 @@ geometry41core =
uniform int u_show_infill; uniform int u_show_infill;
uniform int u_show_starts; uniform int u_show_starts;
uniform highp vec2 u_drawRange;
layout(lines) in; layout(lines) in;
layout(triangle_strip, max_vertices = 40) out; layout(triangle_strip, max_vertices = 40) out;
@ -207,7 +202,6 @@ geometry41core =
in mat4 v_extruder_opacity[]; in mat4 v_extruder_opacity[];
in float v_prev_line_type[]; in float v_prev_line_type[];
in float v_line_type[]; in float v_line_type[];
in float v_index[];
out vec4 f_color; out vec4 f_color;
out vec3 f_normal; out vec3 f_normal;
@ -237,10 +231,6 @@ geometry41core =
float size_x; float size_x;
float size_y; float size_y;
if (u_drawRange[0] >= 0.0 && u_drawRange[1] >= 0.0 && (v_index[0] < u_drawRange[0] || v_index[0] >= u_drawRange[1]))
{
return;
}
if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) {
return; return;
} }
@ -437,15 +427,12 @@ u_max_feedrate = 1
u_min_thickness = 0 u_min_thickness = 0
u_max_thickness = 1 u_max_thickness = 1
u_drawRange = [-1.0, -1.0]
[bindings] [bindings]
u_modelMatrix = model_matrix u_modelMatrix = model_matrix
u_viewMatrix = view_matrix u_viewMatrix = view_matrix
u_projectionMatrix = projection_matrix u_projectionMatrix = projection_matrix
u_normalMatrix = normal_matrix u_normalMatrix = normal_matrix
u_lightPosition = light_0_position u_lightPosition = light_0_position
u_drawRange = draw_range
[attributes] [attributes]
a_vertex = vertex a_vertex = vertex
@ -458,4 +445,3 @@ a_prev_line_type = prev_line_type
a_line_type = line_type a_line_type = line_type
a_feedrate = feedrate a_feedrate = feedrate
a_thickness = thickness a_thickness = thickness
a_vertex_index = vertex_index

View File

@ -18,7 +18,6 @@ vertex41core =
in highp vec2 a_line_dim; // line width and thickness in highp vec2 a_line_dim; // line width and thickness
in highp float a_extruder; in highp float a_extruder;
in highp float a_line_type; in highp float a_line_type;
in highp float a_vertex_index;
out lowp vec4 v_color; out lowp vec4 v_color;
@ -27,8 +26,7 @@ vertex41core =
out lowp vec2 v_line_dim; out lowp vec2 v_line_dim;
out highp int v_extruder; out highp int v_extruder;
out highp mat4 v_extruder_opacity; out highp mat4 v_extruder_opacity;
out highp float v_line_type; out float v_line_type;
out highp float v_index;
out lowp vec4 f_color; out lowp vec4 f_color;
out highp vec3 f_vertex; out highp vec3 f_vertex;
@ -49,7 +47,6 @@ vertex41core =
v_line_dim = a_line_dim; v_line_dim = a_line_dim;
v_extruder = int(a_extruder); v_extruder = int(a_extruder);
v_line_type = a_line_type; v_line_type = a_line_type;
v_index = a_vertex_index;
v_extruder_opacity = u_extruder_opacity; v_extruder_opacity = u_extruder_opacity;
// for testing without geometry shader // for testing without geometry shader
@ -70,8 +67,6 @@ geometry41core =
uniform int u_show_skin; uniform int u_show_skin;
uniform int u_show_infill; uniform int u_show_infill;
uniform highp vec2 u_drawRange;
layout(lines) in; layout(lines) in;
layout(triangle_strip, max_vertices = 26) out; layout(triangle_strip, max_vertices = 26) out;
@ -82,7 +77,6 @@ geometry41core =
in int v_extruder[]; in int v_extruder[];
in mat4 v_extruder_opacity[]; in mat4 v_extruder_opacity[];
in float v_line_type[]; in float v_line_type[];
in float v_index[];
out vec4 f_color; out vec4 f_color;
out vec3 f_normal; out vec3 f_normal;
@ -112,10 +106,6 @@ geometry41core =
float size_x; float size_x;
float size_y; float size_y;
if (u_drawRange[0] >= 0.0 && u_drawRange[1] >= 0.0 && (v_index[0] < u_drawRange[0] || v_index[0] >= u_drawRange[1]))
{
return;
}
if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { if ((v_extruder_opacity[0][int(mod(v_extruder[0], 4))][v_extruder[0] / 4] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) {
return; return;
} }
@ -278,15 +268,12 @@ u_show_helpers = 1
u_show_skin = 1 u_show_skin = 1
u_show_infill = 1 u_show_infill = 1
u_drawRange = [-1.0, -1.0]
[bindings] [bindings]
u_modelMatrix = model_matrix u_modelMatrix = model_matrix
u_viewMatrix = view_matrix u_viewMatrix = view_matrix
u_projectionMatrix = projection_matrix u_projectionMatrix = projection_matrix
u_normalMatrix = normal_matrix u_normalMatrix = normal_matrix
u_lightPosition = light_0_position u_lightPosition = light_0_position
u_drawRange = draw_range
[attributes] [attributes]
a_vertex = vertex a_vertex = vertex
@ -297,4 +284,3 @@ a_line_dim = line_dim
a_extruder = extruder a_extruder = extruder
a_material_color = material_color a_material_color = material_color
a_line_type = line_type a_line_type = line_type
a_vertex_index = vertex_index

View File

@ -13,11 +13,9 @@ vertex =
attribute highp vec4 a_vertex; attribute highp vec4 a_vertex;
attribute lowp vec4 a_color; attribute lowp vec4 a_color;
attribute lowp vec4 a_material_color; attribute lowp vec4 a_material_color;
attribute highp float a_vertex_index;
varying lowp vec4 v_color; varying lowp vec4 v_color;
varying float v_line_type; varying float v_line_type;
varying highp float v_vertex_index;
void main() void main()
{ {
@ -30,7 +28,6 @@ vertex =
// } // }
v_line_type = a_line_type; v_line_type = a_line_type;
v_vertex_index = a_vertex_index;
} }
fragment = fragment =
@ -43,21 +40,14 @@ fragment =
#endif // GL_ES #endif // GL_ES
varying lowp vec4 v_color; varying lowp vec4 v_color;
varying float v_line_type; varying float v_line_type;
varying highp float v_vertex_index;
uniform int u_show_travel_moves; uniform int u_show_travel_moves;
uniform int u_show_helpers; uniform int u_show_helpers;
uniform int u_show_skin; uniform int u_show_skin;
uniform int u_show_infill; uniform int u_show_infill;
uniform highp vec2 u_drawRange;
void main() void main()
{ {
if (u_drawRange.x >= 0.0 && u_drawRange.y >= 0.0 && (v_vertex_index < u_drawRange.x || v_vertex_index > u_drawRange.y))
{
discard;
}
if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5))
{ // actually, 8 and 9 { // actually, 8 and 9
// discard movements // discard movements
@ -91,6 +81,78 @@ fragment =
gl_FragColor = v_color; gl_FragColor = v_color;
} }
vertex41core =
#version 410
uniform highp mat4 u_modelMatrix;
uniform highp mat4 u_viewMatrix;
uniform highp mat4 u_projectionMatrix;
uniform lowp float u_active_extruder;
uniform lowp float u_shade_factor;
uniform highp int u_layer_view_type;
in highp float a_extruder;
in highp float a_line_type;
in highp vec4 a_vertex;
in lowp vec4 a_color;
in lowp vec4 a_material_color;
out lowp vec4 v_color;
out float v_line_type;
void main()
{
gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * a_vertex;
v_color = vec4(0.4, 0.4, 0.4, 0.9); // default color for not current layer
// if ((a_line_type != 8) && (a_line_type != 9)) {
// v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a);
// }
v_line_type = a_line_type;
}
fragment41core =
#version 410
in lowp vec4 v_color;
in float v_line_type;
out vec4 frag_color;
uniform int u_show_travel_moves;
uniform int u_show_helpers;
uniform int u_show_skin;
uniform int u_show_infill;
void main()
{
if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9
// discard movements
discard;
}
// helpers: 4, 5, 7, 10, 11
if ((u_show_helpers == 0) && (
((v_line_type >= 3.5) && (v_line_type <= 4.5)) ||
((v_line_type >= 6.5) && (v_line_type <= 7.5)) ||
((v_line_type >= 9.5) && (v_line_type <= 10.5)) ||
((v_line_type >= 4.5) && (v_line_type <= 5.5)) ||
((v_line_type >= 10.5) && (v_line_type <= 11.5))
)) {
discard;
}
// skin: 1, 2, 3
if ((u_show_skin == 0) && (
(v_line_type >= 0.5) && (v_line_type <= 3.5)
)) {
discard;
}
// infill:
if ((u_show_infill == 0) && (v_line_type >= 5.5) && (v_line_type <= 6.5)) {
// discard movements
discard;
}
frag_color = v_color;
}
[defaults] [defaults]
u_active_extruder = 0.0 u_active_extruder = 0.0
u_shade_factor = 0.60 u_shade_factor = 0.60
@ -102,13 +164,10 @@ u_show_helpers = 1
u_show_skin = 1 u_show_skin = 1
u_show_infill = 1 u_show_infill = 1
u_drawRange = [-1.0, -1.0]
[bindings] [bindings]
u_modelMatrix = model_matrix u_modelMatrix = model_matrix
u_viewMatrix = view_matrix u_viewMatrix = view_matrix
u_projectionMatrix = projection_matrix u_projectionMatrix = projection_matrix
u_drawRange = draw_range
[attributes] [attributes]
a_vertex = vertex a_vertex = vertex
@ -116,4 +175,3 @@ a_color = color
a_extruder = extruder a_extruder = extruder
a_line_type = line_type a_line_type = line_type
a_material_color = material_color a_material_color = material_color
a_vertex_index = vertex_index

View File

@ -66,7 +66,7 @@ class CloudPackageChecker(QObject):
self._application.getHttpRequestManager().get(url, self._application.getHttpRequestManager().get(url,
callback = self._onUserPackagesRequestFinished, callback = self._onUserPackagesRequestFinished,
error_callback = self._onUserPackagesRequestFinished, error_callback = self._onUserPackagesRequestFinished,
timeout=10, timeout = 10,
scope = self._scope) scope = self._scope)
def _onUserPackagesRequestFinished(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"] = None) -> None: def _onUserPackagesRequestFinished(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"] = None) -> None:

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for reading Ultimaker Format Packages.", "description": "Provides support for reading Ultimaker Format Packages.",
"supported_sdk_versions": ["7.8.0"], "supported_sdk_versions": ["7.9.0"],
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -73,10 +73,6 @@ Item
switch (printJob.state) switch (printJob.state)
{ {
case "wait_cleanup": case "wait_cleanup":
if (printJob.timeTotal > printJob.timeElapsed)
{
return catalog.i18nc("@label:status", "Aborted");
}
return catalog.i18nc("@label:status", "Finished"); return catalog.i18nc("@label:status", "Finished");
case "finished": case "finished":
return catalog.i18nc("@label:status", "Finished"); return catalog.i18nc("@label:status", "Finished");
@ -88,6 +84,20 @@ Item
return catalog.i18nc("@label:status", "Aborting..."); return catalog.i18nc("@label:status", "Aborting...");
case "aborted": // NOTE: Unused, see above case "aborted": // NOTE: Unused, see above
return catalog.i18nc("@label:status", "Aborted"); return catalog.i18nc("@label:status", "Aborted");
case "aborted_post_print":
return catalog.i18nc("@label:status", "Aborted");
case "aborted_wait_user_action":
return catalog.i18nc("@label:status", "Aborted");
case "aborted_wait_cleanup":
return catalog.i18nc("@label:status", "Aborted");
case "failed":
return catalog.i18nc("@label:status", "Failed");
case "failed_post_print":
return catalog.i18nc("@label:status", "Failed");
case "failed_wait_user_action":
return catalog.i18nc("@label:status", "Failed");
case "failed_wait_cleanup":
return catalog.i18nc("@label:status", "Failed");
case "pausing": case "pausing":
return catalog.i18nc("@label:status", "Pausing..."); return catalog.i18nc("@label:status", "Pausing...");
case "paused": case "paused":

View File

@ -19,7 +19,7 @@ from cura.CuraApplication import CuraApplication
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To update printer metadata with information received about cloud printers. from cura.Settings.CuraContainerRegistry import CuraContainerRegistry # To update printer metadata with information received about cloud printers.
from cura.Settings.CuraStackBuilder import CuraStackBuilder from cura.Settings.CuraStackBuilder import CuraStackBuilder
from cura.Settings.GlobalStack import GlobalStack from cura.Settings.GlobalStack import GlobalStack
from cura.UltimakerCloud.UltimakerCloudConstants import META_UM_LINKED_TO_ACCOUNT from cura.UltimakerCloud.UltimakerCloudConstants import META_CAPABILITIES, META_UM_LINKED_TO_ACCOUNT
from .CloudApiClient import CloudApiClient from .CloudApiClient import CloudApiClient
from .CloudOutputDevice import CloudOutputDevice from .CloudOutputDevice import CloudOutputDevice
from ..Models.Http.CloudClusterResponse import CloudClusterResponse from ..Models.Http.CloudClusterResponse import CloudClusterResponse
@ -128,6 +128,8 @@ class CloudOutputDeviceManager:
# to the current account # to the current account
if not parseBool(self._um_cloud_printers[device_id].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")): if not parseBool(self._um_cloud_printers[device_id].getMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, "true")):
self._um_cloud_printers[device_id].setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True) self._um_cloud_printers[device_id].setMetaDataEntry(META_UM_LINKED_TO_ACCOUNT, True)
if not self._um_cloud_printers[device_id].getMetaDataEntry(META_CAPABILITIES, None):
self._um_cloud_printers[device_id].setMetaDataEntry(META_CAPABILITIES, ",".join(cluster_data.capabilities))
self._onDevicesDiscovered(new_clusters) self._onDevicesDiscovered(new_clusters)
self._updateOnlinePrinters(all_clusters) self._updateOnlinePrinters(all_clusters)

View File

@ -37,7 +37,7 @@ class CloudClusterResponse(BaseModel):
self.friendly_name = friendly_name self.friendly_name = friendly_name
self.printer_type = printer_type self.printer_type = printer_type
self.printer_count = printer_count self.printer_count = printer_count
self.capabilities = capabilities self.capabilities = capabilities if capabilities is not None else []
super().__init__(**kwargs) super().__init__(**kwargs)
# Validates the model, raising an exception if the model is invalid. # Validates the model, raising an exception if the model is invalid.
@ -45,3 +45,10 @@ class CloudClusterResponse(BaseModel):
super().validate() super().validate()
if not self.cluster_id: if not self.cluster_id:
raise ValueError("cluster_id is required on CloudCluster") raise ValueError("cluster_id is required on CloudCluster")
def __repr__(self) -> str:
"""
Convenience function for printing when debugging.
:return: A human-readable representation of the data in this object.
"""
return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}})

View File

@ -40,7 +40,7 @@ class ClusterPrintJobStatus(BaseModel):
configuration_changes_required: List[ configuration_changes_required: List[
Union[Dict[str, Any], ClusterPrintJobConfigurationChange]] = None, Union[Dict[str, Any], ClusterPrintJobConfigurationChange]] = None,
build_plate: Union[Dict[str, Any], ClusterBuildPlate] = None, build_plate: Union[Dict[str, Any], ClusterBuildPlate] = None,
compatible_machine_families: List[str] = None, compatible_machine_families: Optional[List[str]] = None,
impediments_to_printing: List[Union[Dict[str, Any], ClusterPrintJobImpediment]] = None, impediments_to_printing: List[Union[Dict[str, Any], ClusterPrintJobImpediment]] = None,
preview_url: Optional[str] = None, preview_url: Optional[str] = None,
**kwargs) -> None: **kwargs) -> None:
@ -97,7 +97,7 @@ class ClusterPrintJobStatus(BaseModel):
configuration_changes_required) \ configuration_changes_required) \
if configuration_changes_required else [] if configuration_changes_required else []
self.build_plate = self.parseModel(ClusterBuildPlate, build_plate) if build_plate else None self.build_plate = self.parseModel(ClusterBuildPlate, build_plate) if build_plate else None
self.compatible_machine_families = compatible_machine_families if compatible_machine_families else [] self.compatible_machine_families = compatible_machine_families if compatible_machine_families is not None else []
self.impediments_to_printing = self.parseModels(ClusterPrintJobImpediment, impediments_to_printing) \ self.impediments_to_printing = self.parseModels(ClusterPrintJobImpediment, impediments_to_printing) \
if impediments_to_printing else [] if impediments_to_printing else []
@ -130,8 +130,10 @@ class ClusterPrintJobStatus(BaseModel):
model.updateConfiguration(self._createConfigurationModel()) model.updateConfiguration(self._createConfigurationModel())
model.updateTimeTotal(self.time_total) model.updateTimeTotal(self.time_total)
model.updateTimeElapsed(self.time_elapsed) if self.time_elapsed is not None:
model.updateOwner(self.owner) model.updateTimeElapsed(self.time_elapsed)
if self.owner is not None:
model.updateOwner(self.owner)
model.updateState(self.status) model.updateState(self.status)
model.setCompatibleMachineFamilies(self.compatible_machine_families) model.setCompatibleMachineFamilies(self.compatible_machine_families)

View File

@ -29,7 +29,7 @@ pywin32==301
requests==2.22.0 requests==2.22.0
scipy==1.6.2 scipy==1.6.2
sentry-sdk==0.13.5 sentry-sdk==0.13.5
shapely[vectorized]==1.7.1 shapely[vectorized]==1.8.0
six==1.12.0 six==1.12.0
trimesh==3.2.33 trimesh==3.2.33
twisted==21.2.0 twisted==21.2.0

View File

@ -6,7 +6,7 @@
"display_name": "3MF Reader", "display_name": "3MF Reader",
"description": "Provides support for reading 3MF files.", "description": "Provides support for reading 3MF files.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -23,7 +23,7 @@
"display_name": "3MF Writer", "display_name": "3MF Writer",
"description": "Provides support for writing 3MF files.", "description": "Provides support for writing 3MF files.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -40,7 +40,7 @@
"display_name": "AMF Reader", "display_name": "AMF Reader",
"description": "Provides support for reading AMF files.", "description": "Provides support for reading AMF files.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "fieldOfView", "author_id": "fieldOfView",
@ -57,7 +57,7 @@
"display_name": "Cura Backups", "display_name": "Cura Backups",
"description": "Backup and restore your configuration.", "description": "Backup and restore your configuration.",
"package_version": "1.2.0", "package_version": "1.2.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -74,7 +74,7 @@
"display_name": "CuraEngine Backend", "display_name": "CuraEngine Backend",
"description": "Provides the link to the CuraEngine slicing backend.", "description": "Provides the link to the CuraEngine slicing backend.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -91,7 +91,7 @@
"display_name": "Cura Profile Reader", "display_name": "Cura Profile Reader",
"description": "Provides support for importing Cura profiles.", "description": "Provides support for importing Cura profiles.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -108,7 +108,7 @@
"display_name": "Cura Profile Writer", "display_name": "Cura Profile Writer",
"description": "Provides support for exporting Cura profiles.", "description": "Provides support for exporting Cura profiles.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -125,7 +125,7 @@
"display_name": "Ultimaker Digital Library", "display_name": "Ultimaker Digital Library",
"description": "Connects to the Digital Library, allowing Cura to open files from and save files to the Digital Library.", "description": "Connects to the Digital Library, allowing Cura to open files from and save files to the Digital Library.",
"package_version": "1.1.0", "package_version": "1.1.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -142,7 +142,7 @@
"display_name": "Firmware Update Checker", "display_name": "Firmware Update Checker",
"description": "Checks for firmware updates.", "description": "Checks for firmware updates.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -159,7 +159,7 @@
"display_name": "Firmware Updater", "display_name": "Firmware Updater",
"description": "Provides a machine actions for updating firmware.", "description": "Provides a machine actions for updating firmware.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -176,7 +176,7 @@
"display_name": "Compressed G-code Reader", "display_name": "Compressed G-code Reader",
"description": "Reads g-code from a compressed archive.", "description": "Reads g-code from a compressed archive.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -193,7 +193,7 @@
"display_name": "Compressed G-code Writer", "display_name": "Compressed G-code Writer",
"description": "Writes g-code to a compressed archive.", "description": "Writes g-code to a compressed archive.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -210,7 +210,7 @@
"display_name": "G-Code Profile Reader", "display_name": "G-Code Profile Reader",
"description": "Provides support for importing profiles from g-code files.", "description": "Provides support for importing profiles from g-code files.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -227,7 +227,7 @@
"display_name": "G-Code Reader", "display_name": "G-Code Reader",
"description": "Allows loading and displaying G-code files.", "description": "Allows loading and displaying G-code files.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "VictorLarchenko", "author_id": "VictorLarchenko",
@ -244,7 +244,7 @@
"display_name": "G-Code Writer", "display_name": "G-Code Writer",
"description": "Writes g-code to a file.", "description": "Writes g-code to a file.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -261,7 +261,7 @@
"display_name": "Image Reader", "display_name": "Image Reader",
"description": "Enables ability to generate printable geometry from 2D image files.", "description": "Enables ability to generate printable geometry from 2D image files.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -278,7 +278,7 @@
"display_name": "Legacy Cura Profile Reader", "display_name": "Legacy Cura Profile Reader",
"description": "Provides support for importing profiles from legacy Cura versions.", "description": "Provides support for importing profiles from legacy Cura versions.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -295,7 +295,7 @@
"display_name": "Machine Settings Action", "display_name": "Machine Settings Action",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).", "description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "fieldOfView", "author_id": "fieldOfView",
@ -312,7 +312,7 @@
"display_name": "Model Checker", "display_name": "Model Checker",
"description": "Checks models and print configuration for possible printing issues and give suggestions.", "description": "Checks models and print configuration for possible printing issues and give suggestions.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -329,7 +329,7 @@
"display_name": "Monitor Stage", "display_name": "Monitor Stage",
"description": "Provides a monitor stage in Cura.", "description": "Provides a monitor stage in Cura.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -346,7 +346,7 @@
"display_name": "Per-Object Settings Tool", "display_name": "Per-Object Settings Tool",
"description": "Provides the per-model settings.", "description": "Provides the per-model settings.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -363,7 +363,7 @@
"display_name": "Post Processing", "display_name": "Post Processing",
"description": "Extension that allows for user created scripts for post processing.", "description": "Extension that allows for user created scripts for post processing.",
"package_version": "2.2.1", "package_version": "2.2.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -380,7 +380,7 @@
"display_name": "Prepare Stage", "display_name": "Prepare Stage",
"description": "Provides a prepare stage in Cura.", "description": "Provides a prepare stage in Cura.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -397,7 +397,7 @@
"display_name": "Preview Stage", "display_name": "Preview Stage",
"description": "Provides a preview stage in Cura.", "description": "Provides a preview stage in Cura.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -414,7 +414,7 @@
"display_name": "Removable Drive Output Device", "display_name": "Removable Drive Output Device",
"description": "Provides removable drive hotplugging and writing support.", "description": "Provides removable drive hotplugging and writing support.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -431,7 +431,7 @@
"display_name": "Sentry Logger", "display_name": "Sentry Logger",
"description": "Logs certain events so that they can be used by the crash reporter", "description": "Logs certain events so that they can be used by the crash reporter",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -448,7 +448,7 @@
"display_name": "Simulation View", "display_name": "Simulation View",
"description": "Provides the Simulation view.", "description": "Provides the Simulation view.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -465,7 +465,7 @@
"display_name": "Slice Info", "display_name": "Slice Info",
"description": "Submits anonymous slice info. Can be disabled through preferences.", "description": "Submits anonymous slice info. Can be disabled through preferences.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -482,7 +482,7 @@
"display_name": "Solid View", "display_name": "Solid View",
"description": "Provides a normal solid mesh view.", "description": "Provides a normal solid mesh view.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -499,7 +499,7 @@
"display_name": "Support Eraser Tool", "display_name": "Support Eraser Tool",
"description": "Creates an eraser mesh to block the printing of support in certain places.", "description": "Creates an eraser mesh to block the printing of support in certain places.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -516,7 +516,7 @@
"display_name": "Trimesh Reader", "display_name": "Trimesh Reader",
"description": "Provides support for reading model files.", "description": "Provides support for reading model files.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -533,7 +533,7 @@
"display_name": "Toolbox", "display_name": "Toolbox",
"description": "Find, manage and install new Cura packages.", "description": "Find, manage and install new Cura packages.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -550,7 +550,7 @@
"display_name": "UFP Reader", "display_name": "UFP Reader",
"description": "Provides support for reading Ultimaker Format Packages.", "description": "Provides support for reading Ultimaker Format Packages.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -567,7 +567,7 @@
"display_name": "UFP Writer", "display_name": "UFP Writer",
"description": "Provides support for writing Ultimaker Format Packages.", "description": "Provides support for writing Ultimaker Format Packages.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -584,7 +584,7 @@
"display_name": "Ultimaker Machine Actions", "display_name": "Ultimaker Machine Actions",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).", "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -601,7 +601,7 @@
"display_name": "UM3 Network Printing", "display_name": "UM3 Network Printing",
"description": "Manages network connections to Ultimaker 3 printers.", "description": "Manages network connections to Ultimaker 3 printers.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -618,7 +618,7 @@
"display_name": "USB Printing", "display_name": "USB Printing",
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", "description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
"package_version": "1.0.2", "package_version": "1.0.2",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -635,7 +635,7 @@
"display_name": "Version Upgrade 2.1 to 2.2", "display_name": "Version Upgrade 2.1 to 2.2",
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.", "description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -652,7 +652,7 @@
"display_name": "Version Upgrade 2.2 to 2.4", "display_name": "Version Upgrade 2.2 to 2.4",
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.", "description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -669,7 +669,7 @@
"display_name": "Version Upgrade 2.5 to 2.6", "display_name": "Version Upgrade 2.5 to 2.6",
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.", "description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -686,7 +686,7 @@
"display_name": "Version Upgrade 2.6 to 2.7", "display_name": "Version Upgrade 2.6 to 2.7",
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.", "description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -703,7 +703,7 @@
"display_name": "Version Upgrade 2.7 to 3.0", "display_name": "Version Upgrade 2.7 to 3.0",
"description": "Upgrades configurations from Cura 2.7 to Cura 3.0.", "description": "Upgrades configurations from Cura 2.7 to Cura 3.0.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -720,7 +720,7 @@
"display_name": "Version Upgrade 3.0 to 3.1", "display_name": "Version Upgrade 3.0 to 3.1",
"description": "Upgrades configurations from Cura 3.0 to Cura 3.1.", "description": "Upgrades configurations from Cura 3.0 to Cura 3.1.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -737,7 +737,7 @@
"display_name": "Version Upgrade 3.2 to 3.3", "display_name": "Version Upgrade 3.2 to 3.3",
"description": "Upgrades configurations from Cura 3.2 to Cura 3.3.", "description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -754,7 +754,7 @@
"display_name": "Version Upgrade 3.3 to 3.4", "display_name": "Version Upgrade 3.3 to 3.4",
"description": "Upgrades configurations from Cura 3.3 to Cura 3.4.", "description": "Upgrades configurations from Cura 3.3 to Cura 3.4.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -771,7 +771,7 @@
"display_name": "Version Upgrade 3.4 to 3.5", "display_name": "Version Upgrade 3.4 to 3.5",
"description": "Upgrades configurations from Cura 3.4 to Cura 3.5.", "description": "Upgrades configurations from Cura 3.4 to Cura 3.5.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -788,7 +788,7 @@
"display_name": "Version Upgrade 3.5 to 4.0", "display_name": "Version Upgrade 3.5 to 4.0",
"description": "Upgrades configurations from Cura 3.5 to Cura 4.0.", "description": "Upgrades configurations from Cura 3.5 to Cura 4.0.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -805,7 +805,7 @@
"display_name": "Version Upgrade 4.0 to 4.1", "display_name": "Version Upgrade 4.0 to 4.1",
"description": "Upgrades configurations from Cura 4.0 to Cura 4.1.", "description": "Upgrades configurations from Cura 4.0 to Cura 4.1.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -822,7 +822,7 @@
"display_name": "Version Upgrade 4.1 to 4.2", "display_name": "Version Upgrade 4.1 to 4.2",
"description": "Upgrades configurations from Cura 4.1 to Cura 4.2.", "description": "Upgrades configurations from Cura 4.1 to Cura 4.2.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -839,7 +839,7 @@
"display_name": "Version Upgrade 4.2 to 4.3", "display_name": "Version Upgrade 4.2 to 4.3",
"description": "Upgrades configurations from Cura 4.2 to Cura 4.3.", "description": "Upgrades configurations from Cura 4.2 to Cura 4.3.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -856,7 +856,7 @@
"display_name": "Version Upgrade 4.3 to 4.4", "display_name": "Version Upgrade 4.3 to 4.4",
"description": "Upgrades configurations from Cura 4.3 to Cura 4.4.", "description": "Upgrades configurations from Cura 4.3 to Cura 4.4.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -873,7 +873,7 @@
"display_name": "Version Upgrade 4.4 to 4.5", "display_name": "Version Upgrade 4.4 to 4.5",
"description": "Upgrades configurations from Cura 4.4 to Cura 4.5.", "description": "Upgrades configurations from Cura 4.4 to Cura 4.5.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -890,7 +890,7 @@
"display_name": "Version Upgrade 4.5 to 4.6", "display_name": "Version Upgrade 4.5 to 4.6",
"description": "Upgrades configurations from Cura 4.5 to Cura 4.6.", "description": "Upgrades configurations from Cura 4.5 to Cura 4.6.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -907,7 +907,7 @@
"display_name": "Version Upgrade 4.6.0 to 4.6.2", "display_name": "Version Upgrade 4.6.0 to 4.6.2",
"description": "Upgrades configurations from Cura 4.6.0 to Cura 4.6.2.", "description": "Upgrades configurations from Cura 4.6.0 to Cura 4.6.2.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -924,7 +924,7 @@
"display_name": "Version Upgrade 4.6.2 to 4.7", "display_name": "Version Upgrade 4.6.2 to 4.7",
"description": "Upgrades configurations from Cura 4.6.2 to Cura 4.7.", "description": "Upgrades configurations from Cura 4.6.2 to Cura 4.7.",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -941,7 +941,7 @@
"display_name": "Version Upgrade 4.7.0 to 4.8.0", "display_name": "Version Upgrade 4.7.0 to 4.8.0",
"description": "Upgrades configurations from Cura 4.7.0 to Cura 4.8.0", "description": "Upgrades configurations from Cura 4.7.0 to Cura 4.8.0",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -958,7 +958,7 @@
"display_name": "Version Upgrade 4.8.0 to 4.9.0", "display_name": "Version Upgrade 4.8.0 to 4.9.0",
"description": "Upgrades configurations from Cura 4.8.0 to Cura 4.9.0", "description": "Upgrades configurations from Cura 4.8.0 to Cura 4.9.0",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -976,7 +976,7 @@
"description": "Upgrades configurations from Cura 4.9 to Cura 4.10", "description": "Upgrades configurations from Cura 4.9 to Cura 4.10",
"package_version": "1.0.0", "package_version": "1.0.0",
"sdk_version": 7, "sdk_version": 7,
"sdk_version_semver": "7.8.0", "sdk_version_semver": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1011,7 +1011,7 @@
"display_name": "X3D Reader", "display_name": "X3D Reader",
"description": "Provides support for reading X3D files.", "description": "Provides support for reading X3D files.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "SevaAlekseyev", "author_id": "SevaAlekseyev",
@ -1028,7 +1028,7 @@
"display_name": "XML Material Profiles", "display_name": "XML Material Profiles",
"description": "Provides capabilities to read and write XML-based material profiles.", "description": "Provides capabilities to read and write XML-based material profiles.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1045,7 +1045,7 @@
"display_name": "X-Ray View", "display_name": "X-Ray View",
"description": "Provides the X-Ray view.", "description": "Provides the X-Ray view.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1062,7 +1062,7 @@
"display_name": "Generic ABS", "display_name": "Generic ABS",
"description": "The generic ABS profile which other profiles can be based upon.", "description": "The generic ABS profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1080,7 +1080,7 @@
"display_name": "Generic BAM", "display_name": "Generic BAM",
"description": "The generic BAM profile which other profiles can be based upon.", "description": "The generic BAM profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1098,7 +1098,7 @@
"display_name": "Generic CFF CPE", "display_name": "Generic CFF CPE",
"description": "The generic CFF CPE profile which other profiles can be based upon.", "description": "The generic CFF CPE profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1116,7 +1116,7 @@
"display_name": "Generic CFF PA", "display_name": "Generic CFF PA",
"description": "The generic CFF PA profile which other profiles can be based upon.", "description": "The generic CFF PA profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1134,7 +1134,7 @@
"display_name": "Generic CPE", "display_name": "Generic CPE",
"description": "The generic CPE profile which other profiles can be based upon.", "description": "The generic CPE profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1152,7 +1152,7 @@
"display_name": "Generic CPE+", "display_name": "Generic CPE+",
"description": "The generic CPE+ profile which other profiles can be based upon.", "description": "The generic CPE+ profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1170,7 +1170,7 @@
"display_name": "Generic GFF CPE", "display_name": "Generic GFF CPE",
"description": "The generic GFF CPE profile which other profiles can be based upon.", "description": "The generic GFF CPE profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1188,7 +1188,7 @@
"display_name": "Generic GFF PA", "display_name": "Generic GFF PA",
"description": "The generic GFF PA profile which other profiles can be based upon.", "description": "The generic GFF PA profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1206,7 +1206,7 @@
"display_name": "Generic HIPS", "display_name": "Generic HIPS",
"description": "The generic HIPS profile which other profiles can be based upon.", "description": "The generic HIPS profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1224,7 +1224,7 @@
"display_name": "Generic Nylon", "display_name": "Generic Nylon",
"description": "The generic Nylon profile which other profiles can be based upon.", "description": "The generic Nylon profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1242,7 +1242,7 @@
"display_name": "Generic PC", "display_name": "Generic PC",
"description": "The generic PC profile which other profiles can be based upon.", "description": "The generic PC profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1260,7 +1260,7 @@
"display_name": "Generic PETG", "display_name": "Generic PETG",
"description": "The generic PETG profile which other profiles can be based upon.", "description": "The generic PETG profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1278,7 +1278,7 @@
"display_name": "Generic PLA", "display_name": "Generic PLA",
"description": "The generic PLA profile which other profiles can be based upon.", "description": "The generic PLA profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1296,7 +1296,7 @@
"display_name": "Generic PP", "display_name": "Generic PP",
"description": "The generic PP profile which other profiles can be based upon.", "description": "The generic PP profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1314,7 +1314,7 @@
"display_name": "Generic PVA", "display_name": "Generic PVA",
"description": "The generic PVA profile which other profiles can be based upon.", "description": "The generic PVA profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1332,7 +1332,7 @@
"display_name": "Generic Tough PLA", "display_name": "Generic Tough PLA",
"description": "The generic Tough PLA profile which other profiles can be based upon.", "description": "The generic Tough PLA profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1350,7 +1350,7 @@
"display_name": "Generic TPU", "display_name": "Generic TPU",
"description": "The generic TPU profile which other profiles can be based upon.", "description": "The generic TPU profile which other profiles can be based upon.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://github.com/Ultimaker/fdm_materials", "website": "https://github.com/Ultimaker/fdm_materials",
"author": { "author": {
"author_id": "Generic", "author_id": "Generic",
@ -1368,7 +1368,7 @@
"display_name": "Dagoma Chromatik PLA", "display_name": "Dagoma Chromatik PLA",
"description": "Filament testé et approuvé pour les imprimantes 3D Dagoma. Chromatik est l'idéal pour débuter et suivre les tutoriels premiers pas. Il vous offre qualité et résistance pour chacune de vos impressions.", "description": "Filament testé et approuvé pour les imprimantes 3D Dagoma. Chromatik est l'idéal pour débuter et suivre les tutoriels premiers pas. Il vous offre qualité et résistance pour chacune de vos impressions.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://dagoma.fr/boutique/filaments.html", "website": "https://dagoma.fr/boutique/filaments.html",
"author": { "author": {
"author_id": "Dagoma", "author_id": "Dagoma",
@ -1385,7 +1385,7 @@
"display_name": "FABtotum ABS", "display_name": "FABtotum ABS",
"description": "This material is easy to be extruded but it is not the simplest to use. It is one of the most used in 3D printing to get very well finished objects. It is not sustainable and its smoke can be dangerous if inhaled. The reason to prefer this filament to PLA is mainly because of its precision and mechanical specs. ABS (for plastic) stands for Acrylonitrile Butadiene Styrene and it is a thermoplastic which is widely used in everyday objects. It can be printed with any FFF 3D printer which can get to high temperatures as it must be extruded in a range between 220° and 245°, so its compatible with all versions of the FABtotum Personal fabricator.", "description": "This material is easy to be extruded but it is not the simplest to use. It is one of the most used in 3D printing to get very well finished objects. It is not sustainable and its smoke can be dangerous if inhaled. The reason to prefer this filament to PLA is mainly because of its precision and mechanical specs. ABS (for plastic) stands for Acrylonitrile Butadiene Styrene and it is a thermoplastic which is widely used in everyday objects. It can be printed with any FFF 3D printer which can get to high temperatures as it must be extruded in a range between 220° and 245°, so its compatible with all versions of the FABtotum Personal fabricator.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=40", "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=40",
"author": { "author": {
"author_id": "FABtotum", "author_id": "FABtotum",
@ -1402,7 +1402,7 @@
"display_name": "FABtotum Nylon", "display_name": "FABtotum Nylon",
"description": "When 3D printing started this material was not listed among the extrudable filaments. It is flexible as well as resistant to tractions. It is well known for its uses in textile but also in industries which require a strong and flexible material. There are different kinds of Nylon: 3D printing mostly uses Nylon 6 and Nylon 6.6, which are the most common. It requires higher temperatures to be printed, so a 3D printer must be able to reach them (around 240°C): the FABtotum, of course, can.", "description": "When 3D printing started this material was not listed among the extrudable filaments. It is flexible as well as resistant to tractions. It is well known for its uses in textile but also in industries which require a strong and flexible material. There are different kinds of Nylon: 3D printing mostly uses Nylon 6 and Nylon 6.6, which are the most common. It requires higher temperatures to be printed, so a 3D printer must be able to reach them (around 240°C): the FABtotum, of course, can.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=53", "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=53",
"author": { "author": {
"author_id": "FABtotum", "author_id": "FABtotum",
@ -1419,7 +1419,7 @@
"display_name": "FABtotum PLA", "display_name": "FABtotum PLA",
"description": "It is the most common filament used for 3D printing. It is studied to be bio-degradable as it comes from corn starchs sugar mainly. It is completely made of renewable sources and has no footprint on polluting. PLA stands for PolyLactic Acid and it is a thermoplastic that today is still considered the easiest material to be 3D printed. It can be extruded at lower temperatures: the standard range of FABtotums one is between 185° and 195°.", "description": "It is the most common filament used for 3D printing. It is studied to be bio-degradable as it comes from corn starchs sugar mainly. It is completely made of renewable sources and has no footprint on polluting. PLA stands for PolyLactic Acid and it is a thermoplastic that today is still considered the easiest material to be 3D printed. It can be extruded at lower temperatures: the standard range of FABtotums one is between 185° and 195°.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=39", "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=39",
"author": { "author": {
"author_id": "FABtotum", "author_id": "FABtotum",
@ -1436,7 +1436,7 @@
"display_name": "FABtotum TPU Shore 98A", "display_name": "FABtotum TPU Shore 98A",
"description": "", "description": "",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=66", "website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=66",
"author": { "author": {
"author_id": "FABtotum", "author_id": "FABtotum",
@ -1453,7 +1453,7 @@
"display_name": "Fiberlogy HD PLA", "display_name": "Fiberlogy HD PLA",
"description": "With our HD PLA you have many more options. You can use this material in two ways. Choose the one you like best. You can use it as a normal PLA and get prints characterized by a very good adhesion between the layers and high precision. You can also make your prints acquire similar properties to that of ABS better impact resistance and high temperature resistance. All you need is an oven. Yes, an oven! By annealing our HD PLA in an oven, in accordance with the manual, you will avoid all the inconveniences of printing with ABS, such as unpleasant odour or hazardous fumes.", "description": "With our HD PLA you have many more options. You can use this material in two ways. Choose the one you like best. You can use it as a normal PLA and get prints characterized by a very good adhesion between the layers and high precision. You can also make your prints acquire similar properties to that of ABS better impact resistance and high temperature resistance. All you need is an oven. Yes, an oven! By annealing our HD PLA in an oven, in accordance with the manual, you will avoid all the inconveniences of printing with ABS, such as unpleasant odour or hazardous fumes.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "http://fiberlogy.com/en/fiberlogy-filaments/filament-hd-pla/", "website": "http://fiberlogy.com/en/fiberlogy-filaments/filament-hd-pla/",
"author": { "author": {
"author_id": "Fiberlogy", "author_id": "Fiberlogy",
@ -1470,7 +1470,7 @@
"display_name": "Filo3D PLA", "display_name": "Filo3D PLA",
"description": "Fast, safe and reliable printing. PLA is ideal for the fast and reliable printing of parts and prototypes with a great surface quality.", "description": "Fast, safe and reliable printing. PLA is ideal for the fast and reliable printing of parts and prototypes with a great surface quality.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://dagoma.fr", "website": "https://dagoma.fr",
"author": { "author": {
"author_id": "Dagoma", "author_id": "Dagoma",
@ -1487,7 +1487,7 @@
"display_name": "IMADE3D JellyBOX PETG", "display_name": "IMADE3D JellyBOX PETG",
"description": "", "description": "",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "http://shop.imade3d.com/filament.html", "website": "http://shop.imade3d.com/filament.html",
"author": { "author": {
"author_id": "IMADE3D", "author_id": "IMADE3D",
@ -1504,7 +1504,7 @@
"display_name": "IMADE3D JellyBOX PLA", "display_name": "IMADE3D JellyBOX PLA",
"description": "", "description": "",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "http://shop.imade3d.com/filament.html", "website": "http://shop.imade3d.com/filament.html",
"author": { "author": {
"author_id": "IMADE3D", "author_id": "IMADE3D",
@ -1521,7 +1521,7 @@
"display_name": "Octofiber PLA", "display_name": "Octofiber PLA",
"description": "PLA material from Octofiber.", "description": "PLA material from Octofiber.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://nl.octofiber.com/3d-printing-filament/pla.html", "website": "https://nl.octofiber.com/3d-printing-filament/pla.html",
"author": { "author": {
"author_id": "Octofiber", "author_id": "Octofiber",
@ -1538,7 +1538,7 @@
"display_name": "PolyFlex™ PLA", "display_name": "PolyFlex™ PLA",
"description": "PolyFlex™ is a highly flexible yet easy to print 3D printing material. Featuring good elasticity and a large strain-to- failure, PolyFlex™ opens up a completely new realm of applications.", "description": "PolyFlex™ is a highly flexible yet easy to print 3D printing material. Featuring good elasticity and a large strain-to- failure, PolyFlex™ opens up a completely new realm of applications.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "http://www.polymaker.com/shop/polyflex/", "website": "http://www.polymaker.com/shop/polyflex/",
"author": { "author": {
"author_id": "Polymaker", "author_id": "Polymaker",
@ -1555,7 +1555,7 @@
"display_name": "PolyMax™ PLA", "display_name": "PolyMax™ PLA",
"description": "PolyMax™ PLA is a 3D printing material with excellent mechanical properties and printing quality. PolyMax™ PLA has an impact resistance of up to nine times that of regular PLA, and better overall mechanical properties than ABS.", "description": "PolyMax™ PLA is a 3D printing material with excellent mechanical properties and printing quality. PolyMax™ PLA has an impact resistance of up to nine times that of regular PLA, and better overall mechanical properties than ABS.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "http://www.polymaker.com/shop/polymax/", "website": "http://www.polymaker.com/shop/polymax/",
"author": { "author": {
"author_id": "Polymaker", "author_id": "Polymaker",
@ -1572,7 +1572,7 @@
"display_name": "PolyPlus™ PLA True Colour", "display_name": "PolyPlus™ PLA True Colour",
"description": "PolyPlus™ PLA is a premium PLA designed for all desktop FDM/FFF 3D printers. It is produced with our patented Jam-Free™ technology that ensures consistent extrusion and prevents jams.", "description": "PolyPlus™ PLA is a premium PLA designed for all desktop FDM/FFF 3D printers. It is produced with our patented Jam-Free™ technology that ensures consistent extrusion and prevents jams.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "http://www.polymaker.com/shop/polyplus-true-colour/", "website": "http://www.polymaker.com/shop/polyplus-true-colour/",
"author": { "author": {
"author_id": "Polymaker", "author_id": "Polymaker",
@ -1589,7 +1589,7 @@
"display_name": "PolyWood™ PLA", "display_name": "PolyWood™ PLA",
"description": "PolyWood™ is a wood mimic printing material that contains no actual wood ensuring a clean Jam-Free™ printing experience.", "description": "PolyWood™ is a wood mimic printing material that contains no actual wood ensuring a clean Jam-Free™ printing experience.",
"package_version": "1.0.1", "package_version": "1.0.1",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "http://www.polymaker.com/shop/polywood/", "website": "http://www.polymaker.com/shop/polywood/",
"author": { "author": {
"author_id": "Polymaker", "author_id": "Polymaker",
@ -1606,7 +1606,7 @@
"display_name": "Ultimaker ABS", "display_name": "Ultimaker ABS",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/abs", "website": "https://ultimaker.com/products/materials/abs",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1625,7 +1625,7 @@
"display_name": "Ultimaker Breakaway", "display_name": "Ultimaker Breakaway",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/breakaway", "website": "https://ultimaker.com/products/materials/breakaway",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1644,7 +1644,7 @@
"display_name": "Ultimaker CPE", "display_name": "Ultimaker CPE",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/abs", "website": "https://ultimaker.com/products/materials/abs",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1663,7 +1663,7 @@
"display_name": "Ultimaker CPE+", "display_name": "Ultimaker CPE+",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/cpe", "website": "https://ultimaker.com/products/materials/cpe",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1682,7 +1682,7 @@
"display_name": "Ultimaker Nylon", "display_name": "Ultimaker Nylon",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/abs", "website": "https://ultimaker.com/products/materials/abs",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1701,7 +1701,7 @@
"display_name": "Ultimaker PC", "display_name": "Ultimaker PC",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/pc", "website": "https://ultimaker.com/products/materials/pc",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1720,7 +1720,7 @@
"display_name": "Ultimaker PLA", "display_name": "Ultimaker PLA",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/abs", "website": "https://ultimaker.com/products/materials/abs",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1739,7 +1739,7 @@
"display_name": "Ultimaker PP", "display_name": "Ultimaker PP",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/pp", "website": "https://ultimaker.com/products/materials/pp",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1758,7 +1758,7 @@
"display_name": "Ultimaker PVA", "display_name": "Ultimaker PVA",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/abs", "website": "https://ultimaker.com/products/materials/abs",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1777,7 +1777,7 @@
"display_name": "Ultimaker TPU 95A", "display_name": "Ultimaker TPU 95A",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/tpu-95a", "website": "https://ultimaker.com/products/materials/tpu-95a",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1796,7 +1796,7 @@
"display_name": "Ultimaker Tough PLA", "display_name": "Ultimaker Tough PLA",
"description": "Example package for material and quality profiles for Ultimaker materials.", "description": "Example package for material and quality profiles for Ultimaker materials.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://ultimaker.com/products/materials/tough-pla", "website": "https://ultimaker.com/products/materials/tough-pla",
"author": { "author": {
"author_id": "UltimakerPackages", "author_id": "UltimakerPackages",
@ -1815,7 +1815,7 @@
"display_name": "Vertex Delta ABS", "display_name": "Vertex Delta ABS",
"description": "ABS material and quality files for the Delta Vertex K8800.", "description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://vertex3dprinter.eu", "website": "https://vertex3dprinter.eu",
"author": { "author": {
"author_id": "Velleman", "author_id": "Velleman",
@ -1832,7 +1832,7 @@
"display_name": "Vertex Delta PET", "display_name": "Vertex Delta PET",
"description": "ABS material and quality files for the Delta Vertex K8800.", "description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://vertex3dprinter.eu", "website": "https://vertex3dprinter.eu",
"author": { "author": {
"author_id": "Velleman", "author_id": "Velleman",
@ -1849,7 +1849,7 @@
"display_name": "Vertex Delta PLA", "display_name": "Vertex Delta PLA",
"description": "ABS material and quality files for the Delta Vertex K8800.", "description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://vertex3dprinter.eu", "website": "https://vertex3dprinter.eu",
"author": { "author": {
"author_id": "Velleman", "author_id": "Velleman",
@ -1866,7 +1866,7 @@
"display_name": "Vertex Delta TPU", "display_name": "Vertex Delta TPU",
"description": "ABS material and quality files for the Delta Vertex K8800.", "description": "ABS material and quality files for the Delta Vertex K8800.",
"package_version": "1.4.0", "package_version": "1.4.0",
"sdk_version": "7.8.0", "sdk_version": "7.9.0",
"website": "https://vertex3dprinter.eu", "website": "https://vertex3dprinter.eu",
"author": { "author": {
"author_id": "Velleman", "author_id": "Velleman",

View File

@ -122,6 +122,7 @@
"support_xy_distance": { "value": "wall_line_width_0 * 2" }, "support_xy_distance": { "value": "wall_line_width_0 * 2" },
"support_xy_distance_overhang": { "value": "wall_line_width_0" }, "support_xy_distance_overhang": { "value": "wall_line_width_0" },
"support_z_distance": { "value": "layer_height if layer_height >= 0.16 else layer_height * 2" }, "support_z_distance": { "value": "layer_height if layer_height >= 0.16 else layer_height * 2" },
"support_top_distance": { "value": "extruderValue(support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr, 'support_z_distance') + (layer_height if support_structure == 'tree' else 0)"},
"support_xy_overrides_z": { "value": "'xy_overrides_z'" }, "support_xy_overrides_z": { "value": "'xy_overrides_z'" },
"support_wall_count": { "value": 1 }, "support_wall_count": { "value": 1 },
"support_brim_enable": { "value": true }, "support_brim_enable": { "value": true },

View File

@ -22,8 +22,8 @@
"machine_heated_bed": { "default_value": false }, "machine_heated_bed": { "default_value": false },
"machine_center_is_zero": { "default_value": true }, "machine_center_is_zero": { "default_value": true },
"machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" }, "machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG1 Y-110 Z15\nG0 Z{layer_height_0}\nG92 E0\nG1 F200 Y-100 E6\nG92 E0" },
"machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" }, "machine_end_gcode": { "default_value": "G28\nG91\nG1 E-6 F300\nM104 S0\nG1 E-1000 F5000\nM84\nG90" },
"layer_height": { "default_value": 0.2 }, "layer_height": { "default_value": 0.2 },
"default_material_print_temperature": { "default_value": 210 }, "default_material_print_temperature": { "default_value": 210 },

View File

@ -4,7 +4,6 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Ultimaker",
"manufacturer": "BFB", "manufacturer": "BFB",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform_offset": [ 0, 0, 0], "platform_offset": [ 0, 0, 0],

View File

@ -245,7 +245,8 @@
"support_use_towers": { "value": false }, "support_use_towers": { "value": false },
"support_xy_distance": { "value": "wall_line_width_0 * 2" }, "support_xy_distance": { "value": "wall_line_width_0 * 2" },
"support_xy_distance_overhang": { "value": "wall_line_width_0" }, "support_xy_distance_overhang": { "value": "wall_line_width_0" },
"support_z_distance": { "value": "layer_height if layer_height >= 0.16 else layer_height*2" }, "support_z_distance": { "value": "layer_height if layer_height >= 0.16 else layer_height * 2" },
"support_top_distance": { "value": "extruderValue(support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr, 'support_z_distance') + (layer_height if support_structure == 'tree' else 0)"},
"support_xy_overrides_z": { "value": "'xy_overrides_z'" }, "support_xy_overrides_z": { "value": "'xy_overrides_z'" },
"support_wall_count": { "value": 1 }, "support_wall_count": { "value": 1 },
"support_brim_enable": { "value": true }, "support_brim_enable": { "value": true },

View File

@ -48,10 +48,10 @@
}, },
"gantry_height":{ "value": "0" }, "gantry_height":{ "value": "0" },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "G90 ; use absolute coordinates\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nG28 ; home all without mesh bed level\nG29 ; mesh bed leveling/ABL\nM104 S[first_layer_temperature] ; set extruder temp\nG92 E0.0\nG1 Y-2.0 X150 F2400G1 Z3 F720\nM109 S[first_layer_temperature] ; wait for extruder temp\nG1 X150 F1000\nG1 Z0.2 F720\nG1 X80.0 E8.0 F900\nG1 X20.0 E10.0 F700\nG92 E0.0\nM221 S95 ; set flow\n" "default_value": "G21 ;Metric values\nG90 ;Absolute positioning\nM82 ;Set extruder to absolute mode\nM107 ;Start with the fan off\nG28 ;Homing the hotend\nG29 ;Auto bed leveling detecting\nG92 E0 ;Reset the extruded length\nG1 F200 E3 ;Extrude 3mm of filament\nG92 E0 ;Reset the extruded length again\nG1 Y-3 F1200 ;Move y axis to prime\nG1 X150 F6000 ;Move x axis to prime\nG1 Z0.2 F720 ;Move z axis to prime\nG1 X80.0 E8.0 F900 ;Prime line\nG1 X20.0 E10.0 F700 ;Prime line\nG92 E0 ;Reset the extruded length\nG5 ;Enable resume from power failure\nM117 Printing...\n"
}, },
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 S0 ; turn off extruder\nM140 S0 ; turn off bed\nM84 ; disable motors\nM107\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F{speed_travel} ;move Z up a bit and retract filament even more\nG28 X0 ;Y0 ;move X/Y to min endstops, so the head is out of the way\nG1 Y180 F2000\nM84 ;steppers off\nG90\nM300 P300 S4000" "default_value": "G91 ;Relative positioning\nG1 Z5 F720 ;Raise Z\nG1 E-5 F300 ;Retract a bit to protect nozzle\nM104 S0 ;Turn off extruder\nM140 S0 ;Turn off bed\nM107 ;Turn off all fans\nG90 ;Absolute positioning\nG1 X230 Y200 F4800 ;Parking the hotend\nM84 X Y E ;All steppers off but left Z\n"
}, },
"material_print_temperature": { "material_print_temperature": {
"value": 205 "value": 205

View File

@ -54,7 +54,7 @@
"value": 30 "value": 30
}, },
"machine_gcode_flavor": { "machine_gcode_flavor": {
"default_value": "Marlin" "default_value": "RepRap (Marlin/Sprinter)"
}, },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z10.0 F600 ;move the platform down 10mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 Y-3 F1200 ;move to prime\nG1 X10 F1200 ;\nG1 Z0.1 F600 ;get ready to prime\nG1 X120 E15 F1200 ;prime nozzle \nG1 X120 F3600 ;quick wipe\nG92 E0 ;zero the extruded length\nM413 S1 ;enable resume from power failure\nM117 Printing..." "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z10.0 F600 ;move the platform down 10mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 Y-3 F1200 ;move to prime\nG1 X10 F1200 ;\nG1 Z0.1 F600 ;get ready to prime\nG1 X120 E15 F1200 ;prime nozzle \nG1 X120 F3600 ;quick wipe\nG92 E0 ;zero the extruded length\nM413 S1 ;enable resume from power failure\nM117 Printing..."
@ -62,6 +62,112 @@
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 S0 ;turn off extruder\nM140 S0 ;turn off bed\nM107 ;turn off all fans\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;move Z up a bit and retract filament even more\nG90 ;absolute positioning\nG1 X0 Y250 F4800 ; position for easy part removal\nM84 ;steppers off" "default_value": "M104 S0 ;turn off extruder\nM140 S0 ;turn off bed\nM107 ;turn off all fans\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;move Z up a bit and retract filament even more\nG90 ;absolute positioning\nG1 X0 Y250 F4800 ; position for easy part removal\nM84 ;steppers off"
}, },
"layer_height": {
"value": 0.2
},
"layer_height_0": {
"resolve": "max(0.1, layer_height)"
},
"initial_layer_line_width_factor": {
"value": 120
},
"wall_line_count": {
"value": 3
},
"wall_thickness": {
"value": "line_width * wall_line_count"
},
"optimize_wall_printing_order": {
"default_value": true
},
"z_seam_type": {
"value": "'shortest'"
},
"z_seam_corner": {
"value": "'z_seam_corner_inner'"
},
"roofing_layer_count": {
"value": 1
},
"top_layers": {
"value": 6
},
"top_thickness":{
"value": "layer_height * top_layers"
},
"bottom_layers": {
"value": 4
},
"bottom_thickness":{
"value": "layer_height * bottom_layers"
},
"skin_overlap": {
"value": 10
},
"infill_sparse_density": {
"value": 20
},
"infill_pattern": {
"value": "'lines' if infill_sparse_density > 25 else 'grid'"
},
"infill_overlap": {
"value": "25 if infill_sparse_density < 95 and infill_pattern != 'concentric' else 0"
},
"infill_before_walls": {
"value": false
},
"inset_direction": {
"default_value": "inside_out"
},
"material_print_temperature": {
"value": "default_material_print_temperature",
"maximum_value_warning": 250
},
"material_print_temperature_layer_0": {
"value": "material_print_temperature + 5",
"maximum_value_warning": 250
},
"material_initial_print_temperature": {
"value": "material_print_temperature",
"maximum_value_warning": 250
},
"material_final_print_temperature": {
"value": "material_print_temperature"
},
"material_bed_temperature": {
"value": "default_material_bed_temperature",
"maximum_value_warning": 100
},
"material_bed_temperature_layer_0": {
"value": "material_bed_temperature"
},
"speed_infill": {
"value": "speed_print"
},
"speed_wall": {
"value": "speed_print"
},
"speed_wall_0": {
"value": "math.ceil(speed_print * 30 / 50)"
},
"speed_wall_x": {
"value": "speed_print"
},
"speed_topbottom": {
"value": "math.ceil(speed_print * 20 / 50)"
},
"speed_travel": {
"value": "speed_print if magic_spiralize else 120"
},
"speed_layer_0": {
"value": "math.ceil(speed_print * 30 / 50)"
},
"skirt_brim_speed": {
"value": "math.ceil(speed_print * 40 / 60)"
},
"speed_z_hop": {
"value": "math.ceil(speed_print * 30 / 60)"
},
"acceleration_enabled": { "acceleration_enabled": {
"value": true "value": true
}, },
@ -71,38 +177,6 @@
"acceleration_travel": { "acceleration_travel": {
"value": 1500 "value": 1500
}, },
"adhesion_type": {
"value": "'skirt'"
},
"brim_width": {
"value": 5
},
"cool_fan_full_at_height": {
"value": 0.5
},
"cool_fan_speed": {
"value": 100
},
"cool_fan_speed_0": {
"value": 0
},
"infill_overlap": {
"value": "25 if infill_sparse_density < 95 and infill_pattern != 'concentric' else 0",
"maximum_value_warning": 100,
"minimum_value_warning": -50
},
"infill_pattern": {
"value": "'lines' if infill_sparse_density > 25 else 'grid'"
},
"infill_sparse_density": {
"value": 20
},
"initial_layer_line_width_factor": {
"value": 120
},
"infill_before_walls": {
"value": false
},
"jerk_enabled": { "jerk_enabled": {
"value": true "value": true
}, },
@ -112,35 +186,11 @@
"jerk_travel": { "jerk_travel": {
"value": 15 "value": 15
}, },
"material_bed_temperature": {
"maximum_value_warning": 100
},
"material_print_temperature": {
"maximum_value_warning": 250
},
"optimize_wall_printing_order": {
"default_value": true
},
"inset_direction": {
"default_value": "inside_out"
},
"retract_at_layer_change": { "retract_at_layer_change": {
"value": true "value": true
}, },
"retraction_amount": { "retraction_amount": {
"default_value": 4 "default_value": 4.5
},
"retraction_hop": {
"value": 0.075
},
"retraction_hop_enabled": {
"value": false
},
"retraction_hop_only_when_collides": {
"value": true
},
"retraction_min_travel": {
"value": 1.5
}, },
"retraction_speed": { "retraction_speed": {
"default_value": 85, "default_value": 85,
@ -153,101 +203,56 @@
"value": "math.ceil(retraction_speed * 0.4)", "value": "math.ceil(retraction_speed * 0.4)",
"maximum_value_warning": 130 "maximum_value_warning": 130
}, },
"retraction_min_travel": {
"value": "max(line_width * 2, 1.5)"
},
"retraction_combing": { "retraction_combing": {
"value": "'off' if retraction_hop_enabled else 'noskin'" "value": "'off' if retraction_hop_enabled else 'noskin'"
}, },
"skin_overlap": {
"value": 10
},
"skirt_brim_speed": {
"value": "math.ceil(speed_print * 40 / 60)"
},
"skirt_gap": {
"value": 5
},
"skirt_line_count": {
"value": 3
},
"speed_infill": {
"value": "speed_print"
},
"speed_topbottom": {
"value": "math.ceil(speed_print * 20 / 50)"
},
"speed_travel": {
"value": "120"
},
"speed_layer_0": {
"value": "math.ceil(speed_print * 30 / 50)"
},
"speed_wall": {
"value": "speed_print"
},
"speed_wall_0": {
"value": "math.ceil(speed_print * 30 / 50)"
},
"speed_wall_x": {
"value": "speed_print"
},
"support_angle": {
"value": 50
},
"support_enable": {
"default_value": false
},
"support_interface_enable": {
"value": true
},
"support_pattern": {
"value": "'triangles'"
},
"support_roof_enable": {
"value": true
},
"support_type": {
"value": "'everywhere'"
},
"support_use_towers": {
"value": false
},
"support_z_distance": {
"value": 0.3
},
"support_xy_distance": {
"value": 0.7
},
"support_xy_distance_overhang": {
"value": 0.2
},
"smooth_spiralized_contours": {
"value": false
},
"travel_retract_before_outer_wall": { "travel_retract_before_outer_wall": {
"value": true "value": true
}, },
"wall_line_count": { "retraction_hop_enabled": {
"value": false
},
"retraction_hop_only_when_collides": {
"value": true
},
"retraction_hop": {
"value": 0.1
},
"support_pattern": {
"value": "'triangles'"
},
"support_z_distance": {
"value": 0.3
},
"support_interface_enable": {
"value": true
},
"support_roof_enable": {
"value": true
},
"support_use_towers": {
"value": false
},
"adhesion_type": {
"value": "'skirt'"
},
"skirt_line_count": {
"value": 3 "value": 3
},
"wall_thickness": {
"value": "line_width * wall_line_count"
}, },
"bottom_layers": { "skirt_gap": {
"value": "4" "value": 5
}, },
"bottom_thickness":{ "brim_width": {
"value": "layer_height * bottom_layers" "value": 5
}, },
"top_layers": { "smooth_spiralized_contours": {
"value": "6" "value": false
}, },
"top_thickness":{ "roofing_monotonic": {
"value": "layer_height * top_layers" "value": true
},
"z_seam_type": {
"value": "'shortest'"
},
"z_seam_corner": {
"value": "'z_seam_corner_inner'"
} }
} }
} }

View File

@ -6,7 +6,7 @@
"type": "extruder", "type": "extruder",
"author": "Ultimaker", "author": "Ultimaker",
"manufacturer": "Unknown", "manufacturer": "Unknown",
"setting_version": 18, "setting_version": 19,
"visible": false, "visible": false,
"position": "0" "position": "0"
}, },

View File

@ -4,9 +4,9 @@
"metadata": "metadata":
{ {
"type": "machine", "type": "machine",
"author": "Ultimaker", "author": "Unknown",
"manufacturer": "Unknown", "manufacturer": "Unknown",
"setting_version": 18, "setting_version": 19,
"file_formats": "text/x-gcode;model/stl;application/x-wavefront-obj;application/x3g", "file_formats": "text/x-gcode;model/stl;application/x-wavefront-obj;application/x3g",
"visible": false, "visible": false,
"has_materials": true, "has_materials": true,
@ -1056,6 +1056,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "line_width", "minimum_value_warning": "line_width",
"maximum_value_warning": "10 * line_width", "maximum_value_warning": "10 * line_width",
"maximum_value": "999999 * line_width",
"type": "float", "type": "float",
"limit_to_extruder": "wall_x_extruder_nr", "limit_to_extruder": "wall_x_extruder_nr",
"settable_per_mesh": true, "settable_per_mesh": true,
@ -1069,6 +1070,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "1", "minimum_value_warning": "1",
"maximum_value_warning": "10", "maximum_value_warning": "10",
"maximum_value": "999999",
"type": "int", "type": "int",
"value": "1 if magic_spiralize else max(1, round((wall_thickness - wall_line_width_0) / wall_line_width_x) + 1) if wall_thickness != 0 else 0", "value": "1 if magic_spiralize else max(1, round((wall_thickness - wall_line_width_0) / wall_line_width_x) + 1) if wall_thickness != 0 else 0",
"limit_to_extruder": "wall_x_extruder_nr", "limit_to_extruder": "wall_x_extruder_nr",
@ -1613,6 +1615,7 @@
"default_value": 1, "default_value": 1,
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "10", "maximum_value_warning": "10",
"maximum_value": "999999",
"type": "int", "type": "int",
"enabled": "(top_layers > 0 or bottom_layers > 0) and (top_bottom_pattern != 'concentric' or top_bottom_pattern_0 != 'concentric' or (roofing_layer_count > 0 and roofing_pattern != 'concentric'))", "enabled": "(top_layers > 0 or bottom_layers > 0) and (top_bottom_pattern != 'concentric' or top_bottom_pattern_0 != 'concentric' or (roofing_layer_count > 0 and roofing_pattern != 'concentric'))",
"limit_to_extruder": "top_bottom_extruder_nr", "limit_to_extruder": "top_bottom_extruder_nr",
@ -2055,6 +2058,7 @@
"default_value": 0, "default_value": 0,
"type": "int", "type": "int",
"minimum_value": "0", "minimum_value": "0",
"maximum_value": "999999",
"enabled": "infill_sparse_density > 0", "enabled": "infill_sparse_density > 0",
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
@ -2139,9 +2143,9 @@
"default_value": 0, "default_value": 0,
"type": "int", "type": "int",
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "1 if (infill_pattern == 'cross' or infill_pattern == 'cross_3d' or support_pattern == 'concentric') else 5", "maximum_value_warning": "1 if (infill_pattern == 'cross' or infill_pattern == 'cross_3d' or infill_pattern == 'concentric') else 5",
"maximum_value": "999999 if infill_line_distance == 0 else (20 - math.log(infill_line_distance) / math.log(2))", "maximum_value": "999999 if infill_line_distance == 0 else (20 - math.log(infill_line_distance) / math.log(2))",
"enabled": "infill_pattern != 'lightning' and infill_sparse_density > 0 and infill_pattern != 'cubicsubdiv'", "enabled": "infill_sparse_density > 0 and infill_pattern not in ['cubicsubdiv', 'cross', 'cross_3d', 'lightning']",
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -2154,7 +2158,7 @@
"default_value": 1.5, "default_value": 1.5,
"minimum_value": "0.0001", "minimum_value": "0.0001",
"minimum_value_warning": "3 * resolveOrValue('layer_height')", "minimum_value_warning": "3 * resolveOrValue('layer_height')",
"enabled": "infill_pattern != 'lightning' and infill_sparse_density > 0 and gradual_infill_steps > 0 and infill_pattern != 'cubicsubdiv'", "enabled": "infill_sparse_density > 0 and gradual_infill_steps > 0 and infill_pattern not in ['cubicsubdiv', 'cross', 'cross_3d', 'lightning']",
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -2508,7 +2512,42 @@
"maximum_value_warning": "120", "maximum_value_warning": "120",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false, "settable_per_extruder": false,
"resolve": "sum(extruderValues(\"material_shrinkage_percentage\")) / len(extruderValues(\"material_shrinkage_percentage\"))" "resolve": "sum(extruderValues(\"material_shrinkage_percentage\")) / len(extruderValues(\"material_shrinkage_percentage\"))",
"children":
{
"material_shrinkage_percentage_xy":
{
"label": "Horizontal Scaling Factor Shrinkage Compensation",
"description": "To compensate for the shrinkage of the material as it cools down, the model will be scaled with this factor in the XY-direction (horizontally).",
"unit": "%",
"type": "float",
"default_value": 100.0,
"enabled": false,
"minimum_value": "0.001",
"minimum_value_warning": "100",
"maximum_value_warning": "120",
"settable_per_mesh": false,
"settable_per_extruder": false,
"resolve": "sum(extruderValues(\"material_shrinkage_percentage_xy\")) / len(extruderValues(\"material_shrinkage_percentage_xy\"))",
"value": "material_shrinkage_percentage"
},
"material_shrinkage_percentage_z":
{
"label": "Vertical Scaling Factor Shrinkage Compensation",
"description": "To compensate for the shrinkage of the material as it cools down, the model will be scaled with this factor in the Z-direction (vertically).",
"unit": "%",
"type": "float",
"default_value": 100.0,
"enabled": false,
"minimum_value": "0.001",
"minimum_value_warning": "100",
"maximum_value_warning": "120",
"settable_per_mesh": false,
"settable_per_extruder": false,
"resolve": "sum(extruderValues(\"material_shrinkage_percentage_z\")) / len(extruderValues(\"material_shrinkage_percentage_z\"))",
"value": "material_shrinkage_percentage"
}
}
}, },
"material_crystallinity": "material_crystallinity":
{ {
@ -4491,6 +4530,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "1 if support_pattern == 'concentric' else 0", "minimum_value_warning": "1 if support_pattern == 'concentric' else 0",
"maximum_value_warning": "0 if (support_skip_some_zags and support_pattern == 'zigzag') else 3", "maximum_value_warning": "0 if (support_skip_some_zags and support_pattern == 'zigzag') else 3",
"maximum_value": "999999",
"type": "int", "type": "int",
"value": "1 if support_enable and support_structure == 'tree' else (1 if (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'concentric') else 0)", "value": "1 if support_enable and support_structure == 'tree' else (1 if (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'concentric') else 0)",
"enabled": "support_enable or support_meshes_present", "enabled": "support_enable or support_meshes_present",
@ -4601,6 +4641,7 @@
"default_value": 8.0, "default_value": 8.0,
"minimum_value": "0.0", "minimum_value": "0.0",
"maximum_value_warning": "50.0", "maximum_value_warning": "50.0",
"maximum_value": "0.5 * min(machine_width, machine_depth)",
"enabled": "(support_enable or support_meshes_present) and support_brim_enable", "enabled": "(support_enable or support_meshes_present) and support_brim_enable",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -4615,6 +4656,7 @@
"default_value": 20, "default_value": 20,
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "50 / skirt_brim_line_width", "maximum_value_warning": "50 / skirt_brim_line_width",
"maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width",
"value": "math.ceil(support_brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))", "value": "math.ceil(support_brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))",
"enabled": "(support_enable or support_meshes_present) and support_brim_enable", "enabled": "(support_enable or support_meshes_present) and support_brim_enable",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -4647,7 +4689,7 @@
"default_value": 0.1, "default_value": 0.1,
"type": "float", "type": "float",
"enabled": "support_enable or support_meshes_present", "enabled": "support_enable or support_meshes_present",
"value": "extruderValue(support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr, 'support_z_distance')", "value": "extruderValue(support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr, 'support_z_distance') + (layer_height if support_structure == 'tree' else 0)",
"limit_to_extruder": "support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -5378,6 +5420,7 @@
"default_value": 1, "default_value": 1,
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "10", "maximum_value_warning": "10",
"maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width",
"enabled": "resolveOrValue('adhesion_type') == 'skirt'", "enabled": "resolveOrValue('adhesion_type') == 'skirt'",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -7528,8 +7571,7 @@
"unit": "%", "unit": "%",
"default_value": 100, "default_value": 100,
"type": "float", "type": "float",
"minimum_value": "5", "minimum_value": "0.0001",
"maximum_value": "500",
"minimum_value_warning": "50", "minimum_value_warning": "50",
"maximum_value_warning": "150", "maximum_value_warning": "150",
"enabled": "bridge_settings_enabled and bridge_enable_more_layers", "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
@ -7542,9 +7584,9 @@
"unit": "%", "unit": "%",
"default_value": 75, "default_value": 75,
"type": "float", "type": "float",
"minimum_value": "5", "minimum_value": "0",
"maximum_value": "100",
"minimum_value_warning": "20", "minimum_value_warning": "20",
"maximum_value_warning": "100",
"enabled": "bridge_settings_enabled and bridge_enable_more_layers", "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -7581,8 +7623,7 @@
"unit": "%", "unit": "%",
"default_value": 110, "default_value": 110,
"type": "float", "type": "float",
"minimum_value": "5", "minimum_value": "0.001",
"maximum_value": "500",
"minimum_value_warning": "50", "minimum_value_warning": "50",
"maximum_value_warning": "150", "maximum_value_warning": "150",
"enabled": "bridge_settings_enabled and bridge_enable_more_layers", "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
@ -7595,9 +7636,9 @@
"unit": "%", "unit": "%",
"default_value": 80, "default_value": 80,
"type": "float", "type": "float",
"minimum_value": "5", "minimum_value": "0",
"maximum_value": "100",
"minimum_value_warning": "20", "minimum_value_warning": "20",
"maximum_value_warning": "100",
"enabled": "bridge_settings_enabled and bridge_enable_more_layers", "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -7866,6 +7907,16 @@
"maximum_value_warning": "100", "maximum_value_warning": "100",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"material_alternate_walls":
{
"label": "Alternate Wall Directions",
"description": "Alternate wall directions every other layer and inset. Useful for materials that can build up stress, like for metal printing.",
"type": "bool",
"default_value": false,
"enabled": false,
"settable_per_mesh": true,
"settable_per_extruder": true
},
"raft_remove_inside_corners": "raft_remove_inside_corners":
{ {
"label": "Remove Raft Inside Corners", "label": "Remove Raft Inside Corners",

View File

@ -37,9 +37,15 @@
}, },
"machine_extruder_count": { "machine_extruder_count": {
"default_value": 2 "default_value": 2
},
"machine_extruders_share_heater": {
"default_value": true
},
"machine_extruders_share_nozzle": {
"default_value": true
}, },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "G21\nG90\nM107\nG28 X0 Y0\nG28 Z0\nG1 Z15.0 F300\nT0\nG92 E0\nG1 F700 E-80\nT1\nG92 E0\nG1 F1000 X1 Y1 Z0.3\nG1 F600 X200 E60\nG1 F1000 Y3\nG1 F600 X1 E120\nT1\nG92 E0\nG28 X0 Y0\nG1 F700 E-80\nT0\nG92 E0" "default_value": "M104 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nG21\nG90 \nG28 X0 Y0 \nG28 Z0 \nG1 Z15.0 F300 \nT0 \nG92 E0 \nG1 F700 E-80 \nT1 \nG92 E0 \nG1 F1000 X1 Y1 Z0.3 \nG1 F600 X200 E60 \nG1 F1000 Y3 \nG1 F600 X1 E120 \nT1 \nG92 E0 \nG28 X0 Y0 \nG1 F700 E-80 \nT0 \nG92 E0"
}, },
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 T0 S0\nM104 T1 S0\nM140 S0\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84" "default_value": "M104 T0 S0\nM104 T1 S0\nM140 S0\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"

View File

@ -37,9 +37,15 @@
}, },
"machine_extruder_count": { "machine_extruder_count": {
"default_value": 2 "default_value": 2
},
"machine_extruders_share_heater": {
"default_value": true
},
"machine_extruders_share_nozzle": {
"default_value": true
}, },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "G21\nG90\nM107\nG28 X0 Y0\nG28 Z0\nG1 Z15.0 F300\nT0\nG92 E0\nG1 F700 E-80\nT1\nG92 E0\nG1 F1000 X1 Y1 Z0.3\nG1 F600 X200 E60\nG1 F1000 Y3\nG1 F600 X1 E120\nT1\nG92 E0\nG28 X0 Y0\nG1 F700 E-80\nT0\nG92 E0" "default_value": "M104 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nG21\nG90 \nG28 X0 Y0 \nG28 Z0 \nG1 Z15.0 F300 \nT0 \nG92 E0 \nG1 F700 E-80 \nT1 \nG92 E0 \nG1 F1000 X1 Y1 Z0.3 \nG1 F600 X200 E60 \nG1 F1000 Y3 \nG1 F600 X1 E120 \nT1 \nG92 E0 \nG28 X0 Y0 \nG1 F700 E-80 \nT0 \nG92 E0"
}, },
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 T0 S0\nM104 T1 S0\nM140 S0\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84" "default_value": "M104 T0 S0\nM104 T1 S0\nM140 S0\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"

View File

@ -38,6 +38,12 @@
"machine_extruder_count": { "machine_extruder_count": {
"default_value": 2 "default_value": 2
}, },
"machine_extruders_share_heater": {
"default_value": true
},
"machine_extruders_share_nozzle": {
"default_value": true
},
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "M104 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nG21\nG90 \nG28 X0 Y0 \nG28 Z0 \nG1 Z15.0 F300 \nT0 \nG92 E0 \nG1 F700 E-80 \nT1 \nG92 E0 \nG1 F1000 X1 Y1 Z0.3 \nG1 F600 X200 E60 \nG1 F1000 Y3 \nG1 F600 X1 E120 \nT1 \nG92 E0 \nG28 X0 Y0 \nG1 F700 E-80 \nT0 \nG92 E0" "default_value": "M104 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nG21\nG90 \nG28 X0 Y0 \nG28 Z0 \nG1 Z15.0 F300 \nT0 \nG92 E0 \nG1 F700 E-80 \nT1 \nG92 E0 \nG1 F1000 X1 Y1 Z0.3 \nG1 F600 X200 E60 \nG1 F1000 Y3 \nG1 F600 X1 E120 \nT1 \nG92 E0 \nG28 X0 Y0 \nG1 F700 E-80 \nT0 \nG92 E0"
}, },

View File

@ -37,6 +37,12 @@
}, },
"machine_extruder_count": { "machine_extruder_count": {
"default_value": 2 "default_value": 2
},
"machine_extruders_share_heater": {
"default_value": true
},
"machine_extruders_share_nozzle": {
"default_value": true
}, },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "M104 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nG21\nG90 \nG28 X0 Y0 \nG28 Z0 \nG1 Z15.0 F300 \nT0 \nG92 E0 \nG1 F700 E-80 \nT1 \nG92 E0 \nG1 F1000 X1 Y1 Z0.3 \nG1 F600 X200 E60 \nG1 F1000 Y3 \nG1 F600 X1 E120 \nT1 \nG92 E0 \nG28 X0 Y0 \nG1 F700 E-80 \nT0 \nG92 E0" "default_value": "M104 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nG21\nG90 \nG28 X0 Y0 \nG28 Z0 \nG1 Z15.0 F300 \nT0 \nG92 E0 \nG1 F700 E-80 \nT1 \nG92 E0 \nG1 F1000 X1 Y1 Z0.3 \nG1 F600 X200 E60 \nG1 F1000 Y3 \nG1 F600 X1 E120 \nT1 \nG92 E0 \nG28 X0 Y0 \nG1 F700 E-80 \nT0 \nG92 E0"

View File

@ -0,0 +1,41 @@
{
"version": 2,
"name": "Hellbot Magna SE",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "Hellbot Development Team",
"manufacturer": "Hellbot",
"file_formats": "text/x-gcode",
"platform": "hellbot_magna_SE.obj",
"platform_texture": "hellbot_magna_SE.png",
"has_materials": true,
"machine_extruder_trains":
{
"0": "hellbot_magna_SE_extruder"
}
},
"overrides": {
"machine_name": { "default_value": "Hellbot Magna SE" },
"machine_width": {
"default_value": 230
},
"machine_depth": {
"default_value": 230
},
"machine_height": {
"default_value": 250
},
"machine_heated_bed": {
"default_value": true
},
"machine_center_is_zero": {
"default_value": false
},
"machine_extruder_count": {
"default_value": 1
}
}
}

View File

@ -4,7 +4,6 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Ultimaker",
"manufacturer": "Fracktal", "manufacturer": "Fracktal",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform_offset": [ 0, 0, 0], "platform_offset": [ 0, 0, 0],

View File

@ -4,7 +4,6 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Ultimaker",
"manufacturer": "MakerBot", "manufacturer": "MakerBot",
"machine_x3g_variant": "r1", "machine_x3g_variant": "r1",
"file_formats": "application/x3g", "file_formats": "application/x3g",

View File

@ -4,7 +4,6 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Ultimaker",
"manufacturer": "ORD Solutions", "manufacturer": "ORD Solutions",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"machine_extruder_trains": "machine_extruder_trains":

View File

@ -4,7 +4,6 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Ultimaker",
"manufacturer": "Punchtec", "manufacturer": "Punchtec",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"machine_extruder_trains": "machine_extruder_trains":

View File

@ -4,7 +4,6 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Ultimaker",
"manufacturer": "Robo 3D", "manufacturer": "Robo 3D",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform_offset": [ 0, 0, 0], "platform_offset": [ 0, 0, 0],

View File

@ -0,0 +1,51 @@
{
"version": 2,
"name": "Volumic SH65",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "Volumic",
"manufacturer": "Volumic",
"file_formats": "text/x-gcode",
"icon": "volumic-icon",
"platform": "SH65_platform.STL",
"has_materials": true,
"has_machine_quality": true,
"machine_extruder_trains":{"0": "sh65_extruder"}
},
"overrides": {
"machine_name": { "default_value": "VOLUMIC SH65" },
"machine_heated_bed": { "default_value": true },
"machine_width": { "default_value": 650 },
"machine_height": { "default_value": 300 },
"machine_depth": { "default_value": 300 },
"machine_center_is_zero": { "default_value": false },
"material_diameter": { "default_value": 1.75 },
"machine_nozzle_size": { "default_value": 0.4 },
"layer_height": { "default_value": 0.1 },
"layer_height_0": { "default_value": 0.1 },
"retraction_amount": { "default_value": 2.40 },
"retraction_speed": { "default_value": 30 },
"adhesion_type": { "default_value": "none" },
"infill_sparse_density": { "default_value": 25 },
"fill_outline_gaps": { "default_value": true },
"retract_at_layer_change": { "default_value": true },
"retraction_combing_max_distance": { "default_value": 200 },
"machine_head_with_fans_polygon": { "default_value": [[-38,30],[38,30],[38,-40],[-38,-40]] },
"machine_max_feedrate_z": { "default_value": 30 },
"machine_max_feedrate_e": { "default_value": 60 },
"machine_max_acceleration_z": { "default_value": 500 },
"machine_acceleration": { "default_value": 2000 },
"machine_max_jerk_xy": { "default_value": 10 },
"machine_max_jerk_z": { "default_value": 0.4 },
"machine_max_jerk_e": { "default_value": 5 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
"default_value": "M117 Demarrage\nM106 S0\nM140 S{material_bed_temperature_layer_0}\nM104 T0 S{material_print_temperature_layer_0}\nG28\nG90\nM82\nG92 E0\nG1 Z3 F600\n;M190 S{material_bed_temperature_layer_0}\nM109 T0 S{material_print_temperature_layer_0}\nM300 P350\nM117 Purge\nG1 Z0.15 F600\nG1 E10 F400\nG92 E0\nM117 Impression"
},
"machine_end_gcode": {
"default_value": "M107\nG91\nT0\nG1 E-1\nM104 T0 S0\nG90\nG0 X1 Y190 F5000\nG92 E0\nM140 S0\nM84\nM300"
}
}
}

View File

@ -26,7 +26,7 @@
"default_value": true "default_value": true
}, },
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "M104 S{material_print_temperature} ;Set Hotend Temperature\nM140 S{material_bed_temperature} ;Set Bed Temperature\nG28 ;home\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000 ;Move to corner \nG1 Z0 F1800 ;Go to zero offset\nM109 S{material_print_temperature} ;Wait for Hotend Temperature\nM190 S{material_bed_temperature} ;Wait for Bed Temperature\nG92 E0 ;Zero set extruder position\nG1 E20 F200 ;Feed filament to clear nozzle\nG92 E0 ;Zero set extruder position" "default_value": "M104 S{material_print_temperature_layer_0} ;Set Hotend Temperature\nM140 S{material_bed_temperature_layer_0} ;Set Bed Temperature\nG28 ;home\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000 ;Move to corner \nG1 Z0 F1800 ;Go to zero offset\nM109 S{material_print_temperature_layer_0} ;Wait for Hotend Temperature\nM190 S{material_bed_temperature_layer_0} ;Wait for Bed Temperature\nG92 E0 ;Zero set extruder position\nG1 E20 F200 ;Feed filament to clear nozzle\nG92 E0 ;Zero set extruder position"
}, },
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 S0 ;Extruder heater off\nM140 S0 ;Heated bed heater off\nG90 ;absolute positioning\nG92 E0 ;Retract the filament\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z{machine_width} E-1 F3000 ;move Z up a bit and retract filament even more\nG1 X0 F3000 ;move X to min endstops, so the head is out of the way\nG1 Y{machine_depth} F3000 ;so the head is out of the way and Plate is moved forward" "default_value": "M104 S0 ;Extruder heater off\nM140 S0 ;Heated bed heater off\nG90 ;absolute positioning\nG92 E0 ;Retract the filament\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z{machine_width} E-1 F3000 ;move Z up a bit and retract filament even more\nG1 X0 F3000 ;move X to min endstops, so the head is out of the way\nG1 Y{machine_depth} F3000 ;so the head is out of the way and Plate is moved forward"

View File

@ -0,0 +1,51 @@
{
"version": 2,
"name": "Volumic Stream30Pro MK3",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "Volumic",
"manufacturer": "Volumic",
"file_formats": "text/x-gcode",
"icon": "volumic-icon",
"platform": "STREAM30ULTRA_platform.STL",
"has_materials": true,
"has_machine_quality": true,
"machine_extruder_trains":{"0": "stream30mk3_extruder"}
},
"overrides": {
"machine_name": { "default_value": "VOLUMIC STREAM30PRO MK3" },
"machine_heated_bed": { "default_value": true },
"machine_width": { "default_value": 300 },
"machine_height": { "default_value": 310 },
"machine_depth": { "default_value": 200 },
"machine_center_is_zero": { "default_value": false },
"material_diameter": { "default_value": 1.75 },
"machine_nozzle_size": { "default_value": 0.4 },
"layer_height": { "default_value": 0.1 },
"layer_height_0": { "default_value": 0.1 },
"retraction_amount": { "default_value": 2.40 },
"retraction_speed": { "default_value": 30 },
"adhesion_type": { "default_value": "none" },
"infill_sparse_density": { "default_value": 25 },
"fill_outline_gaps": { "default_value": true },
"retract_at_layer_change": { "default_value": true },
"retraction_combing_max_distance": { "default_value": 200 },
"machine_head_with_fans_polygon": { "default_value": [[-38,30],[38,30],[38,-40],[-38,-40]] },
"machine_max_feedrate_z": { "default_value": 30 },
"machine_max_feedrate_e": { "default_value": 60 },
"machine_max_acceleration_z": { "default_value": 500 },
"machine_acceleration": { "default_value": 2000 },
"machine_max_jerk_xy": { "default_value": 10 },
"machine_max_jerk_z": { "default_value": 0.4 },
"machine_max_jerk_e": { "default_value": 5 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
"default_value": "M117 Demarrage\nM106 S0\nM140 S{material_bed_temperature_layer_0}\nM104 T0 S{material_print_temperature_layer_0}\nG28\nG90\nM82\nG92 E0\nG1 Z3 F600\n;M190 S{material_bed_temperature_layer_0}\nM109 T0 S{material_print_temperature_layer_0}\nM300 P350\nM117 Purge\nG1 Z0.15 F600\nG1 E10 F400\nG92 E0\nM117 Impression"
},
"machine_end_gcode": {
"default_value": "M107\nG91\nT0\nG1 E-1\nM104 T0 S0\nG90\nG0 X1 Y190 F5000\nG92 E0\nM140 S0\nM84\nM300"
}
}
}

View File

@ -0,0 +1,51 @@
{
"version": 2,
"name": "Volumic Stream30Ultra SC2",
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "Volumic",
"manufacturer": "Volumic",
"file_formats": "text/x-gcode",
"icon": "volumic-icon",
"platform": "STREAM30ULTRA_platform.STL",
"has_materials": true,
"has_machine_quality": true,
"machine_extruder_trains":{"0": "stream30ultrasc2_extruder"}
},
"overrides": {
"machine_name": { "default_value": "VOLUMIC STREAM30ULTRA SC2" },
"machine_heated_bed": { "default_value": true },
"machine_width": { "default_value": 300 },
"machine_height": { "default_value": 310 },
"machine_depth": { "default_value": 200 },
"machine_center_is_zero": { "default_value": false },
"material_diameter": { "default_value": 1.75 },
"machine_nozzle_size": { "default_value": 0.4 },
"layer_height": { "default_value": 0.1 },
"layer_height_0": { "default_value": 0.1 },
"retraction_amount": { "default_value": 2.40 },
"retraction_speed": { "default_value": 30 },
"adhesion_type": { "default_value": "none" },
"infill_sparse_density": { "default_value": 25 },
"fill_outline_gaps": { "default_value": true },
"retract_at_layer_change": { "default_value": true },
"retraction_combing_max_distance": { "default_value": 200 },
"machine_head_with_fans_polygon": { "default_value": [[-38,30],[38,30],[38,-40],[-38,-40]] },
"machine_max_feedrate_z": { "default_value": 30 },
"machine_max_feedrate_e": { "default_value": 60 },
"machine_max_acceleration_z": { "default_value": 500 },
"machine_acceleration": { "default_value": 2000 },
"machine_max_jerk_xy": { "default_value": 10 },
"machine_max_jerk_z": { "default_value": 0.4 },
"machine_max_jerk_e": { "default_value": 5 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
"default_value": "M117 Demarrage\nM106 S0\nM140 S{material_bed_temperature_layer_0}\nM104 T0 S{material_print_temperature_layer_0}\nG28\nG90\nM82\nG92 E0\nG1 Z3 F600\n;M190 S{material_bed_temperature_layer_0}\nM109 T0 S{material_print_temperature_layer_0}\nM300 P350\nM117 Purge\nG1 Z0.15 F600\nG1 E10 F400\nG92 E0\nM117 Impression"
},
"machine_end_gcode": {
"default_value": "M107\nG91\nT0\nG1 E-1\nM104 T0 S0\nG90\nG0 X1 Y190 F5000\nG92 E0\nM140 S0\nM84\nM300"
}
}
}

View File

@ -81,7 +81,7 @@
"material_bed_temperature_layer_0": { "maximum_value": 110 }, "material_bed_temperature_layer_0": { "maximum_value": 110 },
"material_print_temperature": { "maximum_value": 260 }, "material_print_temperature": { "maximum_value": 260 },
"meshfix_maximum_resolution": { "value": "(speed_wall_0 + speed_wall_x) / 60" }, "meshfix_maximum_resolution": { "value": "(speed_wall_0 + speed_wall_x) / 60" },
"meshfix_maximum_deviation": { "value": "layer_height / 4" }, "meshfix_maximum_deviation": { "value": "layer_height / 4" },
"meshfix_maximum_travel_resolution": { "value": 0.5 }, "meshfix_maximum_travel_resolution": { "value": 0.5 },
"prime_blob_enable": { "enabled": true, "default_value": true, "value": "resolveOrValue('print_sequence') != 'one_at_a_time'" } "prime_blob_enable": { "enabled": true, "default_value": true, "value": "resolveOrValue('print_sequence') != 'one_at_a_time'" }
} }

View File

@ -4,7 +4,6 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "Ultimaker",
"manufacturer": "Zone3D", "manufacturer": "Zone3D",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform_offset": [ 0, 0, 0], "platform_offset": [ 0, 0, 0],

View File

@ -18,7 +18,7 @@
"default_value": 1.75 "default_value": 1.75
}, },
"machine_nozzle_offset_x": { "machine_nozzle_offset_x": {
"default_value": -10.0 "default_value": 5
}, },
"machine_nozzle_offset_y": { "machine_nozzle_offset_y": {
"default_value": 8.0 "default_value": 8.0

View File

@ -13,6 +13,12 @@
"maximum_value": "1" "maximum_value": "1"
}, },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 } "material_diameter": { "default_value": 1.75 },
"machine_extruder_start_code": {
"default_value": "T0 \nG92 E0 \nG1 F1000 E100 \nG92 E0 \nM104 S{material_print_temperature}"
},
"machine_extruder_end_code": {
"default_value": "G92 E0 \nG1 F2500 E-5 \nG1 F2400 X230 Y200 \nG1 F3000 E-100 \nG92 E0 \nG90"
}
} }
} }

View File

@ -13,6 +13,12 @@
"maximum_value": "1" "maximum_value": "1"
}, },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 } "material_diameter": { "default_value": 1.75 },
"machine_extruder_start_code": {
"default_value": "T1 \nG92 E0 \nG1 F1000 E100 \nG92 E0 \nM104 S{material_print_temperature}"
},
"machine_extruder_end_code": {
"default_value": "G92 E0 \nG1 F2500 E-5 \nG1 F2400 X230 Y200 \nG1 F3000 E-100 \nG92 E0 \nG90"
}
} }
} }

View File

@ -13,6 +13,12 @@
"maximum_value": "1" "maximum_value": "1"
}, },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 } "material_diameter": { "default_value": 1.75 },
"machine_extruder_start_code": {
"default_value": "T0 \nG92 E0 \nG1 F1000 E100 \nG92 E0 \nM104 S{material_print_temperature}"
},
"machine_extruder_end_code": {
"default_value": "G92 E0 \nG1 F2500 E-5 \nG1 F2400 X300 Y250 \nG1 F3000 E-100 \nG92 E0 \nG90"
}
} }
} }

View File

@ -13,6 +13,12 @@
"maximum_value": "1" "maximum_value": "1"
}, },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 } "material_diameter": { "default_value": 1.75 },
"machine_extruder_start_code": {
"default_value": "T1 \nG92 E0 \nG1 F1000 E100 \nG92 E0 \nM104 S{material_print_temperature}"
},
"machine_extruder_end_code": {
"default_value": "G92 E0 \nG1 F2500 E-5 \nG1 F2400 X300 Y250 \nG1 F3000 E-100 \nG92 E0 \nG90"
}
} }
} }

View File

@ -0,0 +1,18 @@
{
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
"machine": "hellbot_magna_SE",
"position": "0"
},
"overrides": {
"extruder_nr": {
"default_value": 0,
"maximum_value": "1"
},
"machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 }
}
}

View File

@ -0,0 +1,21 @@
{
"version": 2,
"name": "Extruder",
"inherits": "fdmextruder",
"metadata": {
"machine": "sh65",
"position": "0"
},
"overrides": {
"extruder_nr": {
"default_value": 0
},
"machine_nozzle_size": {
"default_value": 0.4
},
"material_diameter": {
"default_value": 1.75
}
}
}

View File

@ -0,0 +1,21 @@
{
"version": 2,
"name": "Extruder",
"inherits": "fdmextruder",
"metadata": {
"machine": "stream30mk3",
"position": "0"
},
"overrides": {
"extruder_nr": {
"default_value": 0
},
"machine_nozzle_size": {
"default_value": 0.4
},
"material_diameter": {
"default_value": 1.75
}
}
}

View File

@ -0,0 +1,21 @@
{
"version": 2,
"name": "Extruder",
"inherits": "fdmextruder",
"metadata": {
"machine": "stream30ultrasc2",
"position": "0"
},
"overrides": {
"extruder_nr": {
"default_value": 0
},
"machine_nozzle_size": {
"default_value": 0.4
},
"material_diameter": {
"default_value": 1.75
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: 2020-02-20 17:30+0100\n" "PO-Revision-Date: 2020-02-20 17:30+0100\n"
"Last-Translator: DenyCZ <www.github.com/DenyCZ>\n" "Last-Translator: DenyCZ <www.github.com/DenyCZ>\n"
"Language-Team: DenyCZ <www.github.com/DenyCZ>\n" "Language-Team: DenyCZ <www.github.com/DenyCZ>\n"

View File

@ -5,9 +5,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 11:59+0000\n"
"PO-Revision-Date: 2021-04-04 19:37+0200\n" "PO-Revision-Date: 2021-04-04 19:37+0200\n"
"Last-Translator: Miroslav Šustek <sustmidown@centrum.cz>\n" "Last-Translator: Miroslav Šustek <sustmidown@centrum.cz>\n"
"Language-Team: DenyCZ <www.github.com/DenyCZ>\n" "Language-Team: DenyCZ <www.github.com/DenyCZ>\n"
@ -153,6 +153,16 @@ msgctxt "machine_depth description"
msgid "The depth (Y-direction) of the printable area." msgid "The depth (Y-direction) of the printable area."
msgstr "Hlouba (Isa Y) plochy k tisku." msgstr "Hlouba (Isa Y) plochy k tisku."
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Výška zařízení"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Výška (Osa Z) plochy k tisku."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_shape label" msgctxt "machine_shape label"
msgid "Build Plate Shape" msgid "Build Plate Shape"
@ -193,16 +203,6 @@ msgctxt "machine_buildplate_type option aluminum"
msgid "Aluminum" msgid "Aluminum"
msgstr "Hliník" msgstr "Hliník"
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Výška zařízení"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Výška (Osa Z) plochy k tisku."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_heated_bed label" msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate" msgid "Has Heated Build Plate"
@ -560,8 +560,8 @@ msgstr "Maximální rychlost pro motor ve směru Z."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e label" msgctxt "machine_max_feedrate_e label"
msgid "Maximum Feedrate" msgid "Maximum Speed E"
msgstr "Maximální feedrate" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e description" msgctxt "machine_max_feedrate_e description"
@ -1730,7 +1730,7 @@ msgstr "Výplňový vzor"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern description" msgctxt "infill_pattern description"
msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model." msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the ceiling of the object."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -1771,7 +1771,7 @@ msgstr "Oktet"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option quarter_cubic" msgctxt "infill_pattern option quarter_cubic"
msgid "Quarter Cubic" msgid "Quarter Cubic"
msgstr "Čtvrtina krychlove" msgstr "Čtvrtinově krychlový"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option concentric" msgctxt "infill_pattern option concentric"
@ -1781,7 +1781,7 @@ msgstr "Soustředný"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option zigzag" msgctxt "infill_pattern option zigzag"
msgid "Zig Zag" msgid "Zig Zag"
msgstr "Zig Zag" msgstr "Cik-cak"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option cross" msgctxt "infill_pattern option cross"
@ -1801,7 +1801,7 @@ msgstr "Gyroid"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option lightning" msgctxt "infill_pattern option lightning"
msgid "Lightning" msgid "Lightning"
msgstr "" msgstr "Bleskový"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "zig_zaggify_infill label" msgctxt "zig_zaggify_infill label"
@ -2020,41 +2020,41 @@ msgstr "Počet výplňových vrstev, které podporují okraje povrchu."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_support_angle label" msgctxt "lightning_infill_support_angle label"
msgid "Lightning Infill Support Angle" msgid "Lightning Infill Support Angle"
msgstr "" msgstr "Úhel podpory bleskové výplně"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_support_angle description" msgctxt "lightning_infill_support_angle description"
msgid "Determines when a lightning infill layer has to support anything above it. Measured in the angle given the thickness of a layer." msgid "Determines when a lightning infill layer has to support anything above it. Measured in the angle given the thickness of a layer."
msgstr "" msgstr "Určuje, kdy má vrstva bleskové výplně nad sebou něco, co má podporovat. Zadává se jako úhel a řídí se tloušťkou vrstvy."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_overhang_angle label" msgctxt "lightning_infill_overhang_angle label"
msgid "Lightning Infill Overhang Angle" msgid "Lightning Infill Overhang Angle"
msgstr "" msgstr "Úhel převisu bleskové podpory"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_overhang_angle description" msgctxt "lightning_infill_overhang_angle description"
msgid "Determines when a lightning infill layer has to support the model above it. Measured in the angle given the thickness." msgid "Determines when a lightning infill layer has to support the model above it. Measured in the angle given the thickness."
msgstr "" msgstr "Určuje, od jakého úhlu převisu bude vrstva bleskové výplň podporovat model nad sebou."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle label" msgctxt "lightning_infill_prune_angle label"
msgid "Lightning Infill Prune Angle" msgid "Lightning Infill Prune Angle"
msgstr "" msgstr "Úhel ústupu bleskové vrstvy"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle description" msgctxt "lightning_infill_prune_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness." msgid "The endpoints of infill lines are shortened to save on material. This setting is the angle of overhang of the endpoints of these lines."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle label" msgctxt "lightning_infill_straightening_angle label"
msgid "Lightning Infill Straightening Angle" msgid "Lightning Infill Straightening Angle"
msgstr "" msgstr "Úhel vyrovnávání bleskové vrstvy"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle description" msgctxt "lightning_infill_straightening_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness." msgid "The infill lines are straightened out to save on printing time. This is the maximum angle of overhang allowed across the length of the infill line."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -3250,7 +3250,7 @@ msgstr "Vše"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_combing option no_outer_surfaces" msgctxt "retraction_combing option no_outer_surfaces"
msgid "Not on Outer Surface" msgid "Not on Outer Surface"
msgstr "" msgstr "Ne na vnějším povrchu"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_combing option noskin" msgctxt "retraction_combing option noskin"
@ -5204,7 +5204,7 @@ msgstr "Minimální šířka formy"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "mold_width description" msgctxt "mold_width description"
msgid "The minimal distance between the outside of the mold and the outside of the model." msgid "The minimal distance between the outside of the mold and the outside of the model."
msgstr "" msgstr "Minimální vzdálenost mezi vnější stranou formy a modelu."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "mold_roof_height label" msgctxt "mold_roof_height label"
@ -6480,6 +6480,22 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file." msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Transformační matice, která se použije na model při načítání ze souboru." msgstr "Transformační matice, která se použije na model při načítání ze souboru."
#~ msgctxt "machine_max_feedrate_e label"
#~ msgid "Maximum Feedrate"
#~ msgstr "Maximální feedrate"
#~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model."
#~ msgstr "Vzor výplňového materiálu tisku. Čáry a cik-cak s každou vrstvou obracejí směr výplně, čímž se snižují náklady na materiál. Mřížka, trojúhelník, tri-hexagon, krychle, oktet, čtvrtinově krychlový, křížový a soustředný vzor jsou plně vytištěny v každé vrstvě. Vzory gyroid, krychlový, čtvrtinově krychlový a oktet se mění s každou vrstvou, aby se zajistilo rovnoměrnější rozložení síly v každém směru. Bleskový vzor se snaží minimalizovat množství výplně tím, že podporuje pouze horní povrchy objektu. U bleskového vzoru má procento význam pouze v první vrstvě pod každým povrchem."
#~ msgctxt "lightning_infill_prune_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness."
#~ msgstr "Určuje, pod jakým úhlem mezi jednotlivými vrstvami se větve bleskové výplně zkracují."
#~ msgctxt "lightning_infill_straightening_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness."
#~ msgstr "Určuje, pod jakým úhlem mezi jednotlivými vrstvami může docházet k vyrovnávání větví bleskové výplně."
#~ msgctxt "infill_pattern description" #~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction." #~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
#~ msgstr "Vzor výplňového materiálu tisku. Směr a cik-cak vyplňují směr výměny na alternativních vrstvách, čímž se snižují náklady na materiál. Mřížka, trojúhelník, tri-hexagon, krychlový, oktet, čtvrtý krychlový, křížový a soustředný obrazec jsou plně vytištěny v každé vrstvě. Výplň Gyroid, krychlový, kvartální a oktet se mění s každou vrstvou, aby se zajistilo rovnoměrnější rozložení síly v každém směru." #~ msgstr "Vzor výplňového materiálu tisku. Směr a cik-cak vyplňují směr výměny na alternativních vrstvách, čímž se snižují náklady na materiál. Mřížka, trojúhelník, tri-hexagon, krychlový, oktet, čtvrtý krychlový, křížový a soustředný obrazec jsou plně vytištěny v každé vrstvě. Výplň Gyroid, krychlový, kvartální a oktet se mění s každou vrstvou, aby se zajistilo rovnoměrnější rozložení síly v každém směru."

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: 2021-04-16 15:15+0200\n" "PO-Revision-Date: 2021-04-16 15:15+0200\n"
"Last-Translator: Bothof <info@bothof.nl>\n" "Last-Translator: Bothof <info@bothof.nl>\n"
"Language-Team: German\n" "Language-Team: German\n"

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 11:59+0000\n"
"PO-Revision-Date: 2021-04-16 15:16+0200\n" "PO-Revision-Date: 2021-04-16 15:16+0200\n"
"Last-Translator: Lionbridge <info@lionbridge.com>\n" "Last-Translator: Lionbridge <info@lionbridge.com>\n"
"Language-Team: German <info@lionbridge.com>, German <info@bothof.nl>\n" "Language-Team: German <info@lionbridge.com>, German <info@bothof.nl>\n"
@ -53,8 +53,10 @@ msgstr "Start G-Code"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_start_gcode description" msgctxt "machine_start_gcode description"
msgid "G-code commands to be executed at the very start - separated by \\n." msgid ""
msgstr "G-Code-Befehle, die zu Beginn ausgeführt werden sollen getrennt durch \\n." "G-code commands to be executed at the very start - separated by \n"
"."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_end_gcode label" msgctxt "machine_end_gcode label"
@ -63,8 +65,10 @@ msgstr "Ende G-Code"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_end_gcode description" msgctxt "machine_end_gcode description"
msgid "G-code commands to be executed at the very end - separated by \\n." msgid ""
msgstr "G-Code-Befehle, die am Ende ausgeführt werden sollen getrennt durch \\n." "G-code commands to be executed at the very end - separated by \n"
"."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "material_guid label" msgctxt "material_guid label"
@ -146,6 +150,16 @@ msgctxt "machine_depth description"
msgid "The depth (Y-direction) of the printable area." msgid "The depth (Y-direction) of the printable area."
msgstr "Die Tiefe (Y-Richtung) des druckbaren Bereichs." msgstr "Die Tiefe (Y-Richtung) des druckbaren Bereichs."
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Gerätehöhe"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Die Höhe (Z-Richtung) des druckbaren Bereichs."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_shape label" msgctxt "machine_shape label"
msgid "Build Plate Shape" msgid "Build Plate Shape"
@ -186,16 +200,6 @@ msgctxt "machine_buildplate_type option aluminum"
msgid "Aluminum" msgid "Aluminum"
msgstr "Aluminium" msgstr "Aluminium"
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Gerätehöhe"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Die Höhe (Z-Richtung) des druckbaren Bereichs."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_heated_bed label" msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate" msgid "Has Heated Build Plate"
@ -553,8 +557,8 @@ msgstr "Die Maximaldrehzahl für den Motor der Z-Richtung."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e label" msgctxt "machine_max_feedrate_e label"
msgid "Maximum Feedrate" msgid "Maximum Speed E"
msgstr "Maximaler Vorschub" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e description" msgctxt "machine_max_feedrate_e description"
@ -1723,12 +1727,8 @@ msgstr "Füllmuster"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern description" msgctxt "infill_pattern description"
msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model." msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the ceiling of the object."
msgstr "Das Muster des Füllmaterials des Drucks. Die Linien- und Zickzackfüllmethode wechseln nach jeder Schicht die Richtung, um Materialkosten zu reduzieren." msgstr ""
" Die Gitter-, Dreieck- Tri-Hexagon-, Würfel-, Octahedral-, Viertelwürfel-, Quer- und konzentrischen Muster werden in jeder Schicht vollständig gedruckt."
" Gyroid-, Würfel-, Viertelwürfel- und achtflächige Füllungen wechseln mit jeder Schicht, um eine gleichmäßigere Verteilung der Stärke in allen Richtungen"
" zu erzielen. Die Einstellung Blitz versucht, die Füllung zu minimieren, indem nur die (internen) Dächer des Objekts gestützt werden. Der gültige Prozentsatz"
" der Füllung bezieht sich daher nur auf die jeweilige Ebene unter dem zu stützenden Bereich des Modells."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option grid" msgctxt "infill_pattern option grid"
@ -2041,9 +2041,8 @@ msgstr "Beschnittwinkel der Blitz-Füllung"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle description" msgctxt "lightning_infill_prune_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness." msgid "The endpoints of infill lines are shortened to save on material. This setting is the angle of overhang of the endpoints of these lines."
msgstr "Der Unterschied, den eine Blitz-Füllschicht zu der unmittelbar darüber liegenden Schicht haben kann, wenn es um den Beschnitt der äußeren Enden von Bäumen" msgstr ""
" geht. Gemessen in dem Winkel, den die Schichtstärke vorgibt."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle label" msgctxt "lightning_infill_straightening_angle label"
@ -2052,9 +2051,8 @@ msgstr "Begradigungswinkel der Blitz-Füllung"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle description" msgctxt "lightning_infill_straightening_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness." msgid "The infill lines are straightened out to save on printing time. This is the maximum angle of overhang allowed across the length of the infill line."
msgstr "Die veränderte Position, die eine Schicht der Blitz-Füllung zu der unmittelbar darüber liegenden Schicht haben kann, wenn es um das Ausrunden der äußeren" msgstr ""
" Enden von Bäumen geht. Gemessen als Winkel der Zweige."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "material label" msgctxt "material label"
@ -6479,6 +6477,30 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file." msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Transformationsmatrix, die beim Laden aus der Datei auf das Modell angewandt wird." msgstr "Transformationsmatrix, die beim Laden aus der Datei auf das Modell angewandt wird."
#~ msgctxt "machine_start_gcode description"
#~ msgid "G-code commands to be executed at the very start - separated by \\n."
#~ msgstr "G-Code-Befehle, die zu Beginn ausgeführt werden sollen getrennt durch \\n."
#~ msgctxt "machine_end_gcode description"
#~ msgid "G-code commands to be executed at the very end - separated by \\n."
#~ msgstr "G-Code-Befehle, die am Ende ausgeführt werden sollen getrennt durch \\n."
#~ msgctxt "machine_max_feedrate_e label"
#~ msgid "Maximum Feedrate"
#~ msgstr "Maximaler Vorschub"
#~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model."
#~ msgstr "Das Muster des Füllmaterials des Drucks. Die Linien- und Zickzackfüllmethode wechseln nach jeder Schicht die Richtung, um Materialkosten zu reduzieren. Die Gitter-, Dreieck- Tri-Hexagon-, Würfel-, Octahedral-, Viertelwürfel-, Quer- und konzentrischen Muster werden in jeder Schicht vollständig gedruckt. Gyroid-, Würfel-, Viertelwürfel- und achtflächige Füllungen wechseln mit jeder Schicht, um eine gleichmäßigere Verteilung der Stärke in allen Richtungen zu erzielen. Die Einstellung Blitz versucht, die Füllung zu minimieren, indem nur die (internen) Dächer des Objekts gestützt werden. Der gültige Prozentsatz der Füllung bezieht sich daher nur auf die jeweilige Ebene unter dem zu stützenden Bereich des Modells."
#~ msgctxt "lightning_infill_prune_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness."
#~ msgstr "Der Unterschied, den eine Blitz-Füllschicht zu der unmittelbar darüber liegenden Schicht haben kann, wenn es um den Beschnitt der äußeren Enden von Bäumen geht. Gemessen in dem Winkel, den die Schichtstärke vorgibt."
#~ msgctxt "lightning_infill_straightening_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness."
#~ msgstr "Die veränderte Position, die eine Schicht der Blitz-Füllung zu der unmittelbar darüber liegenden Schicht haben kann, wenn es um das Ausrunden der äußeren Enden von Bäumen geht. Gemessen als Winkel der Zweige."
#~ msgctxt "infill_pattern description" #~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction." #~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
#~ msgstr "Das Muster des Füllmaterials des Drucks. Die Linien- und Zickzackfüllmethode wechseln nach jeder Schicht die Richtung, um Materialkosten zu reduzieren. Die Gitter-, Dreieck- Tri-Hexagon-, Würfel-, Octahedral-, Viertelwürfel-, Quer- und konzentrischen Muster werden in jeder Schicht vollständig gedruckt. Gyroid-, Würfel-, Viertelwürfel- und Octahedral-Füllungen wechseln mit jeder Schicht, um eine gleichmäßigere Verteilung der Stärke in allen Richtungen zu erzielen." #~ msgstr "Das Muster des Füllmaterials des Drucks. Die Linien- und Zickzackfüllmethode wechseln nach jeder Schicht die Richtung, um Materialkosten zu reduzieren. Die Gitter-, Dreieck- Tri-Hexagon-, Würfel-, Octahedral-, Viertelwürfel-, Quer- und konzentrischen Muster werden in jeder Schicht vollständig gedruckt. Gyroid-, Würfel-, Viertelwürfel- und Octahedral-Füllungen wechseln mit jeder Schicht, um eine gleichmäßigere Verteilung der Stärke in allen Richtungen zu erzielen."

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: 2019-03-13 14:00+0200\n" "PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof <info@bothof.nl>\n" "Last-Translator: Bothof <info@bothof.nl>\n"
"Language-Team: Spanish\n" "Language-Team: Spanish\n"

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 11:59+0000\n"
"PO-Revision-Date: 2021-04-16 15:15+0200\n" "PO-Revision-Date: 2021-04-16 15:15+0200\n"
"Last-Translator: Lionbridge <info@lionbridge.com>\n" "Last-Translator: Lionbridge <info@lionbridge.com>\n"
"Language-Team: Spanish <info@lionbridge.com>, Spanish <info@bothof.nl>\n" "Language-Team: Spanish <info@lionbridge.com>, Spanish <info@bothof.nl>\n"
@ -53,8 +53,10 @@ msgstr "Iniciar GCode"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_start_gcode description" msgctxt "machine_start_gcode description"
msgid "G-code commands to be executed at the very start - separated by \\n." msgid ""
msgstr "Los comandos de GCode que se ejecutarán justo al inicio separados por - \\n." "G-code commands to be executed at the very start - separated by \n"
"."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_end_gcode label" msgctxt "machine_end_gcode label"
@ -63,8 +65,10 @@ msgstr "Finalizar GCode"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_end_gcode description" msgctxt "machine_end_gcode description"
msgid "G-code commands to be executed at the very end - separated by \\n." msgid ""
msgstr "Los comandos de GCode que se ejecutarán justo al final separados por - \\n." "G-code commands to be executed at the very end - separated by \n"
"."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "material_guid label" msgctxt "material_guid label"
@ -146,6 +150,16 @@ msgctxt "machine_depth description"
msgid "The depth (Y-direction) of the printable area." msgid "The depth (Y-direction) of the printable area."
msgstr "Profundidad (dimensión sobre el eje Y) del área de impresión." msgstr "Profundidad (dimensión sobre el eje Y) del área de impresión."
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Altura de la máquina"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Altura (dimensión sobre el eje Z) del área de impresión."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_shape label" msgctxt "machine_shape label"
msgid "Build Plate Shape" msgid "Build Plate Shape"
@ -186,16 +200,6 @@ msgctxt "machine_buildplate_type option aluminum"
msgid "Aluminum" msgid "Aluminum"
msgstr "Aluminio" msgstr "Aluminio"
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Altura de la máquina"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Altura (dimensión sobre el eje Z) del área de impresión."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_heated_bed label" msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate" msgid "Has Heated Build Plate"
@ -553,8 +557,8 @@ msgstr "Velocidad máxima del motor de la dirección Z."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e label" msgctxt "machine_max_feedrate_e label"
msgid "Maximum Feedrate" msgid "Maximum Speed E"
msgstr "Velocidad de alimentación máxima" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e description" msgctxt "machine_max_feedrate_e description"
@ -1723,12 +1727,8 @@ msgstr "Patrón de relleno"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern description" msgctxt "infill_pattern description"
msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model." msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the ceiling of the object."
msgstr "Patrón del material de relleno de la impresión. El relleno de línea y zigzag cambia de dirección en capas alternas, con lo que se reduce el coste de material." msgstr ""
" Los patrones de rejilla, triángulo, trihexágono, cubo, octeto, cubo bitruncado, transversal y concéntrico se imprimen en todas las capas por completo."
" El relleno giroide, cúbico, cúbico bitruncado y de octeto cambian en cada capa para proporcionar una distribución de fuerza equitativa en cada dirección."
" El relleno de iluminación intenta minimizar el relleno, apoyando únicamente las cubiertas (internas) del objeto. Como tal, el porcentaje de relleno solo"
" es \"válido\" una capa por debajo de lo que necesite para soportar el modelo."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option grid" msgctxt "infill_pattern option grid"
@ -2041,9 +2041,8 @@ msgstr "Ángulo de recorte de relleno de iluminación"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle description" msgctxt "lightning_infill_prune_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness." msgid "The endpoints of infill lines are shortened to save on material. This setting is the angle of overhang of the endpoints of these lines."
msgstr "La diferencia que puede tener una capa de relleno de iluminación con la inmediatamente superior como cuando se podan las puntas de los árboles. Medido" msgstr ""
" en el ángulo dado el espesor."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle label" msgctxt "lightning_infill_straightening_angle label"
@ -2052,9 +2051,8 @@ msgstr "Ángulo de enderezamiento de iluminación"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle description" msgctxt "lightning_infill_straightening_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness." msgid "The infill lines are straightened out to save on printing time. This is the maximum angle of overhang allowed across the length of the infill line."
msgstr "La diferencia que puede tener una capa de relleno de iluminación con la inmediatamente superior como el suavizado de los árboles. Medido en el ángulo dado" msgstr ""
" el espesor."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "material label" msgctxt "material label"
@ -6479,6 +6477,30 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file." msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Matriz de transformación que se aplicará al modelo cuando se cargue desde el archivo." msgstr "Matriz de transformación que se aplicará al modelo cuando se cargue desde el archivo."
#~ msgctxt "machine_start_gcode description"
#~ msgid "G-code commands to be executed at the very start - separated by \\n."
#~ msgstr "Los comandos de GCode que se ejecutarán justo al inicio separados por - \\n."
#~ msgctxt "machine_end_gcode description"
#~ msgid "G-code commands to be executed at the very end - separated by \\n."
#~ msgstr "Los comandos de GCode que se ejecutarán justo al final separados por - \\n."
#~ msgctxt "machine_max_feedrate_e label"
#~ msgid "Maximum Feedrate"
#~ msgstr "Velocidad de alimentación máxima"
#~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model."
#~ msgstr "Patrón del material de relleno de la impresión. El relleno de línea y zigzag cambia de dirección en capas alternas, con lo que se reduce el coste de material. Los patrones de rejilla, triángulo, trihexágono, cubo, octeto, cubo bitruncado, transversal y concéntrico se imprimen en todas las capas por completo. El relleno giroide, cúbico, cúbico bitruncado y de octeto cambian en cada capa para proporcionar una distribución de fuerza equitativa en cada dirección. El relleno de iluminación intenta minimizar el relleno, apoyando únicamente las cubiertas (internas) del objeto. Como tal, el porcentaje de relleno solo es \"válido\" una capa por debajo de lo que necesite para soportar el modelo."
#~ msgctxt "lightning_infill_prune_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness."
#~ msgstr "La diferencia que puede tener una capa de relleno de iluminación con la inmediatamente superior como cuando se podan las puntas de los árboles. Medido en el ángulo dado el espesor."
#~ msgctxt "lightning_infill_straightening_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness."
#~ msgstr "La diferencia que puede tener una capa de relleno de iluminación con la inmediatamente superior como el suavizado de los árboles. Medido en el ángulo dado el espesor."
#~ msgctxt "infill_pattern description" #~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction." #~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
#~ msgstr "Patrón del material de relleno de la impresión. El relleno de línea y zigzag cambia de dirección en capas alternas, con lo que se reduce el coste de material. Los patrones de rejilla, triángulo, trihexágono, cubo, octeto, cubo bitruncado, transversal y concéntrico se imprimen en todas las capas por completo. El relleno giroide, cúbico, cúbico bitruncado y de octeto cambian en cada capa para proporcionar una distribución de fuerza equitativa en cada dirección." #~ msgstr "Patrón del material de relleno de la impresión. El relleno de línea y zigzag cambia de dirección en capas alternas, con lo que se reduce el coste de material. Los patrones de rejilla, triángulo, trihexágono, cubo, octeto, cubo bitruncado, transversal y concéntrico se imprimen en todas las capas por completo. El relleno giroide, cúbico, cúbico bitruncado y de octeto cambian en cada capa para proporcionar una distribución de fuerza equitativa en cada dirección."

View File

@ -3,7 +3,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Uranium json setting files\n" "Project-Id-Version: Uranium json setting files\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE\n" "Language-Team: LANGUAGE\n"

View File

@ -3,7 +3,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Uranium json setting files\n" "Project-Id-Version: Uranium json setting files\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 11:59+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE\n" "Language-Team: LANGUAGE\n"
@ -157,6 +157,16 @@ msgctxt "machine_depth description"
msgid "The depth (Y-direction) of the printable area." msgid "The depth (Y-direction) of the printable area."
msgstr "" msgstr ""
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr ""
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_shape label" msgctxt "machine_shape label"
msgid "Build Plate Shape" msgid "Build Plate Shape"
@ -198,16 +208,6 @@ msgctxt "machine_buildplate_type option aluminum"
msgid "Aluminum" msgid "Aluminum"
msgstr "" msgstr ""
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr ""
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_heated_bed label" msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate" msgid "Has Heated Build Plate"
@ -612,7 +612,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e label" msgctxt "machine_max_feedrate_e label"
msgid "Maximum Feedrate" msgid "Maximum Speed E"
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -1988,9 +1988,7 @@ msgid ""
"patterns are fully printed every layer. Gyroid, cubic, quarter cubic and " "patterns are fully printed every layer. Gyroid, cubic, quarter cubic and "
"octet infill change with every layer to provide a more equal distribution of " "octet infill change with every layer to provide a more equal distribution of "
"strength over each direction. Lightning infill tries to minimize the infill, " "strength over each direction. Lightning infill tries to minimize the infill, "
"by only supporting the (internal) roofs of the object. As such, the infill " "by only supporting the ceiling of the object."
"percentage is only 'valid' one layer below whatever it needs to support of "
"the model."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -2359,9 +2357,8 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle description" msgctxt "lightning_infill_prune_angle description"
msgid "" msgid ""
"The difference a lightning infill layer can have with the one immediately " "The endpoints of infill lines are shortened to save on material. This "
"above w.r.t the pruning of the outer extremities of trees. Measured in the " "setting is the angle of overhang of the endpoints of these lines."
"angle given the thickness."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -2372,9 +2369,8 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle description" msgctxt "lightning_infill_straightening_angle description"
msgid "" msgid ""
"The difference a lightning infill layer can have with the one immediately " "The infill lines are straightened out to save on printing time. This is the "
"above w.r.t the smoothing of trees. Measured in the angle given the " "maximum angle of overhang allowed across the length of the infill line."
"thickness."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: 2017-08-11 14:31+0200\n" "PO-Revision-Date: 2017-08-11 14:31+0200\n"
"Last-Translator: Bothof <info@bothof.nl>\n" "Last-Translator: Bothof <info@bothof.nl>\n"
"Language-Team: Finnish\n" "Language-Team: Finnish\n"

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 11:59+0000\n"
"PO-Revision-Date: 2017-09-27 12:27+0200\n" "PO-Revision-Date: 2017-09-27 12:27+0200\n"
"Last-Translator: Bothof <info@bothof.nl>\n" "Last-Translator: Bothof <info@bothof.nl>\n"
"Language-Team: Finnish\n" "Language-Team: Finnish\n"
@ -149,6 +149,16 @@ msgctxt "machine_depth description"
msgid "The depth (Y-direction) of the printable area." msgid "The depth (Y-direction) of the printable area."
msgstr "Tulostettavan alueen syvyys (Y-suunta)." msgstr "Tulostettavan alueen syvyys (Y-suunta)."
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Laitteen korkeus"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Tulostettavan alueen korkeus (Z-suunta)."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_shape label" msgctxt "machine_shape label"
msgid "Build Plate Shape" msgid "Build Plate Shape"
@ -189,16 +199,6 @@ msgctxt "machine_buildplate_type option aluminum"
msgid "Aluminum" msgid "Aluminum"
msgstr "" msgstr ""
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Laitteen korkeus"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "Tulostettavan alueen korkeus (Z-suunta)."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_heated_bed label" msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate" msgid "Has Heated Build Plate"
@ -556,8 +556,8 @@ msgstr "Z-suunnan moottorin maksiminopeus."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e label" msgctxt "machine_max_feedrate_e label"
msgid "Maximum Feedrate" msgid "Maximum Speed E"
msgstr "Maksimisyöttönopeus" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e description" msgctxt "machine_max_feedrate_e description"
@ -1726,7 +1726,7 @@ msgstr "Täyttökuvio"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern description" msgctxt "infill_pattern description"
msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model." msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the ceiling of the object."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -2038,7 +2038,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle description" msgctxt "lightning_infill_prune_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness." msgid "The endpoints of infill lines are shortened to save on material. This setting is the angle of overhang of the endpoints of these lines."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -2048,7 +2048,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle description" msgctxt "lightning_infill_straightening_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness." msgid "The infill lines are straightened out to save on printing time. This is the maximum angle of overhang allowed across the length of the infill line."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -6472,6 +6472,10 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file." msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Mallissa käytettävä muunnosmatriisi, kun malli ladataan tiedostosta." msgstr "Mallissa käytettävä muunnosmatriisi, kun malli ladataan tiedostosta."
#~ msgctxt "machine_max_feedrate_e label"
#~ msgid "Maximum Feedrate"
#~ msgstr "Maksimisyöttönopeus"
#~ msgctxt "mold_width description" #~ msgctxt "mold_width description"
#~ msgid "The minimal distance between the ouside of the mold and the outside of the model." #~ msgid "The minimal distance between the ouside of the mold and the outside of the model."
#~ msgstr "Muotin ulkoseinän ja mallin ulkoseinän välinen vähimmäisetäisyys." #~ msgstr "Muotin ulkoseinän ja mallin ulkoseinän välinen vähimmäisetäisyys."

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: 2021-04-16 15:16+0200\n" "PO-Revision-Date: 2021-04-16 15:16+0200\n"
"Last-Translator: Bothof <info@bothof.nl>\n" "Last-Translator: Bothof <info@bothof.nl>\n"
"Language-Team: French\n" "Language-Team: French\n"

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 11:59+0000\n"
"PO-Revision-Date: 2021-04-16 15:16+0200\n" "PO-Revision-Date: 2021-04-16 15:16+0200\n"
"Last-Translator: Lionbridge <info@lionbridge.com>\n" "Last-Translator: Lionbridge <info@lionbridge.com>\n"
"Language-Team: French <info@lionbridge.com>, French <info@bothof.nl>\n" "Language-Team: French <info@lionbridge.com>, French <info@bothof.nl>\n"
@ -53,8 +53,10 @@ msgstr "G-Code de démarrage"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_start_gcode description" msgctxt "machine_start_gcode description"
msgid "G-code commands to be executed at the very start - separated by \\n." msgid ""
msgstr "Commandes G-Code à exécuter au tout début, séparées par \\n." "G-code commands to be executed at the very start - separated by \n"
"."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_end_gcode label" msgctxt "machine_end_gcode label"
@ -63,8 +65,10 @@ msgstr "G-Code de fin"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_end_gcode description" msgctxt "machine_end_gcode description"
msgid "G-code commands to be executed at the very end - separated by \\n." msgid ""
msgstr "Commandes G-Code à exécuter tout à la fin, séparées par \\n." "G-code commands to be executed at the very end - separated by \n"
"."
msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "material_guid label" msgctxt "material_guid label"
@ -146,6 +150,16 @@ msgctxt "machine_depth description"
msgid "The depth (Y-direction) of the printable area." msgid "The depth (Y-direction) of the printable area."
msgstr "La profondeur (sens Y) de la zone imprimable." msgstr "La profondeur (sens Y) de la zone imprimable."
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Hauteur de la machine"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "La hauteur (sens Z) de la zone imprimable."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_shape label" msgctxt "machine_shape label"
msgid "Build Plate Shape" msgid "Build Plate Shape"
@ -186,16 +200,6 @@ msgctxt "machine_buildplate_type option aluminum"
msgid "Aluminum" msgid "Aluminum"
msgstr "Aluminium" msgstr "Aluminium"
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Hauteur de la machine"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "La hauteur (sens Z) de la zone imprimable."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_heated_bed label" msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate" msgid "Has Heated Build Plate"
@ -553,8 +557,8 @@ msgstr "La vitesse maximale pour le moteur du sens Z."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e label" msgctxt "machine_max_feedrate_e label"
msgid "Maximum Feedrate" msgid "Maximum Speed E"
msgstr "Taux d'alimentation maximal" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e description" msgctxt "machine_max_feedrate_e description"
@ -1723,12 +1727,8 @@ msgstr "Motif de remplissage"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern description" msgctxt "infill_pattern description"
msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model." msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the ceiling of the object."
msgstr "Le motif du matériau de remplissage de l'impression. La ligne et le remplissage en zigzag changent de sens à chaque alternance de couche, réduisant ainsi" msgstr ""
" les coûts matériels. Les motifs en grille, en triangle, tri-hexagonaux, cubiques, octaédriques, quart cubiques, entrecroisés et concentriques sont entièrement"
" imprimés sur chaque couche. Les remplissages gyroïdes, cubiques, quart cubiques et octaédriques changent à chaque couche afin d'offrir une répartition"
" plus égale de la solidité dans chaque direction. Le remplissage éclair tente de minimiser le remplissage en ne soutenant que les plafonds (internes) de"
" l'objet. Ainsi, le pourcentage de remplissage n'est « valable » qu'une couche en dessous de ce qu'il doit soutenir dans le modèle."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern option grid" msgctxt "infill_pattern option grid"
@ -2041,9 +2041,8 @@ msgstr "Angle d'élagage du remplissage éclair"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle description" msgctxt "lightning_infill_prune_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness." msgid "The endpoints of infill lines are shortened to save on material. This setting is the angle of overhang of the endpoints of these lines."
msgstr "La différence qu'une couche de remplissage éclair peut avoir avec celle immédiatement au-dessus en ce qui concerne l'élagage des extrémités extérieures" msgstr ""
" des arborescences. Mesuré dans l'angle au vu de l'épaisseur."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle label" msgctxt "lightning_infill_straightening_angle label"
@ -2052,9 +2051,8 @@ msgstr "Angle de redressement du remplissage éclair"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle description" msgctxt "lightning_infill_straightening_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness." msgid "The infill lines are straightened out to save on printing time. This is the maximum angle of overhang allowed across the length of the infill line."
msgstr "La différence qu'une couche de remplissage éclair peut avoir avec celle immédiatement au-dessus en ce qui concerne le lissage des arborescences. Mesuré" msgstr ""
" dans l'angle au vu de l'épaisseur."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "material label" msgctxt "material label"
@ -6479,6 +6477,30 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file." msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "Matrice de transformation à appliquer au modèle lors de son chargement depuis le fichier." msgstr "Matrice de transformation à appliquer au modèle lors de son chargement depuis le fichier."
#~ msgctxt "machine_start_gcode description"
#~ msgid "G-code commands to be executed at the very start - separated by \\n."
#~ msgstr "Commandes G-Code à exécuter au tout début, séparées par \\n."
#~ msgctxt "machine_end_gcode description"
#~ msgid "G-code commands to be executed at the very end - separated by \\n."
#~ msgstr "Commandes G-Code à exécuter tout à la fin, séparées par \\n."
#~ msgctxt "machine_max_feedrate_e label"
#~ msgid "Maximum Feedrate"
#~ msgstr "Taux d'alimentation maximal"
#~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model."
#~ msgstr "Le motif du matériau de remplissage de l'impression. La ligne et le remplissage en zigzag changent de sens à chaque alternance de couche, réduisant ainsi les coûts matériels. Les motifs en grille, en triangle, tri-hexagonaux, cubiques, octaédriques, quart cubiques, entrecroisés et concentriques sont entièrement imprimés sur chaque couche. Les remplissages gyroïdes, cubiques, quart cubiques et octaédriques changent à chaque couche afin d'offrir une répartition plus égale de la solidité dans chaque direction. Le remplissage éclair tente de minimiser le remplissage en ne soutenant que les plafonds (internes) de l'objet. Ainsi, le pourcentage de remplissage n'est « valable » qu'une couche en dessous de ce qu'il doit soutenir dans le modèle."
#~ msgctxt "lightning_infill_prune_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness."
#~ msgstr "La différence qu'une couche de remplissage éclair peut avoir avec celle immédiatement au-dessus en ce qui concerne l'élagage des extrémités extérieures des arborescences. Mesuré dans l'angle au vu de l'épaisseur."
#~ msgctxt "lightning_infill_straightening_angle description"
#~ msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness."
#~ msgstr "La différence qu'une couche de remplissage éclair peut avoir avec celle immédiatement au-dessus en ce qui concerne le lissage des arborescences. Mesuré dans l'angle au vu de l'épaisseur."
#~ msgctxt "infill_pattern description" #~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction." #~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
#~ msgstr "Motif du matériau de remplissage de l'impression. La ligne et le remplissage en zigzag changent de sens à chaque alternance de couche, réduisant ainsi les coûts matériels. Les motifs en grille, en triangle, trihexagonaux, cubiques, octaédriques, quart cubiques et concentriques sont entièrement imprimés sur chaque couche. Les remplissages gyroïde, cubique, quart cubique et octaédrique changent à chaque couche afin d'offrir une répartition plus égale de la solidité dans chaque direction." #~ msgstr "Motif du matériau de remplissage de l'impression. La ligne et le remplissage en zigzag changent de sens à chaque alternance de couche, réduisant ainsi les coûts matériels. Les motifs en grille, en triangle, trihexagonaux, cubiques, octaédriques, quart cubiques et concentriques sont entièrement imprimés sur chaque couche. Les remplissages gyroïde, cubique, quart cubique et octaédrique changent à chaque couche afin d'offrir une répartition plus égale de la solidité dans chaque direction."

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: 2020-03-24 09:27+0100\n" "PO-Revision-Date: 2020-03-24 09:27+0100\n"
"Last-Translator: Nagy Attila <vokroot@gmail.com>\n" "Last-Translator: Nagy Attila <vokroot@gmail.com>\n"
"Language-Team: AT-VLOG\n" "Language-Team: AT-VLOG\n"

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 11:59+0000\n"
"PO-Revision-Date: 2020-03-24 09:43+0100\n" "PO-Revision-Date: 2020-03-24 09:43+0100\n"
"Last-Translator: Nagy Attila <vokroot@gmail.com>\n" "Last-Translator: Nagy Attila <vokroot@gmail.com>\n"
"Language-Team: AT-VLOG\n" "Language-Team: AT-VLOG\n"
@ -155,6 +155,16 @@ msgctxt "machine_depth description"
msgid "The depth (Y-direction) of the printable area." msgid "The depth (Y-direction) of the printable area."
msgstr "A nyomtatási terület mélysége (Y-irány)." msgstr "A nyomtatási terület mélysége (Y-irány)."
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Nyomtatási magasság"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "A nyomtatási terület magassága (Z-irány)."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_shape label" msgctxt "machine_shape label"
msgid "Build Plate Shape" msgid "Build Plate Shape"
@ -195,16 +205,6 @@ msgctxt "machine_buildplate_type option aluminum"
msgid "Aluminum" msgid "Aluminum"
msgstr "Alumínium" msgstr "Alumínium"
#: fdmprinter.def.json
msgctxt "machine_height label"
msgid "Machine Height"
msgstr "Nyomtatási magasság"
#: fdmprinter.def.json
msgctxt "machine_height description"
msgid "The height (Z-direction) of the printable area."
msgstr "A nyomtatási terület magassága (Z-irány)."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_heated_bed label" msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate" msgid "Has Heated Build Plate"
@ -562,8 +562,8 @@ msgstr "A Z motor maximális sebessége."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e label" msgctxt "machine_max_feedrate_e label"
msgid "Maximum Feedrate" msgid "Maximum Speed E"
msgstr "Adagolás maximum" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_feedrate_e description" msgctxt "machine_max_feedrate_e description"
@ -1732,7 +1732,7 @@ msgstr "Kitöltési Minta"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "infill_pattern description" msgctxt "infill_pattern description"
msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the (internal) roofs of the object. As such, the infill percentage is only 'valid' one layer below whatever it needs to support of the model." msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction. Lightning infill tries to minimize the infill, by only supporting the ceiling of the object."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -2046,7 +2046,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_prune_angle description" msgctxt "lightning_infill_prune_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the pruning of the outer extremities of trees. Measured in the angle given the thickness." msgid "The endpoints of infill lines are shortened to save on material. This setting is the angle of overhang of the endpoints of these lines."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -2056,7 +2056,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "lightning_infill_straightening_angle description" msgctxt "lightning_infill_straightening_angle description"
msgid "The difference a lightning infill layer can have with the one immediately above w.r.t the smoothing of trees. Measured in the angle given the thickness." msgid "The infill lines are straightened out to save on printing time. This is the maximum angle of overhang allowed across the length of the infill line."
msgstr "" msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
@ -6480,6 +6480,10 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file." msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "A modellre alkalmazandó átalakítási mátrix, amikor azt fájlból tölti be." msgstr "A modellre alkalmazandó átalakítási mátrix, amikor azt fájlból tölti be."
#~ msgctxt "machine_max_feedrate_e label"
#~ msgid "Maximum Feedrate"
#~ msgstr "Adagolás maximum"
#~ msgctxt "infill_pattern description" #~ msgctxt "infill_pattern description"
#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction." #~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
#~ msgstr "A kitöltés mintázata. A vonal és a cikcakk felváltva cserélgeti az irányát rétegenként, csökkentve ezzel az anyagköltséget. A rács, háromszög, háromhatszög,kocka, oktett, negyed kocka, kereszt és koncentrikus mintákat minden rétegben nyomtatjuk. A gyroid, a kocka, a negyedkocka, és az oktett töltés minden rétegben változik, és így egyenletesebb az erő eloszlása minden irányban." #~ msgstr "A kitöltés mintázata. A vonal és a cikcakk felváltva cserélgeti az irányát rétegenként, csökkentve ezzel az anyagköltséget. A rács, háromszög, háromhatszög,kocka, oktett, negyed kocka, kereszt és koncentrikus mintákat minden rétegben nyomtatjuk. A gyroid, a kocka, a negyedkocka, és az oktett töltés minden rétegben változik, és így egyenletesebb az erő eloszlása minden irányban."

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Cura 4.12\n" "Project-Id-Version: Cura 4.13\n"
"Report-Msgid-Bugs-To: plugins@ultimaker.com\n" "Report-Msgid-Bugs-To: plugins@ultimaker.com\n"
"POT-Creation-Date: 2021-10-20 16:43+0000\n" "POT-Creation-Date: 2021-12-10 12:00+0000\n"
"PO-Revision-Date: 2021-04-16 14:58+0200\n" "PO-Revision-Date: 2021-04-16 14:58+0200\n"
"Last-Translator: Bothof <info@bothof.nl>\n" "Last-Translator: Bothof <info@bothof.nl>\n"
"Language-Team: Italian\n" "Language-Team: Italian\n"

Some files were not shown because too many files have changed in this diff Show More