1# Copyright (c) 2018 Ultimaker B.V.
2# Cura is released under the terms of the LGPLv3 or higher.
3from typing import TYPE_CHECKING
4
5from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
6from UM.FlameProfiler import pyqtSlot
7from UM.Application import Application
8
9if TYPE_CHECKING:
10    from .SimulationView import SimulationView
11
12
13class SimulationViewProxy(QObject):
14    def __init__(self, simulation_view: "SimulationView", parent=None) -> None:
15        super().__init__(parent)
16        self._simulation_view = simulation_view
17        self._current_layer = 0
18        self._controller = Application.getInstance().getController()
19        self._controller.activeViewChanged.connect(self._onActiveViewChanged)
20        self.is_simulationView_selected = False
21        self._onActiveViewChanged()
22
23    currentLayerChanged = pyqtSignal()
24    currentPathChanged = pyqtSignal()
25    maxLayersChanged = pyqtSignal()
26    maxPathsChanged = pyqtSignal()
27    activityChanged = pyqtSignal()
28    globalStackChanged = pyqtSignal()
29    preferencesChanged = pyqtSignal()
30    busyChanged = pyqtSignal()
31
32    @pyqtProperty(bool, notify=activityChanged)
33    def layerActivity(self):
34        return self._simulation_view.getActivity()
35
36    @pyqtProperty(int, notify=maxLayersChanged)
37    def numLayers(self):
38        return self._simulation_view.getMaxLayers()
39
40    @pyqtProperty(int, notify=currentLayerChanged)
41    def currentLayer(self):
42        return self._simulation_view.getCurrentLayer()
43
44    @pyqtProperty(int, notify=currentLayerChanged)
45    def minimumLayer(self):
46        return self._simulation_view.getMinimumLayer()
47
48    @pyqtProperty(int, notify=maxPathsChanged)
49    def numPaths(self):
50        return self._simulation_view.getMaxPaths()
51
52    @pyqtProperty(int, notify=currentPathChanged)
53    def currentPath(self):
54        return self._simulation_view.getCurrentPath()
55
56    @pyqtProperty(int, notify=currentPathChanged)
57    def minimumPath(self):
58        return self._simulation_view.getMinimumPath()
59
60    @pyqtProperty(bool, notify=busyChanged)
61    def busy(self):
62        return self._simulation_view.isBusy()
63
64    @pyqtProperty(bool, notify=preferencesChanged)
65    def compatibilityMode(self):
66        return self._simulation_view.getCompatibilityMode()
67
68    @pyqtProperty(int, notify=globalStackChanged)
69    def extruderCount(self):
70        return self._simulation_view.getExtruderCount()
71
72    @pyqtSlot(int)
73    def setCurrentLayer(self, layer_num):
74        self._simulation_view.setLayer(layer_num)
75
76    @pyqtSlot(int)
77    def setMinimumLayer(self, layer_num):
78        self._simulation_view.setMinimumLayer(layer_num)
79
80    @pyqtSlot(int)
81    def setCurrentPath(self, path_num):
82        self._simulation_view.setPath(path_num)
83
84    @pyqtSlot(int)
85    def setMinimumPath(self, path_num):
86        self._simulation_view.setMinimumPath(path_num)
87
88    @pyqtSlot(int)
89    def setSimulationViewType(self, layer_view_type):
90        self._simulation_view.setSimulationViewType(layer_view_type)
91
92    @pyqtSlot(result=int)
93    def getSimulationViewType(self):
94        return self._simulation_view.getSimulationViewType()
95
96    @pyqtSlot(bool)
97    def setSimulationRunning(self, running):
98        self._simulation_view.setSimulationRunning(running)
99
100    @pyqtSlot(result=bool)
101    def getSimulationRunning(self):
102        return self._simulation_view.isSimulationRunning()
103
104    @pyqtSlot(result=float)
105    def getMinFeedrate(self):
106        return self._simulation_view.getMinFeedrate()
107
108    @pyqtSlot(result=float)
109    def getMaxFeedrate(self):
110        return self._simulation_view.getMaxFeedrate()
111
112    @pyqtSlot(result=float)
113    def getMinThickness(self):
114        return self._simulation_view.getMinThickness()
115
116    @pyqtSlot(result=float)
117    def getMaxThickness(self):
118        return self._simulation_view.getMaxThickness()
119
120    # Opacity 0..1
121    @pyqtSlot(int, float)
122    def setExtruderOpacity(self, extruder_nr, opacity):
123        self._simulation_view.setExtruderOpacity(extruder_nr, opacity)
124
125    @pyqtSlot(int)
126    def setShowTravelMoves(self, show):
127        self._simulation_view.setShowTravelMoves(show)
128
129    @pyqtSlot(int)
130    def setShowHelpers(self, show):
131        self._simulation_view.setShowHelpers(show)
132
133    @pyqtSlot(int)
134    def setShowSkin(self, show):
135        self._simulation_view.setShowSkin(show)
136
137    @pyqtSlot(int)
138    def setShowInfill(self, show):
139        self._simulation_view.setShowInfill(show)
140
141    def _layerActivityChanged(self):
142        self.activityChanged.emit()
143
144    def _onLayerChanged(self):
145        self.currentLayerChanged.emit()
146        self._layerActivityChanged()
147
148    def _onPathChanged(self):
149        self.currentPathChanged.emit()
150        self._layerActivityChanged()
151
152        scene = Application.getInstance().getController().getScene()
153        scene.sceneChanged.emit(scene.getRoot())
154
155    def _onMaxLayersChanged(self):
156        self.maxLayersChanged.emit()
157
158    def _onMaxPathsChanged(self):
159        self.maxPathsChanged.emit()
160
161    def _onBusyChanged(self):
162        self.busyChanged.emit()
163
164    def _onActivityChanged(self):
165        self.activityChanged.emit()
166
167    def _onGlobalStackChanged(self):
168        self.globalStackChanged.emit()
169
170    def _onPreferencesChanged(self):
171        self.preferencesChanged.emit()
172
173    def _onActiveViewChanged(self):
174        active_view = self._controller.getActiveView()
175        if active_view == self._simulation_view:
176            self._simulation_view.currentLayerNumChanged.connect(self._onLayerChanged)
177            self._simulation_view.currentPathNumChanged.connect(self._onPathChanged)
178            self._simulation_view.maxLayersChanged.connect(self._onMaxLayersChanged)
179            self._simulation_view.maxPathsChanged.connect(self._onMaxPathsChanged)
180            self._simulation_view.busyChanged.connect(self._onBusyChanged)
181            self._simulation_view.activityChanged.connect(self._onActivityChanged)
182            self._simulation_view.globalStackChanged.connect(self._onGlobalStackChanged)
183            self._simulation_view.preferencesChanged.connect(self._onPreferencesChanged)
184            self.is_simulationView_selected = True
185        elif self.is_simulationView_selected:
186            # Disconnect all of em again.
187            self.is_simulationView_selected = False
188            self._simulation_view.currentLayerNumChanged.disconnect(self._onLayerChanged)
189            self._simulation_view.currentPathNumChanged.disconnect(self._onPathChanged)
190            self._simulation_view.maxLayersChanged.disconnect(self._onMaxLayersChanged)
191            self._simulation_view.maxPathsChanged.disconnect(self._onMaxPathsChanged)
192            self._simulation_view.busyChanged.disconnect(self._onBusyChanged)
193            self._simulation_view.activityChanged.disconnect(self._onActivityChanged)
194            self._simulation_view.globalStackChanged.disconnect(self._onGlobalStackChanged)
195            self._simulation_view.preferencesChanged.disconnect(self._onPreferencesChanged)
196
197