WIP: Make application initialization and start up more clear

- Create SingleInstance class to handling single instance stuff.
 - Instead of calling getInstance() everywhere, initialize each object
   explicitly in order when application starts and getInstance()s do not
   create instances any more and they merely return the created
   instances.
 - Only set initial values in construtor functions __init__(). Move the
   initialization of context-aware (i.e. things that depend on other
   things) to separate functions.
 - Split application creation and initialziation into several steps and
   them should be called explicitly in the correct order.
This commit is contained in:
Lipu Fei 2018-04-30 16:47:14 +02:00
parent c8f73d303e
commit 051dd7a6e9
14 changed files with 521 additions and 471 deletions

View file

@ -1,14 +1,16 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import math
from typing import List, Optional
import numpy
from PyQt5.QtCore import QTimer
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Settings.ExtruderManager import ExtruderManager
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from UM.Scene.Platform import Platform
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.Scene.SceneNode import SceneNode
from UM.Application import Application
from UM.Resources import Resources
from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Math.Vector import Vector
@ -18,16 +20,14 @@ from UM.Math.AxisAlignedBox import AxisAlignedBox
from UM.Math.Polygon import Polygon
from UM.Message import Message
from UM.Signal import Signal
from PyQt5.QtCore import QTimer
from UM.View.RenderBatch import RenderBatch
from UM.View.GL.OpenGL import OpenGL
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Settings.ExtruderManager import ExtruderManager
catalog = i18nCatalog("cura")
import numpy
import math
from typing import List, Optional
# Setting for clearance around the prime
PRIME_CLEARANCE = 6.5
@ -36,8 +36,10 @@ PRIME_CLEARANCE = 6.5
class BuildVolume(SceneNode):
raftThicknessChanged = Signal()
def __init__(self, parent = None):
def __init__(self, application, parent = None):
super().__init__(parent)
self._application = application
self._machine_manager = self._application.getMachineManager()
self._volume_outline_color = None
self._x_axis_color = None
@ -80,14 +82,14 @@ class BuildVolume(SceneNode):
" with printed models."), title = catalog.i18nc("@info:title", "Build Volume"))
self._global_container_stack = None
Application.getInstance().globalContainerStackChanged.connect(self._onStackChanged)
self._application.globalContainerStackChanged.connect(self._onStackChanged)
self._onStackChanged()
self._engine_ready = False
Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
self._application.engineCreatedSignal.connect(self._onEngineCreated)
self._has_errors = False
Application.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged)
self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged)
#Objects loaded at the moment. We are connected to the property changed events of these objects.
self._scene_objects = set()
@ -105,14 +107,14 @@ class BuildVolume(SceneNode):
# Must be after setting _build_volume_message, apparently that is used in getMachineManager.
# activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality.
# Therefore this works.
Application.getInstance().getMachineManager().activeQualityChanged.connect(self._onStackChanged)
self._machine_manager.activeQualityChanged.connect(self._onStackChanged)
# This should also ways work, and it is semantically more correct,
# but it does not update the disallowed areas after material change
Application.getInstance().getMachineManager().activeStackChanged.connect(self._onStackChanged)
self._machine_manager.activeStackChanged.connect(self._onStackChanged)
# Enable and disable extruder
Application.getInstance().getMachineManager().extruderChanged.connect(self.updateNodeBoundaryCheck)
self._machine_manager.extruderChanged.connect(self.updateNodeBoundaryCheck)
# list of settings which were updated
self._changed_settings_since_last_rebuild = []
@ -122,7 +124,7 @@ class BuildVolume(SceneNode):
self._scene_change_timer.start()
def _onSceneChangeTimerFinished(self):
root = Application.getInstance().getController().getScene().getRoot()
root = self._application.getController().getScene().getRoot()
new_scene_objects = set(node for node in BreadthFirstIterator(root) if node.callDecoration("isSliceable"))
if new_scene_objects != self._scene_objects:
for node in new_scene_objects - self._scene_objects: #Nodes that were added to the scene.
@ -181,7 +183,7 @@ class BuildVolume(SceneNode):
if not self._shader:
self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader"))
self._grid_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "grid.shader"))
theme = Application.getInstance().getTheme()
theme = self._application.getTheme()
self._grid_shader.setUniformValue("u_plateColor", Color(*theme.getColor("buildplate").getRgb()))
self._grid_shader.setUniformValue("u_gridColor0", Color(*theme.getColor("buildplate_grid").getRgb()))
self._grid_shader.setUniformValue("u_gridColor1", Color(*theme.getColor("buildplate_grid_minor").getRgb()))
@ -201,7 +203,7 @@ class BuildVolume(SceneNode):
## For every sliceable node, update node._outside_buildarea
#
def updateNodeBoundaryCheck(self):
root = Application.getInstance().getController().getScene().getRoot()
root = self._application.getController().getScene().getRoot()
nodes = list(BreadthFirstIterator(root))
group_nodes = []
@ -289,11 +291,11 @@ class BuildVolume(SceneNode):
if not self._width or not self._height or not self._depth:
return
if not Application.getInstance()._engine:
if not self._application._qml_engine:
return
if not self._volume_outline_color:
theme = Application.getInstance().getTheme()
theme = self._application.getTheme()
self._volume_outline_color = Color(*theme.getColor("volume_outline").getRgb())
self._x_axis_color = Color(*theme.getColor("x_axis").getRgb())
self._y_axis_color = Color(*theme.getColor("y_axis").getRgb())
@ -465,7 +467,7 @@ class BuildVolume(SceneNode):
maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)
)
Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds
self.updateNodeBoundaryCheck()
@ -518,7 +520,7 @@ class BuildVolume(SceneNode):
for extruder in extruders:
extruder.propertyChanged.disconnect(self._onSettingPropertyChanged)
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
self._global_container_stack = self._application.getGlobalContainerStack()
if self._global_container_stack:
self._global_container_stack.propertyChanged.connect(self._onSettingPropertyChanged)
@ -561,7 +563,7 @@ class BuildVolume(SceneNode):
if setting_key == "print_sequence":
machine_height = self._global_container_stack.getProperty("machine_height", "value")
if Application.getInstance().getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1:
if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1:
self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height)
if self._height < machine_height:
self._build_volume_message.show()