diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000000..bd9c26751c --- /dev/null +++ b/CHANGES @@ -0,0 +1,173 @@ +Cura 15.06 Beta +=============== + +This is the *Beta* version of Cura 15.06. + +Cura 15.06 is a new release built from the ground up on a completely new +framework called Uranium. This framework has been designed to make it easier to +extend Cura with additional functionality as well as provide a cleaner UI. + +Changes since 15.05.95 +---------------------- + +* Fixed: Selection ghost remains visible after deleting an object +* Fixed: Window does not show up immediately after starting application on OSX +* Fixed: Added display of rotation angle during rotation +* Fixed: Object changes position while rotating/scaling +* Fixed: Loading improvements in the layer view +* Fixed: Added application icons +* Fixed: Improved feedback when loading models +* Fixed: Eject device on MacOSX now provides proper feedback +* Fixed: Make it possible to show retraction settings for UM2 +* Fixed: Opening the machine preferences page will switch to the first available machine +* Fixed: Improved tool handle hit area size +* Fixed: Render lines with a thickness based on screen DPI + +Changes since 15.05.94 +---------------------- + +* Added Russian translations +* Fixed: Infill not displayed in layer view +* Fixed: Cannot select/scale/rotate when first activating the tool and then trying to select a model. +* Fixed: Improved font rendering on Windows +* Fixed: Help > Show Documentation crashes Cura on Windows +* Fixed: "There is no disk in the drive" repeating messages on Windows +* Fixed: Retraction settings not visible for Ultimaker2 +* Fixed: Display rotation angle when rotating an object +* Fixed: Time/Quality slider values are properly rounded +* Fixed: Improved clarity of buttons and text +* Fixed: No indication that anything is happening when loading a model +* Fixed: Eject device now works on Windows + +Changes since 15.05.93 +---------------------- + +* Fixed: No shortcuts for moving up/down layers in layer view. +* Fixed: Last view layers could not be scrolled through in layer view. +* Fixed: Files provided on command line would not actually show up on the build + platform. +* Fixed: Render a ghost of the selection in Layer view to make the actual object + position clear. +* Fixed: Showing a menu would clear the selection. +* Fixed: Size and scaling factor display for scale tool. +* Fixed: Missing background for additional tool controls. +* Fixed: Loading message times out when loading large files. +* Fixed: Show recent files in the file menu. +* Fixed: Windows installer will now install MSVC 2010 redistributable, to + prevent issues with missing DLL's. +* Fixed: Collapsed/expanded state of setting categories not stored. + +Changes since 15.05.91 +---------------------- + +* There is now a working MacOSX version. Currently it supports OSX 10.7 and + higher. +* Fixed: Need to deselect before selecting a different object. +* Fixed: Object can be moved on Z axis. +* Fixed: Error values should be considered invalid values and will not trigger a + slice. +* Fixed: Text fields used a locale-aware validator while the underlying code did + not. +* Fixed: Text fields will trigger a slice on text change, not only after focus + change/enter press. +* Fixed: Rotate Tool snaps to incorrect value. +* Fixed: Object Collision would only moved objects to the right. +* Fixed: Object Collision would move the selected object when it should not. +* Fixed: Camera panning now works correctly instead of doing nothing. +* Fixed: Camera would flip around center point at maximum rotation. +* Fixed: Build platform grid blocked view from below objects. +* Fixed: Viewport on MacOSX with high-DPI screens was only taking 1/4th of the +window + +Changes since 15.05.90 +---------------------- + +* Fixed: Additional UI elements for tools and views not loading. +* Fixed: Double click needed to change setting dialog page. +* Fixed: Context menu entries (reload, center object, etc.) not working. +* Fixed: "Open With" or passing files from command line not working. +* Fixed: "Reload All" would not reload files. + +In addition, a lot of work has gone into getting a usable Mac OSX version. + +New Features +------------ + +* Plugin based system + The Uranium framework provides us with a plugin-based system + that provides additional flexibility when extending Cura. Think + of new views, tools, file formats, etc. This is probably the + biggest new feature. +* Improved UI + The UI has received a complete overhaul. +* Time-Quality Slider + The 4 static quick print profiles have been replaced with + a slider that should make it easier to find the right spot + between print time and print quality. +* More Settings + The Advanced mode is now configurable and can show many + additional settings that were previously not available, while at + the same time not overwhelming new users with too many settings. + Custom set of visible settings can be created by the user. +* Support for high-DPI screens + The refreshed UI has been designed with high-DPI screens in + mind which should improve the experience of Cura on such + devices. +* Improved language support + (Not yet available for the Beta release.) +* Improved support structure generation + The new version of the CuraEngine now features improved + support generation algorithms and additional options for support + structure generation. +* Experimental Feature: Wire Printing + Wire Printing has been added as an experimental new feature. It + will print objects as a structure of lines. It can be enabled by + from Advanced Mode -> Fixes -> Wire Printing. +* Undo/Redo + It is now possible to undo and redo most scene operations, like + moving or rotating objects. + +Features from earlier versions not (yet) in this release +-------------------------------------------------------- + +* The All-at-once/One-at-a-time toggle is not available. + We are working on an improved implementation of this mechanism + but it will not be available for this release. +* No dual extrusion features are available yet. + We are working on a completely new workflow for this but this + needs additional time. +* “Lay Flat” has been removed. + The existing implementation was unfortunately not salvageable. + We will be looking into an improved implementation for this + feature. +* "Split Object Into Parts" has been removed. + Due to the same reason as Lay Flat. +* Support for AMF and DAE file formats has been removed. + Both of these will be implemented as plugins in the future. +* Support for directly loading a GCode file is not yet available. + This will be implemented as a plugin in the future. +* Support for PNG, JPG and other image formats has been removed. + These can be supported by a plugin with an improved UI. +* Support for loading Minecraft levels has been removed. + This can be implemented as a plugin. +* Windows XP support has been dropped. + Microsoft is no longer supporting xp, so they no longer back + port certain features that we require. +* X-Ray view is missing. + Will be implemented as a (you might have guessed it) plugin. +* Fixes: Follow Mesh Surface + Has been removed from the engine, the same result can be + achieved using no infill or top/bottom layers. + +Known Issues +------------ + +For an up to date list of all known issues, please see +https://github.com/Ultimaker/Cura/issues and +https://github.com/Ultimaker/Uranium/issues . + +* Some OBJ files are rendered as black objects due to missing + normals. +* Disabling plugins does not work correctly yet. +* Unicorn occasionally still requires feeding. Do not feed it + after midnight. diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cbb9aebc0..bee239975f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 2.8.12) set(URANIUM_SCRIPTS_DIR "${CMAKE_SOURCE_DIR}/../uranium/scripts" CACHE DIRECTORY "The location of the scripts directory of the Uranium repository") -if(${URANIUM_SCRIPTS_DIR}) +if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "") # Extract Strings add_custom_target(extract-messages ${URANIUM_SCRIPTS_DIR}/extract-messages ${CMAKE_SOURCE_DIR} cura) @@ -27,6 +27,12 @@ if(${URANIUM_SCRIPTS_DIR}) set(languages en x-test + ru + fr + de + it + es + fi ) foreach(lang ${languages}) file(GLOB po_files resources/i18n/${lang}/*.po) @@ -55,7 +61,6 @@ find_package(PythonInterp 3.4.0 REQUIRED) set(PYTHON_SITE_PACKAGES_DIR ${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages CACHE PATH "Install location of Python package") install(DIRECTORY resources DESTINATION ${CMAKE_INSTALL_DATADIR}/cura) install(DIRECTORY plugins DESTINATION ${CMAKE_INSTALL_LIBDIR}/cura) -file(GLOB cura_SRCS cura/*) -install(FILES ${cura_SRCS} DESTINATION ${PYTHON_SITE_PACKAGES_DIR}/cura) +install(DIRECTORY cura DESTINATION ${PYTHON_SITE_PACKAGES_DIR}) install(FILES cura_app.py DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/README.md b/README.md index f311976ca1..28942eeb5d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ Cura ==== -This is the source code of Cura. +This is the new, shiny, unreleased frontend for Cura. [daid/Cura](https://github.com/daid/Cura.git) is the old legacy Cura that everyone knows and loves/hates. + +We re-worked the whole GUI code at Ultimaker, because my old code started to become an unmaintainable ball of poo. Dependencies ------------ @@ -12,3 +14,15 @@ Dependencies This will be needed at runtime to perform the actual slicing. * PySerial Only required for USB printing support. + +Configuring Cura +---------------- +* link your CuraEngine backend by inserting the following line in home/.config/cura/config.cfg : +[backend] +location = /[path_to_the..]/CuraEngine/build/CuraEngine + + +Build scripts +------------- + +Please checkout [cura-build](https://github.com/Ultimaker/cura-build) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 85806542f8..cf085bfe61 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -42,6 +42,9 @@ class BuildVolume(SceneNode): def setDepth(self, depth): self._depth = depth + def getDisallowedAreas(self): + return self._disallowed_areas + def setDisallowedAreas(self, areas): self._disallowed_areas = areas @@ -62,7 +65,7 @@ class BuildVolume(SceneNode): self._grid_material.setUniformValue("u_gridColor1", Color(205, 202, 201, 255)) renderer.queueNode(self, material = self._material, mode = Renderer.RenderLines) - renderer.queueNode(self, mesh = self._grid_mesh, material = self._grid_material) + renderer.queueNode(self, mesh = self._grid_mesh, material = self._grid_material, force_single_sided = True) if self._disallowed_area_mesh: renderer.queueNode(self, mesh = self._disallowed_area_mesh, material = self._material) return True @@ -99,29 +102,53 @@ class BuildVolume(SceneNode): mb = MeshBuilder() mb.addQuad( - Vector(minW, minH, maxD), - Vector(maxW, minH, maxD), + Vector(minW, minH, minD), Vector(maxW, minH, minD), - Vector(minW, minH, minD) + Vector(maxW, minH, maxD), + Vector(minW, minH, maxD) ) self._grid_mesh = mb.getData() for n in range(0, 6): v = self._grid_mesh.getVertex(n) self._grid_mesh.setVertexUVCoordinates(n, v[0], v[2]) + disallowed_area_size = 0 if self._disallowed_areas: mb = MeshBuilder() - for area in self._disallowed_areas: + for polygon in self._disallowed_areas: + points = polygon.getPoints() mb.addQuad( - area[0], - area[1], - area[2], - area[3], + Vector(points[0, 0], 0.1, points[0, 1]), + Vector(points[1, 0], 0.1, points[1, 1]), + Vector(points[2, 0], 0.1, points[2, 1]), + Vector(points[3, 0], 0.1, points[3, 1]), color = Color(174, 174, 174, 255) ) + # Find the largest disallowed area to exclude it from the maximum scale bounds + size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1])) + disallowed_area_size = max(size, disallowed_area_size) self._disallowed_area_mesh = mb.getData() else: self._disallowed_area_mesh = None self._aabb = AxisAlignedBox(minimum = Vector(minW, minH - 1.0, minD), maximum = Vector(maxW, maxH, maxD)) + + settings = Application.getInstance().getActiveMachine() + + skirt_size = 0.0 + if settings.getSettingValueByKey("adhesion_type") == "None": + skirt_size = settings.getSettingValueByKey("skirt_line_count") * settings.getSettingValueByKey("skirt_line_width") + settings.getSettingValueByKey("skirt_gap") + elif settings.getSettingValueByKey("adhesion_type") == "Brim": + skirt_size = settings.getSettingValueByKey("brim_line_count") * settings.getSettingValueByKey("skirt_line_width") + else: + skirt_size = settings.getSettingValueByKey("skirt_line_width") + + skirt_size += settings.getSettingValueByKey("skirt_line_width") + + scale_to_max_bounds = AxisAlignedBox( + minimum = Vector(minW + skirt_size, minH, minD + skirt_size + disallowed_area_size), + maximum = Vector(maxW - skirt_size, maxH, maxD - skirt_size - disallowed_area_size) + ) + + Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds diff --git a/cura/ConvexHullNode.py b/cura/ConvexHullNode.py index a94ae60897..5be5820982 100644 --- a/cura/ConvexHullNode.py +++ b/cura/ConvexHullNode.py @@ -48,6 +48,9 @@ class ConvexHullNode(SceneNode): self.setMeshData(mesh) + def getWatchedNode(self): + return self._node + def render(self, renderer): if not self._material: self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag")) diff --git a/cura/CuraActions.py b/cura/CuraActions.py new file mode 100644 index 0000000000..e585b261d0 --- /dev/null +++ b/cura/CuraActions.py @@ -0,0 +1,27 @@ +from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty, QUrl +from PyQt5.QtGui import QDesktopServices + +from UM.Event import CallFunctionEvent +from UM.Application import Application + +import webbrowser + +class CuraActions(QObject): + def __init__(self, parent = None): + super().__init__(parent) + + @pyqtSlot() + def openDocumentation(self): + # Starting a web browser from a signal handler connected to a menu will crash on windows. + # So instead, defer the call to the next run of the event loop, since that does work. + # Note that weirdly enough, only signal handlers that open a web browser fail like that. + event = CallFunctionEvent(self._openUrl, [QUrl("http://ultimaker.com/en/support/software")], {}) + Application.getInstance().functionEvent(event) + + @pyqtSlot() + def openBugReportPage(self): + event = CallFunctionEvent(self._openUrl, [QUrl("http://github.com/Ultimaker/Cura/issues")], {}) + Application.getInstance().functionEvent(event) + + def _openUrl(self, url): + QDesktopServices.openUrl(url) \ No newline at end of file diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index b73629775a..deaeeb254d 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -17,6 +17,8 @@ from UM.Logger import Logger from UM.Preferences import Preferences from UM.Message import Message from UM.PluginRegistry import PluginRegistry +from UM.JobQueue import JobQueue +from UM.Math.Polygon import Polygon from UM.Scene.BoxRenderer import BoxRenderer from UM.Scene.Selection import Selection @@ -32,9 +34,10 @@ from . import PlatformPhysics from . import BuildVolume from . import CameraAnimation from . import PrintInformation +from . import CuraActions from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty -from PyQt5.QtGui import QColor +from PyQt5.QtGui import QColor, QIcon import platform import sys @@ -50,6 +53,8 @@ class CuraApplication(QtApplication): super().__init__(name = "cura", version = "master") + self.setWindowIcon(QIcon(Resources.getPath(Resources.ImagesLocation, "cura-icon.png"))) + self.setRequiredPlugins([ "CuraEngineBackend", "MeshView", @@ -66,11 +71,24 @@ class CuraApplication(QtApplication): self._output_devices = {} self._print_information = None self._i18n_catalog = None + self._previous_active_tool = None self.activeMachineChanged.connect(self._onActiveMachineChanged) Preferences.getInstance().addPreference("cura/active_machine", "") Preferences.getInstance().addPreference("cura/active_mode", "simple") + Preferences.getInstance().addPreference("cura/recent_files", "") + Preferences.getInstance().addPreference("cura/categories_expanded", "") + + JobQueue.getInstance().jobFinished.connect(self._onJobFinished) + + self._recent_files = [] + files = Preferences.getInstance().getValue("cura/recent_files").split(";") + for f in files: + if not os.path.isfile(f): + continue + + self._recent_files.append(QUrl.fromLocalFile(f)) ## Handle loading of all plugin types (and the backend explicitly) # \sa PluginRegistery @@ -162,6 +180,7 @@ class CuraApplication(QtApplication): for file in self.getCommandLineOption("file", []): job = ReadMeshJob(os.path.abspath(file)) + job.finished.connect(self._onFileLoaded) job.start() self.exec_() @@ -170,18 +189,27 @@ class CuraApplication(QtApplication): engine.rootContext().setContextProperty("Printer", self) self._print_information = PrintInformation.PrintInformation() engine.rootContext().setContextProperty("PrintInformation", self._print_information) + self._cura_actions = CuraActions.CuraActions(self) + engine.rootContext().setContextProperty("CuraActions", self._cura_actions) def onSelectionChanged(self): if Selection.hasSelection(): if not self.getController().getActiveTool(): - self.getController().setActiveTool("TranslateTool") + if self._previous_active_tool: + self.getController().setActiveTool(self._previous_active_tool) + self._previous_active_tool = None + else: + self.getController().setActiveTool("TranslateTool") self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin()) self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition()) self._camera_animation.start() else: if self.getController().getActiveTool(): + self._previous_active_tool = self.getController().getActiveTool().getPluginId() self.getController().setActiveTool(None) + else: + self._previous_active_tool = None requestAddPrinter = pyqtSignal() @@ -190,6 +218,9 @@ class CuraApplication(QtApplication): def deleteObject(self, object_id): object = self.getController().getScene().findObject(object_id) + if not object and object_id != 0: #Workaround for tool handles overlapping the selected object + object = Selection.getSelectedObject(0) + if object: op = RemoveSceneNodeOperation(object) op.push() @@ -199,6 +230,9 @@ class CuraApplication(QtApplication): def multiplyObject(self, object_id, count): node = self.getController().getScene().findObject(object_id) + if not node and object_id != 0: #Workaround for tool handles overlapping the selected object + node = Selection.getSelectedObject(0) + if node: op = GroupedOperation() for i in range(count): @@ -215,6 +249,9 @@ class CuraApplication(QtApplication): def centerObject(self, object_id): node = self.getController().getScene().findObject(object_id) + if not node and object_id != 0: #Workaround for tool handles overlapping the selected object + node = Selection.getSelectedObject(0) + if node: op = SetTransformOperation(node, Vector()) op.push() @@ -304,6 +341,25 @@ class CuraApplication(QtApplication): return log + recentFilesChanged = pyqtSignal() + @pyqtProperty("QVariantList", notify = recentFilesChanged) + def recentFiles(self): + return self._recent_files + + @pyqtSlot("QStringList") + def setExpandedCategories(self, categories): + categories = list(set(categories)) + categories.sort() + joined = ";".join(categories) + if joined != Preferences.getInstance().getValue("cura/categories_expanded"): + Preferences.getInstance().setValue("cura/categories_expanded", joined) + self.expandedCategoriesChanged.emit() + + expandedCategoriesChanged = pyqtSignal() + @pyqtProperty("QStringList", notify = expandedCategoriesChanged) + def expandedCategories(self): + return Preferences.getInstance().getValue("cura/categories_expanded").split(";") + outputDevicesChanged = pyqtSignal() @pyqtProperty("QVariantMap", notify = outputDevicesChanged) @@ -385,7 +441,7 @@ class CuraApplication(QtApplication): self.addOutputDevice(drive, { "id": drive, "function": self._writeToSD, - "description": self._i18n_catalog.i18nc("Save button tooltip. {0} is sd card name", "Save to SD Card {0}".format(drive)), + "description": self._i18n_catalog.i18nc("Save button tooltip. {0} is sd card name", "Save to SD Card {0}").format(drive), "icon": "save_sd", "priority": 1 }) @@ -411,21 +467,13 @@ class CuraApplication(QtApplication): disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas") areas = [] if disallowed_areas: - for area in disallowed_areas: - polygon = [] - polygon.append(Vector(area[0][0], 0.2, area[0][1])) - polygon.append(Vector(area[1][0], 0.2, area[1][1])) - polygon.append(Vector(area[2][0], 0.2, area[2][1])) - polygon.append(Vector(area[3][0], 0.2, area[3][1])) - areas.append(polygon) + areas.append(Polygon(numpy.array(area, numpy.float32))) + self._volume.setDisallowedAreas(areas) self._volume.rebuild() - if self.getController().getTool("ScaleTool"): - self.getController().getTool("ScaleTool").setMaximumBounds(self._volume.getBoundingBox()) - offset = machine.getSettingValueByKey("machine_platform_offset") if offset: self._platform.setPosition(Vector(offset[0], offset[1], offset[2])) @@ -438,7 +486,7 @@ class CuraApplication(QtApplication): "eject", self._i18n_catalog.i18nc("Message action", "Eject"), "eject", - self._i18n_catalog.i18nc("Message action tooltip, {0} is sdcard", "Eject SD Card {0}".format(job._sdcard)) + self._i18n_catalog.i18nc("Message action tooltip, {0} is sdcard", "Eject SD Card {0}").format(job._sdcard) ) message._sdcard = job._sdcard message.actionTriggered.connect(self._onMessageActionTriggered) @@ -447,3 +495,34 @@ class CuraApplication(QtApplication): def _onMessageActionTriggered(self, message, action): if action == "eject": self.getStorageDevice("LocalFileStorage").ejectRemovableDrive(message._sdcard) + + def _onFileLoaded(self, job): + mesh = job.getResult() + if mesh != None: + node = SceneNode() + + node.setSelectable(True) + node.setMeshData(mesh) + node.setName(os.path.basename(job.getFileName())) + + op = AddSceneNodeOperation(node, self.getController().getScene().getRoot()) + op.push() + + def _onJobFinished(self, job): + if type(job) is not ReadMeshJob: + return + + f = QUrl.fromLocalFile(job.getFileName()) + if f in self._recent_files: + self._recent_files.remove(f) + + self._recent_files.insert(0, f) + if len(self._recent_files) > 10: + del self._recent_files[10] + + pref = "" + for path in self._recent_files: + pref += path.toLocalFile() + ";" + + Preferences.getInstance().setValue("cura/recent_files", pref) + self.recentFilesChanged.emit() diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 8ddf206aea..9dcd15ad54 100644 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -11,6 +11,7 @@ from UM.Math.Float import Float from UM.Math.Vector import Vector from UM.Math.AxisAlignedBox import AxisAlignedBox from UM.Application import Application +from UM.Scene.Selection import Selection from . import PlatformPhysicsOperation from . import ConvexHullJob @@ -23,8 +24,12 @@ class PlatformPhysics: super().__init__() self._controller = controller self._controller.getScene().sceneChanged.connect(self._onSceneChanged) + self._controller.toolOperationStarted.connect(self._onToolOperationStarted) + self._controller.toolOperationStopped.connect(self._onToolOperationStopped) self._build_volume = volume + self._enabled = True + self._change_timer = QTimer() self._change_timer.setInterval(100) self._change_timer.setSingleShot(True) @@ -34,6 +39,9 @@ class PlatformPhysics: self._change_timer.start() def _onChangeTimerFinished(self): + if not self._enabled: + return + root = self._controller.getScene().getRoot() for node in BreadthFirstIterator(root): if node is root or type(node) is not SceneNode: @@ -41,6 +49,7 @@ class PlatformPhysics: bbox = node.getBoundingBox() if not bbox or not bbox.isValid(): + self._change_timer.start() continue # Mark the node as outside the build volume if the bounding box test fails. @@ -60,6 +69,8 @@ class PlatformPhysics: job = ConvexHullJob.ConvexHullJob(node) job.start() node._convex_hull_job = job + elif Selection.isSelected(node): + pass else: # Check for collisions between convex hulls for other_node in BreadthFirstIterator(root): @@ -80,13 +91,25 @@ class PlatformPhysics: if overlap is None: continue - move_vector.setX(-overlap[0]) - move_vector.setZ(-overlap[1]) + move_vector.setX(overlap[0] * 1.1) + move_vector.setZ(overlap[1] * 1.1) + + if hasattr(node, "_convex_hull"): + # Check for collisions between disallowed areas and the object + for area in self._build_volume.getDisallowedAreas(): + overlap = node._convex_hull.intersectsPolygon(area) + if overlap is None: + continue + + node._outside_buildarea = True if move_vector != Vector(): op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector) op.push() - if node.getBoundingBox().intersectsBox(self._build_volume.getBoundingBox()) == AxisAlignedBox.IntersectionResult.FullIntersection: - op = ScaleToBoundsOperation(node, self._build_volume.getBoundingBox()) - op.push() + def _onToolOperationStarted(self, tool): + self._enabled = False + + def _onToolOperationStopped(self, tool): + self._enabled = True + self._onChangeTimerFinished() diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index f36f2509cf..d0346fbbb5 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -38,6 +38,8 @@ class PrintInformation(QObject): def __init__(self, parent = None): super().__init__(parent) + self._enabled = False + self._minimum_print_time = Duration(None, self) self._current_print_time = Duration(None, self) self._maximum_print_time = Duration(None, self) @@ -51,8 +53,8 @@ class PrintInformation(QObject): self._time_quality_changed_timer.timeout.connect(self._updateTimeQualitySettings) self._interpolation_settings = { - "layer_height": { "minimum": "low", "maximum": "high", "curve": "linear" }, - "fill_sparse_density": { "minimum": "low", "maximum": "high", "curve": "linear" } + "layer_height": { "minimum": "low", "maximum": "high", "curve": "linear", "precision": 2 }, + "fill_sparse_density": { "minimum": "low", "maximum": "high", "curve": "linear", "precision": 0 } } self._low_quality_settings = None @@ -103,6 +105,21 @@ class PrintInformation(QObject): def timeQualityValue(self): return self._time_quality_value + def setEnabled(self, enabled): + if enabled != self._enabled: + self._enabled = enabled + + if self._enabled: + self._updateTimeQualitySettings() + self._onSlicingStarted() + + self.enabledChanged.emit() + + enabledChanged = pyqtSignal() + @pyqtProperty(bool, fset = setEnabled, notify = enabledChanged) + def enabled(self): + return self._enabled + @pyqtSlot(int) def setTimeQualityValue(self, value): if value != self._time_quality_value: @@ -132,7 +149,10 @@ class PrintInformation(QObject): self._material_amount = round(amount / 10) / 100 self.materialAmountChanged.emit() - if self._slice_reason != self.SliceReason.SettingChanged: + if not self._enabled: + return + + if self._slice_reason != self.SliceReason.SettingChanged or not self._minimum_print_time.valid or not self._maximum_print_time.valid: self._slice_pass = self.SlicePass.LowQualitySettings self._backend.slice(settings = self._low_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False) else: @@ -166,7 +186,7 @@ class PrintInformation(QObject): self._slice_reason = self.SliceReason.ActiveMachineChanged def _updateTimeQualitySettings(self): - if not self._current_settings: + if not self._current_settings or not self._enabled: return if not self._low_quality_settings: @@ -196,7 +216,7 @@ class PrintInformation(QObject): else: continue - setting_value = minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100) + setting_value = round(minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100), options["precision"]) self._current_settings.setSettingValueByKey(key, setting_value) def _onSceneChanged(self, source): diff --git a/cura_app.py b/cura_app.py old mode 100644 new mode 100755 diff --git a/icons/cura-128.png b/icons/cura-128.png new file mode 100644 index 0000000000..ecfe0d1e4e Binary files /dev/null and b/icons/cura-128.png differ diff --git a/icons/cura-32.png b/icons/cura-32.png new file mode 100644 index 0000000000..2ad22313e9 Binary files /dev/null and b/icons/cura-32.png differ diff --git a/icons/cura-48.png b/icons/cura-48.png new file mode 100644 index 0000000000..5fadb70f0f Binary files /dev/null and b/icons/cura-48.png differ diff --git a/icons/cura-64.png b/icons/cura-64.png new file mode 100644 index 0000000000..b6abad9ac1 Binary files /dev/null and b/icons/cura-64.png differ diff --git a/icons/cura.icns b/icons/cura.icns new file mode 100644 index 0000000000..eac1092e0e Binary files /dev/null and b/icons/cura.icns differ diff --git a/icons/cura.ico b/icons/cura.ico new file mode 100644 index 0000000000..c6b554301c Binary files /dev/null and b/icons/cura.ico differ diff --git a/installer.nsi b/installer.nsi index 5bd18a929b..35c7fcb596 100644 --- a/installer.nsi +++ b/installer.nsi @@ -1,5 +1,5 @@ !ifndef VERSION - !define VERSION 'BETA' + !define VERSION '15.05.96' !endif ; The name of the installer @@ -44,6 +44,9 @@ SetCompressor /SOLID lzma !define MUI_FINISHPAGE_RUN_TEXT "Start Cura ${VERSION}" !define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink" +;Add an option to show release notes +!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\release_notes.txt" + ; Pages ;!insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_DIRECTORY @@ -89,7 +92,7 @@ Section "Cura ${VERSION}" CreateDirectory "$SMPROGRAMS\Cura ${VERSION}" CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Uninstall Cura ${VERSION}.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk" "$INSTDIR\Cura.exe" '' "$INSTDIR\resources\cura.ico" 0 + CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk" "$INSTDIR\Cura.exe" '' "$INSTDIR\Cura.exe" 0 SectionEnd @@ -99,6 +102,15 @@ Function LaunchLink Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk"' FunctionEnd +Section "Install Visual Studio 2010 Redistributable" + SetOutPath "$INSTDIR" + File "vcredist_2010_20110908_x86.exe" + + IfSilent +2 + ExecWait '"$INSTDIR\vcredist_2010_20110908_x86.exe" /q /norestart' + +SectionEnd + ;Section "Install Arduino Drivers" ; ; Set output path to the driver directory. ; SetOutPath "$INSTDIR\drivers\" diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 7c52a3c6cb..9fbd7a47a1 100644 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -59,6 +59,8 @@ class CuraEngineBackend(Backend): self._save_polygons = True self._report_progress = True + self._enabled = True + self.backendConnected.connect(self._onBackendConnected) def getEngineCommand(self): @@ -86,6 +88,9 @@ class CuraEngineBackend(Backend): # If False, this method will do nothing when already slicing. True by default. # - report_progress: True if the slicing progress should be reported, False if not. Default is True. def slice(self, **kwargs): + if not self._enabled: + return + if self._slicing: if not kwargs.get("force_restart", True): return @@ -110,6 +115,9 @@ class CuraEngineBackend(Backend): if not objects: return #No point in slicing an empty build plate + if kwargs.get("settings", self._settings).hasErrorValue(): + return #No slicing if we have error values since those are by definition illegal values. + self._slicing = True self.slicingStarted.emit() @@ -232,3 +240,10 @@ class CuraEngineBackend(Backend): if self._restart: self._onChanged() self._restart = False + + def _onToolOperationStarted(self, tool): + self._enabled = False + + def _onToolOperationStopped(self, tool): + self._enabled = True + self._onChanged() diff --git a/plugins/CuraEngineBackend/Cura_pb2.py b/plugins/CuraEngineBackend/Cura_pb2.py index cf95bd2832..f97aaafc4d 100644 --- a/plugins/CuraEngineBackend/Cura_pb2.py +++ b/plugins/CuraEngineBackend/Cura_pb2.py @@ -1,6 +1,3 @@ -# Copyright (c) 2015 Ultimaker B.V. -# Cura is released under the terms of the AGPLv3 or higher. - # Generated by the protocol buffer compiler. DO NOT EDIT! # source: Cura.proto @@ -21,7 +18,7 @@ _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor.FileDescriptor( name='Cura.proto', package='Cura', - serialized_pb=_b('\n\nCura.proto\x12\x04\x43ura\"+\n\nObjectList\x12\x1d\n\x07objects\x18\x01 \x03(\x0b\x32\x0c.Cura.Object\"i\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12\x1f\n\x08settings\x18\x05 \x03(\x0b\x32\r.Cura.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"7\n\x10SlicedObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.Cura.SlicedObject\"7\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x1b\n\x06layers\x18\x02 \x03(\x0b\x32\x0b.Cura.Layer\"4\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x1f\n\x08polygons\x18\x02 \x03(\x0b\x32\r.Cura.Polygon\"\x9f\x01\n\x07Polygon\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.Cura.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\"b\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\".\n\x0bSettingList\x12\x1f\n\x08settings\x18\x01 \x03(\x0b\x32\r.Cura.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3') + serialized_pb=_b('\n\nCura.proto\x12\x04\x43ura\"+\n\nObjectList\x12\x1d\n\x07objects\x18\x01 \x03(\x0b\x32\x0c.Cura.Object\"i\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12\x1f\n\x08settings\x18\x05 \x03(\x0b\x32\r.Cura.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"7\n\x10SlicedObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.Cura.SlicedObject\"7\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x1b\n\x06layers\x18\x02 \x03(\x0b\x32\x0b.Cura.Layer\"W\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x02\x12\x11\n\tthickness\x18\x03 \x01(\x02\x12\x1f\n\x08polygons\x18\x04 \x03(\x0b\x32\r.Cura.Polygon\"\xdb\x01\n\x07Polygon\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.Cura.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\x12\x12\n\nline_width\x18\x03 \x01(\x02\"\x89\x01\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\x12\x0e\n\nInfillType\x10\x06\x12\x15\n\x11SupportInfillType\x10\x07\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\".\n\x0bSettingList\x12\x1f\n\x08settings\x18\x01 \x03(\x0b\x32\r.Cura.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3') ) _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -57,11 +54,19 @@ _POLYGON_TYPE = _descriptor.EnumDescriptor( name='SkirtType', index=5, number=5, options=None, type=None), + _descriptor.EnumValueDescriptor( + name='InfillType', index=6, number=6, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SupportInfillType', index=7, number=7, + options=None, + type=None), ], containing_type=None, options=None, - serialized_start=430, - serialized_end=528, + serialized_start=486, + serialized_end=623, ) _sym_db.RegisterEnumDescriptor(_POLYGON_TYPE) @@ -266,8 +271,22 @@ _LAYER = _descriptor.Descriptor( is_extension=False, extension_scope=None, options=None), _descriptor.FieldDescriptor( - name='polygons', full_name='Cura.Layer.polygons', index=1, - number=2, type=11, cpp_type=10, label=3, + name='height', full_name='Cura.Layer.height', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='thickness', full_name='Cura.Layer.thickness', index=2, + number=3, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='polygons', full_name='Cura.Layer.polygons', index=3, + number=4, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -284,7 +303,7 @@ _LAYER = _descriptor.Descriptor( oneofs=[ ], serialized_start=314, - serialized_end=366, + serialized_end=401, ) @@ -309,6 +328,13 @@ _POLYGON = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), + _descriptor.FieldDescriptor( + name='line_width', full_name='Cura.Polygon.line_width', index=2, + number=3, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), ], extensions=[ ], @@ -321,8 +347,8 @@ _POLYGON = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=369, - serialized_end=528, + serialized_start=404, + serialized_end=623, ) @@ -358,8 +384,8 @@ _GCODELAYER = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=530, - serialized_end=568, + serialized_start=625, + serialized_end=663, ) @@ -402,8 +428,8 @@ _OBJECTPRINTTIME = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=570, - serialized_end=638, + serialized_start=665, + serialized_end=733, ) @@ -432,8 +458,8 @@ _SETTINGLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=640, - serialized_end=686, + serialized_start=735, + serialized_end=781, ) @@ -469,8 +495,8 @@ _SETTING = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=688, - serialized_end=726, + serialized_start=783, + serialized_end=821, ) @@ -499,8 +525,8 @@ _GCODEPREFIX = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=728, - serialized_end=755, + serialized_start=823, + serialized_end=850, ) _OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT diff --git a/plugins/CuraEngineBackend/LayerData.py b/plugins/CuraEngineBackend/LayerData.py index 546397e460..c793c17504 100644 --- a/plugins/CuraEngineBackend/LayerData.py +++ b/plugins/CuraEngineBackend/LayerData.py @@ -2,10 +2,13 @@ # Cura is released under the terms of the AGPLv3 or higher. from UM.Mesh.MeshData import MeshData +from UM.Mesh.MeshBuilder import MeshBuilder from UM.Math.Color import Color +from UM.Math.Vector import Vector import numpy import math +import copy class LayerData(MeshData): def __init__(self): @@ -13,12 +16,19 @@ class LayerData(MeshData): self._layers = {} self._element_counts = {} - def addPolygon(self, layer, type, data): + def addLayer(self, layer): if layer not in self._layers: - self._layers[layer] = [] + self._layers[layer] = Layer(layer) - p = Polygon(self, type, data) - self._layers[layer].append(p) + def addPolygon(self, layer, type, data, line_width): + if layer not in self._layers: + self.addLayer(layer) + + p = Polygon(self, type, data, line_width) + self._layers[layer].polygons.append(p) + + def getLayer(self, layer): + return self._layers[layer] def getLayers(self): return self._layers @@ -26,14 +36,134 @@ class LayerData(MeshData): def getElementCounts(self): return self._element_counts - def build(self): - for layer, data in self._layers.items(): - if layer not in self._element_counts: - self._element_counts[layer] = [] + def setLayerHeight(self, layer, height): + if layer not in self._layers: + self.addLayer(layer) - for polygon in data: - polygon.build() - self._element_counts[layer].append(polygon.elementCount) + self._layers[layer].setHeight(height) + + def setLayerThickness(self, layer, thickness): + if layer not in self._layers: + self.addLayer(layer) + + self._layers[layer].setThickness(thickness) + + def build(self): + vertex_count = 0 + for layer, data in self._layers.items(): + vertex_count += data.vertexCount() + + vertices = numpy.empty((vertex_count, 3), numpy.float32) + colors = numpy.empty((vertex_count, 4), numpy.float32) + indices = numpy.empty((vertex_count, 2), numpy.int32) + + offset = 0 + for layer, data in self._layers.items(): + offset = data.build(offset, vertices, colors, indices) + self._element_counts[layer] = data.elementCount + + self.addVertices(vertices) + self.addColors(colors) + self.addIndices(indices.flatten()) + +class Layer(): + def __init__(self, id): + self._id = id + self._height = 0.0 + self._thickness = 0.0 + self._polygons = [] + self._element_count = 0 + + @property + def height(self): + return self._height + + @property + def thickness(self): + return self._thickness + + @property + def polygons(self): + return self._polygons + + @property + def elementCount(self): + return self._element_count + + def setHeight(self, height): + self._height = height + + def setThickness(self, thickness): + self._thickness = thickness + + def vertexCount(self): + result = 0 + for polygon in self._polygons: + result += polygon.vertexCount() + + return result + + def build(self, offset, vertices, colors, indices): + result = offset + for polygon in self._polygons: + if polygon._type == Polygon.InfillType or polygon._type == Polygon.SupportInfillType: + continue + + polygon.build(result, vertices, colors, indices) + result += polygon.vertexCount() + self._element_count += polygon.elementCount + + return result + + def createMesh(self): + builder = MeshBuilder() + + for polygon in self._polygons: + poly_color = polygon.getColor() + + points = numpy.copy(polygon.data) + if polygon.type == Polygon.InfillType or polygon.type == Polygon.SkinType or polygon.type == Polygon.SupportInfillType: + points[:,1] -= 0.01 + + # Calculate normals for the entire polygon using numpy. + normals = numpy.copy(points) + normals[:,1] = 0.0 # We are only interested in 2D normals + + # Calculate the edges between points. + # The call to numpy.roll shifts the entire array by one so that + # we end up subtracting each next point from the current, wrapping + # around. This gives us the edges from the next point to the current + # point. + normals[:] = normals[:] - numpy.roll(normals, -1, axis = 0) + # Calculate the length of each edge using standard Pythagoras + lengths = numpy.sqrt(normals[:,0] ** 2 + normals[:,2] ** 2) + # The normal of a 2D vector is equal to its x and y coordinates swapped + # and then x inverted. This code does that. + normals[:,[0, 2]] = normals[:,[2, 0]] + normals[:,0] *= -1 + + # Normalize the normals. + normals[:,0] /= lengths + normals[:,2] /= lengths + + # Scale all by the line width of the polygon so we can easily offset. + normals *= (polygon.lineWidth / 2) + + #TODO: Use numpy magic to perform the vertex creation to speed up things. + for i in range(len(points)): + start = points[i - 1] + end = points[i] + + normal = normals[i - 1] + + point1 = Vector(data = start - normal) + point2 = Vector(data = start + normal) + point3 = Vector(data = end + normal) + point4 = Vector(data = end - normal) + + builder.addQuad(point1, point2, point3, point4, color = poly_color) + + return builder.getData() class Polygon(): NoneType = 0 @@ -42,43 +172,58 @@ class Polygon(): SkinType = 3 SupportType = 4 SkirtType = 5 + InfillType = 6 + SupportInfillType = 7 - def __init__(self, mesh, type, data): + def __init__(self, mesh, type, data, line_width): super().__init__() self._mesh = mesh self._type = type self._data = data + self._line_width = line_width / 1000 + + def build(self, offset, vertices, colors, indices): + self._begin = offset + + color = self.getColor() + color.setValues(color.r * 0.5, color.g * 0.5, color.b * 0.5, color.a) + + for i in range(len(self._data)): + vertices[offset + i, :] = self._data[i, :] + colors[offset + i, 0] = color.r + colors[offset + i, 1] = color.g + colors[offset + i, 2] = color.b + colors[offset + i, 3] = color.a - def build(self): - self._begin = self._mesh._vertex_count - self._mesh.addVertices(self._data) self._end = self._begin + len(self._data) - 1 - color = None - if self._type == self.Inset0Type: - color = [1, 0, 0, 1] - elif self._type == self.InsetXType: - color = [0, 1, 0, 1] - elif self._type == self.SkinType: - color = [1, 1, 0, 1] - elif self._type == self.SupportType: - color = [0, 1, 1, 1] - elif self._type == self.SkirtType: - color = [0, 1, 1, 1] - else: - color = [1, 1, 1, 1] - - colors = [color for i in range(len(self._data))] - self._mesh.addColors(numpy.array(colors, dtype=numpy.float32)) - - indices = [] for i in range(self._begin, self._end): - indices.append(i) - indices.append(i + 1) + indices[i, 0] = i + indices[i, 1] = i + 1 - indices.append(self._end) - indices.append(self._begin) - self._mesh.addIndices(numpy.array(indices, dtype=numpy.int32)) + indices[self._end, 0] = self._end + indices[self._end, 1] = self._begin + + def getColor(self): + if self._type == self.Inset0Type: + return Color(1.0, 0.0, 0.0, 1.0) + elif self._type == self.InsetXType: + return Color(0.0, 1.0, 0.0, 1.0) + elif self._type == self.SkinType: + return Color(1.0, 1.0, 0.0, 1.0) + elif self._type == self.SupportType: + return Color(0.0, 1.0, 1.0, 1.0) + elif self._type == self.SkirtType: + return Color(0.0, 1.0, 1.0, 1.0) + elif self._type == self.InfillType: + return Color(1.0, 1.0, 0.0, 1.0) + elif self._type == self.SupportInfillType: + return Color(0.0, 1.0, 1.0, 1.0) + else: + return Color(1.0, 1.0, 1.0, 1.0) + + def vertexCount(self): + return len(self._data) @property def type(self): @@ -90,4 +235,8 @@ class Polygon(): @property def elementCount(self): - return (self._end - self._begin) * 2 #The range of vertices multiplied by 2 since each vertex is used twice + return ((self._end - self._begin) + 1) * 2 #The range of vertices multiplied by 2 since each vertex is used twice + + @property + def lineWidth(self): + return self._line_width diff --git a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py b/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py index 804338e4dc..4c6e0fd2ea 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py @@ -7,18 +7,30 @@ from UM.Scene.SceneNode import SceneNode from UM.Application import Application from UM.Mesh.MeshData import MeshData +from UM.Message import Message +from UM.i18n import i18nCatalog + from . import LayerData import numpy import struct +catalog = i18nCatalog("cura") + class ProcessSlicedObjectListJob(Job): def __init__(self, message): super().__init__() self._message = message self._scene = Application.getInstance().getController().getScene() + self._progress = None + Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) + def run(self): + if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView": + self._progress = Message(catalog.i18nc("Layers View mode", "Layers"), 0, False, 0) + self._progress.show() + objectIdMap = {} new_node = SceneNode() ## Put all nodes in a dict identified by ID @@ -32,39 +44,67 @@ class ProcessSlicedObjectListJob(Job): settings = Application.getInstance().getActiveMachine() layerHeight = settings.getSettingValueByKey("layer_height") + center = None + if not settings.getSettingValueByKey("machine_center_is_zero"): + center = numpy.array([settings.getSettingValueByKey("machine_width") / 2, 0.0, -settings.getSettingValueByKey("machine_depth") / 2]) + else: + center = numpy.array([0.0, 0.0, 0.0]) + + if self._progress: + self._progress.setProgress(2) + + mesh = MeshData() for object in self._message.objects: - try: + try: node = objectIdMap[object.id] except KeyError: continue - - mesh = MeshData() layerData = LayerData.LayerData() for layer in object.layers: + layerData.addLayer(layer.id) + layerData.setLayerHeight(layer.id, layer.height) + layerData.setLayerThickness(layer.id, layer.thickness) for polygon in layer.polygons: points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. points = numpy.asarray(points, dtype=numpy.float32) points /= 1000 - points = numpy.insert(points, 1, layer.id * layerHeight, axis = 1) + points = numpy.insert(points, 1, (layer.height / 1000), axis = 1) points[:,2] *= -1 - if not settings.getSettingValueByKey("machine_center_is_zero"): - center = [settings.getSettingValueByKey("machine_width") / 2, 0.0, -settings.getSettingValueByKey("machine_depth") / 2] - points -= numpy.array(center) + points -= numpy.array(center) - #points = numpy.pad(points, ((0,0), (0,1)), "constant", constant_values=(0.0, 1.0)) - #inverse = node.getWorldTransformation().getInverse().getData() - #points = points.dot(inverse) - #points = points[:,0:3] + layerData.addPolygon(layer.id, polygon.type, points, polygon.line_width) - layerData.addPolygon(layer.id, polygon.type, points) + if self._progress: + self._progress.setProgress(50) + + # We are done processing all the layers we got from the engine, now create a mesh out of the data + layerData.build() + mesh.layerData = layerData + + if self._progress: + self._progress.setProgress(100) - # We are done processing all the layers we got from the engine, now create a mesh out of the data - layerData.build() - mesh.layerData = layerData - new_node.setMeshData(mesh) new_node.setParent(self._scene.getRoot()) + + view = Application.getInstance().getController().getActiveView() + if view.getPluginId() == "LayerView": + view.resetLayerData() + + if self._progress: + self._progress.hide() + + def _onActiveViewChanged(self): + if self.isRunning(): + if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView": + if not self._progress: + self._progress = Message(catalog.i18nc("Layers View mode", "Layers"), 0, False, 0) + self._progress.show() + else: + if self._progress: + self._progress.hide() + diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 576feb6cb4..617dda411a 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -5,6 +5,15 @@ from UM.View.View import View from UM.View.Renderer import Renderer from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Resources import Resources +from UM.Event import Event, KeyEvent +from UM.Signal import Signal +from UM.Scene.Selection import Selection +from UM.Math.Color import Color +from UM.Mesh.MeshData import MeshData + +from cura.ConvexHullNode import ConvexHullNode + +from . import LayerViewProxy ## View used to display g-code paths. class LayerView(View): @@ -13,6 +22,25 @@ class LayerView(View): self._material = None self._num_layers = 0 self._layer_percentage = 0 # what percentage of layers need to be shown (SLider gives value between 0 - 100) + self._proxy = LayerViewProxy.LayerViewProxy() + self._controller.getScene().sceneChanged.connect(self._onSceneChanged) + self._max_layers = 10 + self._current_layer_num = 10 + self._current_layer_mesh = None + + self._solid_layers = 5 + + def getCurrentLayer(self): + return self._current_layer_num + + def _onSceneChanged(self, node): + self.calculateMaxLayers() + + def getMaxLayers(self): + return self._max_layers + + def resetLayerData(self): + self._current_layer_mesh = None def beginRendering(self): scene = self.getController().getScene() @@ -23,32 +51,110 @@ class LayerView(View): self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "vertexcolor.frag")) self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0]) + self._selection_material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag")) + self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128)) + for node in DepthFirstIterator(scene.getRoot()): + # We do not want to render ConvexHullNode as it conflicts with the bottom layers. + # However, it is somewhat relevant when the node is selected, so do render it then. + if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()): + continue + if not node.render(renderer): if node.getMeshData() and node.isVisible(): + if Selection.isSelected(node): + renderer.queueNode(node, material = self._selection_material, transparent = True) + try: layer_data = node.getMeshData().layerData except AttributeError: continue - if self._layer_percentage < 100: + # Render all layers below a certain number as line mesh instead of vertices. + if self._current_layer_num - self._solid_layers > -1: start = 0 - end_layer = round(len(layer_data.getLayers()) * (self._layer_percentage / 100)) end = 0 - element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): - end += sum(counts) - - if layer >= end_layer: + if layer + self._solid_layers > self._current_layer_num: break + end += counts + # This uses glDrawRangeElements internally to only draw a certain range of lines. renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end) - else: - renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines) - + + # We currently recreate the current "solid" layers every time a + if not self._current_layer_mesh: + self._current_layer_mesh = MeshData() + for i in range(self._solid_layers): + layer = self._current_layer_num - i + if layer < 0: + continue + + layer_mesh = layer_data.getLayer(layer).createMesh() + if not layer_mesh or layer_mesh.getVertices() is None: + continue + + self._current_layer_mesh.addVertices(layer_mesh.getVertices()) + + # Scale layer color by a brightness factor based on the current layer number + # This will result in a range of 0.5 - 1.0 to multiply colors by. + brightness = (2.0 - (i / self._solid_layers)) / 2.0 + self._current_layer_mesh.addColors(layer_mesh.getColors() * brightness) + + renderer.queueNode(node, mesh = self._current_layer_mesh, material = self._material) + def setLayer(self, value): - self._layer_percentage = value - + if self._current_layer_num != value: + self._current_layer_num = value + if self._current_layer_num < 0: + self._current_layer_num = 0 + if self._current_layer_num > self._max_layers: + self._current_layer_num = self._max_layers + + self._current_layer_mesh = None + self.currentLayerNumChanged.emit() + + currentLayerNumChanged = Signal() + + def calculateMaxLayers(self): + scene = self.getController().getScene() + renderer = self.getRenderer() + if renderer and self._material: + renderer.setRenderSelection(False) + self._old_max_layers = self._max_layers + ## Recalculate num max layers + new_max_layers = 0 + for node in DepthFirstIterator(scene.getRoot()): + if not node.render(renderer): + if node.getMeshData() and node.isVisible(): + try: + layer_data = node.getMeshData().layerData + except AttributeError: + continue + if new_max_layers < len(layer_data.getLayers()): + new_max_layers = len(layer_data.getLayers()) - 1 + + if new_max_layers > 0 and new_max_layers != self._old_max_layers: + self._max_layers = new_max_layers + self.maxLayersChanged.emit() + + # This makes sure we update the current layer + self.setLayer(int(self._max_layers * (self._current_layer_num / self._old_max_layers))) + + maxLayersChanged = Signal() + + ## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created + # as this caused some issues. + def getProxy(self, engine, script_engine): + return self._proxy + def endRendering(self): pass + + def event(self, event): + if event.type == Event.KeyPressEvent: + if event.key == KeyEvent.UpKey: + self.setLayer(self._current_layer_num + 1) + if event.key == KeyEvent.DownKey: + self.setLayer(self._current_layer_num - 1) diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index fc598bfb75..f1d78d78f9 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -20,10 +20,11 @@ Item anchors.right : parent.right orientation: Qt.Vertical minimumValue: 0; - maximumValue: 100; + maximumValue: UM.LayerView.numLayers; + stepSize: 1 - value: 100; - onValueChanged: UM.ActiveView.triggerAction("setLayer", value) + value: UM.LayerView.currentLayer + onValueChanged: UM.LayerView.setCurrentLayer(value) style: UM.Theme.styles.slider; } diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py new file mode 100644 index 0000000000..b6a266233c --- /dev/null +++ b/plugins/LayerView/LayerViewProxy.py @@ -0,0 +1,44 @@ +from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty +from UM.Application import Application +import LayerView +class LayerViewProxy(QObject): + def __init__(self, parent = None): + super().__init__(parent) + self._current_layer = 0 + self._controller = Application.getInstance().getController() + self._controller.activeViewChanged.connect(self._onActiveViewChanged) + self._onActiveViewChanged() + + currentLayerChanged = pyqtSignal() + maxLayersChanged = pyqtSignal() + + @pyqtProperty(int, notify = maxLayersChanged) + def numLayers(self): + active_view = self._controller.getActiveView() + #print("num max layers " , active_view.getMaxLayers()) + return active_view.getMaxLayers() + #return 100 + + @pyqtProperty(int, notify = currentLayerChanged) + def currentLayer(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + return active_view.getCurrentLayer() + + @pyqtSlot(int) + def setCurrentLayer(self, layer_num): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setLayer(layer_num) + + def _onLayerChanged(self): + self.currentLayerChanged.emit() + + def _onMaxLayersChanged(self): + self.maxLayersChanged.emit() + + def _onActiveViewChanged(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.currentLayerNumChanged.connect(self._onLayerChanged) + active_view.maxLayersChanged.connect(self._onMaxLayersChanged) \ No newline at end of file diff --git a/plugins/LayerView/__init__.py b/plugins/LayerView/__init__.py index 93aa856175..eb3ba4cdbe 100644 --- a/plugins/LayerView/__init__.py +++ b/plugins/LayerView/__init__.py @@ -1,7 +1,8 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. -from . import LayerView +from . import LayerView, LayerViewProxy +from PyQt5.QtQml import qmlRegisterType, qmlRegisterSingletonType from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -21,6 +22,10 @@ def getMetaData(): } } +def createLayerViewProxy(engine, script_engine): + return LayerViewProxy.LayerViewProxy() def register(app): + layer_view = LayerView.LayerView() + qmlRegisterSingletonType(LayerViewProxy.LayerViewProxy, "UM", 1, 0, "LayerView", layer_view.getProxy) return { "view": LayerView.LayerView() } diff --git a/plugins/USBPrinting/PrinterConnection.py b/plugins/USBPrinting/PrinterConnection.py index ad231f5207..2ac8dbab0f 100644 --- a/plugins/USBPrinting/PrinterConnection.py +++ b/plugins/USBPrinting/PrinterConnection.py @@ -173,6 +173,10 @@ class PrinterConnection(SignalEmitter): Logger.log("i", "Could not establish connection on %s: %s. Device is not arduino based." %(self._serial_port,str(e))) except Exception as e: Logger.log("i", "Could not establish connection on %s, unknown reasons. Device is not arduino based." % self._serial_port) + + if not self._serial or not programmer.serial: + self._is_connecting = False + return # If the programmer connected, we know its an atmega based version. Not all that usefull, but it does give some debugging information. for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect) @@ -241,10 +245,17 @@ class PrinterConnection(SignalEmitter): ## Close the printer connection def close(self): if self._connect_thread.isAlive(): - self._connect_thread.join() + try: + self._connect_thread.join() + except Exception as e: + pass # This should work, but it does fail sometimes for some reason + if self._serial is not None: self.setIsConnected(False) - self._listen_thread.join() + try: + self._listen_thread.join() + except: + pass self._serial.close() self._serial = None diff --git a/plugins/USBPrinting/USBPrinterManager.py b/plugins/USBPrinting/USBPrinterManager.py index ba515594ae..42081b184b 100644 --- a/plugins/USBPrinting/USBPrinterManager.py +++ b/plugins/USBPrinting/USBPrinterManager.py @@ -19,8 +19,7 @@ from PyQt5.QtQuick import QQuickView from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal from UM.i18n import i18nCatalog -i18n_catalog = i18nCatalog("uranium") - +i18n_catalog = i18nCatalog("cura") class USBPrinterManager(QObject, SignalEmitter, Extension): def __init__(self, parent = None): @@ -40,6 +39,7 @@ class USBPrinterManager(QObject, SignalEmitter, Extension): self._error_message = "" ## Add menu item to top menu of the application. + self.setMenuName("Firmware") self.addMenuItem(i18n_catalog.i18n("Update Firmware"), self.updateAllFirmware) pyqtError = pyqtSignal(str, arguments = ["amount"]) diff --git a/resources/i18n/ru/cura.po b/resources/i18n/ru/cura.po new file mode 100644 index 0000000000..d6016202c6 --- /dev/null +++ b/resources/i18n/ru/cura.po @@ -0,0 +1,91 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-05-07 16:35+0200\n" +"PO-Revision-Date: 2015-06-01 18:29+0300\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Last-Translator: \n" +"Language-Team: \n" +"X-Generator: Poedit 1.8.1\n" + +#: /home/ahiemstra/Projects/Ultimaker/cura/src/CuraApplication.py:91 +msgctxt "Save button tooltip" +msgid "Save to Disk" +msgstr "Сохранить на диск" + +#: /home/ahiemstra/Projects/Ultimaker/cura/src/CuraApplication.py:96 +msgctxt "Splash screen message" +msgid "Setting up scene..." +msgstr "Настройка сцены ..." + +#: /home/ahiemstra/Projects/Ultimaker/cura/src/CuraApplication.py:130 +msgctxt "Splash screen message" +msgid "Loading interface..." +msgstr "Загрузка интерфейса ..." + +#: /home/ahiemstra/Projects/Ultimaker/cura/src/CuraApplication.py:373 +#, python-brace-format +msgctxt "Save button tooltip. {0} is sd card name" +msgid "Save to SD Card {0}" +msgstr "Сохранить на SD карту {0}" + +#: /home/ahiemstra/Projects/Ultimaker/cura/src/CuraApplication.py:421 +#, python-brace-format +msgctxt "Saved to SD message, {0} is sdcard, {1} is filename" +msgid "Saved to SD Card {0} as {1}" +msgstr "Сохранено на SD карту {0} как {1}" + +#: /home/ahiemstra/Projects/Ultimaker/cura/src/CuraApplication.py:424 +msgctxt "Message action" +msgid "Eject" +msgstr "Извлечь" + +#: /home/ahiemstra/Projects/Ultimaker/cura/src/CuraApplication.py:426 +#, python-brace-format +msgctxt "Message action tooltip, {0} is sdcard" +msgid "Eject SD Card {0}" +msgstr "Извлечь SD карту {0}" + +#: /home/ahiemstra/Projects/Ultimaker/cura/plugins/CuraEngineBackend/__init__.py:13 +msgctxt "CuraEngine backend plugin description" +msgid "Provides the link to the CuraEngine slicing backend" +msgstr "Обеспечивает связь с Кура слайсинг сервером" + +#: /home/ahiemstra/Projects/Ultimaker/cura/plugins/USBPrinting/USBPrinterManager.py:40 +msgid "Update Firmware" +msgstr "Обновление прошивки" + +#: /home/ahiemstra/Projects/Ultimaker/cura/plugins/USBPrinting/__init__.py:13 +msgctxt "USB Printing plugin description" +msgid "Accepts G-Code and sends them to a printer. Plugin can also update firmware" +msgstr "Принимает G-коды и отправляет их на принтер. Плагин также может обновить прошивку." + +#: /home/ahiemstra/Projects/Ultimaker/cura/plugins/GCodeWriter/__init__.py:13 +msgctxt "GCode Writer Plugin Description" +msgid "Writes GCode to a file" +msgstr "Записывает G-код в файл " + +#: /home/ahiemstra/Projects/Ultimaker/cura/plugins/GCodeWriter/__init__.py:18 +msgctxt "GCode Writer File Description" +msgid "GCode File" +msgstr "G-код" + +#: /home/ahiemstra/Projects/Ultimaker/cura/plugins/LayerView/__init__.py:13 +msgctxt "Layer View plugin description" +msgid "Provides the Layer view." +msgstr "Обеспечивает просмотр слоев." + +#: /home/ahiemstra/Projects/Ultimaker/cura/plugins/LayerView/__init__.py:16 +msgctxt "Layers View mode" +msgid "Layers" +msgstr "Слой" diff --git a/resources/i18n/ru/cura_qt.po b/resources/i18n/ru/cura_qt.po new file mode 100644 index 0000000000..a3522227c4 --- /dev/null +++ b/resources/i18n/ru/cura_qt.po @@ -0,0 +1,430 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Qt-Contexts: true\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Project-Id-Version: Cura\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: ru\n" +"X-Generator: Poedit 1.8.1\n" + +#. About dialog title +#: ../resources/qml/AboutDialog.qml:12 +msgctxt "AboutDialog|" +msgid "About Cura" +msgstr "О Кура" + +#. About dialog application description +#: ../resources/qml/AboutDialog.qml:42 +msgctxt "AboutDialog|" +msgid "End-to-end solution for fused filament 3D printing." +msgstr "Комплексное решение для 3D печати по технологии послойного накладывание пластика." + +#. About dialog application author note +#: ../resources/qml/AboutDialog.qml:47 +msgctxt "AboutDialog|" +msgid "Cura has been developed by Ultimaker B.V. in cooperation with the community." +msgstr "Кура была разработана компании Ultimaker BV в сотрудничестве с сообществом." + +#. Close about dialog button +#: ../resources/qml/AboutDialog.qml:58 +msgctxt "AboutDialog|" +msgid "Close" +msgstr "Закрыть окно" + +#. Undo action +#: ../resources/qml/Actions.qml:37 +msgctxt "Actions|" +msgid "&Undo" +msgstr "&Отмена" + +#. Redo action +#: ../resources/qml/Actions.qml:45 +msgctxt "Actions|" +msgid "&Redo" +msgstr "&Повтор" + +#. Quit action +#: ../resources/qml/Actions.qml:53 +msgctxt "Actions|" +msgid "&Quit" +msgstr "&Выход" + +#. Preferences action +#: ../resources/qml/Actions.qml:61 +msgctxt "Actions|" +msgid "&Preferences..." +msgstr "&Настройки программы..." + +#. Add Printer action +#: ../resources/qml/Actions.qml:68 +msgctxt "Actions|" +msgid "&Add Printer..." +msgstr "&Добавит новый принтер" + +#. Configure Printers action +#: ../resources/qml/Actions.qml:74 +msgctxt "Actions|" +msgid "&Configure Printers" +msgstr "&Настройки принтера" + +#. Show Online Documentation action +#: ../resources/qml/Actions.qml:81 +msgctxt "Actions|" +msgid "Show Online &Documentation" +msgstr "Показать онлайн &справку" + +#. Report a Bug Action +#: ../resources/qml/Actions.qml:89 +msgctxt "Actions|" +msgid "Report a &Bug" +msgstr "Сообщить о &проблеме" + +#. About action +#: ../resources/qml/Actions.qml:96 +msgctxt "Actions|" +msgid "&About..." +msgstr "&О Кура" + +#. Delete selection action +#: ../resources/qml/Actions.qml:103 +msgctxt "Actions|" +msgid "Delete Selection" +msgstr "Удалить выбранное" + +#. Delete object action +#: ../resources/qml/Actions.qml:111 +msgctxt "Actions|" +msgid "Delete Object" +msgstr "Удалить объект" + +#. Center object action +#: ../resources/qml/Actions.qml:118 +msgctxt "Actions|" +msgid "Center Object on Platform" +msgstr "Расположить объект по центру" + +#. Duplicate object action +#: ../resources/qml/Actions.qml:124 +msgctxt "Actions|" +msgid "Duplicate Object" +msgstr "Умножить объект" + +#. Split object action +#: ../resources/qml/Actions.qml:130 +msgctxt "Actions|" +msgid "Split Object into Parts" +msgstr "Разбить объект на частей" + +#. Clear build platform action +#: ../resources/qml/Actions.qml:137 +msgctxt "Actions|" +msgid "Clear Build Platform" +msgstr "Очистить печатающую платформу" + +#. Reload all objects action +#: ../resources/qml/Actions.qml:144 +msgctxt "Actions|" +msgid "Reload All Objects" +msgstr "Перезагрузить все объекты" + +#. Reset all positions action +#: ../resources/qml/Actions.qml:150 +msgctxt "Actions|" +msgid "Reset All Object Positions" +msgstr "Сбросить все позиции объектов" + +#. Reset all positions action +#: ../resources/qml/Actions.qml:156 +msgctxt "Actions|" +msgid "Reset All Object Transformations" +msgstr "Сбросить все преобразования объектов" + +#. Open file action +#: ../resources/qml/Actions.qml:162 +msgctxt "Actions|" +msgid "&Open..." +msgstr "&Открыть..." + +#. Save file action +#: ../resources/qml/Actions.qml:170 +msgctxt "Actions|" +msgid "&Save..." +msgstr "&Сохранить..." + +#. Show engine log action +#: ../resources/qml/Actions.qml:178 +msgctxt "Actions|" +msgid "Show engine &log..." +msgstr "Показать журнал &слайсера" + +#. Add Printer dialog title +#. ---------- +#. Add Printer wizard page title +#: ../resources/qml/AddMachineWizard.qml:12 +#: ../resources/qml/AddMachineWizard.qml:19 +msgctxt "AddMachineWizard|" +msgid "Add Printer" +msgstr "Добавить новый принтер" + +#. Add Printer wizard page description +#: ../resources/qml/AddMachineWizard.qml:25 +msgctxt "AddMachineWizard|" +msgid "Please select the type of printer:" +msgstr "Выберите тип принтера:" + +#. Add Printer wizard field label +#: ../resources/qml/AddMachineWizard.qml:40 +msgctxt "AddMachineWizard|" +msgid "Printer Name:" +msgstr "Название принтера:" + +#. Add Printer wizarad button +#: ../resources/qml/AddMachineWizard.qml:53 +msgctxt "AddMachineWizard|" +msgid "Next" +msgstr "Дальше" + +#. Add Printer wizarad button +#: ../resources/qml/AddMachineWizard.qml:63 +msgctxt "AddMachineWizard|" +msgid "Cancel" +msgstr "Отменить" + +#. USB Printing dialog label, %1 is head temperature +#: ../plugins/USBPrinting/ControlWindow.qml:15 +#, qt-format +msgctxt "ControlWindow|" +msgid "Extruder Temperature %1" +msgstr "Температура экструдера %1" + +#. USB Printing dialog label, %1 is bed temperature +#: ../plugins/USBPrinting/ControlWindow.qml:20 +#, qt-format +msgctxt "ControlWindow|" +msgid "Bed Temperature %1" +msgstr "Температура платформы %1" + +#. USB Printing dialog start print button +#: ../plugins/USBPrinting/ControlWindow.qml:33 +msgctxt "ControlWindow|" +msgid "Print" +msgstr "Печать" + +#. USB Printing dialog cancel print button +#: ../plugins/USBPrinting/ControlWindow.qml:40 +msgctxt "ControlWindow|" +msgid "Cancel" +msgstr "Отменить" + +#. Cura application window title +#: ../resources/qml/Cura.qml:14 +msgctxt "Cura|" +msgid "Cura" +msgstr "Кура" + +#. File menu +#: ../resources/qml/Cura.qml:26 +msgctxt "Cura|" +msgid "&File" +msgstr "&Файл" + +#. Edit menu +#: ../resources/qml/Cura.qml:38 +msgctxt "Cura|" +msgid "&Edit" +msgstr "&Изменить" + +#. Machine menu +#: ../resources/qml/Cura.qml:50 +msgctxt "Cura|" +msgid "&Machine" +msgstr "&Принтер" + +#. Extensions menu +#: ../resources/qml/Cura.qml:76 +msgctxt "Cura|" +msgid "E&xtensions" +msgstr "&Расширения" + +#. Settings menu +#: ../resources/qml/Cura.qml:107 +msgctxt "Cura|" +msgid "&Settings" +msgstr "&Настройки" + +#. Help menu +#: ../resources/qml/Cura.qml:114 +msgctxt "Cura|" +msgid "&Help" +msgstr "&Помощь" + +#. View Mode toolbar button +#: ../resources/qml/Cura.qml:231 +msgctxt "Cura|" +msgid "View Mode" +msgstr "Режим просмотра" + +#. View preferences page title +#: ../resources/qml/Cura.qml:273 +msgctxt "Cura|" +msgid "View" +msgstr "Просмотр" + +#. File open dialog title +#: ../resources/qml/Cura.qml:370 +msgctxt "Cura|" +msgid "Open File" +msgstr "Открыть файл" + +#. File save dialog title +#: ../resources/qml/Cura.qml:386 +msgctxt "Cura|" +msgid "Save File" +msgstr "Сохранить файл" + +#. Engine Log dialog title +#: ../resources/qml/EngineLog.qml:11 +msgctxt "EngineLog|" +msgid "Engine Log" +msgstr "Журнал слайсера" + +#. Close engine log button +#: ../resources/qml/EngineLog.qml:30 +msgctxt "EngineLog|" +msgid "Close" +msgstr "Закрыть" + +#. Firmware update status label +#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:16 +msgctxt "FirmwareUpdateWindow|" +msgid "Starting firmware update, this may take a while." +msgstr "Начинается обновление прошивки, это может занять некоторое время." + +#. Firmware update status label +#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:21 +msgctxt "FirmwareUpdateWindow|" +msgid "Firmware update completed." +msgstr "Обновление прошивки завершено." + +#. Firmware update status label +#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:26 +msgctxt "FirmwareUpdateWindow|" +msgid "Updating firmware." +msgstr "Обновление прошивки." + +#. Print material amount save button label +#: ../resources/qml/SaveButton.qml:149 +#, qt-format +msgctxt "SaveButton|" +msgid "%1m material" +msgstr "%1m материал" + +#. Save button label +#: ../resources/qml/SaveButton.qml:191 +msgctxt "SaveButton|" +msgid "Please load a 3D model" +msgstr "Пожалуйста, загрузите 3D модель" + +#. Save button label +#: ../resources/qml/SaveButton.qml:194 +msgctxt "SaveButton|" +msgid "Calculating Print-time" +msgstr "Вычисляется время печати" + +#. Save button label +#: ../resources/qml/SaveButton.qml:197 +msgctxt "SaveButton|" +msgid "Estimated Print-time" +msgstr "Расчетное время печати" + +#. Simple configuration mode option +#: ../resources/qml/Sidebar.qml:105 +msgctxt "Sidebar|" +msgid "Simple" +msgstr "Простой" + +#. Advanced configuration mode option +#: ../resources/qml/Sidebar.qml:107 +msgctxt "Sidebar|" +msgid "Advanced" +msgstr "Продвинутый" + +#. Configuration mode label +#: ../resources/qml/SidebarHeader.qml:26 +msgctxt "SidebarHeader|" +msgid "Mode:" +msgstr "Режим:" + +#. Machine selection label +#: ../resources/qml/SidebarHeader.qml:70 +msgctxt "SidebarHeader|" +msgid "Machine:" +msgstr "Принтер:" + +#. Sidebar header label +#: ../resources/qml/SidebarHeader.qml:117 +msgctxt "SidebarHeader|" +msgid "Print Setup" +msgstr "Настройка Печати" + +#. Sidebar configuration label +#: ../resources/qml/SidebarSimple.qml:40 +msgctxt "SidebarSimple|" +msgid "No Model Loaded" +msgstr "Модель не загружена" + +#. Sidebar configuration label +#: ../resources/qml/SidebarSimple.qml:45 +msgctxt "SidebarSimple|" +msgid "Calculating..." +msgstr "Высчитывается..." + +#. Sidebar configuration label +#: ../resources/qml/SidebarSimple.qml:50 +msgctxt "SidebarSimple|" +msgid "Estimated Print Time" +msgstr "Расчетное время печати" + +#. Quality slider label +#: ../resources/qml/SidebarSimple.qml:87 +msgctxt "SidebarSimple|" +msgid "" +"Minimum\n" +"Draft" +msgstr "" +"Минимальная \n" +"тяга" + +#. Quality slider label +#: ../resources/qml/SidebarSimple.qml:97 +msgctxt "SidebarSimple|" +msgid "" +"Maximum\n" +"Quality" +msgstr "" +"Максимальное\n" +"Качество" + +#. Setting checkbox +#: ../resources/qml/SidebarSimple.qml:109 +msgctxt "SidebarSimple|" +msgid "Enable Support" +msgstr "Включить Поддержку" + +#. View configuration page title +#: ../resources/qml/ViewPage.qml:9 +msgctxt "ViewPage|" +msgid "View" +msgstr "Просмотр" + +#. Display Overhang preference checkbox +#: ../resources/qml/ViewPage.qml:24 +msgctxt "ViewPage|" +msgid "Display Overhang" +msgstr "Показать где есть нависающие части" diff --git a/resources/i18n/ru/fdmprinter.json.po b/resources/i18n/ru/fdmprinter.json.po new file mode 100644 index 0000000000..63e0854aae --- /dev/null +++ b/resources/i18n/ru/fdmprinter.json.po @@ -0,0 +1,1843 @@ +msgid "" +msgstr "" +"Project-Id-Version: Uranium json setting files\n" +"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n" +"POT-Creation-Date: 2015-05-08 12:17+0000\n" +"PO-Revision-Date: 2015-06-09 18:29+0300\n" +"Language-Team: LANGUAGE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Last-Translator: \n" +"Language: ru\n" +"X-Generator: Poedit 1.8.1\n" + +#: fdmprinter.json +msgctxt "resolution label" +msgid "Quality" +msgstr "Качество" + +#: fdmprinter.json +msgctxt "layer_height label" +msgid "Layer Height" +msgstr "Высота слоя" + +#: fdmprinter.json +msgctxt "layer_height description" +msgid "" +"The height of each layer, in mm. Normal quality prints are 0.1mm, high " +"quality is 0.06mm. You can go up to 0.25mm with an Ultimaker for very fast " +"prints at low quality. For most purposes, layer heights between 0.1 and " +"0.2mm give a good tradeoff of speed and surface finish." +msgstr "" +"Высота каждого слоя в мм. Нормальное качество печати — это 0.1 мм, а высокое " +"качество печати — это 0.06 мм. Для очень быстрой печати и низкое качество " +"печати, можно поставит высота слоя до 0.25 мм. В большинство случаев печати, " +"используется высота слоя между 0.1 и 0.2 мм, которая дает хорошее качество." + +#: fdmprinter.json +msgctxt "layer_height_0 label" +msgid "Initial Layer Thickness" +msgstr "Первоначальная толщина слоя" + +#: fdmprinter.json +msgctxt "layer_height_0 description" +msgid "" +"The layer thickness of the bottom layer. A thicker bottom layer makes " +"sticking to the bed easier." +msgstr "" +"Толщина нижнего слоя. Чем толще будет нижний слой, тем лучше будет " +"прилипание к платформе." + +#: fdmprinter.json +msgctxt "shell_thickness label" +msgid "Shell Thickness" +msgstr "Толщина стенки" + +#: fdmprinter.json +msgctxt "shell_thickness description" +msgid "" +"The thickness of the outside shell in the horizontal and vertical direction. " +"This is used in combination with the nozzle size to define the number of " +"perimeter lines and the thickness of those perimeter lines. This is also " +"used to define the number of solid top and bottom layers." +msgstr "" +"Толщина внешней стенки в горизонтальном и вертикальном направлении. Это " +"используется в сочетании с размера сопла, для определения количества линий " +"периметра и толщина этих линий периметра. Это также используется для " +"определения количество верхних и нижних слоев." + +#: fdmprinter.json +msgctxt "wall_thickness label" +msgid "Wall Thickness" +msgstr "Толщина стенки" + +#: fdmprinter.json +msgctxt "wall_thickness description" +msgid "" +"The thickness of the outside walls in the horizontal direction. This is used " +"in combination with the nozzle size to define the number of perimeter lines " +"and the thickness of those perimeter lines." +msgstr "" +"Толщина внешней стенки в горизонтальном направлении. Это используется в " +"сочетании с размера сопла для определения количество линий периметра и " +"толщина этих линий периметра." + +#: fdmprinter.json +msgctxt "wall_line_count label" +msgid "Wall Line Count" +msgstr "Количество линий стенки" + +#: fdmprinter.json +msgctxt "wall_line_count description" +msgid "" +"Number of shell lines. This these lines are called perimeter lines in other " +"tools and impact the strength and structural integrity of your print." +msgstr "" +"Количество линий стенки. Эти линии называются линиями по периметру и влияют " +"на ударной прочности и структурной целостности вашей печати." + +#: fdmprinter.json +msgctxt "wall_line_width label" +msgid "Wall Line Width" +msgstr "Ширина линий стенки" + +#: fdmprinter.json +msgctxt "wall_line_width description" +msgid "" +"Width of a single shell line. Each line of the shell will be printed with " +"this width in mind." +msgstr "" +"Ширина одной линий стенки. Каждая линия стенки, будет напечатанная согласно " +"выбранной шириной." + +#: fdmprinter.json +msgctxt "wall_line_width_0 label" +msgid "First Wall Line Width" +msgstr "Ширина первой линий стенки" + +#: fdmprinter.json +msgctxt "wall_line_width_0 description" +msgid "" +"Width of the outermost shell line. By printing a thinner outermost wall line " +"you can print higher details with a larger nozzle." +msgstr "" +"Ширина внешней стенки. При печати тонкой внешней стенки, Вы можете " +"распечатать высокие детали с большим соплом." + +#: fdmprinter.json +msgctxt "wall_line_width_x label" +msgid "Other Walls Line Width" +msgstr "Ширина линий остальных стенок" + +#: fdmprinter.json +msgctxt "wall_line_width_x description" +msgid "" +"Width of a single shell line for all shell lines except the outermost one." +msgstr "" +"Ширина одной линий стенки для всех линий стенки за исключением на самых " +"крайних." + +#: fdmprinter.json +msgctxt "skirt_line_width label" +msgid "Skirt line width" +msgstr "Ширина линий контура" + +#: fdmprinter.json +msgctxt "skirt_line_width description" +msgid "Width of a single skirt line." +msgstr "Ширина одной линий контура" + +#: fdmprinter.json +msgctxt "skin_line_width label" +msgid "Top/bottom line width" +msgstr "Ширина Верхней/Нижней линий" + +#: fdmprinter.json +msgctxt "skin_line_width description" +msgid "" +"Width of a single top/bottom printed line. Which are used to fill up the top/" +"bottom areas of a print." +msgstr "" +"Ширина одной верхней/нижней линий, которые используются для заполнения " +"верхней/нижней область печатающего объекта." + +#: fdmprinter.json +msgctxt "infill_line_width label" +msgid "Infill line width" +msgstr "Ширина линий заполнения" + +#: fdmprinter.json +msgctxt "infill_line_width description" +msgid "Width of the inner infill printed lines." +msgstr "Ширина линий внутреннего заполнения." + +#: fdmprinter.json +msgctxt "support_line_width label" +msgid "Support line width" +msgstr "Ширина линий поддержек" + +#: fdmprinter.json +msgctxt "support_line_width description" +msgid "Width of the printed support structures lines." +msgstr "Ширина линий поддерживающих структур." + +#: fdmprinter.json +msgctxt "top_bottom_thickness label" +msgid "Bottom/Top Thickness" +msgstr "Толщина верхнего/нижнего слоя" + +#: fdmprinter.json +msgctxt "top_bottom_thickness description" +msgid "" +"This controls the thickness of the bottom and top layers, the amount of " +"solid layers put down is calculated by the layer thickness and this value. " +"Having this value a multiple of the layer thickness makes sense. And keep it " +"near your wall thickness to make an evenly strong part." +msgstr "" +"Это контролирует толщину нижнего и верхнего слоев. Количество сплошных слоев " +"определяется толщины слоя и этим значением. Имея это значение, имеет смысл " +"использовать многократную толщину слоя и при этом приблизительно выровнять " +"ее с толщиной стенки, чтобы сделать равномерно прочный объект." + +#: fdmprinter.json +msgctxt "top_thickness label" +msgid "Top Thickness" +msgstr "Толщина верхнего слоя" + +#: fdmprinter.json +msgctxt "top_thickness description" +msgid "" +"This controls the thickness of the top layers. The number of solid layers " +"printed is calculated from the layer thickness and this value. Having this " +"value be a multiple of the layer thickness makes sense. And keep it nearto " +"your wall thickness to make an evenly strong part." +msgstr "" +"Это контролирует толщину верхних слоев. Количество сплошных слоев " +"определяется толщины слоя и этим значением. Имея это значение, имеет смысл " +"использовать многократную толщину слоя и при этом приблизительно выровнять " +"ее с толщиной стенки, чтобы сделать равномерно прочный объект." + +#: fdmprinter.json +msgctxt "top_layers label" +msgid "Top Layers" +msgstr "Верхние слой" + +#: fdmprinter.json +msgctxt "top_layers description" +msgid "This controls the amount of top layers." +msgstr "Это контролирует количество верхних слоев." + +#: fdmprinter.json +msgctxt "bottom_thickness label" +msgid "Bottom Thickness" +msgstr "Толщина нижнего слоя" + +#: fdmprinter.json +msgctxt "bottom_thickness description" +msgid "" +"This controls the thickness of the bottom layers. The number of solid layers " +"printed is calculated from the layer thickness and this value. Having this " +"value be a multiple of the layer thickness makes sense. And keep it near to " +"your wall thickness to make an evenly strong part." +msgstr "" +"Это контролирует толщину нижних слоев. Количество сплошных слоев " +"определяется толщины слоя и этим значением. Имея это значение, имеет смысл " +"использовать многократную толщину слоя и при этом приблизительно выровнять " +"ее с толщиной стенки, чтобы сделать равномерно прочный объект." + +#: fdmprinter.json +msgctxt "bottom_layers label" +msgid "Bottom Layers" +msgstr "Нижние слой" + +#: fdmprinter.json +msgctxt "bottom_layers description" +msgid "This controls the amount of bottom layers." +msgstr "Это контролирует количество нижних слоев." + +#: fdmprinter.json +msgctxt "wall_overlap_avoid_enabled label" +msgid "Avoid Overlapping Walls" +msgstr "Избежать перекрывание стен" + +#: fdmprinter.json +msgctxt "wall_overlap_avoid_enabled description" +msgid "" +"Remove parts of a wall which share an overlap which would result in " +"overextrusion in some places. These overlaps occur in thin pieces in a model " +"and sharp corners." +msgstr "" +"Удалить части стен, которые разделяют перекрытие, которое в некоторых местах " +"может привести к увеличении экструзии. Эти перекрытия появляются в модели с " +"тонких частей и острых углов." + +#: fdmprinter.json +msgctxt "top_bottom_pattern label" +msgid "Bottom/Top Pattern" +msgstr "Нижняя/Верхняя структура" + +#: fdmprinter.json +msgctxt "top_bottom_pattern description" +msgid "" +"Pattern of the top/bottom solid fill. This normally is done with lines to " +"get the best possible finish, but in some cases a concentric fill gives a " +"nicer end result." +msgstr "Структура верхнего/нижнего заполнения." + +#: fdmprinter.json +msgctxt "skin_outline_count label" +msgid "Skin Perimeter Line Count" +msgstr "Количество линий периметра оболочки" + +#: fdmprinter.json +msgctxt "skin_outline_count description" +msgid "" +"Number of lines around skin regions. Using one or two skin perimeter lines " +"can greatly improve on roofs which would start in the middle of infill cells." +msgstr "" +"Количество линий вокруг оболочки. Использование одного или двух линий по " +"периметру оболочки может значительно улучшить покрытия, которые начнутся в " +"середине заполняющих сеток." + +#: fdmprinter.json +msgctxt "xy_offset label" +msgid "Horizontal expansion" +msgstr "Горизонтальное расширение" + +#: fdmprinter.json +msgctxt "xy_offset description" +msgid "" +"Amount of offset applied all polygons in each layer. Positive values can " +"compensate for too big holes; negative values can compensate for too small " +"holes." +msgstr "" +"Количество всех смещении полигонов в каждый слой. Положительные значения, " +"компенсируют для слишком большие отверстия; а отрицательные значения, " +"компенсируют для очень маленькие отверстия." + +#: fdmprinter.json +msgctxt "material label" +msgid "Material" +msgstr "Материал" + +#: fdmprinter.json +msgctxt "material_print_temperature label" +msgid "Printing Temperature" +msgstr "Температура печати" + +#: fdmprinter.json +msgctxt "material_print_temperature description" +msgid "" +"The temperature used for printing. Set at 0 to pre-heat yourself. For PLA a " +"value of 210C is usually used.\n" +"For ABS a value of 230C or higher is required." +msgstr "" +"Температура, используемая для печати. Установите на значение 0 для " +"предварительного нагрева. Для PLA обычно используется температурный режим " +"210C.\n" +"Для ABS обычно используется температурный режим 230C или выше." + +#: fdmprinter.json +msgctxt "material_bed_temperature label" +msgid "Bed Temperature" +msgstr "Температура платформы" + +#: fdmprinter.json +msgctxt "material_bed_temperature description" +msgid "" +"The temperature used for the heated printer bed. Set at 0 to pre-heat it " +"yourself." +msgstr "" +"Температура, используемая для нагревающей платформы. Установите значение 0 " +"для предварительного нагрева." + +#: fdmprinter.json +msgctxt "material_diameter label" +msgid "Diameter" +msgstr "Диаметр" + +#: fdmprinter.json +msgctxt "material_diameter description" +msgid "" +"The diameter of your filament needs to be measured as accurately as " +"possible.\n" +"If you cannot measure this value you will have to calibrate it, a higher " +"number means less extrusion, a smaller number generates more extrusion." +msgstr "" +"Диаметр вашей нити необходимо вымерить как можно точнее.\n" +"Если вы не можете измерить это значение, вы должны откалибровать его, " +"большое число означает меньше выдавливания материала, а меньшее число " +"производит больше выдавливания пластика." + +#: fdmprinter.json +msgctxt "material_flow label" +msgid "Flow" +msgstr "Выдавливания материала" + +#: fdmprinter.json +msgctxt "material_flow description" +msgid "" +"Flow compensation: the amount of material extruded is multiplied by this " +"value." +msgstr "" +"Компенсация выдавливания: количество выдавленного материала умножается с " +"этим значением." + +#: fdmprinter.json +msgctxt "retraction_enable label" +msgid "Enable Retraction" +msgstr "Включит откат материала" + +#: fdmprinter.json +msgctxt "retraction_enable description" +msgid "" +"Retract the filament when the nozzle is moving over a non-printed area. " +"Details about the retraction can be configured in the advanced tab." +msgstr "" +"Откатывает материал назад, когда печатающая головка перемещается над " +"областью. Подробности по поводу отката материала можете найти в вкладке " +"\"дополнительно\"." + +#: fdmprinter.json +msgctxt "retraction_speed label" +msgid "Retraction Speed" +msgstr "Скорость отката" + +#: fdmprinter.json +msgctxt "retraction_speed description" +msgid "" +"The speed at which the filament is retracted. A higher retraction speed " +"works better, but a very high retraction speed can lead to filament grinding." +msgstr "" +"Скорость, при которой происходит откат материала. Высокая скорость отката " +"материала работает лучше, но очень высокая скорость отката может привести к " +"перемалывания материала с стороне механизма подачи." + +#: fdmprinter.json +msgctxt "retraction_retract_speed label" +msgid "Retraction Retract Speed" +msgstr "Скорость отката" + +#: fdmprinter.json +msgctxt "retraction_retract_speed description" +msgid "" +"The speed at which the filament is retracted. A higher retraction speed " +"works better, but a very high retraction speed can lead to filament grinding." +msgstr "" +"Скорость, при которой происходит откат материала. Высокая скорость отката " +"материала работает лучше, но очень высокая скорость отката может привести к " +"перемалывания материала с стороне механизма подачи." + +#: fdmprinter.json +msgctxt "retraction_prime_speed label" +msgid "Retraction Prime Speed" +msgstr "Скорость после отката" + +#: fdmprinter.json +msgctxt "retraction_prime_speed description" +msgid "The speed at which the filament is pushed back after retraction." +msgstr "Скорость, при которой материал проталкивается обратно после отката." + +#: fdmprinter.json +msgctxt "retraction_amount label" +msgid "Retraction Distance" +msgstr "Расстояние отката" + +#: fdmprinter.json +msgctxt "retraction_amount description" +msgid "" +"The amount of retraction: Set at 0 for no retraction at all. A value of " +"4.5mm seems to generate good results for 3mm filament in Bowden-tube fed " +"printers." +msgstr "" +"Количество отката материала: Установите значение 0, чтобы не происходил " +"откат материала. Значение 4.5 мм достаточное, чтобы получить хорошие " +"результаты при использовании материал, диаметром 3 мм для принтеров где " +"подача материала происходит через Боуден-трубки." + +#: fdmprinter.json +msgctxt "retraction_min_travel label" +msgid "Retraction Minimum Travel" +msgstr "Минимальное перемещение" + +#: fdmprinter.json +msgctxt "retraction_min_travel description" +msgid "" +"The minimum distance of travel needed for a retraction to happen at all. " +"This helps ensure you do not get a lot of retractions in a small area." +msgstr "" +"Минимальное расстояние перемещения для того, чтобы произошел откат " +"материала. Эта настройка обеспечивает, чтобы не происходило слишком большое " +"количество откатов на небольшой области печати." + +#: fdmprinter.json +msgctxt "retraction_combing label" +msgid "Enable Combing" +msgstr "Включит обход" + +#: fdmprinter.json +msgctxt "retraction_combing description" +msgid "" +"Combing keeps the head within the interior of the print whenever possible " +"when traveling from one part of the print to another, and does not use " +"retraction. If combing is disabled the printer head moves straight from the " +"start point to the end point and it will always retract." +msgstr "" +"Обход, это когда печатающая головка позиционируется внутри области печати, " +"при перемещении от одной в другой точке без отката. Если откат выключен, " +"печатающая головка будет перемещаться от начальной до конечной точки " +"напрямую и всегда с откатом." + +#: fdmprinter.json +msgctxt "retraction_minimal_extrusion label" +msgid "Minimal Extrusion Before Retraction" +msgstr "Минимальное выдавливание перед откатом" + +#: fdmprinter.json +msgctxt "retraction_minimal_extrusion description" +msgid "" +"The minimum amount of extrusion that needs to happen between retractions. " +"If a retraction should happen before this minimum is reached, it will be " +"ignored. This avoids retracting repeatedly on the same piece of filament as " +"that can flatten the filament and cause grinding issues." +msgstr "" +"Минимальное количество выдавливаемого материала, необходимого для включения " +"отката. Если не достигнуто минимальное количество выдавливания материала, " +"тогда откат не произойдет. Это предотвращает, чтобы откат повторялся в одно " +"и тоже место, так как это приведет к перемалыванием нити." + +#: fdmprinter.json +msgctxt "retraction_hop label" +msgid "Z Hop when Retracting" +msgstr "Подъем по ось Z когда происходит откат" + +#: fdmprinter.json +msgctxt "retraction_hop description" +msgid "" +"Whenever a retraction is done, the head is lifted by this amount to travel " +"over the print. A value of 0.075 works well. This feature has a lot of " +"positive effect on delta towers." +msgstr "" +"Когда откат закончен, печатающий стол немного опускается. Нормальное " +"значение 0,075 мм. При перемещении печатающей головки от точки А к точке В, " +"уменьшается возможность цепляния модели или рисования полосы на поверхности " +"объекта." + +#: fdmprinter.json +msgctxt "speed label" +msgid "Speed" +msgstr "Скорость" + +#: fdmprinter.json +msgctxt "speed_print label" +msgid "Print Speed" +msgstr "Скорость печати" + +#: fdmprinter.json +msgctxt "speed_print description" +msgid "" +"The speed at which printing happens. A well-adjusted Ultimaker can reach " +"150mm/s, but for good quality prints you will want to print slower. Printing " +"speed depends on a lot of factors, so you will need to experiment with " +"optimal settings for this." +msgstr "" +"Скорость, при которой происходит процесс печати. Хорошо настроенный принтер, " +"может достигать скорость печати до 150 мм/сек, но, для получения хорошее " +"качество печати, рекомендуется печатать на низких скоростях. Скорость печати " +"зависит от многих факторов, поэтому для этого необходимо экспериментировать " +"с оптимальными настройками." + +#: fdmprinter.json +msgctxt "speed_infill label" +msgid "Infill Speed" +msgstr "Скорость заполнения" + +#: fdmprinter.json +msgctxt "speed_infill description" +msgid "" +"The speed at which infill parts are printed. Printing the infill faster can " +"greatly reduce printing time, but this can negatively affect print quality." +msgstr "" +"Скорость, при которой происходит заполнение. Печатать заполнения с более " +"высокой скоростью, значительно уменьшит время печати, но, это может " +"отрицательно повлиять на качество печати." + +#: fdmprinter.json +msgctxt "speed_wall label" +msgid "Shell Speed" +msgstr "Скорость печати стенки" + +#: fdmprinter.json +msgctxt "speed_wall description" +msgid "" +"The speed at which shell is printed. Printing the outer shell at a lower " +"speed improves the final skin quality." +msgstr "" +"Скорость, при которой печатается стенка. Печать внешней стенки с более " +"низкой скоростью улучшает качество поверхности." + +#: fdmprinter.json +msgctxt "speed_wall_0 label" +msgid "Outer Shell Speed" +msgstr "Скорость печати внешней стенки" + +#: fdmprinter.json +msgctxt "speed_wall_0 description" +msgid "" +"The speed at which outer shell is printed. Printing the outer shell at a " +"lower speed improves the final skin quality. However, having a large " +"difference between the inner shell speed and the outer shell speed will " +"effect quality in a negative way." +msgstr "" +"Скорость, при которой печатается внешняя стенка. Печать внешней стенки с " +"более низкой скоростью улучшает качество стенки. Но, большая разница между " +"скоростях печати внутренней и внешней стенки может отрицательно повлиять на " +"качество поверхности." + +#: fdmprinter.json +msgctxt "speed_wall_x label" +msgid "Inner Shell Speed" +msgstr "Скорость печати внутренней стенки" + +#: fdmprinter.json +msgctxt "speed_wall_x description" +msgid "" +"The speed at which all inner shells are printed. Printing the inner shell " +"fasster than the outer shell will reduce printing time. It is good to set " +"this in between the outer shell speed and the infill speed." +msgstr "" +"Скорость, при которой печатается внутренняя стенка. Если печатать внутренней " +"стенки быстрее чем внешней стенки, можно уменьшит время печати. Хорошо " +"установить это значение между скоростях печати внешней стенки и заполнение." + +#: fdmprinter.json +msgctxt "speed_topbottom label" +msgid "Top/Bottom Speed" +msgstr "Скорость печати верхнего/нижнего слоя" + +#: fdmprinter.json +msgctxt "speed_topbottom description" +msgid "" +"Speed at which top/bottom parts are printed. Printing the top/bottom faster " +"can greatly reduce printing time, but this can negatively affect print " +"quality." +msgstr "" +"Скорость, при которой печатаются верхние/нижние части. Печатать верх/низ при " +"больших скоростях, может значительно уменьшит время печати, но, это может " +"негативно повлиять на качество печати." + +#: fdmprinter.json +msgctxt "speed_support label" +msgid "Support Speed" +msgstr "Скорость печати поддержек" + +#: fdmprinter.json +msgctxt "speed_support description" +msgid "" +"The speed at which exterior support is printed. Printing exterior supports " +"at higher speeds can greatly improve printing time. And the surface quality " +"of exterior support is usually not important, so higher speeds can be used." +msgstr "" +"Скорость, при которой печатается поддержка. Печатать поддержек при больших " +"скоростях, может значительно улучшить время печати. Качество печати " +"поддержек не является важным и при этом можно использовать большие скорости " +"печати." + +#: fdmprinter.json +msgctxt "speed_travel label" +msgid "Travel Speed" +msgstr "Скорость перемещения " + +#: fdmprinter.json +msgctxt "speed_travel description" +msgid "" +"The speed at which travel moves are done. A well-built Ultimaker can reach " +"speeds of 250mm/s. But some machines might have misaligned layers then." +msgstr "" +"Скорость перемещения печатающей головки. Хорошо настроенный Ultimaker может " +"достигать скорость перемещения до 250 мм/сек. К некоторым принтерам есть " +"возможность появления неровных слоев." + +#: fdmprinter.json +msgctxt "speed_layer_0 label" +msgid "Bottom Layer Speed" +msgstr "Скорость печати нижнего слоя" + +#: fdmprinter.json +msgctxt "speed_layer_0 description" +msgid "" +"The print speed for the bottom layer: You want to print the first layer " +"slower so it sticks to the printer bed better." +msgstr "" +"Скорость, при которой печатается нижний слой: рекомендуется печатать первого " +"слоя на низкую скорость, чтобы получит лучшее прилипание (адгезию) к " +"печатающей платформы." + +#: fdmprinter.json +msgctxt "skirt_speed label" +msgid "Skirt Speed" +msgstr "Скорость печати контур" + +#: fdmprinter.json +msgctxt "skirt_speed description" +msgid "" +"The speed at which the skirt and brim are printed. Normally this is done at " +"the initial layer speed. But sometimes you want to print the skirt at a " +"different speed." +msgstr "" +"Скорость, при которой печатаются контур и кайма. Обычно это делается при " +"определения начальной скорости слоя, но, иногда есть потребность распечатать " +"подложку с другой скоростью." + +#: fdmprinter.json +msgctxt "speed_slowdown_layers label" +msgid "Amount of Slower Layers" +msgstr "Количество печати медленных слоев" + +#: fdmprinter.json +msgctxt "speed_slowdown_layers description" +msgid "" +"The first few layers are printed slower then the rest of the object, this to " +"get better adhesion to the printer bed and improve the overall success rate " +"of prints. The speed is gradually increased over these layers. 4 layers of " +"speed-up is generally right for most materials and printers." +msgstr "" +"Первые несколько слоев печатаются медленнее чем остальных, чтобы получит " +"лучшее прилипание к печатающей платформы и в целом улучшит качество печати. " +"Скорость постепенно увеличивается на последующих 3-ех слоев. Ускорение по 4 " +"слоя, как правило, подходит для большинство материалов и принтеров." + +#: fdmprinter.json +msgctxt "infill label" +msgid "Infill" +msgstr "Заполнение" + +#: fdmprinter.json +msgctxt "fill_sparse_density label" +msgid "Infill Density" +msgstr "Плотность заполнения" + +#: fdmprinter.json +msgctxt "fill_sparse_density description" +msgid "" +"This controls how densely filled the insides of your print will be. For a " +"solid part use 100%, for an hollow part use 0%. A value around 20% is " +"usually enough. This won't affect the outside of the print and only adjusts " +"how strong the part becomes." +msgstr "" +"Контролирует насколько плотно будет заполненные печатающего объекта. Для " +"прочности используйте 100% заполнение, а для пустоты используйте значение " +"0%. 20% заполнение является вполне достаточным. Это не повлияет на " +"внешностью печатающего объекта, а именно регулирует насколько будет прочный " +"сам объект." + +#: fdmprinter.json +msgctxt "fill_pattern label" +msgid "Infill Pattern" +msgstr "Структура заполнения" + +#: fdmprinter.json +msgctxt "fill_pattern description" +msgid "" +"Cura defaults to switching between grid and line infill. But with this " +"setting visible you can control this yourself. The line infill swaps " +"direction on alternate layers of infill, while the grid prints the full " +"cross-hatching on each layer of infill." +msgstr "" +"В Кура есть две структуры заполнения: сетки и линий. Структура заполнения " +"линий, меняет направление на чередующихся слой, которые заполняются, а " +"структура сетки печатает полной штриховкой на каждом слое, который " +"заполняется." + +#: fdmprinter.json +msgctxt "infill_line_distance label" +msgid "Line distance" +msgstr "Расстояние линий" + +#: fdmprinter.json +msgctxt "infill_line_distance description" +msgid "Distance between the printed infill lines." +msgstr "Расстояние между линиями заполнения" + +#: fdmprinter.json +msgctxt "fill_overlap label" +msgid "Infill Overlap" +msgstr "Заполнения перекрытия" + +#: fdmprinter.json +msgctxt "fill_overlap description" +msgid "" +"The amount of overlap between the infill and the walls. A slight overlap " +"allows the walls to connect firmly to the infill." +msgstr "" +"Количество перекрытия между заполнением и стенки. Небольшое перекрытие " +"улучшает соединение/сцепление стенок и их заполнение." + +#: fdmprinter.json +msgctxt "fill_sparse_thickness label" +msgid "Infill Thickness" +msgstr "Толщина заполнения" + +#: fdmprinter.json +msgctxt "fill_sparse_thickness description" +msgid "" +"The thickness of the sparse infill. This is rounded to a multiple of the " +"layerheight and used to print the sparse-infill in fewer, thicker layers to " +"save printing time." +msgstr "" +"Толщина разреженного заполнения. Это значение определяется согласно " +"многократного умножения высоты слоя и используется для печати разреженного " +"заполнения в нескольких толстых слоев, чтобы сэкономить время печати." + +#: fdmprinter.json +msgctxt "fill_sparse_combine label" +msgid "Infill Layers" +msgstr "Заполнение слоев" + +#: fdmprinter.json +msgctxt "fill_sparse_combine description" +msgid "Amount of layers that are combined together to form sparse infill." +msgstr "" +"Количество слоев, которые объединены вместе, чтобы образовать разреженное " +"заполнение." + +#: fdmprinter.json +msgctxt "cooling label" +msgid "Cooling" +msgstr "Охлаждение" + +#: fdmprinter.json +msgctxt "cool_fan_enabled label" +msgid "Enable Cooling Fan" +msgstr "Включит охлаждающий вентилятор" + +#: fdmprinter.json +msgctxt "cool_fan_enabled description" +msgid "" +"Enable the cooling fan during the print. The extra cooling from the cooling " +"fan helps parts with small cross sections that print each layer quickly." +msgstr "" +"Включит охлаждающий вентилятор во время печати. Дополнительное охлаждение " +"вентиляторов позволяет печатать каждого слоя быстрее." + +#: fdmprinter.json +msgctxt "cool_fan_speed label" +msgid "Fan Speed" +msgstr "Скорость вращения вентиляторов" + +#: fdmprinter.json +msgctxt "cool_fan_speed description" +msgid "Fan speed used for the print cooling fan on the printer head." +msgstr "" +"Скорость вращения вентилятора, которая используется для охлаждения " +"печатающей головки." + +#: fdmprinter.json +msgctxt "cool_fan_speed_min label" +msgid "Minimum Fan Speed" +msgstr "Минимальная скорость вращения вентиляторов" + +#: fdmprinter.json +msgctxt "cool_fan_speed_min description" +msgid "" +"Normally the fan runs at the minimum fan speed. If the layer is slowed down " +"due to minimum layer time, the fan speed adjusts between minimum and maximum " +"fan speed." +msgstr "" +"Обычно вентилятор работает на минимальной скорости вращения. Если слой " +"замедлился из-за минимальное время слоя, скорость вентилятора регулируется " +"между минимальной и максимальной скорости вентилятора." + +#: fdmprinter.json +msgctxt "cool_fan_speed_max label" +msgid "Maximum Fan Speed" +msgstr "Максимальная скорость вращения вентиляторов" + +#: fdmprinter.json +msgctxt "cool_fan_speed_max description" +msgid "" +"Normally the fan runs at the minimum fan speed. If the layer is slowed down " +"due to minimum layer time, the fan speed adjusts between minimum and maximum " +"fan speed." +msgstr "" +"Обычно вентилятор работает на минимальной скорости вращения. Если слой " +"замедлился из-за минимальное время слоя, скорость вентилятора регулируется " +"между минимальной и максимальной скорости вентилятора." + +#: fdmprinter.json +msgctxt "cool_fan_full_at_height label" +msgid "Fan Full on at Height" +msgstr "Полный запуск вентиляторов на определенной высоте" + +#: fdmprinter.json +msgctxt "cool_fan_full_at_height description" +msgid "" +"The height at which the fan is turned on completely. For the layers below " +"this the fan speed is scaled linearly with the fan off for the first layer." +msgstr "" +"Высота, на которой вентилятор включен полностью. Для слоев ниже этого, " +"скорость вращения вентилятора масштабируется линейно с выключенным " +"вентилятором для печати первого слоя." + +#: fdmprinter.json +msgctxt "cool_fan_full_layer label" +msgid "Fan Full on at Layer" +msgstr "Полный запуск вентиляторов при определенное количество слоев" + +#: fdmprinter.json +msgctxt "cool_fan_full_layer description" +msgid "" +"The layer number at which the fan is turned on completely. For the layers " +"below this the fan speed is scaled linearly with the fan off for the first " +"layer." +msgstr "" +"Число слоя, при котором вентилятор полностью включается. Для слоев ниже " +"этого значения, скорость вентилятора масштабируется линейно с выключенным " +"вентилятором для печати первого слоя." + +#: fdmprinter.json +msgctxt "cool_min_layer_time label" +msgid "Minimal Layer Time" +msgstr "Минимальное время накладывания слоев" + +#: fdmprinter.json +msgctxt "cool_min_layer_time description" +msgid "" +"The minimum time spent in a layer: Gives the layer time to cool down before " +"the next one is put on top. If a layer would print in less time, then the " +"printer will slow down to make sure it has spent at least this many seconds " +"printing the layer." +msgstr "" +"Минимальное время, требуемое для печати одного слоя, позволяет слою остит " +"перед тем, как начать накладывать следующего слоя. Если слой будут " +"печататься слишком быстро, тогда принтер замедлиться, чтобы соответствовать " +"данному значению." + +#: fdmprinter.json +msgctxt "cool_min_layer_time_fan_speed_max label" +msgid "Minimal Layer Time Full Fan Speed" +msgstr "Полный запуск вентиляторов при минимальное время накладывания слоев" + +#: fdmprinter.json +msgctxt "cool_min_layer_time_fan_speed_max description" +msgid "" +"The minimum time spent in a layer which will cause the fan to be at minmum " +"speed. The fan speed increases linearly from maximal fan speed for layers " +"taking minimal layer time to minimal fan speed for layers taking the time " +"specified here." +msgstr "" +"Минимальное время, требуемое для печати одного слоя, которое вызовет, чтобы " +"вентилятор вращался с минимальной скоростью. Скорость вращения вентилятора " +"увеличивается линейно от максимуме для слоев с минимальное время печати до " +"минимальное вращение вентиляторов для слоев, которые придерживаются время " +"здесь указанное." + +#: fdmprinter.json +msgctxt "cool_min_speed label" +msgid "Minimum Speed" +msgstr "Минимальная скорость" + +#: fdmprinter.json +msgctxt "cool_min_speed description" +msgid "" +"The minimum layer time can cause the print to slow down so much it starts to " +"droop. The minimum feedrate protects against this. Even if a print gets " +"slowed down it will never be slower than this minimum speed." +msgstr "" +"Минимальное время для печати слоев, может вызвать, чтобы процесс печати " +"замедлился на столько, что начинает свисать. Минимальная скорость подачи " +"предотвращает, чтобы произошло нависание. Даже если процесс печати " +"замедлиться, он никогда не будет медленнее чем минимальной скоростью." + +#: fdmprinter.json +msgctxt "cool_lift_head label" +msgid "Lift Head" +msgstr "Подъем печатающей головки" + +#: fdmprinter.json +msgctxt "cool_lift_head description" +msgid "" +"Lift the head away from the print if the minimum speed is hit because of " +"cool slowdown, and wait the extra time away from the print surface until the " +"minimum layer time is used up." +msgstr "" +"Если достигнутая минимальная скорость , из-за необходимости постепенного " +"охлаждения, поднять печатающую головку и подождать до достижения " +"минимального времени печати слоя." + +#: fdmprinter.json +msgctxt "support label" +msgid "Support" +msgstr "Поддержка" + +#: fdmprinter.json +msgctxt "support_enable label" +msgid "Enable Support" +msgstr "Включит поддержку" + +#: fdmprinter.json +msgctxt "support_enable description" +msgid "" +"Enable exterior support structures. This will build up supporting structures " +"below the model to prevent the model from sagging or printing in mid air." +msgstr "" +"Включите поддержку для внутренних структур. Это построить поддерживающих " +"структур под основного объекта, чтобы предотвратить модели от провисания или " +"печать по воздухе." + +#: fdmprinter.json +msgctxt "support_type label" +msgid "Placement" +msgstr "Размещение" + +#: fdmprinter.json +msgctxt "support_type description" +msgid "" +"Where to place support structures. The placement can be restricted such that " +"the support structures won't rest on the model, which could otherwise cause " +"scarring." +msgstr "" +"Где разместить структур поддержки. Размещение может быть ограничено таким " +"образом, что опорные конструкции не будут опираться на основного объекта, " +"которые в противном случае приведут к образованию отпечатков." + +#: fdmprinter.json +msgctxt "support_angle label" +msgid "Overhang Angle" +msgstr "Угол нависания" + +#: fdmprinter.json +msgctxt "support_angle description" +msgid "" +"The maximum angle of overhangs for which support will be added. With 0 " +"degrees being horizontal, and 90 degrees being vertical." +msgstr "" +"Максимальный угол нависания, для построения поддержки. 0 градусов будет " +"горизонтальны, а 90 градусов будет по вертикали." + +#: fdmprinter.json +msgctxt "support_xy_distance label" +msgid "X/Y Distance" +msgstr "Расстояние по оси X/Y" + +#: fdmprinter.json +msgctxt "support_xy_distance description" +msgid "" +"Distance of the support structure from the print, in the X/Y directions. " +"0.7mm typically gives a nice distance from the print so the support does not " +"stick to the surface." +msgstr "" +"Расстояние структуры поддержки от печатаемого объекта в направлении X и Y. " +"Нормальное значение от 0.7 мм обычно дает хорошее расстояние от печатаемого " +"объекта, чтобы поддерживающая структура не прилипала к основного объекта." + +#: fdmprinter.json +msgctxt "support_z_distance label" +msgid "Z Distance" +msgstr "Расстояние по ось Z" + +#: fdmprinter.json +msgctxt "support_z_distance description" +msgid "" +"Distance from the top/bottom of the support to the print. A small gap here " +"makes it easier to remove the support but makes the print a bit uglier. " +"0.15mm allows for easier separation of the support structure." +msgstr "" +"Расстояние от верхней/нижней поддержки до печатающего объекта. Маленькое " +"расстояние обеспечивает легкое удаление поддерживающих структур, но, при " +"этом дает невысокое качество печати поверхностью. Значение 0.15 мм " +"достаточное для легкое удаление поддерживающих структур." + +#: fdmprinter.json +msgctxt "support_top_distance label" +msgid "Top Distance" +msgstr "Верхнее расстояние" + +#: fdmprinter.json +msgctxt "support_top_distance description" +msgid "Distance from the top of the support to the print." +msgstr "" +"Расстояние от верхней части поддерживающей структуры до печатающего объекта." + +#: fdmprinter.json +msgctxt "support_bottom_distance label" +msgid "Bottom Distance" +msgstr "Нижнее расстояние" + +#: fdmprinter.json +msgctxt "support_bottom_distance description" +msgid "Distance from the print to the bottom of the support." +msgstr "" +"Расстояние от печатающего объекта до нижнюю часть поддерживающей структуры." + +#: fdmprinter.json +msgctxt "support_bottom_stair_step_height label" +msgid "Stair Step Height" +msgstr "Ступенчатая высота" + +#: fdmprinter.json +msgctxt "support_bottom_stair_step_height description" +msgid "" +"The height of the steps of the stair-like bottom of support resting on the " +"model. Small steps can cause the support to be hard to remove from the top " +"of the model." +msgstr "" +"Высота ступеней, ступенчатого низа поддерживающей структуры, которая " +"опирается на основного объекта. Небольшие лестницы, могут усложнит удаление " +"поддерживающих структур с верхней части основного объекта." + +#: fdmprinter.json +msgctxt "support_join_distance label" +msgid "Join Distance" +msgstr "Соединить расстояние" + +#: fdmprinter.json +msgctxt "support_join_distance description" +msgid "" +"The maximum distance between support blocks, in the X/Y directions, such " +"that the blocks will merge into a single block." +msgstr "" +"Максимальное расстояние между поддерживающих блоков в направлении X и Y, так " +"чтобы блоки соединились в один блок." + +#: fdmprinter.json +msgctxt "support_area_smoothing label" +msgid "Area Smoothing" +msgstr "Область сглаживания" + +#: fdmprinter.json +msgctxt "support_area_smoothing description" +msgid "" +"Maximal distance in the X/Y directions of a line segment which is to be " +"smoothed out. Ragged lines are introduced by the join distance and support " +"bridge, which cause the machine to resonate. Smoothing the support areas " +"won't cause them to break with the constraints, except it might change the " +"overhang." +msgstr "" +"Минимальное расстояние в направлении X/Y отрезки, которое должно быть " +"сглажено. Рваные линии представленные с стороне соединённых расстояния и " +"поддерживающего моста, которые вызывают, чтобы машина резонировала. " +"Сглаживание поддерживающих областей не вызовет, чтобы они сломались с " +"ограничениями, за исключением того, что может измениться нависание." + +#: fdmprinter.json +msgctxt "support_use_towers label" +msgid "Use towers." +msgstr "Использовать башни." + +#: fdmprinter.json +msgctxt "support_use_towers description" +msgid "" +"Use specialized towers to support tiny overhang areas. These towers have a " +"larger diameter than the region they support. Near the overhang the towers' " +"diameter decreases, forming a roof." +msgstr "" +"Используйте специализированные башни, чтобы поддержать маленькие нависающие " +"области. Эти башни имеют диаметр больше, чем область, которую они " +"поддерживают." + +#: fdmprinter.json +msgctxt "support_minimal_diameter label" +msgid "Minimal Diameter" +msgstr "Минимальный диаметр" + +#: fdmprinter.json +msgctxt "support_minimal_diameter description" +msgid "" +"Maximal diameter in the X/Y directions of a small area which is to be " +"supported by a specialized support tower. " +msgstr "" +"Максимальный диаметр в направлении X/Y на небольшой области, который будет " +"поддерживаться с помощью специализированной башню." + +#: fdmprinter.json +msgctxt "support_tower_diameter label" +msgid "Tower Diameter" +msgstr "Диаметр башни" + +#: fdmprinter.json +msgctxt "support_tower_diameter description" +msgid "The diameter of a special tower. " +msgstr "Диаметр специальной башне." + +#: fdmprinter.json +msgctxt "support_tower_roof_angle label" +msgid "Tower Roof Angle" +msgstr "Угол крыши башни" + +#: fdmprinter.json +msgctxt "support_tower_roof_angle description" +msgid "" +"The angle of the rooftop of a tower. Larger angles mean more pointy towers. " +msgstr "" +"Угол верхнего покрытия башни. Большие углы означает получит более острые " +"башни." + +#: fdmprinter.json +msgctxt "support_pattern label" +msgid "Pattern" +msgstr "Структура" + +#: fdmprinter.json +msgctxt "support_pattern description" +msgid "" +"Cura supports 3 distinct types of support structure. First is a grid based " +"support structure which is quite solid and can be removed as 1 piece. The " +"second is a line based support structure which has to be peeled off line by " +"line. The third is a structure in between the other two; it consists of " +"lines which are connected in an accordeon fashion." +msgstr "" +"Кура поддерживает 3 типа поддерживающих структур. Сетка - очень прочная " +"структура поддержек и может быт удалена как одно целое. Линия - структура " +"поддержек, которая удаляется по одной за раз. Третий тип структур поддержек " +"это структура между предыдущих два типа, и состоится из линий, которые " +"соединены в последовательной формы." + +#: fdmprinter.json +msgctxt "support_connect_zigzags label" +msgid "Connect ZigZags" +msgstr "Подключите ZigZags" + +#: fdmprinter.json +msgctxt "support_connect_zigzags description" +msgid "" +"Connect the ZigZags. Makes them harder to remove, but prevents stringing of " +"disconnected zigzags." +msgstr "" +"Соединяет ZigZags. Их труднее удалить, но при этом предотвращает появления " +"струны к zigzags, которые несоединённые." + +#: fdmprinter.json +msgctxt "support_fill_rate label" +msgid "Fill Amount" +msgstr "Плотность заполнения" + +#: fdmprinter.json +msgctxt "support_fill_rate description" +msgid "" +"The amount of infill structure in the support, less infill gives weaker " +"support which is easier to remove." +msgstr "" +"Количество заполнения поддерживающей структуры. Меньше заполнение дает не " +"очень прочную поддерживающую поддержку, которую легко удалить." + +#: fdmprinter.json +msgctxt "support_line_distance label" +msgid "Line distance" +msgstr "Расстояние линий" + +#: fdmprinter.json +msgctxt "support_line_distance description" +msgid "Distance between the printed support lines." +msgstr "Расстояние между напечатанным линиям поддержек." + +#: fdmprinter.json +msgctxt "platform_adhesion label" +msgid "Platform Adhesion" +msgstr "Тип прилипания к столу" + +#: fdmprinter.json +msgctxt "adhesion_type label" +msgid "Type" +msgstr "Тип" + +#: fdmprinter.json +msgctxt "adhesion_type description" +msgid "" +"Different options that help in preventing corners from lifting due to " +"warping. Brim adds a single-layer-thick flat area around your object which " +"is easy to cut off afterwards, and it is the recommended option. Raft adds a " +"thick grid below the object and a thin interface between this and your " +"object. (Note that enabling the brim or raft disables the skirt.)" +msgstr "" +"Различные опции, которые предотвращают сгибания углов. Кайма - добавляет " +"однослойная плоская область вокруг вашего объекта, которую легко удалить " +"после завершения процесса печати. Эта опция рекомендуется. Подложка - строит " +"толстую сетку под объекта и тонкий интерфейс между этим и основного " +"печатающего объекта. (Замечание: если Вы включите опцию кайму или подложку, " +"тогда выключается опция контур)" + +#: fdmprinter.json +msgctxt "skirt_line_count label" +msgid "Skirt Line Count" +msgstr "Количество линий контура" + +#: fdmprinter.json +msgctxt "skirt_line_count description" +msgid "" +"The skirt is a line drawn around the first layer of the. This helps to prime " +"your extruder, and to see if the object fits on your platform. Setting this " +"to 0 will disable the skirt. Multiple skirt lines can help to prime your " +"extruder better for small objects." +msgstr "" +"Контур, это линия, которая печатается вокруг печатающего объекта на первого " +"слоя. Это позволяет предварительно расписать экструдер и показывает границы " +"основного объекта. Если установите значение 0, это выключит опцию контур. " +"Несколько контуров (линий), помогут лучше расписать экструдер, для печати " +"маленьких объектов." + +#: fdmprinter.json +msgctxt "skirt_gap label" +msgid "Skirt Distance" +msgstr "Расстояние контур" + +#: fdmprinter.json +msgctxt "skirt_gap description" +msgid "" +"The horizontal distance between the skirt and the first layer of the print.\n" +"This is the minimum distance, multiple skirt lines will extend outwards from " +"this distance." +msgstr "" +"Горизонтальное расстояние между контура и первого слоя основного печатающего " +"объекта.\n" +"Это минимальное расстояние за которое контурные линий будут печататься." + +#: fdmprinter.json +msgctxt "skirt_minimal_length label" +msgid "Skirt Minimum Length" +msgstr "Минимальная длина контура" + +#: fdmprinter.json +msgctxt "skirt_minimal_length description" +msgid "" +"The minimum length of the skirt. If this minimum length is not reached, more " +"skirt lines will be added to reach this minimum length. Note: If the line " +"count is set to 0 this is ignored." +msgstr "" +"Если минимальная длина контура не достигнутая, это добавить дополнительные " +"контурные линий для достижения минимальной длине. Замечание: если количество " +"линий имеет значение 0, тогда эта опция игнорируется." + +#: fdmprinter.json +msgctxt "brim_line_count label" +msgid "Brim Line Count" +msgstr "Количество линий каймы" + +#: fdmprinter.json +msgctxt "brim_line_count description" +msgid "" +"The amount of lines used for a brim: More lines means a larger brim which " +"sticks better, but this also makes your effective print area smaller." +msgstr "" +"Количество линий, который используются для каймы: Большое количество линий " +"означает, что большая кайма будет прилипать к платформы лучше, но, это также " +"делает Вашу эффективную область печати меньше." + +#: fdmprinter.json +msgctxt "raft_margin label" +msgid "Raft Extra Margin" +msgstr "Дополнительные поля подложки" + +#: fdmprinter.json +msgctxt "raft_margin description" +msgid "" +"If the raft is enabled, this is the extra raft area around the object which " +"is also given a raft. Increasing this margin will create a stronger raft " +"while using more material and leaving less area for your print." +msgstr "" +"Если подложка включена, это дополнительная область подложки во круг объекта, " +"котоая также имеет подложку. Увеличение этого поле, создаст более прочную " +"подложку, но, при этом используется больше материала и уменьшиться область " +"печати." + +#: fdmprinter.json +msgctxt "raft_line_spacing label" +msgid "Raft Line Spacing" +msgstr "Расстояние между линиями подложки" + +#: fdmprinter.json +msgctxt "raft_line_spacing description" +msgid "" +"The distance between the raft lines. The first 2 layers of the raft have " +"this amount of spacing between the raft lines." +msgstr "" +"Расстояние между линиями подложки. Первые 2 слоя поддержки имеют такое " +"значение для количество расстояние между линиями подложки." + +#: fdmprinter.json +msgctxt "raft_base_thickness label" +msgid "Raft Base Thickness" +msgstr "Толщина основного слоя подложки" + +#: fdmprinter.json +msgctxt "raft_base_thickness description" +msgid "" +"Layer thickness of the first raft layer. This should be a thick layer which " +"sticks firmly to the printer bed." +msgstr "" +"Толщина основного слоя подложки. Это должен быть толстый слой, который " +"плотно прилипает к печатающей платформы." + +#: fdmprinter.json +msgctxt "raft_base_linewidth label" +msgid "Raft Base Line Width" +msgstr "Ширина основной линии подложки" + +#: fdmprinter.json +msgctxt "raft_base_linewidth description" +msgid "" +"Width of the lines in the first raft layer. These should be thick lines to " +"assist in bed adhesion." +msgstr "" +"Ширина основной линий подложки. Линий должны быт толстимы, чтобы улучшит " +"прилипание к печатающей платформы." + +#: fdmprinter.json +msgctxt "raft_base_speed label" +msgid "Raft Base Print Speed" +msgstr "Основная скорость печати подложку" + +#: fdmprinter.json +msgctxt "raft_base_speed description" +msgid "" +"The speed at which the first raft layer is printed. This should be printed " +"quite slowly, as the amount of material coming out of the nozzle is quite " +"high." +msgstr "" +"Скорость при которой печатается первый слой подложки. Скорость печати должна " +"быт низкая, так как количество выдавливаемого материала достаточно высокая." + +#: fdmprinter.json +msgctxt "raft_interface_thickness label" +msgid "Raft Interface Thickness" +msgstr "Толщина переходной линий подложки" + +#: fdmprinter.json +msgctxt "raft_interface_thickness description" +msgid "Thickness of the 2nd raft layer." +msgstr "Толщина второго слоя подложки." + +#: fdmprinter.json +msgctxt "raft_interface_linewidth label" +msgid "Raft Interface Line Width" +msgstr "Ширина переходной линий подложки" + +#: fdmprinter.json +msgctxt "raft_interface_linewidth description" +msgid "" +"Width of the 2nd raft layer lines. These lines should be thinner than the " +"first layer, but strong enough to attach the object to." +msgstr "" +"Ширина второго слоя подложки. Линий второго слоя должны быт тоньше чем для " +"первого слоя, но, достаточно прочные, чтобы прилипал основной объект." + +#: fdmprinter.json +msgctxt "raft_airgap label" +msgid "Raft Air-gap" +msgstr "Воздушный зазор" + +#: fdmprinter.json +msgctxt "raft_airgap description" +msgid "" +"The gap between the final raft layer and the first layer of the object. Only " +"the first layer is raised by this amount to lower the bonding between the " +"raft layer and the object. Makes it easier to peel off the raft." +msgstr "" +"Зазор между последним слоем подложки и первого слоя основного объекта. На " +"это значение поднимается только первый слой, чтобы уменьшит соединения между " +"слоем подложки и основного объекта." + +#: fdmprinter.json +msgctxt "raft_surface_layers label" +msgid "Raft Surface Layers" +msgstr "Поверхностные слой подложки" + +#: fdmprinter.json +msgctxt "raft_surface_layers description" +msgid "" +"The number of surface layers on top of the 2nd raft layer. These are fully " +"filled layers that the object sits on. 2 layers usually works fine." +msgstr "" +"Количество поверхностных слоев, которые накладываются над вторим слоем " +"подложки. Это полностью заполнение слой, на которых печатается основной " +"объект. Обычно два слоя достаточно." + +#: fdmprinter.json +msgctxt "blackmagic label" +msgid "Fixes" +msgstr "Корректировки" + +#: fdmprinter.json +msgctxt "magic_spiralize label" +msgid "Spiralize the Outer Contour" +msgstr "Поверните внешний контур" + +#: fdmprinter.json +msgctxt "magic_spiralize description" +msgid "" +"Spiralize smooths out the Z move of the outer edge. This will create a " +"steady Z increase over the whole print. This feature turns a solid object " +"into a single walled print with a solid bottom. This feature used to be " +"called ‘Joris’ in older versions." +msgstr "" +"Спиральные сглаживания за пределами ось Z для наружной кромки. Это создаст " +"стабильное выращивание объекта по ось Z в течении всего процесса печати. Эта " +"функция превращает сплошного объекта, в печати одной стеной с сплошным дном. " +"Эта функция в предыдущих версии называлась \"Joris\"." + +#: fdmprinter.json +msgctxt "wireframe_enabled label" +msgid "Wire Printing" +msgstr "Проволочная печать" + +#: fdmprinter.json +msgctxt "wireframe_enabled description" +msgid "" +"Print only the outside surface with a sparse webbed structure, printing 'in " +"thin air'. This is realized by horizontally printing the contours of the " +"model at given Z intervals which are connected via upward and diagonally " +"downward lines." +msgstr "" +"Печатает только наружную поверхность с редкой перепончатой структуры, \"в " +"воздухе\". Это реализуется путем горизонтальной печати контуры объекта через " +"заданные интервалы времени Z, которые соединены с помощью верхних и нижних " +"по диагонали линиями." + +#: fdmprinter.json +msgctxt "wireframe_printspeed label" +msgid "Wire Printing speed" +msgstr "Скорость проволочной печати" + +#: fdmprinter.json +msgctxt "wireframe_printspeed description" +msgid "" +"Speed at which the nozzle moves when extruding material. Only applies to " +"Wire Printing." +msgstr "" +"Скорость, при которой двигается печатающая головка когда выдавливает " +"материал. Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_printspeed_bottom label" +msgid "Wire Bottom Printing Speed" +msgstr "Скорость проволочной печати нижнего слоя" + +#: fdmprinter.json +msgctxt "wireframe_printspeed_bottom description" +msgid "" +"Speed of printing the first layer, which is the only layer touching the " +"build platform. Only applies to Wire Printing." +msgstr "" +"Скорость, при которой печатается первый слой и является единственный слой, " +"который касается печатающей платформы. Относиться только для проволочной " +"печати." + +#: fdmprinter.json +msgctxt "wireframe_printspeed_up label" +msgid "Wire Upward Printing Speed" +msgstr "Скорость проволочной печати вверх" + +#: fdmprinter.json +msgctxt "wireframe_printspeed_up description" +msgid "" +"Speed of printing a line upward 'in thin air'. Only applies to Wire Printing." +msgstr "" +"Скорость, при которой печатается линия на верх \"в воздухе\". Относиться " +"только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_printspeed_down label" +msgid "Wire Downward Printing Speed" +msgstr "Скорость проволочной печати вниз" + +#: fdmprinter.json +msgctxt "wireframe_printspeed_down description" +msgid "" +"Speed of printing a line diagonally downward. Only applies to Wire Printing." +msgstr "" +"Скорость, при которой печатается линия по диагонали вниз. Относиться только " +"для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_printspeed_flat label" +msgid "Wire Horizontal Printing Speed" +msgstr "Скорость проволочной печати по горизонтали" + +#: fdmprinter.json +msgctxt "wireframe_printspeed_flat description" +msgid "" +"Speed of printing the horizontal contours of the object. Only applies to " +"Wire Printing." +msgstr "" +"Скорость, при которой печатаются горизонтальные контуры объекта. Относиться " +"только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_flow label" +msgid "Wire Printing Flow" +msgstr "Выдавливание материала для проволочной печати" + +#: fdmprinter.json +msgctxt "wireframe_flow description" +msgid "" +"Flow compensation: the amount of material extruded is multiplied by this " +"value. Only applies to Wire Printing." +msgstr "" +"Компенсация выдавливания: количество выдавливаемого материала умножается на " +"это значение. Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_flow_connection label" +msgid "Wire Connection Flow" +msgstr "Соединительное выдавливания материала" + +#: fdmprinter.json +msgctxt "wireframe_flow_connection description" +msgid "Flow compensation when going up or down. Only applies to Wire Printing." +msgstr "" +"Компенсирует выдавливание материала когда перемещается на верх и вниз. " +"Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_flow_flat label" +msgid "Wire Flat Flow" +msgstr "Плоское выдавливание пластика" + +#: fdmprinter.json +msgctxt "wireframe_flow_flat description" +msgid "" +"Flow compensation when printing flat lines. Only applies to Wire Printing." +msgstr "Компенсирует выдавливание материала, когда печатаются плоские линий." + +#: fdmprinter.json +msgctxt "wireframe_top_delay label" +msgid "Wire Printing Top Delay" +msgstr "Задержка печати верхней линий" + +#: fdmprinter.json +msgctxt "wireframe_top_delay description" +msgid "" +"Delay time after an upward move, so that the upward line can harden. Only " +"applies to Wire Printing." +msgstr "" +"Время задержки после перемещения на верх, так чтобы линия вверх остыла. " +"Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_bottom_delay label" +msgid "Wire Printing Bottom Delay" +msgstr "Задержка проволочной печати нижней линий" + +#: fdmprinter.json +msgctxt "wireframe_bottom_delay description" +msgid "" +"Delay time after a downward move. Only applies to Wire Printing. Only " +"applies to Wire Printing." +msgstr "" +"Время задержки после перемещения вниз. Относиться только для проволочной " +"печати." + +#: fdmprinter.json +msgctxt "wireframe_flat_delay label" +msgid "Wire Printing Flat Delay" +msgstr "Задержка проволочной печати плоской линий" + +#: fdmprinter.json +msgctxt "wireframe_flat_delay description" +msgid "" +"Delay time between two horizontal segments. Introducing such a delay can " +"cause better adhesion to previous layers at the connection points, while too " +"large delay times cause sagging. Only applies to Wire Printing." +msgstr "" +"Время задержки между два горизонтальных сегменты. Такая задержка дает лучшее " +"прилипание предыдущих слоев в точках соединении, а больше задержки на " +"оборот, вызывают пригибания. Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_up_half_speed label" +msgid "Wire Printing Ease Upward" +msgstr "Проволочная печать слегка на верх" + +#: fdmprinter.json +msgctxt "wireframe_up_half_speed description" +msgid "" +"Distance of an upward move which is extruded with half speed.\n" +"This can cause better adhesion to previous layers, while not heating the " +"material in those layers too much. Only applies to Wire Printing." +msgstr "" +"Расстояние верхнего хода, который выдавливается с половиной скорости.\n" +"Это дает лучшее прилипание к предыдущим слоем, при этом не нагревая слишком " +"много материал в этих слоях." + +#: fdmprinter.json +msgctxt "wireframe_top_jump label" +msgid "Wire Printing Knot Size" +msgstr "Проволочная печать размер узла" + +#: fdmprinter.json +msgctxt "wireframe_top_jump description" +msgid "" +"Creates a small knot at the top of an upward line, so that the consecutive " +"horizontal layer has a better chance to connect to it. Only applies to Wire " +"Printing." +msgstr "" +"Создает небольшой узелок в верхней части верхней линий, так чтобы " +"последовательный горизонтальный слой имел больше шансов с ней соединится." + +#: fdmprinter.json +msgctxt "wireframe_fall_down label" +msgid "Wire Printing Fall Down" +msgstr "Проволочная печать идет вниз" + +#: fdmprinter.json +msgctxt "wireframe_fall_down description" +msgid "" +"Distance with which the material falls down after an upward extrusion. This " +"distance is compensated for. Only applies to Wire Printing." +msgstr "" +"Расстояние с которое материал падает вниз после выдавливания материала на " +"верх. Это расстояние компенсируется. Относиться только для проволочной " +"печати." + +#: fdmprinter.json +msgctxt "wireframe_drag_along label" +msgid "Wire Printing Drag along" +msgstr "Проволочная печать с перетаскиванием" + +#: fdmprinter.json +msgctxt "wireframe_drag_along description" +msgid "" +"Distance with which the material of an upward extrusion is dragged along " +"with the diagonally downward extrusion. This distance is compensated for. " +"Only applies to Wire Printing." +msgstr "" +"Расстояние, при которое материал выдавливаемый на верх перетаскивается " +"вместе с диагонального выдавливаемого вниз. Это расстояние компенсируется. " +"Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_strategy label" +msgid "Wire Printing Strategy" +msgstr "Стратегия проволочной печати" + +#: fdmprinter.json +msgctxt "wireframe_strategy description" +msgid "" +"Strategy for making sure two consecutive layers connect at each connection " +"point. Retraction lets the upward lines harden in the right position, but " +"may cause filament grinding. A knot can be made at the end of an upward line " +"to heighten the chance of connecting to it and to let the line cool; however " +"it may require slow printing speeds. Another strategy is to compensate for " +"the sagging of the top of an upward line; however, the lines won't always " +"fall down as predicted." +msgstr "" +"Стратегия, при которой подтверждаем, что 2 последующие слои соединяются в " +"каждой точки соединения. Откат материала позволяет остывание возвышающих " +"линий в правильном положении, но, может привести к перемалывание нити. Чтобы " +"повысить шансы соединении к нему, и позволит остывании линиям, можно сделать " +"узел там где заканчивается возвышающаяся линия; однако возможно потребуется " +"поставит невысокие скорости печати. Другая стратегия заключается в " +"компенсации прогиба на верхней части верхней линии; однако, линии не всегда " +"падают, как предсказано." + +#: fdmprinter.json +msgctxt "wireframe_straight_before_down label" +msgid "Wire Printing Straighten Downward Lines" +msgstr "Проволочная печать прямых линий вниз" + +#: fdmprinter.json +msgctxt "wireframe_straight_before_down description" +msgid "" +"Percentage of a diagonally downward line which is covered by a horizontal " +"line piece. This can prevent sagging of the top most point of upward lines. " +"Only applies to Wire Printing." +msgstr "" +"Процент диагональной линий вниз, который покрыт горизонтальной линии. Это " +"может предотвратить пригибание самой верхней точки верхней линий. Относиться " +"только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_roof_fall_down label" +msgid "Wire Printing Roof Fall Down" +msgstr "Проволочная печать покрытия падает вниз" + +#: fdmprinter.json +msgctxt "wireframe_roof_fall_down description" +msgid "" +"The distance which horizontal roof lines printed 'in thin air' fall down " +"when being printed. This distance is compensated for. Only applies to Wire " +"Printing." +msgstr "" +"Расстояние, при которое напечатанные горизонтальные линий покрытия \"в " +"воздухе\" во время печати падают вниз. Это расстояние компенсируется. " +"Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_roof_drag_along label" +msgid "Wire Printing Roof Drag Along" +msgstr "Проволочная печать перекрытия падает вниз" + +#: fdmprinter.json +msgctxt "wireframe_roof_drag_along description" +msgid "" +"The distance of the end piece of an inward line which gets dragged along " +"when going back to the outer outline of the roof. This distance is " +"compensated for. Only applies to Wire Printing." +msgstr "" +"Расстояние от конца внутренней линий, которая перемещается, когда " +"возвращается к внешнему контуру покрытия. Это расстояние компенсируется. " +"Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_roof_outer_delay label" +msgid "Wire Printing Roof Outer Delay" +msgstr "Проволочная печать внешней задержки покрытия" + +#: fdmprinter.json +msgctxt "wireframe_roof_outer_delay description" +msgid "" +"Time spent at the outer perimeters of hole which is to become a roof. Larger " +"times can ensure a better connection. Only applies to Wire Printing." +msgstr "" +"Время, которое требуется внешнего периметра отверстия, чтобы перекрылось. " +"Больше времени, обеспечивает лучшее соединение. Относиться только для " +"проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_height label" +msgid "Wire Printing Connection Height" +msgstr "Проволочная печать соединения на высоте" + +#: fdmprinter.json +msgctxt "wireframe_height description" +msgid "" +"The height of the upward and diagonally downward lines between two " +"horizontal parts. Only applies to Wire Printing." +msgstr "" +"Высота верхних и диагонально нижних линий между две горизонтальные части. " +"Относиться только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_roof_inset label" +msgid "Wire Printing Roof Inset Distance" +msgstr "Wire Printing Roof Inset Distance" + +#: fdmprinter.json +msgctxt "wireframe_roof_inset description" +msgid "" +"The distance covered when making a connection from a roof outline inward. " +"Only applies to Wire Printing." +msgstr "" +"Пройденное расстояние при соединении из контура крыши на внутрь. Относиться " +"только для проволочной печати." + +#: fdmprinter.json +msgctxt "wireframe_nozzle_clearance label" +msgid "Wire Printing Nozzle Clearance" +msgstr "Wire Printing Nozzle Clearance" + +#: fdmprinter.json +msgctxt "wireframe_nozzle_clearance description" +msgid "" +"Distance between the nozzle and horizontally downward lines. Larger " +"clearance results in diagonally downward lines with a less steep angle, " +"which in turn results in less upward connections with the next layer. Only " +"applies to Wire Printing." +msgstr "" +"Расстояние между соплом и горизонтальных линии вниз. Лучшие результаты " +"оформления диагональных линий вниз с менее крутым углом, что, в свою " +"очередь, приводит к уменьшению верхних соединении с следующего слоя. " +"Относиться только для проволочной печати." diff --git a/resources/images/cura-icon.png b/resources/images/cura-icon.png new file mode 100644 index 0000000000..ecfe0d1e4e Binary files /dev/null and b/resources/images/cura-icon.png differ diff --git a/resources/meshes/ultimaker_platform.stl b/resources/meshes/ultimaker_platform.stl index cd8893143e..e81aeefb04 100644 Binary files a/resources/meshes/ultimaker_platform.stl and b/resources/meshes/ultimaker_platform.stl differ diff --git a/resources/qml/AboutDialog.qml b/resources/qml/AboutDialog.qml index df2ecf4172..1ed9f5dd32 100644 --- a/resources/qml/AboutDialog.qml +++ b/resources/qml/AboutDialog.qml @@ -3,7 +3,6 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 -import QtQuick.Layouts 1.1 import QtQuick.Window 2.1 import UM 1.0 as UM @@ -12,48 +11,53 @@ UM.Dialog { id: base //: About dialog title - title: qsTr("About Cura"); + title: qsTr("About Cura") + minimumWidth: 400 + minimumHeight: 300 - ColumnLayout { - anchors.fill: parent; + Image { + id: logo + width: parent.width * 0.75 + height: width * (1/4.25) - Item { - Layout.fillWidth: true; - Layout.fillHeight: true; - } + source: UM.Theme.images.logo - Image { - Layout.alignment: Qt.AlignHCenter; - Layout.preferredWidth: parent.width * 0.75; - Layout.preferredHeight: width * (1/4.25); + sourceSize.width: width + sourceSize.height: height + anchors.centerIn: parent + anchors.verticalCenterOffset : -(height * 0.5) + } - source: UM.Theme.images.logo; + Label { + id: version - sourceSize.width: width; - sourceSize.height: height; - } + text: "Cura 15.06 Beta" + font: UM.Theme.fonts.large + anchors.horizontalCenter : logo.horizontalCenter + anchors.horizontalCenterOffset : (logo.width * 0.25) + anchors.top: logo.bottom + anchors.topMargin : 5 + } - Label { - Layout.alignment: Qt.AlignHCenter; + Label { + id: description + width: parent.width - text: "Cura 15.06 Beta"; - font: UM.Theme.fonts.large; - } + //: About dialog application description + text: qsTr("End-to-end solution for fused filament 3D printing.") + wrapMode: Text.WordWrap + anchors.top: version.bottom + anchors.topMargin : 10 + } - Label { - //: About dialog application description - text: qsTr("End-to-end solution for fused filament 3D printing.") - } + Label { + id: author_note + width: parent.width - Label { - //: About dialog application author note - text: qsTr("Cura has been developed by Ultimaker B.V. in cooperation with the community.") - } - - Item { - Layout.fillWidth: true; - Layout.fillHeight: true; - } + //: About dialog application author note + text: qsTr("Cura has been developed by Ultimaker B.V. in cooperation with the community.") + wrapMode: Text.WordWrap + anchors.top: description.bottom } rightButtons: Button { diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 7e48765f17..226f4f59a9 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -25,6 +25,7 @@ UM.MainWindow { window: base Menu { + id: fileMenu //: File menu title: qsTr("&File"); @@ -33,6 +34,21 @@ UM.MainWindow { MenuSeparator { } + Instantiator { + model: Printer.recentFiles + MenuItem { + text: { + var path = modelData.toString() + return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1); + } + onTriggered: UM.MeshFileHandler.readLocalFile(modelData); + } + onObjectAdded: fileMenu.insertItem(index, object) + onObjectRemoved: fileMenu.removeItem(object) + } + + MenuSeparator { } + MenuItem { action: actions.quit; } } @@ -144,23 +160,6 @@ UM.MainWindow { } } - Sidebar { - id: sidebar; - - anchors { - top: parent.top; - bottom: parent.bottom; - right: parent.right; - rightMargin: UM.Theme.sizes.window_margin.width; - } - - width: UM.Theme.sizes.panel.width; - - addMachineAction: actions.addMachine; - configureMachinesAction: actions.configureMachines; - saveAction: actions.save; - } - UM.MessageStack { anchors { left: toolbar.right; @@ -195,8 +194,8 @@ UM.MainWindow { id: openFileButton; iconSource: UM.Theme.icons.open; - style: UM.Theme.styles.tool_button; - + style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button; + tooltip: ''; anchors { top: parent.top; topMargin: UM.Theme.sizes.window_margin.height; @@ -235,7 +234,7 @@ UM.MainWindow { iconSource: UM.Theme.icons.viewmode; style: UM.Theme.styles.tool_button; - + tooltip: ''; menu: Menu { id: viewMenu; Instantiator { @@ -265,6 +264,35 @@ UM.MainWindow { bottomMargin: UM.Theme.sizes.window_margin.height; } } + + Sidebar { + id: sidebar; + + anchors { + top: parent.top; + bottom: parent.bottom; + right: parent.right; + } + + width: UM.Theme.sizes.panel.width; + + addMachineAction: actions.addMachine; + configureMachinesAction: actions.configureMachines; + saveAction: actions.save; + } + + Rectangle { + x: base.mouseX + UM.Theme.sizes.default_margin.width; + y: base.mouseY + UM.Theme.sizes.default_margin.height; + + width: childrenRect.width; + height: childrenRect.height; + Label { + text: UM.ActiveTool.properties.Rotation != undefined ? "%1°".arg(UM.ActiveTool.properties.Rotation) : ""; + } + + visible: UM.ActiveTool.valid && UM.ActiveTool.properties.Rotation != undefined; + } } } @@ -323,8 +351,8 @@ UM.MainWindow { preferences.onTriggered: preferences.visible = true; configureMachines.onTriggered: { preferences.visible = true; preferences.setPage(2); } - documentation.onTriggered: Qt.openUrlExternally("https://ultimaker.com/en/support"); - reportBug.onTriggered: Qt.openUrlExternally("https://github.com/Ultimaker/Cura/issues"); + documentation.onTriggered: CuraActions.openDocumentation(); + reportBug.onTriggered: CuraActions.openBugReportPage(); showEngineLog.onTriggered: engineLog.visible = true; about.onTriggered: aboutDialog.visible = true; } @@ -419,3 +447,4 @@ UM.MainWindow { Component.onCompleted: UM.Theme.load(UM.Resources.getPath(UM.Resources.ThemesLocation, "cura")) } + diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 07bc0a9ccc..e45d5b07b6 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -8,7 +8,7 @@ import QtQuick.Layouts 1.1 import UM 1.0 as UM -Button { +Rectangle { id: base; property Action saveAction; @@ -16,8 +16,6 @@ Button { property real progress: UM.Backend.progress; Behavior on progress { NumberAnimation { duration: 250; } } - enabled: progress >= 0.95; - property string currentDevice: "local_file" property bool defaultOverride: false; property bool defaultAmbiguous: false; @@ -25,9 +23,6 @@ Button { property variant printDuration: PrintInformation.currentPrintTime; property real printMaterialAmount: PrintInformation.materialAmount; - iconSource: UM.Theme.icons[Printer.outputDevices[base.currentDevice].icon]; - tooltip: Printer.outputDevices[base.currentDevice].description; - Connections { target: Printer; onOutputDevicesChanged: { @@ -51,161 +46,183 @@ Button { } } - style: ButtonStyle { - background: UM.AngledCornerRectangle { - implicitWidth: control.width; - implicitHeight: control.height; + Rectangle{ + id: background + implicitWidth: base.width; + implicitHeight: parent.height; + color: UM.Theme.colors.save_button_background; + border.width: UM.Theme.sizes.save_button_border.width + border.color: UM.Theme.colors.save_button_border - color: UM.Theme.colors.save_button_border; - cornerSize: UM.Theme.sizes.default_margin.width; + Rectangle { + id: infoBox + width: parent.width - UM.Theme.sizes.default_margin.width * 2; + height: UM.Theme.sizes.save_button_slicing_bar.height - UM.AngledCornerRectangle { - anchors.fill: parent; - anchors.margins: UM.Theme.sizes.save_button_border.width; - cornerSize: UM.Theme.sizes.default_margin.width; - color: UM.Theme.colors.save_button; - } + anchors.top: parent.top + anchors.topMargin: UM.Theme.sizes.default_margin.height; + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.default_margin.width; - UM.AngledCornerRectangle { - anchors { - left: parent.left; - top: parent.top; - bottom: parent.bottom; - } - - width: Math.max(parent.height + (parent.width - parent.height) * control.progress, parent.height); - cornerSize: UM.Theme.sizes.default_margin.width; - - color: !control.enabled ? UM.Theme.colors.save_button_inactive : control.hovered ? UM.Theme.colors.save_button_active_hover : UM.Theme.colors.save_button_active; - Behavior on color { ColorAnimation { duration: 50; } } - } - - UM.AngledCornerRectangle { - anchors.left: parent.left; - width: parent.height + UM.Theme.sizes.save_button_border.width; - height: parent.height; - cornerSize: UM.Theme.sizes.default_margin.width; - color: UM.Theme.colors.save_button; - } - - UM.AngledCornerRectangle { - anchors.left: parent.left; - width: parent.height + UM.Theme.sizes.save_button_border.width; - height: parent.height; - cornerSize: UM.Theme.sizes.default_margin.width; - - color: UM.Theme.colors.save_button; - } - - UM.AngledCornerRectangle { - id: icon; - - anchors.left: parent.left; - width: parent.height; - height: parent.height; - cornerSize: UM.Theme.sizes.default_margin.width; - color: !control.enabled ? UM.Theme.colors.save_button_inactive : control.hovered ? UM.Theme.colors.save_button_active_hover : UM.Theme.colors.save_button_active; - Behavior on color { ColorAnimation { duration: 50; } } - - Image { - anchors.centerIn: parent; - - width: UM.Theme.sizes.button_icon.width; - height: UM.Theme.sizes.button_icon.height; - - sourceSize.width: width; - sourceSize.height: height; - - source: control.iconSource; - } - } - } - - label: Column { + border.width: UM.Theme.sizes.save_button_border.width + border.color: UM.Theme.colors.save_button_border + color: UM.Theme.colors.save_button_estimated_text_background; Label { id: label; - anchors.left: parent.left; - anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width; - - color: UM.Theme.colors.save_button_text; - font: UM.Theme.fonts.default; - - text: control.text; + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width; + visible: base.progress >= 0 && base.progress < 0.99 ? false : true + color: UM.Theme.colors.save_button_estimated_text; + font: UM.Theme.fonts.small; + text: + if(base.progress < 0) { + //: Save button label + return qsTr("Please load a 3D model"); + } else if (base.progress < 0.99) { + //: Save button label + return qsTr("Calculating Print-time"); + } else if (base.progress > 0.99){ + //: Save button label + return qsTr("Estimated Print-time"); + } else if (base.progress == null){ + return qsTr(""); + } } Label { - anchors.left: parent.left; - anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width; - - color: UM.Theme.colors.save_button_text; - font: UM.Theme.fonts.default; - - text: (!control.printDuration || !control.printDuration.valid) ? "" : control.printDuration.getDisplayString(UM.DurationFormat.Long) + id: printDurationLabel + anchors.verticalCenter: parent.verticalCenter + anchors.left: label.right; + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width; + color: UM.Theme.colors.save_button_printtime_text; + font: UM.Theme.fonts.small; + visible: base.progress < 0.99 ? false : true + text: (!base.printDuration || !base.printDuration.valid) ? "" : base.printDuration.getDisplayString(UM.DurationFormat.Long); } Label { - anchors.left: parent.left; - anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width; - - color: UM.Theme.colors.save_button_text; - font: UM.Theme.fonts.default; - + id: printMaterialLabel + anchors.verticalCenter: parent.verticalCenter + anchors.left: printDurationLabel.right; + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width; + color: UM.Theme.colors.save_button_printtime_text; + font: UM.Theme.fonts.small; + visible: base.progress < 0.99 ? false : true //: Print material amount save button label - text: control.printMaterialAmount < 0 ? "" : qsTr("%1m material").arg(control.printMaterialAmount); + text: base.printMaterialAmount < 0 ? "" : qsTr("%1m material").arg(base.printMaterialAmount); } } - } + Rectangle { + id: infoBoxOverlay + anchors { + left: infoBox.left; + top: infoBox.top; + bottom: infoBox.bottom; + } + width: Math.max(infoBox.width * base.progress); + color: UM.Theme.colors.save_button_active + visible: base.progress > 0.99 ? false : true + } - MouseArea { - anchors.fill: parent; + Button { + id: saveToButton + anchors.top: infoBox.bottom + anchors.topMargin: UM.Theme.sizes.save_button_text_margin.height; + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.default_margin.width; + tooltip: '' + enabled: progress >= 0.99; - acceptedButtons: Qt.RightButton; - - onClicked: devicesMenu.popup(); - } - - Menu { - id: devicesMenu; - - Instantiator { - model: Printer.outputDeviceNames; - MenuItem { - text: Printer.outputDevices[modelData].description; - checkable: true; - checked: base.defaultAmbiguous ? false : modelData == base.currentDevice; - exclusiveGroup: devicesMenuGroup; - onTriggered: { - base.defaultOverride = true; - base.currentDevice = modelData; - if(base.defaultAmbiguous) { - base.defaultAmbiguous = false; - Printer.writeToOutputDevice(modelData); + width: infoBox.width/6*4.5 + height: UM.Theme.sizes.save_button_save_to_button.height + style: ButtonStyle { + background: Rectangle { + color: !control.enabled ? UM.Theme.colors.save_button_inactive : control.hovered ? UM.Theme.colors.save_button_active_hover : UM.Theme.colors.save_button_active; + Label { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + color: UM.Theme.colors.save_button_safe_to_text; + font: UM.Theme.fonts.sidebar_save_to; + text: Printer.outputDevices[base.currentDevice].description; } } } - onObjectAdded: devicesMenu.insertItem(index, object) - onObjectRemoved: devicesMenu.removeItem(object) + onClicked: + if(base.defaultAmbiguous) { + devicesMenu.popup(); + } else { + Printer.writeToOutputDevice(base.currentDevice); + } } - ExclusiveGroup { id: devicesMenuGroup; } - } + Button { + id: deviceSelectionMenu; + anchors.top: infoBox.bottom + anchors.topMargin: UM.Theme.sizes.save_button_text_margin.height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.sizes.default_margin.width; + tooltip: '' - text: { - if(base.progress < 0) { - //: Save button label - return qsTr("Please load a 3D model"); - } else if (base.progress < 0.95) { - //: Save button label - return qsTr("Calculating Print-time"); - } else { - //: Save button label - return qsTr("Estimated Print-time"); + width: infoBox.width/6*1.3 - UM.Theme.sizes.save_button_text_margin.height; + height: UM.Theme.sizes.save_button_save_to_button.height + + style: ButtonStyle { + background: Rectangle { + color: UM.Theme.colors.save_button_background; + border.width: control.hovered ? UM.Theme.sizes.save_button_border.width : 0 + border.color: UM.Theme.colors.save_button_border + Rectangle { + id: deviceSelectionIcon + color: UM.Theme.colors.save_button_background; + anchors.left: parent.left + anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width / 2; + anchors.verticalCenter: parent.verticalCenter; + width: parent.height - UM.Theme.sizes.save_button_text_margin.width ; + height: parent.height - UM.Theme.sizes.save_button_text_margin.width; + UM.RecolorImage { + anchors.centerIn: parent; + width: parent.width; + height: parent.height; + sourceSize.width: width; + sourceSize.height: height; + color: UM.Theme.colors.save_button_active + source: UM.Theme.icons[Printer.outputDevices[base.currentDevice].icon]; + } + } + Label { + id: deviceSelectionArrow + anchors.right: parent.right; + anchors.rightMargin: UM.Theme.sizes.save_button_text_margin.height + anchors.verticalCenter: parent.verticalCenter; + text: "▼"; + font: UM.Theme.fonts.tiny; + color: UM.Theme.colors.save_button_active; + } + } + } + + menu: Menu { + id: devicesMenu; + Instantiator { + model: Printer.outputDeviceNames; + MenuItem { + text: Printer.outputDevices[modelData].description; + checkable: true; + checked: base.defaultAmbiguous ? false : modelData == base.currentDevice; + exclusiveGroup: devicesMenuGroup; + onTriggered: { + base.defaultOverride = true; + base.currentDevice = modelData; + if(base.defaultAmbiguous) { + base.defaultAmbiguous = false; + Printer.writeToOutputDevice(modelData); + } + } + } + onObjectAdded: devicesMenu.insertItem(index, object) + onObjectRemoved: devicesMenu.removeItem(object) + } + ExclusiveGroup { id: devicesMenuGroup; } + } } } - - onClicked: { - if(base.defaultAmbiguous) { - devicesMenu.popup(); - } else { - Printer.writeToOutputDevice(base.currentDevice); - } - } -} +} \ No newline at end of file diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 0d4d0df599..23ddfe4ed7 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -8,18 +8,18 @@ import QtQuick.Layouts 1.1 import UM 1.0 as UM -UM.AngledCornerRectangle { +Rectangle { id: base; property Action addMachineAction; property Action configureMachinesAction; property alias saveAction: saveButton.saveAction; - cornerSize: UM.Theme.sizes.default_margin.width; - + color: UM.Theme.colors.sidebar; + function showTooltip(item, position, text) { tooltip.text = text; - position = item.mapToItem(base, position.x, position.y); + position = item.mapToItem(base, position.x, position.y / 2); tooltip.show(position); } @@ -39,7 +39,6 @@ UM.AngledCornerRectangle { ColumnLayout { anchors.fill: parent; anchors.topMargin: UM.Theme.sizes.default_margin.height; - anchors.bottomMargin: UM.Theme.sizes.window_margin.height; spacing: UM.Theme.sizes.default_margin.height; @@ -73,7 +72,7 @@ UM.AngledCornerRectangle { property Item sidebar: base; onLoaded: - { + { if(item) { item.configureSettings = base.configureMachinesAction; @@ -91,13 +90,11 @@ UM.AngledCornerRectangle { SaveButton { id: saveButton; - Layout.preferredWidth: base.width - UM.Theme.sizes.default_margin.width * 2; - Layout.preferredHeight: UM.Theme.sizes.button.height; - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter; + implicitWidth: base.width + implicitHeight: UM.Theme.sizes.save_button_text_margin.height * 2 + UM.Theme.sizes.save_button_slicing_bar.height + UM.Theme.sizes.save_button_save_to_button.height + UM.Theme.sizes.default_margin.height } - } - + SidebarTooltip { id: tooltip; } @@ -109,4 +106,11 @@ UM.AngledCornerRectangle { //: Advanced configuration mode option ListElement { text: QT_TR_NOOP("Advanced"); file: "SidebarAdvanced.qml" } } + + Component.onCompleted: { + for(var i = 0; i < modesListModel.count; ++i) + { + modesListModel.setProperty(i, "text", qsTr(modesListModel.get(i).text)); + } + } } diff --git a/resources/qml/SidebarAdvanced.qml b/resources/qml/SidebarAdvanced.qml index 7d0e391768..8a231aa53d 100644 --- a/resources/qml/SidebarAdvanced.qml +++ b/resources/qml/SidebarAdvanced.qml @@ -1,6 +1,13 @@ // Copyright (c) 2015 Ultimaker B.V. // Cura is released under the terms of the AGPLv3 or higher. +import QtQuick 2.0 + +import QtQuick.Controls 1.2 + import UM 1.0 as UM -UM.SettingView { } +UM.SettingView { + expandedCategories: Printer.expandedCategories; + onExpandedCategoriesChanged: Printer.setExpandedCategories(expandedCategories); +} diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 6059d48155..efc6949668 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -33,7 +33,7 @@ Column { } ToolButton { - text: base.modesModel ? qsTr(base.modesModel.get(modeMenu.currentIndex).text) : ""; + text: base.modesModel ? base.modesModel.get(modeMenu.currentIndex).text : ""; style: UM.Theme.styles.sidebar_header_button; @@ -48,7 +48,7 @@ Column { model: base.modesModel; MenuItem { - text: qsTr(model.text); + text: model.text; checkable: true; checked: modeMenu.currentIndex == index; exclusiveGroup: modeMenuGroup; diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 1b41da7d6f..c27f992031 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -20,6 +20,9 @@ Item { property variant minimumPrintTime: PrintInformation.minimumPrintTime; property variant maximumPrintTime: PrintInformation.maximumPrintTime; + Component.onCompleted: PrintInformation.enabled = true + Component.onDestruction: PrintInformation.enabled = false + ColumnLayout { anchors.fill: parent; diff --git a/resources/qml/SidebarTooltip.qml b/resources/qml/SidebarTooltip.qml index 9003faf995..6e0ba74404 100644 --- a/resources/qml/SidebarTooltip.qml +++ b/resources/qml/SidebarTooltip.qml @@ -22,10 +22,10 @@ Rectangle { function show(position) { if(position.y + base.height > parent.height) { - x = position.x; + x = position.x - base.width; y = parent.height - base.height; } else { - x = position.x; + x = position.x - base.width; y = position.y; } base.opacity = 1; diff --git a/resources/qml/Toolbar.qml b/resources/qml/Toolbar.qml index e24d929ed7..ec7a6bd839 100644 --- a/resources/qml/Toolbar.qml +++ b/resources/qml/Toolbar.qml @@ -14,6 +14,24 @@ Item { width: buttons.width; height: buttons.height + panel.height; + Rectangle { + id: activeItemBackground; + + anchors.bottom: parent.bottom; + anchors.bottomMargin: UM.Theme.sizes.default_margin.height; + + width: UM.Theme.sizes.button.width; + height: UM.Theme.sizes.button.height * 2; + + opacity: panelBackground.opacity; + + color: UM.Theme.colors.tool_panel_background + + function setActive(new_x) { + x = new_x; + } + } + RowLayout { id: buttons; @@ -30,10 +48,10 @@ Item { Button { text: model.name; iconSource: UM.Theme.icons[model.icon]; - tooltip: model.description; checkable: true; checked: model.active; + onCheckedChanged: if (checked) activeItemBackground.setActive(x); style: UM.Theme.styles.tool_button; @@ -43,20 +61,33 @@ Item { anchors.fill: parent; onClicked: parent.checked ? UM.Controller.setActiveTool(null) : UM.Controller.setActiveTool(model.id); } - } + } } } - Loader { - id: panel + UM.AngledCornerRectangle { + id: panelBackground; anchors.left: parent.left; - anchors.right: parent.right; anchors.bottom: buttons.top; anchors.bottomMargin: UM.Theme.sizes.default_margin.height; - height: childrenRect.height; + width: panel.item ? Math.max(panel.width + 2 * UM.Theme.sizes.default_margin.width, activeItemBackground.x + activeItemBackground.width) : 0; + height: panel.item ? panel.height + 2 * UM.Theme.sizes.default_margin.height : 0; - source: UM.ActiveTool.valid ? UM.ActiveTool.activeToolPanel : ""; + opacity: panel.item ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: 100 } } + + color: UM.Theme.colors.tool_panel_background; + cornerSize: width > 0 ? UM.Theme.sizes.default_margin.width : 0; + + Loader { + id: panel + + x: UM.Theme.sizes.default_margin.width; + y: UM.Theme.sizes.default_margin.height; + + source: UM.ActiveTool.valid ? UM.ActiveTool.activeToolPanel : ""; + } } } diff --git a/resources/settings/fdmprinter.json b/resources/settings/fdmprinter.json index 657102c5d2..fc0ea6fa7c 100644 --- a/resources/settings/fdmprinter.json +++ b/resources/settings/fdmprinter.json @@ -30,10 +30,10 @@ "machine_nozzle_expansion_angle": { "default": 45 } }, "categories": { - "resolution": { - "label": "Quality", + "layer_height": { + "label": "Layer Height", "visible": true, - "icon": "category_quality", + "icon": "category_layer_height", "settings": { "layer_height": { "label": "Layer Height", @@ -41,22 +41,28 @@ "unit": "mm", "type": "float", "default": 0.1, - "min_value": 0.06, - "max_value": 2.0, - "always_visible": true, - "children": { - "layer_height_0": { - "label": "Initial Layer Thickness", - "description": "The layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier.", - "unit": "mm", - "type": "float", - "default": 0.3, - "min_value": 0.06, - "max_value": 2.0, - "visible": false - } - } + "min_value": 0.0001, + "min_value_warning": 0.04, + "max_value_warning": 0.32 }, + "layer_height_0": { + "label": "Initial Layer Thickness", + "description": "The layer thickness of the bottom layer. A thicker bottom layer makes sticking to the bed easier.", + "unit": "mm", + "type": "float", + "default": 0.3, + "min_value": 0.0001, + "min_value_warning": 0.04, + "max_value_warning": 0.32, + "visible": false + } + } + }, + "shell": { + "label": "Shell", + "visible": true, + "icon": "category_shell", + "settings": { "shell_thickness": { "label": "Shell Thickness", "description": "The thickness of the outside shell in the horizontal and vertical direction. This is used in combination with the nozzle size to define the number of perimeter lines and the thickness of those perimeter lines. This is also used to define the number of solid top and bottom layers.", @@ -64,7 +70,8 @@ "type": "float", "default": 0.8, "min_value": 0.0, - "max_value": 5.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "children": { "wall_thickness": { "label": "Wall Thickness", @@ -72,9 +79,8 @@ "unit": "mm", "default": 0.8, "min_value": 0.0, - "max_value": 5.0, - "min_value_warning": 0.4, - "max_value_warning": 2.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "type": "float", "visible": false, @@ -82,6 +88,7 @@ "wall_line_count": { "label": "Wall Line Count", "description": "Number of shell lines. This these lines are called perimeter lines in other tools and impact the strength and structural integrity of your print.", + "min_value": 0, "default": 2, "type": "int", "visible": false, @@ -91,6 +98,9 @@ "label": "Wall Line Width", "description": "Width of a single shell line. Each line of the shell will be printed with this width in mind.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false, @@ -98,9 +108,12 @@ "children": { "wall_line_width_0": { - "label": "First Wall Line Width", + "label": "Outer Wall Line Width", "description": "Width of the outermost shell line. By printing a thinner outermost wall line you can print higher details with a larger nozzle.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -109,6 +122,9 @@ "label": "Other Walls Line Width", "description": "Width of a single shell line for all shell lines except the outermost one.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -117,14 +133,20 @@ "label": "Skirt line width", "description": "Width of a single skirt line.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false }, "skin_line_width": { "label": "Top/bottom line width", - "description": "Width of a single top/bottom printed line. Which are used to fill up the top/bottom areas of a print.", + "description": "Width of a single top/bottom printed line, used to fill up the top/bottom areas of a print.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -133,6 +155,9 @@ "label": "Infill line width", "description": "Width of the inner infill printed lines.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", "visible": false @@ -141,14 +166,40 @@ "label": "Support line width", "description": "Width of the printed support structures lines.", "unit": "mm", + "min_value": 0.0, + "min_value_warning": 0.2, + "max_value_warning": 5.0, "default": 0.4, "type": "float", - "visible": false + "visible": false, + "active_if" : { + "setting": "support_enable", + "value": true + } + }, + "support_roof_line_width": { + "label": "Support Hammock line width", + "description": "Width of a single hammock line, used to fill the roof of the support.", + "unit": "mm", + "default": 0.4, + "type": "float", + "visible": false, + "active_if" : { + "setting": "support_roof_enable", + "value": true + } } } } } }, + "alternate_extra_perimeter": { + "label": "Alternate Extra Wall", + "description": "Make an extra wall at every second layer, so that infill will be caught between an extra wall above and one below. This results in a better cohesion between infill and walls, but might have an impact on the surface quality.", + "type": "boolean", + "default": false, + "visible": false + }, "top_bottom_thickness": { "label": "Bottom/Top Thickness", "description": "This controls the thickness of the bottom and top layers, the amount of solid layers put down is calculated by the layer thickness and this value. Having this value a multiple of the layer thickness makes sense. And keep it near your wall thickness to make an evenly strong part.", @@ -166,6 +217,7 @@ "label": "Top Thickness", "description": "This controls the thickness of the top layers. The number of solid layers printed is calculated from the layer thickness and this value. Having this value be a multiple of the layer thickness makes sense. And keep it nearto your wall thickness to make an evenly strong part.", "unit": "mm", + "min_value": 0.0, "default": 0.8, "type": "float", "visible": false, @@ -174,7 +226,8 @@ "top_layers": { "label": "Top Layers", "description": "This controls the amount of top layers.", - "default": 4, + "min_value": 0, + "default": 8, "type": "int", "visible": false, "inherit_function": "math.ceil(parent_value / layer_height)" @@ -185,6 +238,7 @@ "label": "Bottom Thickness", "description": "This controls the thickness of the bottom layers. The number of solid layers printed is calculated from the layer thickness and this value. Having this value be a multiple of the layer thickness makes sense. And keep it near to your wall thickness to make an evenly strong part.", "unit": "mm", + "min_value": 0.0, "default": 0.8, "type": "float", "visible": false, @@ -193,7 +247,8 @@ "bottom_layers": { "label": "Bottom Layers", "description": "This controls the amount of bottom layers.", - "default": 4, + "min_value": 0, + "default": 8, "type": "int", "visible": false, "inherit_function": "math.ceil(parent_value / layer_height)" @@ -204,13 +259,54 @@ } } }, - "wall_overlap_avoid_enabled": { - "label": "Avoid Overlapping Walls", + "remove_overlapping_walls_enabled": { + "label": "Remove Overlapping Wall Parts", "description": "Remove parts of a wall which share an overlap which would result in overextrusion in some places. These overlaps occur in thin pieces in a model and sharp corners.", "type": "boolean", - "default": true, + "default": false, + "visible": false, + "children": { + "remove_overlapping_walls_0_enabled": { + "label": "Remove Overlapping Outer Wall Parts", + "description": "Remove parts of an outer wall which share an overlap which would result in overextrusion in some places. These overlaps occur in thin pieces in a model and sharp corners.", + "type": "boolean", + "default": false, + "visible": false, + "inherit": true + }, + "remove_overlapping_walls_x_enabled": { + "label": "Remove Overlapping Other Wall Parts", + "description": "Remove parts of an inner wall which share an overlap which would result in overextrusion in some places. These overlaps occur in thin pieces in a model and sharp corners.", + "type": "boolean", + "default": true, + "visible": false, + "inherit": false + } + } + }, + "travel_compensate_overlapping_walls_enabled": { + "label": "Compensate Wall Overlaps", + "description": "Compensate the flow for parts of a wall being laid down where there already is a piece of a wall. These overlaps occur in thin pieces in a model. Gcode generation might be slowed down considerably.", + "type": "boolean", + "default": false, "visible": false }, + "fill_perimeter_gaps":{ + "label": "Fill Gaps Between Walls", + "description": "Fill the gaps created by walls where they would otherwise be overlapping. This will also fill thin walls. Optionally only the gaps occurring within the top and bottom skin can be filled.", + "type": "enum", + "options": [ + "Nowhere", + "Everywhere", + "Skin" + ], + "default": "Everywhere", + "visible": false, + "active_if": { + "setting": "remove_overlapping_walls_x_enabled", + "value": true + } + }, "top_bottom_pattern": { "label": "Bottom/Top Pattern", "description": "Pattern of the top/bottom solid fill. This normally is done with lines to get the best possible finish, but in some cases a concentric fill gives a nicer end result.", @@ -222,6 +318,13 @@ "default": "Lines", "visible": false }, + "skin_alternate_rotation": { + "label": "Alternate Skin Rotation", + "description": "Alternate between diagonal skin fill and horizontal + vertical skin fill. Although the diagonal directions can print quicker, this option can improve on the printing quality by reducing the pillowing effect.", + "type": "boolean", + "default": false, + "visible": false + }, "skin_outline_count": { "label": "Skin Perimeter Line Count", "description": "Number of lines around skin regions. Using one or two skin perimeter lines can greatly improve on roofs which would start in the middle of infill cells.", @@ -243,233 +346,6 @@ } } }, - - "material": { - "label": "Material", - "visible": true, - "icon": "category_material", - "settings": { - "material_print_temperature": { - "label": "Printing Temperature", - "description": "The temperature used for printing. Set at 0 to pre-heat yourself. For PLA a value of 210C is usually used.\nFor ABS a value of 230C or higher is required.", - "unit": "°C", - "type": "float", - "default": 220, - "min_value": 10, - "max_value": 340 - }, - "material_bed_temperature": { - "label": "Bed Temperature", - "description": "The temperature used for the heated printer bed. Set at 0 to pre-heat it yourself.", - "unit": "°C", - "type": "float", - "default": 70, - "min_value": 0, - "max_value": 340 - }, - "material_diameter": { - "label": "Diameter", - "description": "The diameter of your filament needs to be measured as accurately as possible.\nIf you cannot measure this value you will have to calibrate it, a higher number means less extrusion, a smaller number generates more extrusion.", - "unit": "mm", - "type": "float", - "default": 2.85, - "min_value": 0.4, - "max_value": 5.0 - }, - "material_flow": { - "label": "Flow", - "description": "Flow compensation: the amount of material extruded is multiplied by this value.", - "unit": "%", - "default": 100.0, - "type": "float", - "min_value": 5.0, - "max_value": 300.0 - }, - "retraction_enable": { - "label": "Enable Retraction", - "description": "Retract the filament when the nozzle is moving over a non-printed area. Details about the retraction can be configured in the advanced tab.", - "type": "boolean", - "default": true, - - "children": { - "retraction_speed": { - "label": "Retraction Speed", - "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", - "unit": "mm/s", - "type": "float", - "default": 25.0, - "visible": false, - "inherit": false, - - "children": { - "retraction_retract_speed": { - "label": "Retraction Retract Speed", - "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", - "unit": "mm/s", - "type": "float", - "default": 25.0, - "visible": false - }, - "retraction_prime_speed": { - "label": "Retraction Prime Speed", - "description": "The speed at which the filament is pushed back after retraction.", - "unit": "mm/s", - "type": "float", - "default": 25.0, - "visible": false - } - } - }, - "retraction_amount": { - "label": "Retraction Distance", - "description": "The amount of retraction: Set at 0 for no retraction at all. A value of 4.5mm seems to generate good results for 3mm filament in Bowden-tube fed printers.", - "unit": "mm", - "type": "float", - "default": 4.5, - "visible": false, - "inherit": false - }, - "retraction_min_travel": { - "label": "Retraction Minimum Travel", - "description": "The minimum distance of travel needed for a retraction to happen at all. This helps ensure you do not get a lot of retractions in a small area.", - "unit": "mm", - "type": "float", - "default": 4.5, - "visible": false, - "inherit": false - }, - "retraction_combing": { - "label": "Enable Combing", - "description": "Combing keeps the head within the interior of the print whenever possible when traveling from one part of the print to another, and does not use retraction. If combing is disabled the printer head moves straight from the start point to the end point and it will always retract.", - "type": "boolean", - "default": true, - "visible": false, - "inherit": false - }, - "retraction_minimal_extrusion": { - "label": "Minimal Extrusion Before Retraction", - "description": "The minimum amount of extrusion that needs to happen between retractions. If a retraction should happen before this minimum is reached, it will be ignored. This avoids retracting repeatedly on the same piece of filament as that can flatten the filament and cause grinding issues.", - "unit": "mm", - "type": "float", - "default": 0.02, - "visible": false, - "inherit": false - }, - "retraction_hop": { - "label": "Z Hop when Retracting", - "description": "Whenever a retraction is done, the head is lifted by this amount to travel over the print. A value of 0.075 works well. This feature has a lot of positive effect on delta towers.", - "unit": "mm", - "type": "float", - "default": 0.0, - "visible": false, - "inherit": false - } - } - } - } - }, - "speed": { - "label": "Speed", - "visible": true, - "icon": "category_speed", - "settings": { - "speed_print": { - "label": "Print Speed", - "description": "The speed at which printing happens. A well-adjusted Ultimaker can reach 150mm/s, but for good quality prints you will want to print slower. Printing speed depends on a lot of factors, so you will need to experiment with optimal settings for this.", - "unit": "mm/s", - "type": "float", - "default": 50.0, - - "children": { - "speed_infill": { - "label": "Infill Speed", - "description": "The speed at which infill parts are printed. Printing the infill faster can greatly reduce printing time, but this can negatively affect print quality.", - "unit": "mm/s", - "type": "float", - "default": 50.0, - "visible": false - }, - "speed_wall": { - "label": "Shell Speed", - "description": "The speed at which shell is printed. Printing the outer shell at a lower speed improves the final skin quality.", - "unit": "mm/s", - "type": "float", - "default": 50.0, - "visible": false, - - "children": { - "speed_wall_0": { - "label": "Outer Shell Speed", - "description": "The speed at which outer shell is printed. Printing the outer shell at a lower speed improves the final skin quality. However, having a large difference between the inner shell speed and the outer shell speed will effect quality in a negative way.", - "unit": "mm/s", - "type": "float", - "default": 50.0, - "visible": false - }, - "speed_wall_x": { - "label": "Inner Shell Speed", - "description": "The speed at which all inner shells are printed. Printing the inner shell fasster than the outer shell will reduce printing time. It is good to set this in between the outer shell speed and the infill speed.", - "unit": "mm/s", - "type": "float", - "default": 50.0, - "visible": false - } - } - }, - "speed_topbottom": { - "label": "Top/Bottom Speed", - "description": "Speed at which top/bottom parts are printed. Printing the top/bottom faster can greatly reduce printing time, but this can negatively affect print quality.", - "unit": "mm/s", - "type": "float", - "default": 50.0, - "visible": false - }, - "speed_support": { - "label": "Support Speed", - "description": "The speed at which exterior support is printed. Printing exterior supports at higher speeds can greatly improve printing time. And the surface quality of exterior support is usually not important, so higher speeds can be used.", - "unit": "mm/s", - "type": "float", - "default": 50.0, - "visible": false, - "inherit_function": "speed_wall_0" - } - } - }, - "speed_travel": { - "label": "Travel Speed", - "description": "The speed at which travel moves are done. A well-built Ultimaker can reach speeds of 250mm/s. But some machines might have misaligned layers then.", - "unit": "mm/s", - "type": "float", - "default": 150.0 - }, - "speed_layer_0": { - "label": "Bottom Layer Speed", - "description": "The print speed for the bottom layer: You want to print the first layer slower so it sticks to the printer bed better.", - "unit": "mm/s", - "type": "float", - "default": 15.0, - "visible": false, - - "children": { - "skirt_speed": { - "label": "Skirt Speed", - "description": "The speed at which the skirt and brim are printed. Normally this is done at the initial layer speed. But sometimes you want to print the skirt at a different speed.", - "unit": "mm/s", - "type": "float", - "default": 15.0, - "visible": false - } - } - }, - "speed_slowdown_layers": { - "label": "Amount of Slower Layers", - "description": "The first few layers are printed slower then the rest of the object, this to get better adhesion to the printer bed and improve the overall success rate of prints. The speed is gradually increased over these layers. 4 layers of speed-up is generally right for most materials and printers.", - "type": "int", - "default": 4, - "visible": false - } - } - }, "infill": { "label": "Infill", "visible": true, @@ -504,7 +380,7 @@ "type": "float", "default": 2.0, "visible": false, - "inherit_function": "(infill_line_width * 100) / parent_value" + "inherit_function": "0 if parent_value == 0 else (infill_line_width * 100) / parent_value" } } }, @@ -537,6 +413,482 @@ } } }, + "material": { + "label": "Material", + "visible": true, + "icon": "category_material", + "settings": { + "material_print_temperature": { + "label": "Printing Temperature", + "description": "The temperature used for printing. Set at 0 to pre-heat yourself. For PLA a value of 210C is usually used.\nFor ABS a value of 230C or higher is required.", + "unit": "°C", + "type": "float", + "default": 210, + "min_value": 0, + "max_value_warning": 260 + }, + "material_bed_temperature": { + "label": "Bed Temperature", + "description": "The temperature used for the heated printer bed. Set at 0 to pre-heat it yourself.", + "unit": "°C", + "type": "float", + "default": 60, + "min_value": 0, + "max_value_warning": 260 + }, + "material_diameter": { + "label": "Diameter", + "description": "The diameter of your filament needs to be measured as accurately as possible.\nIf you cannot measure this value you will have to calibrate it, a higher number means less extrusion, a smaller number generates more extrusion.", + "unit": "mm", + "type": "float", + "default": 2.85, + "min_value_warning": 0.4, + "max_value_warning": 3.5 + }, + "material_flow": { + "label": "Flow", + "description": "Flow compensation: the amount of material extruded is multiplied by this value.", + "unit": "%", + "default": 100.0, + "type": "float", + "min_value": 5.0, + "min_value_warning": 50.0, + "max_value_warning": 150.0 + } + } + }, + "speed": { + "label": "Speed", + "visible": true, + "icon": "category_speed", + "settings": { + "speed_print": { + "label": "Print Speed", + "description": "The speed at which printing happens. A well-adjusted Ultimaker can reach 150mm/s, but for good quality prints you will want to print slower. Printing speed depends on a lot of factors, so you will need to experiment with optimal settings for this.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, + "default": 50.0, + + "children": { + "speed_infill": { + "label": "Infill Speed", + "description": "The speed at which infill parts are printed. Printing the infill faster can greatly reduce printing time, but this can negatively affect print quality.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, + "default": 50.0, + "visible": false + }, + "speed_wall": { + "label": "Shell Speed", + "description": "The speed at which shell is printed. Printing the outer shell at a lower speed improves the final skin quality.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, + "default": 50.0, + "visible": false, + + "children": { + "speed_wall_0": { + "label": "Outer Shell Speed", + "description": "The speed at which outer shell is printed. Printing the outer shell at a lower speed improves the final skin quality. However, having a large difference between the inner shell speed and the outer shell speed will effect quality in a negative way.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, + "default": 50.0, + "visible": false + }, + "speed_wall_x": { + "label": "Inner Shell Speed", + "description": "The speed at which all inner shells are printed. Printing the inner shell fasster than the outer shell will reduce printing time. It is good to set this in between the outer shell speed and the infill speed.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, + "default": 50.0, + "visible": false + } + } + }, + "speed_topbottom": { + "label": "Top/Bottom Speed", + "description": "Speed at which top/bottom parts are printed. Printing the top/bottom faster can greatly reduce printing time, but this can negatively affect print quality.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, + "default": 50.0, + "visible": false + }, + "speed_support": { + "label": "Support Speed", + "description": "The speed at which exterior support is printed. Printing exterior supports at higher speeds can greatly improve printing time. And the surface quality of exterior support is usually not important, so higher speeds can be used.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 150.0, + "default": 50.0, + "visible": false, + "inherit_function": "speed_wall_0", + "active_if" : { + "setting": "support_enable", + "value": true + }, + "children": { + "speed_support_lines": { + "label": "Support Wall Speed", + "description": "The speed at which the walls of exterior support are printed. Printing the walls at higher speeds can improve on the overall duration. ", + "unit": "mm/s", + "type": "float", + "default": 50.0, + "visible": false, + "inherit": true, + "active_if" : { + "setting": "support_roof_enable", + "value": true + } + }, + "speed_support_roof": { + "label": "Support Hammock Speed", + "description": "The speed at which the roofs of exterior support are printed. Printing the hammock at lower speeds can improve on overhang quality. ", + "unit": "mm/s", + "type": "float", + "default": 40.0, + "visible": false, + "inherit": false, + "active_if" : { + "setting": "support_roof_enable", + "value": true + } + } + } + } + } + }, + "speed_travel": { + "label": "Travel Speed", + "description": "The speed at which travel moves are done. A well-built Ultimaker can reach speeds of 250mm/s. But some machines might have misaligned layers then.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "max_value_warning": 300.0, + "default": 150.0 + }, + "speed_layer_0": { + "label": "Bottom Layer Speed", + "description": "The print speed for the bottom layer: You want to print the first layer slower so it sticks to the printer bed better.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "default": 15.0, + "visible": false, + + "children": { + "skirt_speed": { + "label": "Skirt Speed", + "description": "The speed at which the skirt and brim are printed. Normally this is done at the initial layer speed. But sometimes you want to print the skirt at a different speed.", + "unit": "mm/s", + "type": "float", + "min_value": 0.1, + "default": 15.0, + "visible": false + } + } + }, + "speed_slowdown_layers": { + "label": "Amount of Slower Layers", + "description": "The first few layers are printed slower then the rest of the object, this to get better adhesion to the printer bed and improve the overall success rate of prints. The speed is gradually increased over these layers. 4 layers of speed-up is generally right for most materials and printers.", + "type": "int", + "min_value": 0, + "default": 4, + "visible": false + } + } + }, + "travel": { + "label": "Travel", + "visible": true, + "icon": "category_travel", + "settings": { + "retraction_enable": { + "label": "Enable Retraction", + "description": "Retract the filament when the nozzle is moving over a non-printed area. Details about the retraction can be configured in the advanced tab.", + "type": "boolean", + "default": true + }, + "retraction_speed": { + "label": "Retraction Speed", + "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", + "unit": "mm/s", + "type": "float", + "default": 25.0, + "visible": false, + "inherit": false, + "active_if": { + "setting": "retraction_enable", + "value": true + }, + "children": { + "retraction_retract_speed": { + "label": "Retraction Retract Speed", + "description": "The speed at which the filament is retracted. A higher retraction speed works better, but a very high retraction speed can lead to filament grinding.", + "unit": "mm/s", + "type": "float", + "default": 25.0, + "visible": false, + "active_if": { + "setting": "retraction_enable", + "value": true + } + }, + "retraction_prime_speed": { + "label": "Retraction Prime Speed", + "description": "The speed at which the filament is pushed back after retraction.", + "unit": "mm/s", + "type": "float", + "default": 25.0, + "visible": false, + "active_if": { + "setting": "retraction_enable", + "value": true + } + } + } + }, + "retraction_amount": { + "label": "Retraction Distance", + "description": "The amount of retraction: Set at 0 for no retraction at all. A value of 4.5mm seems to generate good results for 3mm filament in Bowden-tube fed printers.", + "unit": "mm", + "type": "float", + "default": 4.5, + "visible": false, + "inherit": false, + "active_if": { + "setting": "retraction_enable", + "value": true + } + }, + "retraction_min_travel": { + "label": "Retraction Minimum Travel", + "description": "The minimum distance of travel needed for a retraction to happen at all. This helps ensure you do not get a lot of retractions in a small area.", + "unit": "mm", + "type": "float", + "default": 4.5, + "visible": false, + "inherit": false, + "active_if": { + "setting": "retraction_enable", + "value": true + } + }, + "retraction_count_max": { + "label": "Maximal Retraction Count", + "description": "This settings limits the number of retractions occuring within the Minimal Extrusion Distance Window. Further retractions within this window will be ignored. This avoids retracting repeatedly on the same piece of filament as that can flatten the filament and cause grinding issues.", + "default": 6, + "type": "int", + "visible": false, + "inherit": false, + "active_if": { + "setting": "retraction_enable", + "value": true + } + }, + "retraction_extrusion_window": { + "label": "Minimal Extrusion Distance Window", + "description": "The window in which the Maximal Retraction Count is enforced. This window should be approximately the size of the Retraction distance, so that effectively the number of times a retraction passes the same patch of material is limited.", + "unit": "mm", + "type": "float", + "default": 4.5, + "visible": false, + "inherit_function": "retraction_amount", + "active_if": { + "setting": "retraction_enable", + "value": true + } + }, + "retraction_hop": { + "label": "Z Hop when Retracting", + "description": "Whenever a retraction is done, the head is lifted by this amount to travel over the print. A value of 0.075 works well. This feature has a lot of positive effect on delta towers.", + "unit": "mm", + "type": "float", + "default": 0.0, + "visible": false, + "inherit": false, + "active_if": { + "setting": "retraction_enable", + "value": true + } + }, + "retraction_combing": { + "label": "Enable Combing", + "description": "Combing keeps the head within the interior of the print whenever possible when traveling from one part of the print to another, and does not use retraction. If combing is disabled the printer head moves straight from the start point to the end point and it will always retract.", + "type": "boolean", + "default": true, + "visible": false + }, + "travel_avoid_other_parts": { + "label": "Avoid Printed Parts", + "description": "Avoid other parts when traveling between parts.", + "type": "boolean", + "default": true, + "visible": false, + "active_if": { + "setting": "retraction_combing", + "value": true + }, + "children": { + "travel_avoid_distance": { + "label": "Avoid Distance", + "description": "The distance to stay clear of parts which are avoided during travel.", + "unit": "mm", + "type": "float", + "default": 1.5, + "visible": false, + "inherit": false, + "active_if": { + "setting": "retraction_combing", + "value": true + } + } + } + }, + "coasting_enable": { + "label": "Enable Coasting", + "description": "Coasting replaces the last part of an extrusion path with a travel path. The oozed material is used to lay down the last piece of the extrusion path in order to reduce stringing.", + "type": "boolean", + "default": true, + "visible": true + }, + "coasting_volume": { + "label": "Coasting Volume", + "description": "The volume otherwise oozed. This value should generally be close to the nozzle diameter cubed.", + "unit": "mm³", + "type": "float", + "default": 0.064, + "visible": false, + "inherit": false, + "active_if": { + "setting": "coasting_enable", + "value": true + }, + "children": { + "coasting_volume_retract": { + "label": "Retract-Coasting Volume", + "description": "The volume otherwise oozed in a travel move with retraction.", + "unit": "mm³", + "type": "float", + "default": 0.096, + "visible": false, + "inherit": true, + "active_if": { + "setting": "coasting_enable", + "value": true + } + }, + "coasting_volume_move": { + "label": "Move-Coasting Volume", + "description": "The volume otherwise oozed in a travel move without retraction.", + "unit": "mm³", + "type": "float", + "default": 0.064, + "visible": false, + "inherit": true, + "active_if": { + "setting": "coasting_enable", + "value": true + } + } + } + }, + "coasting_min_volume": { + "label": "Minimal Volume Before Coasting", + "description": "The least volume an extrusion path should have to coast the full amount. For smaller extrusion paths, less pressure has been built up in the bowden tube and so the coasted volume is scaled linearly.", + "unit": "mm³", + "type": "float", + "default": 0.8, + "visible": false, + "inherit": false, + "active_if": { + "setting": "coasting_enable", + "value": true + }, + "children": { + "coasting_min_volume_retract": { + "label": "Min Volume Retract-Coasting", + "description": "The minimal volume an extrusion path must have in order to coast the full amount before doing a retraction.", + "unit": "mm³", + "type": "float", + "default": 0.6, + "visible": false, + "inherit": true, + "active_if": { + "setting": "coasting_enable", + "value": true + } + }, + "coasting_min_volume_move": { + "label": "Min Volume Move-Coasting", + "description": "The minimal volume an extrusion path must have in order to coast the full amount before doing a travel move without retraction.", + "unit": "mm³", + "type": "float", + "default": 0.8, + "visible": false, + "inherit": true, + "active_if": { + "setting": "coasting_enable", + "value": true + } + } + } + }, + "coasting_speed": { + "label": "Coasting Speed", + "description": "The speed by which to move during coasting, relative to the speed of the extrusion path. A value slightly under 100% is advised, since during the coasting move, the pressure in the bowden tube drops.", + "unit": "%", + "type": "float", + "default": 90.0, + "visible": false, + "inherit": false, + "active_if": { + "setting": "coasting_enable", + "value": true + }, + "children": { + "coasting_speed_retract": { + "label": "Retract-Coasting Speed", + "description": "The speed by which to move during coasting before a retraction, relative to the speed of the extrusion path.", + "unit": "%", + "type": "float", + "default": 90.0, + "visible": false, + "inherit": true, + "active_if": { + "setting": "coasting_enable", + "value": true + } + }, + "coasting_speed_move": { + "label": "Move-Coasting Speed", + "description": "The speed by which to move during coasting before a travel move without retraction, relative to the speed of the extrusion path.", + "unit": "%", + "type": "float", + "default": 90.0, + "visible": false, + "inherit": true, + "active_if": { + "setting": "coasting_enable", + "value": true + } + } + } + } + } + }, "cooling": { "label": "Cooling", "visible": true, @@ -554,6 +906,8 @@ "description": "Fan speed used for the print cooling fan on the printer head.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 100.0, "visible": false, "inherit_function": "100.0 if parent_value else 0.0", @@ -564,6 +918,8 @@ "description": "Normally the fan runs at the minimum fan speed. If the layer is slowed down due to minimum layer time, the fan speed adjusts between minimum and maximum fan speed.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 100.0, "visible": false }, @@ -572,6 +928,8 @@ "description": "Normally the fan runs at the minimum fan speed. If the layer is slowed down due to minimum layer time, the fan speed adjusts between minimum and maximum fan speed.", "unit": "%", "type": "float", + "min_value": 0.0, + "max_value": 100.0, "default": 100.0, "visible": false } @@ -584,6 +942,7 @@ "description": "The height at which the fan is turned on completely. For the layers below this the fan speed is scaled linearly with the fan off for the first layer.", "unit": "mm", "type": "float", + "min_value": 0.0, "default": 0.5, "visible": false, @@ -592,6 +951,7 @@ "label": "Fan Full on at Layer", "description": "The layer number at which the fan is turned on completely. For the layers below this the fan speed is scaled linearly with the fan off for the first layer.", "type": "int", + "min_value": 0, "default": 4, "visible": false, "inherit_function": "int((parent_value - layer_height_0 + 0.001) / layer_height)" @@ -603,6 +963,7 @@ "description": "The minimum time spent in a layer: Gives the layer time to cool down before the next one is put on top. If a layer would print in less time, then the printer will slow down to make sure it has spent at least this many seconds printing the layer.", "unit": "sec", "type": "float", + "min_value": 0.0, "default": 5.0, "visible": false }, @@ -611,6 +972,7 @@ "description": "The minimum time spent in a layer which will cause the fan to be at minmum speed. The fan speed increases linearly from maximal fan speed for layers taking minimal layer time to minimal fan speed for layers taking the time specified here.", "unit": "sec", "type": "float", + "min_value": 0.0, "default": 10.0, "visible": false }, @@ -631,235 +993,6 @@ } } }, - "support": { - "label": "Support", - "visible": true, - "icon": "category_support", - "settings": { - "support_enable": { - "label": "Enable Support", - "description": "Enable exterior support structures. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air.", - "type": "boolean", - "default": true - }, - "support_type": { - "label": "Placement", - "description": "Where to place support structures. The placement can be restricted such that the support structures won't rest on the model, which could otherwise cause scarring.", - "type": "enum", - "options": [ - "None", - "Touching Buildplate", - "Everywhere" - ], - "default": "Touching Buildplate", - "visible": true, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_angle": { - "label": "Overhang Angle", - "description": "The maximum angle of overhangs for which support will be added. With 0 degrees being horizontal, and 90 degrees being vertical.", - "unit": "°", - "type": "float", - "default": 60.0, - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_xy_distance": { - "label": "X/Y Distance", - "description": "Distance of the support structure from the print, in the X/Y directions. 0.7mm typically gives a nice distance from the print so the support does not stick to the surface.", - "unit": "mm", - "type": "float", - "default": 0.7, - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_z_distance": { - "label": "Z Distance", - "description": "Distance from the top/bottom of the support to the print. A small gap here makes it easier to remove the support but makes the print a bit uglier. 0.15mm allows for easier separation of the support structure.", - "unit": "mm", - "type": "float", - "default": 0.15, - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - }, - "children": { - "support_top_distance": { - "label": "Top Distance", - "description": "Distance from the top of the support to the print.", - "unit": "mm", - "default": 0.15, - "type": "float", - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_bottom_distance": { - "label": "Bottom Distance", - "description": "Distance from the print to the bottom of the support.", - "unit": "mm", - "default": 0.15, - "type": "float", - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - } - } - } - }, - "support_bottom_stair_step_height": { - "label": "Stair Step Height", - "description": "The height of the steps of the stair-like bottom of support resting on the model. Small steps can cause the support to be hard to remove from the top of the model.", - "unit": "mm", - "type": "float", - "default": 0.5, - "visible": false, - "active_if": { - "setting": "support_type", - "value": "Everywhere" - } - }, - "support_join_distance": { - "label": "Join Distance", - "description": "The maximum distance between support blocks, in the X/Y directions, such that the blocks will merge into a single block.", - "unit": "mm", - "type": "float", - "default": 0.7, - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_area_smoothing": { - "label": "Area Smoothing", - "description": "Maximal distance in the X/Y directions of a line segment which is to be smoothed out. Ragged lines are introduced by the join distance and support bridge, which cause the machine to resonate. Smoothing the support areas won't cause them to break with the constraints, except it might change the overhang.", - "unit": "mm", - "type": "float", - "default": 0.6, - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_use_towers": { - "label": "Use towers.", - "description": "Use specialized towers to support tiny overhang areas. These towers have a larger diameter than the region they support. Near the overhang the towers' diameter decreases, forming a roof.", - "type": "boolean", - "default": true, - "visible": true, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_minimal_diameter": { - "label": "Minimal Diameter", - "description": "Maximal diameter in the X/Y directions of a small area which is to be supported by a specialized support tower. ", - "unit": "mm", - "type": "float", - "default": 1.0, - "visible": false, - "active_if": { - "setting": "support_use_towers", - "value": true - } - }, - "support_tower_diameter": { - "label": "Tower Diameter", - "description": "The diameter of a special tower. ", - "unit": "mm", - "type": "float", - "default": 1.0, - "visible": false, - "active_if": { - "setting": "support_use_towers", - "value": true - } - }, - "support_tower_roof_angle": { - "label": "Tower Roof Angle", - "description": "The angle of the rooftop of a tower. Larger angles mean more pointy towers. ", - "unit": "°", - "type": "int", - "default": 65, - "visible": false, - "active_if": { - "setting": "support_use_towers", - "value": true - } - }, - "support_pattern": { - "label": "Pattern", - "description": "Cura supports 3 distinct types of support structure. First is a grid based support structure which is quite solid and can be removed as 1 piece. The second is a line based support structure which has to be peeled off line by line. The third is a structure in between the other two; it consists of lines which are connected in an accordeon fashion.", - "type": "enum", - "options": [ - "Grid", - "Lines", - "ZigZag" - ], - "default": "Lines", - "visible": true, - "active_if": { - "setting": "support_enable", - "value": true - } - }, - "support_connect_zigzags": { - "label": "Connect ZigZags", - "description": "Connect the ZigZags. Makes them harder to remove, but prevents stringing of disconnected zigzags.", - "type": "boolean", - "default": true, - "visible": false, - "active_if": { - "setting": "support_pattern", - "value": "ZigZag" - } - }, - "support_fill_rate": { - "label": "Fill Amount", - "description": "The amount of infill structure in the support, less infill gives weaker support which is easier to remove.", - "unit": "%", - "type": "float", - "default": 15, - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - }, - - "children": { - "support_line_distance": { - "label": "Line distance", - "description": "Distance between the printed support lines.", - "unit": "mm", - "type": "float", - "default": 2.66, - "visible": false, - "active_if": { - "setting": "support_enable", - "value": true - }, - "inherit_function": "(support_line_width * 100) / parent_value" - } - } - } - } - }, "platform_adhesion": { "label": "Platform Adhesion", "visible": true, @@ -929,72 +1062,6 @@ "value": "Raft" } }, - "raft_line_spacing": { - "label": "Raft Line Spacing", - "description": "The distance between the raft lines. The first 2 layers of the raft have this amount of spacing between the raft lines.", - "unit": "mm", - "type": "float", - "default": 5.0, - "active_if": { - "setting": "adhesion_type", - "value": "Raft" - } - }, - "raft_base_thickness": { - "label": "Raft Base Thickness", - "description": "Layer thickness of the first raft layer. This should be a thick layer which sticks firmly to the printer bed.", - "unit": "mm", - "type": "float", - "default": 0.3, - "active_if": { - "setting": "adhesion_type", - "value": "Raft" - } - }, - "raft_base_linewidth": { - "label": "Raft Base Line Width", - "description": "Width of the lines in the first raft layer. These should be thick lines to assist in bed adhesion.", - "unit": "mm", - "type": "float", - "default": 1.0, - "active_if": { - "setting": "adhesion_type", - "value": "Raft" - } - }, - "raft_base_speed": { - "label": "Raft Base Print Speed", - "description": "The speed at which the first raft layer is printed. This should be printed quite slowly, as the amount of material coming out of the nozzle is quite high.", - "unit": "mm/s", - "type": "float", - "default": 15.0, - "active_if": { - "setting": "adhesion_type", - "value": "Raft" - } - }, - "raft_interface_thickness": { - "label": "Raft Interface Thickness", - "description": "Thickness of the 2nd raft layer.", - "unit": "mm", - "type": "float", - "default": 0.27, - "active_if": { - "setting": "adhesion_type", - "value": "Raft" - } - }, - "raft_interface_linewidth": { - "label": "Raft Interface Line Width", - "description": "Width of the 2nd raft layer lines. These lines should be thinner than the first layer, but strong enough to attach the object to.", - "unit": "mm", - "type": "float", - "default": 0.4, - "active_if": { - "setting": "adhesion_type", - "value": "Raft" - } - }, "raft_airgap": { "label": "Raft Air-gap", "description": "The gap between the final raft layer and the first layer of the object. Only the first layer is raised by this amount to lower the bonding between the raft layer and the object. Makes it easier to peel off the raft.", @@ -1015,16 +1082,495 @@ "setting": "adhesion_type", "value": "Raft" } + }, + "raft_surface_thickness": { + "label": "Raft Surface Thickness", + "description": "Layer thickness of the surface raft layers.", + "unit": "mm", + "type": "float", + "default": 0.1, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_surface_line_width": { + "label": "Raft Surface Line Width", + "description": "Width of the lines in the surface raft layers. These can be thin lines so that the top of the raft becomes smooth.", + "unit": "mm", + "type": "float", + "default": 0.3, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_surface_line_spacing": { + "label": "Raft Surface Spacing", + "description": "The distance between the raft lines for the surface raft layers. The spacing of the interface should be equal to the line width, so that the surface is solid.", + "unit": "mm", + "type": "float", + "default": 0.3, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + }, + "inherit_function": "raft_surface_line_width" + }, + "raft_interface_thickness": { + "label": "Raft Interface Thickness", + "description": "Layer thickness of the interface raft layer.", + "unit": "mm", + "type": "float", + "default": 0.27, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_interface_line_width": { + "label": "Raft Interface Line Width", + "description": "Width of the lines in the interface raft layer. Making the second layer extrude more causes the lines to stick to the bed.", + "unit": "mm", + "type": "float", + "default": 1.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_interface_line_spacing": { + "label": "Raft Interface Spacing", + "description": "The distance between the raft lines for the interface raft layer. The spacing of the interface should be quite wide, while being dense enough to support the surface raft layers.", + "unit": "mm", + "type": "float", + "default": 2.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_base_thickness": { + "label": "Raft Base Thickness", + "description": "Layer thickness of the base raft layer. This should be a thick layer which sticks firmly to the printer bed.", + "unit": "mm", + "type": "float", + "default": 0.3, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_base_line_width": { + "label": "Raft Base Line Width", + "description": "Width of the lines in the base raft layer. These should be thick lines to assist in bed adhesion.", + "unit": "mm", + "type": "float", + "default": 1.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_base_line_spacing": { + "label": "Raft Line Spacing", + "description": "The distance between the raft lines for the base raft layer. Wide spacing makes for easy removal of the raft from the build plate.", + "unit": "mm", + "type": "float", + "default": 5.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + } + }, + "raft_speed": { + "label": "Raft Print Speed", + "description": "The speed at which the raft is printed.", + "unit": "mm/s", + "type": "float", + "default": 30.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + }, + "inherit_function": "0.6 * speed_print", + "children": { + "raft_surface_speed": { + "label": "Raft Surface Print Speed", + "description": "The speed at which the surface raft layers are printed. This should be printed a bit slower, so that the nozzle can slowly smooth out adjacent surface lines.", + "unit": "mm/s", + "type": "float", + "default": 30.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + }, + "inherit_function": "parent_value" + }, + "raft_interface_speed": { + "label": "Raft Interface Print Speed", + "description": "The speed at which the interface raft layer is printed. This should be printed quite slowly, as the amount of material coming out of the nozzle is quite high.", + "unit": "mm/s", + "type": "float", + "default": 15.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + }, + "inherit_function": "0.5 * parent_value" + }, + "raft_base_speed": { + "label": "Raft Base Print Speed", + "description": "The speed at which the base raft layer is printed. This should be printed quite slowly, as the amount of material coming out of the nozzle is quite high.", + "unit": "mm/s", + "type": "float", + "default": 15.0, + "active_if": { + "setting": "adhesion_type", + "value": "Raft" + }, + "inherit_function": "0.5 * parent_value" + } + } + }, + "raft_fan_speed": { + "label": "Raft Fan Speed", + "description": "The fan speed for the raft.", + "unit": "%", + "type": "float", + "min_value": 0.0, + "max_value": 100.0, + "default": 100.0, + "visible": false, + "children": { + "raft_surface_fan_speed": { + "label": "Raft Surface Fan Speed", + "description": "The fan speed for the surface raft layers.", + "unit": "%", + "type": "float", + "min_value": 0.0, + "max_value": 100.0, + "default": 100.0, + "visible": false, + "inherit": true + }, + "raft_interface_fan_speed": { + "label": "Raft Interface Fan Speed", + "description": "The fan speed for the interface raft layer.", + "unit": "%", + "type": "float", + "min_value": 0.0, + "max_value": 100.0, + "default": 100.0, + "visible": false, + "inherit": true + }, + "raft_base_fan_speed": { + "label": "Raft Base Fan Speed", + "description": "The fan speed for the base raft layer.", + "unit": "%", + "type": "float", + "min_value": 0.0, + "max_value": 100.0, + "default": 100.0, + "visible": false, + "inherit": true + } + } } } }, - "blackmagic": { + "support": { + "label": "Support", + "visible": true, + "icon": "category_support", + "settings": { + "support_enable": { + "label": "Enable Support", + "description": "Enable exterior support structures. This will build up supporting structures below the model to prevent the model from sagging or printing in mid air.", + "type": "boolean", + "default": true + }, + "support_type": { + "label": "Placement", + "description": "Where to place support structures. The placement can be restricted such that the support structures won't rest on the model, which could otherwise cause scarring.", + "type": "enum", + "options": [ + "Touching Buildplate", + "Everywhere" + ], + "default": "Everywhere", + "visible": true, + "inherit_function": "'Everywhere' if support_enable else 'None'", + "active_if": { + "setting": "support_enable", + "value": true + } + }, + "support_angle": { + "label": "Overhang Angle", + "description": "The maximum angle of overhangs for which support will be added. With 0 degrees being vertical, and 90 degrees being horizontal. A smaller overhang angle leads to more support.", + "unit": "°", + "type": "float", + "min_value": 0.0, + "max_value": 90.0, + "default": 60.0, + "visible": false, + "active_if": { + "setting": "support_enable", + "value": true + } + }, + "support_xy_distance": { + "label": "X/Y Distance", + "description": "Distance of the support structure from the print, in the X/Y directions. 0.7mm typically gives a nice distance from the print so the support does not stick to the surface.", + "unit": "mm", + "type": "float", + "min_value": 0.0, + "max_value_warning": 10.0, + "default": 0.7, + "visible": false, + "active_if": { + "setting": "support_enable", + "value": true + } + }, + "support_z_distance": { + "label": "Z Distance", + "description": "Distance from the top/bottom of the support to the print. A small gap here makes it easier to remove the support but makes the print a bit uglier. 0.15mm allows for easier separation of the support structure.", + "unit": "mm", + "type": "float", + "min_value": 0.0, + "max_value_warning": 10.0, + "default": 0.15, + "visible": false, + "active_if": { + "setting": "support_enable", + "value": true + }, + "children": { + "support_top_distance": { + "label": "Top Distance", + "description": "Distance from the top of the support to the print.", + "unit": "mm", + "min_value": 0.0, + "max_value_warning": 10.0, + "default": 0.15, + "type": "float", + "visible": false + }, + "support_bottom_distance": { + "label": "Bottom Distance", + "description": "Distance from the print to the bottom of the support.", + "unit": "mm", + "min_value": 0.0, + "max_value_warning": 10.0, + "default": 0.15, + "type": "float", + "visible": false + } + } + }, + "support_bottom_stair_step_height": { + "label": "Stair Step Height", + "description": "The height of the steps of the stair-like bottom of support resting on the model. Small steps can cause the support to be hard to remove from the top of the model.", + "unit": "mm", + "type": "float", + "default": 1.0, + "visible": false, + "active_if": { + "setting": "support_type", + "value": "Everywhere" + } + }, + "support_join_distance": { + "label": "Join Distance", + "description": "The maximum distance between support blocks, in the X/Y directions, such that the blocks will merge into a single block.", + "unit": "mm", + "type": "float", + "default": 2.0, + "visible": false + }, + "support_area_smoothing": { + "label": "Area Smoothing", + "description": "Maximal distance in the X/Y directions of a line segment which is to be smoothed out. Ragged lines are introduced by the join distance and support bridge, which cause the machine to resonate. Smoothing the support areas won't cause them to break with the constraints, except it might change the overhang.", + "unit": "mm", + "type": "float", + "default": 0.6, + "visible": false + }, + "support_roof_enable": { + "label": "Enable Hammock", + "description": "Generate a solid support roof on which the model sits.", + "type": "boolean", + "default": false, + "visible": true + }, + "support_roof_height": { + "label": "Hammock Thickness", + "description": "The height of the support roofs. ", + "unit": "mm", + "type": "float", + "default": 1.0, + "visible": false, + "active_if": { + "setting": "support_roof_enable", + "value": true + } + }, + "support_use_towers": { + "label": "Use towers.", + "description": "Use specialized towers to support tiny overhang areas. These towers have a larger diameter than the region they support. Near the overhang the towers' diameter decreases, forming a roof.", + "type": "boolean", + "default": true, + "visible": true + }, + "support_minimal_diameter": { + "label": "Minimal Diameter", + "description": "Maximal diameter in the X/Y directions of a small area which is to be supported by a specialized support tower. ", + "unit": "mm", + "type": "float", + "default": 1.0, + "visible": false, + "active_if": { + "setting": "support_use_towers", + "value": true + } + }, + "support_tower_diameter": { + "label": "Tower Diameter", + "description": "The diameter of a special tower. ", + "unit": "mm", + "type": "float", + "default": 1.0, + "visible": false, + "active_if": { + "setting": "support_use_towers", + "value": true + } + }, + "support_tower_roof_angle": { + "label": "Tower Roof Angle", + "description": "The angle of the rooftop of a tower. Larger angles mean more pointy towers. ", + "unit": "°", + "type": "int", + "min_value": 0, + "max_value": 90, + "default": 65, + "visible": false, + "active_if": { + "setting": "support_use_towers", + "value": true + } + }, + "support_pattern": { + "label": "Pattern", + "description": "Cura supports 3 distinct types of support structure. First is a grid based support structure which is quite solid and can be removed as 1 piece. The second is a line based support structure which has to be peeled off line by line. The third is a structure in between the other two; it consists of lines which are connected in an accordeon fashion.", + "type": "enum", + "options": [ + "Grid", + "Lines", + "ZigZag" + ], + "default": "ZigZag", + "visible": true, + "active_if": { + "setting": "support_enable", + "value": true + } + }, + "support_connect_zigzags": { + "label": "Connect ZigZags", + "description": "Connect the ZigZags. Makes them harder to remove, but prevents stringing of disconnected zigzags.", + "type": "boolean", + "default": true, + "visible": false, + "active_if": { + "setting": "support_pattern", + "value": "ZigZag" + } + }, + "support_fill_rate": { + "label": "Fill Amount", + "description": "The amount of infill structure in the support, less infill gives weaker support which is easier to remove.", + "unit": "%", + "type": "float", + "min_value": 0.0, + "max_value": 100.0, + "default": 15, + "visible": false, + "active_if": { + "setting": "support_enable", + "value": true + }, + "children": { + "support_line_distance": { + "label": "Line distance", + "description": "Distance between the printed support lines.", + "unit": "mm", + "type": "float", + "min_value": 0.0, + "default": 2.66, + "visible": false, + "active_if": { + "setting": "support_enable", + "value": true + }, + "inherit_function": "(support_line_width * 100) / parent_value" + } + } + } + } + }, + "meshfix": { "label": "Fixes", "visible": true, "icon": "category_fixes", "settings": { + "meshfix_union_all": { + "label": "Union Overlapping Volumes", + "description": "Ignore the internal geometry arising from overlapping volumes and print the volumes as one. This may cause internal cavaties to disappear.", + "type": "boolean", + "default": true, + "visible": false + }, + "meshfix_union_all_remove_holes": { + "label": "Remove All Holes", + "description": "Remove the holes in each layer and keep only the outside shape. This will ignore any invisible internal geometry. However, it also ignores layer holes which can be viewed from above or below.", + "type": "boolean", + "default": false, + "visible": false + }, + "meshfix_extensive_stitching": { + "label": "Extensive Stitching", + "description": "Extensive stitching tries to stitch up open holes in the mesh by closing the hole with touching polygons. This option can introduce a lot of processing time.", + "type": "boolean", + "default": false, + "visible": false + }, + "meshfix_keep_open_polygons": { + "label": "Keep Disconnected Faces", + "description": "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when all else doesn produce proper GCode.", + "type": "boolean", + "default": false, + "visible": false + } + } + }, + "blackmagic": { + "label": "Special Modes", + "visible": true, + "icon": "category_blackmagic", + "settings": { + "magic_mesh_surface_mode": { + "label": "Surface Mode", + "description": "Print the surface instead of the volume. No infill, no top/bottom skin, just a single wall of which the middle coincides with the surface of the mesh.", + "type": "boolean", + "default": false, + "visible": false + }, "magic_spiralize": { - "label": "Spiralize the Outer Contour", + "label": "Spiralize Outer Contour", "description": "Spiralize smooths out the Z move of the outer edge. This will create a steady Z increase over the whole print. This feature turns a solid object into a single walled print with a solid bottom. This feature used to be called ‘Joris’ in older versions.", "type": "boolean", "default": false, @@ -1056,7 +1602,11 @@ "type": "float", "default": 5.0, "visible": false, - "inherit":true + "inherit":true, + "active_if": { + "setting": "wireframe_enabled", + "value": true + } }, "wireframe_printspeed_up": { "label": "Wire Upward Printing Speed", @@ -1065,7 +1615,11 @@ "type": "float", "default": 5.0, "visible": false, - "inherit":true + "inherit":true, + "active_if": { + "setting": "wireframe_enabled", + "value": true + } }, "wireframe_printspeed_down": { "label": "Wire Downward Printing Speed", @@ -1074,7 +1628,11 @@ "type": "float", "default": 5.0, "visible": false, - "inherit":true + "inherit":true, + "active_if": { + "setting": "wireframe_enabled", + "value": true + } }, "wireframe_printspeed_flat": { "label": "Wire Horizontal Printing Speed", @@ -1083,7 +1641,11 @@ "type": "float", "default": 5.0, "visible": false, - "inherit":true + "inherit":true, + "active_if": { + "setting": "wireframe_enabled", + "value": true + } } } }, @@ -1315,5 +1877,3 @@ } } } - - diff --git a/resources/settings/ultimaker2.json b/resources/settings/ultimaker2.json index d6fc97803a..6cee1d8eb4 100644 --- a/resources/settings/ultimaker2.json +++ b/resources/settings/ultimaker2.json @@ -38,7 +38,20 @@ "categories": { "material": { - "visible": false + "settings": { + "material_print_temperature": { + "visible": false + }, + "material_bed_temperature": { + "visible": false + }, + "material_diameter": { + "visible": false + }, + "material_flow": { + "visible": false + } + } } } } diff --git a/resources/settings/ultimaker_original.json b/resources/settings/ultimaker_original.json index 07be53e46c..360bbbe6b6 100644 --- a/resources/settings/ultimaker_original.json +++ b/resources/settings/ultimaker_original.json @@ -19,6 +19,23 @@ "machine_nozzle_gantry_distance": { "default": 55 }, "machine_nozzle_offset_x_1": { "default": 18.0 }, "machine_nozzle_offset_y_1": { "default": 0.0 }, - "machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" } + "machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" }, + + "machine_start_gcode": { + "default": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..." + }, + "machine_end_gcode": { + "default": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;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" + } + }, + + "categories": { + "material": { + "settings": { + "material_bed_temperature": { + "visible": false + } + } + } } } diff --git a/resources/settings/ultimaker_original_plus.json b/resources/settings/ultimaker_original_plus.json index d0b04879db..9e5cf6370d 100644 --- a/resources/settings/ultimaker_original_plus.json +++ b/resources/settings/ultimaker_original_plus.json @@ -1,6 +1,6 @@ { "id": "ultimaker_original_plus", - "name": "Ultimaker Original Plus", + "name": "Ultimaker Original+", "icon": "icon_ultimaker.png", "platform": "ultimaker2_platform.obj", "platform_texture": "UltimakerPlusbackplate.png", diff --git a/resources/themes/cura/icons/category_blackmagic.svg b/resources/themes/cura/icons/category_blackmagic.svg new file mode 100644 index 0000000000..a16a303908 --- /dev/null +++ b/resources/themes/cura/icons/category_blackmagic.svg @@ -0,0 +1,149 @@ + + + +image/svg+xml? + \ No newline at end of file diff --git a/resources/themes/cura/icons/category_quality.svg b/resources/themes/cura/icons/category_layer_height.svg similarity index 100% rename from resources/themes/cura/icons/category_quality.svg rename to resources/themes/cura/icons/category_layer_height.svg diff --git a/resources/themes/cura/icons/category_shell.svg b/resources/themes/cura/icons/category_shell.svg new file mode 100644 index 0000000000..9fa439878d --- /dev/null +++ b/resources/themes/cura/icons/category_shell.svg @@ -0,0 +1,3384 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/resources/themes/cura/icons/category_travel.svg b/resources/themes/cura/icons/category_travel.svg new file mode 100644 index 0000000000..cb6412d769 --- /dev/null +++ b/resources/themes/cura/icons/category_travel.svg @@ -0,0 +1,3422 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/resources/themes/cura/styles.qml b/resources/themes/cura/styles.qml index d17560d976..d172fdb6d0 100644 --- a/resources/themes/cura/styles.qml +++ b/resources/themes/cura/styles.qml @@ -35,46 +35,42 @@ QtObject { } } - property Component tool_button: Component { + property Component open_file_button: Component { ButtonStyle { - background: UM.AngledCornerRectangle { - property bool down: control.pressed || (control.checkable && control.checked); - + background: Item { implicitWidth: UM.Theme.sizes.button.width; implicitHeight: UM.Theme.sizes.button.height; - color: { - if(!control.enabled) { - return UM.Theme.colors.button_disabled; - } else if(control.checkable && control.checked && control.hovered) { - return UM.Theme.colors.button_active_hover; - } else if(control.pressed || (control.checkable && control.checked)) { - return UM.Theme.colors.button_active; - } else if(control.hovered) { - return UM.Theme.colors.button_hover; - } else { - return UM.Theme.colors.button; - } - } - Behavior on color { ColorAnimation { duration: 50; } } - cornerSize: UM.Theme.sizes.default_margin.width; Rectangle { - anchors.bottom: parent.top; - + anchors.bottom: parent.verticalCenter; width: parent.width; - height: control.hovered ? label.height : 0; - Behavior on height { NumberAnimation { duration: 75; } } + height: control.hovered ? parent.height / 2 + label.height : 0; + Behavior on height { NumberAnimation { duration: 100; } } opacity: control.hovered ? 1.0 : 0.0; - Behavior on opacity { NumberAnimation { duration: 75; } } + Behavior on opacity { NumberAnimation { duration: 100; } } Label { - id: label + id: label; anchors.horizontalCenter: parent.horizontalCenter; - text: control.text; + text: control.text.replace("&", ""); font: UM.Theme.fonts.button_tooltip; + color: UM.Theme.colors.button_tooltip_text; } } + + UM.AngledCornerRectangle { + anchors.fill: parent; + color: { + if(control.hovered) { + return UM.Theme.colors.button_active_hover; + } else { + return UM.Theme.colors.button_active; + } + } + Behavior on color { ColorAnimation { duration: 50; } } + cornerSize: UM.Theme.sizes.default_margin.width; + } } label: Item { @@ -91,6 +87,110 @@ QtObject { } } + property Component tool_button: Component { + ButtonStyle { + background: Item { + implicitWidth: UM.Theme.sizes.button.width; + implicitHeight: UM.Theme.sizes.button.height; + + Rectangle { + anchors.bottom: parent.verticalCenter; + + width: parent.width; + height: control.hovered ? parent.height / 2 + label.height : 0; + Behavior on height { NumberAnimation { duration: 100; } } + + opacity: control.hovered ? 1.0 : 0.0; + Behavior on opacity { NumberAnimation { duration: 100; } } + + Rectangle { + anchors.horizontalCenter: parent.horizontalCenter; + width: childrenRect.width; + height: childrenRect.height; + + Label { + id: label + text: control.text.replace("&", ""); + font: UM.Theme.fonts.button_tooltip; + color: UM.Theme.colors.button_tooltip_text; + } + } + } + + UM.AngledCornerRectangle { + id: buttonFace; + + anchors.fill: parent; + + property bool down: control.pressed || (control.checkable && control.checked); + + color: { + if(!control.enabled) { + return UM.Theme.colors.button_disabled; + } else if(control.checkable && control.checked && control.hovered) { + return UM.Theme.colors.button_active_hover; + } else if(control.pressed || (control.checkable && control.checked)) { + return UM.Theme.colors.button_active; + } else if(control.hovered) { + return UM.Theme.colors.button_hover; + } else { + return UM.Theme.colors.button; + } + } + Behavior on color { ColorAnimation { duration: 50; } } + cornerSize: UM.Theme.sizes.default_margin.width; + } + } + + label: Item { + Image { + anchors.centerIn: parent; + + source: control.iconSource; + width: UM.Theme.sizes.button_icon.width; + height: UM.Theme.sizes.button_icon.height; + + sourceSize: UM.Theme.sizes.button_icon; + } + } + } + } + + + property Component progressbar: Component{ + ProgressBarStyle { + background: UM.AngledCornerRectangle { + cornerSize: UM.Theme.sizes.progressbar_control.height + implicitWidth: UM.Theme.sizes.progressbar.width + implicitHeight: UM.Theme.sizes.progressbar.height + color: UM.Theme.colors.progressbar_background + } + progress: UM.AngledCornerRectangle { + cornerSize: UM.Theme.sizes.progressbar_control.height + color: control.indeterminate ? "transparent" : UM.Theme.colors.progressbar_control + + UM.AngledCornerRectangle { + cornerSize: UM.Theme.sizes.progressbar_control.height + color: UM.Theme.colors.progressbar_control + width: UM.Theme.sizes.progressbar_control.width + height: UM.Theme.sizes.progressbar_control.height + visible: control.indeterminate + + SequentialAnimation on x { + id: xAnim + property int animEndPoint: UM.Theme.sizes.progressbar.width - UM.Theme.sizes.progressbar_control.width + running: control.indeterminate + loops: Animation.Infinite + NumberAnimation { from: 0; to: xAnim.animEndPoint; duration: 2000;} + NumberAnimation { from: xAnim.animEndPoint; to: 0; duration: 2000;} + } + } + } + } + } + + + property Component sidebar_category: Component { ButtonStyle { background: UM.AngledCornerRectangle { @@ -121,6 +221,8 @@ QtObject { Image { anchors.verticalCenter: parent.verticalCenter; source: control.iconSource; + width: UM.Theme.sizes.section_icon.width; + height: UM.Theme.sizes.section_icon.height; } Label { @@ -243,4 +345,32 @@ QtObject { } } } + + property Component text_field: Component { + TextFieldStyle { + textColor: UM.Theme.colors.setting_control_text; + font: UM.Theme.fonts.default; + + background: Rectangle + { + implicitHeight: control.height; + implicitWidth: control.width; + + border.width: 1; + border.color: UM.Theme.colors.setting_control_border; + + color: UM.Theme.colors.setting_validation_ok; + + Label { + anchors.right: parent.right; + anchors.rightMargin: UM.Theme.sizes.setting_unit_margin.width; + anchors.verticalCenter: parent.verticalCenter; + + text: control.unit ? control.unit : "" + color: UM.Theme.colors.setting_unit; + font: UM.Theme.fonts.default; + } + } + } + } } diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 2ea7f138f6..88a236d7ce 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -27,6 +27,10 @@ "capitalize": true, "family": "Roboto" }, + "sidebar_save_to": { + "size": 1.0, + "family": "Roboto" + }, "timeslider_time": { "size": 1.0, "bold": true, @@ -44,23 +48,26 @@ }, "colors": { + "sidebar": [255, 255, 255, 255], + "primary": [12, 169, 227, 255], "primary_hover": [34, 150, 190, 255], "primary_text": [255, 255, 255, 255], "border": [205, 202, 201, 255], "secondary": [205, 202, 201, 255], - "text": [174, 174, 174, 255], - "text_inactive": [205, 202, 201, 255], + "text": [140, 144, 154, 255], + "text_inactive": [174, 174, 174, 255], "text_hover": [35, 35, 35, 255], "text_pressed": [12, 169, 227, 255], - "button": [205, 202, 201, 255], - "button_hover": [174, 174, 174, 255], + "button": [160, 163, 171, 255], + "button_hover": [140, 144, 154, 255], "button_active": [12, 169, 227, 255], - "button_active_hover": [34, 150, 190, 255], + "button_active_hover": [34, 150, 199, 255], "button_text": [255, 255, 255, 255], "button_disabled": [245, 245, 245, 255], + "button_tooltip_text": [35, 35, 35, 255], "scrollbar_background": [245, 245, 245, 255], "scrollbar_handle": [205, 202, 201, 255], @@ -74,7 +81,7 @@ "setting_category_active_hover": [34, 150, 190, 255], "setting_category_text": [255, 255, 255, 255], - "setting_label": [174, 174, 174, 255], + "setting_label": [140, 144, 154, 255], "setting_control": [255, 255, 255, 255], "setting_control_highlight": [245, 245, 245, 255], "setting_control_border": [174, 174, 174, 255], @@ -85,6 +92,9 @@ "setting_validation_warning": [255, 186, 15, 255], "setting_validation_ok": [255, 255, 255, 255], + "progressbar_background": [245, 245, 245, 255], + "progressbar_control": [12, 169, 227, 255], + "slider_groove": [245, 245, 245, 255], "slider_groove_border": [205, 202, 201, 255], "slider_groove_fill": [205, 202, 201, 255], @@ -95,19 +105,24 @@ "checkbox_hover": [245, 245, 245, 255], "checkbox_border": [174, 174, 174, 255], "checkbox_mark": [35, 35, 35, 255], - "checkbox_text": [174, 174, 174, 255], + "checkbox_text": [140, 144, 154, 255], "tooltip": [255, 225, 146, 255], - "save_button": [255, 255, 255, 255], "save_button_border": [205, 202, 201, 255], "save_button_inactive": [205, 202, 201, 255], "save_button_active": [12, 159, 227, 255], "save_button_active_hover": [34, 150, 190, 255], - "save_button_text": [35, 35, 35, 255], + "save_button_safe_to_text": [255, 255, 255, 255], + "save_button_estimated_text": [140, 144, 154, 255], + "save_button_estimated_text_background": [255, 255, 255, 255], + "save_button_printtime_text": [12, 169, 227, 255], + "save_button_background": [249, 249, 249, 255], "message": [205, 202, 201, 255], - "message_text": [35, 35, 35, 255] + "message_text": [35, 35, 35, 255], + + "tool_panel_background": [255, 255, 255, 255] }, "sizes": { @@ -128,7 +143,11 @@ "setting_unit_margin": [0.5, 0.5], "button": [4.25, 4.25], - "button_icon": [3.57, 3.57], + "button_icon": [2.9, 2.9], + + "progressbar": [26.0, 0.5], + "progressbar_control": [8.0, 0.5], + "progressbar_padding": [0.0, 1.0], "scrollbar": [0.5, 0.5], @@ -141,7 +160,10 @@ "tooltip_margins": [1.0, 1.0], "save_button_border": [0.06, 0.06], + "save_button_text_margin": [0.6, 0.6], + "save_button_slicing_bar": [0.0, 2.2], "save_button_label_margin": [0.5, 0.5], + "save_button_save_to_button": [0.3, 2.7], "message": [30.0, 5.0], "message_close": [1.25, 1.25] diff --git a/setup.py b/setup.py index cfd59c47d2..43074ab177 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ def copytree(src, dst, symlinks=False, ignore=None): else: shutil.copy2(s, d) -includes = ["sip", "ctypes", "UM", "PyQt5.QtNetwork", "PyQt5._QOpenGLFunctions_2_0", "serial", "Arcus", "google", "google.protobuf", "google.protobuf.descriptor", "xml.etree", "xml.etree.ElementTree", "src"] +includes = ["sip", "ctypes", "UM", "PyQt5.QtNetwork", "PyQt5._QOpenGLFunctions_2_0", "serial", "Arcus", "google", "google.protobuf", "google.protobuf.descriptor", "xml.etree", "xml.etree.ElementTree", "cura"] # Include all the UM modules in the includes. As py2exe fails to properly find all the dependencies due to the plugin architecture. for dirpath, dirnames, filenames in os.walk(os.path.dirname(UM.__file__)): if "__" in dirpath: @@ -41,20 +41,20 @@ print("Removing previous distribution package") shutil.rmtree("dist", True) setup(name="Cura", - version="2.0", + version="15.05.95", author="Ultimaker", author_email="d.braam@ultimaker.com", url="http://software.ultimaker.com/", license="GNU AFFERO GENERAL PUBLIC LICENSE (AGPL)", scripts=["cura_app.py"], - #windows=[{"script": "printer.py", "dest_name": "Cura"}], - console=[{"script": "cura_app.py"}], + windows=[{"script": "cura_app.py", "dest_name": "Cura", "icon_resources": [(1, "icons/cura.ico")]}], + #console=[{"script": "cura_app.py"}], options={"py2exe": {"skip_archive": False, "includes": includes}}) print("Coping Cura plugins.") -shutil.copytree(os.path.dirname(UM.__file__) + "/../plugins", "dist/plugins") +shutil.copytree(os.path.dirname(UM.__file__) + "/../plugins", "dist/plugins", ignore = shutil.ignore_patterns("ConsoleLogger", "OBJWriter", "MLPWriter", "MLPReader")) for path in os.listdir("plugins"): - shutil.copytree("plugins/" + path, "dist/plugins/" + path) + shutil.copytree("plugins/" + path, "dist/plugins/" + path) print("Coping resources.") shutil.copytree(os.path.dirname(UM.__file__) + "/../resources", "dist/resources") copytree("resources", "dist/resources") @@ -70,3 +70,7 @@ for site_package in site.getsitepackages(): shutil.copytree(os.path.join(qt_origin_path, "qml/QtQuick.2"), "dist/qml/QtQuick.2") print("Coping PyQt5 svg library from: %s" % qt_origin_path) shutil.copy(os.path.join(qt_origin_path, "Qt5Svg.dll"), "dist/Qt5Svg.dll") + print("Copying Angle libraries from %s" % qt_origin_path) + shutil.copy(os.path.join(qt_origin_path, "libEGL.dll"), "dist/libEGL.dll") + shutil.copy(os.path.join(qt_origin_path, "libGLESv2.dll"), "dist/libGLESv2.dll") +os.rename("dist/cura_app.exe", "dist/Cura.exe") \ No newline at end of file