diff --git a/CMakeLists.txt b/CMakeLists.txt index 3993d76754..9bdd48c317 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ set(CURA_CLOUD_ACCOUNT_API_ROOT "" CACHE STRING "Alternative Cura cloud account set(CURA_MARKETPLACE_ROOT "" CACHE STRING "Alternative Marketplace location") set(CURA_DIGITAL_FACTORY_URL "" CACHE STRING "Alternative Digital Factory location") -configure_file(${CMAKE_SOURCE_DIR}/cura.desktop.in ${CMAKE_BINARY_DIR}/cura.desktop @ONLY) +configure_file(${CMAKE_SOURCE_DIR}/com.ultimaker.cura.desktop.in ${CMAKE_BINARY_DIR}/com.ultimaker.cura.desktop @ONLY) configure_file(cura/CuraVersion.py.in CuraVersion.py @ONLY) @@ -82,11 +82,11 @@ if(NOT APPLE AND NOT WIN32) install(FILES ${CMAKE_BINARY_DIR}/CuraVersion.py DESTINATION lib${LIB_SUFFIX}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages/cura) endif() - install(FILES ${CMAKE_BINARY_DIR}/cura.desktop + install(FILES ${CMAKE_BINARY_DIR}/com.ultimaker.cura.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) install(FILES ${CMAKE_SOURCE_DIR}/resources/images/cura-icon.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/128x128/apps/) - install(FILES cura.appdata.xml + install(FILES com.ultimaker.cura.appdata.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo) install(FILES cura.sharedmimeinfo DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages/ diff --git a/cura.appdata.xml b/com.ultimaker.cura.appdata.xml similarity index 88% rename from cura.appdata.xml rename to com.ultimaker.cura.appdata.xml index 6274532ac9..781631e84a 100644 --- a/cura.appdata.xml +++ b/com.ultimaker.cura.appdata.xml @@ -1,7 +1,7 @@ - cura.desktop + com.ultimaker.cura.desktop CC0-1.0 LGPL-3.0 and CC-BY-SA-4.0 Cura @@ -24,7 +24,9 @@ - http://software.ultimaker.com/Cura.png + + https://raw.githubusercontent.com/Ultimaker/Cura/master/screenshot.png + https://ultimaker.com/en/products/cura-software?utm_source=cura&utm_medium=software&utm_campaign=resources Cura diff --git a/cura.desktop.in b/com.ultimaker.cura.desktop.in similarity index 100% rename from cura.desktop.in rename to com.ultimaker.cura.desktop.in diff --git a/cura/API/Account.py b/cura/API/Account.py index 15bccb71e1..d5ef2bfcb9 100644 --- a/cura/API/Account.py +++ b/cura/API/Account.py @@ -81,7 +81,8 @@ class Account(QObject): CLIENT_ID="um----------------------------ultimaker_cura", CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download " "packages.rating.read packages.rating.write connect.cluster.read connect.cluster.write " - "cura.printjob.read cura.printjob.write cura.mesh.read cura.mesh.write", + "library.project.read library.project.write cura.printjob.read cura.printjob.write " + "cura.mesh.read cura.mesh.write", AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data", AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root), AUTH_FAILED_REDIRECT="{}/app/auth-error".format(self._oauth_root) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index f0c69d5a61..9493153bf7 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1,8 +1,9 @@ -# Copyright (c) 2020 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import os import sys +import tempfile import time from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any, Dict @@ -30,6 +31,7 @@ from UM.Operations.SetTransformOperation import SetTransformOperation from UM.Platform import Platform from UM.PluginError import PluginNotFoundError from UM.Preferences import Preferences +from UM.Qt.Bindings.FileProviderModel import FileProviderModel from UM.Qt.QtApplication import QtApplication # The class we're inheriting from. from UM.Resources import Resources from UM.Scene.Camera import Camera @@ -822,6 +824,9 @@ class CuraApplication(QtApplication): self._add_printer_pages_model_without_cancel.initialize(cancellable = False) self._whats_new_pages_model.initialize() + # Initialize the FileProviderModel + self._file_provider_model.initialize(self._onFileProviderEnabledChanged) + # Detect in which mode to run and execute that mode if self._is_headless: self.runWithoutGUI() @@ -1051,6 +1056,13 @@ class CuraApplication(QtApplication): self._simple_mode_settings_manager = SimpleModeSettingsManager() return self._simple_mode_settings_manager + @pyqtSlot(result = QObject) + def getFileProviderModel(self) -> FileProviderModel: + return self._file_provider_model + + def _onFileProviderEnabledChanged(self): + self._file_provider_model.update() + def event(self, event): """Handle Qt events""" @@ -1466,7 +1478,8 @@ class CuraApplication(QtApplication): for file_name, nodes in objects_in_filename.items(): for node in nodes: - job = ReadMeshJob(file_name) + file_path = os.path.normpath(os.path.dirname(file_name)) + job = ReadMeshJob(file_name, add_to_recent_files = file_path != tempfile.gettempdir()) # Don't add temp files to the recent files list job._node = node # type: ignore job.finished.connect(self._reloadMeshFinished) if has_merged_nodes: @@ -1722,9 +1735,10 @@ class CuraApplication(QtApplication): openProjectFile = pyqtSignal(QUrl, arguments = ["project_file"]) # Emitted when a project file is about to open. + @pyqtSlot(QUrl, str, bool) @pyqtSlot(QUrl, str) @pyqtSlot(QUrl) - def readLocalFile(self, file: QUrl, project_mode: Optional[str] = None): + def readLocalFile(self, file: QUrl, project_mode: Optional[str] = None, add_to_recent_files: bool = True): """Open a local file :param project_mode: How to handle project files. Either None(default): Follow user preference, "open_as_model" @@ -1749,7 +1763,7 @@ class CuraApplication(QtApplication): if is_project_file and project_mode == "open_as_project": # open as project immediately without presenting a dialog workspace_handler = self.getWorkspaceFileHandler() - workspace_handler.readLocalFile(file) + workspace_handler.readLocalFile(file, add_to_recent_files_hint = add_to_recent_files) return if is_project_file and project_mode == "always_ask": @@ -1790,7 +1804,7 @@ class CuraApplication(QtApplication): if extension in self._non_sliceable_extensions: self.deleteAll(only_selectable = False) - job = ReadMeshJob(f) + job = ReadMeshJob(f, add_to_recent_files = add_to_recent_files) job.finished.connect(self._readMeshFinished) job.start() @@ -1905,6 +1919,11 @@ class CuraApplication(QtApplication): arrange(nodes_to_arrange, self.getBuildVolume(), fixed_nodes) except: Logger.logException("e", "Failed to arrange the models") + + # Ensure that we don't have any weird floaty objects (CURA-7855) + for node in nodes_to_arrange: + node.translate(Vector(0, -node.getBoundingBox().bottom, 0), SceneNode.TransformSpace.World) + self.fileCompleted.emit(file_name) def addNonSliceableExtension(self, extension): diff --git a/cura/Machines/MaterialNode.py b/cura/Machines/MaterialNode.py index c78c6aff03..18db7d982d 100644 --- a/cura/Machines/MaterialNode.py +++ b/cura/Machines/MaterialNode.py @@ -88,8 +88,10 @@ class MaterialNode(ContainerNode): variant = self.variant.variant_name) else: qualities_any_material = container_registry.findInstanceContainersMetadata(type = "quality", definition = self.variant.machine.quality_definition) - for material_metadata in container_registry.findInstanceContainersMetadata(type = "material", material = my_material_type): - qualities.extend((quality for quality in qualities_any_material if quality.get("material") == material_metadata["base_file"])) + + all_material_base_files = {material_metadata["base_file"] for material_metadata in container_registry.findInstanceContainersMetadata(type = "material", material = my_material_type)} + + qualities.extend((quality for quality in qualities_any_material if quality.get("material") in all_material_base_files)) if not qualities: # No quality profiles found. Go by GUID then. my_guid = self.guid diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py index f7fe6958a1..d79f24df15 100644 --- a/cura/OAuth2/AuthorizationHelpers.py +++ b/cura/OAuth2/AuthorizationHelpers.py @@ -58,7 +58,7 @@ class AuthorizationHelpers: :return: An AuthenticationResponse object. """ - Logger.log("d", "Refreshing the access token.") + 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 "", "redirect_uri": self._settings.CALLBACK_URL if self._settings.CALLBACK_URL is not None else "", @@ -69,7 +69,9 @@ class AuthorizationHelpers: 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") + 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))) @staticmethod def parseTokenResponse(token_response: requests.models.Response) -> "AuthenticationResponse": @@ -108,7 +110,9 @@ class AuthorizationHelpers: """ try: - token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = { + 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: diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index 9a5c81ae55..986f8d9a56 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import json @@ -241,13 +241,13 @@ class AuthorizationService: 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")) self._unable_to_get_data_message.show() - except ValueError: + except (ValueError, TypeError): Logger.logException("w", "Could not load auth data from preferences") def _storeAuthData(self, auth_data: Optional[AuthenticationResponse] = None) -> None: """Store authentication data in preferences.""" - Logger.log("d", "Attempting to store the auth data") + Logger.log("d", "Attempting to store the auth data for [%s]", self._settings.OAUTH_SERVER_URL) if self._preferences is None: Logger.log("e", "Unable to save authentication data, since no preference has been set!") return diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 08fdf707cf..48d4cb3cbc 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -221,6 +221,7 @@ class ContainerManager(QObject): except OSError: return {"status": "error", "message": "Unable to write to this location.", "path": file_url} + Logger.info("Successfully exported container to {path}".format(path = file_url)) return {"status": "success", "message": "Successfully exported container", "path": file_url} @pyqtSlot(QUrl, result = "QVariantMap") diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 24b7436bad..00a0eedbf0 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -400,7 +400,9 @@ class CuraContainerRegistry(ContainerRegistry): try: if int(metadata["setting_version"]) != cura.CuraApplication.CuraApplication.SettingVersion: return False - except ValueError: #Not parsable as int. + except ValueError: # Not parsable as int. + return False + except TypeError: # Expecting string input here, not e.g. list or anything. return False return True diff --git a/cura/Settings/MachineNameValidator.py b/cura/Settings/MachineNameValidator.py index c3ca4ed369..99a5c7da0a 100644 --- a/cura/Settings/MachineNameValidator.py +++ b/cura/Settings/MachineNameValidator.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import pyqtSlot, pyqtProperty, QObject, pyqtSignal, QRegExp @@ -23,7 +23,7 @@ class MachineNameValidator(QObject): #Compute the validation regex for printer names. This is limited by the maximum file name length. try: filename_max_length = os.statvfs(Resources.getDataStoragePath()).f_namemax - except AttributeError: #Doesn't support statvfs. Probably because it's not a Unix system. + except (AttributeError, EnvironmentError): # Doesn't support statvfs. Probably because it's not a Unix system. Or perhaps there is no permission or it doesn't exist. filename_max_length = 255 #Assume it's Windows on NTFS. machine_name_max_length = filename_max_length - len("_current_settings.") - len(ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix) # Characters that urllib.parse.quote_plus escapes count for 12! So now diff --git a/cura/Snapshot.py b/cura/Snapshot.py index 6f12aa88ba..bc7da4080a 100644 --- a/cura/Snapshot.py +++ b/cura/Snapshot.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import numpy @@ -42,8 +42,8 @@ class Snapshot: """ scene = Application.getInstance().getController().getScene() - active_camera = scene.getActiveCamera() - render_width, render_height = active_camera.getWindowSize() + active_camera = scene.getActiveCamera() or scene.findCamera("3d") + 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) preview_pass = PreviewPass(render_width, render_height) diff --git a/docs/How_to_use_the_flame_graph_profiler.md b/docs/How_to_use_the_flame_graph_profiler.md index b1cdaf358e..b40a86bb24 100644 --- a/docs/How_to_use_the_flame_graph_profiler.md +++ b/docs/How_to_use_the_flame_graph_profiler.md @@ -27,7 +27,7 @@ Note: The profiler front-end itself is quite "heavy" (ok, not optimised). It run What the Profiler Sees ---------------------- -The profiler doesn't capture every function call in Cura. It hooks into a number of important systems which give a good picture of activity without too much run time overhead. The most important system is Uranium's signal mechanism and PyQt5 slots. Functions which are called via the signal mechanism are recorded and thier names appear in the results. PyQt5 slots appear in the results with the prefix `[SLOT]`. +The profiler doesn't capture every function call in Cura. It hooks into a number of important systems which give a good picture of activity without too much run time overhead. The most important system is Uranium's signal mechanism and PyQt5 slots. Functions which are called via the signal mechanism are recorded and their names appear in the results. PyQt5 slots appear in the results with the prefix `[SLOT]`. Note that not all slots are captured. Only those slots which belong to classes which use the `pyqtSlot` decorator from the `UM.FlameProfiler` module. diff --git a/docs/scene/images/components_interacting_with_scene.jpg b/docs/scene/images/components_interacting_with_scene.jpg new file mode 100644 index 0000000000..34e34e25af Binary files /dev/null and b/docs/scene/images/components_interacting_with_scene.jpg differ diff --git a/docs/scene/images/components_interacting_with_scene.png b/docs/scene/images/components_interacting_with_scene.png new file mode 100644 index 0000000000..a01a138811 Binary files /dev/null and b/docs/scene/images/components_interacting_with_scene.png differ diff --git a/docs/scene/images/layer_data_scene_node.jpg b/docs/scene/images/layer_data_scene_node.jpg new file mode 100644 index 0000000000..313b409ddf Binary files /dev/null and b/docs/scene/images/layer_data_scene_node.jpg differ diff --git a/docs/scene/images/mirror_tool.jpg b/docs/scene/images/mirror_tool.jpg new file mode 100644 index 0000000000..e3d485008e Binary files /dev/null and b/docs/scene/images/mirror_tool.jpg differ diff --git a/docs/scene/images/per_objectsettings_tool.jpg b/docs/scene/images/per_objectsettings_tool.jpg new file mode 100644 index 0000000000..0634177d4b Binary files /dev/null and b/docs/scene/images/per_objectsettings_tool.jpg differ diff --git a/docs/scene/images/rotate_tool.jpg b/docs/scene/images/rotate_tool.jpg new file mode 100644 index 0000000000..4e10569678 Binary files /dev/null and b/docs/scene/images/rotate_tool.jpg differ diff --git a/docs/scene/images/scale_tool.jpg b/docs/scene/images/scale_tool.jpg new file mode 100644 index 0000000000..c413aa0caf Binary files /dev/null and b/docs/scene/images/scale_tool.jpg differ diff --git a/docs/scene/images/scene_example.jpg b/docs/scene/images/scene_example.jpg new file mode 100644 index 0000000000..5e787c4420 Binary files /dev/null and b/docs/scene/images/scene_example.jpg differ diff --git a/docs/scene/images/scene_example_scene_graph.jpg b/docs/scene/images/scene_example_scene_graph.jpg new file mode 100644 index 0000000000..da8c10169d Binary files /dev/null and b/docs/scene/images/scene_example_scene_graph.jpg differ diff --git a/docs/scene/images/selection_tool.jpg b/docs/scene/images/selection_tool.jpg new file mode 100644 index 0000000000..c9058de526 Binary files /dev/null and b/docs/scene/images/selection_tool.jpg differ diff --git a/docs/scene/images/support_blocker_tool.jpg b/docs/scene/images/support_blocker_tool.jpg new file mode 100644 index 0000000000..bdc4b118c2 Binary files /dev/null and b/docs/scene/images/support_blocker_tool.jpg differ diff --git a/docs/scene/images/tools_tool-handles_class_diagram.jpg b/docs/scene/images/tools_tool-handles_class_diagram.jpg new file mode 100644 index 0000000000..cd58fad066 Binary files /dev/null and b/docs/scene/images/tools_tool-handles_class_diagram.jpg differ diff --git a/docs/scene/images/translate_tool.jpg b/docs/scene/images/translate_tool.jpg new file mode 100644 index 0000000000..80886a7f17 Binary files /dev/null and b/docs/scene/images/translate_tool.jpg differ diff --git a/docs/scene/operations.md b/docs/scene/operations.md new file mode 100644 index 0000000000..fe625514be --- /dev/null +++ b/docs/scene/operations.md @@ -0,0 +1,113 @@ +# Operations and the OperationStack + +Cura supports an operation stack. The `OperationStack` class maintains a history of the operations performed in Cura, which allows for undo and redo actions. Every operation registers itself in the stack. The OperationStuck supports the following functions: + + * `push(operation)`: Pushes an operation in the stack and applies the operation. This function is called when an operation pushes itself in the stack. + * `undo()`: Reverses the actions performed by the last operation and reduces the current index of the stack. + * `redo()`: Applies the actions performed by the next operation in the stack and increments the current index of the stack. + * `getOperations()`: Returns a list of all the operations that are currently inside the OperationStack + * `canUndo()`: Indicates whether the index of the operation stack has reached the bottom of the stack, which means that there are no more operations to be undone. + * `canRedo()`: Indicates whether the index of the operation stack has reached the top of the stack, which means that there are no more operations to be redone. + +**Note 1:** When consecutive operations are performed very quickly after each other, they are merged together at the top of the stack. This action ensures that these minor operation will be undone with one Undo keystroke (e.g. when moving the object around and you press and release the left mouse button really fast, it is considered as one move operation). + +**Note 2:** When an operation is pushed in the middle of the stack, all operations above it are removed from the stack. This ensures that there won't be any "history branches" created. + +### Operations + +Every action that happens in the scene and affects one or multiple models is associated with a subclass of the `Operation` class and is it added to the `OperationStack`. The subclassed operations that can be found in Cura (excluding the ones from downloadable plugins) are the following: + + * [GroupedOperation](#groupedoperation) + * [AddSceneNodeOperation](#addscenenodeoperation) + * [RemoveSceneNodeOperation](#removescenenodeoperation) + * [SetParentOperation](#setparentoperation) + * [SetTransformOperation](#settransformoperation) + * [SetObjectExtruderOperation](#setobjectextruderoperation) + * [GravityOperation](#gravityoperation) + * [PlatformPhysicsOperation](#platformphysicsoperation) + * [TranslateOperation](#translateoperation) + * [ScaleOperation](#scaleoperation) + * [RotateOperation](#rotateoperation) + * [MirrorOperation](#mirroroperation) + * [LayFlatOperation](#layflatoperation) + * [SetBuildPlateNumberOperation]() + +### GroupedOperation + +The `GroupedOperation` is an operation that groups several other operations together. The intent of this operation is to hide an underlying chain of operations from the user if they correspond to only one interaction with the user, such as an operation applied to multiple scene nodes or a re-arrangement of multiple items in the scene. + +Once a `GroupedOperation` is pushed into the stack, it applies all of its children operations in one go. Similarly, when it is undone, it reverses all its children operations at once. + + +### AddSceneNodeOperation + +The `AddSceneNodeOperation` is added to the stack whenever a mesh is loaded inside the `Scene`, either by a `FileReader` or by inserting a [Support Blocker](tools.md#supporteraser-tool) in an object. + +### RemoveSceneNodeOperation + +The `RemoveSceneNodeOperation` is added to the stack whenever a mesh is removed from the Scene by the user or when the user requests to clear the build plate (_Ctrl+D_). + +### SetParentOperation + +The `SetParentOperation` changes the parent of a node. It is primarily used when grouping (the group node is set as the nodes' parent) and ungrouping (the group's children's parent is set to the group's parent before the group node is deleted), or when a SupportEraser node is added to the scene (to set the selected object as the Eraser's parent). + +### SetTransformOperation + +The `SetTransformOperation` translates, rotates, and scales a node all at once. This operation accepts a transformation matrix, an orientation matrix, and a scale matrix, and it is used by the _"Reset All Model Positions"_ and _"Reset All Model Transformations"_ options in the right-click (context) menu. + +### SetObjectExtruderOperation + +This operation is used to set the extruder with which a certain object should be printed with. It adds a [SettingOverrideDecorator](scene.md#settingoverridedecorator) to the object (if it doesn't have any) and then sets the extruder number via the decoration function `node.callDecoration("setActiveExtruder", extruder_id)`. + +### GravityOperation + +The `GravityOperation` moves a scene node down to 0 on the y-axis. It is currently used by the _"Lay flat"_ and _"Select face to align to the build plate"_ actions of the `RotationTool` to ensure that the object will end up touching the build plate after the corresponding rotation operations have be done. + +### PlatformPhysicsOperation + +The `PlatformPhysicsOperation` is generated by the `PlatformPhysics` class and it is associated with the preferences _"Ensure models are kept apart"_ and _"Automatically drop models to the build plate"_. If any of these preferences is set to true, the `PlatformPhysics` class periodically checks to make sure that the two conditions are met and if not, it calculates the move vector for each of the nodes that will satisfy the conditions. + +Once the move vectors have been computed, they are applied to the nodes through consecutive `PlatformPhysicsOperations`, whose job is to use the `translate` function on the nodes. + +**Note:** When there are multiple nodes, multiple `PlatformPhysicsOperations` may be generated (all models may be moved to ensure they are kept apart). These operations eventually get merged together by the `OperationStack` due to the fact that the individual operations are applied very fast one after the other. + +### TranslateOperation + +The `TranslateOperation` applies a linear transformation on a node, moving the node in the scene. This operation is primarily linked to the [TranslateTool](tools.md#translatetool) but it is also used in other places around Cura, such as arranging objects on the build plate (Ctrl+R) and centering an object to the build plate (via the right-click context menu's _"Center Selected Model"_ option). + +When an object is moved using the move tool handles, multiple translate operations are generated to make sure that the object is rendered properly while it is moved. These translate operations are merged together once the user releases the tool handle. + +**Note:** Some functionalities may move (translate) nodes without generating a TranslateOperation (such as when a model with is imported from a 3mf into a certain position). This ensures that the moving of the object cannot be accidentally undone by the user. + +### ScaleOperation + +The `ScaleOperation` scales the selected scene node uniformly or non-uniformly. This operation is primarily generated by the [ScaleTool](tools.md#scaletool). + +When an object is scaled using the scale tool handles, multiple scale operations are generated to make sure that the object is rendered properly while it is being resized. These scale operations are merged together once the user releases the tool handle. + +**Note:** When the _"Scale extremely small models"_ or the _"Scale large models"_ preferences are enabled the model is scaled when it is inserted into the build plate but it **DOES NOT** generate a `ScaleOperation`. This ensures that Cura doesn't register the scaling as an action that can be undone and the user doesn't accidentally end up with a very big or very small model. + + +### RotateOperation + +The `RotateOperation` rotates the selected scene node(s) according to a given rotation quaternion and, optionally, around a given point. This operation is primarily generated by the [RotationTool](tools.md#rotatetool). It is also used by the arrange algorithm, which may rotate some models to fit them in the build plate. + +When an object is rotated using the rotate tool handles, multiple rotate operations are generated to make sure that the object is rendered properly while it is being rotated. These operations are merged together once the user releases the tool handle. + +### MirrorOperation + +The `MirrorOperation` mirrors the selected object. It is primarily associated with the [MirrorTool](tools.md#mirrortool) and allows for mirroring the object in a certain direction, using the `MirrorToolHandles`. + +The `MirrorOperation` accepts a transformation matrix that should only define values on the diagonal of the matrix, and only the values 1 or -1. It allows for mirroring around the center of the object or around the axis origin. The latter isn't used that often. + +### LayFlatOperation + +The `LayFlatOperation` computes some orientation to hopefully lay the object flat on the build plate. It is generated by the `layFlat()` function of the [RotateTool](tools.md#rotatetool). Contrary to the other operations, the `LayFlatOperation` is computed in a separate thread through the `LayFlatJob` since it can be quite computationally expensive. + + +### SetBuildPlateNumberOperation + +The `SetBuildPlateNumberOperation` is linked to a legacy feature which allowed the user to have multiple build plates open in Cura at the same time. With this operation it was possible to transfer a node to another build plate through the node's [BuildPlateDecorator](scene.md#buildplatedecorator) by calling the decoration `node.callDecoration("setBuildPlateNumber", new_build_plate_nr)`. + +**Note:** Changing the active build plate is a disabled feature in Cura and it is intended to be completely removed (internal ticket: CURA-4975), along with the `SetBuildPlateNumberOperation`. + diff --git a/docs/scene/scene.md b/docs/scene/scene.md index 5539df4a67..265554264c 100644 --- a/docs/scene/scene.md +++ b/docs/scene/scene.md @@ -8,19 +8,209 @@ Cura's scene graph is a mere tree data structure. This tree contains all scene n The main idea behind the scene tree is that each scene node has a transformation applied to it. The scene nodes can be nested beneath other scene nodes. The transformation of the parents is then also applied to the children. This way you can have scene nodes grouped together and transform the group as a whole. Since the transformations are all linear, this ensures that the elements of this group stay in the same relative position and orientation. It will look as if the whole group is a single object. This idea is very common for games where objects are often composed of multiple 3D models but need to move together as a whole. For Cura it is used to group objects together and to transform the collision area correctly. +Class Diagram +---- + +The following class diagram depicts the classes that interact with the Scene + +![alt text](images/components_interacting_with_scene.jpg) + +The scene lives in the Controller of the Application, and it is primarily interacting with SceneNode objects, which are the components of the Scene Graph. + + A Typical Scene ---- -Cura's scene has a few nodes that are always present, and a few nodes that are repeated for every object that the user loads onto their build plate. To give an idea of how a scene normally looks, this is an overview of a typical scene tree for Cura. +Cura's scene has a few nodes that are always present, and a few nodes that are repeated for every object that the user loads onto their build plate. The root of the scene graph is a SceneNode that lives inside the Scene and contains all the other children SceneNodes of the scene. Typically, inside the root you can find the SceneNodes that are always loaded (the Cameras, the [BuildVolume](build_volume.md), and the Platform), the objects that are loaded on the platform, and finally a ConvexHullNode for each object and each group of objects in the Scene. -* Root - * Camera - * [Build volume](build_volume.md) - * Platform - * Object 1 - * Group 1 - * Object 2 - * Object 3 - * Object 1 convex hull node - * Object 2 convex hull node - * Object 3 convex hull node - * Group 1 convex hull node \ No newline at end of file +Let's take the following example Scene: + +![scene_example.png](images/scene_example.jpg) + +The scene graph in this case is the following: + + +![scene_example_scene_graph.png](images/scene_example_scene_graph.jpg) + +**Note 1:** The Platform is actually a child of the BuildVolume. + +**Note 2:** The ConvexHullNodes are not actually named after the object they decorate. Their names are used in the image to convey how the ConvexHullNodes are related to the objects in the scene. + +**Note 3:** The CuraSceneNode that holds the layer data (inside the BuildVolume) is created and destroyed according to the availability of sliced layer data provided by the CuraEngine. See the [LayerDataDecorator](#layerdatadecorator) for more information. + +Accessing SceneNodes in the Scene +---- + +SceneNodes can be accessed using a `BreadthFirstIterator` or a `DepthFirstIterator`. Each iterator traverses the scene graph and returns a Python iterator, which yields all the SceneNodes and their children. + +``` python +for node in BreadthFirstIterator(scene.getRoot()): + # do stuff with the node +``` + +Example result when iterating the above scene graph: + +```python +[i for i in BreadthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()] +``` + * 00 = {SceneNode} + * 01 = {BuildVolume} + * 02 = {Camera} + * 03 = {CuraSceneNode} + * 04 = {CuraSceneNode} + * 05 = {Camera} + * 06 = {CuraSceneNode} + * 07 = {ConvexHullNode} + * 08 = {ConvexHullNode} + * 09 = {ConvexHullNode} + * 10 = {ConvexHullNode} + * 11 = {ConvexHullNode} + * 12 = {ConvexHullNode} + * 13 = {ConvexHullNode} + * 14 = {Platform} + * 15 = {CuraSceneNode} + * 16 = {CuraSceneNode} + * 17 = {CuraSceneNode} + * 18 = {CuraSceneNode} + +SceneNodeDecorators +---- + +SceneNodeDecorators are decorators that can be added to the nodes of the scene to provide them with additional functions. + +Cura provides the following classes derived from the SceneNodeDecorator class: + 1. [GroupDecorator](#groupdecorator) + 2. [ConvexHullDecorator](#convexhulldecorator) + 3. [SettingOverrideDecorator](#settingoverridedecorator) + 4. [SliceableObjectDecorator](#sliceableobjectdecorator) + 5. [LayerDataDecorator](#layerdatadecorator) + 6. [ZOffsetDecorator](#zoffsetdecorator) + 7. [BlockSlicingDecorator](#blockslicingdecorator) + 8. [GCodeListDecorator](#gcodelistdecorator) + 9. [BuildPlateDecorator](#buildplatedecorator) + +GroupDecorator +---- + +Whenever objects on the build plate are grouped together, a new node is added in the scene as the parent of the grouped objects. Group nodes can be identified when traversing the SceneGraph by running the following: + +```python +node.callDecoration("isGroup") == True +``` + +Group nodes decorated by GroupDecorators are added in the scene either by reading project files which contain grouped objects, or when the user selects multiple objects and groups them together (Ctrl + G). + +Group nodes that are left with only one child are removed from the scene, making their only child a child of the group's parent. In addition, group nodes without any remaining children are removed from the scene. + +ConvexHullDecorator +---- + +As seen in the scene graph of the scene example, each CuraSceneNode that represents an object on the build plate is linked to a ConvexHullNode which is rendered as the object's shadow on the build plate. The ConvexHullDecorator is the link between these two nodes. + +In essence, the CuraSceneNode has a ConvexHullDecorator which points to the ConvexHullNode of the object. The data of the object's convex hull can be accessed via + +```python +convex_hull_polygon = object_node.callDecoration("getConvexHull") +``` + +The ConvexHullDecorator also provides convex hulls that include the head, the fans, and the adhesion of the object. These are primarily used and rendered when One-at-a-time mode is activated. + +For more information on the functions added to the node by this decorator, visit the [ConvexHullDecorator.py](https://github.com/Ultimaker/Cura/blob/master/cura/Scene/ConvexHullDecorator.py). + +SettingOverrideDecorator +---- + +SettingOverrideDecorators are primarily used for modifier meshes such as support meshes, cutting meshes, infill meshes, and anti-overhang meshes. When a user converts an object to a modifier mesh, the object's node is decorated by a SettingOverrideDecorator. This decorator adds a PerObjectContainerStack to the CuraSceneNode, which allows the user to modify the settings of the specific model. + +For more information on the functions added to the node by this decorator, visit the [SettingOverrideDecorator.py](https://github.com/Ultimaker/Cura/blob/master/cura/Settings/SettingOverrideDecorator.py). + + +SliceableObjectDecorator +---- + +This is a convenience decorator that allows us to easily identify the nodes which can be sliced. All **individual** objects (meshes) added to the build plate receive this decorator, apart from the nodes loaded from GCode files (.gcode, .g, .gz, .ufp). + +The SceneNodes that do not receive this decorator are: + + - Cameras + - BuildVolume + - Platform + - ConvexHullNodes + - CuraSceneNodes that serve as group nodes (these have a GroupDecorator instead) + - The CuraSceneNode that serves as the layer data node + - ToolHandles + - NozzleNode + - Nodes that contain GCode data. See the [BlockSlicingDecorator](#blockslicingdecorator) for more information on that. + +This decorator provides the following function to the node: + +```python +node.callDecoration("isSliceable") +``` + +LayerDataDecorator +---- + +Once the Slicing has completed and the CuraEngine has returned the slicing data, Cura creates a CuraSceneNode inside the BuildVolume which is decorated by a LayerDataDecorator. This decorator holds the layer data of the scene. + +![Layer Data Scene Node](images/layer_data_scene_node.jpg) + +The layer data can be accessed through the function given to the aforementioned CuraSceneNode by the LayerDataDecorator: + +```python +node.callDecoration("getLayerData") +``` + +This CuraSceneNode is created once Cura has completed processing the Layer data (after the user clicks on the Preview tab after slicing). The CuraSceneNode then is destroyed once any action that changes the Scene occurs (e.g. if the user moves/rotates/scales an object or changes a setting value), indicating that the layer data is no longer available. When that happens, the "Slice" button becomes available again. + +ZOffsetDecorator +---- + +The ZOffsetDecorator is added to an object in the scene when that object is moved below the build plate. It is primarily used when the "Automatically drop models to the build plate" preference is enabled, in order to make sure that the GravityOperation, which drops the mode on the build plate, is not applied when the object is moved under the build plate. + +The amount the object is moved under the build plate can be retrieved by calling the "getZOffset" decoration on the node: + +```python +z_offset = node.callDecoration("getZOffset") +``` + +The ZOffsetDecorator is removed from the node when the node is move above the build plate. + +BlockSlicingDecorator +---- + +The BlockSlicingDecorator is the opposite of the SliceableObjectDecorator. It is added on objects loaded on the scene which should not be sliced. This decorator is primarily added on objects loaded from ".gcode", ".ufp", ".g", and ".gz" files. Such an object already contains all the slice information and therefore should not allow Cura to slice it. + +If an object with a BlockSlicingDecorator appears in the scene, the backend (CuraEngine) and the print setup (changing print settings) become disabled, considering that G-code files cannot be modified. + +The BlockSlicingDecorator adds the following decoration function to the node: + +```python +node.callDecoration("isBlockSlicing") +``` + +GCodeListDecorator +---- + +The GCodeListDecorator is also added only when a file containing GCode is loaded in the scene. It's purpose is to hold a list of all the GCode data of the loaded object. +The GCode list data is stored in the scene's gcode_dict attribute which then is used in other places in the Cura code, e.g. to provide the GCode to the GCodeWriter or to the PostProcessingPlugin. + +The GCode data becomes available by calling the "getGCodeList" decoration of the node: + +```python +gcode_list = node.callDecoration("getGCodeList") +``` + +The CuraSceneNode with the GCodeListDecorator is destroyed when another object or project file is loaded in the Scene. + +BuildPlateDecorator +---- + +The BuildPlateDecorator is added to all the CuraSceneNodes. This decorator is linked to a legacy feature which allowed the user to have multiple build plates open in Cura at the same time. With this decorator it was possible to determine which nodes are present on each build plate, and therefore, which objects should be visible in the currently active build plate. It indicates the number of the build plate this scene node belongs to, which currently is always the build plate -1. + +This decorator provides a function to the node that returns the number of the build plate it belongs to: + +```python +node.callDecoration("getBuildPlateNumber") +``` + +**Note:** Changing the active build plate is a disabled feature in Cura and it is intended to be completely removed (internal ticket: CURA-4975). diff --git a/docs/scene/tools.md b/docs/scene/tools.md new file mode 100644 index 0000000000..0418bf4a97 --- /dev/null +++ b/docs/scene/tools.md @@ -0,0 +1,86 @@ +# Tools + +Tools are plugin objects which are used to manipulate or interact with the scene and the objects (node) in the scene. + +![Class diagram of tools in the scene](images/tools_tool-handles_class_diagram.jpg) + +Tools live inside the Controller of the Application and may be associated with ToolHandles. Some of them interact with the scene as a whole (such as the Camera), while others interact with the objects (nodes) in the Scene (selection tool, rotate tool, scale tool etc.). The tools that are available in Cura (excluding the ones provided by downloadable plugins) are the following: + + * [CameraTool](#cameratool) + * [SelectionTool](#selectiontool) + * [TranslateTool](#translatetool) + * [ScaleTool](#scaletool) + * [RotateTool](#rotatetool) + * [MirrorTool](#mirrortool) + * [PerObjectSettingsTool](#perobjectsettingstool) + * [SupportEraserTool](#supporteraser) + +***** + +### CameraTool + +The CameraTool is the tool that allows the user to manipulate the Camera. It provides the functions of moving, zooming, and rotating the Camera. This tool does not contain a handle. + +### SelectionTool +This tool allows the user to select objects and groups of objects in the scene. The selected objects gain a blue outline and become available in the code through the Selection class. + +![Selection Tool](images/selection_tool.jpg) + +This tool does not contain a handle. + +### TranslateTool + +This tool allows the user to move the object around the build plate. The TranslateTool is activated once the user presses the Move icon in the tool sidebar or hits the shortcut (T) while an object is selected. + +![Translate Tool](images/translate_tool.jpg) + +The TranslateTool contains the TranslateToolHandle, which draws the arrow handles on the selected object(s). The TranslateTool generates TranslateOperations whenever the object is moved around the build plate. + + +### ScaleTool + +This tool allows the user to scale the selected object(s). The ScaleTool is activated once the user presses the Scale icon in the tool sidebar or hits the shortcut (S) while an object is selected. + +![Scale Tool](images/scale_tool.jpg) + +The ScaleTool contains the ScaleToolHandle, which draws the box handles on the selected object(s). The ScaleTool generates ScaleOperations whenever the object is scaled. + +### RotateTool + +This tool allows the user to rotate the selected object(s). The RotateTool is activated once the user presses the Rotate icon in the tool sidebar or hits the shortcut (R) while an object is selected. + +![Rotate Tool](images/rotate_tool.jpg) + +The RotateTool contains the RotateToolHandle, which draws the donuts (tori) and arrow handles on the selected object(s). The RotateTool generates RotateOperations whenever the object is rotated or if a face is selected to be laid flat on the build plate. It also contains the `layFlat()` action, which generates the [LayFlatOperation](operations.md#layflatoperation). + + +### MirrorTool + +This tool allows the user to mirror the selected object(s) in the required direction. The MirrorTool is activated once the user presses the Mirror icon in the tool sidebar or hits the shortcut (M) while an object is selected. + +![Mirror Tool](images/mirror_tool.jpg) + +The MirrorTool contains the MirrorToolHandle, which draws pyramid handles on the selected object(s). The MirrorTool generates MirrorOperations whenever the object is mirrored against an axis. + +### PerObjectSettingsTool + +This tool allows the user to change the mesh type of the object into one of the following: + + * Normal Model + * Print as support + * Modify settings for overlaps + - Infill mesh only + - Cutting mesh + * Don't support overlaps + +![Per object settings tool](images/per_objectsettings_tool.jpg) + +Contrary to other tools, this tool doesn't have any handles and it does not generate any operations. This means that once an object's type is changed it cannot be undone/redone using the OperationStack. This tool adds a [SettingOverrideDecorator](scene.md#settingoverridedecorator) on the object's node instead, which allows the user to change certain settings only for this mesh. + +### SupportEraser tool + +This tool allows the user to add support blockers on the selected model. The SupportEraserTool is activated once the user pressed the Support Blocker icon in the tool sidebar or hits the shortcut (E) while an object is selected. With this tool active, the user can add support blockers (cubes) on the object by clicking on various places on the selected mesh. + +![Support Eraser Tool](images/support_blocker_tool.jpg) + +The SupportEraser uses a GroupOperation to add a new CuraSceneNode (the eraser) in the scene and set the selected model as the parent of the eraser. This means that the addition of Erasers in the scene can be undone/redone. The SupportEraser does not have any tool handles. \ No newline at end of file diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 7a063467d8..669bee8f40 100755 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -51,6 +51,10 @@ class ThreeMFReader(MeshReader): self._root = None self._base_name = "" self._unit = None + self._empty_project = False + + def emptyFileHintSet(self) -> bool: + return self._empty_project def _createMatrixFromTransformationString(self, transformation: str) -> Matrix: if transformation == "": @@ -196,6 +200,7 @@ class ThreeMFReader(MeshReader): return um_node def _read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: + self._empty_project = False result = [] # The base object of 3mf is a zipped archive. try: @@ -264,6 +269,9 @@ class ThreeMFReader(MeshReader): result.append(um_node) + if len(result) == 0: + self._empty_project = True + except Exception: Logger.logException("e", "An exception occurred in 3mf reader.") return [] diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 2248b64389..754069dc9b 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -43,6 +43,10 @@ class DriveApiService: return backup_list_response = HttpRequestManager.readJSON(reply) + if backup_list_response is None: + Logger.error("List of back-ups can't be parsed.") + changed([]) + return if "data" not in backup_list_response: Logger.log("w", "Could not get backups from remote, actual response body was: %s", str(backup_list_response)) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 4b196f7b5d..1aa6c86dcb 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import argparse #To run the engine in debug mode if the front-end is in debug mode. @@ -9,6 +9,8 @@ import sys from time import time from typing import Any, cast, Dict, List, Optional, Set, TYPE_CHECKING +from PyQt5.QtGui import QImage + from UM.Backend.Backend import Backend, BackendState from UM.Scene.SceneNode import SceneNode from UM.Signal import Signal @@ -24,6 +26,8 @@ from UM.Tool import Tool #For typing. from cura.CuraApplication import CuraApplication from cura.Settings.ExtruderManager import ExtruderManager +from cura.Snapshot import Snapshot +from cura.Utils.Threading import call_on_qt_thread from .ProcessSlicedLayersJob import ProcessSlicedLayersJob from .StartSliceJob import StartSliceJob, StartJobResult @@ -153,6 +157,8 @@ class CuraEngineBackend(QObject, Backend): self.determineAutoSlicing() application.getPreferences().preferenceChanged.connect(self._onPreferencesChanged) + self._snapshot = None #type: Optional[QImage] + application.initializationFinished.connect(self.initialize) def initialize(self) -> None: @@ -241,9 +247,27 @@ class CuraEngineBackend(QObject, Backend): self.markSliceAll() self.slice() + @call_on_qt_thread # must be called from the main thread because of OpenGL + def _createSnapshot(self) -> None: + self._snapshot = None + if not CuraApplication.getInstance().isVisible: + Logger.log("w", "Can't create snapshot when renderer not initialized.") + return + Logger.log("i", "Creating thumbnail image (just before slice)...") + try: + self._snapshot = Snapshot.snapshot(width = 300, height = 300) + except: + Logger.logException("w", "Failed to create snapshot image") + self._snapshot = None # Failing to create thumbnail should not fail creation of UFP + + def getLatestSnapshot(self) -> Optional[QImage]: + return self._snapshot + def slice(self) -> None: """Perform a slice of the scene.""" + self._createSnapshot() + Logger.log("i", "Starting to slice...") self._slice_start_time = time() if not self._build_plates_to_be_sliced: @@ -331,7 +355,6 @@ class CuraEngineBackend(QObject, Backend): def _onStartSliceCompleted(self, job: StartSliceJob) -> None: """Event handler to call when the job to initiate the slicing process is - completed. When the start slice job is successfully completed, it will be happily diff --git a/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml b/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml index 902388b669..293e7386b2 100644 --- a/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml +++ b/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml @@ -137,6 +137,7 @@ Item labelWidth: base.labelWidth controlWidth: base.controlWidth unitText: "" + decimals: 0 forceUpdateOnChangeFunction: forceUpdateFunction } } diff --git a/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml b/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml index 758efd2e4e..0b3eba66c2 100644 --- a/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml +++ b/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml @@ -330,6 +330,25 @@ Item } } + /* + - Fix for this issue: https://github.com/Ultimaker/Cura/issues/9167 + - Allows user to toggle if GCODE coordinates are affected by the extruder offset. + - Machine wide setting. CuraEngine/src/gcodeExport.cpp is not set up to evaluate per extruder currently. + - If it is moved to per-extruder (unlikely), then this should be moved to the extruder tab. + */ + Cura.SimpleCheckBox // "GCode Affected By Extruder Offsets" + { + id: applyExtruderOffsetsCheckbox + containerStackId: machineStackId + settingKey: "machine_use_extruder_offset_to_offset_coords" + settingStoreIndex: propertyStoreIndex + labelText: catalog.i18nc("@label", "Apply Extruder offsets to GCode") + labelFont: base.labelFont + labelWidth: base.labelWidth + forceUpdateOnChangeFunction: forceUpdateFunction + } + + /* The "Shared Heater" feature is temporarily disabled because its implementation is incomplete. Printers with multiple filaments going into one nozzle will keep the inactive filaments retracted at the diff --git a/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py index b4036f7ff2..a23e52b750 100644 --- a/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py +++ b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py @@ -774,15 +774,15 @@ class ChangeAtZProcessor: # looking for wait for bed temp if "bedTemp" in values: - codes.append("BedTemp: " + str(values["bedTemp"])) + codes.append("BedTemp: " + str(round(values["bedTemp"]))) # set our extruder one temp (if specified) if "extruderOne" in values: - codes.append("Extruder 1 Temp: " + str(values["extruderOne"])) + codes.append("Extruder 1 Temp: " + str(round(values["extruderOne"]))) # set our extruder two temp (if specified) if "extruderTwo" in values: - codes.append("Extruder 2 Temp: " + str(values["extruderTwo"])) + codes.append("Extruder 2 Temp: " + str(round(values["extruderTwo"]))) # set global flow rate if "flowrate" in values: diff --git a/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py b/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py new file mode 100644 index 0000000000..0ce6ac6eff --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/CreateThumbnail.py @@ -0,0 +1,109 @@ +import base64 + +from UM.Logger import Logger +from cura.Snapshot import Snapshot +from PyQt5.QtCore import QByteArray, QIODevice, QBuffer + +from ..Script import Script + + +class CreateThumbnail(Script): + def __init__(self): + super().__init__() + + def _createSnapshot(self, width, height): + Logger.log("d", "Creating thumbnail image...") + try: + return Snapshot.snapshot(width, height) + except Exception: + Logger.logException("w", "Failed to create snapshot image") + + def _encodeSnapshot(self, snapshot): + Logger.log("d", "Encoding thumbnail image...") + try: + thumbnail_buffer = QBuffer() + thumbnail_buffer.open(QBuffer.ReadWrite) + thumbnail_image = snapshot + thumbnail_image.save(thumbnail_buffer, "PNG") + base64_bytes = base64.b64encode(thumbnail_buffer.data()) + base64_message = base64_bytes.decode('ascii') + thumbnail_buffer.close() + return base64_message + except Exception: + Logger.logException("w", "Failed to encode snapshot image") + + def _convertSnapshotToGcode(self, encoded_snapshot, width, height, chunk_size=78): + gcode = [] + + encoded_snapshot_length = len(encoded_snapshot) + gcode.append(";") + gcode.append("; thumbnail begin {} {} {}".format( + width, height, encoded_snapshot_length)) + + chunks = ["; {}".format(encoded_snapshot[i:i+chunk_size]) + for i in range(0, len(encoded_snapshot), chunk_size)] + gcode.extend(chunks) + + gcode.append("; thumbnail end") + gcode.append(";") + gcode.append("") + + return gcode + + def getSettingDataString(self): + return """{ + "name": "Create Thumbnail", + "key": "CreateThumbnail", + "metadata": {}, + "version": 2, + "settings": + { + "width": + { + "label": "Width", + "description": "Width of the generated thumbnail", + "unit": "px", + "type": "int", + "default_value": 32, + "minimum_value": "0", + "minimum_value_warning": "12", + "maximum_value_warning": "800" + }, + "height": + { + "label": "Height", + "description": "Height of the generated thumbnail", + "unit": "px", + "type": "int", + "default_value": 32, + "minimum_value": "0", + "minimum_value_warning": "12", + "maximum_value_warning": "600" + } + } + }""" + + def execute(self, data): + width = self.getSettingValueByKey("width") + height = self.getSettingValueByKey("height") + + snapshot = self._createSnapshot(width, height) + if snapshot: + encoded_snapshot = self._encodeSnapshot(snapshot) + snapshot_gcode = self._convertSnapshotToGcode( + encoded_snapshot, width, height) + + for layer in data: + layer_index = data.index(layer) + lines = data[layer_index].split("\n") + for line in lines: + if line.startswith(";Generated with Cura"): + line_index = lines.index(line) + insert_index = line_index + 1 + lines[insert_index:insert_index] = snapshot_gcode + break + + final_lines = "\n".join(lines) + data[layer_index] = final_lines + + return data diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py index fc7bfec60a..69a67990fe 100644 --- a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py +++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py @@ -182,8 +182,7 @@ class PauseAtHeight(Script): "Repetier": "Repetier" }, "default_value": "RepRap (Marlin/Sprinter)", - "enabled": false, - "default_value": "" + "enabled": false }, "custom_gcode_before_pause": { diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index 93485eb3a3..cbe75cc548 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -15,9 +15,10 @@ from UM.View.RenderBatch import RenderBatch from UM.View.GL.OpenGL import OpenGL from cura.Settings.ExtruderManager import ExtruderManager - +from cura.LayerPolygon import LayerPolygon import os.path +import numpy ## RenderPass used to display g-code paths. from .NozzleNode import NozzleNode @@ -60,6 +61,9 @@ class SimulationPass(RenderPass): self._current_shader = self._layer_shader # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers) self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) + if not self._compatibility_mode: + self._layer_shader.setUniformValue("u_starts_color", Color(*Application.getInstance().getTheme().getColor("layerview_starts").getRgb())) + if self._layer_view: self._layer_shader.setUniformValue("u_max_feedrate", self._layer_view.getMaxFeedrate()) self._layer_shader.setUniformValue("u_min_feedrate", self._layer_view.getMinFeedrate()) @@ -71,6 +75,7 @@ class SimulationPass(RenderPass): self._layer_shader.setUniformValue("u_show_helpers", self._layer_view.getShowHelpers()) self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) self._layer_shader.setUniformValue("u_show_infill", self._layer_view.getShowInfill()) + self._layer_shader.setUniformValue("u_show_starts", self._layer_view.getShowStarts()) else: #defaults self._layer_shader.setUniformValue("u_max_feedrate", 1) @@ -83,6 +88,7 @@ class SimulationPass(RenderPass): self._layer_shader.setUniformValue("u_show_helpers", 1) self._layer_shader.setUniformValue("u_show_skin", 1) self._layer_shader.setUniformValue("u_show_infill", 1) + self._layer_shader.setUniformValue("u_show_starts", 1) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) @@ -161,6 +167,13 @@ class SimulationPass(RenderPass): self._current_shader = self._layer_shader self._switching_layers = True + # The first line does not have a previous line: add a MoveCombingType in front for start detection + # this way the first start of the layer can also be drawn + prev_line_types = numpy.concatenate([numpy.asarray([LayerPolygon.MoveCombingType], dtype = numpy.float32), layer_data._attributes["line_types"]["value"]]) + # Remove the last element + prev_line_types = prev_line_types[0:layer_data._attributes["line_types"]["value"].size] + layer_data._attributes["prev_line_types"] = {'opengl_type': 'float', 'value': prev_line_types, 'opengl_name': 'a_prev_line_type'} + layers_batch = RenderBatch(self._current_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end), backface_cull = True) layers_batch.addItem(node.getWorldTransformation(), layer_data) layers_batch.render(self._scene.getActiveCamera()) diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 349426d463..1324d793fb 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -104,13 +104,14 @@ class SimulationView(CuraView): Application.getInstance().getPreferences().addPreference("view/only_show_top_layers", False) Application.getInstance().getPreferences().addPreference("view/force_layer_view_compatibility_mode", False) - Application.getInstance().getPreferences().addPreference("layerview/layer_view_type", 0) + Application.getInstance().getPreferences().addPreference("layerview/layer_view_type", 1) # Default to "Line Type". Application.getInstance().getPreferences().addPreference("layerview/extruder_opacities", "") Application.getInstance().getPreferences().addPreference("layerview/show_travel_moves", False) Application.getInstance().getPreferences().addPreference("layerview/show_helpers", True) Application.getInstance().getPreferences().addPreference("layerview/show_skin", True) Application.getInstance().getPreferences().addPreference("layerview/show_infill", True) + Application.getInstance().getPreferences().addPreference("layerview/show_starts", True) self._updateWithPreferences() @@ -146,6 +147,7 @@ class SimulationView(CuraView): self._show_helpers = True self._show_skin = True self._show_infill = True + self._show_starts = True self.resetLayerData() def getActivity(self) -> bool: @@ -355,6 +357,13 @@ class SimulationView(CuraView): def getShowInfill(self) -> bool: return self._show_infill + def setShowStarts(self, show: bool) -> None: + self._show_starts = show + self.currentLayerNumChanged.emit() + + def getShowStarts(self) -> bool: + return self._show_starts + def getCompatibilityMode(self) -> bool: return self._compatibility_mode @@ -638,6 +647,7 @@ class SimulationView(CuraView): self.setShowHelpers(bool(Application.getInstance().getPreferences().getValue("layerview/show_helpers"))) self.setShowSkin(bool(Application.getInstance().getPreferences().getValue("layerview/show_skin"))) self.setShowInfill(bool(Application.getInstance().getPreferences().getValue("layerview/show_infill"))) + self.setShowStarts(bool(Application.getInstance().getPreferences().getValue("layerview/show_starts"))) self._startUpdateTopLayers() self.preferencesChanged.emit() @@ -653,6 +663,7 @@ class SimulationView(CuraView): "layerview/show_helpers", "layerview/show_skin", "layerview/show_infill", + "layerview/show_starts", }: return diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index ffb7eebc95..d29d4051a4 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -82,6 +82,7 @@ Cura.ExpandableComponent property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers") property bool show_skin: UM.Preferences.getValue("layerview/show_skin") property bool show_infill: UM.Preferences.getValue("layerview/show_infill") + property bool show_starts: UM.Preferences.getValue("layerview/show_starts") // If we are in compatibility mode, we only show the "line type" property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1 @@ -250,6 +251,15 @@ Cura.ExpandableComponent preference: "layerview/show_infill", colorId: "layerview_infill" }); + if (! UM.SimulationView.compatibilityMode) + { + typesLegendModel.append({ + label: catalog.i18nc("@label", "Starts"), + initialValue: viewSettings.show_starts, + preference: "layerview/show_starts", + colorId: "layerview_starts" + }); + } } } diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index ceda09f9d5..0a5cc23ce7 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -21,6 +21,7 @@ vertex41core = in highp vec4 a_normal; in highp vec2 a_line_dim; // line width and thickness in highp float a_extruder; + in highp float a_prev_line_type; in highp float a_line_type; in highp float a_feedrate; in highp float a_thickness; @@ -32,6 +33,7 @@ vertex41core = out lowp vec2 v_line_dim; out highp int v_extruder; out highp mat4 v_extruder_opacity; + out float v_prev_line_type; out float v_line_type; out lowp vec4 f_color; @@ -92,6 +94,7 @@ vertex41core = v_normal = (u_normalMatrix * normalize(a_normal)).xyz; v_line_dim = a_line_dim; v_extruder = int(a_extruder); + v_prev_line_type = a_prev_line_type; v_line_type = a_line_type; v_extruder_opacity = u_extruder_opacity; @@ -108,13 +111,16 @@ geometry41core = uniform highp mat4 u_viewMatrix; uniform highp mat4 u_projectionMatrix; + uniform lowp vec4 u_starts_color; + uniform int u_show_travel_moves; uniform int u_show_helpers; uniform int u_show_skin; uniform int u_show_infill; + uniform int u_show_starts; layout(lines) in; - layout(triangle_strip, max_vertices = 26) out; + layout(triangle_strip, max_vertices = 40) out; in vec4 v_color[]; in vec3 v_vertex[]; @@ -122,6 +128,7 @@ geometry41core = in vec2 v_line_dim[]; in int v_extruder[]; in mat4 v_extruder_opacity[]; + in float v_prev_line_type[]; in float v_line_type[]; out vec4 f_color; @@ -268,6 +275,29 @@ geometry41core = EndPrimitive(); } + + + if ((u_show_starts == 1) && (v_prev_line_type[0] != 1) && (v_line_type[0] == 1)) { + float w = v_line_dim[0].x / 2; + float h = v_line_dim[0].y / 2; + + myEmitVertex(v_vertex[0] + vec3( w, h, w), u_starts_color, normalize(vec3( 1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, h, w, 0.0))); // Front-top-left + myEmitVertex(v_vertex[0] + vec3(-w, h, w), u_starts_color, normalize(vec3(-1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, h, w, 0.0))); // Front-top-right + myEmitVertex(v_vertex[0] + vec3( w, -h, w), u_starts_color, normalize(vec3( 1.0, -1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, -h, w, 0.0))); // Front-bottom-left + myEmitVertex(v_vertex[0] + vec3(-w, -h, w), u_starts_color, normalize(vec3(-1.0, -1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, -h, w, 0.0))); // Front-bottom-right + myEmitVertex(v_vertex[0] + vec3(-w, -h, -w), u_starts_color, normalize(vec3(-1.0, -1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, -h, -w, 0.0))); // Back-bottom-right + myEmitVertex(v_vertex[0] + vec3(-w, h, w), u_starts_color, normalize(vec3(-1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, h, w, 0.0))); // Front-top-right + myEmitVertex(v_vertex[0] + vec3(-w, h, -w), u_starts_color, normalize(vec3(-1.0, 1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, h, -w, 0.0))); // Back-top-right + myEmitVertex(v_vertex[0] + vec3( w, h, w), u_starts_color, normalize(vec3( 1.0, 1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, h, w, 0.0))); // Front-top-left + myEmitVertex(v_vertex[0] + vec3( w, h, -w), u_starts_color, normalize(vec3( 1.0, 1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, h, -w, 0.0))); // Back-top-left + myEmitVertex(v_vertex[0] + vec3( w, -h, w), u_starts_color, normalize(vec3( 1.0, -1.0, 1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, -h, w, 0.0))); // Front-bottom-left + myEmitVertex(v_vertex[0] + vec3( w, -h, -w), u_starts_color, normalize(vec3( 1.0, -1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, -h, -w, 0.0))); // Back-bottom-left + myEmitVertex(v_vertex[0] + vec3(-w, -h, -w), u_starts_color, normalize(vec3(-1.0, -1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, -h, -w, 0.0))); // Back-bottom-right + myEmitVertex(v_vertex[0] + vec3( w, h, -w), u_starts_color, normalize(vec3( 1.0, 1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4( w, h, -w, 0.0))); // Back-top-left + myEmitVertex(v_vertex[0] + vec3(-w, h, -w), u_starts_color, normalize(vec3(-1.0, 1.0, -1.0)), viewProjectionMatrix * (gl_in[0].gl_Position + vec4(-w, h, -w, 0.0))); // Back-top-right + + EndPrimitive(); + } } fragment41core = @@ -312,10 +342,13 @@ u_diffuseColor = [1.0, 0.79, 0.14, 1.0] u_minimumAlbedo = [0.1, 0.1, 0.1, 1.0] u_shininess = 20.0 +u_starts_color = [1.0, 1.0, 1.0, 1.0] + u_show_travel_moves = 0 u_show_helpers = 1 u_show_skin = 1 u_show_infill = 1 +u_show_starts = 1 u_min_feedrate = 0 u_max_feedrate = 1 @@ -337,6 +370,7 @@ a_normal = normal a_line_dim = line_dim a_extruder = extruder a_material_color = material_color +a_prev_line_type = prev_line_type a_line_type = line_type a_feedrate = feedrate a_thickness = thickness diff --git a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py index 5693b82ded..a85c13f639 100644 --- a/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py +++ b/plugins/Toolbox/src/CloudSync/SyncOrchestrator.py @@ -1,3 +1,6 @@ +# Copyright (c) 2021 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import os from typing import List, Dict, Any, cast @@ -96,7 +99,10 @@ class SyncOrchestrator(Extension): else: self._cloud_api.unsubscribe(item["package_id"]) # delete temp file - os.remove(item["package_path"]) + try: + os.remove(item["package_path"]) + except EnvironmentError as e: # File was already removed, no access rights, etc. + Logger.error("Can't delete temporary package file: {err}".format(err = str(e))) if has_changes: self._restart_presenter.present() diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py index 6179872b2d..f9b86be651 100644 --- a/plugins/UFPWriter/UFPWriter.py +++ b/plugins/UFPWriter/UFPWriter.py @@ -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 typing import cast, List, Dict @@ -7,16 +7,16 @@ from Charon.VirtualFile import VirtualFile # To open UFP files. from Charon.OpenMode import OpenMode # To indicate that we want to write to UFP files. from io import StringIO # For converting g-code to bytes. +from PyQt5.QtCore import QBuffer + from UM.Logger import Logger from UM.Mesh.MeshWriter import MeshWriter # The writer we need to implement. from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType from UM.PluginRegistry import PluginRegistry # To get the g-code writer. -from PyQt5.QtCore import QBuffer from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from cura.CuraApplication import CuraApplication -from cura.Snapshot import Snapshot from cura.Utils.Threading import call_on_qt_thread from UM.i18n import i18nCatalog @@ -38,17 +38,6 @@ class UFPWriter(MeshWriter): ) ) - self._snapshot = None - - def _createSnapshot(self, *args): - # must be called from the main thread because of OpenGL - Logger.log("d", "Creating thumbnail image...") - try: - self._snapshot = Snapshot.snapshot(width = 300, height = 300) - except Exception: - Logger.logException("w", "Failed to create snapshot image") - self._snapshot = None # Failing to create thumbnail should not fail creation of UFP - # This needs to be called on the main thread (Qt thread) because the serialization of material containers can # trigger loading other containers. Because those loaded containers are QtObjects, they must be created on the # Qt thread. The File read/write operations right now are executed on separated threads because they are scheduled @@ -72,24 +61,23 @@ class UFPWriter(MeshWriter): gcode.write(gcode_textio.getvalue().encode("UTF-8")) archive.addRelation(virtual_path = "/3D/model.gcode", relation_type = "http://schemas.ultimaker.org/package/2018/relationships/gcode") - self._createSnapshot() - - # Store the thumbnail. - if self._snapshot: + # Attempt to store the thumbnail, if any: + backend = CuraApplication.getInstance().getBackend() + snapshot = None if getattr(backend, "getLatestSnapshot", None) is None else backend.getLatestSnapshot() + if snapshot: archive.addContentType(extension = "png", mime_type = "image/png") thumbnail = archive.getStream("/Metadata/thumbnail.png") thumbnail_buffer = QBuffer() thumbnail_buffer.open(QBuffer.ReadWrite) - thumbnail_image = self._snapshot - thumbnail_image.save(thumbnail_buffer, "PNG") + snapshot.save(thumbnail_buffer, "PNG") thumbnail.write(thumbnail_buffer.data()) archive.addRelation(virtual_path = "/Metadata/thumbnail.png", relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail", origin = "/3D/model.gcode") else: - Logger.log("d", "Thumbnail not created, cannot save it") + Logger.log("w", "Thumbnail not created, cannot save it") # Store the material. application = CuraApplication.getInstance() diff --git a/plugins/UM3NetworkPrinting/src/ExportFileJob.py b/plugins/UM3NetworkPrinting/src/ExportFileJob.py index 6fde08cc5f..12f5a28877 100644 --- a/plugins/UM3NetworkPrinting/src/ExportFileJob.py +++ b/plugins/UM3NetworkPrinting/src/ExportFileJob.py @@ -1,3 +1,6 @@ +# Copyright (c) 2021 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from typing import List, Optional from UM.FileHandler.FileHandler import FileHandler diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 70e702d0bf..ce0bb06d8d 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -151,7 +151,7 @@ class XmlMaterialProfile(InstanceContainer): "version": self.CurrentFdmMaterialVersion}) ## Begin Metadata Block - builder.start("metadata") # type: ignore + builder.start("metadata", {}) # type: ignore metadata = copy.deepcopy(self.getMetaData()) # setting_version is derived from the "version" tag in the schema, so don't serialize it into a file @@ -165,21 +165,21 @@ class XmlMaterialProfile(InstanceContainer): properties = metadata.pop("properties", {}) ## Begin Name Block - builder.start("name") # type: ignore + builder.start("name", {}) # type: ignore - builder.start("brand") # type: ignore + builder.start("brand", {}) # type: ignore builder.data(metadata.pop("brand", "")) builder.end("brand") - builder.start("material") # type: ignore + builder.start("material", {}) # type: ignore builder.data(metadata.pop("material", "")) builder.end("material") - builder.start("color") # type: ignore + builder.start("color", {}) # type: ignore builder.data(metadata.pop("color_name", "")) builder.end("color") - builder.start("label") # type: ignore + builder.start("label", {}) # type: ignore builder.data(self.getName()) builder.end("label") @@ -190,7 +190,7 @@ class XmlMaterialProfile(InstanceContainer): key_to_use = key if key in self._metadata_tags_that_have_cura_namespace: key_to_use = "cura:" + key_to_use - builder.start(key_to_use) # type: ignore + builder.start(key_to_use, {}) # type: ignore if value is not None: #Nones get handled well by the builder. #Otherwise the builder always expects a string. #Deserialize expects the stringified version. @@ -202,10 +202,10 @@ class XmlMaterialProfile(InstanceContainer): ## End Metadata Block ## Begin Properties Block - builder.start("properties") # type: ignore + builder.start("properties", {}) # type: ignore for key, value in properties.items(): - builder.start(key) # type: ignore + builder.start(key, {}) # type: ignore builder.data(value) builder.end(key) @@ -213,7 +213,7 @@ class XmlMaterialProfile(InstanceContainer): ## End Properties Block ## Begin Settings Block - builder.start("settings") # type: ignore + builder.start("settings", {}) # type: ignore if self.getMetaDataEntry("definition") == "fdmprinter": for instance in self.findInstances(): @@ -258,7 +258,7 @@ class XmlMaterialProfile(InstanceContainer): product = product_name break - builder.start("machine") # type: ignore + builder.start("machine", {}) # type: ignore builder.start("machine_identifier", { "manufacturer": container.getMetaDataEntry("machine_manufacturer", definition_metadata.get("manufacturer", "Unknown")), diff --git a/resources/definitions/bibo2_dual.def.json b/resources/definitions/bibo2_dual.def.json index b9b1164e9d..8c6dc4ec76 100644 --- a/resources/definitions/bibo2_dual.def.json +++ b/resources/definitions/bibo2_dual.def.json @@ -71,7 +71,7 @@ "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z2.0 F400 ;move the platform down 15mm\nT0\nG92 E0\nG28\nG1 Y0 F1200 E0\nG92 E0\nM117 BIBO Printing..." + "default_value": "M104 T0 165\nM104 T1 165\nM109 T{initial_extruder_nr} S{material_print_temperature_layer_0, initial_extruder_nr}\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z2.0 F400 ;move the platform down 2mm\nT0\nG92 E0\nG28\nG1 Y0 F1200 E0\nG92 E0\nT{initial_extruder_nr}\nM117 BIBO Printing..." }, "machine_end_gcode": { "default_value": ";End GCode\nM104 T0 S0 ;extruder heater off\nM104 T1 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91\nG1 Z1 F100 ;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-2 X-20 Y-20 F300 ;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" diff --git a/resources/definitions/cubicon_style_neo_a22.def.json b/resources/definitions/cubicon_style_neo_a22.def.json index 95d6b5e933..01763524a4 100644 --- a/resources/definitions/cubicon_style_neo_a22.def.json +++ b/resources/definitions/cubicon_style_neo_a22.def.json @@ -22,7 +22,7 @@ "default_value": "Cubicon Style Neo-A22" }, "machine_start_gcode": { - "default_value": "M911 Style Neo-A22\nM201 X400 Y400\nM202 X400 Y400\nG28 ; Home\nG1 Z15.0 F6000 ;move the platform down 15mm\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0" + "default_value": "M911 Style Neo-A22\nM201 X400 Y400\nM202 X400 Y400\nG28 ; Home\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0" }, "machine_width": { "default_value": 220 diff --git a/resources/definitions/cubicon_style_neo_a31.def.json b/resources/definitions/cubicon_style_neo_a31.def.json new file mode 100644 index 0000000000..d41b6fc17e --- /dev/null +++ b/resources/definitions/cubicon_style_neo_a31.def.json @@ -0,0 +1,40 @@ +{ + "version": 2, + "name": "Cubicon Style Neo-A31", + "inherits": "cubicon_common", + "metadata": { + "author": "Cubicon R&D Center", + "manufacturer": "Cubicon", + "visible": true, + "file_formats": "text/x-gcode", + "supports_usb_connection": false, + "machine_extruder_trains": { + "0": "cubicon_style_neo_a31_extruder_0" + }, + "platform_offset": [ + 0, + 0, + 0 + ] + }, + "overrides": { + "machine_name": { + "default_value": "Cubicon Style Neo-A31" + }, + "machine_start_gcode": { + "default_value": "M911 Style Neo-A31\nM201 X400 Y400\nM202 X400 Y400\nG28 ; Home\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0" + }, + "machine_width": { + "default_value": 310 + }, + "machine_depth": { + "default_value": 310 + }, + "machine_height": { + "default_value": 310 + }, + "material_bed_temp_wait":{ + "default_value": false + } + } +} diff --git a/resources/definitions/cubicon_style_plus_a15.def.json b/resources/definitions/cubicon_style_plus_a15.def.json index a55d5aa791..b7e3dfd123 100644 --- a/resources/definitions/cubicon_style_plus_a15.def.json +++ b/resources/definitions/cubicon_style_plus_a15.def.json @@ -22,7 +22,7 @@ "default_value": "Cubicon Style Plus-A15" }, "machine_start_gcode": { - "default_value": "M911 Style Plus-A15\nM201 X400 Y400\nM202 X400 Y400\nG28 ; Home\nG1 Z15.0 F6000 ;move the platform down 15mm\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0" + "default_value": "M911 Style Plus-A15\nM201 X400 Y400\nM202 X400 Y400\nG28 ; Home\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0" }, "machine_width": { "default_value": 150 diff --git a/resources/definitions/eryone_er20.def.json b/resources/definitions/eryone_er20.def.json new file mode 100644 index 0000000000..236ef63188 --- /dev/null +++ b/resources/definitions/eryone_er20.def.json @@ -0,0 +1,241 @@ +{ + "version": 2, + "name": "Eryone ER20", + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "Eryone3d", + "manufacturer": "Eryone", + "file_formats": "text/x-gcode", + "platform": "eryone_er20_plateform.stl", + "has_machine_quality": true, + "preferred_quality_type": "high", + "machine_extruder_trains": + { + "0": "eryone_er20_extruder_0" + } + }, + + "overrides": { + "machine_name": { + "default_value": "Eryone ER20" + }, + "machine_heated_bed": { + "default_value": true + }, + "machine_width": { + "default_value": 250 + }, + "machine_height": { + "default_value": 200 + }, + "machine_depth": { + "default_value": 220 + }, + "machine_center_is_zero": { + "default_value": false + }, + "machine_gcode_flavor": { + "default_value": "RepRap (Marlin/Sprinter)" + }, + "machine_head_with_fans_polygon": { + "default_value": [ + [-10, -10], + [-10, 10], + [10, 10], + [10, -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" + }, + "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" + }, + "material_print_temperature": { + "value": 205 + }, + "material_print_temperature_layer_0": { + "value": 215 + }, + "material_initial_print_temperature": { + "value": 205 + }, + "material_final_print_temperature": { + "value": 205 + }, + "acceleration_enabled": { + "value": true + }, + "acceleration_travel": { + "value": 1800 + }, + "adhesion_type": { + "value": "'brim'" + }, + "brim_width": { + "value": 5 + }, + "cool_fan_full_at_height": { + "value": 0.5 + }, + "cool_fan_speed": { + "value": 100 + }, + "cool_fan_speed_0": { + "value": 100 + }, + "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": "'grid'" + }, + "infill_sparse_density": { + "value": 20 + }, + "initial_layer_line_width_factor": { + "value": 105 + }, + "infill_before_walls": { + "value": false + }, + "material_bed_temperature": { + "value": 60 + }, + "material_bed_temperature_layer_0": { + "value": 65 + }, + "optimize_wall_printing_order": { + "default_value": true + }, + "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 + }, + "retraction_speed": { + "default_value": 85, + "maximum_value_warning": 100 + }, + "retraction_retract_speed": { + "maximum_value_warning": 130 + }, + "retraction_prime_speed": { + "value": "math.ceil(retraction_speed * 0.4)", + "maximum_value_warning": 130 + }, + "retraction_combing": { + "value": "'noskin'" + }, + "skin_overlap": { + "value": 10 + }, + "skirt_brim_speed": { + "value": 40 + }, + "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": "150" + }, + "speed_layer_0": { + "value": "20" + }, + "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": { + "value": 3 + }, + "wall_thickness": { + "value": "1.2" + }, + "bottom_layers": { + "value": "4" + }, + "bottom_thickness":{ + "value": "layer_height * 4" + }, + "top_thickness":{ + "value": "layer_height * 5" + }, + "top_layers": { + "value": "5" + }, + "z_seam_type": { + "value": "'shortest'" + }, + "z_seam_corner": { + "value": "'z_seam_corner_inner'" + } + } +} diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 63c7b25b0b..458c97af00 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -485,7 +485,7 @@ "machine_use_extruder_offset_to_offset_coords": { "label": "Offset with Extruder", - "description": "Apply the extruder offset to the coordinate system.", + "description": "Apply the extruder offset to the coordinate system. Affects all extruders.", "type": "bool", "default_value": true, "settable_per_mesh": false, @@ -977,7 +977,7 @@ }, "shell": { - "label": "Shell", + "label": "Walls", "icon": "category_shell", "description": "Shell", "type": "category", @@ -1066,184 +1066,6 @@ "limit_to_extruder": "wall_0_extruder_nr", "settable_per_mesh": true }, - "roofing_extruder_nr": - { - "label": "Top Surface Skin Extruder", - "description": "The extruder train used for printing the top most skin. This is used in multi-extrusion.", - "type": "optional_extruder", - "default_value": "-1", - "value": "top_bottom_extruder_nr", - "settable_per_mesh": false, - "settable_per_extruder": false, - "settable_per_meshgroup": true, - "settable_globally": true, - "enabled": "extruders_enabled_count > 1 and max(extruderValues('roofing_layer_count')) > 0 and max(extruderValues('top_layers')) > 0" - }, - "roofing_layer_count": - { - "label": "Top Surface Skin Layers", - "description": "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces.", - "default_value": 0, - "minimum_value": "0", - "maximum_value_warning": "top_layers - 1", - "type": "int", - "value": "0", - "limit_to_extruder": "roofing_extruder_nr", - "settable_per_mesh": true, - "enabled": "top_layers > 0" - }, - "top_bottom_extruder_nr": - { - "label": "Top/Bottom Extruder", - "description": "The extruder train used for printing the top and bottom skin. This is used in multi-extrusion.", - "type": "optional_extruder", - "default_value": "-1", - "settable_per_mesh": false, - "settable_per_extruder": false, - "settable_per_meshgroup": true, - "settable_globally": true, - "enabled": "extruders_enabled_count > 1" - }, - "top_bottom_thickness": - { - "label": "Top/Bottom Thickness", - "description": "The thickness of the top/bottom layers in the print. This value divided by the layer height defines the number of top/bottom layers.", - "unit": "mm", - "default_value": 0.8, - "minimum_value": "0", - "minimum_value_warning": "0.6", - "maximum_value": "machine_height", - "type": "float", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true, - "children": - { - "top_thickness": - { - "label": "Top Thickness", - "description": "The thickness of the top layers in the print. This value divided by the layer height defines the number of top layers.", - "unit": "mm", - "default_value": 0.8, - "minimum_value": "0", - "minimum_value_warning": "0.2 + resolveOrValue('layer_height')", - "maximum_value": "machine_height", - "type": "float", - "value": "top_bottom_thickness", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true, - "children": - { - "top_layers": - { - "label": "Top Layers", - "description": "The number of top layers. When calculated by the top thickness, this value is rounded to a whole number.", - "default_value": 8, - "minimum_value": "0", - "maximum_value_warning": "100", - "type": "int", - "minimum_value_warning": "2", - "value": "0 if infill_sparse_density == 100 else math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - } - } - }, - "bottom_thickness": - { - "label": "Bottom Thickness", - "description": "The thickness of the bottom layers in the print. This value divided by the layer height defines the number of bottom layers.", - "unit": "mm", - "default_value": 0.6, - "minimum_value": "0", - "minimum_value_warning": "0.2 + resolveOrValue('layer_height')", - "type": "float", - "value": "top_bottom_thickness", - "maximum_value": "machine_height", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true, - "children": - { - "bottom_layers": - { - "label": "Bottom Layers", - "description": "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number.", - "minimum_value": "0", - "minimum_value_warning": "2", - "default_value": 6, - "type": "int", - "value": "999999 if infill_sparse_density == 100 else math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "initial_bottom_layers": - { - "label": "Initial Bottom Layers", - "description": "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number.", - "minimum_value": "0", - "minimum_value_warning": "2", - "default_value": 6, - "type": "int", - "value": "bottom_layers", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - } - } - } - } - }, - "top_bottom_pattern": - { - "label": "Top/Bottom Pattern", - "description": "The pattern of the top/bottom layers.", - "type": "enum", - "options": - { - "lines": "Lines", - "concentric": "Concentric", - "zigzag": "Zig Zag" - }, - "default_value": "lines", - "enabled": "top_layers > 0 or bottom_layers > 0", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "top_bottom_pattern_0": - { - "label": "Bottom Pattern Initial Layer", - "description": "The pattern on the bottom of the print on the first layer.", - "type": "enum", - "options": - { - "lines": "Lines", - "concentric": "Concentric", - "zigzag": "Zig Zag" - }, - "default_value": "lines", - "enabled": "top_layers > 0 or bottom_layers > 0", - "value": "top_bottom_pattern", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "connect_skin_polygons": - { - "label": "Connect Top/Bottom Polygons", - "description": "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality.", - "type": "bool", - "default_value": false, - "enabled": "((top_layers > 0 or bottom_layers > 0) and top_bottom_pattern == 'concentric') or (roofing_layer_count > 0 and roofing_pattern == 'concentric')", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "skin_angles": - { - "label": "Top/Bottom Line Directions", - "description": "A list of integer line directions to use when the top/bottom layers use the lines or zig zag pattern. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees).", - "type": "[int]", - "default_value": "[ ]", - "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, "wall_0_inset": { "label": "Outer Wall Inset", @@ -1495,6 +1317,194 @@ "enabled": "z_seam_type == 'back'", "limit_to_extruder": "wall_0_extruder_nr", "settable_per_mesh": true + } + } + }, + "top_bottom": + { + "label": "Top/Bottom", + "icon": "category_topbottom", + "description": "Top/Bottom", + "type": "category", + "children": + { + "roofing_extruder_nr": + { + "label": "Top Surface Skin Extruder", + "description": "The extruder train used for printing the top most skin. This is used in multi-extrusion.", + "type": "optional_extruder", + "default_value": "-1", + "value": "top_bottom_extruder_nr", + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": true, + "settable_globally": true, + "enabled": "extruders_enabled_count > 1 and max(extruderValues('roofing_layer_count')) > 0 and max(extruderValues('top_layers')) > 0" + }, + "roofing_layer_count": + { + "label": "Top Surface Skin Layers", + "description": "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces.", + "default_value": 0, + "minimum_value": "0", + "maximum_value_warning": "top_layers - 1", + "type": "int", + "value": "0", + "limit_to_extruder": "roofing_extruder_nr", + "settable_per_mesh": true, + "enabled": "top_layers > 0" + }, + "top_bottom_extruder_nr": + { + "label": "Top/Bottom Extruder", + "description": "The extruder train used for printing the top and bottom skin. This is used in multi-extrusion.", + "type": "optional_extruder", + "default_value": "-1", + "settable_per_mesh": false, + "settable_per_extruder": false, + "settable_per_meshgroup": true, + "settable_globally": true, + "enabled": "extruders_enabled_count > 1" + }, + "top_bottom_thickness": + { + "label": "Top/Bottom Thickness", + "description": "The thickness of the top/bottom layers in the print. This value divided by the layer height defines the number of top/bottom layers.", + "unit": "mm", + "default_value": 0.8, + "minimum_value": "0", + "minimum_value_warning": "0.6", + "maximum_value": "machine_height", + "type": "float", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true, + "children": + { + "top_thickness": + { + "label": "Top Thickness", + "description": "The thickness of the top layers in the print. This value divided by the layer height defines the number of top layers.", + "unit": "mm", + "default_value": 0.8, + "minimum_value": "0", + "minimum_value_warning": "0.2 + resolveOrValue('layer_height')", + "maximum_value": "machine_height", + "type": "float", + "value": "top_bottom_thickness", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true, + "children": + { + "top_layers": + { + "label": "Top Layers", + "description": "The number of top layers. When calculated by the top thickness, this value is rounded to a whole number.", + "default_value": 8, + "minimum_value": "0", + "maximum_value_warning": "100", + "type": "int", + "minimum_value_warning": "2", + "value": "0 if infill_sparse_density == 100 else math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + } + } + }, + "bottom_thickness": + { + "label": "Bottom Thickness", + "description": "The thickness of the bottom layers in the print. This value divided by the layer height defines the number of bottom layers.", + "unit": "mm", + "default_value": 0.6, + "minimum_value": "0", + "minimum_value_warning": "0.2 + resolveOrValue('layer_height')", + "type": "float", + "value": "top_bottom_thickness", + "maximum_value": "machine_height", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true, + "children": + { + "bottom_layers": + { + "label": "Bottom Layers", + "description": "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number.", + "minimum_value": "0", + "minimum_value_warning": "2", + "default_value": 6, + "type": "int", + "value": "999999 if infill_sparse_density == 100 else math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "initial_bottom_layers": + { + "label": "Initial Bottom Layers", + "description": "The number of initial bottom layers, from the build-plate upwards. When calculated by the bottom thickness, this value is rounded to a whole number.", + "minimum_value": "0", + "minimum_value_warning": "2", + "default_value": 6, + "type": "int", + "value": "bottom_layers", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + } + } + } + } + }, + "top_bottom_pattern": + { + "label": "Top/Bottom Pattern", + "description": "The pattern of the top/bottom layers.", + "type": "enum", + "options": + { + "lines": "Lines", + "concentric": "Concentric", + "zigzag": "Zig Zag" + }, + "default_value": "lines", + "enabled": "top_layers > 0 or bottom_layers > 0", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "top_bottom_pattern_0": + { + "label": "Bottom Pattern Initial Layer", + "description": "The pattern on the bottom of the print on the first layer.", + "type": "enum", + "options": + { + "lines": "Lines", + "concentric": "Concentric", + "zigzag": "Zig Zag" + }, + "default_value": "lines", + "enabled": "top_layers > 0 or bottom_layers > 0", + "value": "top_bottom_pattern", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "connect_skin_polygons": + { + "label": "Connect Top/Bottom Polygons", + "description": "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality.", + "type": "bool", + "default_value": false, + "enabled": "((top_layers > 0 or bottom_layers > 0) and top_bottom_pattern == 'concentric') or (initial_bottom_layers > 0 and top_bottom_pattern_0 == 'concentric') or (roofing_layer_count > 0 and roofing_pattern == 'concentric')", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "skin_angles": + { + "label": "Top/Bottom Line Directions", + "description": "A list of integer line directions to use when the top/bottom layers use the lines or zig zag pattern. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees).", + "type": "[int]", + "default_value": "[ ]", + "enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern != 'concentric'", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true }, "skin_no_small_gaps_heuristic": { @@ -1666,6 +1676,123 @@ "settable_per_mesh": true } } + }, + "skin_preshrink": + { + "label": "Skin Removal Width", + "description": "The largest width of skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing top/bottom skin at slanted surfaces in the model.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", + "minimum_value": "0", + "maximum_value_warning": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", + "enabled": "top_layers > 0 or bottom_layers > 0", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true, + "children": + { + "top_skin_preshrink": + { + "label": "Top Skin Removal Width", + "description": "The largest width of top skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing top skin at slanted surfaces in the model.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "skin_preshrink", + "maximum_value_warning": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", + "minimum_value": "0", + "enabled": "top_layers > 0 or bottom_layers > 0", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "bottom_skin_preshrink": + { + "label": "Bottom Skin Removal Width", + "description": "The largest width of bottom skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing bottom skin at slanted surfaces in the model.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "skin_preshrink", + "maximum_value_warning": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", + "minimum_value": "0", + "enabled": "top_layers > 0 or bottom_layers > 0", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + } + } + }, + "expand_skins_expand_distance": + { + "label": "Skin Expand Distance", + "description": "The distance the skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the walls on neighboring layers adhere better to the skin. Lower values save amount of material used.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", + "minimum_value": "-skin_preshrink", + "limit_to_extruder": "top_bottom_extruder_nr", + "enabled": "top_layers > 0 or bottom_layers > 0", + "settable_per_mesh": true, + "children": + { + "top_skin_expand_distance": + { + "label": "Top Skin Expand Distance", + "description": "The distance the top skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the walls on the layer above adhere better to the skin. Lower values save amount of material used.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "expand_skins_expand_distance", + "minimum_value": "-top_skin_preshrink", + "enabled": "top_layers > 0 or bottom_layers > 0", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + }, + "bottom_skin_expand_distance": + { + "label": "Bottom Skin Expand Distance", + "description": "The distance the bottom skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the skin adhere better to the walls on the layer below. Lower values save amount of material used.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "expand_skins_expand_distance", + "minimum_value": "-bottom_skin_preshrink", + "enabled": "top_layers > 0 or bottom_layers > 0", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + } + } + }, + "max_skin_angle_for_expansion": + { + "label": "Maximum Skin Angle for Expansion", + "description": "Top and/or bottom surfaces of your object with an angle larger than this setting, won't have their top/bottom skin expanded. This avoids expanding the narrow skin areas that are created when the model surface has a near vertical slope. An angle of 0° is horizontal and will cause no skin to be expanded, while an angle of 90° is vertical and will cause all skin to be expanded.", + "unit": "°", + "type": "float", + "minimum_value": "0", + "minimum_value_warning": "2", + "maximum_value": "90", + "default_value": 90, + "enabled": "(top_layers > 0 or bottom_layers > 0) and (top_skin_expand_distance > 0 or bottom_skin_expand_distance > 0)", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true, + "children": + { + "min_skin_width_for_expansion": + { + "label": "Minimum Skin Width for Expansion", + "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", + "unit": "mm", + "type": "float", + "default_value": 0, + "value": "top_layers * layer_height / math.tan(math.radians(max_skin_angle_for_expansion))", + "minimum_value": "0", + "enabled": "(top_layers > 0 or bottom_layers > 0) and (top_skin_expand_distance > 0 or bottom_skin_expand_distance > 0)", + "limit_to_extruder": "top_bottom_extruder_nr", + "settable_per_mesh": true + } + } } } }, @@ -1975,123 +2102,6 @@ "limit_to_extruder": "infill_extruder_nr", "settable_per_mesh": true }, - "skin_preshrink": - { - "label": "Skin Removal Width", - "description": "The largest width of skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing top/bottom skin at slanted surfaces in the model.", - "unit": "mm", - "type": "float", - "default_value": 1, - "value": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", - "minimum_value": "0", - "maximum_value_warning": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", - "enabled": "top_layers > 0 or bottom_layers > 0", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true, - "children": - { - "top_skin_preshrink": - { - "label": "Top Skin Removal Width", - "description": "The largest width of top skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing top skin at slanted surfaces in the model.", - "unit": "mm", - "type": "float", - "default_value": 1, - "value": "skin_preshrink", - "maximum_value_warning": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", - "minimum_value": "0", - "enabled": "top_layers > 0 or bottom_layers > 0", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "bottom_skin_preshrink": - { - "label": "Bottom Skin Removal Width", - "description": "The largest width of bottom skin areas which are to be removed. Every skin area smaller than this value will disappear. This can help in limiting the amount of time and material spent on printing bottom skin at slanted surfaces in the model.", - "unit": "mm", - "type": "float", - "default_value": 1, - "value": "skin_preshrink", - "maximum_value_warning": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", - "minimum_value": "0", - "enabled": "top_layers > 0 or bottom_layers > 0", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - } - } - }, - "expand_skins_expand_distance": - { - "label": "Skin Expand Distance", - "description": "The distance the skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the walls on neighboring layers adhere better to the skin. Lower values save amount of material used.", - "unit": "mm", - "type": "float", - "default_value": 1, - "value": "wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x", - "minimum_value": "-skin_preshrink", - "limit_to_extruder": "top_bottom_extruder_nr", - "enabled": "top_layers > 0 or bottom_layers > 0", - "settable_per_mesh": true, - "children": - { - "top_skin_expand_distance": - { - "label": "Top Skin Expand Distance", - "description": "The distance the top skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the walls on the layer above adhere better to the skin. Lower values save amount of material used.", - "unit": "mm", - "type": "float", - "default_value": 1, - "value": "expand_skins_expand_distance", - "minimum_value": "-top_skin_preshrink", - "enabled": "top_layers > 0 or bottom_layers > 0", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - }, - "bottom_skin_expand_distance": - { - "label": "Bottom Skin Expand Distance", - "description": "The distance the bottom skins are expanded into the infill. Higher values makes the skin attach better to the infill pattern and makes the skin adhere better to the walls on the layer below. Lower values save amount of material used.", - "unit": "mm", - "type": "float", - "default_value": 1, - "value": "expand_skins_expand_distance", - "minimum_value": "-bottom_skin_preshrink", - "enabled": "top_layers > 0 or bottom_layers > 0", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - } - } - }, - "max_skin_angle_for_expansion": - { - "label": "Maximum Skin Angle for Expansion", - "description": "Top and/or bottom surfaces of your object with an angle larger than this setting, won't have their top/bottom skin expanded. This avoids expanding the narrow skin areas that are created when the model surface has a near vertical slope. An angle of 0° is horizontal and will cause no skin to be expanded, while an angle of 90° is vertical and will cause all skin to be expanded.", - "unit": "°", - "type": "float", - "minimum_value": "0", - "minimum_value_warning": "2", - "maximum_value": "90", - "default_value": 90, - "enabled": "(top_layers > 0 or bottom_layers > 0) and (top_skin_expand_distance > 0 or bottom_skin_expand_distance > 0)", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true, - "children": - { - "min_skin_width_for_expansion": - { - "label": "Minimum Skin Width for Expansion", - "description": "Skin areas narrower than this are not expanded. This avoids expanding the narrow skin areas that are created when the model surface has a slope close to the vertical.", - "unit": "mm", - "type": "float", - "default_value": 0, - "value": "top_layers * layer_height / math.tan(math.radians(max_skin_angle_for_expansion))", - "minimum_value": "0", - "enabled": "(top_layers > 0 or bottom_layers > 0) and (top_skin_expand_distance > 0 or bottom_skin_expand_distance > 0)", - "limit_to_extruder": "top_bottom_extruder_nr", - "settable_per_mesh": true - } - } - }, "skin_edge_support_thickness": { "label": "Skin Edge Support Thickness", @@ -2960,7 +2970,7 @@ "speed_layer_0": { "label": "Initial Layer Speed", - "description": "The speed for the initial layer. A lower value is advised to improve adhesion to the build plate.", + "description": "The speed for the initial layer. A lower value is advised to improve adhesion to the build plate. Does not affect the build plate adhesion structures themselves, like brim and raft.", "unit": "mm/s", "type": "float", "default_value": 30, @@ -6518,6 +6528,17 @@ "default_value": 50, "enabled": "conical_overhang_enabled" }, + "conical_overhang_hole_size": + { + "label": "Maximum Overhang Hole Area", + "description": "The maximum area of a hole in the base of the model before it's removed by Make Overhang Printable. Holes smaller than this will be retained. A value of 0 mm² will fill all holes in the models base.", + "unit": "mm²", + "type": "float", + "minimum_value": "0", + "minimum_value_warning": "0", + "default_value": 0, + "enabled": "conical_overhang_enabled" + }, "coasting_enable": { "label": "Enable Coasting", diff --git a/resources/definitions/maker_made_300x.def.json b/resources/definitions/maker_made_300x.def.json new file mode 100644 index 0000000000..9651aaf5f3 --- /dev/null +++ b/resources/definitions/maker_made_300x.def.json @@ -0,0 +1,150 @@ +{ + "version": 2, + "name": "Maker Made 300x", + "inherits": "fdmprinter", + "metadata": { + "visible": true, + "author": "DragonJe", + "manufacturer": "Maker Made", + "file_formats": "text/x-gcode", + "platform_offset": [0, 0, 0], + "has_materials": true, + "has_variants": false, + "preferred_quality_type": "normal", + "has_machine_quality": false, + "preferred_material": "generic_pla", + "machine_extruder_trains": + { + "0": "maker_made_300x_extruder_0" + } + }, + + "overrides": { + "machine_name": {"default_value": "Maker Made 300x"}, + "machine_width": {"default_value": 300}, + "machine_height": {"default_value": 400}, + "machine_depth": {"default_value": 300}, + "machine_head_with_fans_polygon": {"default_value": [[-30, 34],[-30, -32],[30, -32],[30, 34]]}, + "gantry_height": {"value": "30"}, + "machine_heated_bed": {"default_value": true}, + "material_diameter": {"default_value": 1.75}, + "machine_gcode_flavor": {"default_value": " RepRap (Marlin/Sprinter)"}, + "machine_start_gcode": {"default_value": "G28 ;Home\n G29 ;Auto Level\n G92 E0 ;Reset Extruder\n G1 Z5.0 F3000 ;Move Z Axis up\n G1 X25 Y295.0 Z0.28 F3000.0 ;Move to extrude\n G1 X250 Y295.0 Z0.28 F1500.0 E15 ;Draw the first line\n G1 X25 Y290.0 Z0.28 F3000.0 ;Move to side a little\n G1 X250 Y290.0 Z0.28 F1500.0 E30 ;Draw the second line\n G92 E0 ;Reset Extruder\n G1 Z5.0 F3000 ;Move Z Axis up" }, + "machine_end_gcode": {"default_value": "M104 S0\n M140 S0\n ;Retract the filament\n G92 E1\n G1 E-1 F300\n G28 X0 Y0\n G1 Y300 F3000 ;Move bed forward\n M84" }, + + "layer_height": {"value": 0.16}, + "layer_height_0": {"value": 0.32}, + "line_width": {"value": 0.4}, + "wall_line_width_0": {"value": 0.4}, + "initial_layer_line_width_factor": {"value": 100}, + "wall_thickness": {"value": 0.8}, + "wall_0_wipe_dist": {"value": 0.2}, + "roofing_layer_count": {"value": 1}, + "top_bottom_thickness": {"value": 0.6}, + "top_thickness": {"value": 0.8}, + "top_layers": {"value": 5}, + "bottom_thickness": {"value": 0.6}, + "bottom_layers": {"value": 3}, + "top_bottom_pattern": {"value": "'lines'" }, + "top_bottom_pattern_0": {"value": "'lines'" }, + "wall_0_inset": {"value": 0}, + "optimize_wall_printing_order": {"value": false }, + "outer_inset_first": {"value": false }, + "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}, + "skin_no_small_gaps_heuristic": {"value": true }, + "skin_outline_count": {"value": 1}, + "ironing_enabled": {"value": false }, + "infill_sparse_density": {"value": 20 }, + "zig_zaggify_infill": {"value": false }, + "infill_multiplier": {"value": 1}, + "infill_wall_line_count": {"value": 0}, + "infill_overlap": {"value": 10}, + "skin_overlap": {"value": 5}, + "infill_wipe_dist": {"value": 0.1}, + "gradual_infill_steps": {"value": 0}, + "infill_before_walls": {"value": false }, + "infill_support_enabled": {"value": false }, + "max_skin_angle_for_expansion": {"value": 90}, + "default_material_print_temperature": {"value": 220}, + "material_print_temperature": {"value": 220}, + "material_print_temperature_layer_0": {"value": 220}, + "material_initial_print_temperature": {"value": 220}, + "material_final_print_temperature": {"value": 220}, + "default_material_bed_temperature": {"value": 50}, + "material_bed_temperature": {"value": 50}, + "material_flow": {"value": 100}, + "retraction_enable": {"value": true }, + "retract_at_layer_change": {"value": false }, + "retraction_amount": {"value": 5}, + "retraction_speed": {"value": 45}, + "retraction_extra_prime_amount": {"value": 0}, + "retraction_min_travel": {"value": 0.8}, + "retraction_count_max": {"value": 90}, + "retraction_extrusion_window": {"value": 5}, + "limit_support_retractions": {"value": true }, + "switch_extruder_retraction_amount": {"value": 16}, + "switch_extruder_retraction_speeds": {"value": 20}, + "speed_print": {"value": 50}, + "speed_travel": {"value": 150}, + "speed_layer_0": {"value": 10}, + "speed_travel_layer_0": {"value": 50}, + "machine_max_feedrate_z": {"value": 0}, + "speed_slowdown_layers": {"value": 2}, + "speed_equalize_flow_enabled": {"value": false }, + "acceleration_enabled": {"value": false }, + "acceleration_roofing": {"value": 3000 }, + "jerk_enabled": {"value": false }, + "retraction_combing": {"value": "'within infill'" }, + "travel_retract_before_outer_wall": {"value": false }, + "travel_avoid_other_parts": {"value": true }, + "retraction_hop_enabled": {"value": false }, + "cool_fan_enabled": {"value": true }, + "cool_fan_speed": {"value": 100}, + "cool_fan_speed_0": {"value": 0}, + "cool_fan_full_at_height": {"value": 0.32 }, + "cool_lift_head": {"value": false }, + "support_enable": {"value": true }, + "support_type": {"value": "'everywhere'" }, + "support_angle": {"value": "50"}, + "support_pattern": {"value": "'grid'"}, + "support_wall_count": {"value": 0}, + "zig_zaggify_support": {"value": false }, + "support_infill_rate": {"value": "15 if support_enable else 0"}, + "support_brim_enable": {"value": true }, + "support_brim_line_count": {"value": 5}, + "support_z_distance": {"value": 0.2}, + "support_xy_distance": {"value": 0.7}, + "support_xy_distance_overhang": {"value": 0.2}, + "support_bottom_stair_step_height": {"value": 0.3}, + "support_bottom_stair_step_width": {"value": 5.0}, + "support_join_distance": {"value": 2.0}, + "support_offset": {"value": 0.2}, + "gradual_support_infill_steps": {"value": 0}, + "support_roof_enable": {"value": true }, + "support_bottom_enable": {"value": false }, + "support_roof_height": {"value": 0.45}, + "support_roof_density": {"value": 45}, + "support_roof_pattern": {"value": "'lines'" }, + "support_fan_enable": {"value": false }, + "support_use_towers": {"value": true }, + "support_tower_diameter": {"value": 3}, + "support_tower_roof_angle": {"value": "65"}, + "adhesion_type": {"value": "'skirt'"}, + "skirt_line_count": {"value": 2}, + "skirt_gap": {"value": 3}, + "meshfix_union_all": {"value": true }, + "meshfix_union_all_remove_holes": {"value": false }, + "meshfix_extensive_stitching": {"value": false }, + "meshfix_keep_open_polygons": {"value": false }, + "multiple_mesh_overlap": {"value": "0.16"}, + "carve_multiple_volumes": {"value": false } + } +} diff --git a/resources/definitions/mingda_base.def.json b/resources/definitions/mingda_base.def.json new file mode 100644 index 0000000000..a7daa76d97 --- /dev/null +++ b/resources/definitions/mingda_base.def.json @@ -0,0 +1,264 @@ +{ + "name": "MINGDA Base Printer", + "version": 2, + "inherits": "fdmprinter", + "metadata": { + "visible": false, + "author": "cataclism", + "manufacturer": "MINGDA", + "file_formats": "text/x-gcode", + "first_start_actions": ["MachineSettingsAction"], + + "machine_extruder_trains": { + "0": "mingda_base_extruder_0" + }, + + "has_materials": true, + "has_variants": true, + "has_machine_quality": true, + "variants_name": "Nozzle Size", + + "preferred_variant_name": "0.4mm Nozzle", + "preferred_quality_type": "standard", + "preferred_material": "generic_pla", + "exclude_materials": [ + "Vertex_Delta_ABS", + "Vertex_Delta_PET", + "Vertex_Delta_PLA", + "Vertex_Delta_TPU", + "chromatik_pla", + "dsm_arnitel2045_175", + "dsm_novamid1070_175", + "fabtotum_abs", + "fabtotum_nylon", + "fabtotum_pla", + "fabtotum_tpu", + "fiberlogy_hd_pla", + "filo3d_pla", + "filo3d_pla_green", + "filo3d_pla_red", + "generic_bam", + "generic_cffcpe", + "generic_cffpa", + "generic_cpe", + "generic_cpe_plus", + "generic_gffcpe", + "generic_gffpa", + "generic_hips", + "generic_nylon", + "generic_pc", + "generic_pp", + "generic_pva", + "generic_tough_pla", + "imade3d_petg_green", + "imade3d_petg_pink", + "imade3d_pla_green", + "imade3d_pla_pink", + "innofill_innoflex60_175", + "octofiber_pla", + "polyflex_pla", + "polymax_pla", + "polyplus_pla", + "polywood_pla", + "structur3d_dap100silicone", + "tizyx_abs", + "tizyx_pla", + "tizyx_pla_bois", + "ultimaker_abs_black", + "ultimaker_abs_blue", + "ultimaker_abs_green", + "ultimaker_abs_grey", + "ultimaker_abs_orange", + "ultimaker_abs_pearl-gold", + "ultimaker_abs_red", + "ultimaker_abs_silver-metallic", + "ultimaker_abs_white", + "ultimaker_abs_yellow", + "ultimaker_bam", + "ultimaker_cpe_black", + "ultimaker_cpe_blue", + "ultimaker_cpe_dark-grey", + "ultimaker_cpe_green", + "ultimaker_cpe_light-grey", + "ultimaker_cpe_plus_black", + "ultimaker_cpe_plus_transparent", + "ultimaker_cpe_plus_white", + "ultimaker_cpe_red", + "ultimaker_cpe_transparent", + "ultimaker_cpe_white", + "ultimaker_cpe_yellow", + "ultimaker_nylon_black", + "ultimaker_nylon_transparent", + "ultimaker_pc_black", + "ultimaker_pc_transparent", + "ultimaker_pc_white", + "ultimaker_pla_black", + "ultimaker_pla_blue", + "ultimaker_pla_green", + "ultimaker_pla_magenta", + "ultimaker_pla_orange", + "ultimaker_pla_pearl-white", + "ultimaker_pla_red", + "ultimaker_pla_silver-metallic", + "ultimaker_pla_transparent", + "ultimaker_pla_white", + "ultimaker_pla_yellow", + "ultimaker_pp_transparent", + "ultimaker_pva", + "ultimaker_tough_pla_black", + "ultimaker_tough_pla_green", + "ultimaker_tough_pla_red", + "ultimaker_tough_pla_white", + "ultimaker_tpu_black", + "ultimaker_tpu_blue", + "ultimaker_tpu_red", + "ultimaker_tpu_white", + "verbatim_bvoh_175", + "zyyx_pro_flex", + "zyyx_pro_pla" + ] + }, + "overrides": { + "machine_name": { "default_value": "MINGDA Base Printer" }, + "machine_start_gcode": { "default_value": "G28 ; home all axes\n M117 Purge extruder\n G92 E0 ; reset extruder\n G1 Z1.0 F3000 ; move z up little to prevent scratching of surface\n G1 X2 Y20 Z0.3 F5000.0 ; move to start-line position\n G1 X2 Y200.0 Z0.3 F1500.0 E15 ; draw 1st line\n G1 X2 Y200.0 Z0.4 F5000.0 ; move to side a little\n G1 X2 Y20 Z0.4 F1500.0 E30 ; draw 2nd line\n G92 E0 ; reset extruder\n G1 Z1.0 F3000 ; move z up little to prevent scratching of surface"}, + "machine_end_gcode": { "default_value": "G91; relative positioning\n G1 Z1.0 F3000 ; move z up little to prevent scratching of print\n G90; absolute positioning\n G1 X0 Y200 F1000 ; prepare for part removal\n M104 S0; turn off extruder\n M140 S0 ; turn off bed\n G1 X0 Y300 F1000 ; prepare for part removal\n M84 ; disable motors\n M106 S0 ; turn off fan" }, + + "machine_max_feedrate_x": { "value": 500 }, + "machine_max_feedrate_y": { "value": 500 }, + "machine_max_feedrate_z": { "value": 10 }, + "machine_max_feedrate_e": { "value": 50 }, + + "machine_max_acceleration_x": { "value": 500 }, + "machine_max_acceleration_y": { "value": 500 }, + "machine_max_acceleration_z": { "value": 100 }, + "machine_max_acceleration_e": { "value": 5000 }, + "machine_acceleration": { "value": 500 }, + + "machine_max_jerk_xy": { "value": 10 }, + "machine_max_jerk_z": { "value": 0.4 }, + "machine_max_jerk_e": { "value": 5 }, + + "machine_heated_bed": { "default_value": true }, + + "material_diameter": { "default_value": 1.75 }, + + "acceleration_print": { "value": 500 }, + "acceleration_travel": { "value": 500 }, + "acceleration_travel_layer_0": { "value": "acceleration_travel" }, + "acceleration_roofing": { "enabled": "acceleration_enabled and roofing_layer_count > 0 and top_layers > 0" }, + + "jerk_print": { "value": 8 }, + "jerk_travel": { "value": "jerk_print" }, + "jerk_travel_layer_0": { "value": "jerk_travel" }, + + "acceleration_enabled": { "value": false }, + "jerk_enabled": { "value": false }, + + "speed_print": { "value": 60.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_layer_0": { "value": 20.0 }, + "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" }, + "speed_z_hop": { "value": 5 }, + + "skirt_brim_speed": { "value": "speed_layer_0" }, + + "line_width": { "value": "machine_nozzle_size * 1.1" }, + + "optimize_wall_printing_order": { "value": true }, + + "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'" }, + + "infill_sparse_density": { "value": "15" }, + "infill_pattern": { "value": "'lines' if infill_sparse_density > 50 else 'cubic'" }, + "infill_before_walls": { "value": false }, + "infill_overlap": { "value": 30.0 }, + "skin_overlap": { "value": 10.0 }, + "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_speed": { + "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 + }, + + "retraction_hop_enabled": { "value": true }, + "retraction_hop": { "value": "layer_height*2" }, + "retraction_combing": { "value": "'off' if retraction_hop_enabled else 'infill'" }, + "retraction_combing_max_distance": { "value": 30 }, + "travel_avoid_other_parts": { "value": true }, + "travel_avoid_supports": { "value": true }, + "travel_retract_before_outer_wall": { "value": true }, + + "retraction_amount": { "value": 2 }, + "retraction_enable": { "value": true }, + "retraction_count_max": { "value": 100 }, + "retraction_extrusion_window": { "value": 10 }, + "retraction_min_travel": { "value": 1.5 }, + + "cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" }, + "cool_fan_enabled": { "value": true }, + "cool_min_layer_time": { "value": 10 }, + + "adhesion_type": { "value": "'none' if support_enable else 'skirt'" }, + "brim_replaces_support": { "value": false }, + "skirt_gap": { "value": 10.0 }, + "skirt_line_count": { "value": 4 }, + + "adaptive_layer_height_variation": { "value": 0.04 }, + "adaptive_layer_height_variation_step": { "value": 0.04 }, + + "meshfix_maximum_resolution": { "value": "0.05" }, + "meshfix_maximum_travel_resolution": { "value": "meshfix_maximum_resolution" }, + + "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" }, + "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_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_interface_height": { "value": "layer_height * 4" }, + "support_interface_density": { "value": 33.333 }, + "support_interface_pattern": { "value": "'grid'" }, + "support_interface_skip_height": { "value": 0.2 }, + "minimum_support_area": { "value": 2 }, + "minimum_interface_area": { "value": 10 }, + "top_bottom_thickness": {"value": "layer_height_0 + layer_height * 3" }, + "wall_thickness": {"value": "line_width * 2" } + + } +} diff --git a/resources/definitions/mingda_d2.def.json b/resources/definitions/mingda_d2.def.json new file mode 100644 index 0000000000..a20ff53db1 --- /dev/null +++ b/resources/definitions/mingda_d2.def.json @@ -0,0 +1,19 @@ +{ + "name": "MINGDA D2", + "version": 2, + "inherits": "mingda_base", + "overrides": { + "machine_name": { "default_value": "MINGDA D2" }, + "machine_width": { "default_value": 230 }, + "machine_depth": { "default_value": 230 }, + "machine_height": { "default_value": 260 }, + "gantry_height": { "value": 25 } + + }, + "metadata": { + "quality_definition": "mingda_base", + "visible": true, + "platform": "mingda_d2_base.stl", + "platform_offset": [ -205, -77, 65] + } +} diff --git a/resources/definitions/snapmaker2.def.json b/resources/definitions/snapmaker2.def.json new file mode 100644 index 0000000000..e4ad7e19df --- /dev/null +++ b/resources/definitions/snapmaker2.def.json @@ -0,0 +1,77 @@ +{ + "version": 2, + "name": "Snapmaker 2", + "inherits": "fdmprinter", + "metadata": { + "visible": false, + "manufacturer": "Snapmaker", + "file_formats": "text/x-gcode", + "machine_extruder_trains": { + "0": "snapmaker_extruder_0" + }, + "has_materials": true, + "has_machine_quality": true, + "preferred_quality_type": "normal", + "preferred_material": "generic_pla", + "exclude_materials": [ ] + }, + "overrides": { + "machine_name": { + "default_value": "Snapmaker" + }, + "machine_buildplate_type": { + "default_value": "aluminum" + }, + "machine_heated_bed": { + "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" + }, + "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" + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 + }, + "machine_max_acceleration_x": { + "default_value": 1000 + }, + "machine_max_acceleration_y": { + "default_value": 1000 + }, + "machine_max_acceleration_z": { + "default_value": 1000 + }, + "machine_max_acceleration_e": { + "default_value": 1000 + }, + "machine_acceleration": { + "default_value": 1000 + }, + "material_print_temp_prepend": { + "default_value": false + }, + "material_bed_temp_prepend": { + "default_value": false + }, + "default_material_print_temperature": { + "default_value": 205 + }, + "retraction_enable": { + "default_value": true + }, + "retraction_amount": { + "default_value": 5 + }, + "retraction_speed": { + "default_value": 60 + }, + "retract_at_layer_change": { + "default_value": false + } + } +} diff --git a/resources/definitions/snapmaker2_A150.def.json b/resources/definitions/snapmaker2_A150.def.json new file mode 100644 index 0000000000..8baea05016 --- /dev/null +++ b/resources/definitions/snapmaker2_A150.def.json @@ -0,0 +1,39 @@ +{ + "version": 2, + "name": "Snapmaker 2 A150", + "inherits": "snapmaker2", + "metadata": { + "visible": true, + "manufacturer": "Snapmaker", + "file_formats": "text/x-gcode", + "machine_extruder_trains": { + "0": "snapmaker_extruder_0" + }, + "quality_definition": "snapmaker2" + }, + "overrides": { + "machine_name": { + "default_value": "Snapmaker A150" + }, + "machine_width": { + "default_value": 160 + }, + "machine_depth": { + "default_value": 160 + }, + "machine_height": { + "default_value": 145 + }, + "machine_head_with_fans_polygon": { + "default_value": [ + [-67, 22], + [-67, -25], + [25.5, 22], + [25.5, -25] + ] + }, + "gantry_height": { + "value": 27 + } + } +} diff --git a/resources/definitions/snapmaker2_A250.def.json b/resources/definitions/snapmaker2_A250.def.json new file mode 100644 index 0000000000..a61d52c46f --- /dev/null +++ b/resources/definitions/snapmaker2_A250.def.json @@ -0,0 +1,39 @@ +{ + "version": 2, + "name": "Snapmaker 2 A250", + "inherits": "snapmaker2", + "metadata": { + "visible": true, + "manufacturer": "Snapmaker", + "file_formats": "text/x-gcode", + "machine_extruder_trains": { + "0": "snapmaker_extruder_0" + }, + "quality_definition": "snapmaker2" + }, + "overrides": { + "machine_name": { + "default_value": "Snapmaker A250" + }, + "machine_width": { + "default_value": 230 + }, + "machine_depth": { + "default_value": 250 + }, + "machine_height": { + "default_value": 235 + }, + "machine_head_with_fans_polygon": { + "default_value": [ + [-67, 22], + [-67, -25], + [25.5, 22], + [25.5, -25] + ] + }, + "gantry_height": { + "value": 27 + } + } +} diff --git a/resources/definitions/snapmaker2_A350.def.json b/resources/definitions/snapmaker2_A350.def.json new file mode 100644 index 0000000000..944e9ebc3b --- /dev/null +++ b/resources/definitions/snapmaker2_A350.def.json @@ -0,0 +1,39 @@ +{ + "version": 2, + "name": "Snapmaker 2 A350", + "inherits": "snapmaker2", + "metadata": { + "visible": true, + "manufacturer": "Snapmaker", + "file_formats": "text/x-gcode", + "machine_extruder_trains": { + "0": "snapmaker_extruder_0" + }, + "quality_definition": "snapmaker2" + }, + "overrides": { + "machine_name": { + "default_value": "Snapmaker A350" + }, + "machine_width": { + "default_value": 320 + }, + "machine_depth": { + "default_value": 350 + }, + "machine_height": { + "default_value": 330 + }, + "machine_head_with_fans_polygon": { + "default_value": [ + [-67, 22], + [-67, -25], + [25.5, 22], + [25.5, -25] + ] + }, + "gantry_height": { + "value": 27 + } + } +} diff --git a/resources/extruders/cubicon_style_neo_a31_extruder_0.def.json b/resources/extruders/cubicon_style_neo_a31_extruder_0.def.json new file mode 100644 index 0000000000..4f6ced9818 --- /dev/null +++ b/resources/extruders/cubicon_style_neo_a31_extruder_0.def.json @@ -0,0 +1,26 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "cubicon_style_neo_a31", + "position": "0" + }, + "overrides": { + "extruder_nr": { + "default_value": 0 + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "machine_nozzle_offset_x": { + "default_value": -7.13 + }, + "machine_nozzle_offset_y": { + "default_value": -3.77 + }, + "material_diameter": { + "default_value": 1.75 + } + } +} diff --git a/resources/extruders/eryone_er20_extruder_0.def.json b/resources/extruders/eryone_er20_extruder_0.def.json new file mode 100644 index 0000000000..9b1c1fa435 --- /dev/null +++ b/resources/extruders/eryone_er20_extruder_0.def.json @@ -0,0 +1,27 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "eryone_er20", + "position": "0" + }, + + "overrides": { + "extruder_nr": { + "default_value": 0 + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 + }, + "machine_nozzle_offset_x": { + "default_value": -10.0 + }, + "machine_nozzle_offset_y": { + "default_value": 8.0 + } + } +} diff --git a/resources/extruders/maker_made_300x_extruder_0.def.json b/resources/extruders/maker_made_300x_extruder_0.def.json new file mode 100644 index 0000000000..a35c47b395 --- /dev/null +++ b/resources/extruders/maker_made_300x_extruder_0.def.json @@ -0,0 +1,15 @@ +{ + "name": "Extruder 1", + "version": 2, + "inherits": "fdmextruder", + "metadata": { + "machine": "maker_made_300x", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + } +} diff --git a/resources/extruders/mingda_base_extruder_0.def.json b/resources/extruders/mingda_base_extruder_0.def.json new file mode 100644 index 0000000000..034f6ce45f --- /dev/null +++ b/resources/extruders/mingda_base_extruder_0.def.json @@ -0,0 +1,16 @@ +{ + "version": 2, + "name": "Extruder 1", + "inherits": "fdmextruder", + "metadata": { + "machine": "mingda_base", + "position": "0" + }, + + "overrides": { + "extruder_nr": { "default_value": 0 }, + "machine_nozzle_size": { "default_value": 0.4 }, + "material_diameter": { "default_value": 1.75 } + + } +} diff --git a/resources/extruders/snapmaker_extruder_0.def.json b/resources/extruders/snapmaker_extruder_0.def.json new file mode 100644 index 0000000000..c9b69703a7 --- /dev/null +++ b/resources/extruders/snapmaker_extruder_0.def.json @@ -0,0 +1,20 @@ +{ + "name": "Extruder 1", + "version": 2, + "inherits": "fdmextruder", + "metadata": { + "machine": "snapmaker2", + "position": "0" + }, + "overrides": { + "extruder_nr": { + "default_value": 0 + }, + "machine_nozzle_size": { + "default_value": 0.4 + }, + "material_diameter": { + "default_value": 1.75 + } + } +} diff --git a/resources/meshes/eryone_er20_plateform.stl b/resources/meshes/eryone_er20_plateform.stl new file mode 100644 index 0000000000..a181d0f37e Binary files /dev/null and b/resources/meshes/eryone_er20_plateform.stl differ diff --git a/resources/meshes/mingda_d2_base.stl b/resources/meshes/mingda_d2_base.stl new file mode 100644 index 0000000000..025900f243 Binary files /dev/null and b/resources/meshes/mingda_d2_base.stl differ diff --git a/resources/qml/ActionPanel/PrintJobInformation.qml b/resources/qml/ActionPanel/PrintJobInformation.qml index 5b80e1a614..9cdbf0714f 100644 --- a/resources/qml/ActionPanel/PrintJobInformation.qml +++ b/resources/qml/ActionPanel/PrintJobInformation.qml @@ -144,7 +144,7 @@ Column { names.push(printMaterialNames[index]) lengths.push(printMaterialLengths[index].toFixed(2)) - weights.push(String(Math.round(printMaterialWeights[index]))) + weights.push(String(printMaterialWeights[index].toFixed(1))) var cost = printMaterialCosts[index] == undefined ? 0 : printMaterialCosts[index].toFixed(2) costs.push(cost) } @@ -153,7 +153,7 @@ Column if(lengths.length == 0) { lengths = ["0.00"] - weights = ["0"] + weights = ["0.0"] costs = ["0.00"] } diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index c62b0cb89a..78c4958598 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -416,9 +416,13 @@ Item Action { id: openAction; + property var fileProviderModel: CuraApplication.getFileProviderModel() + text: catalog.i18nc("@action:inmenu menubar:file","&Open File(s)..."); iconName: "document-open"; - shortcut: StandardKey.Open; + // Unassign the shortcut when there are more than one file providers, since then the file provider's shortcut is + // enabled instead, and Ctrl+O is assigned to the local file provider + shortcut: fileProviderModel.count == 1 ? StandardKey.Open : ""; } Action diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 9f24d91caf..bb7b5ac19c 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -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. import QtQuick 2.7 @@ -149,15 +149,6 @@ UM.MainWindow id: backgroundItem anchors.fill: parent - signal hasMesh(string name) //this signal sends the filebase name so it can be used for the JobSpecs.qml - function getMeshName(path) - { - //takes the path the complete path of the meshname and returns only the filebase - var fileName = path.slice(path.lastIndexOf("/") + 1) - var fileBase = fileName.slice(0, fileName.indexOf(".")) - return fileBase - } - //DeleteSelection on the keypress backspace event Keys.onPressed: { diff --git a/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml b/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml index 8cdaeea5fa..8c29fc7845 100644 --- a/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml +++ b/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2015 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -32,30 +32,25 @@ UM.Dialog // load the entire project function loadProjectFile() { - // update preference if (rememberChoiceCheckBox.checked) { UM.Preferences.setValue("cura/choice_on_open_project", "open_as_project") } - UM.WorkspaceFileHandler.readLocalFile(base.fileUrl) - var meshName = backgroundItem.getMeshName(base.fileUrl.toString()) - backgroundItem.hasMesh(decodeURIComponent(meshName)) + var addToRecent = UM.WorkspaceFileHandler.getAddToRecentFilesHint(base.fileUrl); + UM.WorkspaceFileHandler.readLocalFile(base.fileUrl, addToRecent); base.hide() } // load the project file as separated models function loadModelFiles() { - // update preference if (rememberChoiceCheckBox.checked) { UM.Preferences.setValue("cura/choice_on_open_project", "open_as_model") } CuraApplication.readLocalFile(base.fileUrl, "open_as_model") - var meshName = backgroundItem.getMeshName(base.fileUrl.toString()) - backgroundItem.hasMesh(decodeURIComponent(meshName)) base.hide() } diff --git a/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml b/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml index 187578f12c..2ba8a409ef 100644 --- a/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml +++ b/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -32,10 +32,8 @@ UM.Dialog function loadProjectFile(projectFile) { - UM.WorkspaceFileHandler.readLocalFile(projectFile); - - var meshName = backgroundItem.getMeshName(projectFile.toString()); - backgroundItem.hasMesh(decodeURIComponent(meshName)); + var addToRecent = UM.WorkspaceFileHandler.getAddToRecentFilesHint(projectFile); + UM.WorkspaceFileHandler.readLocalFile(projectFile, addToRecent); } function loadModelFiles(fileUrls) @@ -44,9 +42,6 @@ UM.Dialog { CuraApplication.readLocalFile(fileUrls[i], "open_as_model"); } - - var meshName = backgroundItem.getMeshName(fileUrls[0].toString()); - backgroundItem.hasMesh(decodeURIComponent(meshName)); } Column @@ -108,5 +103,11 @@ UM.Dialog } } } + + UM.I18nCatalog + { + id: catalog + name: "cura" + } } -} +} \ No newline at end of file diff --git a/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml b/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml index 031ef5241a..32e0e6dcaa 100644 --- a/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml +++ b/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml @@ -156,12 +156,24 @@ UM.TooltipArea const value = propertyProvider.properties.value return value ? value : "" } - validator: DoubleValidator + property string validatorString: { - bottom: numericTextFieldWithUnit.minimum - top: numericTextFieldWithUnit.maximum - decimals: numericTextFieldWithUnit.decimals - notation: DoubleValidator.StandardNotation + var digits = Math.min(8, 1 + Math.floor( + Math.log(Math.max(Math.abs(numericTextFieldWithUnit.maximum), Math.abs(numericTextFieldWithUnit.minimum)))/Math.log(10) + )) + var minus = numericTextFieldWithUnit.minimum < 0 ? "-?" : "" + if (numericTextFieldWithUnit.decimals == 0) + { + return "^%0\\d{1,%1}$".arg(minus).arg(digits) + } + else + { + return "^%0\\d{0,%1}[.,]?\\d{0,%2}$".arg(minus).arg(digits).arg(numericTextFieldWithUnit.decimals) + } + } + validator: RegExpValidator + { + regExp: new RegExp(textFieldWithUnit.validatorString) } //Enforce actual minimum and maximum values. diff --git a/resources/qml/Menus/FileMenu.qml b/resources/qml/Menus/FileMenu.qml index b9845678d6..5ea1c9bc06 100644 --- a/resources/qml/Menus/FileMenu.qml +++ b/resources/qml/Menus/FileMenu.qml @@ -4,13 +4,14 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 -import UM 1.2 as UM +import UM 1.6 as UM import Cura 1.0 as Cura Menu { id: base title: catalog.i18nc("@title:menu menubar:toplevel", "&File") + property var fileProviderModel: CuraApplication.getFileProviderModel() MenuItem { @@ -22,6 +23,13 @@ Menu { id: openMenu action: Cura.Actions.open + visible: (base.fileProviderModel.count == 1) + } + + OpenFilesMenu + { + id: openFilesMenu + visible: (base.fileProviderModel.count > 1) } RecentFilesMenu { } @@ -29,8 +37,9 @@ Menu MenuItem { id: saveWorkspaceMenu - shortcut: StandardKey.Save + shortcut: visible ? StandardKey.Save : "" text: catalog.i18nc("@title:menu menubar:file", "&Save Project...") + visible: saveProjectMenu.model.count == 1 onTriggered: { var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" }; @@ -46,6 +55,15 @@ Menu } } + UM.ProjectOutputDevicesModel { id: projectOutputDevicesModel } + + SaveProjectMenu + { + id: saveProjectMenu + model: projectOutputDevicesModel + visible: model.count > 1 + } + MenuSeparator { } MenuItem diff --git a/resources/qml/Menus/OpenFilesMenu.qml b/resources/qml/Menus/OpenFilesMenu.qml new file mode 100644 index 0000000000..3c2b64ee62 --- /dev/null +++ b/resources/qml/Menus/OpenFilesMenu.qml @@ -0,0 +1,46 @@ +// Copyright (c) 2020 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 + +import UM 1.6 as UM +import Cura 1.0 as Cura + +import "../Dialogs" + +Menu +{ + id: openFilesMenu + title: catalog.i18nc("@title:menu menubar:file", "Open File(s)...") + iconName: "document-open-recent"; + + Instantiator + { + id: fileProviders + model: CuraApplication.getFileProviderModel() + MenuItem + { + text: + { + return model.displayText; + } + onTriggered: + { + if (model.index == 0) // The 0th element is the "From Disk" option, which should activate the open local file dialog + { + Cura.Actions.open.trigger() + } + else + { + CuraApplication.getFileProviderModel().trigger(model.name); + } + } + // Unassign the shortcuts when the submenu is invisible (i.e. when there is only one file provider) to avoid ambiguous shortcuts. + // When there is a signle file provider, the openAction is assigned with the Ctrl+O shortcut instead. + shortcut: openFilesMenu.visible ? model.shortcut : "" + } + onObjectAdded: openFilesMenu.insertItem(index, object) + onObjectRemoved: openFilesMenu.removeItem(object) + } +} diff --git a/resources/qml/Menus/RecentFilesMenu.qml b/resources/qml/Menus/RecentFilesMenu.qml index 9de523280c..de6d2e3817 100644 --- a/resources/qml/Menus/RecentFilesMenu.qml +++ b/resources/qml/Menus/RecentFilesMenu.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Ultimaker B.V. +// Copyright (c) 2021 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.2 @@ -27,13 +27,7 @@ Menu var path = decodeURIComponent(modelData.toString()) return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1); } - onTriggered: - { - CuraApplication.readLocalFile(modelData); - - var meshName = backgroundItem.getMeshName(modelData.toString()) - backgroundItem.hasMesh(decodeURIComponent(meshName)) - } + onTriggered: CuraApplication.readLocalFile(modelData) } onObjectAdded: menu.insertItem(index, object) onObjectRemoved: menu.removeItem(object) diff --git a/resources/qml/Menus/SaveProjectMenu.qml b/resources/qml/Menus/SaveProjectMenu.qml new file mode 100644 index 0000000000..dd17324e58 --- /dev/null +++ b/resources/qml/Menus/SaveProjectMenu.qml @@ -0,0 +1,53 @@ +// Copyright (c) 2021 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 + +import UM 1.6 as UM +import Cura 1.1 as Cura + +import "../Dialogs" + +Menu +{ + id: saveProjectMenu + title: catalog.i18nc("@title:menu menubar:file", "Save Project...") + property alias model: projectOutputDevices.model + + Instantiator + { + id: projectOutputDevices + MenuItem + { + text: model.name + onTriggered: + { + var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" }; + if (UM.Preferences.getValue("cura/dialog_on_project_save")) + { + saveWorkspaceDialog.deviceId = model.id + saveWorkspaceDialog.args = args + saveWorkspaceDialog.open() + } + else + { + UM.OutputDeviceManager.requestWriteToDevice(model.id, PrintInformation.jobName, args) + } + } + // Unassign the shortcuts when the submenu is invisible (i.e. when there is only one project output device) to avoid ambiguous shortcuts. + // When there is only the LocalFileOutputDevice, the Ctrl+S shortcut is assigned to the saveWorkspaceMenu MenuItem + shortcut: saveProjectMenu.visible ? model.shortcut : "" + } + onObjectAdded: saveProjectMenu.insertItem(index, object) + onObjectRemoved: saveProjectMenu.removeItem(object) + } + + WorkspaceSummaryDialog + { + id: saveWorkspaceDialog + property var args + property var deviceId + onYes: UM.OutputDeviceManager.requestWriteToDevice(deviceId, PrintInformation.jobName, args) + } +} diff --git a/resources/qml/TableView.qml b/resources/qml/TableView.qml new file mode 100644 index 0000000000..dd80304b83 --- /dev/null +++ b/resources/qml/TableView.qml @@ -0,0 +1,68 @@ +// Copyright (C) 2021 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.10 +import QtQuick.Controls 1.4 as OldControls // TableView doesn't exist in the QtQuick Controls 2.x in 5.10, so use the old one +import QtQuick.Controls 2.3 +import QtQuick.Controls.Styles 1.4 + +import UM 1.2 as UM + + +OldControls.TableView +{ + itemDelegate: Item + { + height: tableCellLabel.implicitHeight + + Label + { + id: tableCellLabel + color: UM.Theme.getColor("text") + elide: Text.ElideRight + text: styleData.value + anchors.fill: parent + anchors.leftMargin: 10 * screenScaleFactor + verticalAlignment: Text.AlignVCenter + } + } + + rowDelegate: Rectangle + { + color: styleData.selected ? UM.Theme.getColor("secondary") : UM.Theme.getColor("main_background") + height: UM.Theme.getSize("table_row").height + } + + // Use the old styling technique since it's the only way to make the scrollbars themed in the TableView + style: TableViewStyle + { + backgroundColor: UM.Theme.getColor("main_background") + + handle: Rectangle + { + // Both implicit width and height have to be set, since the handle is used by both the horizontal and the vertical scrollbars + implicitWidth: UM.Theme.getSize("scrollbar").width + implicitHeight: UM.Theme.getSize("scrollbar").width + radius: width / 2 + color: UM.Theme.getColor(styleData.pressed ? "scrollbar_handle_down" : (styleData.hovered ? "scrollbar_handle_hover" : "scrollbar_handle")) + } + + scrollBarBackground: Rectangle + { + // Both implicit width and height have to be set, since the handle is used by both the horizontal and the vertical scrollbars + implicitWidth: UM.Theme.getSize("scrollbar").width + implicitHeight: UM.Theme.getSize("scrollbar").width + color: UM.Theme.getColor("main_background") + } + + // The little rectangle between the vertical and horizontal scrollbars + corner: Rectangle + { + color: UM.Theme.getColor("main_background") + } + + // Override the control arrows + incrementControl: Item { } + decrementControl: Item { } + } +} \ No newline at end of file diff --git a/resources/qml/Widgets/ComboBox.qml b/resources/qml/Widgets/ComboBox.qml index d4c526e265..7eb366f0a3 100644 --- a/resources/qml/Widgets/ComboBox.qml +++ b/resources/qml/Widgets/ComboBox.qml @@ -15,6 +15,18 @@ ComboBox { id: control + UM.I18nCatalog + { + id: catalog + name: "cura" + } + + property var defaultTextOnEmptyModel: catalog.i18nc("@label", "No items to select from") // Text displayed in the combobox when the model is empty + property var defaultTextOnEmptyIndex: "" // Text displayed in the combobox when the model has items but no item is selected + enabled: delegateModel.count > 0 + + onVisibleChanged: { popup.close() } + states: [ State { @@ -67,11 +79,22 @@ ComboBox anchors.verticalCenter: parent.verticalCenter anchors.right: downArrow.left - text: control.currentText + text: + { + if (control.delegateModel.count == 0) + { + return control.defaultTextOnEmptyModel != "" ? control.defaultTextOnEmptyModel : control.defaultTextOnEmptyIndex + } + else + { + return control.currentIndex == -1 ? control.defaultTextOnEmptyIndex : control.currentText + } + } + textFormat: Text.PlainText renderType: Text.NativeRendering font: UM.Theme.getFont("default") - color: UM.Theme.getColor("setting_control_text") + color: control.currentIndex == -1 ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text") elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } @@ -81,6 +104,7 @@ ComboBox y: control.height - UM.Theme.getSize("default_lining").height width: control.width implicitHeight: contentItem.implicitHeight + 2 * UM.Theme.getSize("default_lining").width + bottomMargin: UM.Theme.getSize("default_margin").height padding: UM.Theme.getSize("default_lining").width contentItem: ListView @@ -133,7 +157,7 @@ ComboBox text: delegateItem.text textFormat: Text.PlainText renderType: Text.NativeRendering - color: control.contentItem.color + color: UM.Theme.getColor("setting_control_text") font: UM.Theme.getFont("default") elide: Text.ElideRight verticalAlignment: Text.AlignVCenter diff --git a/resources/quality/eryone_er20/eryone_er20_draft.inst.cfg b/resources/quality/eryone_er20/eryone_er20_draft.inst.cfg new file mode 100644 index 0000000000..64e4f2b180 --- /dev/null +++ b/resources/quality/eryone_er20/eryone_er20_draft.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Draft +definition = eryone_er20 + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +weight = -2 +global_quality = True + +[values] +acceleration_print = 1500 +layer_height = 0.3 +layer_height_0 = 0.3 +speed_print = 80 +speed_support = 60 \ No newline at end of file diff --git a/resources/quality/eryone_er20/eryone_er20_high.inst.cfg b/resources/quality/eryone_er20/eryone_er20_high.inst.cfg new file mode 100644 index 0000000000..db15abbeb4 --- /dev/null +++ b/resources/quality/eryone_er20/eryone_er20_high.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = High +definition = eryone_er20 + +[metadata] +setting_version = 16 +type = quality +quality_type = high +weight = 1 +global_quality = True + +[values] +acceleration_print = 500 +layer_height = 0.15 +layer_height_0 = 0.2 +speed_print = 50 +speed_support = 30 \ No newline at end of file diff --git a/resources/quality/eryone_er20/eryone_er20_normal.inst.cfg b/resources/quality/eryone_er20/eryone_er20_normal.inst.cfg new file mode 100644 index 0000000000..ca29834126 --- /dev/null +++ b/resources/quality/eryone_er20/eryone_er20_normal.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Normal +definition = eryone_er20 + +[metadata] +setting_version = 16 +type = quality +quality_type = normal +weight = 0 +global_quality = True + +[values] +acceleration_print = 1000 +layer_height = 0.2 +layer_height_0 = 0.2 +speed_print = 50 +speed_support = 30 \ No newline at end of file diff --git a/resources/quality/mingda/ABS/mingda_0.2_ABS_super.inst.cfg b/resources/quality/mingda/ABS/mingda_0.2_ABS_super.inst.cfg new file mode 100644 index 0000000000..7c2e814649 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.2_ABS_super.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_abs +variant = 0.2mm Nozzle + +[values] +wall_thickness = =line_width*8 diff --git a/resources/quality/mingda/ABS/mingda_0.2_ABS_ultra.inst.cfg b/resources/quality/mingda/ABS/mingda_0.2_ABS_ultra.inst.cfg new file mode 100644 index 0000000000..a8a356f5e0 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.2_ABS_ultra.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Ultra Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = ultra +material = generic_abs +variant = 0.2mm Nozzle + +[values] +wall_thickness = =line_width*8 diff --git a/resources/quality/mingda/ABS/mingda_0.3_ABS_adaptive.inst.cfg b/resources/quality/mingda/ABS/mingda_0.3_ABS_adaptive.inst.cfg new file mode 100644 index 0000000000..78c7fd0b97 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.3_ABS_adaptive.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_abs +variant = 0.3mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.3_ABS_low.inst.cfg b/resources/quality/mingda/ABS/mingda_0.3_ABS_low.inst.cfg new file mode 100644 index 0000000000..e257c64381 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.3_ABS_low.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_abs +variant = 0.3mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.3_ABS_standard.inst.cfg b/resources/quality/mingda/ABS/mingda_0.3_ABS_standard.inst.cfg new file mode 100644 index 0000000000..698b980a07 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.3_ABS_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_abs +variant = 0.3mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.3_ABS_super.inst.cfg b/resources/quality/mingda/ABS/mingda_0.3_ABS_super.inst.cfg new file mode 100644 index 0000000000..747a43b724 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.3_ABS_super.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_abs +variant = 0.3mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.4_ABS_adaptive.inst.cfg b/resources/quality/mingda/ABS/mingda_0.4_ABS_adaptive.inst.cfg new file mode 100644 index 0000000000..af4b2a871e --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.4_ABS_adaptive.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_abs +variant = 0.4mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.4_ABS_low.inst.cfg b/resources/quality/mingda/ABS/mingda_0.4_ABS_low.inst.cfg new file mode 100644 index 0000000000..fa446b947a --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.4_ABS_low.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_abs +variant = 0.4mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.4_ABS_standard.inst.cfg b/resources/quality/mingda/ABS/mingda_0.4_ABS_standard.inst.cfg new file mode 100644 index 0000000000..4e97c377c7 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.4_ABS_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_abs +variant = 0.4mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.4_ABS_super.inst.cfg b/resources/quality/mingda/ABS/mingda_0.4_ABS_super.inst.cfg new file mode 100644 index 0000000000..2d7f2de56a --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.4_ABS_super.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_abs +variant = 0.4mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.5_ABS_adaptive.inst.cfg b/resources/quality/mingda/ABS/mingda_0.5_ABS_adaptive.inst.cfg new file mode 100644 index 0000000000..09950351b6 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.5_ABS_adaptive.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_abs +variant = 0.5mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.5_ABS_low.inst.cfg b/resources/quality/mingda/ABS/mingda_0.5_ABS_low.inst.cfg new file mode 100644 index 0000000000..dfd3eed5e0 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.5_ABS_low.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_abs +variant = 0.5mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.5_ABS_standard.inst.cfg b/resources/quality/mingda/ABS/mingda_0.5_ABS_standard.inst.cfg new file mode 100644 index 0000000000..88a2680152 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.5_ABS_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_abs +variant = 0.5mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.5_ABS_super.inst.cfg b/resources/quality/mingda/ABS/mingda_0.5_ABS_super.inst.cfg new file mode 100644 index 0000000000..16699522e0 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.5_ABS_super.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_abs +variant = 0.5mm Nozzle + +[values] +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/ABS/mingda_0.6_ABS_standard.inst.cfg b/resources/quality/mingda/ABS/mingda_0.6_ABS_standard.inst.cfg new file mode 100644 index 0000000000..08c5f830a5 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.6_ABS_standard.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_abs +variant = 0.6mm Nozzle + +[values] +wall_thickness = =line_width*3 diff --git a/resources/quality/mingda/ABS/mingda_0.8_ABS_draft.inst.cfg b/resources/quality/mingda/ABS/mingda_0.8_ABS_draft.inst.cfg new file mode 100644 index 0000000000..90a5676672 --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_0.8_ABS_draft.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_abs +variant = 0.8mm Nozzle + +[values] +wall_thickness = =line_width*3 diff --git a/resources/quality/mingda/ABS/mingda_1.0_ABS_draft.inst.cfg b/resources/quality/mingda/ABS/mingda_1.0_ABS_draft.inst.cfg new file mode 100644 index 0000000000..af16ce5e0a --- /dev/null +++ b/resources/quality/mingda/ABS/mingda_1.0_ABS_draft.inst.cfg @@ -0,0 +1,14 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_abs +variant = 1.0mm Nozzle + +[values] +wall_thickness = =line_width*3 diff --git a/resources/quality/mingda/PETG/mingda_0.2_PETG_super.inst.cfg b/resources/quality/mingda/PETG/mingda_0.2_PETG_super.inst.cfg new file mode 100644 index 0000000000..0871a9f60f --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.2_PETG_super.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_petg +variant = 0.2mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*8 diff --git a/resources/quality/mingda/PETG/mingda_0.2_PETG_ultra.inst.cfg b/resources/quality/mingda/PETG/mingda_0.2_PETG_ultra.inst.cfg new file mode 100644 index 0000000000..e5ad91cd01 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.2_PETG_ultra.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Ultra Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = ultra +material = generic_petg +variant = 0.2mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*8 diff --git a/resources/quality/mingda/PETG/mingda_0.3_PETG_adaptive.inst.cfg b/resources/quality/mingda/PETG/mingda_0.3_PETG_adaptive.inst.cfg new file mode 100644 index 0000000000..addac275be --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.3_PETG_adaptive.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_petg +variant = 0.3mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.3_PETG_low.inst.cfg b/resources/quality/mingda/PETG/mingda_0.3_PETG_low.inst.cfg new file mode 100644 index 0000000000..775a23b89b --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.3_PETG_low.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_petg +variant = 0.3mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.3_PETG_standard.inst.cfg b/resources/quality/mingda/PETG/mingda_0.3_PETG_standard.inst.cfg new file mode 100644 index 0000000000..29d09c2cc3 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.3_PETG_standard.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_petg +variant = 0.3mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.3_PETG_super.inst.cfg b/resources/quality/mingda/PETG/mingda_0.3_PETG_super.inst.cfg new file mode 100644 index 0000000000..00ae181704 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.3_PETG_super.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_petg +variant = 0.3mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.4_PETG_adaptive.inst.cfg b/resources/quality/mingda/PETG/mingda_0.4_PETG_adaptive.inst.cfg new file mode 100644 index 0000000000..4684750c3d --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.4_PETG_adaptive.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_petg +variant = 0.4mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.4_PETG_low.inst.cfg b/resources/quality/mingda/PETG/mingda_0.4_PETG_low.inst.cfg new file mode 100644 index 0000000000..bb984a0b40 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.4_PETG_low.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_petg +variant = 0.4mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.4_PETG_standard.inst.cfg b/resources/quality/mingda/PETG/mingda_0.4_PETG_standard.inst.cfg new file mode 100644 index 0000000000..957d95f8c6 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.4_PETG_standard.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_petg +variant = 0.4mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.4_PETG_super.inst.cfg b/resources/quality/mingda/PETG/mingda_0.4_PETG_super.inst.cfg new file mode 100644 index 0000000000..c3c8f4d145 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.4_PETG_super.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_petg +variant = 0.4mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.5_PETG_adaptive.inst.cfg b/resources/quality/mingda/PETG/mingda_0.5_PETG_adaptive.inst.cfg new file mode 100644 index 0000000000..0387d7c45f --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.5_PETG_adaptive.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_petg +variant = 0.5mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.5_PETG_low.inst.cfg b/resources/quality/mingda/PETG/mingda_0.5_PETG_low.inst.cfg new file mode 100644 index 0000000000..d41ed8ed76 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.5_PETG_low.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_petg +variant = 0.5mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.5_PETG_standard.inst.cfg b/resources/quality/mingda/PETG/mingda_0.5_PETG_standard.inst.cfg new file mode 100644 index 0000000000..dd88e16730 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.5_PETG_standard.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_petg +variant = 0.5mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.5_PETG_super.inst.cfg b/resources/quality/mingda/PETG/mingda_0.5_PETG_super.inst.cfg new file mode 100644 index 0000000000..6c30bf5153 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.5_PETG_super.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_petg +variant = 0.5mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*4 diff --git a/resources/quality/mingda/PETG/mingda_0.6_PETG_standard.inst.cfg b/resources/quality/mingda/PETG/mingda_0.6_PETG_standard.inst.cfg new file mode 100644 index 0000000000..5e523397b7 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.6_PETG_standard.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_petg +variant = 0.6mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*3 diff --git a/resources/quality/mingda/PETG/mingda_0.8_PETG_draft.inst.cfg b/resources/quality/mingda/PETG/mingda_0.8_PETG_draft.inst.cfg new file mode 100644 index 0000000000..c0a9722d81 --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_0.8_PETG_draft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_petg +variant = 0.8mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*3 diff --git a/resources/quality/mingda/PETG/mingda_1.0_PETG_draft.inst.cfg b/resources/quality/mingda/PETG/mingda_1.0_PETG_draft.inst.cfg new file mode 100644 index 0000000000..dea437311b --- /dev/null +++ b/resources/quality/mingda/PETG/mingda_1.0_PETG_draft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_petg +variant = 1.0mm Nozzle + +[values] +speed_layer_0 = 15 +wall_thickness = =line_width*3 diff --git a/resources/quality/mingda/PLA/mingda_0.2_PLA_super.inst.cfg b/resources/quality/mingda/PLA/mingda_0.2_PLA_super.inst.cfg new file mode 100644 index 0000000000..15ddd05f47 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.2_PLA_super.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_pla +variant = 0.2mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.2_PLA_ultra.inst.cfg b/resources/quality/mingda/PLA/mingda_0.2_PLA_ultra.inst.cfg new file mode 100644 index 0000000000..5723a1405f --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.2_PLA_ultra.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Ultra Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = ultra +material = generic_pla +variant = 0.2mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.3_PLA_adaptive.inst.cfg b/resources/quality/mingda/PLA/mingda_0.3_PLA_adaptive.inst.cfg new file mode 100644 index 0000000000..14d9209d26 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.3_PLA_adaptive.inst.cfg @@ -0,0 +1,12 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_pla +variant = 0.3mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.3_PLA_low.inst.cfg b/resources/quality/mingda/PLA/mingda_0.3_PLA_low.inst.cfg new file mode 100644 index 0000000000..12512be2e4 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.3_PLA_low.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_pla +variant = 0.3mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.3_PLA_standard.inst.cfg b/resources/quality/mingda/PLA/mingda_0.3_PLA_standard.inst.cfg new file mode 100644 index 0000000000..643fa0c905 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.3_PLA_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_pla +variant = 0.3mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.3_PLA_super.inst.cfg b/resources/quality/mingda/PLA/mingda_0.3_PLA_super.inst.cfg new file mode 100644 index 0000000000..a1b265ec24 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.3_PLA_super.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_pla +variant = 0.3mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.4_PLA_adaptive.inst.cfg b/resources/quality/mingda/PLA/mingda_0.4_PLA_adaptive.inst.cfg new file mode 100644 index 0000000000..7cfa128ba5 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.4_PLA_adaptive.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_pla +variant = 0.4mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.4_PLA_low.inst.cfg b/resources/quality/mingda/PLA/mingda_0.4_PLA_low.inst.cfg new file mode 100644 index 0000000000..b6c078707e --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.4_PLA_low.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_pla +variant = 0.4mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.4_PLA_standard.inst.cfg b/resources/quality/mingda/PLA/mingda_0.4_PLA_standard.inst.cfg new file mode 100644 index 0000000000..3db4a26325 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.4_PLA_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_pla +variant = 0.4mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.4_PLA_super.inst.cfg b/resources/quality/mingda/PLA/mingda_0.4_PLA_super.inst.cfg new file mode 100644 index 0000000000..33324cae94 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.4_PLA_super.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_pla +variant = 0.4mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.5_PLA_adaptive.inst.cfg b/resources/quality/mingda/PLA/mingda_0.5_PLA_adaptive.inst.cfg new file mode 100644 index 0000000000..1280ed4076 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.5_PLA_adaptive.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_pla +variant = 0.5mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.5_PLA_low.inst.cfg b/resources/quality/mingda/PLA/mingda_0.5_PLA_low.inst.cfg new file mode 100644 index 0000000000..f3ad9f556b --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.5_PLA_low.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_pla +variant = 0.5mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.5_PLA_standard.inst.cfg b/resources/quality/mingda/PLA/mingda_0.5_PLA_standard.inst.cfg new file mode 100644 index 0000000000..31811ca4a6 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.5_PLA_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_pla +variant = 0.5mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.5_PLA_super.inst.cfg b/resources/quality/mingda/PLA/mingda_0.5_PLA_super.inst.cfg new file mode 100644 index 0000000000..af672c0162 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.5_PLA_super.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_pla +variant = 0.5mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.6_PLA_draft.inst.cfg b/resources/quality/mingda/PLA/mingda_0.6_PLA_draft.inst.cfg new file mode 100644 index 0000000000..56bad6424c --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.6_PLA_draft.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_pla +variant = 0.6mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.6_PLA_low.inst.cfg b/resources/quality/mingda/PLA/mingda_0.6_PLA_low.inst.cfg new file mode 100644 index 0000000000..70cc021595 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.6_PLA_low.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +material = generic_pla +variant = 0.6mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.6_PLA_standard.inst.cfg b/resources/quality/mingda/PLA/mingda_0.6_PLA_standard.inst.cfg new file mode 100644 index 0000000000..d95105aba5 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.6_PLA_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_pla +variant = 0.6mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_0.8_PLA_draft.inst.cfg b/resources/quality/mingda/PLA/mingda_0.8_PLA_draft.inst.cfg new file mode 100644 index 0000000000..2d00b31944 --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_0.8_PLA_draft.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_pla +variant = 0.8mm Nozzle + +[values] diff --git a/resources/quality/mingda/PLA/mingda_1.0_PLA_draft.inst.cfg b/resources/quality/mingda/PLA/mingda_1.0_PLA_draft.inst.cfg new file mode 100644 index 0000000000..ab5c178e5c --- /dev/null +++ b/resources/quality/mingda/PLA/mingda_1.0_PLA_draft.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_pla +variant = 1.0mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.3_TPU_adaptive.inst.cfg b/resources/quality/mingda/TPU/mingda_0.3_TPU_adaptive.inst.cfg new file mode 100644 index 0000000000..24d5010449 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.3_TPU_adaptive.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_tpu +variant = 0.3mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.3_TPU_standard.inst.cfg b/resources/quality/mingda/TPU/mingda_0.3_TPU_standard.inst.cfg new file mode 100644 index 0000000000..3d3a74b8a2 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.3_TPU_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_tpu +variant = 0.3mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.3_TPU_super.inst.cfg b/resources/quality/mingda/TPU/mingda_0.3_TPU_super.inst.cfg new file mode 100644 index 0000000000..87234879a5 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.3_TPU_super.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_tpu +variant = 0.3mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.4_TPU_adaptive.inst.cfg b/resources/quality/mingda/TPU/mingda_0.4_TPU_adaptive.inst.cfg new file mode 100644 index 0000000000..418ca97b82 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.4_TPU_adaptive.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_tpu +variant = 0.4mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.4_TPU_standard.inst.cfg b/resources/quality/mingda/TPU/mingda_0.4_TPU_standard.inst.cfg new file mode 100644 index 0000000000..73114d9b2a --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.4_TPU_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_tpu +variant = 0.4mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.4_TPU_super.inst.cfg b/resources/quality/mingda/TPU/mingda_0.4_TPU_super.inst.cfg new file mode 100644 index 0000000000..4048767b19 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.4_TPU_super.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_tpu +variant = 0.4mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.5_TPU_adaptive.inst.cfg b/resources/quality/mingda/TPU/mingda_0.5_TPU_adaptive.inst.cfg new file mode 100644 index 0000000000..8894f10b54 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.5_TPU_adaptive.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +material = generic_tpu +variant = 0.5mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.5_TPU_standard.inst.cfg b/resources/quality/mingda/TPU/mingda_0.5_TPU_standard.inst.cfg new file mode 100644 index 0000000000..56d36baccf --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.5_TPU_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_tpu +variant = 0.5mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.5_TPU_super.inst.cfg b/resources/quality/mingda/TPU/mingda_0.5_TPU_super.inst.cfg new file mode 100644 index 0000000000..6f2b29c110 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.5_TPU_super.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +material = generic_tpu +variant = 0.5mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.6_TPU_standard.inst.cfg b/resources/quality/mingda/TPU/mingda_0.6_TPU_standard.inst.cfg new file mode 100644 index 0000000000..3660421e0c --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.6_TPU_standard.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +material = generic_tpu +variant = 0.6mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_0.8_TPU_draft.inst.cfg b/resources/quality/mingda/TPU/mingda_0.8_TPU_draft.inst.cfg new file mode 100644 index 0000000000..3d1fcfb8df --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_0.8_TPU_draft.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_tpu +variant = 0.8mm Nozzle + +[values] diff --git a/resources/quality/mingda/TPU/mingda_1.0_TPU_draft.inst.cfg b/resources/quality/mingda/TPU/mingda_1.0_TPU_draft.inst.cfg new file mode 100644 index 0000000000..394609a6e0 --- /dev/null +++ b/resources/quality/mingda/TPU/mingda_1.0_TPU_draft.inst.cfg @@ -0,0 +1,13 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +material = generic_tpu +variant = 1.0mm Nozzle + +[values] diff --git a/resources/quality/mingda/mingda_global_adaptive.inst.cfg b/resources/quality/mingda/mingda_global_adaptive.inst.cfg new file mode 100644 index 0000000000..e0866c1aec --- /dev/null +++ b/resources/quality/mingda/mingda_global_adaptive.inst.cfg @@ -0,0 +1,19 @@ +[general] +version = 4 +name = Dynamic Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = adaptive +weight = -2 +global_quality = True + +[values] +layer_height = 0.16 +layer_height_0 = 0.20 +top_bottom_thickness = =layer_height_0+layer_height*4 +wall_thickness = =line_width*3 +support_interface_height = =layer_height*6 +adaptive_layer_height_enabled = true diff --git a/resources/quality/mingda/mingda_global_draft.inst.cfg b/resources/quality/mingda/mingda_global_draft.inst.cfg new file mode 100644 index 0000000000..fcc21881b5 --- /dev/null +++ b/resources/quality/mingda/mingda_global_draft.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Draft Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = draft +weight = -5 +global_quality = True + +[values] +layer_height = 0.32 +layer_height_0 = 0.32 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*2 +support_interface_height = =layer_height*4 diff --git a/resources/quality/mingda/mingda_global_low.inst.cfg b/resources/quality/mingda/mingda_global_low.inst.cfg new file mode 100644 index 0000000000..65ee18e4c0 --- /dev/null +++ b/resources/quality/mingda/mingda_global_low.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Low Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = low +weight = -4 +global_quality = True + +[values] +layer_height = 0.28 +layer_height_0 = 0.28 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*2 +support_interface_height = =layer_height*4 diff --git a/resources/quality/mingda/mingda_global_standard.inst.cfg b/resources/quality/mingda/mingda_global_standard.inst.cfg new file mode 100644 index 0000000000..3ff9196b4b --- /dev/null +++ b/resources/quality/mingda/mingda_global_standard.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Standard Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = standard +weight = -3 +global_quality = True + +[values] +layer_height = 0.2 +layer_height_0 = 0.2 +top_bottom_thickness = =layer_height_0+layer_height*3 +wall_thickness = =line_width*3 +support_interface_height = =layer_height*5 diff --git a/resources/quality/mingda/mingda_global_super.inst.cfg b/resources/quality/mingda/mingda_global_super.inst.cfg new file mode 100644 index 0000000000..140c0e9e29 --- /dev/null +++ b/resources/quality/mingda/mingda_global_super.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Super Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = super +weight = -1 +global_quality = True + +[values] +layer_height = 0.12 +layer_height_0 = 0.12 +top_bottom_thickness = =layer_height_0+layer_height*6 +wall_thickness = =line_width*3 +support_interface_height = =layer_height*8 diff --git a/resources/quality/mingda/mingda_global_ultra.inst.cfg b/resources/quality/mingda/mingda_global_ultra.inst.cfg new file mode 100644 index 0000000000..4cc949ceeb --- /dev/null +++ b/resources/quality/mingda/mingda_global_ultra.inst.cfg @@ -0,0 +1,18 @@ +[general] +version = 4 +name = Ultra Quality +definition = mingda_base + +[metadata] +setting_version = 16 +type = quality +quality_type = ultra +weight = 0 +global_quality = True + +[values] +layer_height = 0.08 +layer_height_0 = 0.12 +top_bottom_thickness = =layer_height_0+layer_height*10 +wall_thickness = =line_width*3 +support_interface_height = =layer_height*12 diff --git a/resources/quality/snapmaker2/snapmaker2_fast.inst.cfg b/resources/quality/snapmaker2/snapmaker2_fast.inst.cfg new file mode 100644 index 0000000000..a2249ac1cb --- /dev/null +++ b/resources/quality/snapmaker2/snapmaker2_fast.inst.cfg @@ -0,0 +1,66 @@ +[general] +version = 4 +name = Fast +definition = snapmaker2 + +[metadata] +setting_version = 16 +type = quality +quality_type = fast +weight = -2 +global_quality = True + +[values] +layer_height = 0.24 +layer_height_0 = 0.2 +initial_layer_line_width_factor = 100 + +wall_thickness = 0.8 +wall_line_count = 2 +top_thickness = 0.8 +top_layers = 4 +bottom_thickness = 0.8 +bottom_layers = 4 +outer_inset_first = False +skin_outline_count = 0 + +; infill_line_distance = 8 +infill_sparse_density = 15 +infill_sparse_thickness = 0.24 +skin_preshrink = 0.8 +top_skin_preshrink = 0.8 +bottom_skin_preshrink = 0.8 +expand_skins_expand_distance = 0.8 +top_skin_expand_distance = 0.8 +bottom_skin_expand_distance = 0.8 + +speed_travel = 80 +speed_topbottom = 30 +speed_wall_x = 25 +speed_wall_0 = 20 +speed_wall = 40 +speed_infill = 60 +speed_print = 60 +speed_print_layer_0 = 18 +speed_travel_layer_0 = 24 +skirt_brim_speed = 18 + +retraction_hop = 1 +retraction_hop_enabled = False + +magic_spiralize = False +magic_mesh_surface_mode = normal + +adhesion_type = skirt +skirt_line_count = 1 +brim_width = 8 +brim_line_count = 20 +raft_margin = 15 + +support_enable = False +support_type = everywhere +support_pattern = zigzag +support_angle = 50 +support_infill_rate = 15 +support_line_distance = 2.66 +support_initial_layer_line_distance = 2.66 \ No newline at end of file diff --git a/resources/quality/snapmaker2/snapmaker2_high.inst.cfg b/resources/quality/snapmaker2/snapmaker2_high.inst.cfg new file mode 100644 index 0000000000..7dc84e0378 --- /dev/null +++ b/resources/quality/snapmaker2/snapmaker2_high.inst.cfg @@ -0,0 +1,65 @@ +[general] +version = 4 +name = High +definition = snapmaker2 + +[metadata] +setting_version = 16 +type = quality +quality_type = high +weight = 1 +global_quality = True + +[values] +layer_height = 0.08 +layer_height_0 = 0.15 +initial_layer_line_width_factor = 100 + +wall_thickness = 1.2 +wall_line_count = 3 +top_thickness = 0.8 +top_layers = 10 +bottom_thickness = 0.8 +bottom_layers = 10 +outer_inset_first = False +skin_outline_count = 1 + +; infill_line_distance = 8 +infill_sparse_density = 15 +infill_sparse_thickness = 0.08 +skin_preshrink = 1.2 +top_skin_preshrink = 1.2 +bottom_skin_preshrink = 1.2 +expand_skins_expand_distance = 1.2 +top_skin_expand_distance = 1.2 +bottom_skin_expand_distance = 1.2 + +speed_travel = 60 +speed_topbottom = 20 +speed_wall_x = 15 +speed_wall_0 = 10 +speed_wall = 30 +speed_infill = 40 +speed_print = 40 +speed_print_layer_0 = 18 +speed_travel_layer_0 = 24 +skirt_brim_speed = 18 + +retraction_hop = 1 +retraction_hop_enabled = False + +magic_spiralize = False +magic_mesh_surface_mode = normal + +adhesion_type = skirt +skirt_line_count = 1 +brim_width = 8 +brim_line_count = 20 +raft_margin = 15 + +support_enable = False +support_type = everywhere +support_pattern = zigzag +support_angle = 50 +support_infill_rate = 15 +support_line_distance = 2.66 diff --git a/resources/quality/snapmaker2/snapmaker2_normal.inst.cfg b/resources/quality/snapmaker2/snapmaker2_normal.inst.cfg new file mode 100644 index 0000000000..5680725817 --- /dev/null +++ b/resources/quality/snapmaker2/snapmaker2_normal.inst.cfg @@ -0,0 +1,66 @@ +[general] +version = 4 +name = Normal +definition = snapmaker2 + +[metadata] +setting_version = 16 +type = quality +quality_type = normal +weight = 0 +global_quality = True + +[values] +layer_height = 0.16 +layer_height_0 = 0.2 +initial_layer_line_width_factor = 100 + +wall_thickness = 1.2 +wall_line_count = 3 +top_thickness = 0.8 +top_layers = 5 +bottom_thickness = 0.8 +bottom_layers = 5 +outer_inset_first = False +skin_outline_count = 0 + +; infill_line_distance = 8 +infill_sparse_density = 15 +infill_sparse_thickness = 0.16 +skin_preshrink = 1.2 +top_skin_preshrink = 1.2 +bottom_skin_preshrink = 1.2 +expand_skins_expand_distance = 1.2 +top_skin_expand_distance = 1.2 +bottom_skin_expand_distance = 1.2 + +speed_travel = 70 +speed_topbottom = 25 +speed_wall_x = 20 +speed_wall_0 = 15 +speed_wall = 30 +speed_infill = 50 +speed_print = 50 +speed_print_layer_0 = 18 +speed_travel_layer_0 = 24 +skirt_brim_speed = 18 + +retraction_hop = 1 +retraction_hop_enabled = False + +magic_spiralize = False +magic_mesh_surface_mode = normal + +adhesion_type = skirt +skirt_line_count = 1 +brim_width = 8 +brim_line_count = 20 +raft_margin = 15 + +support_enable = False +support_type = everywhere +support_pattern = zigzag +support_angle = 50 +support_infill_rate = 15 +support_line_distance = 2.66 +support_initial_layer_line_distance = 2.66 \ No newline at end of file diff --git a/resources/setting_visibility/advanced.cfg b/resources/setting_visibility/advanced.cfg index d3ed1094a6..dd44df06e9 100644 --- a/resources/setting_visibility/advanced.cfg +++ b/resources/setting_visibility/advanced.cfg @@ -21,15 +21,17 @@ wall_0_extruder_nr wall_x_extruder_nr wall_thickness wall_line_count +optimize_wall_printing_order +fill_perimeter_gaps +xy_offset + +[top_bottom] top_bottom_extruder_nr top_bottom_thickness top_thickness top_layers bottom_thickness bottom_layers -optimize_wall_printing_order -fill_perimeter_gaps -xy_offset ironing_enabled [infill] diff --git a/resources/setting_visibility/basic.cfg b/resources/setting_visibility/basic.cfg index 82045db93b..f23d498c7e 100644 --- a/resources/setting_visibility/basic.cfg +++ b/resources/setting_visibility/basic.cfg @@ -10,12 +10,14 @@ layer_height [shell] wall_thickness wall_line_count +xy_offset + +[top_bottom] top_bottom_thickness top_thickness top_layers bottom_thickness bottom_layers -xy_offset [infill] infill_sparse_density diff --git a/resources/setting_visibility/expert.cfg b/resources/setting_visibility/expert.cfg index e96c4c342e..1ad90e5467 100644 --- a/resources/setting_visibility/expert.cfg +++ b/resources/setting_visibility/expert.cfg @@ -28,17 +28,6 @@ wall_x_extruder_nr wall_thickness wall_line_count wall_0_wipe_dist -roofing_layer_count -top_bottom_extruder_nr -top_bottom_thickness -top_thickness -top_layers -bottom_thickness -bottom_layers -top_bottom_pattern -top_bottom_pattern_0 -connect_skin_polygons -skin_angles wall_0_inset optimize_wall_printing_order outer_inset_first @@ -58,6 +47,19 @@ z_seam_x z_seam_y z_seam_corner z_seam_relative + +[top_bottom] +roofing_layer_count +top_bottom_extruder_nr +top_bottom_thickness +top_thickness +top_layers +bottom_thickness +bottom_layers +top_bottom_pattern +top_bottom_pattern_0 +connect_skin_polygons +skin_angles skin_no_small_gaps_heuristic skin_outline_count ironing_enabled diff --git a/resources/themes/cura-light/icons/category_topbottom.svg b/resources/themes/cura-light/icons/category_topbottom.svg new file mode 100644 index 0000000000..7efefbd4bb --- /dev/null +++ b/resources/themes/cura-light/icons/category_topbottom.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 7bb8156458..5a99b023eb 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -389,6 +389,7 @@ "layerview_support_interface": [63, 127, 255, 127], "layerview_prime_tower": [0, 255, 255, 255], "layerview_nozzle": [224, 192, 16, 64], + "layerview_starts": [255, 255, 255, 255], "tab_status_connected": [50, 130, 255, 255], "tab_status_disconnected": [200, 200, 200, 255], @@ -630,6 +631,8 @@ "monitor_external_link_icon": [1.16, 1.16], "monitor_column": [18.0, 1.0], "monitor_progress_bar": [16.5, 1.0], - "monitor_margin": [1.5, 1.5] + "monitor_margin": [1.5, 1.5], + + "table_row": [2.0, 2.0] } } diff --git a/resources/variants/mingda_base_0.2.inst.cfg b/resources/variants/mingda_base_0.2.inst.cfg new file mode 100644 index 0000000000..97c42d6950 --- /dev/null +++ b/resources/variants/mingda_base_0.2.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.2mm Nozzle +version = 4 +definition = mingda_base + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.2 diff --git a/resources/variants/mingda_base_0.3.inst.cfg b/resources/variants/mingda_base_0.3.inst.cfg new file mode 100644 index 0000000000..fea77ffde2 --- /dev/null +++ b/resources/variants/mingda_base_0.3.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.3mm Nozzle +version = 4 +definition = mingda_base + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.3 diff --git a/resources/variants/mingda_base_0.4.inst.cfg b/resources/variants/mingda_base_0.4.inst.cfg new file mode 100644 index 0000000000..6da23aef60 --- /dev/null +++ b/resources/variants/mingda_base_0.4.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.4mm Nozzle +version = 4 +definition = mingda_base + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.4 diff --git a/resources/variants/mingda_base_0.6.inst.cfg b/resources/variants/mingda_base_0.6.inst.cfg new file mode 100644 index 0000000000..d478c2d596 --- /dev/null +++ b/resources/variants/mingda_base_0.6.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.6mm Nozzle +version = 4 +definition = mingda_base + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.6 diff --git a/resources/variants/mingda_base_0.8.inst.cfg b/resources/variants/mingda_base_0.8.inst.cfg new file mode 100644 index 0000000000..3e0cc6e913 --- /dev/null +++ b/resources/variants/mingda_base_0.8.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.8mm Nozzle +version = 4 +definition = mingda_base + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.8 diff --git a/resources/variants/mingda_base_1.0.inst.cfg b/resources/variants/mingda_base_1.0.inst.cfg new file mode 100644 index 0000000000..72cb23ac11 --- /dev/null +++ b/resources/variants/mingda_base_1.0.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 1.0mm Nozzle +version = 4 +definition = mingda_base + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 1.0 diff --git a/resources/variants/mingda_d2_0.2.inst.cfg b/resources/variants/mingda_d2_0.2.inst.cfg new file mode 100644 index 0000000000..8a5aa48df1 --- /dev/null +++ b/resources/variants/mingda_d2_0.2.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.2mm Nozzle +version = 4 +definition = mingda_d2 + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.2 diff --git a/resources/variants/mingda_d2_0.3.inst.cfg b/resources/variants/mingda_d2_0.3.inst.cfg new file mode 100644 index 0000000000..0e9fd36dc7 --- /dev/null +++ b/resources/variants/mingda_d2_0.3.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.3mm Nozzle +version = 4 +definition = mingda_d2 + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.3 diff --git a/resources/variants/mingda_d2_0.4.inst.cfg b/resources/variants/mingda_d2_0.4.inst.cfg new file mode 100644 index 0000000000..bd7d3b6804 --- /dev/null +++ b/resources/variants/mingda_d2_0.4.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.4mm Nozzle +version = 4 +definition = mingda_d2 + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.4 diff --git a/resources/variants/mingda_d2_0.5.inst.cfg b/resources/variants/mingda_d2_0.5.inst.cfg new file mode 100644 index 0000000000..50c2f4497c --- /dev/null +++ b/resources/variants/mingda_d2_0.5.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.5mm Nozzle +version = 4 +definition = mingda_d2 + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.5 diff --git a/resources/variants/mingda_d2_0.6.inst.cfg b/resources/variants/mingda_d2_0.6.inst.cfg new file mode 100644 index 0000000000..58500e6a39 --- /dev/null +++ b/resources/variants/mingda_d2_0.6.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.6mm Nozzle +version = 4 +definition = mingda_d2 + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.6 diff --git a/resources/variants/mingda_d2_0.8.inst.cfg b/resources/variants/mingda_d2_0.8.inst.cfg new file mode 100644 index 0000000000..fb59e5a7cd --- /dev/null +++ b/resources/variants/mingda_d2_0.8.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 0.8mm Nozzle +version = 4 +definition = mingda_d2 + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 0.8 diff --git a/resources/variants/mingda_d2_1.0.inst.cfg b/resources/variants/mingda_d2_1.0.inst.cfg new file mode 100644 index 0000000000..f42b7da1ef --- /dev/null +++ b/resources/variants/mingda_d2_1.0.inst.cfg @@ -0,0 +1,12 @@ +[general] +name = 1.0mm Nozzle +version = 4 +definition = mingda_d2 + +[metadata] +setting_version = 16 +type = variant +hardware_type = nozzle + +[values] +machine_nozzle_size = 1.0