mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-14 18:27:51 -06:00
Make a snapshot on slice instead of write.
In some cases, UFP-writing is going to be done when the OpenGL-context is off the main window. This doesn't work. That unfortunately also goes for this commit, but it's a work in progress.
This commit is contained in:
parent
cdedb56a9a
commit
4fc0612806
2 changed files with 45 additions and 34 deletions
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2021 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 argparse #To run the engine in debug mode if the front-end is in debug mode.
|
import argparse #To run the engine in debug mode if the front-end is in debug mode.
|
||||||
|
@ -9,6 +9,8 @@ import sys
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Any, cast, Dict, List, Optional, Set, TYPE_CHECKING
|
from typing import Any, cast, Dict, List, Optional, Set, TYPE_CHECKING
|
||||||
|
|
||||||
|
from PyQt5.QtGui import QImage
|
||||||
|
|
||||||
from UM.Backend.Backend import Backend, BackendState
|
from UM.Backend.Backend import Backend, BackendState
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from UM.Signal import Signal
|
from UM.Signal import Signal
|
||||||
|
@ -24,6 +26,8 @@ from UM.Tool import Tool #For typing.
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.Settings.ExtruderManager import ExtruderManager
|
from cura.Settings.ExtruderManager import ExtruderManager
|
||||||
|
from cura.Snapshot import Snapshot
|
||||||
|
from cura.Utils.Threading import call_on_qt_thread
|
||||||
from .ProcessSlicedLayersJob import ProcessSlicedLayersJob
|
from .ProcessSlicedLayersJob import ProcessSlicedLayersJob
|
||||||
from .StartSliceJob import StartSliceJob, StartJobResult
|
from .StartSliceJob import StartSliceJob, StartJobResult
|
||||||
|
|
||||||
|
@ -153,6 +157,8 @@ class CuraEngineBackend(QObject, Backend):
|
||||||
self.determineAutoSlicing()
|
self.determineAutoSlicing()
|
||||||
application.getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
|
application.getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
|
||||||
|
|
||||||
|
self._snapshot = None #type: Optional[QImage]
|
||||||
|
|
||||||
application.initializationFinished.connect(self.initialize)
|
application.initializationFinished.connect(self.initialize)
|
||||||
|
|
||||||
def initialize(self) -> None:
|
def initialize(self) -> None:
|
||||||
|
@ -241,9 +247,24 @@ class CuraEngineBackend(QObject, Backend):
|
||||||
self.markSliceAll()
|
self.markSliceAll()
|
||||||
self.slice()
|
self.slice()
|
||||||
|
|
||||||
|
@call_on_qt_thread # must be called from the main thread because of OpenGL
|
||||||
|
def _createSnapshot(self) -> None:
|
||||||
|
self._snapshot = None
|
||||||
|
Logger.log("i", "Creating thumbnail image (just before slice)...")
|
||||||
|
try:
|
||||||
|
self._snapshot = Snapshot.snapshot(width = 300, height = 300)
|
||||||
|
except:
|
||||||
|
Logger.logException("w", "Failed to create snapshot image")
|
||||||
|
self._snapshot = None # Failing to create thumbnail should not fail creation of UFP
|
||||||
|
|
||||||
|
def getLatestSnapShot(self) -> Optional[QImage]:
|
||||||
|
return self._snapshot
|
||||||
|
|
||||||
def slice(self) -> None:
|
def slice(self) -> None:
|
||||||
"""Perform a slice of the scene."""
|
"""Perform a slice of the scene."""
|
||||||
|
|
||||||
|
self._createSnapshot()
|
||||||
|
|
||||||
Logger.log("i", "Starting to slice...")
|
Logger.log("i", "Starting to slice...")
|
||||||
self._slice_start_time = time()
|
self._slice_start_time = time()
|
||||||
if not self._build_plates_to_be_sliced:
|
if not self._build_plates_to_be_sliced:
|
||||||
|
@ -331,7 +352,6 @@ class CuraEngineBackend(QObject, Backend):
|
||||||
|
|
||||||
def _onStartSliceCompleted(self, job: StartSliceJob) -> None:
|
def _onStartSliceCompleted(self, job: StartSliceJob) -> None:
|
||||||
"""Event handler to call when the job to initiate the slicing process is
|
"""Event handler to call when the job to initiate the slicing process is
|
||||||
|
|
||||||
completed.
|
completed.
|
||||||
|
|
||||||
When the start slice job is successfully completed, it will be happily
|
When the start slice job is successfully completed, it will be happily
|
||||||
|
|
|
@ -7,19 +7,20 @@ from Charon.VirtualFile import VirtualFile # To open UFP files.
|
||||||
from Charon.OpenMode import OpenMode # To indicate that we want to write to UFP files.
|
from Charon.OpenMode import OpenMode # To indicate that we want to write to UFP files.
|
||||||
from io import StringIO # For converting g-code to bytes.
|
from io import StringIO # For converting g-code to bytes.
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QBuffer
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Mesh.MeshWriter import MeshWriter # The writer we need to implement.
|
from UM.Mesh.MeshWriter import MeshWriter # The writer we need to implement.
|
||||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||||
from UM.PluginRegistry import PluginRegistry # To get the g-code writer.
|
from UM.PluginRegistry import PluginRegistry # To get the g-code writer.
|
||||||
from PyQt5.QtCore import QBuffer
|
|
||||||
|
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from cura.Snapshot import Snapshot
|
|
||||||
from cura.Utils.Threading import call_on_qt_thread
|
from cura.Utils.Threading import call_on_qt_thread
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from plugins.CuraEngineBackend.CuraEngineBackend import CuraEngineBackend
|
||||||
|
|
||||||
METADATA_OBJECTS_PATH = "metadata/objects"
|
METADATA_OBJECTS_PATH = "metadata/objects"
|
||||||
|
|
||||||
|
@ -38,17 +39,6 @@ class UFPWriter(MeshWriter):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self._snapshot = None
|
|
||||||
|
|
||||||
def _createSnapshot(self, *args):
|
|
||||||
# must be called from the main thread because of OpenGL
|
|
||||||
Logger.log("d", "Creating thumbnail image...")
|
|
||||||
try:
|
|
||||||
self._snapshot = Snapshot.snapshot(width = 300, height = 300)
|
|
||||||
except Exception:
|
|
||||||
Logger.logException("w", "Failed to create snapshot image")
|
|
||||||
self._snapshot = None # Failing to create thumbnail should not fail creation of UFP
|
|
||||||
|
|
||||||
# This needs to be called on the main thread (Qt thread) because the serialization of material containers can
|
# This needs to be called on the main thread (Qt thread) because the serialization of material containers can
|
||||||
# trigger loading other containers. Because those loaded containers are QtObjects, they must be created on the
|
# trigger loading other containers. Because those loaded containers are QtObjects, they must be created on the
|
||||||
# Qt thread. The File read/write operations right now are executed on separated threads because they are scheduled
|
# Qt thread. The File read/write operations right now are executed on separated threads because they are scheduled
|
||||||
|
@ -72,25 +62,26 @@ class UFPWriter(MeshWriter):
|
||||||
gcode.write(gcode_textio.getvalue().encode("UTF-8"))
|
gcode.write(gcode_textio.getvalue().encode("UTF-8"))
|
||||||
archive.addRelation(virtual_path = "/3D/model.gcode", relation_type = "http://schemas.ultimaker.org/package/2018/relationships/gcode")
|
archive.addRelation(virtual_path = "/3D/model.gcode", relation_type = "http://schemas.ultimaker.org/package/2018/relationships/gcode")
|
||||||
|
|
||||||
# TODO temporarily commented out, as is causes a crash whenever the UFPWriter is called outside of the main thread
|
snapshot = None
|
||||||
# self._createSnapshot()
|
backend = CuraApplication.getInstance().getBackend()
|
||||||
#
|
if isinstance(backend, CuraEngineBackend):
|
||||||
# # Store the thumbnail.
|
snapshot = backend.getLatestSnapshot()
|
||||||
# if self._snapshot:
|
|
||||||
# archive.addContentType(extension = "png", mime_type = "image/png")
|
# Store the thumbnail.
|
||||||
# thumbnail = archive.getStream("/Metadata/thumbnail.png")
|
if snapshot:
|
||||||
#
|
archive.addContentType(extension = "png", mime_type = "image/png")
|
||||||
# thumbnail_buffer = QBuffer()
|
thumbnail = archive.getStream("/Metadata/thumbnail.png")
|
||||||
# thumbnail_buffer.open(QBuffer.ReadWrite)
|
|
||||||
# thumbnail_image = self._snapshot
|
thumbnail_buffer = QBuffer()
|
||||||
# thumbnail_image.save(thumbnail_buffer, "PNG")
|
thumbnail_buffer.open(QBuffer.ReadWrite)
|
||||||
#
|
snapshot.save(thumbnail_buffer, "PNG")
|
||||||
# thumbnail.write(thumbnail_buffer.data())
|
|
||||||
# archive.addRelation(virtual_path = "/Metadata/thumbnail.png",
|
thumbnail.write(thumbnail_buffer.data())
|
||||||
# relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail",
|
archive.addRelation(virtual_path = "/Metadata/thumbnail.png",
|
||||||
# origin = "/3D/model.gcode")
|
relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail",
|
||||||
# else:
|
origin = "/3D/model.gcode")
|
||||||
# Logger.log("d", "Thumbnail not created, cannot save it")
|
else:
|
||||||
|
Logger.log("w", "Thumbnail not created, cannot save it")
|
||||||
|
|
||||||
# Store the material.
|
# Store the material.
|
||||||
application = CuraApplication.getInstance()
|
application = CuraApplication.getInstance()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue