Fix merge conflicts after multi-buildplate refactor

This commit is contained in:
ChrisTerBeke 2018-01-04 10:52:01 +01:00
commit c7c989f2a0
87 changed files with 12891 additions and 740 deletions

View file

@ -1,4 +1,5 @@
# Copyright (c) 2017 Ultimaker B.V.
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtNetwork import QLocalServer
from PyQt5.QtNetwork import QLocalSocket
@ -16,7 +17,6 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Mesh.ReadMeshJob import ReadMeshJob
from UM.Logger import Logger
from UM.Preferences import Preferences
from UM.SaveFile import SaveFile
from UM.Scene.Selection import Selection
from UM.Scene.GroupDecorator import GroupDecorator
from UM.Settings.ContainerStack import ContainerStack
@ -32,15 +32,19 @@ from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
from UM.Operations.GroupedOperation import GroupedOperation
from UM.Operations.SetTransformOperation import SetTransformOperation
from cura.Arrange import Arrange
from cura.ShapeArray import ShapeArray
from cura.ConvexHullDecorator import ConvexHullDecorator
from cura.SetParentOperation import SetParentOperation
from cura.SliceableObjectDecorator import SliceableObjectDecorator
from cura.BlockSlicingDecorator import BlockSlicingDecorator
from cura.ArrangeObjectsJob import ArrangeObjectsJob
from cura.Arranging.Arrange import Arrange
from cura.Arranging.ArrangeObjectsJob import ArrangeObjectsJob
from cura.Arranging.ArrangeObjectsAllBuildPlatesJob import ArrangeObjectsAllBuildPlatesJob
from cura.Arranging.ShapeArray import ShapeArray
from cura.MultiplyObjectsJob import MultiplyObjectsJob
from cura.Scene.ConvexHullDecorator import ConvexHullDecorator
from cura.Operations.SetParentOperation import SetParentOperation
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
from cura.Scene.BlockSlicingDecorator import BlockSlicingDecorator
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.CuraSceneController import CuraSceneController
from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType
from UM.Settings.ContainerRegistry import ContainerRegistry
@ -53,12 +57,13 @@ from cura.Settings.SettingInheritanceManager import SettingInheritanceManager
from cura.Settings.UserProfilesModel import UserProfilesModel
from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager
from . import PlatformPhysics
from . import BuildVolume
from . import CameraAnimation
from . import PrintInformation
from . import CuraActions
from . import ZOffsetDecorator
from cura.Scene import ZOffsetDecorator
from . import CuraSplashScreen
from . import CameraImageProvider
from . import MachineActionManager
@ -72,8 +77,9 @@ from cura.Settings.ContainerSettingsModel import ContainerSettingsModel
from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
from cura.Settings.QualitySettingsModel import QualitySettingsModel
from cura.Settings.ContainerManager import ContainerManager
from cura.Settings.GlobalStack import GlobalStack
from cura.Settings.ExtruderStack import ExtruderStack
from cura.ObjectsModel import ObjectsModel
from cura.BuildPlateModel import BuildPlateModel
from PyQt5.QtCore import QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
from UM.FlameProfiler import pyqtSlot
@ -85,7 +91,6 @@ import sys
import os.path
import numpy
import copy
import urllib.parse
import os
import argparse
import json
@ -203,8 +208,11 @@ class CuraApplication(QtApplication):
self._machine_manager = None # This is initialized on demand.
self._extruder_manager = None
self._material_manager = None
self._object_manager = None
self._build_plate_model = None
self._setting_inheritance_manager = None
self._simple_mode_settings_manager = None
self._cura_scene_controller = None
self._additional_components = {} # Components to add to certain areas in the interface
@ -311,12 +319,15 @@ class CuraApplication(QtApplication):
preferences.addPreference("cura/asked_dialog_on_project_save", False)
preferences.addPreference("cura/choice_on_profile_override", "always_ask")
preferences.addPreference("cura/choice_on_open_project", "always_ask")
preferences.addPreference("cura/arrange_objects_on_load", True)
preferences.addPreference("cura/use_multi_build_plate", False)
preferences.addPreference("cura/currency", "")
preferences.addPreference("cura/material_settings", "{}")
preferences.addPreference("view/invert_zoom", False)
preferences.addPreference("cura/sidebar_collapse", False)
preferences.addPreference("view/filter_current_build_plate", False)
preferences.addPreference("cura/sidebar_collapsed", False)
self._need_to_show_user_agreement = not Preferences.getInstance().getValue("general/accepted_user_agreement")
@ -389,6 +400,8 @@ class CuraApplication(QtApplication):
self._plugin_registry.addSupportedPluginExtension("curaplugin", "Cura Plugin")
self.getCuraSceneController().setActiveBuildPlate(0) # Initialize
def _onEngineCreated(self):
self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
@ -733,6 +746,22 @@ class CuraApplication(QtApplication):
self._material_manager = MaterialManager.createMaterialManager()
return self._material_manager
def getObjectsModel(self, *args):
if self._object_manager is None:
self._object_manager = ObjectsModel.createObjectsModel()
return self._object_manager
def getBuildPlateModel(self, *args):
if self._build_plate_model is None:
self._build_plate_model = BuildPlateModel.createBuildPlateModel()
return self._build_plate_model
def getCuraSceneController(self, *args):
if self._cura_scene_controller is None:
self._cura_scene_controller = CuraSceneController.createCuraSceneController()
return self._cura_scene_controller
def getSettingInheritanceManager(self, *args):
if self._setting_inheritance_manager is None:
self._setting_inheritance_manager = SettingInheritanceManager.createSettingInheritanceManager()
@ -777,6 +806,7 @@ class CuraApplication(QtApplication):
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 2, "SceneController", self.getCuraSceneController)
qmlRegisterSingletonType(ExtruderManager, "Cura", 1, 0, "ExtruderManager", self.getExtruderManager)
qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager)
qmlRegisterSingletonType(MaterialManager, "Cura", 1, 0, "MaterialManager", self.getMaterialManager)
@ -784,6 +814,8 @@ class CuraApplication(QtApplication):
qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 2, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager)
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 2, "ObjectsModel", self.getObjectsModel)
qmlRegisterSingletonType(BuildPlateModel, "Cura", 1, 2, "BuildPlateModel", self.getBuildPlateModel)
qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel)
@ -875,7 +907,7 @@ class CuraApplication(QtApplication):
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() and not node.callDecoration("getLayerData")):
if not issubclass(type(node), SceneNode) or (not node.getMeshData() and not node.callDecoration("getLayerData")):
continue
if node.callDecoration("isBlockSlicing"):
is_block_slicing_node = True
@ -992,7 +1024,7 @@ class CuraApplication(QtApplication):
Selection.clear()
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode:
if not issubclass(type(node), SceneNode):
continue
if not node.getMeshData() and not node.callDecoration("isGroup"):
continue # Node that doesnt have a mesh and is not a group.
@ -1000,6 +1032,9 @@ class CuraApplication(QtApplication):
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
if not node.isSelectable():
continue # i.e. node with layer data
if not node.callDecoration("isSliceable"):
continue # i.e. node with layer data
Selection.add(node)
## Delete all nodes containing mesh data in the scene.
@ -1011,7 +1046,7 @@ class CuraApplication(QtApplication):
nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode:
if type(node) not in {SceneNode, CuraSceneNode}:
continue
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.
@ -1027,13 +1062,15 @@ class CuraApplication(QtApplication):
op.push()
Selection.clear()
## Reset all translation on nodes with mesh data.
self.getCuraSceneController().setActiveBuildPlate(0) # Select first build plate
## Reset all translation on nodes with mesh data.
@pyqtSlot()
def resetAllTranslation(self):
Logger.log("i", "Resetting all scene translations")
nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode:
if not issubclass(type(node), SceneNode):
continue
if not node.getMeshData() and not node.callDecoration("isGroup"):
continue # Node that doesnt have a mesh and is not a group.
@ -1061,13 +1098,13 @@ class CuraApplication(QtApplication):
Logger.log("i", "Resetting all scene transformations")
nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode:
if not issubclass(type(node), SceneNode):
continue
if not node.getMeshData() 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)
if not node.isSelectable():
if not node.callDecoration("isSliceable"):
continue # i.e. node with layer data
nodes.append(node)
@ -1085,10 +1122,31 @@ class CuraApplication(QtApplication):
## Arrange all objects.
@pyqtSlot()
def arrangeAll(self):
def arrangeObjectsToAllBuildPlates(self):
nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode:
if not issubclass(type(node), SceneNode):
continue
if not node.getMeshData() 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)
if not node.callDecoration("isSliceable"):
continue # i.e. node with layer data
# Skip nodes that are too big
if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
nodes.append(node)
job = ArrangeObjectsAllBuildPlatesJob(nodes)
job.start()
self.getCuraSceneController().setActiveBuildPlate(0) # Select first build plate
# Single build plate
@pyqtSlot()
def arrangeAll(self):
nodes = []
active_build_plate = self.getBuildPlateModel().activeBuildPlate
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if not issubclass(type(node), SceneNode):
continue
if not node.getMeshData() and not node.callDecoration("isGroup"):
continue # Node that doesnt have a mesh and is not a group.
@ -1096,9 +1154,12 @@ class CuraApplication(QtApplication):
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
if not node.isSelectable():
continue # i.e. node with layer data
# Skip nodes that are too big
if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
nodes.append(node)
if not node.callDecoration("isSliceable"):
continue # i.e. node with layer data
if node.callDecoration("getBuildPlateNumber") == active_build_plate:
# Skip nodes that are too big
if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
nodes.append(node)
self.arrange(nodes, fixed_nodes = [])
## Arrange Selection
@ -1109,7 +1170,7 @@ class CuraApplication(QtApplication):
# What nodes are on the build plate and are not being moved
fixed_nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode:
if not issubclass(type(node), SceneNode):
continue
if not node.getMeshData() and not node.callDecoration("isGroup"):
continue # Node that doesnt have a mesh and is not a group.
@ -1117,6 +1178,8 @@ class CuraApplication(QtApplication):
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
if not node.isSelectable():
continue # i.e. node with layer data
if not node.callDecoration("isSliceable"):
continue # i.e. node with layer data
if node in nodes: # exclude selected node from fixed_nodes
continue
fixed_nodes.append(node)
@ -1135,7 +1198,7 @@ class CuraApplication(QtApplication):
Logger.log("i", "Reloading all loaded mesh data.")
nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if type(node) is not SceneNode or not node.getMeshData():
if not issubclass(type(node), SceneNode) or not node.getMeshData():
continue
nodes.append(node)
@ -1152,7 +1215,7 @@ class CuraApplication(QtApplication):
job.start()
else:
Logger.log("w", "Unable to reload data because we don't have a filename.")
## Get logging data of the backend engine
# \returns \type{string} Logging data
@pyqtSlot(result = str)
@ -1226,10 +1289,11 @@ class CuraApplication(QtApplication):
@pyqtSlot()
def groupSelected(self):
# Create a group-node
group_node = SceneNode()
group_node = CuraSceneNode()
group_decorator = GroupDecorator()
group_node.addDecorator(group_decorator)
group_node.addDecorator(ConvexHullDecorator())
group_node.addDecorator(BuildPlateDecorator(self.getBuildPlateModel().activeBuildPlate))
group_node.setParent(self.getController().getScene().getRoot())
group_node.setSelectable(True)
center = Selection.getSelectionCenter()
@ -1374,8 +1438,15 @@ class CuraApplication(QtApplication):
min_offset = 8
self.fileLoaded.emit(filename)
arrange_objects_on_load = (
not Preferences.getInstance().getValue("cura/use_multi_build_plate") or
Preferences.getInstance().getValue("cura/arrange_objects_on_load"))
target_build_plate = self.getBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1
for original_node in nodes:
node = CuraSceneNode() # We want our own CuraSceneNode
node.setMeshData(original_node.getMeshData())
for node in nodes:
node.setSelectable(True)
node.setName(os.path.basename(filename))
@ -1402,21 +1473,23 @@ class CuraApplication(QtApplication):
if not child.getDecorator(ConvexHullDecorator):
child.addDecorator(ConvexHullDecorator())
if node.callDecoration("isSliceable"):
# Only check position if it's not already blatantly obvious that it won't fit.
if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
# Find node location
offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = min_offset)
if arrange_objects_on_load:
if node.callDecoration("isSliceable"):
# Only check position if it's not already blatantly obvious that it won't fit.
if node.getBoundingBox() is None or self._volume.getBoundingBox() is None or node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
# Find node location
offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = min_offset)
# If a model is to small then it will not contain any points
if offset_shape_arr is None and hull_shape_arr is None:
Message(self._i18n_catalog.i18nc("@info:status", "The selected model was too small to load."),
title=self._i18n_catalog.i18nc("@info:title", "Warning")
).show()
return
# If a model is to small then it will not contain any points
if offset_shape_arr is None and hull_shape_arr is None:
Message(self._i18n_catalog.i18nc("@info:status", "The selected model was too small to load."),
title=self._i18n_catalog.i18nc("@info:title", "Warning")).show()
return
# Step is for skipping tests to make it a lot faster. it also makes the outcome somewhat rougher
node, _ = arranger.findNodePlacement(node, offset_shape_arr, hull_shape_arr, step = 10)
# Step is for skipping tests to make it a lot faster. it also makes the outcome somewhat rougher
node, _ = arranger.findNodePlacement(node, offset_shape_arr, hull_shape_arr, step = 10)
node.addDecorator(BuildPlateDecorator(target_build_plate))
op = AddSceneNodeOperation(node, scene.getRoot())
op.push()