mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-23 22:54:01 -06:00
Fixed merge issues & updated proto files
This commit is contained in:
commit
7c744044fd
5 changed files with 181 additions and 78 deletions
|
@ -140,26 +140,7 @@ class Layer():
|
|||
if polygon.type == Polygon.MoveCombingType or polygon.type == Polygon.MoveRetractionType:
|
||||
points[:,1] += 0.01
|
||||
|
||||
# Calculate normals for the entire polygon using numpy.
|
||||
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
|
||||
normals = polygon.getNormals()
|
||||
|
||||
# Scale all by the line width of the polygon so we can easily offset.
|
||||
normals *= (polygon.lineWidth / 2)
|
||||
|
@ -199,16 +180,33 @@ class Polygon():
|
|||
self._data = data
|
||||
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):
|
||||
self._begin = offset
|
||||
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[:, :]
|
||||
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):
|
||||
indices[i, 0] = i
|
||||
|
@ -218,26 +216,7 @@ class Polygon():
|
|||
indices[self._end, 1] = self._begin
|
||||
|
||||
def getColor(self):
|
||||
if self._type == self.Inset0Type:
|
||||
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)
|
||||
return self._color
|
||||
|
||||
def vertexCount(self):
|
||||
return len(self._data)
|
||||
|
@ -257,3 +236,27 @@ class Polygon():
|
|||
@property
|
||||
def lineWidth(self):
|
||||
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.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
from UM.Message import Message
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
|
||||
from cura.OneAtATimeIterator import OneAtATimeIterator
|
||||
from . import Cura_pb2
|
||||
|
@ -62,12 +63,12 @@ class CuraEngineBackend(Backend):
|
|||
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._message_handlers[Cura_pb2.SlicingFinished] = self._onSlicingFinishedMessage
|
||||
self._message_handlers["cura.proto.SlicedObjectList"] = self._onSlicedObjectListMessage
|
||||
self._message_handlers["cura.proto.Progress"] = self._onProgressMessage
|
||||
self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage
|
||||
self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage
|
||||
self._message_handlers["cura.proto.ObjectPrintTime"] = self._onObjectPrintTimeMessage
|
||||
self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage
|
||||
|
||||
self._slicing = False
|
||||
self._restart = False
|
||||
|
@ -230,16 +231,7 @@ class CuraEngineBackend(Backend):
|
|||
self.printDurationMessage.emit(message.time, message.material_amount)
|
||||
|
||||
def _createSocket(self):
|
||||
super()._createSocket()
|
||||
|
||||
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)
|
||||
super()._createSocket(os.path.abspath(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "Cura.proto")))
|
||||
|
||||
## Manually triggers a reslice
|
||||
def forceSlice(self):
|
||||
|
@ -278,7 +270,6 @@ class CuraEngineBackend(Backend):
|
|||
else:
|
||||
self._layer_view_active = False
|
||||
|
||||
|
||||
def _onInstanceChanged(self):
|
||||
self._terminate()
|
||||
self.slicingCancelled.emit()
|
||||
|
|
|
@ -56,21 +56,27 @@ class ProcessSlicedObjectListJob(Job):
|
|||
layer_data = LayerData.LayerData()
|
||||
|
||||
layer_count = 0
|
||||
for object in self._message.objects:
|
||||
layer_count += len(object.layers)
|
||||
for i in range(self._message.repeatedMessageCount("objects")):
|
||||
layer_count += self._message.getRepeatedMessage("objects", i).repeatedMessageCount("layers")
|
||||
|
||||
current_layer = 0
|
||||
for object in self._message.objects:
|
||||
for i in range(self._message.repeatedMessageCount("objects")):
|
||||
object = self._message.getRepeatedMessage("objects", i)
|
||||
try:
|
||||
node = object_id_map[object.id]
|
||||
except KeyError:
|
||||
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.setLayerHeight(layer.id, layer.height)
|
||||
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 = 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)
|
||||
|
@ -83,8 +89,6 @@ class ProcessSlicedObjectListJob(Job):
|
|||
|
||||
layer_data.addPolygon(layer.id, polygon.type, points, polygon.line_width)
|
||||
|
||||
Job.yieldThread()
|
||||
|
||||
current_layer += 1
|
||||
progress = (current_layer / layer_count) * 100
|
||||
# TODO: Rebuild the layer data mesh once the layer has been processed.
|
||||
|
|
|
@ -81,20 +81,21 @@ class StartSliceJob(Job):
|
|||
|
||||
self._sendSettings(self._profile)
|
||||
|
||||
slice_message = Cura_pb2.Slice()
|
||||
slice_message = self._socket.createMessage("cura.proto.Slice");
|
||||
|
||||
for group in object_groups:
|
||||
group_message = slice_message.object_lists.add()
|
||||
group_message = slice_message.addRepeatedMessage("object_lists");
|
||||
for object in group:
|
||||
mesh_data = object.getMeshData().getTransformed(object.getWorldTransformation())
|
||||
|
||||
obj = group_message.objects.add()
|
||||
obj = group_message.addRepeatedMessage("objects");
|
||||
obj.id = id(object)
|
||||
|
||||
verts = numpy.array(mesh_data.getVertices())
|
||||
verts[:,[1,2]] = verts[:,[2,1]]
|
||||
verts[:,1] *= -1
|
||||
obj.vertices = verts.tostring()
|
||||
|
||||
obj.vertices = verts
|
||||
|
||||
self._handlePerObjectSettings(object, obj)
|
||||
|
||||
|
@ -115,13 +116,13 @@ class StartSliceJob(Job):
|
|||
return str(value).encode("utf-8")
|
||||
|
||||
def _sendSettings(self, profile):
|
||||
msg = Cura_pb2.SettingList()
|
||||
msg = self._socket.createMessage("cura.proto.SettingList");
|
||||
settings = profile.getAllSettingValues(include_machine = True)
|
||||
start_gcode = settings["machine_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
|
||||
for key, value in settings.items():
|
||||
s = msg.settings.add()
|
||||
s = msg.addRepeatedMessage("settings")
|
||||
s.name = key
|
||||
if key == "machine_start_gcode" or key == "machine_end_gcode":
|
||||
s.value = self._expandGcodeTokens(key, value, settings)
|
||||
|
@ -134,7 +135,7 @@ class StartSliceJob(Job):
|
|||
profile = node.callDecoration("getProfile")
|
||||
if profile:
|
||||
for key, value in profile.getAllSettingValues().items():
|
||||
setting = message.settings.add()
|
||||
setting = message.addRepeatedMessage("settings")
|
||||
setting.name = key
|
||||
setting.value = str(value).encode()
|
||||
|
||||
|
@ -145,7 +146,7 @@ class StartSliceJob(Job):
|
|||
return
|
||||
|
||||
for key, value in object_settings.items():
|
||||
setting = message.settings.add()
|
||||
setting = message.addRepeatedMessage("settings")
|
||||
setting.name = key
|
||||
setting.value = str(value).encode()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue