173
CHANGES
Normal file
@ -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.
|
@ -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")
|
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
|
# Extract Strings
|
||||||
add_custom_target(extract-messages ${URANIUM_SCRIPTS_DIR}/extract-messages ${CMAKE_SOURCE_DIR} cura)
|
add_custom_target(extract-messages ${URANIUM_SCRIPTS_DIR}/extract-messages ${CMAKE_SOURCE_DIR} cura)
|
||||||
|
|
||||||
@ -27,6 +27,12 @@ if(${URANIUM_SCRIPTS_DIR})
|
|||||||
set(languages
|
set(languages
|
||||||
en
|
en
|
||||||
x-test
|
x-test
|
||||||
|
ru
|
||||||
|
fr
|
||||||
|
de
|
||||||
|
it
|
||||||
|
es
|
||||||
|
fi
|
||||||
)
|
)
|
||||||
foreach(lang ${languages})
|
foreach(lang ${languages})
|
||||||
file(GLOB po_files resources/i18n/${lang}/*.po)
|
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")
|
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 resources DESTINATION ${CMAKE_INSTALL_DATADIR}/cura)
|
||||||
install(DIRECTORY plugins DESTINATION ${CMAKE_INSTALL_LIBDIR}/cura)
|
install(DIRECTORY plugins DESTINATION ${CMAKE_INSTALL_LIBDIR}/cura)
|
||||||
file(GLOB cura_SRCS cura/*)
|
install(DIRECTORY cura DESTINATION ${PYTHON_SITE_PACKAGES_DIR})
|
||||||
install(FILES ${cura_SRCS} DESTINATION ${PYTHON_SITE_PACKAGES_DIR}/cura)
|
|
||||||
install(FILES cura_app.py DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install(FILES cura_app.py DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
|
16
README.md
@ -1,7 +1,9 @@
|
|||||||
Cura
|
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
|
Dependencies
|
||||||
------------
|
------------
|
||||||
@ -12,3 +14,15 @@ Dependencies
|
|||||||
This will be needed at runtime to perform the actual slicing.
|
This will be needed at runtime to perform the actual slicing.
|
||||||
* PySerial
|
* PySerial
|
||||||
Only required for USB printing support.
|
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)
|
||||||
|
@ -42,6 +42,9 @@ class BuildVolume(SceneNode):
|
|||||||
def setDepth(self, depth):
|
def setDepth(self, depth):
|
||||||
self._depth = depth
|
self._depth = depth
|
||||||
|
|
||||||
|
def getDisallowedAreas(self):
|
||||||
|
return self._disallowed_areas
|
||||||
|
|
||||||
def setDisallowedAreas(self, areas):
|
def setDisallowedAreas(self, areas):
|
||||||
self._disallowed_areas = areas
|
self._disallowed_areas = areas
|
||||||
|
|
||||||
@ -62,7 +65,7 @@ class BuildVolume(SceneNode):
|
|||||||
self._grid_material.setUniformValue("u_gridColor1", Color(205, 202, 201, 255))
|
self._grid_material.setUniformValue("u_gridColor1", Color(205, 202, 201, 255))
|
||||||
|
|
||||||
renderer.queueNode(self, material = self._material, mode = Renderer.RenderLines)
|
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:
|
if self._disallowed_area_mesh:
|
||||||
renderer.queueNode(self, mesh = self._disallowed_area_mesh, material = self._material)
|
renderer.queueNode(self, mesh = self._disallowed_area_mesh, material = self._material)
|
||||||
return True
|
return True
|
||||||
@ -99,29 +102,53 @@ class BuildVolume(SceneNode):
|
|||||||
|
|
||||||
mb = MeshBuilder()
|
mb = MeshBuilder()
|
||||||
mb.addQuad(
|
mb.addQuad(
|
||||||
Vector(minW, minH, maxD),
|
Vector(minW, minH, minD),
|
||||||
Vector(maxW, minH, maxD),
|
|
||||||
Vector(maxW, minH, minD),
|
Vector(maxW, minH, minD),
|
||||||
Vector(minW, minH, minD)
|
Vector(maxW, minH, maxD),
|
||||||
|
Vector(minW, minH, maxD)
|
||||||
)
|
)
|
||||||
self._grid_mesh = mb.getData()
|
self._grid_mesh = mb.getData()
|
||||||
for n in range(0, 6):
|
for n in range(0, 6):
|
||||||
v = self._grid_mesh.getVertex(n)
|
v = self._grid_mesh.getVertex(n)
|
||||||
self._grid_mesh.setVertexUVCoordinates(n, v[0], v[2])
|
self._grid_mesh.setVertexUVCoordinates(n, v[0], v[2])
|
||||||
|
|
||||||
|
disallowed_area_size = 0
|
||||||
if self._disallowed_areas:
|
if self._disallowed_areas:
|
||||||
mb = MeshBuilder()
|
mb = MeshBuilder()
|
||||||
for area in self._disallowed_areas:
|
for polygon in self._disallowed_areas:
|
||||||
|
points = polygon.getPoints()
|
||||||
mb.addQuad(
|
mb.addQuad(
|
||||||
area[0],
|
Vector(points[0, 0], 0.1, points[0, 1]),
|
||||||
area[1],
|
Vector(points[1, 0], 0.1, points[1, 1]),
|
||||||
area[2],
|
Vector(points[2, 0], 0.1, points[2, 1]),
|
||||||
area[3],
|
Vector(points[3, 0], 0.1, points[3, 1]),
|
||||||
color = Color(174, 174, 174, 255)
|
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()
|
self._disallowed_area_mesh = mb.getData()
|
||||||
else:
|
else:
|
||||||
self._disallowed_area_mesh = None
|
self._disallowed_area_mesh = None
|
||||||
|
|
||||||
self._aabb = AxisAlignedBox(minimum = Vector(minW, minH - 1.0, minD), maximum = Vector(maxW, maxH, maxD))
|
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
|
||||||
|
@ -48,6 +48,9 @@ class ConvexHullNode(SceneNode):
|
|||||||
|
|
||||||
self.setMeshData(mesh)
|
self.setMeshData(mesh)
|
||||||
|
|
||||||
|
def getWatchedNode(self):
|
||||||
|
return self._node
|
||||||
|
|
||||||
def render(self, renderer):
|
def render(self, renderer):
|
||||||
if not self._material:
|
if not self._material:
|
||||||
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag"))
|
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag"))
|
||||||
|
27
cura/CuraActions.py
Normal file
@ -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)
|
@ -17,6 +17,8 @@ from UM.Logger import Logger
|
|||||||
from UM.Preferences import Preferences
|
from UM.Preferences import Preferences
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.PluginRegistry import PluginRegistry
|
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.BoxRenderer import BoxRenderer
|
||||||
from UM.Scene.Selection import Selection
|
from UM.Scene.Selection import Selection
|
||||||
@ -32,9 +34,10 @@ from . import PlatformPhysics
|
|||||||
from . import BuildVolume
|
from . import BuildVolume
|
||||||
from . import CameraAnimation
|
from . import CameraAnimation
|
||||||
from . import PrintInformation
|
from . import PrintInformation
|
||||||
|
from . import CuraActions
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty
|
||||||
from PyQt5.QtGui import QColor
|
from PyQt5.QtGui import QColor, QIcon
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
@ -50,6 +53,8 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
super().__init__(name = "cura", version = "master")
|
super().__init__(name = "cura", version = "master")
|
||||||
|
|
||||||
|
self.setWindowIcon(QIcon(Resources.getPath(Resources.ImagesLocation, "cura-icon.png")))
|
||||||
|
|
||||||
self.setRequiredPlugins([
|
self.setRequiredPlugins([
|
||||||
"CuraEngineBackend",
|
"CuraEngineBackend",
|
||||||
"MeshView",
|
"MeshView",
|
||||||
@ -66,11 +71,24 @@ class CuraApplication(QtApplication):
|
|||||||
self._output_devices = {}
|
self._output_devices = {}
|
||||||
self._print_information = None
|
self._print_information = None
|
||||||
self._i18n_catalog = None
|
self._i18n_catalog = None
|
||||||
|
self._previous_active_tool = None
|
||||||
|
|
||||||
self.activeMachineChanged.connect(self._onActiveMachineChanged)
|
self.activeMachineChanged.connect(self._onActiveMachineChanged)
|
||||||
|
|
||||||
Preferences.getInstance().addPreference("cura/active_machine", "")
|
Preferences.getInstance().addPreference("cura/active_machine", "")
|
||||||
Preferences.getInstance().addPreference("cura/active_mode", "simple")
|
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)
|
## Handle loading of all plugin types (and the backend explicitly)
|
||||||
# \sa PluginRegistery
|
# \sa PluginRegistery
|
||||||
@ -162,6 +180,7 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
for file in self.getCommandLineOption("file", []):
|
for file in self.getCommandLineOption("file", []):
|
||||||
job = ReadMeshJob(os.path.abspath(file))
|
job = ReadMeshJob(os.path.abspath(file))
|
||||||
|
job.finished.connect(self._onFileLoaded)
|
||||||
job.start()
|
job.start()
|
||||||
|
|
||||||
self.exec_()
|
self.exec_()
|
||||||
@ -170,10 +189,16 @@ class CuraApplication(QtApplication):
|
|||||||
engine.rootContext().setContextProperty("Printer", self)
|
engine.rootContext().setContextProperty("Printer", self)
|
||||||
self._print_information = PrintInformation.PrintInformation()
|
self._print_information = PrintInformation.PrintInformation()
|
||||||
engine.rootContext().setContextProperty("PrintInformation", self._print_information)
|
engine.rootContext().setContextProperty("PrintInformation", self._print_information)
|
||||||
|
self._cura_actions = CuraActions.CuraActions(self)
|
||||||
|
engine.rootContext().setContextProperty("CuraActions", self._cura_actions)
|
||||||
|
|
||||||
def onSelectionChanged(self):
|
def onSelectionChanged(self):
|
||||||
if Selection.hasSelection():
|
if Selection.hasSelection():
|
||||||
if not self.getController().getActiveTool():
|
if not self.getController().getActiveTool():
|
||||||
|
if self._previous_active_tool:
|
||||||
|
self.getController().setActiveTool(self._previous_active_tool)
|
||||||
|
self._previous_active_tool = None
|
||||||
|
else:
|
||||||
self.getController().setActiveTool("TranslateTool")
|
self.getController().setActiveTool("TranslateTool")
|
||||||
|
|
||||||
self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin())
|
self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin())
|
||||||
@ -181,7 +206,10 @@ class CuraApplication(QtApplication):
|
|||||||
self._camera_animation.start()
|
self._camera_animation.start()
|
||||||
else:
|
else:
|
||||||
if self.getController().getActiveTool():
|
if self.getController().getActiveTool():
|
||||||
|
self._previous_active_tool = self.getController().getActiveTool().getPluginId()
|
||||||
self.getController().setActiveTool(None)
|
self.getController().setActiveTool(None)
|
||||||
|
else:
|
||||||
|
self._previous_active_tool = None
|
||||||
|
|
||||||
requestAddPrinter = pyqtSignal()
|
requestAddPrinter = pyqtSignal()
|
||||||
|
|
||||||
@ -190,6 +218,9 @@ class CuraApplication(QtApplication):
|
|||||||
def deleteObject(self, object_id):
|
def deleteObject(self, object_id):
|
||||||
object = self.getController().getScene().findObject(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:
|
if object:
|
||||||
op = RemoveSceneNodeOperation(object)
|
op = RemoveSceneNodeOperation(object)
|
||||||
op.push()
|
op.push()
|
||||||
@ -199,6 +230,9 @@ class CuraApplication(QtApplication):
|
|||||||
def multiplyObject(self, object_id, count):
|
def multiplyObject(self, object_id, count):
|
||||||
node = self.getController().getScene().findObject(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:
|
if node:
|
||||||
op = GroupedOperation()
|
op = GroupedOperation()
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
@ -215,6 +249,9 @@ class CuraApplication(QtApplication):
|
|||||||
def centerObject(self, object_id):
|
def centerObject(self, object_id):
|
||||||
node = self.getController().getScene().findObject(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:
|
if node:
|
||||||
op = SetTransformOperation(node, Vector())
|
op = SetTransformOperation(node, Vector())
|
||||||
op.push()
|
op.push()
|
||||||
@ -304,6 +341,25 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
return log
|
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()
|
outputDevicesChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtProperty("QVariantMap", notify = outputDevicesChanged)
|
@pyqtProperty("QVariantMap", notify = outputDevicesChanged)
|
||||||
@ -385,7 +441,7 @@ class CuraApplication(QtApplication):
|
|||||||
self.addOutputDevice(drive, {
|
self.addOutputDevice(drive, {
|
||||||
"id": drive,
|
"id": drive,
|
||||||
"function": self._writeToSD,
|
"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",
|
"icon": "save_sd",
|
||||||
"priority": 1
|
"priority": 1
|
||||||
})
|
})
|
||||||
@ -411,21 +467,13 @@ class CuraApplication(QtApplication):
|
|||||||
disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas")
|
disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas")
|
||||||
areas = []
|
areas = []
|
||||||
if disallowed_areas:
|
if disallowed_areas:
|
||||||
|
|
||||||
for area in disallowed_areas:
|
for area in disallowed_areas:
|
||||||
polygon = []
|
areas.append(Polygon(numpy.array(area, numpy.float32)))
|
||||||
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)
|
|
||||||
self._volume.setDisallowedAreas(areas)
|
self._volume.setDisallowedAreas(areas)
|
||||||
|
|
||||||
self._volume.rebuild()
|
self._volume.rebuild()
|
||||||
|
|
||||||
if self.getController().getTool("ScaleTool"):
|
|
||||||
self.getController().getTool("ScaleTool").setMaximumBounds(self._volume.getBoundingBox())
|
|
||||||
|
|
||||||
offset = machine.getSettingValueByKey("machine_platform_offset")
|
offset = machine.getSettingValueByKey("machine_platform_offset")
|
||||||
if offset:
|
if offset:
|
||||||
self._platform.setPosition(Vector(offset[0], offset[1], offset[2]))
|
self._platform.setPosition(Vector(offset[0], offset[1], offset[2]))
|
||||||
@ -438,7 +486,7 @@ class CuraApplication(QtApplication):
|
|||||||
"eject",
|
"eject",
|
||||||
self._i18n_catalog.i18nc("Message action", "Eject"),
|
self._i18n_catalog.i18nc("Message action", "Eject"),
|
||||||
"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._sdcard = job._sdcard
|
||||||
message.actionTriggered.connect(self._onMessageActionTriggered)
|
message.actionTriggered.connect(self._onMessageActionTriggered)
|
||||||
@ -447,3 +495,34 @@ class CuraApplication(QtApplication):
|
|||||||
def _onMessageActionTriggered(self, message, action):
|
def _onMessageActionTriggered(self, message, action):
|
||||||
if action == "eject":
|
if action == "eject":
|
||||||
self.getStorageDevice("LocalFileStorage").ejectRemovableDrive(message._sdcard)
|
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()
|
||||||
|
@ -11,6 +11,7 @@ from UM.Math.Float import Float
|
|||||||
from UM.Math.Vector import Vector
|
from UM.Math.Vector import Vector
|
||||||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
from UM.Scene.Selection import Selection
|
||||||
|
|
||||||
from . import PlatformPhysicsOperation
|
from . import PlatformPhysicsOperation
|
||||||
from . import ConvexHullJob
|
from . import ConvexHullJob
|
||||||
@ -23,8 +24,12 @@ class PlatformPhysics:
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self._controller = controller
|
self._controller = controller
|
||||||
self._controller.getScene().sceneChanged.connect(self._onSceneChanged)
|
self._controller.getScene().sceneChanged.connect(self._onSceneChanged)
|
||||||
|
self._controller.toolOperationStarted.connect(self._onToolOperationStarted)
|
||||||
|
self._controller.toolOperationStopped.connect(self._onToolOperationStopped)
|
||||||
self._build_volume = volume
|
self._build_volume = volume
|
||||||
|
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
self._change_timer = QTimer()
|
self._change_timer = QTimer()
|
||||||
self._change_timer.setInterval(100)
|
self._change_timer.setInterval(100)
|
||||||
self._change_timer.setSingleShot(True)
|
self._change_timer.setSingleShot(True)
|
||||||
@ -34,6 +39,9 @@ class PlatformPhysics:
|
|||||||
self._change_timer.start()
|
self._change_timer.start()
|
||||||
|
|
||||||
def _onChangeTimerFinished(self):
|
def _onChangeTimerFinished(self):
|
||||||
|
if not self._enabled:
|
||||||
|
return
|
||||||
|
|
||||||
root = self._controller.getScene().getRoot()
|
root = self._controller.getScene().getRoot()
|
||||||
for node in BreadthFirstIterator(root):
|
for node in BreadthFirstIterator(root):
|
||||||
if node is root or type(node) is not SceneNode:
|
if node is root or type(node) is not SceneNode:
|
||||||
@ -41,6 +49,7 @@ class PlatformPhysics:
|
|||||||
|
|
||||||
bbox = node.getBoundingBox()
|
bbox = node.getBoundingBox()
|
||||||
if not bbox or not bbox.isValid():
|
if not bbox or not bbox.isValid():
|
||||||
|
self._change_timer.start()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Mark the node as outside the build volume if the bounding box test fails.
|
# 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 = ConvexHullJob.ConvexHullJob(node)
|
||||||
job.start()
|
job.start()
|
||||||
node._convex_hull_job = job
|
node._convex_hull_job = job
|
||||||
|
elif Selection.isSelected(node):
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
# Check for collisions between convex hulls
|
# Check for collisions between convex hulls
|
||||||
for other_node in BreadthFirstIterator(root):
|
for other_node in BreadthFirstIterator(root):
|
||||||
@ -80,13 +91,25 @@ class PlatformPhysics:
|
|||||||
if overlap is None:
|
if overlap is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
move_vector.setX(-overlap[0])
|
move_vector.setX(overlap[0] * 1.1)
|
||||||
move_vector.setZ(-overlap[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():
|
if move_vector != Vector():
|
||||||
op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector)
|
op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector)
|
||||||
op.push()
|
op.push()
|
||||||
|
|
||||||
if node.getBoundingBox().intersectsBox(self._build_volume.getBoundingBox()) == AxisAlignedBox.IntersectionResult.FullIntersection:
|
def _onToolOperationStarted(self, tool):
|
||||||
op = ScaleToBoundsOperation(node, self._build_volume.getBoundingBox())
|
self._enabled = False
|
||||||
op.push()
|
|
||||||
|
def _onToolOperationStopped(self, tool):
|
||||||
|
self._enabled = True
|
||||||
|
self._onChangeTimerFinished()
|
||||||
|
@ -38,6 +38,8 @@ class PrintInformation(QObject):
|
|||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self._enabled = False
|
||||||
|
|
||||||
self._minimum_print_time = Duration(None, self)
|
self._minimum_print_time = Duration(None, self)
|
||||||
self._current_print_time = Duration(None, self)
|
self._current_print_time = Duration(None, self)
|
||||||
self._maximum_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._time_quality_changed_timer.timeout.connect(self._updateTimeQualitySettings)
|
||||||
|
|
||||||
self._interpolation_settings = {
|
self._interpolation_settings = {
|
||||||
"layer_height": { "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" }
|
"fill_sparse_density": { "minimum": "low", "maximum": "high", "curve": "linear", "precision": 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
self._low_quality_settings = None
|
self._low_quality_settings = None
|
||||||
@ -103,6 +105,21 @@ class PrintInformation(QObject):
|
|||||||
def timeQualityValue(self):
|
def timeQualityValue(self):
|
||||||
return self._time_quality_value
|
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)
|
@pyqtSlot(int)
|
||||||
def setTimeQualityValue(self, value):
|
def setTimeQualityValue(self, value):
|
||||||
if value != self._time_quality_value:
|
if value != self._time_quality_value:
|
||||||
@ -132,7 +149,10 @@ class PrintInformation(QObject):
|
|||||||
self._material_amount = round(amount / 10) / 100
|
self._material_amount = round(amount / 10) / 100
|
||||||
self.materialAmountChanged.emit()
|
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._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)
|
self._backend.slice(settings = self._low_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False)
|
||||||
else:
|
else:
|
||||||
@ -166,7 +186,7 @@ class PrintInformation(QObject):
|
|||||||
self._slice_reason = self.SliceReason.ActiveMachineChanged
|
self._slice_reason = self.SliceReason.ActiveMachineChanged
|
||||||
|
|
||||||
def _updateTimeQualitySettings(self):
|
def _updateTimeQualitySettings(self):
|
||||||
if not self._current_settings:
|
if not self._current_settings or not self._enabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self._low_quality_settings:
|
if not self._low_quality_settings:
|
||||||
@ -196,7 +216,7 @@ class PrintInformation(QObject):
|
|||||||
else:
|
else:
|
||||||
continue
|
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)
|
self._current_settings.setSettingValueByKey(key, setting_value)
|
||||||
|
|
||||||
def _onSceneChanged(self, source):
|
def _onSceneChanged(self, source):
|
||||||
|
0
cura_app.py
Normal file → Executable file
BIN
icons/cura-128.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/cura-32.png
Normal file
After Width: | Height: | Size: 625 B |
BIN
icons/cura-48.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
icons/cura-64.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/cura.icns
Normal file
BIN
icons/cura.ico
Normal file
After Width: | Height: | Size: 30 KiB |
@ -1,5 +1,5 @@
|
|||||||
!ifndef VERSION
|
!ifndef VERSION
|
||||||
!define VERSION 'BETA'
|
!define VERSION '15.05.96'
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
; The name of the installer
|
; The name of the installer
|
||||||
@ -44,6 +44,9 @@ SetCompressor /SOLID lzma
|
|||||||
!define MUI_FINISHPAGE_RUN_TEXT "Start Cura ${VERSION}"
|
!define MUI_FINISHPAGE_RUN_TEXT "Start Cura ${VERSION}"
|
||||||
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
|
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
|
||||||
|
|
||||||
|
;Add an option to show release notes
|
||||||
|
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\release_notes.txt"
|
||||||
|
|
||||||
; Pages
|
; Pages
|
||||||
;!insertmacro MUI_PAGE_WELCOME
|
;!insertmacro MUI_PAGE_WELCOME
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
@ -89,7 +92,7 @@ Section "Cura ${VERSION}"
|
|||||||
|
|
||||||
CreateDirectory "$SMPROGRAMS\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}\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
|
SectionEnd
|
||||||
|
|
||||||
@ -99,6 +102,15 @@ Function LaunchLink
|
|||||||
Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk"'
|
Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk"'
|
||||||
FunctionEnd
|
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"
|
;Section "Install Arduino Drivers"
|
||||||
; ; Set output path to the driver directory.
|
; ; Set output path to the driver directory.
|
||||||
; SetOutPath "$INSTDIR\drivers\"
|
; SetOutPath "$INSTDIR\drivers\"
|
||||||
|
@ -59,6 +59,8 @@ class CuraEngineBackend(Backend):
|
|||||||
self._save_polygons = True
|
self._save_polygons = True
|
||||||
self._report_progress = True
|
self._report_progress = True
|
||||||
|
|
||||||
|
self._enabled = True
|
||||||
|
|
||||||
self.backendConnected.connect(self._onBackendConnected)
|
self.backendConnected.connect(self._onBackendConnected)
|
||||||
|
|
||||||
def getEngineCommand(self):
|
def getEngineCommand(self):
|
||||||
@ -86,6 +88,9 @@ class CuraEngineBackend(Backend):
|
|||||||
# If False, this method will do nothing when already slicing. True by default.
|
# 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.
|
# - report_progress: True if the slicing progress should be reported, False if not. Default is True.
|
||||||
def slice(self, **kwargs):
|
def slice(self, **kwargs):
|
||||||
|
if not self._enabled:
|
||||||
|
return
|
||||||
|
|
||||||
if self._slicing:
|
if self._slicing:
|
||||||
if not kwargs.get("force_restart", True):
|
if not kwargs.get("force_restart", True):
|
||||||
return
|
return
|
||||||
@ -110,6 +115,9 @@ class CuraEngineBackend(Backend):
|
|||||||
if not objects:
|
if not objects:
|
||||||
return #No point in slicing an empty build plate
|
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._slicing = True
|
||||||
self.slicingStarted.emit()
|
self.slicingStarted.emit()
|
||||||
|
|
||||||
@ -232,3 +240,10 @@ class CuraEngineBackend(Backend):
|
|||||||
if self._restart:
|
if self._restart:
|
||||||
self._onChanged()
|
self._onChanged()
|
||||||
self._restart = False
|
self._restart = False
|
||||||
|
|
||||||
|
def _onToolOperationStarted(self, tool):
|
||||||
|
self._enabled = False
|
||||||
|
|
||||||
|
def _onToolOperationStopped(self, tool):
|
||||||
|
self._enabled = True
|
||||||
|
self._onChanged()
|
||||||
|
@ -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!
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
# source: Cura.proto
|
# source: Cura.proto
|
||||||
|
|
||||||
@ -21,7 +18,7 @@ _sym_db = _symbol_database.Default()
|
|||||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||||
name='Cura.proto',
|
name='Cura.proto',
|
||||||
package='Cura',
|
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)
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||||
|
|
||||||
@ -57,11 +54,19 @@ _POLYGON_TYPE = _descriptor.EnumDescriptor(
|
|||||||
name='SkirtType', index=5, number=5,
|
name='SkirtType', index=5, number=5,
|
||||||
options=None,
|
options=None,
|
||||||
type=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,
|
containing_type=None,
|
||||||
options=None,
|
options=None,
|
||||||
serialized_start=430,
|
serialized_start=486,
|
||||||
serialized_end=528,
|
serialized_end=623,
|
||||||
)
|
)
|
||||||
_sym_db.RegisterEnumDescriptor(_POLYGON_TYPE)
|
_sym_db.RegisterEnumDescriptor(_POLYGON_TYPE)
|
||||||
|
|
||||||
@ -266,8 +271,22 @@ _LAYER = _descriptor.Descriptor(
|
|||||||
is_extension=False, extension_scope=None,
|
is_extension=False, extension_scope=None,
|
||||||
options=None),
|
options=None),
|
||||||
_descriptor.FieldDescriptor(
|
_descriptor.FieldDescriptor(
|
||||||
name='polygons', full_name='Cura.Layer.polygons', index=1,
|
name='height', full_name='Cura.Layer.height', index=1,
|
||||||
number=2, type=11, cpp_type=10, label=3,
|
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=[],
|
has_default_value=False, default_value=[],
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=False, extension_scope=None,
|
is_extension=False, extension_scope=None,
|
||||||
@ -284,7 +303,7 @@ _LAYER = _descriptor.Descriptor(
|
|||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=314,
|
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,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=False, extension_scope=None,
|
is_extension=False, extension_scope=None,
|
||||||
options=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=[
|
extensions=[
|
||||||
],
|
],
|
||||||
@ -321,8 +347,8 @@ _POLYGON = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=369,
|
serialized_start=404,
|
||||||
serialized_end=528,
|
serialized_end=623,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -358,8 +384,8 @@ _GCODELAYER = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=530,
|
serialized_start=625,
|
||||||
serialized_end=568,
|
serialized_end=663,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -402,8 +428,8 @@ _OBJECTPRINTTIME = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=570,
|
serialized_start=665,
|
||||||
serialized_end=638,
|
serialized_end=733,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -432,8 +458,8 @@ _SETTINGLIST = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=640,
|
serialized_start=735,
|
||||||
serialized_end=686,
|
serialized_end=781,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -469,8 +495,8 @@ _SETTING = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=688,
|
serialized_start=783,
|
||||||
serialized_end=726,
|
serialized_end=821,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -499,8 +525,8 @@ _GCODEPREFIX = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=728,
|
serialized_start=823,
|
||||||
serialized_end=755,
|
serialized_end=850,
|
||||||
)
|
)
|
||||||
|
|
||||||
_OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT
|
_OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT
|
||||||
|
@ -2,10 +2,13 @@
|
|||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from UM.Mesh.MeshData import MeshData
|
from UM.Mesh.MeshData import MeshData
|
||||||
|
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||||
from UM.Math.Color import Color
|
from UM.Math.Color import Color
|
||||||
|
from UM.Math.Vector import Vector
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
import math
|
import math
|
||||||
|
import copy
|
||||||
|
|
||||||
class LayerData(MeshData):
|
class LayerData(MeshData):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -13,12 +16,19 @@ class LayerData(MeshData):
|
|||||||
self._layers = {}
|
self._layers = {}
|
||||||
self._element_counts = {}
|
self._element_counts = {}
|
||||||
|
|
||||||
def addPolygon(self, layer, type, data):
|
def addLayer(self, layer):
|
||||||
if layer not in self._layers:
|
if layer not in self._layers:
|
||||||
self._layers[layer] = []
|
self._layers[layer] = Layer(layer)
|
||||||
|
|
||||||
p = Polygon(self, type, data)
|
def addPolygon(self, layer, type, data, line_width):
|
||||||
self._layers[layer].append(p)
|
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):
|
def getLayers(self):
|
||||||
return self._layers
|
return self._layers
|
||||||
@ -26,14 +36,134 @@ class LayerData(MeshData):
|
|||||||
def getElementCounts(self):
|
def getElementCounts(self):
|
||||||
return self._element_counts
|
return self._element_counts
|
||||||
|
|
||||||
def build(self):
|
def setLayerHeight(self, layer, height):
|
||||||
for layer, data in self._layers.items():
|
if layer not in self._layers:
|
||||||
if layer not in self._element_counts:
|
self.addLayer(layer)
|
||||||
self._element_counts[layer] = []
|
|
||||||
|
|
||||||
for polygon in data:
|
self._layers[layer].setHeight(height)
|
||||||
polygon.build()
|
|
||||||
self._element_counts[layer].append(polygon.elementCount)
|
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():
|
class Polygon():
|
||||||
NoneType = 0
|
NoneType = 0
|
||||||
@ -42,43 +172,58 @@ class Polygon():
|
|||||||
SkinType = 3
|
SkinType = 3
|
||||||
SupportType = 4
|
SupportType = 4
|
||||||
SkirtType = 5
|
SkirtType = 5
|
||||||
|
InfillType = 6
|
||||||
|
SupportInfillType = 7
|
||||||
|
|
||||||
def __init__(self, mesh, type, data):
|
def __init__(self, mesh, type, data, line_width):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._mesh = mesh
|
self._mesh = mesh
|
||||||
self._type = type
|
self._type = type
|
||||||
self._data = data
|
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
|
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):
|
for i in range(self._begin, self._end):
|
||||||
indices.append(i)
|
indices[i, 0] = i
|
||||||
indices.append(i + 1)
|
indices[i, 1] = i + 1
|
||||||
|
|
||||||
indices.append(self._end)
|
indices[self._end, 0] = self._end
|
||||||
indices.append(self._begin)
|
indices[self._end, 1] = self._begin
|
||||||
self._mesh.addIndices(numpy.array(indices, dtype=numpy.int32))
|
|
||||||
|
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
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
@ -90,4 +235,8 @@ class Polygon():
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def elementCount(self):
|
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
|
||||||
|
@ -7,18 +7,30 @@ from UM.Scene.SceneNode import SceneNode
|
|||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Mesh.MeshData import MeshData
|
from UM.Mesh.MeshData import MeshData
|
||||||
|
|
||||||
|
from UM.Message import Message
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
|
||||||
from . import LayerData
|
from . import LayerData
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
class ProcessSlicedObjectListJob(Job):
|
class ProcessSlicedObjectListJob(Job):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._message = message
|
self._message = message
|
||||||
self._scene = Application.getInstance().getController().getScene()
|
self._scene = Application.getInstance().getController().getScene()
|
||||||
|
|
||||||
|
self._progress = None
|
||||||
|
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
|
||||||
|
|
||||||
def run(self):
|
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 = {}
|
objectIdMap = {}
|
||||||
new_node = SceneNode()
|
new_node = SceneNode()
|
||||||
## Put all nodes in a dict identified by ID
|
## Put all nodes in a dict identified by ID
|
||||||
@ -32,39 +44,67 @@ class ProcessSlicedObjectListJob(Job):
|
|||||||
settings = Application.getInstance().getActiveMachine()
|
settings = Application.getInstance().getActiveMachine()
|
||||||
layerHeight = settings.getSettingValueByKey("layer_height")
|
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:
|
for object in self._message.objects:
|
||||||
try:
|
try:
|
||||||
node = objectIdMap[object.id]
|
node = objectIdMap[object.id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mesh = MeshData()
|
|
||||||
|
|
||||||
layerData = LayerData.LayerData()
|
layerData = LayerData.LayerData()
|
||||||
for layer in object.layers:
|
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:
|
for polygon in layer.polygons:
|
||||||
points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array
|
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 = 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 = numpy.asarray(points, dtype=numpy.float32)
|
||||||
points /= 1000
|
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
|
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))
|
layerData.addPolygon(layer.id, polygon.type, points, polygon.line_width)
|
||||||
#inverse = node.getWorldTransformation().getInverse().getData()
|
|
||||||
#points = points.dot(inverse)
|
|
||||||
#points = points[:,0:3]
|
|
||||||
|
|
||||||
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
|
# We are done processing all the layers we got from the engine, now create a mesh out of the data
|
||||||
layerData.build()
|
layerData.build()
|
||||||
mesh.layerData = layerData
|
mesh.layerData = layerData
|
||||||
|
|
||||||
|
if self._progress:
|
||||||
|
self._progress.setProgress(100)
|
||||||
|
|
||||||
new_node.setMeshData(mesh)
|
new_node.setMeshData(mesh)
|
||||||
new_node.setParent(self._scene.getRoot())
|
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()
|
||||||
|
|
||||||
|
@ -5,6 +5,15 @@ from UM.View.View import View
|
|||||||
from UM.View.Renderer import Renderer
|
from UM.View.Renderer import Renderer
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
from UM.Resources import Resources
|
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.
|
## View used to display g-code paths.
|
||||||
class LayerView(View):
|
class LayerView(View):
|
||||||
@ -13,6 +22,25 @@ class LayerView(View):
|
|||||||
self._material = None
|
self._material = None
|
||||||
self._num_layers = 0
|
self._num_layers = 0
|
||||||
self._layer_percentage = 0 # what percentage of layers need to be shown (SLider gives value between 0 - 100)
|
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):
|
def beginRendering(self):
|
||||||
scene = self.getController().getScene()
|
scene = self.getController().getScene()
|
||||||
@ -23,6 +51,80 @@ class LayerView(View):
|
|||||||
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "vertexcolor.frag"))
|
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._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
|
||||||
|
|
||||||
|
# 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 = 0
|
||||||
|
element_counts = layer_data.getElementCounts()
|
||||||
|
for layer, counts in element_counts.items():
|
||||||
|
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)
|
||||||
|
|
||||||
|
# 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):
|
||||||
|
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()):
|
for node in DepthFirstIterator(scene.getRoot()):
|
||||||
if not node.render(renderer):
|
if not node.render(renderer):
|
||||||
if node.getMeshData() and node.isVisible():
|
if node.getMeshData() and node.isVisible():
|
||||||
@ -30,25 +132,29 @@ class LayerView(View):
|
|||||||
layer_data = node.getMeshData().layerData
|
layer_data = node.getMeshData().layerData
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
|
if new_max_layers < len(layer_data.getLayers()):
|
||||||
|
new_max_layers = len(layer_data.getLayers()) - 1
|
||||||
|
|
||||||
if self._layer_percentage < 100:
|
if new_max_layers > 0 and new_max_layers != self._old_max_layers:
|
||||||
start = 0
|
self._max_layers = new_max_layers
|
||||||
end_layer = round(len(layer_data.getLayers()) * (self._layer_percentage / 100))
|
self.maxLayersChanged.emit()
|
||||||
end = 0
|
|
||||||
|
|
||||||
element_counts = layer_data.getElementCounts()
|
# This makes sure we update the current layer
|
||||||
for layer, counts in element_counts.items():
|
self.setLayer(int(self._max_layers * (self._current_layer_num / self._old_max_layers)))
|
||||||
end += sum(counts)
|
|
||||||
|
|
||||||
if layer >= end_layer:
|
maxLayersChanged = Signal()
|
||||||
break
|
|
||||||
|
|
||||||
renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end)
|
## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created
|
||||||
else:
|
# as this caused some issues.
|
||||||
renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines)
|
def getProxy(self, engine, script_engine):
|
||||||
|
return self._proxy
|
||||||
def setLayer(self, value):
|
|
||||||
self._layer_percentage = value
|
|
||||||
|
|
||||||
def endRendering(self):
|
def endRendering(self):
|
||||||
pass
|
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)
|
||||||
|
@ -20,10 +20,11 @@ Item
|
|||||||
anchors.right : parent.right
|
anchors.right : parent.right
|
||||||
orientation: Qt.Vertical
|
orientation: Qt.Vertical
|
||||||
minimumValue: 0;
|
minimumValue: 0;
|
||||||
maximumValue: 100;
|
maximumValue: UM.LayerView.numLayers;
|
||||||
|
stepSize: 1
|
||||||
|
|
||||||
value: 100;
|
value: UM.LayerView.currentLayer
|
||||||
onValueChanged: UM.ActiveView.triggerAction("setLayer", value)
|
onValueChanged: UM.LayerView.setCurrentLayer(value)
|
||||||
|
|
||||||
style: UM.Theme.styles.slider;
|
style: UM.Theme.styles.slider;
|
||||||
}
|
}
|
||||||
|
44
plugins/LayerView/LayerViewProxy.py
Normal file
@ -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)
|
@ -1,7 +1,8 @@
|
|||||||
# Copyright (c) 2015 Ultimaker B.V.
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# 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
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
@ -21,6 +22,10 @@ def getMetaData():
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def createLayerViewProxy(engine, script_engine):
|
||||||
|
return LayerViewProxy.LayerViewProxy()
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
|
layer_view = LayerView.LayerView()
|
||||||
|
qmlRegisterSingletonType(LayerViewProxy.LayerViewProxy, "UM", 1, 0, "LayerView", layer_view.getProxy)
|
||||||
return { "view": LayerView.LayerView() }
|
return { "view": LayerView.LayerView() }
|
||||||
|
@ -174,6 +174,10 @@ class PrinterConnection(SignalEmitter):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
Logger.log("i", "Could not establish connection on %s, unknown reasons. Device is not arduino based." % self._serial_port)
|
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.
|
# 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)
|
for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect)
|
||||||
|
|
||||||
@ -241,10 +245,17 @@ class PrinterConnection(SignalEmitter):
|
|||||||
## Close the printer connection
|
## Close the printer connection
|
||||||
def close(self):
|
def close(self):
|
||||||
if self._connect_thread.isAlive():
|
if self._connect_thread.isAlive():
|
||||||
|
try:
|
||||||
self._connect_thread.join()
|
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:
|
if self._serial is not None:
|
||||||
self.setIsConnected(False)
|
self.setIsConnected(False)
|
||||||
|
try:
|
||||||
self._listen_thread.join()
|
self._listen_thread.join()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
self._serial.close()
|
self._serial.close()
|
||||||
|
|
||||||
self._serial = None
|
self._serial = None
|
||||||
|
@ -19,8 +19,7 @@ from PyQt5.QtQuick import QQuickView
|
|||||||
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal
|
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
i18n_catalog = i18nCatalog("uranium")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
class USBPrinterManager(QObject, SignalEmitter, Extension):
|
class USBPrinterManager(QObject, SignalEmitter, Extension):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
@ -40,6 +39,7 @@ class USBPrinterManager(QObject, SignalEmitter, Extension):
|
|||||||
self._error_message = ""
|
self._error_message = ""
|
||||||
|
|
||||||
## Add menu item to top menu of the application.
|
## Add menu item to top menu of the application.
|
||||||
|
self.setMenuName("Firmware")
|
||||||
self.addMenuItem(i18n_catalog.i18n("Update Firmware"), self.updateAllFirmware)
|
self.addMenuItem(i18n_catalog.i18n("Update Firmware"), self.updateAllFirmware)
|
||||||
|
|
||||||
pyqtError = pyqtSignal(str, arguments = ["amount"])
|
pyqtError = pyqtSignal(str, arguments = ["amount"])
|
||||||
|
91
resources/i18n/ru/cura.po
Normal file
@ -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 <EMAIL@ADDRESS>, 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 "Слой"
|
430
resources/i18n/ru/cura_qt.po
Normal file
@ -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 "Показать где есть нависающие части"
|
1843
resources/i18n/ru/fdmprinter.json.po
Normal file
BIN
resources/images/cura-icon.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
import QtQuick.Window 2.1
|
||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.0 as UM
|
||||||
@ -12,48 +11,53 @@ UM.Dialog {
|
|||||||
id: base
|
id: base
|
||||||
|
|
||||||
//: About dialog title
|
//: About dialog title
|
||||||
title: qsTr("About Cura");
|
title: qsTr("About Cura")
|
||||||
|
minimumWidth: 400
|
||||||
ColumnLayout {
|
minimumHeight: 300
|
||||||
anchors.fill: parent;
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true;
|
|
||||||
Layout.fillHeight: true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
Layout.alignment: Qt.AlignHCenter;
|
id: logo
|
||||||
Layout.preferredWidth: parent.width * 0.75;
|
width: parent.width * 0.75
|
||||||
Layout.preferredHeight: width * (1/4.25);
|
height: width * (1/4.25)
|
||||||
|
|
||||||
source: UM.Theme.images.logo;
|
source: UM.Theme.images.logo
|
||||||
|
|
||||||
sourceSize.width: width;
|
sourceSize.width: width
|
||||||
sourceSize.height: height;
|
sourceSize.height: height
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.verticalCenterOffset : -(height * 0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.alignment: Qt.AlignHCenter;
|
id: version
|
||||||
|
|
||||||
text: "Cura 15.06 Beta";
|
text: "Cura 15.06 Beta"
|
||||||
font: UM.Theme.fonts.large;
|
font: UM.Theme.fonts.large
|
||||||
|
anchors.horizontalCenter : logo.horizontalCenter
|
||||||
|
anchors.horizontalCenterOffset : (logo.width * 0.25)
|
||||||
|
anchors.top: logo.bottom
|
||||||
|
anchors.topMargin : 5
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
id: description
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
//: About dialog application description
|
//: About dialog application description
|
||||||
text: qsTr("End-to-end solution for fused filament 3D printing.")
|
text: qsTr("End-to-end solution for fused filament 3D printing.")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
anchors.top: version.bottom
|
||||||
|
anchors.topMargin : 10
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
id: author_note
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
//: About dialog application author note
|
//: About dialog application author note
|
||||||
text: qsTr("Cura has been developed by Ultimaker B.V. in cooperation with the community.")
|
text: qsTr("Cura has been developed by Ultimaker B.V. in cooperation with the community.")
|
||||||
}
|
wrapMode: Text.WordWrap
|
||||||
|
anchors.top: description.bottom
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true;
|
|
||||||
Layout.fillHeight: true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rightButtons: Button {
|
rightButtons: Button {
|
||||||
|
@ -25,6 +25,7 @@ UM.MainWindow {
|
|||||||
window: base
|
window: base
|
||||||
|
|
||||||
Menu {
|
Menu {
|
||||||
|
id: fileMenu
|
||||||
//: File menu
|
//: File menu
|
||||||
title: qsTr("&File");
|
title: qsTr("&File");
|
||||||
|
|
||||||
@ -33,6 +34,21 @@ UM.MainWindow {
|
|||||||
|
|
||||||
MenuSeparator { }
|
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; }
|
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 {
|
UM.MessageStack {
|
||||||
anchors {
|
anchors {
|
||||||
left: toolbar.right;
|
left: toolbar.right;
|
||||||
@ -195,8 +194,8 @@ UM.MainWindow {
|
|||||||
id: openFileButton;
|
id: openFileButton;
|
||||||
|
|
||||||
iconSource: UM.Theme.icons.open;
|
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 {
|
anchors {
|
||||||
top: parent.top;
|
top: parent.top;
|
||||||
topMargin: UM.Theme.sizes.window_margin.height;
|
topMargin: UM.Theme.sizes.window_margin.height;
|
||||||
@ -235,7 +234,7 @@ UM.MainWindow {
|
|||||||
iconSource: UM.Theme.icons.viewmode;
|
iconSource: UM.Theme.icons.viewmode;
|
||||||
|
|
||||||
style: UM.Theme.styles.tool_button;
|
style: UM.Theme.styles.tool_button;
|
||||||
|
tooltip: '';
|
||||||
menu: Menu {
|
menu: Menu {
|
||||||
id: viewMenu;
|
id: viewMenu;
|
||||||
Instantiator {
|
Instantiator {
|
||||||
@ -265,6 +264,35 @@ UM.MainWindow {
|
|||||||
bottomMargin: UM.Theme.sizes.window_margin.height;
|
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;
|
preferences.onTriggered: preferences.visible = true;
|
||||||
configureMachines.onTriggered: { preferences.visible = true; preferences.setPage(2); }
|
configureMachines.onTriggered: { preferences.visible = true; preferences.setPage(2); }
|
||||||
|
|
||||||
documentation.onTriggered: Qt.openUrlExternally("https://ultimaker.com/en/support");
|
documentation.onTriggered: CuraActions.openDocumentation();
|
||||||
reportBug.onTriggered: Qt.openUrlExternally("https://github.com/Ultimaker/Cura/issues");
|
reportBug.onTriggered: CuraActions.openBugReportPage();
|
||||||
showEngineLog.onTriggered: engineLog.visible = true;
|
showEngineLog.onTriggered: engineLog.visible = true;
|
||||||
about.onTriggered: aboutDialog.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"))
|
Component.onCompleted: UM.Theme.load(UM.Resources.getPath(UM.Resources.ThemesLocation, "cura"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import QtQuick.Layouts 1.1
|
|||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.0 as UM
|
||||||
|
|
||||||
Button {
|
Rectangle {
|
||||||
id: base;
|
id: base;
|
||||||
|
|
||||||
property Action saveAction;
|
property Action saveAction;
|
||||||
@ -16,8 +16,6 @@ Button {
|
|||||||
property real progress: UM.Backend.progress;
|
property real progress: UM.Backend.progress;
|
||||||
Behavior on progress { NumberAnimation { duration: 250; } }
|
Behavior on progress { NumberAnimation { duration: 250; } }
|
||||||
|
|
||||||
enabled: progress >= 0.95;
|
|
||||||
|
|
||||||
property string currentDevice: "local_file"
|
property string currentDevice: "local_file"
|
||||||
property bool defaultOverride: false;
|
property bool defaultOverride: false;
|
||||||
property bool defaultAmbiguous: false;
|
property bool defaultAmbiguous: false;
|
||||||
@ -25,9 +23,6 @@ Button {
|
|||||||
property variant printDuration: PrintInformation.currentPrintTime;
|
property variant printDuration: PrintInformation.currentPrintTime;
|
||||||
property real printMaterialAmount: PrintInformation.materialAmount;
|
property real printMaterialAmount: PrintInformation.materialAmount;
|
||||||
|
|
||||||
iconSource: UM.Theme.icons[Printer.outputDevices[base.currentDevice].icon];
|
|
||||||
tooltip: Printer.outputDevices[base.currentDevice].description;
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Printer;
|
target: Printer;
|
||||||
onOutputDevicesChanged: {
|
onOutputDevicesChanged: {
|
||||||
@ -51,120 +46,162 @@ Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
Rectangle{
|
||||||
background: UM.AngledCornerRectangle {
|
id: background
|
||||||
implicitWidth: control.width;
|
implicitWidth: base.width;
|
||||||
implicitHeight: control.height;
|
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;
|
Rectangle {
|
||||||
cornerSize: UM.Theme.sizes.default_margin.width;
|
id: infoBox
|
||||||
|
width: parent.width - UM.Theme.sizes.default_margin.width * 2;
|
||||||
|
height: UM.Theme.sizes.save_button_slicing_bar.height
|
||||||
|
|
||||||
UM.AngledCornerRectangle {
|
anchors.top: parent.top
|
||||||
anchors.fill: parent;
|
anchors.topMargin: UM.Theme.sizes.default_margin.height;
|
||||||
anchors.margins: UM.Theme.sizes.save_button_border.width;
|
anchors.left: parent.left
|
||||||
cornerSize: UM.Theme.sizes.default_margin.width;
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||||
color: UM.Theme.colors.save_button;
|
|
||||||
}
|
|
||||||
|
|
||||||
UM.AngledCornerRectangle {
|
border.width: UM.Theme.sizes.save_button_border.width
|
||||||
anchors {
|
border.color: UM.Theme.colors.save_button_border
|
||||||
left: parent.left;
|
color: UM.Theme.colors.save_button_estimated_text_background;
|
||||||
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 {
|
|
||||||
Label {
|
Label {
|
||||||
id: label;
|
id: label;
|
||||||
anchors.left: parent.left;
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width;
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width;
|
||||||
color: UM.Theme.colors.save_button_text;
|
visible: base.progress >= 0 && base.progress < 0.99 ? false : true
|
||||||
font: UM.Theme.fonts.default;
|
color: UM.Theme.colors.save_button_estimated_text;
|
||||||
|
font: UM.Theme.fonts.small;
|
||||||
text: control.text;
|
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 {
|
Label {
|
||||||
anchors.left: parent.left;
|
id: printDurationLabel
|
||||||
anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width;
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: label.right;
|
||||||
color: UM.Theme.colors.save_button_text;
|
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width;
|
||||||
font: UM.Theme.fonts.default;
|
color: UM.Theme.colors.save_button_printtime_text;
|
||||||
|
font: UM.Theme.fonts.small;
|
||||||
text: (!control.printDuration || !control.printDuration.valid) ? "" : control.printDuration.getDisplayString(UM.DurationFormat.Long)
|
visible: base.progress < 0.99 ? false : true
|
||||||
|
text: (!base.printDuration || !base.printDuration.valid) ? "" : base.printDuration.getDisplayString(UM.DurationFormat.Long);
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
anchors.left: parent.left;
|
id: printMaterialLabel
|
||||||
anchors.leftMargin: control.height + UM.Theme.sizes.save_button_label_margin.width;
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: printDurationLabel.right;
|
||||||
color: UM.Theme.colors.save_button_text;
|
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width;
|
||||||
font: UM.Theme.fonts.default;
|
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
|
//: 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
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked:
|
||||||
|
if(base.defaultAmbiguous) {
|
||||||
|
devicesMenu.popup();
|
||||||
|
} else {
|
||||||
|
Printer.writeToOutputDevice(base.currentDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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: ''
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
menu: Menu {
|
||||||
anchors.fill: parent;
|
|
||||||
|
|
||||||
acceptedButtons: Qt.RightButton;
|
|
||||||
|
|
||||||
onClicked: devicesMenu.popup();
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu {
|
|
||||||
id: devicesMenu;
|
id: devicesMenu;
|
||||||
|
|
||||||
Instantiator {
|
Instantiator {
|
||||||
model: Printer.outputDeviceNames;
|
model: Printer.outputDeviceNames;
|
||||||
MenuItem {
|
MenuItem {
|
||||||
@ -184,28 +221,8 @@ Button {
|
|||||||
onObjectAdded: devicesMenu.insertItem(index, object)
|
onObjectAdded: devicesMenu.insertItem(index, object)
|
||||||
onObjectRemoved: devicesMenu.removeItem(object)
|
onObjectRemoved: devicesMenu.removeItem(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusiveGroup { id: devicesMenuGroup; }
|
ExclusiveGroup { id: devicesMenuGroup; }
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if(base.defaultAmbiguous) {
|
|
||||||
devicesMenu.popup();
|
|
||||||
} else {
|
|
||||||
Printer.writeToOutputDevice(base.currentDevice);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,18 +8,18 @@ import QtQuick.Layouts 1.1
|
|||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.0 as UM
|
||||||
|
|
||||||
UM.AngledCornerRectangle {
|
Rectangle {
|
||||||
id: base;
|
id: base;
|
||||||
|
|
||||||
property Action addMachineAction;
|
property Action addMachineAction;
|
||||||
property Action configureMachinesAction;
|
property Action configureMachinesAction;
|
||||||
property alias saveAction: saveButton.saveAction;
|
property alias saveAction: saveButton.saveAction;
|
||||||
|
|
||||||
cornerSize: UM.Theme.sizes.default_margin.width;
|
color: UM.Theme.colors.sidebar;
|
||||||
|
|
||||||
function showTooltip(item, position, text) {
|
function showTooltip(item, position, text) {
|
||||||
tooltip.text = text;
|
tooltip.text = text;
|
||||||
position = item.mapToItem(base, position.x, position.y);
|
position = item.mapToItem(base, position.x, position.y / 2);
|
||||||
tooltip.show(position);
|
tooltip.show(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,6 @@ UM.AngledCornerRectangle {
|
|||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
anchors.topMargin: UM.Theme.sizes.default_margin.height;
|
anchors.topMargin: UM.Theme.sizes.default_margin.height;
|
||||||
anchors.bottomMargin: UM.Theme.sizes.window_margin.height;
|
|
||||||
|
|
||||||
spacing: UM.Theme.sizes.default_margin.height;
|
spacing: UM.Theme.sizes.default_margin.height;
|
||||||
|
|
||||||
@ -91,11 +90,9 @@ UM.AngledCornerRectangle {
|
|||||||
|
|
||||||
SaveButton {
|
SaveButton {
|
||||||
id: saveButton;
|
id: saveButton;
|
||||||
Layout.preferredWidth: base.width - UM.Theme.sizes.default_margin.width * 2;
|
implicitWidth: base.width
|
||||||
Layout.preferredHeight: UM.Theme.sizes.button.height;
|
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
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SidebarTooltip {
|
SidebarTooltip {
|
||||||
@ -109,4 +106,11 @@ UM.AngledCornerRectangle {
|
|||||||
//: Advanced configuration mode option
|
//: Advanced configuration mode option
|
||||||
ListElement { text: QT_TR_NOOP("Advanced"); file: "SidebarAdvanced.qml" }
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
// Copyright (c) 2015 Ultimaker B.V.
|
// Copyright (c) 2015 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the AGPLv3 or higher.
|
// 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
|
import UM 1.0 as UM
|
||||||
|
|
||||||
UM.SettingView { }
|
UM.SettingView {
|
||||||
|
expandedCategories: Printer.expandedCategories;
|
||||||
|
onExpandedCategoriesChanged: Printer.setExpandedCategories(expandedCategories);
|
||||||
|
}
|
||||||
|
@ -33,7 +33,7 @@ Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ToolButton {
|
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;
|
style: UM.Theme.styles.sidebar_header_button;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ Column {
|
|||||||
model: base.modesModel;
|
model: base.modesModel;
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: qsTr(model.text);
|
text: model.text;
|
||||||
checkable: true;
|
checkable: true;
|
||||||
checked: modeMenu.currentIndex == index;
|
checked: modeMenu.currentIndex == index;
|
||||||
exclusiveGroup: modeMenuGroup;
|
exclusiveGroup: modeMenuGroup;
|
||||||
|
@ -20,6 +20,9 @@ Item {
|
|||||||
property variant minimumPrintTime: PrintInformation.minimumPrintTime;
|
property variant minimumPrintTime: PrintInformation.minimumPrintTime;
|
||||||
property variant maximumPrintTime: PrintInformation.maximumPrintTime;
|
property variant maximumPrintTime: PrintInformation.maximumPrintTime;
|
||||||
|
|
||||||
|
Component.onCompleted: PrintInformation.enabled = true
|
||||||
|
Component.onDestruction: PrintInformation.enabled = false
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ Rectangle {
|
|||||||
|
|
||||||
function show(position) {
|
function show(position) {
|
||||||
if(position.y + base.height > parent.height) {
|
if(position.y + base.height > parent.height) {
|
||||||
x = position.x;
|
x = position.x - base.width;
|
||||||
y = parent.height - base.height;
|
y = parent.height - base.height;
|
||||||
} else {
|
} else {
|
||||||
x = position.x;
|
x = position.x - base.width;
|
||||||
y = position.y;
|
y = position.y;
|
||||||
}
|
}
|
||||||
base.opacity = 1;
|
base.opacity = 1;
|
||||||
|
@ -14,6 +14,24 @@ Item {
|
|||||||
width: buttons.width;
|
width: buttons.width;
|
||||||
height: buttons.height + panel.height;
|
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 {
|
RowLayout {
|
||||||
id: buttons;
|
id: buttons;
|
||||||
|
|
||||||
@ -30,10 +48,10 @@ Item {
|
|||||||
Button {
|
Button {
|
||||||
text: model.name;
|
text: model.name;
|
||||||
iconSource: UM.Theme.icons[model.icon];
|
iconSource: UM.Theme.icons[model.icon];
|
||||||
tooltip: model.description;
|
|
||||||
|
|
||||||
checkable: true;
|
checkable: true;
|
||||||
checked: model.active;
|
checked: model.active;
|
||||||
|
onCheckedChanged: if (checked) activeItemBackground.setActive(x);
|
||||||
|
|
||||||
style: UM.Theme.styles.tool_button;
|
style: UM.Theme.styles.tool_button;
|
||||||
|
|
||||||
@ -47,16 +65,29 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
UM.AngledCornerRectangle {
|
||||||
id: panel
|
id: panelBackground;
|
||||||
|
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.bottom: buttons.top;
|
anchors.bottom: buttons.top;
|
||||||
anchors.bottomMargin: UM.Theme.sizes.default_margin.height;
|
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;
|
||||||
|
|
||||||
|
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 : "";
|
source: UM.ActiveTool.valid ? UM.ActiveTool.activeToolPanel : "";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,20 @@
|
|||||||
|
|
||||||
"categories": {
|
"categories": {
|
||||||
"material": {
|
"material": {
|
||||||
|
"settings": {
|
||||||
|
"material_print_temperature": {
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
"material_bed_temperature": {
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
"material_diameter": {
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
"material_flow": {
|
||||||
"visible": false
|
"visible": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,23 @@
|
|||||||
"machine_nozzle_gantry_distance": { "default": 55 },
|
"machine_nozzle_gantry_distance": { "default": 55 },
|
||||||
"machine_nozzle_offset_x_1": { "default": 18.0 },
|
"machine_nozzle_offset_x_1": { "default": 18.0 },
|
||||||
"machine_nozzle_offset_y_1": { "default": 0.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "ultimaker_original_plus",
|
"id": "ultimaker_original_plus",
|
||||||
"name": "Ultimaker Original Plus",
|
"name": "Ultimaker Original+",
|
||||||
"icon": "icon_ultimaker.png",
|
"icon": "icon_ultimaker.png",
|
||||||
"platform": "ultimaker2_platform.obj",
|
"platform": "ultimaker2_platform.obj",
|
||||||
"platform_texture": "UltimakerPlusbackplate.png",
|
"platform_texture": "UltimakerPlusbackplate.png",
|
||||||
|
149
resources/themes/cura/icons/category_blackmagic.svg
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:i="&#38;#38;ns_ai;"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="30px"
|
||||||
|
height="30px"
|
||||||
|
viewBox="0 0 30 30"
|
||||||
|
enable-background="new 0 0 30 30"
|
||||||
|
xml:space="preserve"
|
||||||
|
id="svg3445"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="category_blackmagic.svg"><metadata
|
||||||
|
id="metadata3464"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs3462" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1104"
|
||||||
|
id="namedview3460"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="15.733333"
|
||||||
|
inkscape:cx="17.360656"
|
||||||
|
inkscape:cy="-1.829103"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g3449" /><switch
|
||||||
|
id="switch3447"
|
||||||
|
style="fill:#000000"><foreignObject
|
||||||
|
requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"><i:pgfRef
|
||||||
|
xlink:href="#adobe_illustrator_pgf" /></foreignObject><g
|
||||||
|
i:extraneous="self"
|
||||||
|
id="g3449"
|
||||||
|
style="fill:#000000"><g
|
||||||
|
id="frame_30x30"
|
||||||
|
display="none"
|
||||||
|
style="fill:#000000"><rect
|
||||||
|
display="inline"
|
||||||
|
width="30"
|
||||||
|
height="30"
|
||||||
|
id="rect3452"
|
||||||
|
style="fill:#000000" /></g><g
|
||||||
|
id="frame_24x24"
|
||||||
|
display="none"
|
||||||
|
style="fill:#000000"><rect
|
||||||
|
x="3"
|
||||||
|
y="3"
|
||||||
|
display="inline"
|
||||||
|
fill="#C6C7C8"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
id="rect3455"
|
||||||
|
style="fill:#000000" /></g><g
|
||||||
|
id="icon"
|
||||||
|
style="fill:#ffffff"><path
|
||||||
|
d="M 21,11 24,3 6,3 9,11 3,27 27,27 Z M 9.937,10.648 7.443,4 22.556,4 20.063,10.648 19.932,11 l 0.132,0.352 5.495386,14.648398 c -21.1116911,-0.0086 0,0 -21.1116911,-0.0086 L 9.938,11.352 10.068,11 Z"
|
||||||
|
id="path3458"
|
||||||
|
style="fill:#ffffff"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccccccccccccccccc" /><text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:18.84262657px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="8.4277077"
|
||||||
|
y="19.917229"
|
||||||
|
id="text3477"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
transform="scale(1.0563883,0.94662161)"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3479"
|
||||||
|
x="8.4277077"
|
||||||
|
y="19.917229"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:gargi;-inkscape-font-specification:'gargi Medium';fill:#ffffff">?</tspan></text>
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#ffffff"
|
||||||
|
id="path3481"
|
||||||
|
sodipodi:sides="4"
|
||||||
|
sodipodi:cx="9.3481913"
|
||||||
|
sodipodi:cy="22.314709"
|
||||||
|
sodipodi:r1="2.4681976"
|
||||||
|
sodipodi:r2="0.83969672"
|
||||||
|
sodipodi:arg1="-0.57790194"
|
||||||
|
sodipodi:arg2="0.14505566"
|
||||||
|
inkscape:flatsided="false"
|
||||||
|
inkscape:rounded="0"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 11.41558,20.966412 -1.236511,1.469673 0.517419,1.946012 -1.4696728,-1.23651 -1.9460124,0.517419 1.2365104,-1.469673 -0.5174188,-1.946013 1.4696729,1.236511 z"
|
||||||
|
inkscape:transform-center-x="1.0389927"
|
||||||
|
inkscape:transform-center-y="0.029898609"
|
||||||
|
transform="matrix(-0.22728467,0.67950815,-0.70858638,-0.2354929,27.791673,20.846699)" /><path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#ffffff"
|
||||||
|
id="path3483"
|
||||||
|
sodipodi:sides="4"
|
||||||
|
sodipodi:cx="19.64019"
|
||||||
|
sodipodi:cy="21.10124"
|
||||||
|
sodipodi:r1="3.1779661"
|
||||||
|
sodipodi:r2="1.3224357"
|
||||||
|
sodipodi:arg1="1.7126934"
|
||||||
|
sodipodi:arg2="2.4768523"
|
||||||
|
inkscape:flatsided="false"
|
||||||
|
inkscape:rounded="0"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 19.190758,24.247266 -0.591427,-2.330275 -2.105167,-1.265183 2.330275,-0.591427 1.265183,-2.105167 0.591427,2.330275 2.105167,1.265183 -2.330275,0.591427 z"
|
||||||
|
inkscape:transform-center-x="-0.16053709"
|
||||||
|
inkscape:transform-center-y="0.22160086"
|
||||||
|
transform="matrix(0.6277977,0.94579165,-0.90860936,0.60311684,26.861228,-9.3621234)" /><path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#ffffff"
|
||||||
|
id="path3487"
|
||||||
|
sodipodi:sides="4"
|
||||||
|
sodipodi:cx="14.741379"
|
||||||
|
sodipodi:cy="18.045101"
|
||||||
|
sodipodi:r1="2.2819479"
|
||||||
|
sodipodi:r2="0.93399796"
|
||||||
|
sodipodi:arg1="-1.0101093"
|
||||||
|
sodipodi:arg2="-0.21584978"
|
||||||
|
inkscape:flatsided="false"
|
||||||
|
inkscape:rounded="0"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="m 15.954846,16.112542 -0.301143,1.732518 1.020235,1.413508 -1.732518,-0.301143 -1.413508,1.020235 0.301142,-1.732517 -1.020234,-1.413509 1.732517,0.301143 z"
|
||||||
|
inkscape:transform-center-x="-0.17795886"
|
||||||
|
inkscape:transform-center-y="-0.0146708"
|
||||||
|
transform="matrix(0.18679438,-0.98239903,0.98239903,0.18679438,-5.8318713,29.017206)" /></g></g></switch><i:pgf
|
||||||
|
id="adobe_illustrator_pgf" /></svg>
|
After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 246 KiB After Width: | Height: | Size: 246 KiB |
3384
resources/themes/cura/icons/category_shell.svg
Normal file
After Width: | Height: | Size: 248 KiB |
3422
resources/themes/cura/icons/category_travel.svg
Normal file
After Width: | Height: | Size: 249 KiB |
@ -35,45 +35,41 @@ QtObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property Component tool_button: Component {
|
property Component open_file_button: Component {
|
||||||
ButtonStyle {
|
ButtonStyle {
|
||||||
background: UM.AngledCornerRectangle {
|
background: Item {
|
||||||
property bool down: control.pressed || (control.checkable && control.checked);
|
|
||||||
|
|
||||||
implicitWidth: UM.Theme.sizes.button.width;
|
implicitWidth: UM.Theme.sizes.button.width;
|
||||||
implicitHeight: UM.Theme.sizes.button.height;
|
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; } }
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: label;
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
|
text: control.text.replace("&", "");
|
||||||
|
font: UM.Theme.fonts.button_tooltip;
|
||||||
|
color: UM.Theme.colors.button_tooltip_text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.AngledCornerRectangle {
|
||||||
|
anchors.fill: parent;
|
||||||
color: {
|
color: {
|
||||||
if(!control.enabled) {
|
if(control.hovered) {
|
||||||
return UM.Theme.colors.button_disabled;
|
|
||||||
} else if(control.checkable && control.checked && control.hovered) {
|
|
||||||
return UM.Theme.colors.button_active_hover;
|
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 {
|
} else {
|
||||||
return UM.Theme.colors.button;
|
return UM.Theme.colors.button_active;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Behavior on color { ColorAnimation { duration: 50; } }
|
Behavior on color { ColorAnimation { duration: 50; } }
|
||||||
cornerSize: UM.Theme.sizes.default_margin.width;
|
cornerSize: UM.Theme.sizes.default_margin.width;
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.bottom: parent.top;
|
|
||||||
|
|
||||||
width: parent.width;
|
|
||||||
height: control.hovered ? label.height : 0;
|
|
||||||
Behavior on height { NumberAnimation { duration: 75; } }
|
|
||||||
|
|
||||||
opacity: control.hovered ? 1.0 : 0.0;
|
|
||||||
Behavior on opacity { NumberAnimation { duration: 75; } }
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: label
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter;
|
|
||||||
text: control.text;
|
|
||||||
font: UM.Theme.fonts.button_tooltip;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 {
|
property Component sidebar_category: Component {
|
||||||
ButtonStyle {
|
ButtonStyle {
|
||||||
background: UM.AngledCornerRectangle {
|
background: UM.AngledCornerRectangle {
|
||||||
@ -121,6 +221,8 @@ QtObject {
|
|||||||
Image {
|
Image {
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
source: control.iconSource;
|
source: control.iconSource;
|
||||||
|
width: UM.Theme.sizes.section_icon.width;
|
||||||
|
height: UM.Theme.sizes.section_icon.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
"capitalize": true,
|
"capitalize": true,
|
||||||
"family": "Roboto"
|
"family": "Roboto"
|
||||||
},
|
},
|
||||||
|
"sidebar_save_to": {
|
||||||
|
"size": 1.0,
|
||||||
|
"family": "Roboto"
|
||||||
|
},
|
||||||
"timeslider_time": {
|
"timeslider_time": {
|
||||||
"size": 1.0,
|
"size": 1.0,
|
||||||
"bold": true,
|
"bold": true,
|
||||||
@ -44,23 +48,26 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"colors": {
|
"colors": {
|
||||||
|
"sidebar": [255, 255, 255, 255],
|
||||||
|
|
||||||
"primary": [12, 169, 227, 255],
|
"primary": [12, 169, 227, 255],
|
||||||
"primary_hover": [34, 150, 190, 255],
|
"primary_hover": [34, 150, 190, 255],
|
||||||
"primary_text": [255, 255, 255, 255],
|
"primary_text": [255, 255, 255, 255],
|
||||||
"border": [205, 202, 201, 255],
|
"border": [205, 202, 201, 255],
|
||||||
"secondary": [205, 202, 201, 255],
|
"secondary": [205, 202, 201, 255],
|
||||||
|
|
||||||
"text": [174, 174, 174, 255],
|
"text": [140, 144, 154, 255],
|
||||||
"text_inactive": [205, 202, 201, 255],
|
"text_inactive": [174, 174, 174, 255],
|
||||||
"text_hover": [35, 35, 35, 255],
|
"text_hover": [35, 35, 35, 255],
|
||||||
"text_pressed": [12, 169, 227, 255],
|
"text_pressed": [12, 169, 227, 255],
|
||||||
|
|
||||||
"button": [205, 202, 201, 255],
|
"button": [160, 163, 171, 255],
|
||||||
"button_hover": [174, 174, 174, 255],
|
"button_hover": [140, 144, 154, 255],
|
||||||
"button_active": [12, 169, 227, 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_text": [255, 255, 255, 255],
|
||||||
"button_disabled": [245, 245, 245, 255],
|
"button_disabled": [245, 245, 245, 255],
|
||||||
|
"button_tooltip_text": [35, 35, 35, 255],
|
||||||
|
|
||||||
"scrollbar_background": [245, 245, 245, 255],
|
"scrollbar_background": [245, 245, 245, 255],
|
||||||
"scrollbar_handle": [205, 202, 201, 255],
|
"scrollbar_handle": [205, 202, 201, 255],
|
||||||
@ -74,7 +81,7 @@
|
|||||||
"setting_category_active_hover": [34, 150, 190, 255],
|
"setting_category_active_hover": [34, 150, 190, 255],
|
||||||
"setting_category_text": [255, 255, 255, 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": [255, 255, 255, 255],
|
||||||
"setting_control_highlight": [245, 245, 245, 255],
|
"setting_control_highlight": [245, 245, 245, 255],
|
||||||
"setting_control_border": [174, 174, 174, 255],
|
"setting_control_border": [174, 174, 174, 255],
|
||||||
@ -85,6 +92,9 @@
|
|||||||
"setting_validation_warning": [255, 186, 15, 255],
|
"setting_validation_warning": [255, 186, 15, 255],
|
||||||
"setting_validation_ok": [255, 255, 255, 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": [245, 245, 245, 255],
|
||||||
"slider_groove_border": [205, 202, 201, 255],
|
"slider_groove_border": [205, 202, 201, 255],
|
||||||
"slider_groove_fill": [205, 202, 201, 255],
|
"slider_groove_fill": [205, 202, 201, 255],
|
||||||
@ -95,19 +105,24 @@
|
|||||||
"checkbox_hover": [245, 245, 245, 255],
|
"checkbox_hover": [245, 245, 245, 255],
|
||||||
"checkbox_border": [174, 174, 174, 255],
|
"checkbox_border": [174, 174, 174, 255],
|
||||||
"checkbox_mark": [35, 35, 35, 255],
|
"checkbox_mark": [35, 35, 35, 255],
|
||||||
"checkbox_text": [174, 174, 174, 255],
|
"checkbox_text": [140, 144, 154, 255],
|
||||||
|
|
||||||
"tooltip": [255, 225, 146, 255],
|
"tooltip": [255, 225, 146, 255],
|
||||||
|
|
||||||
"save_button": [255, 255, 255, 255],
|
|
||||||
"save_button_border": [205, 202, 201, 255],
|
"save_button_border": [205, 202, 201, 255],
|
||||||
"save_button_inactive": [205, 202, 201, 255],
|
"save_button_inactive": [205, 202, 201, 255],
|
||||||
"save_button_active": [12, 159, 227, 255],
|
"save_button_active": [12, 159, 227, 255],
|
||||||
"save_button_active_hover": [34, 150, 190, 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": [205, 202, 201, 255],
|
||||||
"message_text": [35, 35, 35, 255]
|
"message_text": [35, 35, 35, 255],
|
||||||
|
|
||||||
|
"tool_panel_background": [255, 255, 255, 255]
|
||||||
},
|
},
|
||||||
|
|
||||||
"sizes": {
|
"sizes": {
|
||||||
@ -128,7 +143,11 @@
|
|||||||
"setting_unit_margin": [0.5, 0.5],
|
"setting_unit_margin": [0.5, 0.5],
|
||||||
|
|
||||||
"button": [4.25, 4.25],
|
"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],
|
"scrollbar": [0.5, 0.5],
|
||||||
|
|
||||||
@ -141,7 +160,10 @@
|
|||||||
"tooltip_margins": [1.0, 1.0],
|
"tooltip_margins": [1.0, 1.0],
|
||||||
|
|
||||||
"save_button_border": [0.06, 0.06],
|
"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_label_margin": [0.5, 0.5],
|
||||||
|
"save_button_save_to_button": [0.3, 2.7],
|
||||||
|
|
||||||
"message": [30.0, 5.0],
|
"message": [30.0, 5.0],
|
||||||
"message_close": [1.25, 1.25]
|
"message_close": [1.25, 1.25]
|
||||||
|
14
setup.py
@ -22,7 +22,7 @@ def copytree(src, dst, symlinks=False, ignore=None):
|
|||||||
else:
|
else:
|
||||||
shutil.copy2(s, d)
|
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.
|
# 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__)):
|
for dirpath, dirnames, filenames in os.walk(os.path.dirname(UM.__file__)):
|
||||||
if "__" in dirpath:
|
if "__" in dirpath:
|
||||||
@ -41,18 +41,18 @@ print("Removing previous distribution package")
|
|||||||
shutil.rmtree("dist", True)
|
shutil.rmtree("dist", True)
|
||||||
|
|
||||||
setup(name="Cura",
|
setup(name="Cura",
|
||||||
version="2.0",
|
version="15.05.95",
|
||||||
author="Ultimaker",
|
author="Ultimaker",
|
||||||
author_email="d.braam@ultimaker.com",
|
author_email="d.braam@ultimaker.com",
|
||||||
url="http://software.ultimaker.com/",
|
url="http://software.ultimaker.com/",
|
||||||
license="GNU AFFERO GENERAL PUBLIC LICENSE (AGPL)",
|
license="GNU AFFERO GENERAL PUBLIC LICENSE (AGPL)",
|
||||||
scripts=["cura_app.py"],
|
scripts=["cura_app.py"],
|
||||||
#windows=[{"script": "printer.py", "dest_name": "Cura"}],
|
windows=[{"script": "cura_app.py", "dest_name": "Cura", "icon_resources": [(1, "icons/cura.ico")]}],
|
||||||
console=[{"script": "cura_app.py"}],
|
#console=[{"script": "cura_app.py"}],
|
||||||
options={"py2exe": {"skip_archive": False, "includes": includes}})
|
options={"py2exe": {"skip_archive": False, "includes": includes}})
|
||||||
|
|
||||||
print("Coping Cura plugins.")
|
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"):
|
for path in os.listdir("plugins"):
|
||||||
shutil.copytree("plugins/" + path, "dist/plugins/" + path)
|
shutil.copytree("plugins/" + path, "dist/plugins/" + path)
|
||||||
print("Coping resources.")
|
print("Coping 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")
|
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)
|
print("Coping PyQt5 svg library from: %s" % qt_origin_path)
|
||||||
shutil.copy(os.path.join(qt_origin_path, "Qt5Svg.dll"), "dist/Qt5Svg.dll")
|
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")
|