mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-23 14:44:13 -06:00
Fixed merge issues & updated proto files
This commit is contained in:
commit
7c744044fd
5 changed files with 181 additions and 78 deletions
|
@ -131,7 +131,7 @@ class Layer():
|
||||||
continue
|
continue
|
||||||
if not make_mesh and not (polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType):
|
if not make_mesh and not (polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
poly_color = polygon.getColor()
|
poly_color = polygon.getColor()
|
||||||
|
|
||||||
points = numpy.copy(polygon.data)
|
points = numpy.copy(polygon.data)
|
||||||
|
@ -140,26 +140,7 @@ class Layer():
|
||||||
if polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType:
|
if polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType:
|
||||||
points[:,1] += 0.01
|
points[:,1] += 0.01
|
||||||
|
|
||||||
# Calculate normals for the entire polygon using numpy.
|
normals = polygon.getNormals()
|
||||||
normals = numpy.copy(points)
|
|
||||||
normals[:,1] = 0.0 # We are only interested in 2D normals
|
|
||||||
|
|
||||||
# Calculate the edges between points.
|
|
||||||
# The call to numpy.roll shifts the entire array by one so that
|
|
||||||
# we end up subtracting each next point from the current, wrapping
|
|
||||||
# around. This gives us the edges from the next point to the current
|
|
||||||
# point.
|
|
||||||
normals[:] = normals[:] - numpy.roll(normals, -1, axis = 0)
|
|
||||||
# Calculate the length of each edge using standard Pythagoras
|
|
||||||
lengths = numpy.sqrt(normals[:,0] ** 2 + normals[:,2] ** 2)
|
|
||||||
# The normal of a 2D vector is equal to its x and y coordinates swapped
|
|
||||||
# and then x inverted. This code does that.
|
|
||||||
normals[:,[0, 2]] = normals[:,[2, 0]]
|
|
||||||
normals[:,0] *= -1
|
|
||||||
|
|
||||||
# Normalize the normals.
|
|
||||||
normals[:,0] /= lengths
|
|
||||||
normals[:,2] /= lengths
|
|
||||||
|
|
||||||
# Scale all by the line width of the polygon so we can easily offset.
|
# Scale all by the line width of the polygon so we can easily offset.
|
||||||
normals *= (polygon.lineWidth / 2)
|
normals *= (polygon.lineWidth / 2)
|
||||||
|
@ -199,16 +180,33 @@ class Polygon():
|
||||||
self._data = data
|
self._data = data
|
||||||
self._line_width = line_width / 1000
|
self._line_width = line_width / 1000
|
||||||
|
|
||||||
|
if type == self.Inset0Type:
|
||||||
|
self._color = Color(1.0, 0.0, 0.0, 1.0)
|
||||||
|
elif self._type == self.InsetXType:
|
||||||
|
self._color = Color(0.0, 1.0, 0.0, 1.0)
|
||||||
|
elif self._type == self.SkinType:
|
||||||
|
self._color = Color(1.0, 1.0, 0.0, 1.0)
|
||||||
|
elif self._type == self.SupportType:
|
||||||
|
self._color = Color(0.0, 1.0, 1.0, 1.0)
|
||||||
|
elif self._type == self.SkirtType:
|
||||||
|
self._color = Color(0.0, 1.0, 1.0, 1.0)
|
||||||
|
elif self._type == self.InfillType:
|
||||||
|
self._color = Color(1.0, 0.74, 0.0, 1.0)
|
||||||
|
elif self._type == self.SupportInfillType:
|
||||||
|
self._color = Color(0.0, 1.0, 1.0, 1.0)
|
||||||
|
elif self._type == self.MoveCombingType:
|
||||||
|
self._color = Color(0.0, 0.0, 1.0, 1.0)
|
||||||
|
elif self._type == self.MoveRetractionType:
|
||||||
|
self._color = Color(0.5, 0.5, 1.0, 1.0)
|
||||||
|
else:
|
||||||
|
self._color = Color(1.0, 1.0, 1.0, 1.0)
|
||||||
|
|
||||||
def build(self, offset, vertices, colors, indices):
|
def build(self, offset, vertices, colors, indices):
|
||||||
self._begin = offset
|
self._begin = offset
|
||||||
self._end = self._begin + len(self._data) - 1
|
self._end = self._begin + len(self._data) - 1
|
||||||
|
|
||||||
color = self.getColor()
|
|
||||||
color.setValues(color.r * 0.5, color.g * 0.5, color.b * 0.5, color.a)
|
|
||||||
color = numpy.array([color.r, color.g, color.b, color.a], numpy.float32)
|
|
||||||
|
|
||||||
vertices[self._begin:self._end + 1, :] = self._data[:, :]
|
vertices[self._begin:self._end + 1, :] = self._data[:, :]
|
||||||
colors[self._begin:self._end + 1, :] = color
|
colors[self._begin:self._end + 1, :] = numpy.array([self._color.r * 0.5, self._color.g * 0.5, self._color.b * 0.5, self._color.a], numpy.float32)
|
||||||
|
|
||||||
for i in range(self._begin, self._end):
|
for i in range(self._begin, self._end):
|
||||||
indices[i, 0] = i
|
indices[i, 0] = i
|
||||||
|
@ -218,26 +216,7 @@ class Polygon():
|
||||||
indices[self._end, 1] = self._begin
|
indices[self._end, 1] = self._begin
|
||||||
|
|
||||||
def getColor(self):
|
def getColor(self):
|
||||||
if self._type == self.Inset0Type:
|
return self._color
|
||||||
return Color(1.0, 0.0, 0.0, 1.0)
|
|
||||||
elif self._type == self.InsetXType:
|
|
||||||
return Color(0.0, 1.0, 0.0, 1.0)
|
|
||||||
elif self._type == self.SkinType:
|
|
||||||
return Color(1.0, 1.0, 0.0, 1.0)
|
|
||||||
elif self._type == self.SupportType:
|
|
||||||
return Color(0.0, 1.0, 1.0, 1.0)
|
|
||||||
elif self._type == self.SkirtType:
|
|
||||||
return Color(0.0, 1.0, 1.0, 1.0)
|
|
||||||
elif self._type == self.InfillType:
|
|
||||||
return Color(1.0, 0.74, 0.0, 1.0)
|
|
||||||
elif self._type == self.SupportInfillType:
|
|
||||||
return Color(0.0, 1.0, 1.0, 1.0)
|
|
||||||
elif self._type == self.MoveCombingType:
|
|
||||||
return Color(0.0, 0.0, 1.0, 1.0)
|
|
||||||
elif self._type == self.MoveRetractionType:
|
|
||||||
return Color(0.5, 0.5, 1.0, 1.0)
|
|
||||||
else:
|
|
||||||
return Color(1.0, 1.0, 1.0, 1.0)
|
|
||||||
|
|
||||||
def vertexCount(self):
|
def vertexCount(self):
|
||||||
return len(self._data)
|
return len(self._data)
|
||||||
|
@ -257,3 +236,27 @@ class Polygon():
|
||||||
@property
|
@property
|
||||||
def lineWidth(self):
|
def lineWidth(self):
|
||||||
return self._line_width
|
return self._line_width
|
||||||
|
|
||||||
|
# Calculate normals for the entire polygon using numpy.
|
||||||
|
def getNormals(self):
|
||||||
|
normals = numpy.copy(self._data)
|
||||||
|
normals[:,1] = 0.0 # We are only interested in 2D normals
|
||||||
|
|
||||||
|
# Calculate the edges between points.
|
||||||
|
# The call to numpy.roll shifts the entire array by one so that
|
||||||
|
# we end up subtracting each next point from the current, wrapping
|
||||||
|
# around. This gives us the edges from the next point to the current
|
||||||
|
# point.
|
||||||
|
normals[:] = normals[:] - numpy.roll(normals, -1, axis = 0)
|
||||||
|
# Calculate the length of each edge using standard Pythagoras
|
||||||
|
lengths = numpy.sqrt(normals[:,0] ** 2 + normals[:,2] ** 2)
|
||||||
|
# The normal of a 2D vector is equal to its x and y coordinates swapped
|
||||||
|
# and then x inverted. This code does that.
|
||||||
|
normals[:,[0, 2]] = normals[:,[2, 0]]
|
||||||
|
normals[:,0] *= -1
|
||||||
|
|
||||||
|
# Normalize the normals.
|
||||||
|
normals[:,0] /= lengths
|
||||||
|
normals[:,2] /= lengths
|
||||||
|
|
||||||
|
return normals
|
||||||
|
|
104
plugins/CuraEngineBackend/Cura.proto
Normal file
104
plugins/CuraEngineBackend/Cura.proto
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package cura.proto;
|
||||||
|
|
||||||
|
|
||||||
|
message ObjectList
|
||||||
|
{
|
||||||
|
repeated Object objects = 1;
|
||||||
|
repeated Setting settings = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 1
|
||||||
|
message Slice
|
||||||
|
{
|
||||||
|
repeated ObjectList object_lists = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Object
|
||||||
|
{
|
||||||
|
int64 id = 1;
|
||||||
|
bytes vertices = 2; //An array of 3 floats.
|
||||||
|
bytes normals = 3; //An array of 3 floats.
|
||||||
|
bytes indices = 4; //An array of ints.
|
||||||
|
repeated Setting settings = 5; // Setting override per object, overruling the global settings.
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 3
|
||||||
|
message Progress
|
||||||
|
{
|
||||||
|
float amount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 2
|
||||||
|
message SlicedObjectList
|
||||||
|
{
|
||||||
|
repeated SlicedObject objects = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SlicedObject
|
||||||
|
{
|
||||||
|
int64 id = 1;
|
||||||
|
|
||||||
|
repeated Layer layers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Layer {
|
||||||
|
int32 id = 1;
|
||||||
|
|
||||||
|
float height = 2;
|
||||||
|
float thickness = 3;
|
||||||
|
|
||||||
|
repeated Polygon polygons = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Polygon {
|
||||||
|
enum Type {
|
||||||
|
NoneType = 0;
|
||||||
|
Inset0Type = 1;
|
||||||
|
InsetXType = 2;
|
||||||
|
SkinType = 3;
|
||||||
|
SupportType = 4;
|
||||||
|
SkirtType = 5;
|
||||||
|
InfillType = 6;
|
||||||
|
SupportInfillType = 7;
|
||||||
|
MoveCombingType = 8;
|
||||||
|
MoveRetractionType = 9;
|
||||||
|
}
|
||||||
|
Type type = 1;
|
||||||
|
bytes points = 2;
|
||||||
|
float line_width = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 4
|
||||||
|
message GCodeLayer {
|
||||||
|
int64 id = 1;
|
||||||
|
bytes data = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 5
|
||||||
|
message ObjectPrintTime {
|
||||||
|
int64 id = 1;
|
||||||
|
float time = 2;
|
||||||
|
float material_amount = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 6
|
||||||
|
message SettingList {
|
||||||
|
repeated Setting settings = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Setting {
|
||||||
|
string name = 1;
|
||||||
|
|
||||||
|
bytes value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 7
|
||||||
|
message GCodePrefix {
|
||||||
|
bytes data = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeid 8
|
||||||
|
message SlicingFinished {
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ from UM.Qt.Bindings.BackendProxy import BackendState #To determine the state of
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
|
||||||
from cura.OneAtATimeIterator import OneAtATimeIterator
|
from cura.OneAtATimeIterator import OneAtATimeIterator
|
||||||
from . import Cura_pb2
|
from . import Cura_pb2
|
||||||
|
@ -62,12 +63,12 @@ class CuraEngineBackend(Backend):
|
||||||
self._change_timer.setSingleShot(True)
|
self._change_timer.setSingleShot(True)
|
||||||
self._change_timer.timeout.connect(self.slice)
|
self._change_timer.timeout.connect(self.slice)
|
||||||
|
|
||||||
self._message_handlers[Cura_pb2.SlicedObjectList] = self._onSlicedObjectListMessage
|
self._message_handlers["cura.proto.SlicedObjectList"] = self._onSlicedObjectListMessage
|
||||||
self._message_handlers[Cura_pb2.Progress] = self._onProgressMessage
|
self._message_handlers["cura.proto.Progress"] = self._onProgressMessage
|
||||||
self._message_handlers[Cura_pb2.GCodeLayer] = self._onGCodeLayerMessage
|
self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage
|
||||||
self._message_handlers[Cura_pb2.GCodePrefix] = self._onGCodePrefixMessage
|
self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage
|
||||||
self._message_handlers[Cura_pb2.ObjectPrintTime] = self._onObjectPrintTimeMessage
|
self._message_handlers["cura.proto.ObjectPrintTime"] = self._onObjectPrintTimeMessage
|
||||||
self._message_handlers[Cura_pb2.SlicingFinished] = self._onSlicingFinishedMessage
|
self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage
|
||||||
|
|
||||||
self._slicing = False
|
self._slicing = False
|
||||||
self._restart = False
|
self._restart = False
|
||||||
|
@ -230,16 +231,7 @@ class CuraEngineBackend(Backend):
|
||||||
self.printDurationMessage.emit(message.time, message.material_amount)
|
self.printDurationMessage.emit(message.time, message.material_amount)
|
||||||
|
|
||||||
def _createSocket(self):
|
def _createSocket(self):
|
||||||
super()._createSocket()
|
super()._createSocket(os.path.abspath(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "Cura.proto")))
|
||||||
|
|
||||||
self._socket.registerMessageType(1, Cura_pb2.Slice)
|
|
||||||
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)
|
|
||||||
self._socket.registerMessageType(8, Cura_pb2.SlicingFinished)
|
|
||||||
|
|
||||||
## Manually triggers a reslice
|
## Manually triggers a reslice
|
||||||
def forceSlice(self):
|
def forceSlice(self):
|
||||||
|
@ -278,7 +270,6 @@ class CuraEngineBackend(Backend):
|
||||||
else:
|
else:
|
||||||
self._layer_view_active = False
|
self._layer_view_active = False
|
||||||
|
|
||||||
|
|
||||||
def _onInstanceChanged(self):
|
def _onInstanceChanged(self):
|
||||||
self._terminate()
|
self._terminate()
|
||||||
self.slicingCancelled.emit()
|
self.slicingCancelled.emit()
|
||||||
|
|
|
@ -56,21 +56,27 @@ class ProcessSlicedObjectListJob(Job):
|
||||||
layer_data = LayerData.LayerData()
|
layer_data = LayerData.LayerData()
|
||||||
|
|
||||||
layer_count = 0
|
layer_count = 0
|
||||||
for object in self._message.objects:
|
for i in range(self._message.repeatedMessageCount("objects")):
|
||||||
layer_count += len(object.layers)
|
layer_count += self._message.getRepeatedMessage("objects", i).repeatedMessageCount("layers")
|
||||||
|
|
||||||
current_layer = 0
|
current_layer = 0
|
||||||
for object in self._message.objects:
|
for i in range(self._message.repeatedMessageCount("objects")):
|
||||||
|
object = self._message.getRepeatedMessage("objects", i)
|
||||||
try:
|
try:
|
||||||
node = object_id_map[object.id]
|
node = object_id_map[object.id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for layer in object.layers:
|
for l in range(object.repeatedMessageCount("layers")):
|
||||||
|
layer = object.getRepeatedMessage("layers", l)
|
||||||
|
|
||||||
layer_data.addLayer(layer.id)
|
layer_data.addLayer(layer.id)
|
||||||
layer_data.setLayerHeight(layer.id, layer.height)
|
layer_data.setLayerHeight(layer.id, layer.height)
|
||||||
layer_data.setLayerThickness(layer.id, layer.thickness)
|
layer_data.setLayerThickness(layer.id, layer.thickness)
|
||||||
for polygon in layer.polygons:
|
|
||||||
|
for p in range(layer.repeatedMessageCount("polygons")):
|
||||||
|
polygon = layer.getRepeatedMessage("polygons", p)
|
||||||
|
|
||||||
points = numpy.fromstring(polygon.points, dtype="i8") # Convert bytearray to numpy array
|
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 = 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 = numpy.asarray(points, dtype=numpy.float32)
|
||||||
|
@ -83,8 +89,6 @@ class ProcessSlicedObjectListJob(Job):
|
||||||
|
|
||||||
layer_data.addPolygon(layer.id, polygon.type, points, polygon.line_width)
|
layer_data.addPolygon(layer.id, polygon.type, points, polygon.line_width)
|
||||||
|
|
||||||
Job.yieldThread()
|
|
||||||
|
|
||||||
current_layer += 1
|
current_layer += 1
|
||||||
progress = (current_layer / layer_count) * 100
|
progress = (current_layer / layer_count) * 100
|
||||||
# TODO: Rebuild the layer data mesh once the layer has been processed.
|
# TODO: Rebuild the layer data mesh once the layer has been processed.
|
||||||
|
|
|
@ -81,20 +81,21 @@ class StartSliceJob(Job):
|
||||||
|
|
||||||
self._sendSettings(self._profile)
|
self._sendSettings(self._profile)
|
||||||
|
|
||||||
slice_message = Cura_pb2.Slice()
|
slice_message = self._socket.createMessage("cura.proto.Slice");
|
||||||
|
|
||||||
for group in object_groups:
|
for group in object_groups:
|
||||||
group_message = slice_message.object_lists.add()
|
group_message = slice_message.addRepeatedMessage("object_lists");
|
||||||
for object in group:
|
for object in group:
|
||||||
mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())
|
mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())
|
||||||
|
|
||||||
obj = group_message.objects.add()
|
obj = group_message.addRepeatedMessage("objects");
|
||||||
obj.id = id(object)
|
obj.id = id(object)
|
||||||
|
|
||||||
verts = numpy.array(mesh_data.getVertices())
|
verts = numpy.array(mesh_data.getVertices())
|
||||||
verts[:,[1,2]] = verts[:,[2,1]]
|
verts[:,[1,2]] = verts[:,[2,1]]
|
||||||
verts[:,1] *= -1
|
verts[:,1] *= -1
|
||||||
obj.vertices = verts.tostring()
|
|
||||||
|
obj.vertices = verts
|
||||||
|
|
||||||
self._handlePerObjectSettings(object, obj)
|
self._handlePerObjectSettings(object, obj)
|
||||||
|
|
||||||
|
@ -115,13 +116,13 @@ class StartSliceJob(Job):
|
||||||
return str(value).encode("utf-8")
|
return str(value).encode("utf-8")
|
||||||
|
|
||||||
def _sendSettings(self, profile):
|
def _sendSettings(self, profile):
|
||||||
msg = Cura_pb2.SettingList()
|
msg = self._socket.createMessage("cura.proto.SettingList");
|
||||||
settings = profile.getAllSettingValues(include_machine = True)
|
settings = profile.getAllSettingValues(include_machine = True)
|
||||||
start_gcode = settings["machine_start_gcode"]
|
start_gcode = settings["machine_start_gcode"]
|
||||||
settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode
|
settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode
|
||||||
settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode
|
settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode
|
||||||
for key, value in settings.items():
|
for key, value in settings.items():
|
||||||
s = msg.settings.add()
|
s = msg.addRepeatedMessage("settings")
|
||||||
s.name = key
|
s.name = key
|
||||||
if key == "machine_start_gcode" or key == "machine_end_gcode":
|
if key == "machine_start_gcode" or key == "machine_end_gcode":
|
||||||
s.value = self._expandGcodeTokens(key, value, settings)
|
s.value = self._expandGcodeTokens(key, value, settings)
|
||||||
|
@ -134,7 +135,7 @@ class StartSliceJob(Job):
|
||||||
profile = node.callDecoration("getProfile")
|
profile = node.callDecoration("getProfile")
|
||||||
if profile:
|
if profile:
|
||||||
for key, value in profile.getAllSettingValues().items():
|
for key, value in profile.getAllSettingValues().items():
|
||||||
setting = message.settings.add()
|
setting = message.addRepeatedMessage("settings")
|
||||||
setting.name = key
|
setting.name = key
|
||||||
setting.value = str(value).encode()
|
setting.value = str(value).encode()
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ class StartSliceJob(Job):
|
||||||
return
|
return
|
||||||
|
|
||||||
for key, value in object_settings.items():
|
for key, value in object_settings.items():
|
||||||
setting = message.settings.add()
|
setting = message.addRepeatedMessage("settings")
|
||||||
setting.name = key
|
setting.name = key
|
||||||
setting.value = str(value).encode()
|
setting.value = str(value).encode()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue