Browse Source

Merge branch 'master' into layer_view3_cleanup

Jack Ha 8 years ago
parent
commit
abe7a8e9a3

+ 9 - 0
cura/BlockSlicingDecorator.py

@@ -0,0 +1,9 @@
+from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
+
+
+class BlockSlicingDecorator(SceneNodeDecorator):
+    def __init__(self):
+        super().__init__()
+
+    def isBlockSlicing(self):
+        return True

+ 16 - 4
cura/BuildVolume.py

@@ -538,8 +538,11 @@ class BuildVolume(SceneNode):
             prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value")
             machine_width = self._global_container_stack.getProperty("machine_width", "value")
             machine_depth = self._global_container_stack.getProperty("machine_depth", "value")
-            prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value") - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
-            prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value") + machine_depth / 2
+            prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value")
+            prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value")
+            if not self._global_container_stack.getProperty("machine_center_is_zero", "value"):
+                prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
+                prime_tower_y = prime_tower_y + machine_depth / 2
 
             prime_tower_area = Polygon([
                 [prime_tower_x - prime_tower_size, prime_tower_y - prime_tower_size],
@@ -570,8 +573,17 @@ class BuildVolume(SceneNode):
         machine_width = self._global_container_stack.getProperty("machine_width", "value")
         machine_depth = self._global_container_stack.getProperty("machine_depth", "value")
         for extruder in used_extruders:
-            prime_x = extruder.getProperty("extruder_prime_pos_x", "value") - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
-            prime_y = machine_depth / 2 - extruder.getProperty("extruder_prime_pos_y", "value")
+            prime_x = extruder.getProperty("extruder_prime_pos_x", "value")
+            prime_y = - extruder.getProperty("extruder_prime_pos_y", "value")
+
+            #Ignore extruder prime position if it is not set
+            if prime_x == 0 and prime_y == 0:
+                result[extruder.getId()] = []
+                continue
+
+            if not self._global_container_stack.getProperty("machine_center_is_zero", "value"):
+                prime_x = prime_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
+                prime_y = prime_x + machine_depth / 2
 
             prime_polygon = Polygon.approximatedCircle(PRIME_CLEARANCE)
             prime_polygon = prime_polygon.translate(prime_x, prime_y)

+ 2 - 1
cura/CuraActions.py

@@ -1,5 +1,6 @@
-from PyQt5.QtCore import QObject, pyqtSlot, QUrl
+from PyQt5.QtCore import QObject, QUrl
 from PyQt5.QtGui import QDesktopServices
+from UM.FlameProfiler import pyqtSlot
 
 from UM.Event import CallFunctionEvent
 from UM.Application import Application

+ 94 - 6
cura/CuraApplication.py

@@ -19,6 +19,8 @@ from UM.SaveFile import SaveFile
 from UM.Scene.Selection import Selection
 from UM.Scene.GroupDecorator import GroupDecorator
 from UM.Settings.Validator import Validator
+from UM.Message import Message
+from UM.i18n import i18nCatalog
 
 from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
 from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
@@ -26,13 +28,13 @@ from UM.Operations.GroupedOperation import GroupedOperation
 from UM.Operations.SetTransformOperation import SetTransformOperation
 from UM.Operations.TranslateOperation import TranslateOperation
 from cura.SetParentOperation import SetParentOperation
+from cura.SliceableObjectDecorator import SliceableObjectDecorator
+from cura.BlockSlicingDecorator import BlockSlicingDecorator
 
 from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType
 from UM.Settings.ContainerRegistry import ContainerRegistry
 from UM.Settings.SettingFunction import SettingFunction
 
-from UM.i18n import i18nCatalog
-
 from . import PlatformPhysics
 from . import BuildVolume
 from . import CameraAnimation
@@ -45,7 +47,8 @@ from . import MachineActionManager
 
 import cura.Settings
 
-from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
+from PyQt5.QtCore import QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
+from UM.FlameProfiler import pyqtSlot
 from PyQt5.QtGui import QColor, QIcon
 from PyQt5.QtWidgets import QMessageBox
 from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType
@@ -135,6 +138,9 @@ class CuraApplication(QtApplication):
             }
         )
 
+        self._currently_loading_files = []
+        self._non_sliceable_extensions = []
+
         self._machine_action_manager = MachineActionManager.MachineActionManager()
         self._machine_manager = None    # This is initialized on demand.
         self._setting_inheritance_manager = None
@@ -212,7 +218,7 @@ class CuraApplication(QtApplication):
         Preferences.getInstance().addPreference("cura/recent_files", "")
         Preferences.getInstance().addPreference("cura/categories_expanded", "")
         Preferences.getInstance().addPreference("cura/jobname_prefix", True)
-        Preferences.getInstance().addPreference("view/center_on_select", True)
+        Preferences.getInstance().addPreference("view/center_on_select", False)
         Preferences.getInstance().addPreference("mesh/scale_to_fit", True)
         Preferences.getInstance().addPreference("mesh/scale_tiny_meshes", True)
         Preferences.getInstance().addPreference("cura/dialog_on_project_save", True)
@@ -581,9 +587,12 @@ class CuraApplication(QtApplication):
     def updatePlatformActivity(self, node = None):
         count = 0
         scene_bounding_box = None
+        is_block_slicing_node = False
         for node in DepthFirstIterator(self.getController().getScene().getRoot()):
-            if type(node) is not SceneNode or not node.getMeshData():
+            if type(node) is not SceneNode or (not node.getMeshData() and not node.callDecoration("getLayerData")):
                 continue
+            if node.callDecoration("isBlockSlicing"):
+                is_block_slicing_node = True
 
             count += 1
             if not scene_bounding_box:
@@ -593,6 +602,10 @@ class CuraApplication(QtApplication):
                 if other_bb is not None:
                     scene_bounding_box = scene_bounding_box + node.getBoundingBox()
 
+        print_information = self.getPrintInformation()
+        if print_information:
+            print_information.setPreSliced(is_block_slicing_node)
+
         if not scene_bounding_box:
             scene_bounding_box = AxisAlignedBox.Null
 
@@ -713,7 +726,7 @@ class CuraApplication(QtApplication):
         for node in DepthFirstIterator(self.getController().getScene().getRoot()):
             if type(node) is not SceneNode:
                 continue
-            if not node.getMeshData() and not node.callDecoration("isGroup"):
+            if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
                 continue  # Node that doesnt have a mesh and is not a group.
             if node.getParent() and node.getParent().callDecoration("isGroup"):
                 continue  # Grouped nodes don't need resetting as their parent (the group) is resetted)
@@ -1008,3 +1021,78 @@ class CuraApplication(QtApplication):
     @pyqtSlot(str)
     def log(self, msg):
         Logger.log("d", msg)
+
+    @pyqtSlot(QUrl)
+    def readLocalFile(self, file):
+        if not file.isValid():
+            return
+
+        scene = self.getController().getScene()
+
+        for node in DepthFirstIterator(scene.getRoot()):
+            if node.callDecoration("isBlockSlicing"):
+                self.deleteAll()
+                break
+
+        f = file.toLocalFile()
+        extension = os.path.splitext(f)[1]
+        filename = os.path.basename(f)
+        if len(self._currently_loading_files) > 0:
+            # If a non-slicable file is already being loaded, we prevent loading of any further non-slicable files
+            if extension.lower() in self._non_sliceable_extensions:
+                message = Message(
+                    self._i18n_catalog.i18nc("@info:status",
+                                       "Only one G-code file can be loaded at a time. Skipped importing {0}",
+                                       filename))
+                message.show()
+                return
+            # If file being loaded is non-slicable file, then prevent loading of any other files
+            extension = os.path.splitext(self._currently_loading_files[0])[1]
+            if extension.lower() in self._non_sliceable_extensions:
+                message = Message(
+                    self._i18n_catalog.i18nc("@info:status",
+                                       "Can't open any other file if G-code is loading. Skipped importing {0}",
+                                       filename))
+                message.show()
+                return
+
+        self._currently_loading_files.append(f)
+        if extension in self._non_sliceable_extensions:
+            self.deleteAll()
+
+        job = ReadMeshJob(f)
+        job.finished.connect(self._readMeshFinished)
+        job.start()
+
+    def _readMeshFinished(self, job):
+        nodes = job.getResult()
+        filename = job.getFileName()
+        self._currently_loading_files.remove(filename)
+
+        for node in nodes:
+            node.setSelectable(True)
+            node.setName(os.path.basename(filename))
+
+            extension = os.path.splitext(filename)[1]
+            if extension.lower() in self._non_sliceable_extensions:
+                self.getController().setActiveView("LayerView")
+                view = self.getController().getActiveView()
+                view.resetLayerData()
+                view.setLayer(9999999)
+                view.calculateMaxLayers()
+
+                block_slicing_decorator = BlockSlicingDecorator()
+                node.addDecorator(block_slicing_decorator)
+            else:
+                sliceable_decorator = SliceableObjectDecorator()
+                node.addDecorator(sliceable_decorator)
+
+            scene = self.getController().getScene()
+
+            op = AddSceneNodeOperation(node, scene.getRoot())
+            op.push()
+
+            scene.sceneChanged.emit(node)
+
+    def addNonSliceableExtension(self, extension):
+        self._non_sliceable_extensions.append(extension)

+ 13 - 0
cura/GCodeListDecorator.py

@@ -0,0 +1,13 @@
+from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
+
+
+class GCodeListDecorator(SceneNodeDecorator):
+    def __init__(self):
+        super().__init__()
+        self._gcode_list = []
+
+    def getGCodeList(self):
+        return self._gcode_list
+
+    def setGCodeList(self, list):
+        self._gcode_list = list

+ 2 - 1
cura/MachineActionManager.py

@@ -6,7 +6,8 @@ from UM.PluginRegistry import PluginRegistry  # So MachineAction can be added as
 from UM.Settings.ContainerRegistry import ContainerRegistry
 from UM.Settings.DefinitionContainer import DefinitionContainer
 
-from PyQt5.QtCore import QObject, pyqtSlot
+from PyQt5.QtCore import QObject
+from UM.FlameProfiler import pyqtSlot
 
 ##  Raised when trying to add an unknown machine action as a required action
 class UnknownMachineActionError(Exception):

+ 21 - 3
cura/PrintInformation.py

@@ -1,7 +1,8 @@
 # Copyright (c) 2015 Ultimaker B.V.
 # Cura is released under the terms of the AGPLv3 or higher.
 
-from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
+from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
+from UM.FlameProfiler import pyqtSlot
 
 from UM.Application import Application
 from UM.Qt.Duration import Duration
@@ -13,6 +14,9 @@ import math
 import os.path
 import unicodedata
 
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
 ##  A class for processing and calculating minimum, current and maximum print time as well as managing the job name
 #
 #   This class contains all the logic relating to calculation and slicing for the
@@ -49,6 +53,8 @@ class PrintInformation(QObject):
         self._material_lengths = []
         self._material_weights = []
 
+        self._pre_sliced = False
+
         self._backend = Application.getInstance().getBackend()
         if self._backend:
             self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
@@ -61,6 +67,16 @@ class PrintInformation(QObject):
 
     currentPrintTimeChanged = pyqtSignal()
 
+    preSlicedChanged = pyqtSignal()
+
+    @pyqtProperty(bool, notify=preSlicedChanged)
+    def preSliced(self):
+        return self._pre_sliced
+
+    def setPreSliced(self, pre_sliced):
+        self._pre_sliced = pre_sliced
+        self.preSlicedChanged.emit()
+
     @pyqtProperty(Duration, notify = currentPrintTimeChanged)
     def currentPrintTime(self):
         return self._current_print_time
@@ -122,7 +138,9 @@ class PrintInformation(QObject):
     def createJobName(self, base_name):
         base_name = self._stripAccents(base_name)
         self._setAbbreviatedMachineName()
-        if Preferences.getInstance().getValue("cura/jobname_prefix"):
+        if self._pre_sliced:
+            return catalog.i18nc("@label", "Pre-sliced file {0}", base_name)
+        elif Preferences.getInstance().getValue("cura/jobname_prefix"):
             return self._abbr_machine + "_" + base_name
         else:
             return base_name
@@ -150,4 +168,4 @@ class PrintInformation(QObject):
 
     ##  Utility method that strips accents from characters (eg: â -> a)
     def _stripAccents(self, str):
-       return ''.join(char for char in unicodedata.normalize('NFD', str) if unicodedata.category(char) != 'Mn')
+       return ''.join(char for char in unicodedata.normalize('NFD', str) if unicodedata.category(char) != 'Mn')

+ 3 - 0
cura/QualityManager.py

@@ -220,6 +220,9 @@ class QualityManager:
             material_ids = set()
             for material_instance in material_containers:
                 if material_instance is not None:
+                    # Add the parent material too.
+                    for basic_material in self._getBasicMaterials(material_instance):
+                        material_ids.add(basic_material.getId())
                     material_ids.add(material_instance.getId())
 
         containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria)

+ 2 - 1
cura/Settings/ContainerManager.py

@@ -4,7 +4,8 @@
 import os.path
 import urllib
 
-from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal, QUrl, QVariant
+from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QUrl, QVariant
+from UM.FlameProfiler import pyqtSlot
 from PyQt5.QtWidgets import QMessageBox
 
 import UM.PluginRegistry

+ 2 - 1
cura/Settings/ExtruderManager.py

@@ -1,7 +1,8 @@
 # Copyright (c) 2016 Ultimaker B.V.
 # Cura is released under the terms of the AGPLv3 or higher.
 
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject, QVariant #For communicating data and events to Qt.
+from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant #For communicating data and events to Qt.
+from UM.FlameProfiler import pyqtSlot
 
 import UM.Application #To get the global container stack to find the current machine.
 import UM.Logger

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