Merge remote-tracking branch 'origin/main' into CURA-11137_update_pyqt6

This commit is contained in:
Remco Burema 2023-12-13 10:56:01 +01:00
commit 0aa7e74fe5
6 changed files with 45 additions and 8 deletions

View File

@ -179,6 +179,7 @@ class CuraApplication(QtApplication):
self._use_single_instance = False self._use_single_instance = False
self._single_instance = None self._single_instance = None
self._open_project_mode: Optional[str] = None
self._cura_formula_functions = None # type: Optional[CuraFormulaFunctions] self._cura_formula_functions = None # type: Optional[CuraFormulaFunctions]
@ -1845,7 +1846,7 @@ class CuraApplication(QtApplication):
Logger.log("i", "Attempting to read file %s", file.toString()) Logger.log("i", "Attempting to read file %s", file.toString())
if not file.isValid(): if not file.isValid():
return return
self._open_project_mode = project_mode
scene = self.getController().getScene() scene = self.getController().getScene()
for node in DepthFirstIterator(scene.getRoot()): for node in DepthFirstIterator(scene.getRoot()):
@ -1855,16 +1856,16 @@ class CuraApplication(QtApplication):
is_project_file = self.checkIsValidProjectFile(file) is_project_file = self.checkIsValidProjectFile(file)
if project_mode is None: if self._open_project_mode is None:
project_mode = self.getPreferences().getValue("cura/choice_on_open_project") self._open_project_mode = self.getPreferences().getValue("cura/choice_on_open_project")
if is_project_file and project_mode == "open_as_project": if is_project_file and self._open_project_mode == "open_as_project":
# open as project immediately without presenting a dialog # open as project immediately without presenting a dialog
workspace_handler = self.getWorkspaceFileHandler() workspace_handler = self.getWorkspaceFileHandler()
workspace_handler.readLocalFile(file, add_to_recent_files_hint = add_to_recent_files) workspace_handler.readLocalFile(file, add_to_recent_files_hint = add_to_recent_files)
return return
if is_project_file and project_mode == "always_ask": if is_project_file and self._open_project_mode == "always_ask":
# present a dialog asking to open as project or import models # present a dialog asking to open as project or import models
self.callLater(self.openProjectFile.emit, file, add_to_recent_files) self.callLater(self.openProjectFile.emit, file, add_to_recent_files)
return return
@ -1999,8 +2000,11 @@ class CuraApplication(QtApplication):
center_y = 0 center_y = 0
node.translate(Vector(0, center_y, 0)) node.translate(Vector(0, center_y, 0))
nodes_to_arrange.append(node) nodes_to_arrange.append(node)
# If the file is a project,and models are to be loaded from a that project,
# models inside file should be arranged in buildplate.
elif self._open_project_mode == "open_as_model":
nodes_to_arrange.append(node)
# This node is deep copied from some other node which already has a BuildPlateDecorator, but the deepcopy # This node is deep copied from some other node which already has a BuildPlateDecorator, but the deepcopy
# of BuildPlateDecorator produces one that's associated with build plate -1. So, here we need to check if # of BuildPlateDecorator produces one that's associated with build plate -1. So, here we need to check if

View File

@ -1,5 +1,6 @@
# Copyright (c) 2019 Ultimaker B.V. # Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import math
import numpy import numpy
from typing import Optional, cast from typing import Optional, cast
@ -186,6 +187,11 @@ class LayerPolygon:
def types(self): def types(self):
return self._types return self._types
@property
def lineLengths(self):
data_array = numpy.array(self._data)
return numpy.linalg.norm(data_array[1:] - data_array[:-1], axis=1)
@property @property
def data(self): def data(self):
return self._data return self._data

View File

@ -49,7 +49,7 @@ class Snapshot:
""" """
if node is None: if node is None:
root = Application.getInstance().getController().getScene().getRoot() node = Application.getInstance().getController().getScene().getRoot()
# the direction the camera is looking at to create the isometric view # the direction the camera is looking at to create the isometric view
iso_view_dir = Vector(-1, -1, -1).normalized() iso_view_dir = Vector(-1, -1, -1).normalized()

View File

@ -78,6 +78,8 @@ class SimulationView(CuraView):
self._minimum_path_num = 0 self._minimum_path_num = 0
self.currentLayerNumChanged.connect(self._onCurrentLayerNumChanged) self.currentLayerNumChanged.connect(self._onCurrentLayerNumChanged)
self._current_feedrates = {}
self._lengths_of_polyline ={}
self._busy = False self._busy = False
self._simulation_running = False self._simulation_running = False
@ -400,6 +402,15 @@ class SimulationView(CuraView):
def getMaxFeedrate(self) -> float: def getMaxFeedrate(self) -> float:
return self._max_feedrate return self._max_feedrate
def getSimulationTime(self, currentIndex) -> float:
try:
return (self._lengths_of_polyline[self._current_layer_num][currentIndex] / self._current_feedrates[self._current_layer_num][currentIndex])[0]
except:
# In case of change in layers, currentIndex comes one more than the items in the lengths_of_polyline
# We give 1 second time for layer change
return 1.0
def getMinThickness(self) -> float: def getMinThickness(self) -> float:
if abs(self._min_thickness - sys.float_info.max) < 10: # Some lenience due to floating point rounding. if abs(self._min_thickness - sys.float_info.max) < 10: # Some lenience due to floating point rounding.
return 0.0 # If it's still max-float, there are no measurements. Use 0 then. return 0.0 # If it's still max-float, there are no measurements. Use 0 then.
@ -524,8 +535,10 @@ class SimulationView(CuraView):
visible_indicies_with_extrusion = numpy.where(numpy.isin(polyline.types, visible_line_types_with_extrusion))[0] visible_indicies_with_extrusion = numpy.where(numpy.isin(polyline.types, visible_line_types_with_extrusion))[0]
if visible_indices.size == 0: # No items to take maximum or minimum of. if visible_indices.size == 0: # No items to take maximum or minimum of.
continue continue
self._lengths_of_polyline[layer_index] = polyline.lineLengths
visible_feedrates = numpy.take(polyline.lineFeedrates, visible_indices) visible_feedrates = numpy.take(polyline.lineFeedrates, visible_indices)
visible_feedrates_with_extrusion = numpy.take(polyline.lineFeedrates, visible_indicies_with_extrusion) visible_feedrates_with_extrusion = numpy.take(polyline.lineFeedrates, visible_indicies_with_extrusion)
self._current_feedrates[layer_index] = polyline.lineFeedrates
visible_linewidths = numpy.take(polyline.lineWidths, visible_indices) visible_linewidths = numpy.take(polyline.lineWidths, visible_indices)
visible_linewidths_with_extrusion = numpy.take(polyline.lineWidths, visible_indicies_with_extrusion) visible_linewidths_with_extrusion = numpy.take(polyline.lineWidths, visible_indicies_with_extrusion)
visible_thicknesses = numpy.take(polyline.lineThicknesses, visible_indices) visible_thicknesses = numpy.take(polyline.lineThicknesses, visible_indices)

View File

@ -136,7 +136,7 @@ Item
Timer Timer
{ {
id: simulationTimer id: simulationTimer
interval: 100 interval: UM.SimulationView.simulationTime
running: false running: false
repeat: true repeat: true
onTriggered: onTriggered:

View File

@ -2,6 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import numpy
from PyQt6.QtCore import QObject, pyqtSignal, pyqtProperty from PyQt6.QtCore import QObject, pyqtSignal, pyqtProperty
from UM.FlameProfiler import pyqtSlot from UM.FlameProfiler import pyqtSlot
from UM.Application import Application from UM.Application import Application
@ -11,6 +12,11 @@ if TYPE_CHECKING:
class SimulationViewProxy(QObject): class SimulationViewProxy(QObject):
S_TO_MS = 1000
SPEED_OF_SIMULATION = 10
FACTOR = S_TO_MS/SPEED_OF_SIMULATION
def __init__(self, simulation_view: "SimulationView", parent=None) -> None: def __init__(self, simulation_view: "SimulationView", parent=None) -> None:
super().__init__(parent) super().__init__(parent)
self._simulation_view = simulation_view self._simulation_view = simulation_view
@ -54,6 +60,14 @@ class SimulationViewProxy(QObject):
def currentPath(self): def currentPath(self):
return self._simulation_view.getCurrentPath() return self._simulation_view.getCurrentPath()
@pyqtProperty(int, notify=currentPathChanged)
def simulationTime(self):
# Extracts the currents paths simulation time (in seconds) for the current path from the dict of simulation time of the current layer.
# We multiply the time with 100 to make it to ms from s.(Should be 1000 in real time). This scaling makes the simulation time 10x faster than the real time.
simulationTimeOfpath = self._simulation_view.getSimulationTime(self._simulation_view.getCurrentPath()) * SimulationViewProxy.FACTOR
# Since the timer cannot process time less than 1 ms, we put a lower limit here
return int(max(1, simulationTimeOfpath))
@pyqtProperty(int, notify=currentPathChanged) @pyqtProperty(int, notify=currentPathChanged)
def minimumPath(self): def minimumPath(self):
return self._simulation_view.getMinimumPath() return self._simulation_view.getMinimumPath()