From a9671cdcfd0686010951aedea02c2facaf8efd9f Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 11 Jun 2016 23:00:44 +0200 Subject: [PATCH] Deleting a backup This removes a backup, which I made when switching between git branches. --- cura/CuraApplication2.py | 784 --------------------------------------- 1 file changed, 784 deletions(-) delete mode 100644 cura/CuraApplication2.py diff --git a/cura/CuraApplication2.py b/cura/CuraApplication2.py deleted file mode 100644 index 85c269fc8b..0000000000 --- a/cura/CuraApplication2.py +++ /dev/null @@ -1,784 +0,0 @@ -# Copyright (c) 2015 Ultimaker B.V. -# Cura is released under the terms of the AGPLv3 or higher. - -from memory_profiler import profile - -from UM.Qt.QtApplication import QtApplication -from UM.Scene.SceneNode import SceneNode -from UM.Scene.Camera import Camera -from UM.Scene.Platform import Platform -from UM.Math.Vector import Vector -from UM.Math.Quaternion import Quaternion -from UM.Math.AxisAlignedBox import AxisAlignedBox -from UM.Resources import Resources -from UM.Scene.ToolHandle import ToolHandle -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.JobQueue import JobQueue -from UM.SaveFile import SaveFile -from UM.Scene.Selection import Selection -from UM.Scene.GroupDecorator import GroupDecorator -import UM.Settings.Validator - -from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation -from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation -from UM.Operations.GroupedOperation import GroupedOperation -from UM.Operations.SetTransformOperation import SetTransformOperation -from cura.SetParentOperation import SetParentOperation - -from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType -from UM.Settings.ContainerRegistry import ContainerRegistry - -from UM.i18n import i18nCatalog - -from . import ExtruderManager -from . import ExtrudersModel -from . import PlatformPhysics -from . import BuildVolume -from . import CameraAnimation -from . import PrintInformation -from . import CuraActions -from . import MultiMaterialDecorator -from . import ZOffsetDecorator -from . import CuraSplashScreen -from . import MachineManagerModel - -from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS -from PyQt5.QtGui import QColor, QIcon -from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType - -import platform -import sys -import os.path -import numpy -import copy -import urllib -numpy.seterr(all="ignore") - -#WORKAROUND: GITHUB-88 GITHUB-385 GITHUB-612 -if platform.system() == "Linux": # Needed for platform.linux_distribution, which is not available on Windows and OSX - # For Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826 - if platform.linux_distribution()[0] in ("Ubuntu", ): # TODO: Needs a "if X11_GFX == 'nvidia'" here. The workaround is only needed on Ubuntu+NVidia drivers. Other drivers are not affected, but fine with this fix. - import ctypes - from ctypes.util import find_library - ctypes.CDLL(find_library('GL'), ctypes.RTLD_GLOBAL) - -try: - from cura.CuraVersion import CuraVersion, CuraBuildType -except ImportError: - CuraVersion = "master" # [CodeStyle: Reflecting imported value] - CuraBuildType = "" - -@profile -class CuraApplication(QtApplication): - class ResourceTypes: - QmlFiles = Resources.UserType + 1 - Firmware = Resources.UserType + 2 - QualityInstanceContainer = Resources.UserType + 3 - MaterialInstanceContainer = Resources.UserType + 4 - VariantInstanceContainer = Resources.UserType + 5 - UserInstanceContainer = Resources.UserType + 6 - MachineStack = Resources.UserType + 7 - ExtruderStack = Resources.UserType + 8 - - Q_ENUMS(ResourceTypes) - - def __init__(self): - Resources.addSearchPath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura", "resources")) - if not hasattr(sys, "frozen"): - Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources")) - - self._open_file_queue = [] # Files to open when plug-ins are loaded. - - # Need to do this before ContainerRegistry tries to load the machines - SettingDefinition.addSupportedProperty("global_only", DefinitionPropertyType.Function, default = False) - SettingDefinition.addSettingType("extruder", int, str, UM.Settings.Validator) - - super().__init__(name = "cura", version = CuraVersion, buildtype = CuraBuildType) - - self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png"))) - - self.setRequiredPlugins([ - "CuraEngineBackend", - "MeshView", - "LayerView", - "STLReader", - "SelectionTool", - "CameraTool", - "GCodeWriter", - "LocalFileOutputDevice" - ]) - self._physics = None - self._volume = None - self._platform = None - self._output_devices = {} - self._print_information = None - self._i18n_catalog = None - self._previous_active_tool = None - self._platform_activity = False - self._scene_bounding_box = AxisAlignedBox() - self._job_name = None - self._center_after_select = False - self._camera_animation = None - self._cura_actions = None - self._started = False - - self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity) - self.getController().toolOperationStopped.connect(self._onToolOperationStopped) - - Resources.addType(self.ResourceTypes.QmlFiles, "qml") - Resources.addType(self.ResourceTypes.Firmware, "firmware") - - ## Add the 4 types of profiles to storage. - Resources.addStorageType(self.ResourceTypes.QualityInstanceContainer, "quality") - Resources.addStorageType(self.ResourceTypes.VariantInstanceContainer, "variants") - Resources.addStorageType(self.ResourceTypes.MaterialInstanceContainer, "materials") - Resources.addStorageType(self.ResourceTypes.UserInstanceContainer, "user") - Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders") - Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances") - - ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer) - ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.VariantInstanceContainer) - ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.MaterialInstanceContainer) - ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.UserInstanceContainer) - ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.ExtruderStack) - ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.MachineStack) - - # Add empty variant, material and quality containers. - # Since they are empty, they should never be serialized and instead just programmatically created. - # We need them to simplify the switching between materials. - empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() - empty_variant_container = copy.deepcopy(empty_container) - empty_variant_container._id = "empty_variant" - empty_variant_container.addMetaDataEntry("type", "variant") - ContainerRegistry.getInstance().addContainer(empty_variant_container) - empty_material_container = copy.deepcopy(empty_container) - empty_material_container._id = "empty_material" - empty_material_container.addMetaDataEntry("type", "material") - ContainerRegistry.getInstance().addContainer(empty_material_container) - empty_quality_container = copy.deepcopy(empty_container) - empty_quality_container._id = "empty_quality" - empty_quality_container.addMetaDataEntry("type", "quality") - ContainerRegistry.getInstance().addContainer(empty_quality_container) - - ContainerRegistry.getInstance().load() - - Preferences.getInstance().addPreference("cura/active_mode", "simple") - 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("mesh/scale_to_fit", True) - Preferences.getInstance().addPreference("mesh/scale_tiny_meshes", True) - Preferences.getInstance().setDefault("local_file/last_used_type", "text/x-gcode") - - Preferences.getInstance().setDefault("general/visible_settings", """ - machine_settings - resolution - layer_height - shell - wall_thickness - top_bottom_thickness - infill - infill_sparse_density - material - material_print_temperature - material_bed_temperature - material_diameter - material_flow - retraction_enable - speed - speed_print - speed_travel - travel - cooling - cool_fan_enabled - support - support_enable - support_type - support_roof_density - platform_adhesion - adhesion_type - brim_width - raft_airgap - layer_0_z_overlap - raft_surface_layers - meshfix - blackmagic - print_sequence - dual - experimental - """.replace("\n", ";").replace(" ", "")) - - JobQueue.getInstance().jobFinished.connect(self._onJobFinished) - - self.applicationShuttingDown.connect(self.saveSettings) - - 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)) - - ## Cura has multiple locations where instance containers need to be saved, so we need to handle this differently. - # - # Note that the AutoSave plugin also calls this method. - def saveSettings(self): - if not self._started: # Do not do saving during application start - return - - for instance in ContainerRegistry.getInstance().findInstanceContainers(): - if not instance.isDirty(): - continue - - try: - data = instance.serialize() - except NotImplementedError: - continue - except Exception: - Logger.logException("e", "An exception occurred when serializing container %s", instance.getId()) - continue - - file_name = urllib.parse.quote_plus(instance.getId()) + ".inst.cfg" - instance_type = instance.getMetaDataEntry("type") - path = None - if instance_type == "material": - path = Resources.getStoragePath(self.ResourceTypes.MaterialInstanceContainer, file_name) - elif instance_type == "quality": - path = Resources.getStoragePath(self.ResourceTypes.QualityInstanceContainer, file_name) - elif instance_type == "user": - path = Resources.getStoragePath(self.ResourceTypes.UserInstanceContainer, file_name) - elif instance_type == "variant": - path = Resources.getStoragePath(self.ResourceTypes.VariantInstanceContainer, file_name) - - if path: - with SaveFile(path, "wt", -1, "utf-8") as f: - f.write(data) - - for stack in ContainerRegistry.getInstance().findContainerStacks(): - if not stack.isDirty(): - continue - - try: - data = stack.serialize() - except NotImplementedError: - continue - except Exception: - Logger.logException("e", "An exception occurred when serializing container %s", instance.getId()) - continue - - file_name = urllib.parse.quote_plus(stack.getId()) + ".stack.cfg" - stack_type = stack.getMetaDataEntry("type", None) - path = None - if not stack_type or stack_type == "machine": - path = Resources.getStoragePath(self.ResourceTypes.MachineStack, file_name) - elif stack_type == "extruder": - path = Resources.getStoragePath(self.ResourceTypes.ExtruderStack, file_name) - if path: - with SaveFile(path, "wt", -1, "utf-8") as f: - f.write(data) - - - @pyqtSlot(result = QUrl) - def getDefaultPath(self): - return QUrl.fromLocalFile(os.path.expanduser("~/")) - - ## Handle loading of all plugin types (and the backend explicitly) - # \sa PluginRegistery - def _loadPlugins(self): - self._plugin_registry.addType("profile_reader", self._addProfileReader) - self._plugin_registry.addPluginLocation(os.path.join(QtApplication.getInstallPrefix(), "lib", "cura")) - if not hasattr(sys, "frozen"): - self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins")) - self._plugin_registry.loadPlugin("ConsoleLogger") - self._plugin_registry.loadPlugin("CuraEngineBackend") - - self._plugin_registry.loadPlugins() - - if self.getBackend() == None: - raise RuntimeError("Could not load the backend plugin!") - - self._plugins_loaded = True - - def addCommandLineOptions(self, parser): - super().addCommandLineOptions(parser) - parser.add_argument("file", nargs="*", help="Files to load after starting the application.") - parser.add_argument("--debug", dest="debug-mode", action="store_true", default=False, help="Enable detailed crash reports.") - - def run(self): - self._i18n_catalog = i18nCatalog("cura"); - - i18nCatalog.setTagReplacements({ - "filename": "font color=\"black\"", - "message": "font color=UM.Theme.colors.message_text;", - }) - - self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene...")) - - controller = self.getController() - - controller.setActiveView("SolidView") - controller.setCameraTool("CameraTool") - controller.setSelectionTool("SelectionTool") - - t = controller.getTool("TranslateTool") - if t: - t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.YAxis,ToolHandle.ZAxis]) - - Selection.selectionChanged.connect(self.onSelectionChanged) - - root = controller.getScene().getRoot() - self._platform = Platform(root) - - self._volume = BuildVolume.BuildVolume(root) - - self.getRenderer().setBackgroundColor(QColor(245, 245, 245)) - - self._physics = PlatformPhysics.PlatformPhysics(controller, self._volume) - - camera = Camera("3d", root) - camera.setPosition(Vector(-80, 250, 700)) - camera.setPerspective(True) - camera.lookAt(Vector(0, 0, 0)) - controller.getScene().setActiveCamera("3d") - - self.getController().getTool("CameraTool").setOrigin(Vector(0, 100, 0)) - - self._camera_animation = CameraAnimation.CameraAnimation() - self._camera_animation.setCameraTool(self.getController().getTool("CameraTool")) - - self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading interface...")) - - qmlRegisterSingletonType(MachineManagerModel.MachineManagerModel, "Cura", 1, 0, "MachineManager", - MachineManagerModel.createMachineManagerModel) - - self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml")) - self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles)) - self.initializeEngine() - - if self._engine.rootObjects: - self.closeSplash() - - for file in self.getCommandLineOption("file", []): - self._openFile(file) - for file_name in self._open_file_queue: #Open all the files that were queued up while plug-ins were loading. - self._openFile(file_name) - - self._started = True - - self.exec_() - - ## Handle Qt events - def event(self, event): - if event.type() == QEvent.FileOpen: - if self._plugins_loaded: - self._openFile(event.file()) - else: - self._open_file_queue.append(event.file()) - - return super().event(event) - - ## Get print information (duration / material used) - def getPrintInformation(self): - return self._print_information - - ## Registers objects for the QML engine to use. - # - # \param engine The QML engine. - def registerObjects(self, engine): - engine.rootContext().setContextProperty("Printer", self) - self._print_information = PrintInformation.PrintInformation() - engine.rootContext().setContextProperty("PrintInformation", self._print_information) - self._cura_actions = CuraActions.CuraActions(self) - engine.rootContext().setContextProperty("CuraActions", self._cura_actions) - - qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") - - qmlRegisterType(ExtrudersModel.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") - - qmlRegisterSingletonType(QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions") - - engine.rootContext().setContextProperty("ExtruderManager", ExtruderManager.ExtruderManager.getInstance()) - - for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles): - type_name = os.path.splitext(os.path.basename(path))[0] - if type_name in ("Cura", "Actions"): - continue - - qmlRegisterType(QUrl.fromLocalFile(path), "Cura", 1, 0, type_name) - - def onSelectionChanged(self): - if Selection.hasSelection(): - 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") - if Preferences.getInstance().getValue("view/center_on_select"): - self._center_after_select = True - else: - if self.getController().getActiveTool(): - self._previous_active_tool = self.getController().getActiveTool().getPluginId() - self.getController().setActiveTool(None) - else: - self._previous_active_tool = None - - def _onToolOperationStopped(self, event): - if self._center_after_select: - self._center_after_select = False - self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin()) - self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition()) - self._camera_animation.start() - - requestAddPrinter = pyqtSignal() - activityChanged = pyqtSignal() - sceneBoundingBoxChanged = pyqtSignal() - - @pyqtProperty(bool, notify = activityChanged) - def getPlatformActivity(self): - return self._platform_activity - - @pyqtProperty(str, notify = sceneBoundingBoxChanged) - def getSceneBoundingBoxString(self): - return self._i18n_catalog.i18nc("@info", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_bounding_box.width.item(), 'depth': self._scene_bounding_box.depth.item(), 'height' : self._scene_bounding_box.height.item()} - - def updatePlatformActivity(self, node = None): - count = 0 - scene_bounding_box = None - for node in DepthFirstIterator(self.getController().getScene().getRoot()): - if type(node) is not SceneNode or not node.getMeshData(): - continue - - count += 1 - if not scene_bounding_box: - scene_bounding_box = copy.deepcopy(node.getBoundingBox()) - else: - scene_bounding_box += node.getBoundingBox() - - if not scene_bounding_box: - scene_bounding_box = AxisAlignedBox() - - if repr(self._scene_bounding_box) != repr(scene_bounding_box): - self._scene_bounding_box = scene_bounding_box - self.sceneBoundingBoxChanged.emit() - - self._platform_activity = True if count > 0 else False - self.activityChanged.emit() - - # Remove all selected objects from the scene. - @pyqtSlot() - def deleteSelection(self): - if not self.getController().getToolsEnabled(): - return - - op = GroupedOperation() - nodes = Selection.getAllSelectedObjects() - for node in nodes: - op.addOperation(RemoveSceneNodeOperation(node)) - - op.push() - - pass - - ## Remove an object from the scene. - # Note that this only removes an object if it is selected. - @pyqtSlot("quint64") - def deleteObject(self, object_id): - if not self.getController().getToolsEnabled(): - return - - 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.getParent(): - group_node = node.getParent() - if not group_node.callDecoration("isGroup"): - op = RemoveSceneNodeOperation(node) - else: - while group_node.getParent().callDecoration("isGroup"): - group_node = group_node.getParent() - op = RemoveSceneNodeOperation(group_node) - op.push() - - ## Create a number of copies of existing object. - @pyqtSlot("quint64", int) - def multiplyObject(self, object_id, count): - node = self.getController().getScene().findObject(object_id) - - if not node and object_id != 0: # Workaround for tool handles overlapping the selected object - node = Selection.getSelectedObject(0) - - if node: - op = GroupedOperation() - for _ in range(count): - if node.getParent() and node.getParent().callDecoration("isGroup"): - new_node = copy.deepcopy(node.getParent()) #Copy the group node. - new_node.callDecoration("setConvexHull",None) - - op.addOperation(AddSceneNodeOperation(new_node,node.getParent().getParent())) - else: - new_node = copy.deepcopy(node) - new_node.callDecoration("setConvexHull", None) - op.addOperation(AddSceneNodeOperation(new_node, node.getParent())) - - op.push() - - ## Center object on platform. - @pyqtSlot("quint64") - def centerObject(self, object_id): - node = self.getController().getScene().findObject(object_id) - if not node and object_id != 0: # Workaround for tool handles overlapping the selected object - node = Selection.getSelectedObject(0) - - if not node: - return - - if node.getParent() and node.getParent().callDecoration("isGroup"): - node = node.getParent() - - if node: - op = SetTransformOperation(node, Vector()) - op.push() - - ## Delete all nodes containing mesh data in the scene. - @pyqtSlot() - def deleteAll(self): - if not self.getController().getToolsEnabled(): - return - - nodes = [] - for node in DepthFirstIterator(self.getController().getScene().getRoot()): - if type(node) is not 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) - nodes.append(node) - if nodes: - op = GroupedOperation() - - for node in nodes: - op.addOperation(RemoveSceneNodeOperation(node)) - - op.push() - - ## Reset all translation on nodes with mesh data. - @pyqtSlot() - def resetAllTranslation(self): - nodes = [] - for node in DepthFirstIterator(self.getController().getScene().getRoot()): - if type(node) is not 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) - - nodes.append(node) - - if nodes: - op = GroupedOperation() - for node in nodes: - node.removeDecorator(ZOffsetDecorator.ZOffsetDecorator) - op.addOperation(SetTransformOperation(node, Vector(0,0,0))) - - op.push() - - ## Reset all transformations on nodes with mesh data. - @pyqtSlot() - def resetAll(self): - nodes = [] - for node in DepthFirstIterator(self.getController().getScene().getRoot()): - if type(node) is not 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) - nodes.append(node) - - if nodes: - op = GroupedOperation() - - for node in nodes: - # Ensure that the object is above the build platform - node.removeDecorator(ZOffsetDecorator.ZOffsetDecorator) - op.addOperation(SetTransformOperation(node, Vector(0,0,0), Quaternion(), Vector(1, 1, 1))) - - op.push() - - ## Reload all mesh data on the screen from file. - @pyqtSlot() - def reloadAll(self): - nodes = [] - for node in DepthFirstIterator(self.getController().getScene().getRoot()): - if type(node) is not SceneNode or not node.getMeshData(): - continue - - nodes.append(node) - - if not nodes: - return - - for node in nodes: - if not node.getMeshData(): - continue - - file_name = node.getMeshData().getFileName() - if file_name: - job = ReadMeshJob(file_name) - job._node = node - job.finished.connect(self._reloadMeshFinished) - job.start() - - ## Get logging data of the backend engine - # \returns \type{string} Logging data - @pyqtSlot(result = str) - def getEngineLog(self): - log = "" - - for entry in self.getBackend().getLog(): - log += entry.decode() - - 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(";") - - @pyqtSlot() - def mergeSelected(self): - self.groupSelected() - try: - group_node = Selection.getAllSelectedObjects()[0] - except Exception as e: - Logger.log("d", "mergeSelected: Exception:", e) - return - multi_material_decorator = MultiMaterialDecorator.MultiMaterialDecorator() - group_node.addDecorator(multi_material_decorator) - # Reset the position of each node - for node in group_node.getChildren(): - new_position = node.getMeshData().getCenterPosition() - new_position = new_position.scale(node.getScale()) - node.setPosition(new_position) - - # Use the previously found center of the group bounding box as the new location of the group - group_node.setPosition(group_node.getBoundingBox().center) - - @pyqtSlot() - def groupSelected(self): - # Create a group-node - group_node = SceneNode() - group_decorator = GroupDecorator() - group_node.addDecorator(group_decorator) - group_node.setParent(self.getController().getScene().getRoot()) - group_node.setSelectable(True) - center = Selection.getSelectionCenter() - group_node.setPosition(center) - group_node.setCenterPosition(center) - - # Move selected nodes into the group-node - Selection.applyOperation(SetParentOperation, group_node) - - # Deselect individual nodes and select the group-node instead - for node in group_node.getChildren(): - Selection.remove(node) - Selection.add(group_node) - - @pyqtSlot() - def ungroupSelected(self): - selected_objects = Selection.getAllSelectedObjects().copy() - for node in selected_objects: - if node.callDecoration("isGroup"): - op = GroupedOperation() - - group_parent = node.getParent() - children = node.getChildren().copy() - for child in children: - # Set the parent of the children to the parent of the group-node - op.addOperation(SetParentOperation(child, group_parent)) - - # Add all individual nodes to the selection - Selection.add(child) - child.callDecoration("setConvexHull", None) - - op.push() - # Note: The group removes itself from the scene once all its children have left it, - # see GroupDecorator._onChildrenChanged - - def _createSplashScreen(self): - return CuraSplashScreen.CuraSplashScreen() - - def _onActiveMachineChanged(self): - pass - - fileLoaded = pyqtSignal(str) - - def _onFileLoaded(self, job): - node = job.getResult() - if node != None: - self.fileLoaded.emit(job.getFileName()) - node.setSelectable(True) - node.setName(os.path.basename(job.getFileName())) - op = AddSceneNodeOperation(node, self.getController().getScene().getRoot()) - op.push() - - self.getController().getScene().sceneChanged.emit(node) #Force scene change. - - def _onJobFinished(self, job): - if type(job) is not ReadMeshJob or not job.getResult(): - 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() - - def _reloadMeshFinished(self, job): - # TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh! - job._node.setMeshData(job.getResult().getMeshData()) - - def _openFile(self, file): - job = ReadMeshJob(os.path.abspath(file)) - job.finished.connect(self._onFileLoaded) - job.start() - - def _addProfileReader(self, profile_reader): - # TODO: Add the profile reader to the list of plug-ins that can be used when importing profiles. - pass