mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Merge branch 'master' of github.com:Ultimaker/Cura into replace_controls_1_for_controls_2
This commit is contained in:
commit
f11d728c6b
838 changed files with 99530 additions and 92324 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -56,6 +56,11 @@ plugins/SettingsGuide
|
|||
plugins/SettingsGuide2
|
||||
plugins/SVGToolpathReader
|
||||
plugins/X3GWriter
|
||||
plugins/CuraFlatPack
|
||||
plugins/CuraRemoteSupport
|
||||
plugins/ModelCutter
|
||||
plugins/PrintProfileCreator
|
||||
plugins/MultiPrintPlugin
|
||||
|
||||
#Build stuff
|
||||
CMakeCache.txt
|
||||
|
|
|
@ -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.
|
||||
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 typing import Any, Optional, Dict, TYPE_CHECKING, Callable
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
from UM.i18n import i18nCatalog
|
||||
from cura.OAuth2.AuthorizationService import AuthorizationService
|
||||
from cura.OAuth2.Models import OAuth2Settings
|
||||
from cura.OAuth2.Models import OAuth2Settings, UserProfile
|
||||
from cura.UltimakerCloud import UltimakerCloudConstants
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -46,6 +46,9 @@ class Account(QObject):
|
|||
loginStateChanged = pyqtSignal(bool)
|
||||
"""Signal emitted when user logged in or out"""
|
||||
|
||||
userProfileChanged = pyqtSignal()
|
||||
"""Signal emitted when new account information is available."""
|
||||
|
||||
additionalRightsChanged = pyqtSignal("QVariantMap")
|
||||
"""Signal emitted when a users additional rights change"""
|
||||
|
||||
|
@ -71,13 +74,14 @@ class Account(QObject):
|
|||
self._application = application
|
||||
self._new_cloud_printers_detected = False
|
||||
|
||||
self._error_message = None # type: Optional[Message]
|
||||
self._error_message: Optional[Message] = None
|
||||
self._logged_in = False
|
||||
self._user_profile: Optional[UserProfile] = None
|
||||
self._additional_rights: Dict[str, Any] = {}
|
||||
self._sync_state = SyncState.IDLE
|
||||
self._manual_sync_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._callback_port = 32118
|
||||
|
@ -103,7 +107,7 @@ class Account(QObject):
|
|||
self._update_timer.setSingleShot(True)
|
||||
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"""
|
||||
|
||||
def initialize(self) -> None:
|
||||
|
@ -196,12 +200,17 @@ class Account(QObject):
|
|||
self._logged_in = logged_in
|
||||
self.loginStateChanged.emit(logged_in)
|
||||
if logged_in:
|
||||
self._authorization_service.getUserProfile(self._onProfileChanged)
|
||||
self._setManualSyncEnabled(False)
|
||||
self._sync()
|
||||
else:
|
||||
if self._update_timer.isActive():
|
||||
self._update_timer.stop()
|
||||
|
||||
def _onProfileChanged(self, profile: Optional[UserProfile]) -> None:
|
||||
self._user_profile = profile
|
||||
self.userProfileChanged.emit()
|
||||
|
||||
def _sync(self) -> None:
|
||||
"""Signals all sync services to start syncing
|
||||
|
||||
|
@ -243,32 +252,28 @@ class Account(QObject):
|
|||
return
|
||||
self._authorization_service.startAuthorizationFlow(force_logout_before_login)
|
||||
|
||||
@pyqtProperty(str, notify=loginStateChanged)
|
||||
@pyqtProperty(str, notify = userProfileChanged)
|
||||
def userName(self):
|
||||
user_profile = self._authorization_service.getUserProfile()
|
||||
if not user_profile:
|
||||
return None
|
||||
return user_profile.username
|
||||
if not self._user_profile:
|
||||
return ""
|
||||
return self._user_profile.username
|
||||
|
||||
@pyqtProperty(str, notify = loginStateChanged)
|
||||
@pyqtProperty(str, notify = userProfileChanged)
|
||||
def profileImageUrl(self):
|
||||
user_profile = self._authorization_service.getUserProfile()
|
||||
if not user_profile:
|
||||
return None
|
||||
return user_profile.profile_image_url
|
||||
if not self._user_profile:
|
||||
return ""
|
||||
return self._user_profile.profile_image_url
|
||||
|
||||
@pyqtProperty(str, notify=accessTokenChanged)
|
||||
def accessToken(self) -> Optional[str]:
|
||||
return self._authorization_service.getAccessToken()
|
||||
|
||||
@pyqtProperty("QVariantMap", notify = loginStateChanged)
|
||||
@pyqtProperty("QVariantMap", notify = userProfileChanged)
|
||||
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 """
|
||||
|
||||
user_profile = self._authorization_service.getUserProfile()
|
||||
if not user_profile:
|
||||
if not self._user_profile:
|
||||
return None
|
||||
return user_profile.__dict__
|
||||
return self._user_profile.__dict__
|
||||
|
||||
@pyqtProperty(str, notify=lastSyncDateTimeChanged)
|
||||
def lastSyncDateTime(self) -> str:
|
||||
|
|
|
@ -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.
|
||||
|
||||
# ---------
|
||||
|
@ -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
|
||||
# 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.
|
||||
CuraSDKVersion = "7.8.0"
|
||||
CuraSDKVersion = "7.9.0"
|
||||
|
||||
try:
|
||||
from cura.CuraVersion import CuraAppName # type: ignore
|
||||
|
@ -46,6 +46,10 @@ except ImportError:
|
|||
# Various convenience flags indicating what kind of Cura build it is.
|
||||
__ENTERPRISE_VERSION_TYPE = "enterprise"
|
||||
IsEnterpriseVersion = CuraBuildType.lower() == __ENTERPRISE_VERSION_TYPE
|
||||
IsAlternateVersion = CuraBuildType.lower() not in [DEFAULT_CURA_BUILD_TYPE, __ENTERPRISE_VERSION_TYPE]
|
||||
# NOTE: IsAlternateVersion is to make it possibile to have 'non-numbered' versions, at least as presented to the user.
|
||||
# (Internally, it'll still have some sort of version-number, but the user is never meant to see it in the GUI).
|
||||
# Warning: This will also change (some of) the icons/splash-screen to the 'work in progress' alternatives!
|
||||
|
||||
try:
|
||||
from cura.CuraVersion import CuraAppDisplayName # type: ignore
|
||||
|
|
|
@ -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
|
||||
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.markAsFixedInBin(0)
|
||||
node_items.append(item)
|
||||
|
|
|
@ -181,8 +181,7 @@ class Backup:
|
|||
|
||||
return extracted
|
||||
|
||||
@staticmethod
|
||||
def _extractArchive(archive: "ZipFile", target_path: str) -> bool:
|
||||
def _extractArchive(self, archive: "ZipFile", target_path: str) -> bool:
|
||||
"""Extract the whole archive to the given target path.
|
||||
|
||||
:param archive: The archive as ZipFile.
|
||||
|
@ -201,7 +200,11 @@ class Backup:
|
|||
Resources.factoryReset()
|
||||
Logger.log("d", "Extracting backup to location: %s", target_path)
|
||||
name_list = archive.namelist()
|
||||
ignore_string = re.compile("|".join(self.IGNORED_FILES + self.IGNORED_FOLDERS))
|
||||
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:
|
||||
archive.extract(archive_filename, target_path)
|
||||
except (PermissionError, EnvironmentError):
|
||||
|
|
|
@ -66,6 +66,7 @@ class BuildVolume(SceneNode):
|
|||
self._height = 0 # type: float
|
||||
self._depth = 0 # type: float
|
||||
self._shape = "" # type: str
|
||||
self._scale_vector = Vector(1.0, 1.0, 1.0)
|
||||
|
||||
self._shader = None
|
||||
|
||||
|
@ -513,6 +514,13 @@ class BuildVolume(SceneNode):
|
|||
self._disallowed_area_size = max(size, self._disallowed_area_size)
|
||||
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:
|
||||
"""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._updateScaleFactor()
|
||||
|
||||
self._volume_aabb = AxisAlignedBox(
|
||||
minimum = Vector(min_w, min_h - 1.0, min_d),
|
||||
maximum = Vector(max_w, max_h - self._raft_thickness - self._extra_z_clearance, max_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).scale(self._scale_vector)
|
||||
)
|
||||
|
||||
bed_adhesion_size = self.getEdgeDisallowedSize()
|
||||
|
||||
|
@ -564,15 +575,15 @@ class BuildVolume(SceneNode):
|
|||
# This is probably wrong in all other cases. TODO!
|
||||
# The +1 and -1 is added as there is always a bit of extra room required to work properly.
|
||||
scale_to_max_bounds = AxisAlignedBox(
|
||||
minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_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)
|
||||
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).scale(self._scale_vector)
|
||||
)
|
||||
|
||||
self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds # type: ignore
|
||||
|
||||
self.updateNodeBoundaryCheck()
|
||||
|
||||
def getBoundingBox(self):
|
||||
def getBoundingBox(self) -> Optional[AxisAlignedBox]:
|
||||
return self._volume_aabb
|
||||
|
||||
def getRaftThickness(self) -> float:
|
||||
|
@ -633,18 +644,18 @@ class BuildVolume(SceneNode):
|
|||
for extruder in extruders:
|
||||
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")
|
||||
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)
|
||||
if self._height < machine_height:
|
||||
self._height = min(self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height)
|
||||
if self._height < (machine_height * self._scale_vector.z):
|
||||
self._build_volume_message.show()
|
||||
else:
|
||||
self._build_volume_message.hide()
|
||||
else:
|
||||
self._height = self._global_container_stack.getProperty("machine_height", "value")
|
||||
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._updateDisallowedAreas()
|
||||
|
@ -678,18 +689,18 @@ class BuildVolume(SceneNode):
|
|||
if setting_key == "print_sequence":
|
||||
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:
|
||||
self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height)
|
||||
if self._height < machine_height:
|
||||
self._height = min(self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height)
|
||||
if self._height < (machine_height * self._scale_vector.z):
|
||||
self._build_volume_message.show()
|
||||
else:
|
||||
self._build_volume_message.hide()
|
||||
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()
|
||||
update_disallowed_areas = True
|
||||
|
||||
# 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()
|
||||
update_extra_z_clearance = True
|
||||
update_disallowed_areas = True
|
||||
|
@ -738,9 +749,10 @@ class BuildVolume(SceneNode):
|
|||
def _updateMachineSizeProperties(self) -> None:
|
||||
if not self._global_container_stack:
|
||||
return
|
||||
self._height = self._global_container_stack.getProperty("machine_height", "value")
|
||||
self._width = self._global_container_stack.getProperty("machine_width", "value")
|
||||
self._depth = self._global_container_stack.getProperty("machine_depth", "value")
|
||||
self._updateScaleFactor()
|
||||
self._height = self._global_container_stack.getProperty("machine_height", "value") * self._scale_vector.z
|
||||
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")
|
||||
|
||||
def _updateDisallowedAreasAndRebuild(self):
|
||||
|
@ -757,6 +769,14 @@ class BuildVolume(SceneNode):
|
|||
self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks())
|
||||
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:
|
||||
if not self._global_container_stack:
|
||||
return
|
||||
|
@ -812,9 +832,11 @@ class BuildVolume(SceneNode):
|
|||
|
||||
self._disallowed_areas = []
|
||||
for extruder_id in result_areas:
|
||||
self._scaleAreas(result_areas[extruder_id])
|
||||
self._disallowed_areas.extend(result_areas[extruder_id])
|
||||
self._disallowed_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])
|
||||
|
||||
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"]
|
||||
_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"]
|
||||
_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
|
||||
|
|
|
@ -152,11 +152,11 @@ class CuraApplication(QtApplication):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(name = ApplicationMetadata.CuraAppName,
|
||||
app_display_name = ApplicationMetadata.CuraAppDisplayName,
|
||||
version = ApplicationMetadata.CuraVersion,
|
||||
version = ApplicationMetadata.CuraVersion if not ApplicationMetadata.IsAlternateVersion else ApplicationMetadata.CuraBuildType,
|
||||
api_version = ApplicationMetadata.CuraSDKVersion,
|
||||
build_type = ApplicationMetadata.CuraBuildType,
|
||||
is_debug_mode = ApplicationMetadata.CuraDebugMode,
|
||||
tray_icon_name = "cura-icon-32.png",
|
||||
tray_icon_name = "cura-icon-32.png" if not ApplicationMetadata.IsAlternateVersion else "cura-icon-32_wip.png",
|
||||
**kwargs)
|
||||
|
||||
self.default_theme = "cura-light"
|
||||
|
@ -484,7 +484,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
if not self.getIsHeadLess():
|
||||
try:
|
||||
self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
|
||||
self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png" if not ApplicationMetadata.IsAlternateVersion else "cura-icon_wip.png")))
|
||||
except FileNotFoundError:
|
||||
Logger.log("w", "Unable to find the window icon.")
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
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.i18n import i18nCatalog
|
||||
|
@ -11,6 +11,7 @@ from UM.Util import parseBool
|
|||
from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
|
||||
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
from cura.UltimakerCloud.UltimakerCloudConstants import META_CAPABILITIES # To filter on the printer's capabilities.
|
||||
|
||||
|
||||
class GlobalStacksModel(ListModel):
|
||||
|
@ -42,6 +43,7 @@ class GlobalStacksModel(ListModel):
|
|||
|
||||
self._filter_connection_type = None # type: Optional[ConnectionType]
|
||||
self._filter_online_only = False
|
||||
self._filter_capabilities: List[str] = [] # Required capabilities that all listed printers must have.
|
||||
|
||||
# Listen to changes
|
||||
CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
|
||||
|
@ -50,8 +52,13 @@ class GlobalStacksModel(ListModel):
|
|||
self._updateDelayed()
|
||||
|
||||
filterConnectionTypeChanged = pyqtSignal()
|
||||
filterCapabilitiesChanged = pyqtSignal()
|
||||
filterOnlineOnlyChanged = pyqtSignal()
|
||||
|
||||
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)
|
||||
def filterConnectionType(self) -> int:
|
||||
|
@ -65,9 +72,10 @@ class GlobalStacksModel(ListModel):
|
|||
return -1
|
||||
return self._filter_connection_type.value
|
||||
|
||||
filterOnlineOnlyChanged = pyqtSignal()
|
||||
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)
|
||||
def filterOnlineOnly(self) -> bool:
|
||||
|
@ -76,6 +84,20 @@ class GlobalStacksModel(ListModel):
|
|||
"""
|
||||
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:
|
||||
"""Handler for container added/removed events from registry"""
|
||||
|
||||
|
@ -108,6 +130,10 @@ class GlobalStacksModel(ListModel):
|
|||
if self._filter_online_only and not is_online:
|
||||
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())
|
||||
section_name = "Connected printers" if has_remote_connection else "Preset printers"
|
||||
section_name = self._catalog.i18nc("@info:title", section_name)
|
||||
|
|
|
@ -106,11 +106,15 @@ class IntentCategoryModel(ListModel):
|
|||
for category in available_categories:
|
||||
qualities = IntentModel()
|
||||
qualities.setIntentCategory(category)
|
||||
try:
|
||||
weight = list(IntentCategoryModel._get_translations().keys()).index(category)
|
||||
except ValueError:
|
||||
weight = 99
|
||||
result.append({
|
||||
"name": IntentCategoryModel.translation(category, "name", category),
|
||||
"description": IntentCategoryModel.translation(category, "description", None),
|
||||
"intent_category": category,
|
||||
"weight": list(IntentCategoryModel._get_translations().keys()).index(category),
|
||||
"weight": weight,
|
||||
"qualities": qualities
|
||||
})
|
||||
result.sort(key = lambda k: k["weight"])
|
||||
|
|
|
@ -361,8 +361,15 @@ class QualityManagementModel(ListModel):
|
|||
"section_name": catalog.i18nc("@label", intent_translations.get(intent_category, {}).get("name", catalog.i18nc("@label", "Unknown"))),
|
||||
})
|
||||
# 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
|
||||
|
||||
# Create quality_changes group items
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# 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 typing import Optional
|
||||
import requests
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Logger import Logger
|
||||
from datetime import datetime
|
||||
from hashlib import sha512
|
||||
from PyQt5.QtNetwork import QNetworkReply
|
||||
import secrets
|
||||
from typing import Callable, Optional
|
||||
import urllib.parse
|
||||
|
||||
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")
|
||||
TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
|
@ -30,14 +31,13 @@ class AuthorizationHelpers:
|
|||
|
||||
return self._settings
|
||||
|
||||
def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str) -> "AuthenticationResponse":
|
||||
"""Request the access token from the authorization server.
|
||||
|
||||
def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str, callback: Callable[[AuthenticationResponse], None]) -> None:
|
||||
"""
|
||||
Request the access token from the authorization server.
|
||||
:param authorization_code: The authorization code from the 1st step.
|
||||
: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 = {
|
||||
"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 "",
|
||||
|
@ -46,18 +46,21 @@ class AuthorizationHelpers:
|
|||
"code_verifier": verification_code,
|
||||
"scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "",
|
||||
}
|
||||
try:
|
||||
return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore
|
||||
except requests.exceptions.ConnectionError as connection_error:
|
||||
return AuthenticationResponse(success = False, err_message = f"Unable to connect to remote server: {connection_error}")
|
||||
headers = {"Content-type": "application/x-www-form-urlencoded"}
|
||||
HttpRequestManager.getInstance().post(
|
||||
self._token_url,
|
||||
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":
|
||||
"""Request the access token from the authorization server using a refresh token.
|
||||
|
||||
:param refresh_token:
|
||||
:return: An AuthenticationResponse object.
|
||||
def getAccessTokenUsingRefreshToken(self, refresh_token: str, callback: Callable[[AuthenticationResponse], None]) -> None:
|
||||
"""
|
||||
Request the access token from the authorization server using a refresh token.
|
||||
:param refresh_token: A long-lived token used to refresh the authentication token.
|
||||
: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)
|
||||
data = {
|
||||
"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,
|
||||
"scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "",
|
||||
}
|
||||
try:
|
||||
return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore
|
||||
except requests.exceptions.ConnectionError:
|
||||
return AuthenticationResponse(success = False, err_message = "Unable to connect to remote server")
|
||||
except OSError as e:
|
||||
return AuthenticationResponse(success = False, err_message = "Operating system is unable to set up a secure connection: {err}".format(err = str(e)))
|
||||
headers = {"Content-type": "application/x-www-form-urlencoded"}
|
||||
HttpRequestManager.getInstance().post(
|
||||
self._token_url,
|
||||
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)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def parseTokenResponse(token_response: requests.models.Response) -> "AuthenticationResponse":
|
||||
def parseTokenResponse(self, token_response: QNetworkReply, callback: Callable[[AuthenticationResponse], None]) -> None:
|
||||
"""Parse the token response from the authorization server into an AuthenticationResponse object.
|
||||
|
||||
:param token_response: The JSON string data response from the authorization server.
|
||||
:return: An AuthenticationResponse object.
|
||||
"""
|
||||
|
||||
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)
|
||||
|
||||
token_data = HttpRequestManager.readJSON(token_response)
|
||||
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):
|
||||
return AuthenticationResponse(success = False, err_message = token_data["error_description"])
|
||||
if token_response.error() != QNetworkReply.NetworkError.NoError:
|
||||
callback(AuthenticationResponse(success = False, err_message = token_data["error_description"]))
|
||||
return
|
||||
|
||||
return AuthenticationResponse(success=True,
|
||||
token_type=token_data["token_type"],
|
||||
access_token=token_data["access_token"],
|
||||
refresh_token=token_data["refresh_token"],
|
||||
expires_in=token_data["expires_in"],
|
||||
scope=token_data["scope"],
|
||||
received_at=datetime.now().strftime(TOKEN_TIMESTAMP_FORMAT))
|
||||
callback(AuthenticationResponse(success = True,
|
||||
token_type = token_data["token_type"],
|
||||
access_token = token_data["access_token"],
|
||||
refresh_token = token_data["refresh_token"],
|
||||
expires_in = token_data["expires_in"],
|
||||
scope = token_data["scope"],
|
||||
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.
|
||||
|
||||
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.
|
||||
: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.
|
||||
"""
|
||||
|
||||
try:
|
||||
check_token_url = "{}/check-token".format(self._settings.OAUTH_SERVER_URL)
|
||||
Logger.log("d", "Checking the access token for [%s]", check_token_url)
|
||||
token_request = requests.get(check_token_url, headers = {
|
||||
"Authorization": "Bearer {}".format(access_token)
|
||||
})
|
||||
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
|
||||
# Connection was suddenly dropped. Nothing we can do about that.
|
||||
Logger.logException("w", "Something failed while attempting to parse the JWT token")
|
||||
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", [])
|
||||
check_token_url = "{}/check-token".format(self._settings.OAUTH_SERVER_URL)
|
||||
Logger.log("d", "Checking the access token for [%s]", check_token_url)
|
||||
headers = {
|
||||
"Authorization": f"Bearer {access_token}"
|
||||
}
|
||||
HttpRequestManager.getInstance().get(
|
||||
check_token_url,
|
||||
headers_dict = headers,
|
||||
callback = lambda reply: self._parseUserProfile(reply, success_callback, failed_callback),
|
||||
error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None
|
||||
)
|
||||
|
||||
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
|
||||
def generateVerificationCode(code_length: int = 32) -> str:
|
||||
"""Generate a verification code of arbitrary length.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
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 urllib.parse import parse_qs, urlparse
|
||||
|
||||
|
@ -14,6 +15,7 @@ if TYPE_CHECKING:
|
|||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
class AuthorizationRequestHandler(BaseHTTPRequestHandler):
|
||||
"""This handler handles all HTTP requests on the local web server.
|
||||
|
||||
|
@ -24,11 +26,11 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
|
|||
super().__init__(request, client_address, server)
|
||||
|
||||
# These values will be injected by the HTTPServer that this handler belongs to.
|
||||
self.authorization_helpers = None # type: Optional[AuthorizationHelpers]
|
||||
self.authorization_callback = None # type: Optional[Callable[[AuthenticationResponse], None]]
|
||||
self.verification_code = None # type: Optional[str]
|
||||
self.authorization_helpers: Optional[AuthorizationHelpers] = None
|
||||
self.authorization_callback: Optional[Callable[[AuthenticationResponse], None]] = None
|
||||
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.
|
||||
def do_HEAD(self) -> None:
|
||||
|
@ -70,13 +72,23 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
|
|||
if state != self.state:
|
||||
token_response = AuthenticationResponse(
|
||||
success = False,
|
||||
err_message=catalog.i18nc("@message",
|
||||
"The provided state is not correct.")
|
||||
err_message = catalog.i18nc("@message", "The provided state is not correct.")
|
||||
)
|
||||
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.
|
||||
token_response = self.authorization_helpers.getAccessTokenUsingAuthorizationCode(
|
||||
code, self.verification_code)
|
||||
lock = Lock()
|
||||
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":
|
||||
# Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog).
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
import json
|
||||
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
|
||||
|
||||
import requests.exceptions
|
||||
from PyQt5.QtCore import QUrl
|
||||
from PyQt5.QtGui import QDesktopServices
|
||||
|
||||
|
@ -16,7 +15,7 @@ from UM.Signal import Signal
|
|||
from UM.i18n import i18nCatalog
|
||||
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT
|
||||
from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer
|
||||
from cura.OAuth2.Models import AuthenticationResponse
|
||||
from cura.OAuth2.Models import AuthenticationResponse, BaseModel
|
||||
|
||||
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"
|
||||
|
||||
|
||||
class AuthorizationService:
|
||||
"""The authorization service is responsible for handling the login flow, storing user credentials and providing
|
||||
account information.
|
||||
|
@ -43,12 +43,13 @@ class AuthorizationService:
|
|||
self._settings = settings
|
||||
self._auth_helpers = AuthorizationHelpers(settings)
|
||||
self._auth_url = "{}/authorize".format(self._settings.OAUTH_SERVER_URL)
|
||||
self._auth_data = None # type: Optional[AuthenticationResponse]
|
||||
self._user_profile = None # type: Optional["UserProfile"]
|
||||
self._auth_data: Optional[AuthenticationResponse] = None
|
||||
self._user_profile: Optional["UserProfile"] = None
|
||||
self._preferences = preferences
|
||||
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)
|
||||
|
||||
|
@ -62,69 +63,80 @@ class AuthorizationService:
|
|||
if self._preferences:
|
||||
self._preferences.addPreference(self._settings.AUTH_DATA_PREFERENCE_KEY, "{}")
|
||||
|
||||
def getUserProfile(self) -> Optional["UserProfile"]:
|
||||
"""Get the user profile as obtained from the JWT (JSON Web Token).
|
||||
def getUserProfile(self, callback: Optional[Callable[[Optional["UserProfile"]], None]] = None) -> None:
|
||||
"""
|
||||
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.
|
||||
|
||||
:return: UserProfile if a user is logged in, None otherwise.
|
||||
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
|
||||
the profile fails to be obtained, this function will be called with None.
|
||||
|
||||
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.
|
||||
try:
|
||||
self._user_profile = self._parseJWT()
|
||||
except requests.exceptions.ConnectionError:
|
||||
# Unable to get connection, can't login.
|
||||
Logger.logException("w", "Unable to validate user data with the remote server.")
|
||||
return None
|
||||
# If no user profile was stored locally, we try to get it from JWT.
|
||||
def store_profile(profile: Optional["UserProfile"]) -> None:
|
||||
if profile is not None:
|
||||
self._user_profile = profile
|
||||
if callback is not None:
|
||||
callback(profile)
|
||||
elif self._auth_data:
|
||||
# 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:
|
||||
# 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
|
||||
self._parseJWT(callback = store_profile)
|
||||
|
||||
return self._user_profile
|
||||
|
||||
def _parseJWT(self) -> Optional["UserProfile"]:
|
||||
"""Tries to parse the JWT (JSON Web Token) data, which it does if all the needed data is there.
|
||||
|
||||
:return: UserProfile if it was able to parse, None otherwise.
|
||||
def _parseJWT(self, callback: Callable[[Optional["UserProfile"]], None]) -> None:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
if not self._auth_data or self._auth_data.access_token is None:
|
||||
# If no auth data exists, we should always log in again.
|
||||
Logger.log("d", "There was no auth data or access token")
|
||||
return None
|
||||
Logger.debug("There was no auth data or access token")
|
||||
callback(None)
|
||||
return
|
||||
|
||||
try:
|
||||
user_data = self._auth_helpers.parseJWT(self._auth_data.access_token)
|
||||
except AttributeError:
|
||||
# THis might seem a bit double, but we get crash reports about this (CURA-2N2 in sentry)
|
||||
Logger.log("d", "There was no auth data or access token")
|
||||
return None
|
||||
# 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.
|
||||
def check_user_profile(user_profile: Optional["UserProfile"]) -> None:
|
||||
if user_profile:
|
||||
# If the profile was found, we call it back immediately.
|
||||
callback(user_profile)
|
||||
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:
|
||||
# If the profile was found, we return it immediately.
|
||||
return user_data
|
||||
# The JWT was expired or invalid and we should request a new one.
|
||||
if self._auth_data.refresh_token is None:
|
||||
Logger.log("w", "There was no refresh token in the auth data.")
|
||||
return None
|
||||
self._auth_data = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token)
|
||||
if not self._auth_data or self._auth_data.access_token is None:
|
||||
Logger.log("w", "Unable to use the refresh token to get a new access token.")
|
||||
# The token could not be refreshed using the refresh token. We should login again.
|
||||
return None
|
||||
# Ensure it gets stored as otherwise we only have it in memory. The stored refresh token has been deleted
|
||||
# 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
|
||||
if self._auth_data.success:
|
||||
self._storeAuthData(self._auth_data)
|
||||
return self._auth_helpers.parseJWT(self._auth_data.access_token)
|
||||
def process_auth_data(auth_data: AuthenticationResponse) -> None:
|
||||
if auth_data.access_token is None:
|
||||
Logger.warning("Unable to use the refresh token to get a new access token.")
|
||||
callback(None)
|
||||
return
|
||||
# Ensure it gets stored as otherwise we only have it in memory. The stored refresh token has been
|
||||
# deleted from the server already. Do not store the auth_data if we could not get new auth_data (e.g.
|
||||
# due to a network error), since this would cause an infinite loop trying to get new auth-data.
|
||||
if auth_data.success:
|
||||
self._storeAuthData(auth_data)
|
||||
self._auth_helpers.checkToken(auth_data.access_token, callback, lambda: callback(None))
|
||||
|
||||
self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token, process_auth_data)
|
||||
|
||||
self._auth_helpers.checkToken(self._auth_data.access_token, check_user_profile, lambda: check_user_profile(None))
|
||||
|
||||
def getAccessToken(self) -> Optional[str]:
|
||||
"""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:
|
||||
Logger.log("w", "Unable to refresh access token, since there is no refresh token.")
|
||||
return
|
||||
response = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token)
|
||||
if response.success:
|
||||
self._storeAuthData(response)
|
||||
self.onAuthStateChanged.emit(logged_in = True)
|
||||
else:
|
||||
Logger.log("w", "Failed to get a new access token from the server.")
|
||||
self.onAuthStateChanged.emit(logged_in = False)
|
||||
|
||||
def process_auth_data(response: AuthenticationResponse) -> None:
|
||||
if response.success:
|
||||
self._storeAuthData(response)
|
||||
self.onAuthStateChanged.emit(logged_in = True)
|
||||
else:
|
||||
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:
|
||||
"""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))
|
||||
if 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",
|
||||
"Unable to reach the Ultimaker account server."),
|
||||
title = i18n_catalog.i18nc("@info:title", "Warning"),
|
||||
message_type = Message.MessageType.ERROR)
|
||||
Logger.log("w", "Unable to load auth data from preferences")
|
||||
self._unable_to_get_data_message.show()
|
||||
# Also check if we can actually get the user profile information.
|
||||
def callback(profile: Optional["UserProfile"]) -> None:
|
||||
if profile is not None:
|
||||
self.onAuthStateChanged.emit(logged_in = True)
|
||||
Logger.debug("Auth data was successfully loaded")
|
||||
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):
|
||||
Logger.logException("w", "Could not load auth data from preferences")
|
||||
|
||||
|
@ -271,8 +292,9 @@ class AuthorizationService:
|
|||
return
|
||||
|
||||
self._auth_data = auth_data
|
||||
self._currently_refreshing_token = False
|
||||
if auth_data:
|
||||
self._user_profile = self.getUserProfile()
|
||||
self.getUserProfile()
|
||||
self._preferences.setValue(self._settings.AUTH_DATA_PREFERENCE_KEY, json.dumps(auth_data.dump()))
|
||||
else:
|
||||
Logger.log("d", "Clearing the user profile")
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
from typing import Type, TYPE_CHECKING, Optional, List
|
||||
|
||||
from io import BlockingIOError
|
||||
import keyring
|
||||
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
|
||||
|
||||
|
@ -44,7 +45,7 @@ class KeyringAttribute:
|
|||
self._store_secure = False
|
||||
Logger.logException("w", "No keyring backend present")
|
||||
return getattr(instance, self._name)
|
||||
except KeyringLocked:
|
||||
except (KeyringLocked, BlockingIOError):
|
||||
self._store_secure = False
|
||||
Logger.log("i", "Access to the keyring was denied.")
|
||||
return getattr(instance, self._name)
|
||||
|
@ -52,6 +53,10 @@ class KeyringAttribute:
|
|||
self._store_secure = False
|
||||
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)
|
||||
except KeyringError:
|
||||
self._store_secure = False
|
||||
Logger.logException("w", "Unknown keyring error.")
|
||||
return getattr(instance, self._name)
|
||||
else:
|
||||
return getattr(instance, self._name)
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ class PickingPass(RenderPass):
|
|||
|
||||
window_size = self._renderer.getWindowSize()
|
||||
|
||||
px = (0.5 + x / 2.0) * window_size[0]
|
||||
py = (0.5 + y / 2.0) * window_size[1]
|
||||
px = int((0.5 + x / 2.0) * window_size[0])
|
||||
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):
|
||||
return -1
|
||||
|
|
|
@ -42,7 +42,7 @@ class PrintJobOutputModel(QObject):
|
|||
self._preview_image = None # type: Optional[QImage]
|
||||
|
||||
@pyqtProperty("QStringList", notify=compatibleMachineFamiliesChanged)
|
||||
def compatibleMachineFamilies(self):
|
||||
def compatibleMachineFamilies(self) -> List[str]:
|
||||
# Hack; Some versions of cluster will return a family more than once...
|
||||
return list(set(self._compatible_machine_families))
|
||||
|
||||
|
@ -77,11 +77,11 @@ class PrintJobOutputModel(QObject):
|
|||
self._configuration = configuration
|
||||
self.configurationChanged.emit()
|
||||
|
||||
@pyqtProperty(str, notify=ownerChanged)
|
||||
def owner(self):
|
||||
@pyqtProperty(str, notify = ownerChanged)
|
||||
def owner(self) -> str:
|
||||
return self._owner
|
||||
|
||||
def updateOwner(self, owner):
|
||||
def updateOwner(self, owner: str) -> None:
|
||||
if self._owner != owner:
|
||||
self._owner = owner
|
||||
self.ownerChanged.emit()
|
||||
|
@ -132,7 +132,7 @@ class PrintJobOutputModel(QObject):
|
|||
|
||||
@pyqtProperty(float, notify = timeElapsedChanged)
|
||||
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
|
||||
|
||||
@pyqtProperty(str, notify=stateChanged)
|
||||
|
@ -151,12 +151,12 @@ class PrintJobOutputModel(QObject):
|
|||
return False
|
||||
return True
|
||||
|
||||
def updateTimeTotal(self, new_time_total):
|
||||
def updateTimeTotal(self, new_time_total: int) -> None:
|
||||
if self._time_total != new_time_total:
|
||||
self._time_total = new_time_total
|
||||
self.timeTotalChanged.emit()
|
||||
|
||||
def updateTimeElapsed(self, new_time_elapsed):
|
||||
def updateTimeElapsed(self, new_time_elapsed: int) -> None:
|
||||
if self._time_elapsed != new_time_elapsed:
|
||||
self._time_elapsed = new_time_elapsed
|
||||
self.timeElapsedChanged.emit()
|
||||
|
|
|
@ -83,6 +83,14 @@ class UploadMaterialsJob(Job):
|
|||
host_guid = "*", # 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:
|
||||
self._printer_sync_status[printer["host_guid"]] = self.PrinterStatus.UPLOADING.value
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ from UM.Scene.SceneNode import SceneNode
|
|||
from UM.Scene.Selection import Selection
|
||||
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
||||
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
|
||||
|
||||
|
@ -403,6 +404,32 @@ class ExtruderManager(QObject):
|
|||
raise IndexError(msg)
|
||||
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")
|
||||
def getInstanceExtruderValues(self, key: str) -> List:
|
||||
"""Get all extruder values for a certain setting.
|
||||
|
|
|
@ -1535,7 +1535,7 @@ class MachineManager(QObject):
|
|||
machine_node = ContainerTree.getInstance().machines.get(machine_definition_id)
|
||||
variant_node = machine_node.variants.get(variant_name)
|
||||
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
|
||||
self.setVariant(position, variant_node)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import numpy
|
||||
|
||||
from PyQt5 import QtCore
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
from PyQt5.QtGui import QImage
|
||||
|
||||
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 = int(render_width)
|
||||
render_height = int(render_height)
|
||||
QCoreApplication.processEvents() # This ensures that the opengl context is correctly available
|
||||
preview_pass = PreviewPass(render_width, render_height)
|
||||
|
||||
root = scene.getRoot()
|
||||
|
|
|
@ -17,7 +17,9 @@ class CuraSplashScreen(QSplashScreen):
|
|||
self._scale = 0.7
|
||||
self._version_y_offset = 0 # when extra visual elements are in the background image, move version text down
|
||||
|
||||
if ApplicationMetadata.IsEnterpriseVersion:
|
||||
if ApplicationMetadata.IsAlternateVersion:
|
||||
splash_image = QPixmap(Resources.getPath(Resources.Images, "cura_wip.png"))
|
||||
elif ApplicationMetadata.IsEnterpriseVersion:
|
||||
splash_image = QPixmap(Resources.getPath(Resources.Images, "cura_enterprise.png"))
|
||||
self._version_y_offset = 26
|
||||
else:
|
||||
|
@ -70,7 +72,7 @@ class CuraSplashScreen(QSplashScreen):
|
|||
font = QFont() # Using system-default font here
|
||||
font.setPixelSize(18)
|
||||
painter.setFont(font)
|
||||
painter.drawText(60, 70 + self._version_y_offset, round(330 * self._scale), round(230 * self._scale), Qt.AlignLeft | Qt.AlignTop, version[0])
|
||||
painter.drawText(60, 70 + self._version_y_offset, round(330 * self._scale), round(230 * self._scale), Qt.AlignLeft | Qt.AlignTop, version[0] if not ApplicationMetadata.IsAlternateVersion else ApplicationMetadata.CuraBuildType)
|
||||
if len(version) > 1:
|
||||
font.setPixelSize(16)
|
||||
painter.setFont(font)
|
||||
|
|
|
@ -46,7 +46,9 @@ class TextManager(QObject):
|
|||
line = line.replace("[", "")
|
||||
line = line.replace("]", "")
|
||||
open_version = Version(line)
|
||||
if open_version > Version([14, 99, 99]): # Bit of a hack: We released the 15.x.x versions before 2.x
|
||||
if open_version < Version([0, 0, 1]): # Something went wrong with parsing, assume non-numerical alternate version that should be on top.
|
||||
open_version = Version([99, 99, 99])
|
||||
if Version([14, 99, 99]) < open_version < Version([16, 0, 0]): # Bit of a hack: We released the 15.x.x versions before 2.x
|
||||
open_version = Version([0, open_version.getMinor(), open_version.getRevision(), open_version.getPostfixVersion()])
|
||||
open_header = ""
|
||||
change_logs_dict[open_version] = collections.OrderedDict()
|
||||
|
@ -66,7 +68,9 @@ class TextManager(QObject):
|
|||
text_version = version
|
||||
if version < Version([1, 0, 0]): # Bit of a hack: We released the 15.x.x versions before 2.x
|
||||
text_version = Version([15, version.getMinor(), version.getRevision(), version.getPostfixVersion()])
|
||||
content += "<h1>" + str(text_version) + "</h1><br>"
|
||||
if version > Version([99, 0, 0]): # Leave it out altogether if it was originally a non-numbered version.
|
||||
text_version = ""
|
||||
content += ("<h1>" + str(text_version) + "</h1><br>") if text_version else ""
|
||||
content += ""
|
||||
for change in change_logs_dict[version]:
|
||||
if str(change) != "":
|
||||
|
|
|
@ -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.
|
||||
from collections import deque
|
||||
|
||||
import os
|
||||
|
||||
from collections import deque
|
||||
from typing import TYPE_CHECKING, Optional, List, Dict, Any
|
||||
|
||||
from PyQt5.QtCore import QUrl, Qt, pyqtSlot, pyqtProperty, pyqtSignal
|
||||
|
@ -16,24 +18,23 @@ if TYPE_CHECKING:
|
|||
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):
|
||||
"""
|
||||
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
|
||||
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._pages = [] # type: List[Dict[str, Any]]
|
||||
self._pages: List[Dict[str, Any]] = []
|
||||
|
||||
self._current_page_index = 0
|
||||
# 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
|
||||
# specific case. See initialize() for how this variable is set.
|
||||
|
@ -72,17 +73,21 @@ class WelcomePagesModel(ListModel):
|
|||
def currentPageIndex(self) -> int:
|
||||
return self._current_page_index
|
||||
|
||||
# Returns a float number in [0, 1] which indicates the current progress.
|
||||
@pyqtProperty(float, notify = currentPageIndexChanged)
|
||||
def currentProgress(self) -> float:
|
||||
"""
|
||||
Returns a float number in [0, 1] which indicates the current progress.
|
||||
"""
|
||||
if len(self._items) == 0:
|
||||
return 0
|
||||
else:
|
||||
return self._current_page_index / len(self._items)
|
||||
|
||||
# Indicates if the current page is the last page.
|
||||
@pyqtProperty(bool, notify = currentPageIndexChanged)
|
||||
def isCurrentPageLast(self) -> bool:
|
||||
"""
|
||||
Indicates if the current page is the last page.
|
||||
"""
|
||||
return self._current_page_index == len(self._items) - 1
|
||||
|
||||
def _setCurrentPageIndex(self, page_index: int) -> None:
|
||||
|
@ -91,17 +96,22 @@ class WelcomePagesModel(ListModel):
|
|||
self._current_page_index = page_index
|
||||
self.currentPageIndexChanged.emit()
|
||||
|
||||
# Ends the Welcome-Pages. Put as a separate function for cases like the 'decline' in the User-Agreement.
|
||||
@pyqtSlot()
|
||||
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.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()
|
||||
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
|
||||
current_index = self._current_page_index if from_index is None else from_index
|
||||
while True:
|
||||
|
@ -137,9 +147,11 @@ class WelcomePagesModel(ListModel):
|
|||
# Move to the next page
|
||||
self._setCurrentPageIndex(next_page_index)
|
||||
|
||||
# Goes to the previous page. If there's no previous page, do nothing.
|
||||
@pyqtSlot()
|
||||
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:
|
||||
Logger.log("i", "No previous page, do nothing")
|
||||
return
|
||||
|
@ -148,9 +160,9 @@ class WelcomePagesModel(ListModel):
|
|||
self._current_page_index = previous_page_index
|
||||
self.currentPageIndexChanged.emit()
|
||||
|
||||
# Sets the current page to the given page ID. If the page ID is not found, do nothing.
|
||||
@pyqtSlot(str)
|
||||
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)
|
||||
if page_index is None:
|
||||
# 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"
|
||||
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:
|
||||
"""
|
||||
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)
|
||||
should_show_function = next_page_item.get("should_show_function", lambda: True)
|
||||
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()
|
||||
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._previous_page_indices_stack.clear()
|
||||
|
||||
|
@ -188,8 +204,8 @@ class WelcomePagesModel(ListModel):
|
|||
def shouldShowWelcomeFlow(self) -> bool:
|
||||
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]:
|
||||
"""Gets the page index with the given page ID. If the page ID doesn't exist, returns None."""
|
||||
page_idx = None
|
||||
for idx, page_item in enumerate(self._items):
|
||||
if page_item["id"] == page_id:
|
||||
|
@ -197,8 +213,9 @@ class WelcomePagesModel(ListModel):
|
|||
break
|
||||
return page_idx
|
||||
|
||||
# Convenience function to get QUrl path to pages that's located in "resources/qml/WelcomePages".
|
||||
def _getBuiltinWelcomePagePath(self, page_filename: str) -> "QUrl":
|
||||
@staticmethod
|
||||
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
|
||||
return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles,
|
||||
os.path.join("WelcomePages", page_filename)))
|
||||
|
@ -213,21 +230,22 @@ class WelcomePagesModel(ListModel):
|
|||
self._initialize()
|
||||
|
||||
def _initialize(self, update_should_show_flag: bool = True) -> None:
|
||||
show_whatsnew_only = False
|
||||
show_whats_new_only = False
|
||||
if update_should_show_flag:
|
||||
has_active_machine = self._application.getMachineManager().activeMachine is not None
|
||||
has_app_just_upgraded = self._application.hasJustUpdatedFromOldVersion()
|
||||
|
||||
# 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_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
|
||||
# possibly some others, setting the initial active machine is not done when the MachineManager gets initialized.
|
||||
# So at this point, we don't know if there will be an active machine or not. It could be that the active machine
|
||||
# files are corrupted so we cannot rely on Preferences either. This makes sure that once the active machine
|
||||
# gets changed, this model updates the flags, so it can decide whether to show the welcome flow or not.
|
||||
should_show_welcome_flow = show_complete_flow or show_whatsnew_only
|
||||
# possibly some others, setting the initial active machine is not done when the MachineManager gets
|
||||
# initialized. So at this point, we don't know if there will be an active machine or not. It could be that
|
||||
# the active machine files are corrupted so we cannot rely on Preferences either. This makes sure that once
|
||||
# the active machine gets changed, this model updates the flags, so it can decide whether to show the
|
||||
# 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:
|
||||
self._should_show_welcome_flow = should_show_welcome_flow
|
||||
self.shouldShowWelcomeFlowChanged.emit()
|
||||
|
@ -274,23 +292,25 @@ class WelcomePagesModel(ListModel):
|
|||
]
|
||||
|
||||
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))
|
||||
|
||||
self._pages = pages_to_show
|
||||
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:
|
||||
# For convenience, inject the default "next" button text to each item if it's not present.
|
||||
for item in items:
|
||||
if "next_page_button_text" not in item:
|
||||
item["next_page_button_text"] = self._default_next_button_text
|
||||
|
||||
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:
|
||||
"""
|
||||
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
|
||||
if global_stack is None:
|
||||
return False
|
||||
|
@ -312,6 +332,3 @@ class WelcomePagesModel(ListModel):
|
|||
|
||||
def addPage(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
__all__ = ["WelcomePagesModel"]
|
||||
|
|
|
@ -1,27 +1,39 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
from .WelcomePagesModel import WelcomePagesModel
|
||||
|
||||
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 UM.Logger import Logger
|
||||
from UM.Resources import Resources
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
from cura.UI.WelcomePagesModel import WelcomePagesModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from PyQt5.QtCore import QObject
|
||||
from cura.CuraApplication import CuraApplication
|
||||
|
||||
|
||||
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"]
|
||||
text_formats = [".txt", ".htm", ".html"]
|
||||
image_key = "image"
|
||||
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
|
||||
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
|
||||
try:
|
||||
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)
|
||||
highest = max(max_image, max_text)
|
||||
|
||||
self._subpages = [] #type: List[Dict[str, Optional[str]]]
|
||||
self._subpages = []
|
||||
for n in range(0, highest + 1):
|
||||
self._subpages.append({
|
||||
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:
|
||||
result = self._getSubpageItem(page, WhatsNewPagesModel.text_key)
|
||||
return result if result else "* * *"
|
||||
|
||||
__all__ = ["WhatsNewPagesModel"]
|
||||
|
|
|
@ -57,6 +57,7 @@ class CloudMaterialSync(QObject):
|
|||
self.sync_all_dialog.setProperty("syncModel", self)
|
||||
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("syncStatusText", "") # Reset any previous error messages.
|
||||
self.sync_all_dialog.show()
|
||||
|
||||
def _showSyncNewMaterialsMessage(self) -> None:
|
||||
|
|
|
@ -13,6 +13,9 @@ DEFAULT_DIGITAL_FACTORY_URL = "https://digitalfactory.ultimaker.com" # type: st
|
|||
META_UM_LINKED_TO_ACCOUNT = "um_linked_to_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:
|
||||
from cura.CuraVersion import CuraCloudAPIRoot # type: ignore
|
||||
if CuraCloudAPIRoot == "":
|
||||
|
|
|
@ -48,6 +48,8 @@ if with_sentry_sdk:
|
|||
sentry_env = "development" # Master is always a development version.
|
||||
elif "beta" in ApplicationMetadata.CuraVersion or "BETA" in ApplicationMetadata.CuraVersion:
|
||||
sentry_env = "beta"
|
||||
elif "alpha" in ApplicationMetadata.CuraVersion or "ALPHA" in ApplicationMetadata.CuraVersion:
|
||||
sentry_env = "alpha"
|
||||
try:
|
||||
if ApplicationMetadata.CuraVersion.split(".")[2] == "99":
|
||||
sentry_env = "nightly"
|
||||
|
|
|
@ -49,7 +49,9 @@ _ignored_machine_network_metadata = {
|
|||
"removal_warning",
|
||||
"group_name",
|
||||
"group_size",
|
||||
"connection_type"
|
||||
"connection_type",
|
||||
"capabilities",
|
||||
"octoprint_api_key",
|
||||
} # type: Set[str]
|
||||
|
||||
|
||||
|
@ -377,7 +379,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
# - the global stack DOESN'T exist but some/all of the extruder stacks exist
|
||||
# To simplify this, only check if the global stack exists or not
|
||||
global_stack_id = self._stripFileToId(global_stack_file)
|
||||
|
||||
serialized = archive.open(global_stack_file).read().decode("utf-8")
|
||||
|
||||
serialized = GlobalStack._updateSerialized(serialized, global_stack_file)
|
||||
machine_name = self._getMachineNameFromSerializedStack(serialized)
|
||||
self._machine_info.metadata_dict = self._getMetaDataDictFromSerializedStack(serialized)
|
||||
|
|
|
@ -32,6 +32,12 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
Logger.error("3MF Writer class is unavailable. Can't write workspace.")
|
||||
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).
|
||||
mesh_writer.setStoreArchive(True)
|
||||
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.
|
||||
archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED)
|
||||
|
||||
global_stack = machine_manager.activeMachine
|
||||
|
||||
try:
|
||||
# Add global container stack data to the archive.
|
||||
|
@ -149,7 +154,8 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
"group_name",
|
||||
"group_size",
|
||||
"connection_type",
|
||||
"octoprint_api_key"
|
||||
"capabilities",
|
||||
"octoprint_api_key",
|
||||
}
|
||||
serialized_data = container.serialize(ignored_metadata_keys = ignore_keys)
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ from UM.Application import Application
|
|||
from UM.Scene.SceneNode import SceneNode
|
||||
|
||||
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
|
||||
|
||||
|
@ -149,6 +153,22 @@ class ThreeMFWriter(MeshWriter):
|
|||
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")
|
||||
|
||||
# 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()
|
||||
|
||||
metadata_to_store = CuraApplication.getInstance().getController().getScene().getMetaData()
|
||||
|
@ -212,3 +232,17 @@ class ThreeMFWriter(MeshWriter):
|
|||
self._archive = archive
|
||||
|
||||
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
|
||||
|
|
|
@ -261,7 +261,10 @@ class DigitalFactoryController(QObject):
|
|||
"""
|
||||
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)
|
||||
|
||||
@pyqtSlot()
|
||||
|
|
|
@ -479,7 +479,15 @@ class PauseAtHeight(Script):
|
|||
else:
|
||||
Logger.log("w", "No previous feedrate found in gcode, feedrate for next layer(s) might be incorrect")
|
||||
|
||||
prepend_gcode += self.putValue(M = 82) + "\n"
|
||||
extrusion_mode_string = "absolute"
|
||||
extrusion_mode_numeric = 82
|
||||
|
||||
relative_extrusion = Application.getInstance().getGlobalContainerStack().getProperty("relative_extrusion", "value")
|
||||
if relative_extrusion:
|
||||
extrusion_mode_string = "relative"
|
||||
extrusion_mode_numeric = 83
|
||||
|
||||
prepend_gcode += self.putValue(M = extrusion_mode_numeric) + " ; switch back to " + extrusion_mode_string + " E values\n"
|
||||
|
||||
# reset extrude value to pre pause value
|
||||
prepend_gcode += self.putValue(G = 92, E = current_e) + "\n"
|
||||
|
|
|
@ -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.
|
||||
|
||||
from UM.Math.Color import Color
|
||||
|
|
|
@ -56,12 +56,12 @@ vertex41core =
|
|||
value = (abs_value - min_value) / (max_value - min_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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ vertex41core =
|
|||
{
|
||||
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);
|
||||
if (value > 0.75)
|
||||
{
|
||||
|
@ -98,18 +98,18 @@ vertex41core =
|
|||
value = (abs_value - min_value) / (max_value - min_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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Simulation View",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.1",
|
||||
"description": "Provides the Simulation view.",
|
||||
"description": "Provides the preview of sliced layerdata.",
|
||||
"api": 7,
|
||||
"i18n-catalog": "cura"
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class CloudPackageChecker(QObject):
|
|||
self._application.getHttpRequestManager().get(url,
|
||||
callback = self._onUserPackagesRequestFinished,
|
||||
error_callback = self._onUserPackagesRequestFinished,
|
||||
timeout=10,
|
||||
timeout = 10,
|
||||
scope = self._scope)
|
||||
|
||||
def _onUserPackagesRequestFinished(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"] = None) -> None:
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"description": "Provides support for reading Ultimaker Format Packages.",
|
||||
"supported_sdk_versions": ["7.8.0"],
|
||||
"supported_sdk_versions": ["7.9.0"],
|
||||
"i18n-catalog": "cura"
|
||||
}
|
|
@ -66,6 +66,8 @@ Item
|
|||
switch (printJob.state)
|
||||
{
|
||||
case "wait_cleanup":
|
||||
// This hack was removed previously. Then we found out that we don't get back 'aborted_wait_cleanup'
|
||||
// for the UM2+C it seems. Will communicate this to other teams, in the mean time, put this back.
|
||||
if (printJob.timeTotal > printJob.timeElapsed)
|
||||
{
|
||||
return catalog.i18nc("@label:status", "Aborted");
|
||||
|
@ -81,6 +83,20 @@ Item
|
|||
return catalog.i18nc("@label:status", "Aborting...");
|
||||
case "aborted": // NOTE: Unused, see above
|
||||
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":
|
||||
return catalog.i18nc("@label:status", "Pausing...");
|
||||
case "paused":
|
||||
|
|
|
@ -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.CuraStackBuilder import CuraStackBuilder
|
||||
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 .CloudOutputDevice import CloudOutputDevice
|
||||
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
|
||||
|
@ -128,6 +128,8 @@ class CloudOutputDeviceManager:
|
|||
# to the current account
|
||||
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)
|
||||
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._updateOnlinePrinters(all_clusters)
|
||||
|
|
|
@ -37,7 +37,7 @@ class CloudClusterResponse(BaseModel):
|
|||
self.friendly_name = friendly_name
|
||||
self.printer_type = printer_type
|
||||
self.printer_count = printer_count
|
||||
self.capabilities = capabilities
|
||||
self.capabilities = capabilities if capabilities is not None else []
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# Validates the model, raising an exception if the model is invalid.
|
||||
|
@ -45,3 +45,10 @@ class CloudClusterResponse(BaseModel):
|
|||
super().validate()
|
||||
if not self.cluster_id:
|
||||
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"}})
|
||||
|
|
|
@ -40,7 +40,7 @@ class ClusterPrintJobStatus(BaseModel):
|
|||
configuration_changes_required: List[
|
||||
Union[Dict[str, Any], ClusterPrintJobConfigurationChange]] = 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,
|
||||
preview_url: Optional[str] = None,
|
||||
**kwargs) -> None:
|
||||
|
@ -97,7 +97,7 @@ class ClusterPrintJobStatus(BaseModel):
|
|||
configuration_changes_required) \
|
||||
if configuration_changes_required else []
|
||||
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) \
|
||||
if impediments_to_printing else []
|
||||
|
||||
|
@ -130,8 +130,10 @@ class ClusterPrintJobStatus(BaseModel):
|
|||
|
||||
model.updateConfiguration(self._createConfigurationModel())
|
||||
model.updateTimeTotal(self.time_total)
|
||||
model.updateTimeElapsed(self.time_elapsed)
|
||||
model.updateOwner(self.owner)
|
||||
if self.time_elapsed is not None:
|
||||
model.updateTimeElapsed(self.time_elapsed)
|
||||
if self.owner is not None:
|
||||
model.updateOwner(self.owner)
|
||||
model.updateState(self.status)
|
||||
model.setCompatibleMachineFamilies(self.compatible_machine_families)
|
||||
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser
|
||||
from typing import Tuple, List
|
||||
import io
|
||||
from UM.VersionUpgrade import VersionUpgrade
|
||||
|
||||
_removed_settings = {
|
||||
"travel_compensate_overlapping_walls_enabled",
|
||||
"travel_compensate_overlapping_walls_0_enabled",
|
||||
"travel_compensate_overlapping_walls_x_enabled",
|
||||
"fill_perimeter_gaps",
|
||||
"wall_min_flow",
|
||||
"wall_min_flow_retract",
|
||||
"speed_equalize_flow_enabled",
|
||||
"speed_equalize_flow_min"
|
||||
}
|
||||
|
||||
|
||||
class VersionUpgrade49to50(VersionUpgrade):
|
||||
def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades preferences to remove from the visibility list the settings that were removed in this version.
|
||||
It also changes the preferences to have the new version number.
|
||||
|
||||
This removes any settings that were removed in the new Cura version.
|
||||
:param serialized: The original contents of the preferences file.
|
||||
:param filename: The file name of the preferences file.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = "18"
|
||||
|
||||
# Remove deleted settings from the visible settings list.
|
||||
if "general" in parser and "visible_settings" in parser["general"]:
|
||||
visible_settings = set(parser["general"]["visible_settings"].split(";"))
|
||||
for removed in _removed_settings:
|
||||
if removed in visible_settings:
|
||||
visible_settings.remove(removed)
|
||||
|
||||
# Replace Outer Before Inner Walls with equivalent.
|
||||
if "outer_inset_first" in visible_settings:
|
||||
visible_settings.remove("outer_inset_first")
|
||||
visible_settings.add("inset_direction")
|
||||
|
||||
parser["general"]["visible_settings"] = ";".join(visible_settings)
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades instance containers to remove the settings that were removed in this version.
|
||||
It also changes the instance containers to have the new version number.
|
||||
|
||||
This removes any settings that were removed in the new Cura version and updates settings that need to be updated
|
||||
with a new value.
|
||||
|
||||
:param serialized: The original contents of the instance container.
|
||||
:param filename: The original file name of the instance container.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes = ())
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
parser["metadata"]["setting_version"] = "18"
|
||||
|
||||
if "values" in parser:
|
||||
# Remove deleted settings from the instance containers.
|
||||
for removed in _removed_settings:
|
||||
if removed in parser["values"]:
|
||||
del parser["values"][removed]
|
||||
|
||||
# Replace Outer Before Inner Walls with equivalent setting.
|
||||
if "outer_inset_first" in parser["values"]:
|
||||
old_value = parser["values"]["outer_inset_first"]
|
||||
if old_value.startswith("="): # Was already a formula.
|
||||
old_value = old_value[1:]
|
||||
parser["values"]["inset_direction"] = f"='outside_in' if ({old_value}) else 'inside_out'" # Makes it work both with plain setting values and formulas.
|
||||
|
||||
# Disable Fuzzy Skin as it doesn't work with with the libArachne walls
|
||||
if "magic_fuzzy_skin_enabled" in parser["values"]:
|
||||
parser["values"]["magic_fuzzy_skin_enabled"] = "False"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades stacks to have the new version number.
|
||||
|
||||
:param serialized: The original contents of the stack.
|
||||
:param filename: The original file name of the stack.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
|
||||
# Update version number.
|
||||
if "metadata" not in parser:
|
||||
parser["metadata"] = {}
|
||||
|
||||
parser["general"]["version"] = "5"
|
||||
parser["metadata"]["setting_version"] = "18"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
61
plugins/VersionUpgrade/VersionUpgrade49to50/__init__.py
Normal file
61
plugins/VersionUpgrade/VersionUpgrade49to50/__init__.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Copyright (c) 2020 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from typing import Any, Dict, TYPE_CHECKING
|
||||
|
||||
from . import VersionUpgrade49to50
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from UM.Application import Application
|
||||
|
||||
upgrade = VersionUpgrade49to50.VersionUpgrade49to50()
|
||||
|
||||
def getMetaData() -> Dict[str, Any]:
|
||||
return { # Since there is no VersionUpgrade from 48 to 49 yet, upgrade the 48 profiles to 50.
|
||||
"version_upgrade": {
|
||||
# From To Upgrade function
|
||||
("preferences", 6000016): ("preferences", 6000018, upgrade.upgradePreferences),
|
||||
("machine_stack", 5000016): ("machine_stack", 5000018, upgrade.upgradeStack),
|
||||
("extruder_train", 5000016): ("extruder_train", 5000018, upgrade.upgradeStack),
|
||||
("machine_stack", 4000018): ("machine_stack", 5000018, upgrade.upgradeStack), # We made a mistake in the arachne beta 1
|
||||
("extruder_train", 4000018): ("extruder_train", 5000018, upgrade.upgradeStack), # We made a mistake in the arachne beta 1
|
||||
("definition_changes", 4000016): ("definition_changes", 4000018, upgrade.upgradeInstanceContainer),
|
||||
("quality_changes", 4000016): ("quality_changes", 4000018, upgrade.upgradeInstanceContainer),
|
||||
("quality", 4000016): ("quality", 4000018, upgrade.upgradeInstanceContainer),
|
||||
("user", 4000016): ("user", 4000018, upgrade.upgradeInstanceContainer),
|
||||
},
|
||||
"sources": {
|
||||
"preferences": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"."}
|
||||
},
|
||||
"machine_stack": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./machine_instances"}
|
||||
},
|
||||
"extruder_train": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./extruders"}
|
||||
},
|
||||
"definition_changes": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./definition_changes"}
|
||||
},
|
||||
"quality_changes": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./quality_changes"}
|
||||
},
|
||||
"quality": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./quality"}
|
||||
},
|
||||
"user": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./user"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def register(app: "Application") -> Dict[str, Any]:
|
||||
return {"version_upgrade": upgrade}
|
8
plugins/VersionUpgrade/VersionUpgrade49to50/plugin.json
Normal file
8
plugins/VersionUpgrade/VersionUpgrade49to50/plugin.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Version Upgrade 4.9 to 5.0",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"description": "Upgrades configurations from Cura 4.9 to Cura 5.0.",
|
||||
"api": "7.4.0",
|
||||
"i18n-catalog": "cura"
|
||||
}
|
|
@ -29,7 +29,7 @@ pywin32==301
|
|||
requests==2.22.0
|
||||
scipy==1.6.2
|
||||
sentry-sdk==0.13.5
|
||||
shapely[vectorized]==1.7.1
|
||||
shapely[vectorized]==1.8.0
|
||||
six==1.12.0
|
||||
trimesh==3.2.33
|
||||
twisted==21.2.0
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"display_name": "3MF Reader",
|
||||
"description": "Provides support for reading 3MF files.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -23,7 +23,7 @@
|
|||
"display_name": "3MF Writer",
|
||||
"description": "Provides support for writing 3MF files.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -40,7 +40,7 @@
|
|||
"display_name": "AMF Reader",
|
||||
"description": "Provides support for reading AMF files.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "fieldOfView",
|
||||
|
@ -57,7 +57,7 @@
|
|||
"display_name": "Cura Backups",
|
||||
"description": "Backup and restore your configuration.",
|
||||
"package_version": "1.2.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -74,7 +74,7 @@
|
|||
"display_name": "CuraEngine Backend",
|
||||
"description": "Provides the link to the CuraEngine slicing backend.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -91,7 +91,7 @@
|
|||
"display_name": "Cura Profile Reader",
|
||||
"description": "Provides support for importing Cura profiles.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -108,7 +108,7 @@
|
|||
"display_name": "Cura Profile Writer",
|
||||
"description": "Provides support for exporting Cura profiles.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -125,7 +125,7 @@
|
|||
"display_name": "Ultimaker 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",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -142,7 +142,7 @@
|
|||
"display_name": "Firmware Update Checker",
|
||||
"description": "Checks for firmware updates.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -159,7 +159,7 @@
|
|||
"display_name": "Firmware Updater",
|
||||
"description": "Provides a machine actions for updating firmware.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -176,7 +176,7 @@
|
|||
"display_name": "Compressed G-code Reader",
|
||||
"description": "Reads g-code from a compressed archive.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -193,7 +193,7 @@
|
|||
"display_name": "Compressed G-code Writer",
|
||||
"description": "Writes g-code to a compressed archive.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -210,7 +210,7 @@
|
|||
"display_name": "G-Code Profile Reader",
|
||||
"description": "Provides support for importing profiles from g-code files.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -227,7 +227,7 @@
|
|||
"display_name": "G-Code Reader",
|
||||
"description": "Allows loading and displaying G-code files.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "VictorLarchenko",
|
||||
|
@ -244,7 +244,7 @@
|
|||
"display_name": "G-Code Writer",
|
||||
"description": "Writes g-code to a file.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -261,7 +261,7 @@
|
|||
"display_name": "Image Reader",
|
||||
"description": "Enables ability to generate printable geometry from 2D image files.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -278,7 +278,7 @@
|
|||
"display_name": "Legacy Cura Profile Reader",
|
||||
"description": "Provides support for importing profiles from legacy Cura versions.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -295,7 +295,7 @@
|
|||
"display_name": "Machine Settings Action",
|
||||
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "fieldOfView",
|
||||
|
@ -312,7 +312,7 @@
|
|||
"display_name": "Model Checker",
|
||||
"description": "Checks models and print configuration for possible printing issues and give suggestions.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -329,7 +329,7 @@
|
|||
"display_name": "Monitor Stage",
|
||||
"description": "Provides a monitor stage in Cura.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -346,7 +346,7 @@
|
|||
"display_name": "Per-Object Settings Tool",
|
||||
"description": "Provides the per-model settings.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -363,7 +363,7 @@
|
|||
"display_name": "Post Processing",
|
||||
"description": "Extension that allows for user created scripts for post processing.",
|
||||
"package_version": "2.2.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -380,7 +380,7 @@
|
|||
"display_name": "Prepare Stage",
|
||||
"description": "Provides a prepare stage in Cura.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -397,7 +397,7 @@
|
|||
"display_name": "Preview Stage",
|
||||
"description": "Provides a preview stage in Cura.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -414,7 +414,7 @@
|
|||
"display_name": "Removable Drive Output Device",
|
||||
"description": "Provides removable drive hotplugging and writing support.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -431,7 +431,7 @@
|
|||
"display_name": "Sentry Logger",
|
||||
"description": "Logs certain events so that they can be used by the crash reporter",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -448,7 +448,7 @@
|
|||
"display_name": "Simulation View",
|
||||
"description": "Provides the Simulation view.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -465,7 +465,7 @@
|
|||
"display_name": "Slice Info",
|
||||
"description": "Submits anonymous slice info. Can be disabled through preferences.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -482,7 +482,7 @@
|
|||
"display_name": "Solid View",
|
||||
"description": "Provides a normal solid mesh view.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -499,7 +499,7 @@
|
|||
"display_name": "Support Eraser Tool",
|
||||
"description": "Creates an eraser mesh to block the printing of support in certain places.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -516,7 +516,7 @@
|
|||
"display_name": "Trimesh Reader",
|
||||
"description": "Provides support for reading model files.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -533,7 +533,7 @@
|
|||
"display_name": "Toolbox",
|
||||
"description": "Find, manage and install new Cura packages.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -550,7 +550,7 @@
|
|||
"display_name": "UFP Reader",
|
||||
"description": "Provides support for reading Ultimaker Format Packages.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -567,7 +567,7 @@
|
|||
"display_name": "UFP Writer",
|
||||
"description": "Provides support for writing Ultimaker Format Packages.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -584,7 +584,7 @@
|
|||
"display_name": "Ultimaker Machine Actions",
|
||||
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -601,7 +601,7 @@
|
|||
"display_name": "UM3 Network Printing",
|
||||
"description": "Manages network connections to Ultimaker 3 printers.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -618,7 +618,7 @@
|
|||
"display_name": "USB Printing",
|
||||
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
|
||||
"package_version": "1.0.2",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -635,7 +635,7 @@
|
|||
"display_name": "Version Upgrade 2.1 to 2.2",
|
||||
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -652,7 +652,7 @@
|
|||
"display_name": "Version Upgrade 2.2 to 2.4",
|
||||
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -669,7 +669,7 @@
|
|||
"display_name": "Version Upgrade 2.5 to 2.6",
|
||||
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -686,7 +686,7 @@
|
|||
"display_name": "Version Upgrade 2.6 to 2.7",
|
||||
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -703,7 +703,7 @@
|
|||
"display_name": "Version Upgrade 2.7 to 3.0",
|
||||
"description": "Upgrades configurations from Cura 2.7 to Cura 3.0.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -720,7 +720,7 @@
|
|||
"display_name": "Version Upgrade 3.0 to 3.1",
|
||||
"description": "Upgrades configurations from Cura 3.0 to Cura 3.1.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -737,7 +737,7 @@
|
|||
"display_name": "Version Upgrade 3.2 to 3.3",
|
||||
"description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -754,7 +754,7 @@
|
|||
"display_name": "Version Upgrade 3.3 to 3.4",
|
||||
"description": "Upgrades configurations from Cura 3.3 to Cura 3.4.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -771,7 +771,7 @@
|
|||
"display_name": "Version Upgrade 3.4 to 3.5",
|
||||
"description": "Upgrades configurations from Cura 3.4 to Cura 3.5.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -788,7 +788,7 @@
|
|||
"display_name": "Version Upgrade 3.5 to 4.0",
|
||||
"description": "Upgrades configurations from Cura 3.5 to Cura 4.0.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -805,7 +805,7 @@
|
|||
"display_name": "Version Upgrade 4.0 to 4.1",
|
||||
"description": "Upgrades configurations from Cura 4.0 to Cura 4.1.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -822,7 +822,7 @@
|
|||
"display_name": "Version Upgrade 4.1 to 4.2",
|
||||
"description": "Upgrades configurations from Cura 4.1 to Cura 4.2.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -839,7 +839,7 @@
|
|||
"display_name": "Version Upgrade 4.2 to 4.3",
|
||||
"description": "Upgrades configurations from Cura 4.2 to Cura 4.3.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -856,7 +856,7 @@
|
|||
"display_name": "Version Upgrade 4.3 to 4.4",
|
||||
"description": "Upgrades configurations from Cura 4.3 to Cura 4.4.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -873,7 +873,7 @@
|
|||
"display_name": "Version Upgrade 4.4 to 4.5",
|
||||
"description": "Upgrades configurations from Cura 4.4 to Cura 4.5.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -890,7 +890,7 @@
|
|||
"display_name": "Version Upgrade 4.5 to 4.6",
|
||||
"description": "Upgrades configurations from Cura 4.5 to Cura 4.6.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -907,7 +907,7 @@
|
|||
"display_name": "Version Upgrade 4.6.0 to 4.6.2",
|
||||
"description": "Upgrades configurations from Cura 4.6.0 to Cura 4.6.2.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -924,7 +924,7 @@
|
|||
"display_name": "Version Upgrade 4.6.2 to 4.7",
|
||||
"description": "Upgrades configurations from Cura 4.6.2 to Cura 4.7.",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -941,7 +941,7 @@
|
|||
"display_name": "Version Upgrade 4.7.0 to 4.8.0",
|
||||
"description": "Upgrades configurations from Cura 4.7.0 to Cura 4.8.0",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -958,7 +958,7 @@
|
|||
"display_name": "Version Upgrade 4.8.0 to 4.9.0",
|
||||
"description": "Upgrades configurations from Cura 4.8.0 to Cura 4.9.0",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -976,7 +976,7 @@
|
|||
"description": "Upgrades configurations from Cura 4.9 to Cura 4.10",
|
||||
"package_version": "1.0.0",
|
||||
"sdk_version": 7,
|
||||
"sdk_version_semver": "7.8.0",
|
||||
"sdk_version_semver": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1011,7 +1011,7 @@
|
|||
"display_name": "X3D Reader",
|
||||
"description": "Provides support for reading X3D files.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "SevaAlekseyev",
|
||||
|
@ -1028,7 +1028,7 @@
|
|||
"display_name": "XML Material Profiles",
|
||||
"description": "Provides capabilities to read and write XML-based material profiles.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1045,7 +1045,7 @@
|
|||
"display_name": "X-Ray View",
|
||||
"description": "Provides the X-Ray view.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1062,7 +1062,7 @@
|
|||
"display_name": "Generic ABS",
|
||||
"description": "The generic ABS profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1080,7 +1080,7 @@
|
|||
"display_name": "Generic BAM",
|
||||
"description": "The generic BAM profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1098,7 +1098,7 @@
|
|||
"display_name": "Generic CFF CPE",
|
||||
"description": "The generic CFF CPE profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1116,7 +1116,7 @@
|
|||
"display_name": "Generic CFF PA",
|
||||
"description": "The generic CFF PA profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1134,7 +1134,7 @@
|
|||
"display_name": "Generic CPE",
|
||||
"description": "The generic CPE profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1152,7 +1152,7 @@
|
|||
"display_name": "Generic CPE+",
|
||||
"description": "The generic CPE+ profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1170,7 +1170,7 @@
|
|||
"display_name": "Generic GFF CPE",
|
||||
"description": "The generic GFF CPE profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1188,7 +1188,7 @@
|
|||
"display_name": "Generic GFF PA",
|
||||
"description": "The generic GFF PA profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1206,7 +1206,7 @@
|
|||
"display_name": "Generic HIPS",
|
||||
"description": "The generic HIPS profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1224,7 +1224,7 @@
|
|||
"display_name": "Generic Nylon",
|
||||
"description": "The generic Nylon profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1242,7 +1242,7 @@
|
|||
"display_name": "Generic PC",
|
||||
"description": "The generic PC profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1260,7 +1260,7 @@
|
|||
"display_name": "Generic PETG",
|
||||
"description": "The generic PETG profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1278,7 +1278,7 @@
|
|||
"display_name": "Generic PLA",
|
||||
"description": "The generic PLA profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1296,7 +1296,7 @@
|
|||
"display_name": "Generic PP",
|
||||
"description": "The generic PP profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1314,7 +1314,7 @@
|
|||
"display_name": "Generic PVA",
|
||||
"description": "The generic PVA profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1332,7 +1332,7 @@
|
|||
"display_name": "Generic Tough PLA",
|
||||
"description": "The generic Tough PLA profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1350,7 +1350,7 @@
|
|||
"display_name": "Generic TPU",
|
||||
"description": "The generic TPU profile which other profiles can be based upon.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://github.com/Ultimaker/fdm_materials",
|
||||
"author": {
|
||||
"author_id": "Generic",
|
||||
|
@ -1368,7 +1368,7 @@
|
|||
"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.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://dagoma.fr/boutique/filaments.html",
|
||||
"author": {
|
||||
"author_id": "Dagoma",
|
||||
|
@ -1385,7 +1385,7 @@
|
|||
"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 it’s compatible with all versions of the FABtotum Personal fabricator.",
|
||||
"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",
|
||||
"author": {
|
||||
"author_id": "FABtotum",
|
||||
|
@ -1402,7 +1402,7 @@
|
|||
"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.",
|
||||
"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",
|
||||
"author": {
|
||||
"author_id": "FABtotum",
|
||||
|
@ -1419,7 +1419,7 @@
|
|||
"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 starch’s 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 FABtotum’s one is between 185° and 195°.",
|
||||
"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",
|
||||
"author": {
|
||||
"author_id": "FABtotum",
|
||||
|
@ -1436,7 +1436,7 @@
|
|||
"display_name": "FABtotum TPU Shore 98A",
|
||||
"description": "",
|
||||
"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",
|
||||
"author": {
|
||||
"author_id": "FABtotum",
|
||||
|
@ -1453,7 +1453,7 @@
|
|||
"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.",
|
||||
"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/",
|
||||
"author": {
|
||||
"author_id": "Fiberlogy",
|
||||
|
@ -1470,7 +1470,7 @@
|
|||
"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.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://dagoma.fr",
|
||||
"author": {
|
||||
"author_id": "Dagoma",
|
||||
|
@ -1487,7 +1487,7 @@
|
|||
"display_name": "IMADE3D JellyBOX PETG",
|
||||
"description": "",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "http://shop.imade3d.com/filament.html",
|
||||
"author": {
|
||||
"author_id": "IMADE3D",
|
||||
|
@ -1504,7 +1504,7 @@
|
|||
"display_name": "IMADE3D JellyBOX PLA",
|
||||
"description": "",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "http://shop.imade3d.com/filament.html",
|
||||
"author": {
|
||||
"author_id": "IMADE3D",
|
||||
|
@ -1521,7 +1521,7 @@
|
|||
"display_name": "Octofiber PLA",
|
||||
"description": "PLA material from Octofiber.",
|
||||
"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",
|
||||
"author": {
|
||||
"author_id": "Octofiber",
|
||||
|
@ -1538,7 +1538,7 @@
|
|||
"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.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "http://www.polymaker.com/shop/polyflex/",
|
||||
"author": {
|
||||
"author_id": "Polymaker",
|
||||
|
@ -1555,7 +1555,7 @@
|
|||
"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.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "http://www.polymaker.com/shop/polymax/",
|
||||
"author": {
|
||||
"author_id": "Polymaker",
|
||||
|
@ -1572,7 +1572,7 @@
|
|||
"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.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "http://www.polymaker.com/shop/polyplus-true-colour/",
|
||||
"author": {
|
||||
"author_id": "Polymaker",
|
||||
|
@ -1589,7 +1589,7 @@
|
|||
"display_name": "PolyWood™ PLA",
|
||||
"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",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "http://www.polymaker.com/shop/polywood/",
|
||||
"author": {
|
||||
"author_id": "Polymaker",
|
||||
|
@ -1606,7 +1606,7 @@
|
|||
"display_name": "Ultimaker ABS",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/abs",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1625,7 +1625,7 @@
|
|||
"display_name": "Ultimaker Breakaway",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/breakaway",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1644,7 +1644,7 @@
|
|||
"display_name": "Ultimaker CPE",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/abs",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1663,7 +1663,7 @@
|
|||
"display_name": "Ultimaker CPE+",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/cpe",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1682,7 +1682,7 @@
|
|||
"display_name": "Ultimaker Nylon",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/abs",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1701,7 +1701,7 @@
|
|||
"display_name": "Ultimaker PC",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/pc",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1720,7 +1720,7 @@
|
|||
"display_name": "Ultimaker PLA",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/abs",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1739,7 +1739,7 @@
|
|||
"display_name": "Ultimaker PP",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/pp",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1758,7 +1758,7 @@
|
|||
"display_name": "Ultimaker PVA",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/abs",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1777,7 +1777,7 @@
|
|||
"display_name": "Ultimaker TPU 95A",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/tpu-95a",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1796,7 +1796,7 @@
|
|||
"display_name": "Ultimaker Tough PLA",
|
||||
"description": "Example package for material and quality profiles for Ultimaker materials.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://ultimaker.com/products/materials/tough-pla",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
|
@ -1815,7 +1815,7 @@
|
|||
"display_name": "Vertex Delta ABS",
|
||||
"description": "ABS material and quality files for the Delta Vertex K8800.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://vertex3dprinter.eu",
|
||||
"author": {
|
||||
"author_id": "Velleman",
|
||||
|
@ -1832,7 +1832,7 @@
|
|||
"display_name": "Vertex Delta PET",
|
||||
"description": "ABS material and quality files for the Delta Vertex K8800.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://vertex3dprinter.eu",
|
||||
"author": {
|
||||
"author_id": "Velleman",
|
||||
|
@ -1849,7 +1849,7 @@
|
|||
"display_name": "Vertex Delta PLA",
|
||||
"description": "ABS material and quality files for the Delta Vertex K8800.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://vertex3dprinter.eu",
|
||||
"author": {
|
||||
"author_id": "Velleman",
|
||||
|
@ -1866,7 +1866,7 @@
|
|||
"display_name": "Vertex Delta TPU",
|
||||
"description": "ABS material and quality files for the Delta Vertex K8800.",
|
||||
"package_version": "1.4.0",
|
||||
"sdk_version": "7.8.0",
|
||||
"sdk_version": "7.9.0",
|
||||
"website": "https://vertex3dprinter.eu",
|
||||
"author": {
|
||||
"author_id": "Velleman",
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_weighted'" },
|
||||
|
@ -87,7 +86,6 @@
|
|||
"infill_wipe_dist": { "value": 0 },
|
||||
"wall_0_wipe_dist": { "value": 0.2 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": true },
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature + 10" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"infill_sparse_density": { "value": 25 },
|
||||
"infill_before_walls": { "value": false },
|
||||
|
@ -91,7 +90,7 @@
|
|||
|
||||
"retraction_hop_enabled": { "value": true },
|
||||
"retraction_hop": { "value": 0.075 },
|
||||
"retraction_hop_only_when_collides": { "value": true },
|
||||
"retraction_hop_only_when_collides": { "value": true },
|
||||
|
||||
"retraction_combing": { "value": "'off'" },
|
||||
"retraction_combing_max_distance": { "value": 30 },
|
||||
|
@ -99,13 +98,13 @@
|
|||
"travel_avoid_supports": { "value": true },
|
||||
"travel_retract_before_outer_wall": { "value": true },
|
||||
|
||||
"retraction_amount": { "value": 6 },
|
||||
"retraction_amount": { "value": 6 },
|
||||
"retraction_enable": { "value": true },
|
||||
"retraction_min_travel": { "value": 1.5 },
|
||||
|
||||
"cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" },
|
||||
"cool_fan_speed": { "value": 70 },
|
||||
"cool_fan_speed_0": { "value": 30 },
|
||||
"cool_fan_speed": { "value": 70 },
|
||||
"cool_fan_speed_0": { "value": 30 },
|
||||
|
||||
"cool_fan_enabled": { "value": true },
|
||||
"cool_min_layer_time": { "value": 10 },
|
||||
|
@ -116,7 +115,6 @@
|
|||
"skirt_line_count": { "value": 4 },
|
||||
|
||||
"meshfix_maximum_deviation": { "value": 0.05 },
|
||||
|
||||
"support_angle": { "value": "math.floor(math.degrees(math.atan(line_width / 2.0 / layer_height)))" },
|
||||
"support_pattern": { "value": "'zigzag'" },
|
||||
"support_infill_rate": { "value": "0 if support_enable and support_structure == 'tree' else 20" },
|
||||
|
@ -124,14 +122,15 @@
|
|||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
"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_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_wall_count": { "value": 1 },
|
||||
"support_brim_enable": { "value": true },
|
||||
"support_brim_width": { "value": 4 },
|
||||
|
||||
"support_interface_enable": { "value": true },
|
||||
"support_structure": { "value": "'tree'" },
|
||||
"support_type": { "value": "'buildplate' if support_structure == 'tree' else 'everywhere'" },
|
||||
"support_structure": { "value": "'tree'" },
|
||||
"support_type": { "value": "'buildplate' if support_structure == 'tree' else 'everywhere'" },
|
||||
"support_interface_height": { "value": "layer_height * 4" },
|
||||
"support_interface_density": { "value": 33.333 },
|
||||
"support_interface_pattern": { "value": "'grid'" },
|
||||
|
|
|
@ -179,7 +179,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_none'" },
|
||||
|
@ -192,7 +191,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -258,7 +258,6 @@
|
|||
"layer_height_0": { "resolve": "max(0.2, min(extruderValues('layer_height')))" },
|
||||
"line_width": { "value": "machine_nozzle_size * 1.125" },
|
||||
"wall_line_width": { "value": "machine_nozzle_size" },
|
||||
"fill_perimeter_gaps": { "default_value": "everywhere" },
|
||||
"fill_outline_gaps": { "value": "True" },
|
||||
"meshfix_maximum_resolution": { "value": "0.01" },
|
||||
"meshfix_maximum_deviation": { "value": "layer_height / 2" },
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
"machine_heated_bed": { "default_value": false },
|
||||
"machine_center_is_zero": { "default_value": true },
|
||||
|
||||
"machine_start_gcode": { "default_value": "G21\nG90 \nM107\nG28\nG92 E0\nG1 F200 E3\nG92 E0" },
|
||||
"machine_end_gcode": { "default_value": "M104 S0\nG28\nG91\nG1 E-6 F300\nM84\nG90" },
|
||||
"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": "G28\nG91\nG1 E-6 F300\nM104 S0\nG1 E-1000 F5000\nM84\nG90" },
|
||||
|
||||
"layer_height": { "default_value": 0.2 },
|
||||
"default_material_print_temperature": { "default_value": 210 },
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Ultimaker",
|
||||
"manufacturer": "BFB",
|
||||
"file_formats": "text/x-gcode",
|
||||
"platform_offset": [ 0, 0, 0],
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"z_seam_type": { "value": "'sharpest_corner'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_inner'" },
|
||||
|
@ -97,7 +96,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -45,9 +45,6 @@
|
|||
"machine_gcode_flavor": {
|
||||
"default_value": "RepRap (RepRap)"
|
||||
},
|
||||
"fill_perimeter_gaps": {
|
||||
"value": "'everywhere'"
|
||||
},
|
||||
"fill_outline_gaps": {
|
||||
"value": true
|
||||
},
|
||||
|
|
|
@ -52,9 +52,9 @@
|
|||
"skirt_line_count": { "default_value" : 5 },
|
||||
"initial_layer_line_width_factor": { "default_value" : 140 },
|
||||
"top_bottom_pattern": { "default_value" : "concentric" },
|
||||
"outer_inset_first": { "default_value": true },
|
||||
"fill_outline_gaps": { "default_value": true },
|
||||
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
|
||||
"inset_direction": {"value": "'outside_in'" },
|
||||
"machine_start_gcode": {
|
||||
"default_value": "G28 ; home all axes\nG1 Z15 F5000 ; lift nozzle\nG92 E0\nG1 F200 E3\n"
|
||||
},
|
||||
|
|
|
@ -183,7 +183,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_weighted'" },
|
||||
|
@ -196,7 +195,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
@ -247,7 +245,8 @@
|
|||
"support_use_towers": { "value": false },
|
||||
"support_xy_distance": { "value": "wall_line_width_0 * 2" },
|
||||
"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_wall_count": { "value": 1 },
|
||||
"support_brim_enable": { "value": true },
|
||||
|
|
25
resources/definitions/creality_cr100.def.json
Normal file
25
resources/definitions/creality_cr100.def.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "Creality CR-100",
|
||||
"version": 2,
|
||||
"inherits": "creality_base",
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Creality CR-100" },
|
||||
"machine_width": { "default_value": 100 },
|
||||
"machine_depth": { "default_value": 100 },
|
||||
"machine_height": { "default_value": 80 },
|
||||
"machine_head_with_fans_polygon": { "default_value": [
|
||||
[-26, 34],
|
||||
[-26, -32],
|
||||
[32, -32],
|
||||
[32, 34]
|
||||
]
|
||||
},
|
||||
|
||||
"gantry_height": { "value": 25 }
|
||||
|
||||
},
|
||||
"metadata": {
|
||||
"quality_definition": "creality_base",
|
||||
"visible": true
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
"inherits": "creality_base",
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Creality Ender-5" },
|
||||
"machine_end_gcode": { "default_value": "G91 ;Relative positioning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positioning\n\nG1 X0 Y0 ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" },
|
||||
"machine_end_gcode": { "default_value": "G91 ;Relative positioning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positioning\n\nG28 X0 Y0 ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n" },
|
||||
"machine_width": { "default_value": 220 },
|
||||
"machine_depth": { "default_value": 220 },
|
||||
"machine_height": { "default_value": 300 },
|
||||
|
|
25
resources/definitions/creality_sermoond1.def.json
Normal file
25
resources/definitions/creality_sermoond1.def.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "Creality Sermoon D1",
|
||||
"version": 2,
|
||||
"inherits": "creality_base",
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Creality Sermoon D1" },
|
||||
"machine_width": { "default_value": 280 },
|
||||
"machine_depth": { "default_value": 260 },
|
||||
"machine_height": { "default_value": 310 },
|
||||
"machine_head_with_fans_polygon": { "default_value": [
|
||||
[-26, 34],
|
||||
[-26, -32],
|
||||
[32, -32],
|
||||
[32, 34]
|
||||
]
|
||||
},
|
||||
|
||||
"gantry_height": { "value": 25 }
|
||||
|
||||
},
|
||||
"metadata": {
|
||||
"quality_definition": "creality_base",
|
||||
"visible": true
|
||||
}
|
||||
}
|
|
@ -20,9 +20,6 @@
|
|||
"machine_heated_bed": {
|
||||
"default_value": true
|
||||
},
|
||||
"travel_compensate_overlapping_walls_enabled": {
|
||||
"default_value": false
|
||||
},
|
||||
"layer_height": {
|
||||
"default_value": 0.2
|
||||
},
|
||||
|
@ -33,7 +30,6 @@
|
|||
"default_value": "raft"
|
||||
},
|
||||
"top_bottom_pattern": { "default_value": "lines" },
|
||||
"fill_perimeter_gaps": { "default_value": "everywhere" },
|
||||
"infill_sparse_density": { "default_value": 20 },
|
||||
"infill_before_walls": { "default_value": false },
|
||||
"top_bottom_thickness": {
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
|
||||
"wall_thickness": {"value":3.0},
|
||||
"optimize_wall_printing_order": { "value": "True" },
|
||||
"travel_compensate_overlapping_walls_enabled": { "value": false},
|
||||
|
||||
"top_bottom_thickness": {"value":0},
|
||||
"bottom_layers":{"value":2},
|
||||
|
|
|
@ -48,10 +48,10 @@
|
|||
},
|
||||
"gantry_height":{ "value": "0" },
|
||||
"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": {
|
||||
"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": {
|
||||
"value": 205
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
"value": 30
|
||||
},
|
||||
"machine_gcode_flavor": {
|
||||
"default_value": "Marlin"
|
||||
"default_value": "RepRap (Marlin/Sprinter)"
|
||||
},
|
||||
"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..."
|
||||
|
@ -62,6 +62,112 @@
|
|||
"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"
|
||||
},
|
||||
"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": {
|
||||
"value": true
|
||||
},
|
||||
|
@ -71,38 +177,6 @@
|
|||
"acceleration_travel": {
|
||||
"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": {
|
||||
"value": true
|
||||
},
|
||||
|
@ -112,35 +186,11 @@
|
|||
"jerk_travel": {
|
||||
"value": 15
|
||||
},
|
||||
"material_bed_temperature": {
|
||||
"maximum_value_warning": 100
|
||||
},
|
||||
"material_print_temperature": {
|
||||
"maximum_value_warning": 250
|
||||
},
|
||||
"optimize_wall_printing_order": {
|
||||
"default_value": true
|
||||
},
|
||||
"outer_inset_first": {
|
||||
"default_value": false
|
||||
},
|
||||
"retract_at_layer_change": {
|
||||
"value": true
|
||||
},
|
||||
"retraction_amount": {
|
||||
"default_value": 4
|
||||
},
|
||||
"retraction_hop": {
|
||||
"value": 0.075
|
||||
},
|
||||
"retraction_hop_enabled": {
|
||||
"value": false
|
||||
},
|
||||
"retraction_hop_only_when_collides": {
|
||||
"value": true
|
||||
},
|
||||
"retraction_min_travel": {
|
||||
"value": 1.5
|
||||
"default_value": 4.5
|
||||
},
|
||||
"retraction_speed": {
|
||||
"default_value": 85,
|
||||
|
@ -153,101 +203,56 @@
|
|||
"value": "math.ceil(retraction_speed * 0.4)",
|
||||
"maximum_value_warning": 130
|
||||
},
|
||||
"retraction_min_travel": {
|
||||
"value": "max(line_width * 2, 1.5)"
|
||||
},
|
||||
"retraction_combing": {
|
||||
"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": {
|
||||
"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
|
||||
},
|
||||
"wall_thickness": {
|
||||
"value": "line_width * wall_line_count"
|
||||
},
|
||||
"bottom_layers": {
|
||||
"value": "4"
|
||||
"skirt_gap": {
|
||||
"value": 5
|
||||
},
|
||||
"bottom_thickness":{
|
||||
"value": "layer_height * bottom_layers"
|
||||
"brim_width": {
|
||||
"value": 5
|
||||
},
|
||||
"top_layers": {
|
||||
"value": "6"
|
||||
"smooth_spiralized_contours": {
|
||||
"value": false
|
||||
},
|
||||
"top_thickness":{
|
||||
"value": "layer_height * top_layers"
|
||||
},
|
||||
"z_seam_type": {
|
||||
"value": "'shortest'"
|
||||
},
|
||||
"z_seam_corner": {
|
||||
"value": "'z_seam_corner_inner'"
|
||||
"roofing_monotonic": {
|
||||
"value": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,8 +62,6 @@
|
|||
"retraction_amount": { "default_value": 6.5 },
|
||||
|
||||
"speed_print": { "default_value": 40 },
|
||||
"speed_equalize_flow_enabled": { "default_value": true },
|
||||
"speed_equalize_flow_max": { "default_value": 100 },
|
||||
|
||||
"acceleration_print": { "default_value": 1000 },
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"metadata":
|
||||
{
|
||||
"type": "machine",
|
||||
"author": "Ultimaker",
|
||||
"author": "Unknown",
|
||||
"manufacturer": "Unknown",
|
||||
"setting_version": 19,
|
||||
"file_formats": "text/x-gcode;model/stl;application/x-wavefront-obj;application/x3g",
|
||||
|
@ -159,6 +159,16 @@
|
|||
"settable_per_extruder": false,
|
||||
"settable_per_meshgroup": false
|
||||
},
|
||||
"machine_height":
|
||||
{
|
||||
"label": "Machine Height",
|
||||
"description": "The height (Z-direction) of the printable area.",
|
||||
"default_value": 100,
|
||||
"type": "float",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false,
|
||||
"settable_per_meshgroup": false
|
||||
},
|
||||
"machine_shape":
|
||||
{
|
||||
"label": "Build Plate Shape",
|
||||
|
@ -189,16 +199,6 @@
|
|||
"settable_per_extruder": false,
|
||||
"settable_per_meshgroup": false
|
||||
},
|
||||
"machine_height":
|
||||
{
|
||||
"label": "Machine Height",
|
||||
"description": "The height (Z-direction) of the printable area.",
|
||||
"default_value": 100,
|
||||
"type": "float",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false,
|
||||
"settable_per_meshgroup": false
|
||||
},
|
||||
"machine_heated_bed":
|
||||
{
|
||||
"label": "Has Heated Build Plate",
|
||||
|
@ -448,7 +448,7 @@
|
|||
"machine_head_with_fans_polygon":
|
||||
{
|
||||
"label": "Machine Head & Fan Polygon",
|
||||
"description": "A 2D silhouette of the print head (fan caps included).",
|
||||
"description": "The shape of the print head. These are coordinates relative to the position of the print head, which is usually the position of its first extruder. The dimensions left and in front of the print head must be negative coordinates.",
|
||||
"type": "polygon",
|
||||
"default_value":
|
||||
[
|
||||
|
@ -571,7 +571,7 @@
|
|||
},
|
||||
"machine_max_feedrate_e":
|
||||
{
|
||||
"label": "Maximum Feedrate",
|
||||
"label": "Maximum Speed E",
|
||||
"description": "The maximum speed of the filament.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
|
@ -831,7 +831,7 @@
|
|||
"description": "Width of the outermost wall line. By lowering this value, higher levels of detail can be printed.",
|
||||
"unit": "mm",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "(0.1 + 0.4 * machine_nozzle_size) if outer_inset_first else 0.1 * machine_nozzle_size",
|
||||
"minimum_value_warning": "(0.1 + 0.4 * machine_nozzle_size) if inset_direction == \"outside_in\" else 0.1 * machine_nozzle_size",
|
||||
"maximum_value_warning": "2 * machine_nozzle_size",
|
||||
"default_value": 0.4,
|
||||
"value": "wall_line_width",
|
||||
|
@ -1056,6 +1056,7 @@
|
|||
"minimum_value": "0",
|
||||
"minimum_value_warning": "line_width",
|
||||
"maximum_value_warning": "10 * line_width",
|
||||
"maximum_value": "999999 * line_width",
|
||||
"type": "float",
|
||||
"limit_to_extruder": "wall_x_extruder_nr",
|
||||
"settable_per_mesh": true,
|
||||
|
@ -1069,6 +1070,7 @@
|
|||
"minimum_value": "0",
|
||||
"minimum_value_warning": "1",
|
||||
"maximum_value_warning": "10",
|
||||
"maximum_value": "999999",
|
||||
"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",
|
||||
"limit_to_extruder": "wall_x_extruder_nr",
|
||||
|
@ -1076,6 +1078,98 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"beading_strategy_type":
|
||||
{
|
||||
"label": "Variable Line Strategy",
|
||||
"description": "Strategy to use to print the width of a part with a number of walls. This determines how many walls it will use for a certain total width, and how wide each of these lines are. \"Center Deviation\" will print all walls at the nominal line width except the central one(s), causing big variations in the center but very consistent outsides. \"Distributed\" distributes the width equally over all walls. \"Inward Distributed\" is a balance between the other two, distributing the changes in width over all walls but keeping the walls on the outside slightly more consistent.",
|
||||
"type": "enum",
|
||||
"options":
|
||||
{
|
||||
"center_deviation": "Center Deviation",
|
||||
"distributed": "Distributed",
|
||||
"inward_distributed": "Inward Distributed"
|
||||
},
|
||||
"default_value": "inward_distributed",
|
||||
"limit_to_extruder": "wall_0_extruder_nr"
|
||||
},
|
||||
"wall_transition_threshold": {
|
||||
"label": "Middle Line Threshold",
|
||||
"description": "The smallest line width, as a factor of the normal line width, below which it will choose to use fewer, but wider lines to fill the available space the wall needs to occupy. Reduce this setting to use more, thinner lines. Increase to use fewer, wider lines. Note that this applies -as if- the entire shape should be filled with wall, so the middle here refers to the middle of the object between two outer edges of the shape, even if there actually is fill or (other) skin in the print instead of wall.",
|
||||
"type": "float",
|
||||
"unit": "%",
|
||||
"default_value": 90,
|
||||
"minimum_value": "1",
|
||||
"maximum_value": "99",
|
||||
"children":
|
||||
{
|
||||
"wall_split_middle_threshold": {
|
||||
"label": "Split Middle Line Threshold",
|
||||
"description": "The smallest line width, as a factor of the normal line width, above which the middle line (if there is one) will be split into two. Reduce this setting to use more, thinner lines. Increase to use fewer, wider lines. Note that this applies -as if- the entire shape should be filled with wall, so the middle here refers to the middle of the object between two outer edges of the shape, even if there actually is fill or (other) skin in the print instead of wall.",
|
||||
"type": "float",
|
||||
"unit": "%",
|
||||
"default_value": 50,
|
||||
"value": "wall_transition_threshold",
|
||||
"minimum_value": "1",
|
||||
"maximum_value": "99"
|
||||
},
|
||||
"wall_add_middle_threshold": {
|
||||
"label": "Add Middle Line Threshold",
|
||||
"description": "The smallest line width, as a factor of the normal line width, above which a middle line (if there wasn't one already) will be added. Reduce this setting to use more, thinner lines. Increase to use fewer, wider lines. Note that this applies -as if- the entire shape should be filled with wall, so the middle here refers to the middle of the object between two outer edges of the shape, even if there actually is fill or (other) skin in the print instead of wall.",
|
||||
"type": "float",
|
||||
"unit": "%",
|
||||
"default_value": 50,
|
||||
"value": "wall_transition_threshold * 8 / 9",
|
||||
"minimum_value": "1",
|
||||
"maximum_value": "99"
|
||||
}
|
||||
}
|
||||
},
|
||||
"wall_transition_length":
|
||||
{
|
||||
"label": "Wall Transition Length",
|
||||
"description": "When transitioning between different numbers of walls as the part becomes thinner, a certain amount of space is allotted to split or join the wall lines.",
|
||||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default_value": 0.4,
|
||||
"value": "line_width",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "0.5 * line_width",
|
||||
"maximum_value_warning": "2 * line_width",
|
||||
"maximum_value": "min_bead_width * 3 * math.pi"
|
||||
},
|
||||
"wall_distribution_count":
|
||||
{
|
||||
"label": "Wall Distribution Count",
|
||||
"description": "The number of walls, counted from the center, over which the variation needs to be spread. Lower values mean that the outer walls don't change in width.",
|
||||
"type": "int",
|
||||
"default_value": 1,
|
||||
"minimum_value": "1",
|
||||
"enabled": "beading_strategy_type == 'inward_distributed'"
|
||||
},
|
||||
"wall_transition_angle":
|
||||
{
|
||||
"label": "Wall Transition Angle",
|
||||
"description": "When transitioning between different numbers of walls as the part becomes thinner, two adjacent walls will join together at this angle. This can make the walls come together faster than what the Wall Transition Length indicates, filling the space better.",
|
||||
"type": "float",
|
||||
"unit": "°",
|
||||
"default_value": 10,
|
||||
"minimum_value": "1",
|
||||
"minimum_value_warning": "5",
|
||||
"maximum_value_warning": "50",
|
||||
"maximum_value": "59"
|
||||
},
|
||||
"wall_transition_filter_distance":
|
||||
{
|
||||
"label": "Wall Transition Distance Filter",
|
||||
"description": "If it would be transitioning back and forth between different numbers of walls in quick succession, don't transition at all. Remove transitions if they are closer together than this distance.",
|
||||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default_value": 1.4,
|
||||
"value": "4 * math.cos(wall_transition_angle / 180 * math.pi) * wall_line_width_x",
|
||||
"minimum_value": "wall_transition_length",
|
||||
"minimum_value_warning": "math.cos(wall_transition_angle / 180 * math.pi) * wall_line_width_x",
|
||||
"maximum_value_warning": "10 * math.cos(wall_transition_angle / 180 * math.pi) * wall_line_width_x"
|
||||
},
|
||||
"wall_0_wipe_dist":
|
||||
{
|
||||
"label": "Outer Wall Wipe Distance",
|
||||
|
@ -1096,7 +1190,7 @@
|
|||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0.0,
|
||||
"value": "(machine_nozzle_size - wall_line_width_0) / 2 if (wall_line_width_0 < machine_nozzle_size and not outer_inset_first) else 0",
|
||||
"value": "(machine_nozzle_size - wall_line_width_0) / 2 if (wall_line_width_0 < machine_nozzle_size and inset_direction != \"outside_in\") else 0",
|
||||
"minimum_value_warning": "0",
|
||||
"maximum_value_warning": "machine_nozzle_size",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
|
@ -1104,19 +1198,23 @@
|
|||
},
|
||||
"optimize_wall_printing_order":
|
||||
{
|
||||
"label": "Optimize Wall Printing Order",
|
||||
"description": "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization. First layer is not optimized when choosing brim as build plate adhesion type.",
|
||||
"label": "Order Inner Walls By Inset",
|
||||
"description": "Order inner wall printing by inset-index, instead of by (hole) region.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"outer_inset_first":
|
||||
"inset_direction":
|
||||
{
|
||||
"label": "Outer Before Inner Walls",
|
||||
"description": "Prints walls in order of outside to inside when enabled. This can help improve dimensional accuracy in X and Y when using a high viscosity plastic like ABS; however it can decrease outer surface print quality, especially on overhangs.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"enabled": "wall_0_extruder_nr == wall_x_extruder_nr",
|
||||
"label": "Wall Ordering",
|
||||
"description": "Determines the order in which walls are printed. Printing outer walls earlier helps with dimensional accuracy, as faults from inner walls cannot propagate to the outside. However printing them later allows them to stack better when overhangs are printed.",
|
||||
"type": "enum",
|
||||
"options": {
|
||||
"inside_out": "Inside To Outside",
|
||||
"outside_in": "Outside To Inside",
|
||||
"center_last": "Center Last"
|
||||
},
|
||||
"default_value": "center_last",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"alternate_extra_perimeter":
|
||||
|
@ -1128,72 +1226,6 @@
|
|||
"limit_to_extruder": "infill_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"travel_compensate_overlapping_walls_enabled":
|
||||
{
|
||||
"label": "Compensate Wall Overlaps",
|
||||
"description": "Compensate the flow for parts of a wall being printed where there is already a wall in place.",
|
||||
"type": "bool",
|
||||
"default_value": true,
|
||||
"limit_to_extruder": "wall_x_extruder_nr",
|
||||
"settable_per_mesh": true,
|
||||
"children":
|
||||
{
|
||||
"travel_compensate_overlapping_walls_0_enabled":
|
||||
{
|
||||
"label": "Compensate Outer Wall Overlaps",
|
||||
"description": "Compensate the flow for parts of an outer wall being printed where there is already a wall in place.",
|
||||
"type": "bool",
|
||||
"default_value": true,
|
||||
"value": "travel_compensate_overlapping_walls_enabled",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"travel_compensate_overlapping_walls_x_enabled":
|
||||
{
|
||||
"label": "Compensate Inner Wall Overlaps",
|
||||
"description": "Compensate the flow for parts of an inner wall being printed where there is already a wall in place.",
|
||||
"type": "bool",
|
||||
"default_value": true,
|
||||
"value": "travel_compensate_overlapping_walls_enabled",
|
||||
"limit_to_extruder": "wall_x_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"wall_min_flow":
|
||||
{
|
||||
"label": "Minimum Wall Flow",
|
||||
"description": "Minimum allowed percentage flow for a wall line. The wall overlap compensation reduces a wall's flow when it lies close to an existing wall. Walls whose flow is less than this value will be replaced with a travel move. When using this setting, you must enable the wall overlap compensation and print the outer wall before inner walls.",
|
||||
"unit": "%",
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "100",
|
||||
"default_value": 0,
|
||||
"type": "float",
|
||||
"enabled": "travel_compensate_overlapping_walls_0_enabled or travel_compensate_overlapping_walls_x_enabled",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"wall_min_flow_retract":
|
||||
{
|
||||
"label": "Prefer Retract",
|
||||
"description": "If enabled, retraction is used rather than combing for travel moves that replace walls whose flow is below the minimum flow threshold.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"enabled": "(travel_compensate_overlapping_walls_0_enabled or travel_compensate_overlapping_walls_x_enabled) and wall_min_flow > 0",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"fill_perimeter_gaps":
|
||||
{
|
||||
"label": "Fill Gaps Between Walls",
|
||||
"description": "Fills the gaps between walls where no walls fit.",
|
||||
"type": "enum",
|
||||
"options": {
|
||||
"nowhere": "Nowhere",
|
||||
"everywhere": "Everywhere"
|
||||
},
|
||||
"default_value": "everywhere",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"filter_out_tiny_gaps":
|
||||
{
|
||||
"label": "Filter Out Tiny Gaps",
|
||||
|
@ -1207,10 +1239,36 @@
|
|||
"label": "Print Thin Walls",
|
||||
"description": "Print pieces of the model which are horizontally thinner than the nozzle size.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"default_value": true,
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"min_feature_size":
|
||||
{
|
||||
"label": "Minimum Feature Size",
|
||||
"description": "Minimum thickness of thin features. Model features that are thinner than this value will not be printed, while features thicker than the Minimum Feature Size will be widened to the Minimum Wall Line Width.",
|
||||
"unit": "mm",
|
||||
"value": "wall_line_width_0 / 4",
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "wall_line_width_0",
|
||||
"type": "float",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"enabled": "fill_outline_gaps"
|
||||
},
|
||||
"min_bead_width":
|
||||
{
|
||||
"label": "Minimum Wall Line Width",
|
||||
"description": "Width of the wall that will replace thin features (according to the Minimum Feature Size) of the model. If the Minimum Wall Line Width is thinner than the thickness of the feature, the wall will become as thick as the feature itself.",
|
||||
"unit": "mm",
|
||||
"value": "wall_line_width_0 * (100.0 + wall_split_middle_threshold)/200",
|
||||
"default_value": "0.2",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "min_feature_size",
|
||||
"maximum_value_warning": "wall_line_width_0",
|
||||
"type": "float",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"enabled": "fill_outline_gaps"
|
||||
},
|
||||
"xy_offset":
|
||||
{
|
||||
"label": "Horizontal Expansion",
|
||||
|
@ -1557,6 +1615,7 @@
|
|||
"default_value": 1,
|
||||
"minimum_value": "0",
|
||||
"maximum_value_warning": "10",
|
||||
"maximum_value": "999999",
|
||||
"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'))",
|
||||
"limit_to_extruder": "top_bottom_extruder_nr",
|
||||
|
@ -1999,6 +2058,7 @@
|
|||
"default_value": 0,
|
||||
"type": "int",
|
||||
"minimum_value": "0",
|
||||
"maximum_value": "999999",
|
||||
"enabled": "infill_sparse_density > 0",
|
||||
"limit_to_extruder": "infill_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
|
@ -2083,9 +2143,9 @@
|
|||
"default_value": 0,
|
||||
"type": "int",
|
||||
"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))",
|
||||
"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",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -2098,7 +2158,7 @@
|
|||
"default_value": 1.5,
|
||||
"minimum_value": "0.0001",
|
||||
"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",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -2452,7 +2512,42 @@
|
|||
"maximum_value_warning": "120",
|
||||
"settable_per_mesh": 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":
|
||||
{
|
||||
|
@ -3163,26 +3258,15 @@
|
|||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"speed_equalize_flow_enabled":
|
||||
"speed_equalize_flow_width_factor":
|
||||
{
|
||||
"label": "Equalize Filament Flow",
|
||||
"description": "Print thinner than normal lines faster so that the amount of material extruded per second remains the same. Thin pieces in your model might require lines printed with smaller line width than provided in the settings. This setting controls the speed changes for such lines.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
"speed_equalize_flow_max":
|
||||
{
|
||||
"label": "Maximum Speed for Flow Equalization",
|
||||
"description": "Maximum print speed when adjusting the print speed in order to equalize flow.",
|
||||
"label": "Flow Equalization Ratio",
|
||||
"description": "Extrusion width based correction factor on the speed. At 0% the movement speed is kept constant at the Print Speed. At 100% the movement speed is adjusted so that the flow (in mm³/s) is kept constant, i.e. lines half the normal Line Width are printed twice as fast and lines twice as wide are printed half as fast. A value larger than 100% can help to compensate for the higher pressure required to extrude wide lines.",
|
||||
"type": "float",
|
||||
"unit": "mm/s",
|
||||
"enabled": "speed_equalize_flow_enabled",
|
||||
"default_value": 150,
|
||||
"minimum_value": "0.1",
|
||||
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
|
||||
"maximum_value_warning": "150",
|
||||
"unit": "%",
|
||||
"default_value": 100.0,
|
||||
"minimum_value": "0.0",
|
||||
"maximum_value_warning": "200.0",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
},
|
||||
|
@ -4446,6 +4530,7 @@
|
|||
"minimum_value": "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": "999999",
|
||||
"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)",
|
||||
"enabled": "support_enable or support_meshes_present",
|
||||
|
@ -4556,6 +4641,7 @@
|
|||
"default_value": 8.0,
|
||||
"minimum_value": "0.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",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
|
@ -4570,6 +4656,7 @@
|
|||
"default_value": 20,
|
||||
"minimum_value": "0",
|
||||
"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))",
|
||||
"enabled": "(support_enable or support_meshes_present) and support_brim_enable",
|
||||
"settable_per_mesh": false,
|
||||
|
@ -4602,7 +4689,7 @@
|
|||
"default_value": 0.1,
|
||||
"type": "float",
|
||||
"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",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -5333,6 +5420,7 @@
|
|||
"default_value": 1,
|
||||
"minimum_value": "0",
|
||||
"maximum_value_warning": "10",
|
||||
"maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'skirt'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true,
|
||||
|
@ -5458,7 +5546,7 @@
|
|||
"default_value": 5,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "raft_interface_line_width",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft' and not raft_remove_inside_corners",
|
||||
"limit_to_extruder": "adhesion_extruder_nr",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": true
|
||||
|
@ -6244,6 +6332,18 @@
|
|||
"minimum_value_warning": "0.01",
|
||||
"maximum_value_warning": "0.3",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"meshfix_maximum_extrusion_area_deviation":
|
||||
{
|
||||
"label": "Maximum Extrusion Area Deviation",
|
||||
"description": "The maximum extrusion area deviation allowed when removing intermediate points from a straight line. An intermediate point may serve as width-changing point in a long straight line. Therefore, if it is removed, it will cause the line to have a uniform width and, as a result, lose (or gain) a bit of extrusion area. If you increase this you may notice slight under- (or over-) extrusion in between straight parallel walls, as more intermediate width-changing points will be allowed to be removed. Your print will be less accurate, but the g-code will be smaller.",
|
||||
"type": "float",
|
||||
"unit": "μm²",
|
||||
"default_value": 2000,
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "500",
|
||||
"maximum_value_warning": "50000",
|
||||
"settable_per_mesh": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6793,6 +6893,7 @@
|
|||
"type": "bool",
|
||||
"default_value": false,
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"enabled": false,
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
"magic_fuzzy_skin_outside_only":
|
||||
|
@ -6801,7 +6902,7 @@
|
|||
"description": "Jitter only the parts' outlines and not the parts' holes.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"enabled": "magic_fuzzy_skin_enabled",
|
||||
"enabled": "magic_fuzzy_skin_enabled and False" ,
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -6814,7 +6915,7 @@
|
|||
"default_value": 0.3,
|
||||
"minimum_value": "0.001",
|
||||
"maximum_value_warning": "wall_line_width_0",
|
||||
"enabled": "magic_fuzzy_skin_enabled",
|
||||
"enabled": "magic_fuzzy_skin_enabled and False",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -6829,7 +6930,7 @@
|
|||
"minimum_value_warning": "0.1",
|
||||
"maximum_value_warning": "10",
|
||||
"maximum_value": "2 / magic_fuzzy_skin_thickness",
|
||||
"enabled": "magic_fuzzy_skin_enabled",
|
||||
"enabled": "magic_fuzzy_skin_enabled and False",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"settable_per_mesh": true,
|
||||
"children":
|
||||
|
@ -6845,7 +6946,7 @@
|
|||
"minimum_value_warning": "0.1",
|
||||
"maximum_value_warning": "10",
|
||||
"value": "10000 if magic_fuzzy_skin_point_density == 0 else 1 / magic_fuzzy_skin_point_density",
|
||||
"enabled": "magic_fuzzy_skin_enabled",
|
||||
"enabled": "magic_fuzzy_skin_enabled and False",
|
||||
"limit_to_extruder": "wall_0_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
}
|
||||
|
@ -7424,6 +7525,7 @@
|
|||
"minimum_value": "5",
|
||||
"maximum_value": "100",
|
||||
"minimum_value_warning": "20",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "bridge_settings_enabled",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -7469,8 +7571,7 @@
|
|||
"unit": "%",
|
||||
"default_value": 100,
|
||||
"type": "float",
|
||||
"minimum_value": "5",
|
||||
"maximum_value": "500",
|
||||
"minimum_value": "0.0001",
|
||||
"minimum_value_warning": "50",
|
||||
"maximum_value_warning": "150",
|
||||
"enabled": "bridge_settings_enabled and bridge_enable_more_layers",
|
||||
|
@ -7483,9 +7584,9 @@
|
|||
"unit": "%",
|
||||
"default_value": 75,
|
||||
"type": "float",
|
||||
"minimum_value": "5",
|
||||
"maximum_value": "100",
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "20",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "bridge_settings_enabled and bridge_enable_more_layers",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -7522,8 +7623,7 @@
|
|||
"unit": "%",
|
||||
"default_value": 110,
|
||||
"type": "float",
|
||||
"minimum_value": "5",
|
||||
"maximum_value": "500",
|
||||
"minimum_value": "0.001",
|
||||
"minimum_value_warning": "50",
|
||||
"maximum_value_warning": "150",
|
||||
"enabled": "bridge_settings_enabled and bridge_enable_more_layers",
|
||||
|
@ -7536,9 +7636,9 @@
|
|||
"unit": "%",
|
||||
"default_value": 80,
|
||||
"type": "float",
|
||||
"minimum_value": "5",
|
||||
"maximum_value": "100",
|
||||
"minimum_value": "0",
|
||||
"minimum_value_warning": "20",
|
||||
"maximum_value_warning": "100",
|
||||
"enabled": "bridge_settings_enabled and bridge_enable_more_layers",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
@ -7806,6 +7906,36 @@
|
|||
"minimum_value_warning": "25",
|
||||
"maximum_value_warning": "100",
|
||||
"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":
|
||||
{
|
||||
"label": "Remove Raft Inside Corners",
|
||||
"description": "Remove inside corners from the raft, causing the raft to become convex.",
|
||||
"type": "bool",
|
||||
"default_value": false,
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
},
|
||||
"raft_base_wall_count":
|
||||
{
|
||||
"label": "Raft Base Wall Count",
|
||||
"description": "The number of contours to print around the linear pattern in the base layer of the raft.",
|
||||
"type": "int",
|
||||
"default_value": 1,
|
||||
"enabled": "resolveOrValue('adhesion_type') == 'raft'",
|
||||
"settable_per_mesh": false,
|
||||
"settable_per_extruder": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -175,8 +175,6 @@
|
|||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
"top_bottom_thickness": { "value": "layer_height_0 + layer_height * 3 if layer_height > 0.15 else 0.8" },
|
||||
"optimize_wall_printing_order": { "value": true },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": false },
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"z_seam_type": { "value": "'sharpest_corner'" },
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
"speed_topbottom": {"value": 40 },
|
||||
"speed_wall": { "value": 35 },
|
||||
"speed_wall_x": { "value": 40 },
|
||||
"speed_equalize_flow_max": { "value": 70 },
|
||||
|
||||
"retraction_enable": {"default_value":true},
|
||||
"retraction_amount": { "default_value": 4 },
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
"speed_topbottom": {"value": 40 },
|
||||
"speed_wall": { "value": 35 },
|
||||
"speed_wall_x": { "value": 40 },
|
||||
"speed_equalize_flow_max": { "value": 70 },
|
||||
|
||||
"retraction_enable": {"default_value":true},
|
||||
"retraction_amount": { "default_value": 4 },
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_weighted'" },
|
||||
|
@ -97,7 +96,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -37,9 +37,15 @@
|
|||
},
|
||||
"machine_extruder_count": {
|
||||
"default_value": 2
|
||||
},
|
||||
"machine_extruders_share_heater": {
|
||||
"default_value": true
|
||||
},
|
||||
"machine_extruders_share_nozzle": {
|
||||
"default_value": true
|
||||
},
|
||||
"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": {
|
||||
"default_value": "M104 T0 S0\nM104 T1 S0\nM140 S0\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"
|
||||
|
|
|
@ -37,9 +37,15 @@
|
|||
},
|
||||
"machine_extruder_count": {
|
||||
"default_value": 2
|
||||
},
|
||||
"machine_extruders_share_heater": {
|
||||
"default_value": true
|
||||
},
|
||||
"machine_extruders_share_nozzle": {
|
||||
"default_value": true
|
||||
},
|
||||
"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": {
|
||||
"default_value": "M104 T0 S0\nM104 T1 S0\nM140 S0\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84"
|
||||
|
|
|
@ -38,6 +38,12 @@
|
|||
"machine_extruder_count": {
|
||||
"default_value": 2
|
||||
},
|
||||
"machine_extruders_share_heater": {
|
||||
"default_value": true
|
||||
},
|
||||
"machine_extruders_share_nozzle": {
|
||||
"default_value": true
|
||||
},
|
||||
"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"
|
||||
},
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
},
|
||||
"machine_extruder_count": {
|
||||
"default_value": 2
|
||||
},
|
||||
"machine_extruders_share_heater": {
|
||||
"default_value": true
|
||||
},
|
||||
"machine_extruders_share_nozzle": {
|
||||
"default_value": true
|
||||
},
|
||||
"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"
|
||||
|
|
41
resources/definitions/hellbot_magna_SE.def.json
Normal file
41
resources/definitions/hellbot_magna_SE.def.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -89,9 +89,8 @@
|
|||
"top_layers": {"value": "4 if infill_sparse_density < 95 else 1" },
|
||||
"bottom_layers": {"value": "(top_layers)" },
|
||||
"wall_0_inset": {"value": "0" },
|
||||
"outer_inset_first": {"value": true },
|
||||
"inset_direction": {"value": "'outside_in'" },
|
||||
"alternate_extra_perimeter": {"value": false },
|
||||
"travel_compensate_overlapping_walls_enabled": {"value": false },
|
||||
"filter_out_tiny_gaps": {"value": true },
|
||||
"fill_outline_gaps": {"value": true },
|
||||
"z_seam_type": {"value": "'shortest'"},
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Ultimaker",
|
||||
"manufacturer": "Fracktal",
|
||||
"file_formats": "text/x-gcode",
|
||||
"platform_offset": [ 0, 0, 0],
|
||||
|
|
|
@ -194,7 +194,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": false },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_none'" },
|
||||
|
@ -207,7 +206,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -112,7 +112,6 @@
|
|||
"minimum_support_area": { "value": 2 },
|
||||
"minimum_interface_area": { "value": 10 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -129,7 +129,6 @@
|
|||
"minimum_support_area": { "value": 2 },
|
||||
"minimum_interface_area": { "value": 10 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -130,7 +130,6 @@
|
|||
"minimum_support_area": { "value": 2 },
|
||||
"minimum_interface_area": { "value": 10 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -144,7 +144,6 @@
|
|||
"retraction_prime_speed": { "value": "35" },
|
||||
|
||||
"skin_overlap": { "value": "10" },
|
||||
"speed_equalize_flow_enabled": { "value": "True" },
|
||||
"speed_layer_0": { "value": "20" },
|
||||
"speed_prime_tower": { "value": "speed_topbottom" },
|
||||
"speed_print": { "value": "35" },
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_weighted'" },
|
||||
|
@ -97,7 +96,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -49,13 +49,8 @@
|
|||
"top_bottom_pattern_0": {"value": "'lines'" },
|
||||
"wall_0_inset": {"value": 0},
|
||||
"optimize_wall_printing_order": {"value": false },
|
||||
"outer_inset_first": {"value": false },
|
||||
"inset_direction": {"value": "'inside_out'" },
|
||||
"alternate_extra_perimeter": {"value": false },
|
||||
"travel_compensate_overlapping_walls_enabled": {"value": true },
|
||||
"travel_compensate_overlapping_walls_0_enabled": {"value": true },
|
||||
"travel_compensate_overlapping_walls_x_enabled": {"value": true },
|
||||
"wall_min_flow": {"value": 0},
|
||||
"fill_perimeter_gaps": {"value": "'everywhere'" },
|
||||
"filter_out_tiny_gaps": {"value": true },
|
||||
"fill_outline_gaps": {"value": true },
|
||||
"xy_offset": {"value": 0},
|
||||
|
@ -97,7 +92,6 @@
|
|||
"speed_layer_0": {"value": 10},
|
||||
"speed_travel_layer_0": {"value": 50},
|
||||
"speed_slowdown_layers": {"value": 2},
|
||||
"speed_equalize_flow_enabled": {"value": false },
|
||||
"acceleration_enabled": {"value": false },
|
||||
"acceleration_roofing": {"value": 3000 },
|
||||
"jerk_enabled": {"value": false },
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
"default_value": 0.2
|
||||
},
|
||||
"support_pattern": {
|
||||
"default_value": "ZigZag"
|
||||
"default_value": "zigzag"
|
||||
},
|
||||
"support_infill_rate": {
|
||||
"value": "15 if support_enable and support_structure == 'normal' else 0 if support_enable and support_structure == 'tree' else 15"
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Ultimaker",
|
||||
"manufacturer": "MakerBot",
|
||||
"machine_x3g_variant": "r1",
|
||||
"file_formats": "application/x3g",
|
||||
|
|
|
@ -179,7 +179,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": false },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_none'" },
|
||||
|
@ -192,7 +191,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
372
resources/definitions/mixware_hyper_s.def.json
Normal file
372
resources/definitions/mixware_hyper_s.def.json
Normal file
|
@ -0,0 +1,372 @@
|
|||
{
|
||||
"name": "Hyper S",
|
||||
"version": 2,
|
||||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Mixware",
|
||||
"manufacturer": "Mixware",
|
||||
"file_formats": "text/x-gcode",
|
||||
"platform": "mixware_hyper_s_platform.stl",
|
||||
"has_materials": true,
|
||||
"has_machine_quality": true,
|
||||
"preferred_material": "generic_pla",
|
||||
"preferred_quality": "coarse",
|
||||
"machine_extruder_trains": {
|
||||
"0": "mixware_hyper_s_extruder_0"
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"machine_name": {
|
||||
"default_value": "Hyper S"
|
||||
},
|
||||
"machine_start_gcode": {
|
||||
"default_value": "M140 S{material_bed_temperature} ; Heat bed\nM109 S{material_print_temperature} ; Heat nozzle\nM190 S{material_bed_temperature} ; Wait for bed heating\nG28 ; home all axes\nM117 Purge extruder\nG92 E0 ; reset extruder\nG1 Z5.0 F1000 ; move z up little to prevent scratching of surface\nG1 X0.1 Y20 Z0.3 F5000.0 ; move to start-line position\nG1 X0.1 Y100.0 Z0.3 F1500.0 E15 ; draw 1st line\nG1 X0.4 Y100.0 Z0.3 F5000.0 ; move to side a little\nG1 X0.4 Y20 Z0.3 F1500.0 E30 ; draw 2nd line\nG92 E0 ; reset extruder\nG1 Z5.0 F1000 ; move z up little to prevent scratching of surface"
|
||||
},
|
||||
"machine_end_gcode": {
|
||||
"default_value": "G91; relative positioning\nG1 Z1.0 F3000 ; move z up little to prevent scratching of print\nG90; absolute positioning\nG1 X0 Y200 F1000 ; prepare for part removal\nM104 S0; turn off extruder\nM140 S0 ; turn off bed\nG1 X0 Y220 F1000 ; prepare for part removal\nM84 ; disable motors\nM106 S0 ; turn off fan"
|
||||
},
|
||||
"machine_width": {
|
||||
"default_value": 300
|
||||
},
|
||||
"machine_depth": {
|
||||
"default_value": 300
|
||||
},
|
||||
"machine_height": {
|
||||
"default_value": 400
|
||||
},
|
||||
"raft_margin": {
|
||||
"default_value": 3,
|
||||
"minimum_value_warning": "0.01"
|
||||
},
|
||||
"raft_airgap": {
|
||||
"default_value": 0.24
|
||||
},
|
||||
"brim_width": {
|
||||
"default_value": 3
|
||||
},
|
||||
"machine_heated_bed": {
|
||||
"default_value": true
|
||||
},
|
||||
"material_diameter": {
|
||||
"default_value": 1.75
|
||||
},
|
||||
"top_bottom_pattern": {
|
||||
"default_value": "zigzag"
|
||||
},
|
||||
"ironing_line_spacing": {
|
||||
"default_value": 0.4
|
||||
},
|
||||
"ironing_pattern": {
|
||||
"default_value": "concentric"
|
||||
},
|
||||
"skin_no_small_gaps_heuristic": {
|
||||
"default_value": false
|
||||
},
|
||||
"retraction_hop_enabled": {
|
||||
"default_value": false
|
||||
},
|
||||
"support_enable": {
|
||||
"default_value": true
|
||||
},
|
||||
"support_type": {
|
||||
"default_value": "buildplate"
|
||||
},
|
||||
"support_angle": {
|
||||
"default_value": 60
|
||||
},
|
||||
"support_pattern": {
|
||||
"default_value": "zigzag"
|
||||
},
|
||||
"support_infill_rate": {
|
||||
"value": 15
|
||||
},
|
||||
"gantry_height": {
|
||||
"value": 25
|
||||
},
|
||||
"machine_max_feedrate_x": {
|
||||
"default_value": 500
|
||||
},
|
||||
"machine_max_feedrate_y": {
|
||||
"default_value": 500
|
||||
},
|
||||
"machine_max_feedrate_z": {
|
||||
"default_value": 10
|
||||
},
|
||||
"machine_max_feedrate_e": {
|
||||
"default_value": 50
|
||||
},
|
||||
"machine_max_acceleration_x": {
|
||||
"default_value": 500
|
||||
},
|
||||
"machine_max_acceleration_y": {
|
||||
"default_value": 500
|
||||
},
|
||||
"machine_max_acceleration_z": {
|
||||
"default_value": 100
|
||||
},
|
||||
"machine_max_acceleration_e": {
|
||||
"default_value": 500
|
||||
},
|
||||
"machine_acceleration": {
|
||||
"default_value": 500
|
||||
},
|
||||
"machine_max_jerk_xy": {
|
||||
"default_value": 10
|
||||
},
|
||||
"machine_max_jerk_z": {
|
||||
"default_value": 0.4
|
||||
},
|
||||
"machine_max_jerk_e": {
|
||||
"default_value": 5
|
||||
},
|
||||
"acceleration_print": {
|
||||
"default_value": 1000
|
||||
},
|
||||
"jerk_print": {
|
||||
"default_value": 10
|
||||
},
|
||||
"acceleration_enabled": {
|
||||
"default_value": false
|
||||
},
|
||||
"jerk_enabled": {
|
||||
"default_value": false
|
||||
},
|
||||
"speed_print": {
|
||||
"default_value": 40.0
|
||||
},
|
||||
"optimize_wall_printing_order": {
|
||||
"default_value": "True"
|
||||
},
|
||||
"z_seam_type": {
|
||||
"default_value": "shortest"
|
||||
},
|
||||
"infill_before_walls": {
|
||||
"default_value": false
|
||||
},
|
||||
"infill_sparse_density": {
|
||||
"default_value": 15
|
||||
},
|
||||
"fill_outline_gaps": {
|
||||
"default_value": false
|
||||
},
|
||||
"filter_out_tiny_gaps": {
|
||||
"default_value": false
|
||||
},
|
||||
"retraction_hop": {
|
||||
"default_value": 0.2
|
||||
},
|
||||
"travel_avoid_other_parts": {
|
||||
"default_value": false
|
||||
},
|
||||
"travel_retract_before_outer_wall": {
|
||||
"default_value": true
|
||||
},
|
||||
"retraction_amount": {
|
||||
"default_value": 2
|
||||
},
|
||||
"retraction_enable": {
|
||||
"default_value": true
|
||||
},
|
||||
"retraction_count_max": {
|
||||
"default_value": 100
|
||||
},
|
||||
"cool_fan_enabled": {
|
||||
"default_value": true
|
||||
},
|
||||
"cool_min_layer_time": {
|
||||
"default_value": 10
|
||||
},
|
||||
"skirt_gap": {
|
||||
"default_value": 8.0
|
||||
},
|
||||
"skirt_line_count": {
|
||||
"default_value": 3
|
||||
},
|
||||
"adaptive_layer_height_variation": {
|
||||
"default_value": 0.04
|
||||
},
|
||||
"adaptive_layer_height_variation_step": {
|
||||
"default_value": 0.04
|
||||
},
|
||||
"support_use_towers": {
|
||||
"default_value": false
|
||||
},
|
||||
"support_interface_enable": {
|
||||
"default_value": true
|
||||
},
|
||||
"support_interface_density": {
|
||||
"default_value": 33.333
|
||||
},
|
||||
"support_interface_pattern": {
|
||||
"default_value": "grid"
|
||||
},
|
||||
"support_interface_skip_height": {
|
||||
"default_value": 0.24
|
||||
},
|
||||
"top_bottom_thickness": {
|
||||
"default_value": 0.8
|
||||
},
|
||||
"material_flow": {
|
||||
"default_value": 100
|
||||
},
|
||||
"material_print_temperature": {
|
||||
"maximum_value_warning": "330"
|
||||
},
|
||||
"acceleration_roofing": {
|
||||
"enabled": "acceleration_enabled and roofing_layer_count > 0 and top_layers > 0"
|
||||
},
|
||||
"retraction_speed": {
|
||||
"default_value": 40,
|
||||
"maximum_value_warning": "machine_max_feedrate_e if retraction_enable else float('inf')",
|
||||
"maximum_value": "200"
|
||||
},
|
||||
"retraction_retract_speed": {
|
||||
"maximum_value_warning": "machine_max_feedrate_e if retraction_enable else float('inf')",
|
||||
"maximum_value": "200"
|
||||
},
|
||||
"retraction_prime_speed": {
|
||||
"maximum_value_warning": "machine_max_feedrate_e if retraction_enable else float('inf')",
|
||||
"maximum_value": "200"
|
||||
},
|
||||
"speed_layer_0": {
|
||||
"value": "speed_print / 2"
|
||||
},
|
||||
"acceleration_travel_layer_0": {
|
||||
"value": "acceleration_travel"
|
||||
},
|
||||
"jerk_travel": {
|
||||
"value": "jerk_print"
|
||||
},
|
||||
"jerk_travel_layer_0": {
|
||||
"value": "jerk_travel"
|
||||
},
|
||||
"skirt_brim_speed": {
|
||||
"value": "speed_layer_0"
|
||||
},
|
||||
"speed_infill": {
|
||||
"value": "speed_print"
|
||||
},
|
||||
"speed_wall": {
|
||||
"value": "speed_print / 2"
|
||||
},
|
||||
"speed_wall_0": {
|
||||
"value": "speed_wall"
|
||||
},
|
||||
"speed_wall_x": {
|
||||
"value": "speed_wall"
|
||||
},
|
||||
"speed_topbottom": {
|
||||
"value": "speed_print / 2"
|
||||
},
|
||||
"speed_roofing": {
|
||||
"value": "speed_topbottom"
|
||||
},
|
||||
"speed_travel": {
|
||||
"value": "150.0 if speed_print < 60 else 250.0 if speed_print > 100 else speed_print * 2.5"
|
||||
},
|
||||
"speed_print_layer_0": {
|
||||
"value": "speed_layer_0"
|
||||
},
|
||||
"speed_travel_layer_0": {
|
||||
"value": "100 if speed_layer_0 < 20 else 150 if speed_layer_0 > 30 else speed_layer_0 * 5"
|
||||
},
|
||||
"speed_prime_tower": {
|
||||
"value": "speed_topbottom"
|
||||
},
|
||||
"speed_support": {
|
||||
"value": "speed_wall_0"
|
||||
},
|
||||
"speed_support_interface": {
|
||||
"value": "speed_topbottom"
|
||||
},
|
||||
"material_initial_print_temperature": {
|
||||
"value": "material_print_temperature"
|
||||
},
|
||||
"material_final_print_temperature": {
|
||||
"value": "material_print_temperature"
|
||||
},
|
||||
"cool_fan_full_at_height": {
|
||||
"value": "layer_height_0 + 2 * layer_height"
|
||||
},
|
||||
"adhesion_type": {
|
||||
"default_value": "skirt"
|
||||
},
|
||||
"meshfix_maximum_travel_resolution": {
|
||||
"value": "meshfix_maximum_resolution"
|
||||
},
|
||||
"support_xy_distance": {
|
||||
"value": "wall_line_width_0 * 2"
|
||||
},
|
||||
"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_xy_overrides_z": {
|
||||
"default_value": "xy_overrides_z"
|
||||
},
|
||||
"support_interface_height": {
|
||||
"value": "layer_height * 4"
|
||||
},
|
||||
"wall_thickness": {
|
||||
"value": "line_width * 2"
|
||||
},
|
||||
"acceleration_travel": {
|
||||
"value": 1000
|
||||
},
|
||||
"line_width": {
|
||||
"value": 0.4
|
||||
},
|
||||
"speed_z_hop": {
|
||||
"default_value": 5
|
||||
},
|
||||
"retraction_combing_max_distance": {
|
||||
"default_value": 30
|
||||
},
|
||||
"travel_avoid_supports": {
|
||||
"default_value": true
|
||||
},
|
||||
"brim_replaces_support": {
|
||||
"default_value": false
|
||||
},
|
||||
"support_brim_width": {
|
||||
"default_value": 4
|
||||
},
|
||||
"minimum_support_area": {
|
||||
"default_value": 2
|
||||
},
|
||||
"minimum_interface_area": {
|
||||
"default_value": 10
|
||||
},
|
||||
"support_wall_count": {
|
||||
"value": 1
|
||||
},
|
||||
"support_brim_enable": {
|
||||
"value": false
|
||||
},
|
||||
"retraction_combing": {
|
||||
"value": "all"
|
||||
},
|
||||
"retraction_extrusion_window": {
|
||||
"value": 10,
|
||||
"maximum_value_warning": "20"
|
||||
},
|
||||
"retraction_min_travel": {
|
||||
"value": 1.5
|
||||
},
|
||||
"infill_wipe_dist": {
|
||||
"value": 0.0
|
||||
},
|
||||
"skin_overlap": {
|
||||
"value": 10.0
|
||||
},
|
||||
"infill_overlap": {
|
||||
"value": 30.0
|
||||
},
|
||||
"wall_0_wipe_dist": {
|
||||
"value": 0.0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Ultimaker",
|
||||
"manufacturer": "ORD Solutions",
|
||||
"file_formats": "text/x-gcode",
|
||||
"machine_extruder_trains":
|
||||
|
|
|
@ -176,15 +176,6 @@
|
|||
"skin_outline_count": {
|
||||
"value": 0
|
||||
},
|
||||
"travel_compensate_overlapping_walls_enabled": {
|
||||
"value": "False"
|
||||
},
|
||||
"travel_compensate_overlapping_walls_0_enabled": {
|
||||
"value": "False"
|
||||
},
|
||||
"travel_compensate_overlapping_walls_x_enabled": {
|
||||
"value": "False"
|
||||
},
|
||||
"wall_0_wipe_dist": {
|
||||
"value": "machine_nozzle_size / 3"
|
||||
},
|
||||
|
@ -218,10 +209,6 @@
|
|||
"material_flow_layer_0": {
|
||||
"enabled": false
|
||||
},
|
||||
"speed_equalize_flow_enabled": {
|
||||
"enabled": false,
|
||||
"value": "False"
|
||||
},
|
||||
"draft_shield_enabled": {
|
||||
"enabled": false,
|
||||
"value": "False"
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Ultimaker",
|
||||
"manufacturer": "Punchtec",
|
||||
"file_formats": "text/x-gcode",
|
||||
"machine_extruder_trains":
|
||||
|
|
|
@ -88,9 +88,6 @@
|
|||
|
||||
"wall_0_wipe_dist": { "value": 0.05 },
|
||||
"optimize_wall_printing_order": { "value": "True" },
|
||||
"travel_compensate_overlapping_walls_enabled": { "value": "False" },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
"travel_compensate_overlapping_walls_x_enabled": { "value": "False" },
|
||||
|
||||
"infill_sparse_density": { "value": 16 },
|
||||
"infill_wipe_dist": { "value": 0 },
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Ultimaker",
|
||||
"manufacturer": "Robo 3D",
|
||||
"file_formats": "text/x-gcode",
|
||||
"platform_offset": [ 0, 0, 0],
|
||||
|
|
51
resources/definitions/sh65.def.json
Normal file
51
resources/definitions/sh65.def.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -110,9 +110,6 @@
|
|||
"switch_extruder_retraction_speed": {
|
||||
"value": "30"
|
||||
},
|
||||
"travel_compensate_overlapping_walls_enabled": {
|
||||
"default_value": false
|
||||
},
|
||||
"raft_base_acceleration": {
|
||||
"value": "400"
|
||||
},
|
||||
|
@ -389,9 +386,6 @@
|
|||
"acceleration_support_infill": {
|
||||
"value": "400"
|
||||
},
|
||||
"travel_compensate_overlapping_walls_0_enabled": {
|
||||
"value": "False"
|
||||
},
|
||||
"support_bottom_material_flow": {
|
||||
"value": "99"
|
||||
},
|
||||
|
@ -584,9 +578,6 @@
|
|||
"infill_material_flow": {
|
||||
"value": "99"
|
||||
},
|
||||
"speed_equalize_flow_max": {
|
||||
"default_value": 40
|
||||
},
|
||||
"skin_preshrink": {
|
||||
"value": "0.0"
|
||||
},
|
||||
|
@ -644,9 +635,6 @@
|
|||
"skirt_line_count": {
|
||||
"default_value": 2
|
||||
},
|
||||
"travel_compensate_overlapping_walls_x_enabled": {
|
||||
"value": "False"
|
||||
},
|
||||
"jerk_wall_0": {
|
||||
"value": "5"
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"default_value": true
|
||||
},
|
||||
"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": {
|
||||
"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"
|
||||
|
|
51
resources/definitions/stream30mk3.def.json
Normal file
51
resources/definitions/stream30mk3.def.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
51
resources/definitions/stream30ultrasc2.def.json
Normal file
51
resources/definitions/stream30ultrasc2.def.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,8 @@
|
|||
"file_formats": "text/x-gcode",
|
||||
"platform": "tinyboy_fabrikator15.stl",
|
||||
"platform_offset": [-95, -3, -46],
|
||||
"has_materials": false,
|
||||
"has_materials": true,
|
||||
"preferred_material": "generic_pla_175",
|
||||
"has_machine_quality": true,
|
||||
"preferred_quality_type": "normal",
|
||||
"machine_extruder_trains":
|
||||
|
@ -33,12 +34,10 @@
|
|||
"gantry_height": { "value": 45 },
|
||||
"machine_center_is_zero": { "default_value": false },
|
||||
"machine_start_gcode": {
|
||||
"default_value": ";Sliced at: {day} {date} {time}\n;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {infill_sparse_density}\n;Print time: {print_time}\n;Filament used: {filament_amount}m {filament_weight}g\n;Filament cost: {filament_cost}\n;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line\n;M109 S{print_temperature} ;Uncomment to add your own temperature line\nG21 ;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 X0.0 Y0.0 Z15.0 F{travel_speed} ;move the printhead up 15mm\nG92 E0 ;zero the extruded length\n;M109 S{print_temperature} ;set extruder temperature\nG1 F200 E30 ;extrude 30mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{travel_speed}\n;Put printing message on LCD screen\nM117 Printing..."
|
||||
|
||||
"default_value": ";Sliced at: {day} {date} {time}\n;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {infill_sparse_density}\n;Print time: {print_time}\n;Filament used: {filament_amount}m {filament_weight}g\n;Filament cost: {filament_cost}\nG21 ;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 X0.0 Y0.0 Z15.0 F6000 ;move the printhead up 15mm\nG92 E0 ;zero the extruded length\nM104 S{material_print_temperature} ;set extruder temperature\nM105\nM109 S{material_print_temperature} ;wait for extruder temperature\nG1 F200 E30 ;extrude 30mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F6000\n;Put printing message on LCD screen\nM117 Printing..."
|
||||
},
|
||||
"machine_end_gcode": {
|
||||
"default_value": ";End GCode\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\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{travel_speed} ;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\nM84 ;steppers off\nG90 ;absolute positioning\n;{jobname}"
|
||||
|
||||
"default_value": ";End GCode\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\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 F6000 ;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\nM84 ;steppers off\nG90 ;absolute positioning\n;{jobname}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
"material_initial_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_final_print_temperature": { "value": "material_print_temperature" },
|
||||
"material_flow": { "value": 100 },
|
||||
"travel_compensate_overlapping_walls_0_enabled": { "value": "False" },
|
||||
|
||||
"z_seam_type": { "value": "'back'" },
|
||||
"z_seam_corner": { "value": "'z_seam_corner_weighted'" },
|
||||
|
@ -96,7 +95,6 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
|
||||
|
||||
"speed_print": { "value": 50.0 } ,
|
||||
"speed_infill": { "value": "speed_print" },
|
||||
"speed_wall": { "value": "speed_print / 2" },
|
||||
|
@ -64,11 +63,9 @@
|
|||
"infill_wipe_dist": { "value": 0.0 },
|
||||
"wall_0_wipe_dist": { "value": 0.0 },
|
||||
|
||||
"fill_perimeter_gaps": { "value": "'everywhere'" },
|
||||
"fill_outline_gaps": { "value": false },
|
||||
"filter_out_tiny_gaps": { "value": false },
|
||||
|
||||
|
||||
"retraction_hop_enabled": { "value": "False" },
|
||||
"retraction_hop": { "value": 0.2 },
|
||||
"retraction_combing": { "value": "'off' if retraction_hop_enabled else 'noskin'" },
|
||||
|
@ -121,6 +118,5 @@
|
|||
"minimum_interface_area": { "value": 10 },
|
||||
"top_bottom_thickness": {"value": "layer_height_0 + layer_height * 3" },
|
||||
"wall_thickness": {"value": "line_width * 2" }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue