mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Add 'plugins/CuraEngineBackend/' from commit '918d4b41c8
'
git-subtree-dir: plugins/CuraEngineBackend git-subtree-mainline:49210587ff
git-subtree-split:918d4b41c8
This commit is contained in:
commit
3823afd8cc
6 changed files with 1024 additions and 0 deletions
231
plugins/CuraEngineBackend/CuraEngineBackend.py
Normal file
231
plugins/CuraEngineBackend/CuraEngineBackend.py
Normal file
|
@ -0,0 +1,231 @@
|
|||
from UM.Backend.Backend import Backend
|
||||
from UM.Application import Application
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Signal import Signal
|
||||
from UM.Logger import Logger
|
||||
from UM.Resources import Resources
|
||||
|
||||
from . import Cura_pb2
|
||||
from . import ProcessSlicedObjectListJob
|
||||
from . import ProcessGCodeJob
|
||||
|
||||
import os
|
||||
import sys
|
||||
import numpy
|
||||
|
||||
from PyQt5.QtCore import QTimer
|
||||
|
||||
class CuraEngineBackend(Backend):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Find out where the engine is located, and how it is called. This depends on how Cura is packaged and which OS we are running on.
|
||||
default_engine_location = '../PinkUnicornEngine/CuraEngine'
|
||||
if hasattr(sys, 'frozen'):
|
||||
default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'CuraEngine')
|
||||
if sys.platform == 'win32':
|
||||
default_engine_location += '.exe'
|
||||
default_engine_location = os.path.abspath(default_engine_location)
|
||||
Preferences.getInstance().addPreference('backend/location', default_engine_location)
|
||||
|
||||
self._scene = Application.getInstance().getController().getScene()
|
||||
self._scene.sceneChanged.connect(self._onSceneChanged)
|
||||
|
||||
self._settings = None
|
||||
Application.getInstance().activeMachineChanged.connect(self._onActiveMachineChanged)
|
||||
self._onActiveMachineChanged()
|
||||
|
||||
self._change_timer = QTimer()
|
||||
self._change_timer.setInterval(500)
|
||||
self._change_timer.setSingleShot(True)
|
||||
self._change_timer.timeout.connect(self.slice)
|
||||
|
||||
self._message_handlers[Cura_pb2.SlicedObjectList] = self._onSlicedObjectListMessage
|
||||
self._message_handlers[Cura_pb2.Progress] = self._onProgressMessage
|
||||
self._message_handlers[Cura_pb2.GCodeLayer] = self._onGCodeLayerMessage
|
||||
self._message_handlers[Cura_pb2.GCodePrefix] = self._onGCodePrefixMessage
|
||||
self._message_handlers[Cura_pb2.ObjectPrintTime] = self._onObjectPrintTimeMessage
|
||||
|
||||
self._slicing = False
|
||||
self._restart = False
|
||||
|
||||
self._save_gcode = True
|
||||
self._save_polygons = True
|
||||
self._report_progress = True
|
||||
|
||||
self.backendConnected.connect(self._onBackendConnected)
|
||||
|
||||
def getEngineCommand(self):
|
||||
return [Preferences.getInstance().getValue("backend/location"), '-j', Resources.getPath(Resources.SettingsLocation, 'fdmprinter.json'), '-vv', '--connect', "127.0.0.1:{0}".format(self._port)]
|
||||
|
||||
## Emitted when we get a message containing print duration and material amount. This also implies the slicing has finished.
|
||||
# \param time The amount of time the print will take.
|
||||
# \param material_amount The amount of material the print will use.
|
||||
printDurationMessage = Signal()
|
||||
|
||||
## Emitted when the slicing process starts.
|
||||
slicingStarted = Signal()
|
||||
|
||||
## Emitted whne the slicing process is aborted forcefully.
|
||||
slicingCancelled = Signal()
|
||||
|
||||
## Perform a slice of the scene with the given set of settings.
|
||||
#
|
||||
# \param kwargs Keyword arguments.
|
||||
# Valid values are:
|
||||
# - settings: The settings to use for the slice. The default is the active machine.
|
||||
# - save_gcode: True if the generated gcode should be saved, False if not. True by default.
|
||||
# - save_polygons: True if the generated polygon data should be saved, False if not. True by default.
|
||||
# - force_restart: True if the slicing process should be forcefully restarted if it is already slicing.
|
||||
# If False, this method will do nothing when already slicing. True by default.
|
||||
# - report_progress: True if the slicing progress should be reported, False if not. Default is True.
|
||||
def slice(self, **kwargs):
|
||||
if self._slicing:
|
||||
if not kwargs.get('force_restart', True):
|
||||
return
|
||||
|
||||
self._slicing = False
|
||||
self._restart = True
|
||||
if self._process is not None:
|
||||
Logger.log('d', "Killing engine process")
|
||||
try:
|
||||
self._process.terminate()
|
||||
except: # terminating a process that is already terminating causes an exception, silently ignore this.
|
||||
pass
|
||||
self.slicingCancelled.emit()
|
||||
return
|
||||
|
||||
objects = []
|
||||
for node in DepthFirstIterator(self._scene.getRoot()):
|
||||
if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
|
||||
if not getattr(node, '_outside_buildarea', False):
|
||||
objects.append(node)
|
||||
|
||||
if not objects:
|
||||
return #No point in slicing an empty build plate
|
||||
|
||||
self._slicing = True
|
||||
self.slicingStarted.emit()
|
||||
|
||||
self._report_progress = kwargs.get('report_progress', True)
|
||||
if self._report_progress:
|
||||
self.processingProgress.emit(0.0)
|
||||
|
||||
self._sendSettings(kwargs.get('settings', self._settings))
|
||||
|
||||
self._scene.acquireLock()
|
||||
|
||||
# Set the gcode as an empty list. This will be filled with strings by GCodeLayer messages.
|
||||
# This is done so the gcode can be fragmented in memory and does not need a continues memory space.
|
||||
# (AKA. This prevents MemoryErrors)
|
||||
self._save_gcode = kwargs.get('save_gcode', True)
|
||||
if self._save_gcode:
|
||||
setattr(self._scene, 'gcode_list', [])
|
||||
|
||||
self._save_polygons = kwargs.get('save_polygons', True)
|
||||
|
||||
msg = Cura_pb2.ObjectList()
|
||||
|
||||
#TODO: All at once/one at a time mode
|
||||
center = Vector()
|
||||
for object in objects:
|
||||
center += object.getPosition()
|
||||
|
||||
mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())
|
||||
|
||||
obj = msg.objects.add()
|
||||
obj.id = id(object)
|
||||
|
||||
verts = numpy.array(mesh_data.getVertices(), copy=True)
|
||||
verts[:,[1,2]] = verts[:,[2,1]]
|
||||
verts[:,1] *= -1
|
||||
obj.vertices = verts.tostring()
|
||||
|
||||
#if meshData.hasNormals():
|
||||
#obj.normals = meshData.getNormalsAsByteArray()
|
||||
|
||||
#if meshData.hasIndices():
|
||||
#obj.indices = meshData.getIndicesAsByteArray()
|
||||
|
||||
self._scene.releaseLock()
|
||||
|
||||
self._socket.sendMessage(msg)
|
||||
|
||||
def _onSceneChanged(self, source):
|
||||
if (type(source) is not SceneNode) or (source is self._scene.getRoot()) or (source.getMeshData() is None):
|
||||
return
|
||||
|
||||
if(source.getMeshData().getVertices() is None):
|
||||
return
|
||||
|
||||
self._onChanged()
|
||||
|
||||
def _onActiveMachineChanged(self):
|
||||
if self._settings:
|
||||
self._settings.settingChanged.disconnect(self._onSettingChanged)
|
||||
|
||||
self._settings = Application.getInstance().getActiveMachine()
|
||||
if self._settings:
|
||||
self._settings.settingChanged.connect(self._onSettingChanged)
|
||||
self._onChanged()
|
||||
|
||||
def _onSettingChanged(self, setting):
|
||||
self._onChanged()
|
||||
|
||||
def _onSlicedObjectListMessage(self, message):
|
||||
if self._save_polygons:
|
||||
job = ProcessSlicedObjectListJob.ProcessSlicedObjectListJob(message)
|
||||
job.start()
|
||||
|
||||
def _onProgressMessage(self, message):
|
||||
if message.amount >= 0.99:
|
||||
self._slicing = False
|
||||
|
||||
if self._report_progress:
|
||||
self.processingProgress.emit(message.amount)
|
||||
|
||||
def _onGCodeLayerMessage(self, message):
|
||||
if self._save_gcode:
|
||||
job = ProcessGCodeJob.ProcessGCodeLayerJob(message)
|
||||
job.start()
|
||||
|
||||
def _onGCodePrefixMessage(self, message):
|
||||
if self._save_gcode:
|
||||
self._scene.gcode_list.insert(0, message.data.decode('utf-8', 'replace'))
|
||||
|
||||
def _onObjectPrintTimeMessage(self, message):
|
||||
self.printDurationMessage.emit(message.time, message.material_amount)
|
||||
|
||||
def _createSocket(self):
|
||||
super()._createSocket()
|
||||
|
||||
self._socket.registerMessageType(1, Cura_pb2.ObjectList)
|
||||
self._socket.registerMessageType(2, Cura_pb2.SlicedObjectList)
|
||||
self._socket.registerMessageType(3, Cura_pb2.Progress)
|
||||
self._socket.registerMessageType(4, Cura_pb2.GCodeLayer)
|
||||
self._socket.registerMessageType(5, Cura_pb2.ObjectPrintTime)
|
||||
self._socket.registerMessageType(6, Cura_pb2.SettingList)
|
||||
self._socket.registerMessageType(7, Cura_pb2.GCodePrefix)
|
||||
|
||||
def _onChanged(self):
|
||||
if not self._settings:
|
||||
return
|
||||
|
||||
self._change_timer.start()
|
||||
|
||||
def _sendSettings(self, settings):
|
||||
msg = Cura_pb2.SettingList()
|
||||
for setting in settings.getAllSettings(include_machine=True):
|
||||
s = msg.settings.add()
|
||||
s.name = setting.getKey()
|
||||
s.value = str(setting.getValue()).encode('utf-8')
|
||||
|
||||
self._socket.sendMessage(msg)
|
||||
|
||||
def _onBackendConnected(self):
|
||||
if self._restart:
|
||||
self._onChanged()
|
||||
self._restart = False
|
609
plugins/CuraEngineBackend/Cura_pb2.py
Normal file
609
plugins/CuraEngineBackend/Cura_pb2.py
Normal file
|
@ -0,0 +1,609 @@
|
|||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: Cura.proto
|
||||
|
||||
import sys
|
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf import descriptor_pb2
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='Cura.proto',
|
||||
package='Cura',
|
||||
serialized_pb=_b('\n\nCura.proto\x12\x04\x43ura\"+\n\nObjectList\x12\x1d\n\x07objects\x18\x01 \x03(\x0b\x32\x0c.Cura.Object\"i\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12\x1f\n\x08settings\x18\x05 \x03(\x0b\x32\r.Cura.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"7\n\x10SlicedObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.Cura.SlicedObject\"7\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x1b\n\x06layers\x18\x02 \x03(\x0b\x32\x0b.Cura.Layer\"4\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x1f\n\x08polygons\x18\x02 \x03(\x0b\x32\r.Cura.Polygon\"\x9f\x01\n\x07Polygon\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.Cura.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\"b\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\".\n\x0bSettingList\x12\x1f\n\x08settings\x18\x01 \x03(\x0b\x32\r.Cura.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3')
|
||||
)
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
|
||||
|
||||
_POLYGON_TYPE = _descriptor.EnumDescriptor(
|
||||
name='Type',
|
||||
full_name='Cura.Polygon.Type',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='NoneType', index=0, number=0,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='Inset0Type', index=1, number=1,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='InsetXType', index=2, number=2,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SkinType', index=3, number=3,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SupportType', index=4, number=4,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SkirtType', index=5, number=5,
|
||||
options=None,
|
||||
type=None),
|
||||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=430,
|
||||
serialized_end=528,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_POLYGON_TYPE)
|
||||
|
||||
|
||||
_OBJECTLIST = _descriptor.Descriptor(
|
||||
name='ObjectList',
|
||||
full_name='Cura.ObjectList',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='objects', full_name='Cura.ObjectList.objects', index=0,
|
||||
number=1, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=20,
|
||||
serialized_end=63,
|
||||
)
|
||||
|
||||
|
||||
_OBJECT = _descriptor.Descriptor(
|
||||
name='Object',
|
||||
full_name='Cura.Object',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='Cura.Object.id', index=0,
|
||||
number=1, type=3, cpp_type=2, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='vertices', full_name='Cura.Object.vertices', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='normals', full_name='Cura.Object.normals', index=2,
|
||||
number=3, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='indices', full_name='Cura.Object.indices', index=3,
|
||||
number=4, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='settings', full_name='Cura.Object.settings', index=4,
|
||||
number=5, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=65,
|
||||
serialized_end=170,
|
||||
)
|
||||
|
||||
|
||||
_PROGRESS = _descriptor.Descriptor(
|
||||
name='Progress',
|
||||
full_name='Cura.Progress',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='amount', full_name='Cura.Progress.amount', index=0,
|
||||
number=1, type=2, cpp_type=6, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=172,
|
||||
serialized_end=198,
|
||||
)
|
||||
|
||||
|
||||
_SLICEDOBJECTLIST = _descriptor.Descriptor(
|
||||
name='SlicedObjectList',
|
||||
full_name='Cura.SlicedObjectList',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='objects', full_name='Cura.SlicedObjectList.objects', index=0,
|
||||
number=1, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=200,
|
||||
serialized_end=255,
|
||||
)
|
||||
|
||||
|
||||
_SLICEDOBJECT = _descriptor.Descriptor(
|
||||
name='SlicedObject',
|
||||
full_name='Cura.SlicedObject',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='Cura.SlicedObject.id', index=0,
|
||||
number=1, type=3, cpp_type=2, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='layers', full_name='Cura.SlicedObject.layers', index=1,
|
||||
number=2, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=257,
|
||||
serialized_end=312,
|
||||
)
|
||||
|
||||
|
||||
_LAYER = _descriptor.Descriptor(
|
||||
name='Layer',
|
||||
full_name='Cura.Layer',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='Cura.Layer.id', index=0,
|
||||
number=1, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='polygons', full_name='Cura.Layer.polygons', index=1,
|
||||
number=2, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=314,
|
||||
serialized_end=366,
|
||||
)
|
||||
|
||||
|
||||
_POLYGON = _descriptor.Descriptor(
|
||||
name='Polygon',
|
||||
full_name='Cura.Polygon',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='type', full_name='Cura.Polygon.type', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='points', full_name='Cura.Polygon.points', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
_POLYGON_TYPE,
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=369,
|
||||
serialized_end=528,
|
||||
)
|
||||
|
||||
|
||||
_GCODELAYER = _descriptor.Descriptor(
|
||||
name='GCodeLayer',
|
||||
full_name='Cura.GCodeLayer',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='Cura.GCodeLayer.id', index=0,
|
||||
number=1, type=3, cpp_type=2, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='data', full_name='Cura.GCodeLayer.data', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=530,
|
||||
serialized_end=568,
|
||||
)
|
||||
|
||||
|
||||
_OBJECTPRINTTIME = _descriptor.Descriptor(
|
||||
name='ObjectPrintTime',
|
||||
full_name='Cura.ObjectPrintTime',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='Cura.ObjectPrintTime.id', index=0,
|
||||
number=1, type=3, cpp_type=2, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='time', full_name='Cura.ObjectPrintTime.time', index=1,
|
||||
number=2, type=2, cpp_type=6, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='material_amount', full_name='Cura.ObjectPrintTime.material_amount', index=2,
|
||||
number=3, type=2, cpp_type=6, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=570,
|
||||
serialized_end=638,
|
||||
)
|
||||
|
||||
|
||||
_SETTINGLIST = _descriptor.Descriptor(
|
||||
name='SettingList',
|
||||
full_name='Cura.SettingList',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='settings', full_name='Cura.SettingList.settings', index=0,
|
||||
number=1, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=640,
|
||||
serialized_end=686,
|
||||
)
|
||||
|
||||
|
||||
_SETTING = _descriptor.Descriptor(
|
||||
name='Setting',
|
||||
full_name='Cura.Setting',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='name', full_name='Cura.Setting.name', index=0,
|
||||
number=1, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='Cura.Setting.value', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=688,
|
||||
serialized_end=726,
|
||||
)
|
||||
|
||||
|
||||
_GCODEPREFIX = _descriptor.Descriptor(
|
||||
name='GCodePrefix',
|
||||
full_name='Cura.GCodePrefix',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='data', full_name='Cura.GCodePrefix.data', index=0,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=728,
|
||||
serialized_end=755,
|
||||
)
|
||||
|
||||
_OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT
|
||||
_OBJECT.fields_by_name['settings'].message_type = _SETTING
|
||||
_SLICEDOBJECTLIST.fields_by_name['objects'].message_type = _SLICEDOBJECT
|
||||
_SLICEDOBJECT.fields_by_name['layers'].message_type = _LAYER
|
||||
_LAYER.fields_by_name['polygons'].message_type = _POLYGON
|
||||
_POLYGON.fields_by_name['type'].enum_type = _POLYGON_TYPE
|
||||
_POLYGON_TYPE.containing_type = _POLYGON
|
||||
_SETTINGLIST.fields_by_name['settings'].message_type = _SETTING
|
||||
DESCRIPTOR.message_types_by_name['ObjectList'] = _OBJECTLIST
|
||||
DESCRIPTOR.message_types_by_name['Object'] = _OBJECT
|
||||
DESCRIPTOR.message_types_by_name['Progress'] = _PROGRESS
|
||||
DESCRIPTOR.message_types_by_name['SlicedObjectList'] = _SLICEDOBJECTLIST
|
||||
DESCRIPTOR.message_types_by_name['SlicedObject'] = _SLICEDOBJECT
|
||||
DESCRIPTOR.message_types_by_name['Layer'] = _LAYER
|
||||
DESCRIPTOR.message_types_by_name['Polygon'] = _POLYGON
|
||||
DESCRIPTOR.message_types_by_name['GCodeLayer'] = _GCODELAYER
|
||||
DESCRIPTOR.message_types_by_name['ObjectPrintTime'] = _OBJECTPRINTTIME
|
||||
DESCRIPTOR.message_types_by_name['SettingList'] = _SETTINGLIST
|
||||
DESCRIPTOR.message_types_by_name['Setting'] = _SETTING
|
||||
DESCRIPTOR.message_types_by_name['GCodePrefix'] = _GCODEPREFIX
|
||||
|
||||
ObjectList = _reflection.GeneratedProtocolMessageType('ObjectList', (_message.Message,), dict(
|
||||
DESCRIPTOR = _OBJECTLIST,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.ObjectList)
|
||||
))
|
||||
_sym_db.RegisterMessage(ObjectList)
|
||||
|
||||
Object = _reflection.GeneratedProtocolMessageType('Object', (_message.Message,), dict(
|
||||
DESCRIPTOR = _OBJECT,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.Object)
|
||||
))
|
||||
_sym_db.RegisterMessage(Object)
|
||||
|
||||
Progress = _reflection.GeneratedProtocolMessageType('Progress', (_message.Message,), dict(
|
||||
DESCRIPTOR = _PROGRESS,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.Progress)
|
||||
))
|
||||
_sym_db.RegisterMessage(Progress)
|
||||
|
||||
SlicedObjectList = _reflection.GeneratedProtocolMessageType('SlicedObjectList', (_message.Message,), dict(
|
||||
DESCRIPTOR = _SLICEDOBJECTLIST,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.SlicedObjectList)
|
||||
))
|
||||
_sym_db.RegisterMessage(SlicedObjectList)
|
||||
|
||||
SlicedObject = _reflection.GeneratedProtocolMessageType('SlicedObject', (_message.Message,), dict(
|
||||
DESCRIPTOR = _SLICEDOBJECT,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.SlicedObject)
|
||||
))
|
||||
_sym_db.RegisterMessage(SlicedObject)
|
||||
|
||||
Layer = _reflection.GeneratedProtocolMessageType('Layer', (_message.Message,), dict(
|
||||
DESCRIPTOR = _LAYER,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.Layer)
|
||||
))
|
||||
_sym_db.RegisterMessage(Layer)
|
||||
|
||||
Polygon = _reflection.GeneratedProtocolMessageType('Polygon', (_message.Message,), dict(
|
||||
DESCRIPTOR = _POLYGON,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.Polygon)
|
||||
))
|
||||
_sym_db.RegisterMessage(Polygon)
|
||||
|
||||
GCodeLayer = _reflection.GeneratedProtocolMessageType('GCodeLayer', (_message.Message,), dict(
|
||||
DESCRIPTOR = _GCODELAYER,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.GCodeLayer)
|
||||
))
|
||||
_sym_db.RegisterMessage(GCodeLayer)
|
||||
|
||||
ObjectPrintTime = _reflection.GeneratedProtocolMessageType('ObjectPrintTime', (_message.Message,), dict(
|
||||
DESCRIPTOR = _OBJECTPRINTTIME,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.ObjectPrintTime)
|
||||
))
|
||||
_sym_db.RegisterMessage(ObjectPrintTime)
|
||||
|
||||
SettingList = _reflection.GeneratedProtocolMessageType('SettingList', (_message.Message,), dict(
|
||||
DESCRIPTOR = _SETTINGLIST,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.SettingList)
|
||||
))
|
||||
_sym_db.RegisterMessage(SettingList)
|
||||
|
||||
Setting = _reflection.GeneratedProtocolMessageType('Setting', (_message.Message,), dict(
|
||||
DESCRIPTOR = _SETTING,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.Setting)
|
||||
))
|
||||
_sym_db.RegisterMessage(Setting)
|
||||
|
||||
GCodePrefix = _reflection.GeneratedProtocolMessageType('GCodePrefix', (_message.Message,), dict(
|
||||
DESCRIPTOR = _GCODEPREFIX,
|
||||
__module__ = 'Cura_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Cura.GCodePrefix)
|
||||
))
|
||||
_sym_db.RegisterMessage(GCodePrefix)
|
||||
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
90
plugins/CuraEngineBackend/LayerData.py
Normal file
90
plugins/CuraEngineBackend/LayerData.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
from UM.Mesh.MeshData import MeshData
|
||||
from UM.Math.Color import Color
|
||||
|
||||
import numpy
|
||||
import math
|
||||
|
||||
class LayerData(MeshData):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._layers = {}
|
||||
self._element_counts = {}
|
||||
|
||||
def addPolygon(self, layer, type, data):
|
||||
if layer not in self._layers:
|
||||
self._layers[layer] = []
|
||||
|
||||
p = Polygon(self, type, data)
|
||||
self._layers[layer].append(p)
|
||||
|
||||
def getLayers(self):
|
||||
return self._layers
|
||||
|
||||
def getElementCounts(self):
|
||||
return self._element_counts
|
||||
|
||||
def build(self):
|
||||
for layer, data in self._layers.items():
|
||||
if layer not in self._element_counts:
|
||||
self._element_counts[layer] = []
|
||||
|
||||
for polygon in data:
|
||||
polygon.build()
|
||||
self._element_counts[layer].append(polygon.elementCount)
|
||||
|
||||
class Polygon():
|
||||
NoneType = 0
|
||||
Inset0Type = 1
|
||||
InsetXType = 2
|
||||
SkinType = 3
|
||||
SupportType = 4
|
||||
SkirtType = 5
|
||||
|
||||
def __init__(self, mesh, type, data):
|
||||
super().__init__()
|
||||
self._mesh = mesh
|
||||
self._type = type
|
||||
self._data = data
|
||||
|
||||
def build(self):
|
||||
self._begin = self._mesh._vertex_count
|
||||
self._mesh.addVertices(self._data)
|
||||
self._end = self._begin + len(self._data) - 1
|
||||
|
||||
color = None
|
||||
if self._type == self.Inset0Type:
|
||||
color = [1, 0, 0, 1]
|
||||
elif self._type == self.InsetXType:
|
||||
color = [0, 1, 0, 1]
|
||||
elif self._type == self.SkinType:
|
||||
color = [1, 1, 0, 1]
|
||||
elif self._type == self.SupportType:
|
||||
color = [0, 1, 1, 1]
|
||||
elif self._type == self.SkirtType:
|
||||
color = [0, 1, 1, 1]
|
||||
else:
|
||||
color = [1, 1, 1, 1]
|
||||
|
||||
colors = [color for i in range(len(self._data))]
|
||||
self._mesh.addColors(numpy.array(colors, dtype=numpy.float32))
|
||||
|
||||
indices = []
|
||||
for i in range(self._begin, self._end):
|
||||
indices.append(i)
|
||||
indices.append(i + 1)
|
||||
|
||||
indices.append(self._end)
|
||||
indices.append(self._begin)
|
||||
self._mesh.addIndices(numpy.array(indices, dtype=numpy.int32))
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def elementCount(self):
|
||||
return (self._end - self._begin) * 2 #The range of vertices multiplied by 2 since each vertex is used twice
|
13
plugins/CuraEngineBackend/ProcessGCodeJob.py
Normal file
13
plugins/CuraEngineBackend/ProcessGCodeJob.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
from UM.Job import Job
|
||||
from UM.Application import Application
|
||||
|
||||
|
||||
class ProcessGCodeLayerJob(Job):
|
||||
def __init__(self, message):
|
||||
super().__init__()
|
||||
|
||||
self._scene = Application.getInstance().getController().getScene()
|
||||
self._message = message
|
||||
|
||||
def run(self):
|
||||
self._scene.gcode_list.append(self._message.data.decode('utf-8', 'replace'))
|
67
plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py
Normal file
67
plugins/CuraEngineBackend/ProcessSlicedObjectListJob.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
from UM.Job import Job
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Application import Application
|
||||
from UM.Mesh.MeshData import MeshData
|
||||
|
||||
from . import LayerData
|
||||
|
||||
import numpy
|
||||
import struct
|
||||
|
||||
class ProcessSlicedObjectListJob(Job):
|
||||
def __init__(self, message):
|
||||
super().__init__(description = 'Processing sliced object')
|
||||
self._message = message
|
||||
self._scene = Application.getInstance().getController().getScene()
|
||||
|
||||
def run(self):
|
||||
objectIdMap = {}
|
||||
new_node = SceneNode()
|
||||
## Put all nodes in a dict identified by ID
|
||||
for node in DepthFirstIterator(self._scene.getRoot()):
|
||||
if type(node) is SceneNode and node.getMeshData():
|
||||
if hasattr(node.getMeshData(), "layerData"):
|
||||
self._scene.getRoot().removeChild(node)
|
||||
else:
|
||||
objectIdMap[id(node)] = node
|
||||
|
||||
settings = Application.getInstance().getActiveMachine()
|
||||
layerHeight = settings.getSettingValueByKey('layer_height')
|
||||
|
||||
for object in self._message.objects:
|
||||
try:
|
||||
node = objectIdMap[object.id]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
mesh = MeshData()
|
||||
|
||||
layerData = LayerData.LayerData()
|
||||
for layer in object.layers:
|
||||
for polygon in layer.polygons:
|
||||
points = numpy.fromstring(polygon.points, dtype='i8') # Convert bytearray to numpy array
|
||||
points = points.reshape((-1,2)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly.
|
||||
points = numpy.asarray(points, dtype=numpy.float32)
|
||||
points /= 1000
|
||||
points = numpy.insert(points, 1, layer.id * layerHeight, axis = 1)
|
||||
|
||||
points[:,2] *= -1
|
||||
|
||||
if not settings.getSettingValueByKey('machine_center_is_zero'):
|
||||
center = [settings.getSettingValueByKey('machine_width') / 2, 0.0, -settings.getSettingValueByKey('machine_depth') / 2]
|
||||
points -= numpy.array(center)
|
||||
|
||||
#points = numpy.pad(points, ((0,0), (0,1)), 'constant', constant_values=(0.0, 1.0))
|
||||
#inverse = node.getWorldTransformation().getInverse().getData()
|
||||
#points = points.dot(inverse)
|
||||
#points = points[:,0:3]
|
||||
|
||||
layerData.addPolygon(layer.id, polygon.type, points)
|
||||
|
||||
# We are done processing all the layers we got from the engine, now create a mesh out of the data
|
||||
layerData.build()
|
||||
mesh.layerData = layerData
|
||||
|
||||
new_node.setMeshData(mesh)
|
||||
new_node.setParent(self._scene.getRoot())
|
14
plugins/CuraEngineBackend/__init__.py
Normal file
14
plugins/CuraEngineBackend/__init__.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
#Shoopdawoop
|
||||
from . import CuraEngineBackend
|
||||
|
||||
def getMetaData():
|
||||
return {
|
||||
'type': 'backend',
|
||||
'plugin': {
|
||||
'name': "CuraEngine Backend"
|
||||
}
|
||||
}
|
||||
|
||||
def register(app):
|
||||
return {"backend":CuraEngineBackend.CuraEngineBackend()}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue