mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 07:19:05 +08:00
Merge branch '15.06' of https://github.com/Ultimaker/Cura into 15.06
This commit is contained in:
commit
e3a9386fdf
@ -48,6 +48,9 @@ class ConvexHullNode(SceneNode):
|
||||
|
||||
self.setMeshData(mesh)
|
||||
|
||||
def getWatchedNode(self):
|
||||
return self._node
|
||||
|
||||
def render(self, renderer):
|
||||
if not self._material:
|
||||
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag"))
|
||||
|
@ -1,6 +1,3 @@
|
||||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: Cura.proto
|
||||
|
||||
@ -21,7 +18,7 @@ _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')
|
||||
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\"W\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x02\x12\x11\n\tthickness\x18\x03 \x01(\x02\x12\x1f\n\x08polygons\x18\x04 \x03(\x0b\x32\r.Cura.Polygon\"\xdb\x01\n\x07Polygon\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.Cura.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\x12\x12\n\nline_width\x18\x03 \x01(\x02\"\x89\x01\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\x12\x0e\n\nInfillType\x10\x06\x12\x15\n\x11SupportInfillType\x10\x07\"&\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)
|
||||
|
||||
@ -57,11 +54,19 @@ _POLYGON_TYPE = _descriptor.EnumDescriptor(
|
||||
name='SkirtType', index=5, number=5,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='InfillType', index=6, number=6,
|
||||
options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SupportInfillType', index=7, number=7,
|
||||
options=None,
|
||||
type=None),
|
||||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=430,
|
||||
serialized_end=528,
|
||||
serialized_start=486,
|
||||
serialized_end=623,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_POLYGON_TYPE)
|
||||
|
||||
@ -266,8 +271,22 @@ _LAYER = _descriptor.Descriptor(
|
||||
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,
|
||||
name='height', full_name='Cura.Layer.height', 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='thickness', full_name='Cura.Layer.thickness', 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),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='polygons', full_name='Cura.Layer.polygons', index=3,
|
||||
number=4, 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,
|
||||
@ -284,7 +303,7 @@ _LAYER = _descriptor.Descriptor(
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=314,
|
||||
serialized_end=366,
|
||||
serialized_end=401,
|
||||
)
|
||||
|
||||
|
||||
@ -309,6 +328,13 @@ _POLYGON = _descriptor.Descriptor(
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='line_width', full_name='Cura.Polygon.line_width', 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=[
|
||||
],
|
||||
@ -321,8 +347,8 @@ _POLYGON = _descriptor.Descriptor(
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=369,
|
||||
serialized_end=528,
|
||||
serialized_start=404,
|
||||
serialized_end=623,
|
||||
)
|
||||
|
||||
|
||||
@ -358,8 +384,8 @@ _GCODELAYER = _descriptor.Descriptor(
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=530,
|
||||
serialized_end=568,
|
||||
serialized_start=625,
|
||||
serialized_end=663,
|
||||
)
|
||||
|
||||
|
||||
@ -402,8 +428,8 @@ _OBJECTPRINTTIME = _descriptor.Descriptor(
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=570,
|
||||
serialized_end=638,
|
||||
serialized_start=665,
|
||||
serialized_end=733,
|
||||
)
|
||||
|
||||
|
||||
@ -432,8 +458,8 @@ _SETTINGLIST = _descriptor.Descriptor(
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=640,
|
||||
serialized_end=686,
|
||||
serialized_start=735,
|
||||
serialized_end=781,
|
||||
)
|
||||
|
||||
|
||||
@ -469,8 +495,8 @@ _SETTING = _descriptor.Descriptor(
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=688,
|
||||
serialized_end=726,
|
||||
serialized_start=783,
|
||||
serialized_end=821,
|
||||
)
|
||||
|
||||
|
||||
@ -499,8 +525,8 @@ _GCODEPREFIX = _descriptor.Descriptor(
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=728,
|
||||
serialized_end=755,
|
||||
serialized_start=823,
|
||||
serialized_end=850,
|
||||
)
|
||||
|
||||
_OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT
|
||||
|
@ -2,7 +2,9 @@
|
||||
# Cura is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
from UM.Mesh.MeshData import MeshData
|
||||
from UM.Mesh.MeshBuilder import MeshBuilder
|
||||
from UM.Math.Color import Color
|
||||
from UM.Math.Vector import Vector
|
||||
|
||||
import numpy
|
||||
import math
|
||||
@ -13,12 +15,19 @@ class LayerData(MeshData):
|
||||
self._layers = {}
|
||||
self._element_counts = {}
|
||||
|
||||
def addPolygon(self, layer, type, data):
|
||||
def addLayer(self, layer):
|
||||
if layer not in self._layers:
|
||||
self._layers[layer] = []
|
||||
self._layers[layer] = Layer(layer)
|
||||
|
||||
p = Polygon(self, type, data)
|
||||
self._layers[layer].append(p)
|
||||
def addPolygon(self, layer, type, data, line_width):
|
||||
if layer not in self._layers:
|
||||
self.addLayer(layer)
|
||||
|
||||
p = Polygon(self, type, data, line_width)
|
||||
self._layers[layer].polygons.append(p)
|
||||
|
||||
def getLayer(self, layer):
|
||||
return self._layers[layer]
|
||||
|
||||
def getLayers(self):
|
||||
return self._layers
|
||||
@ -26,14 +35,112 @@ class LayerData(MeshData):
|
||||
def getElementCounts(self):
|
||||
return self._element_counts
|
||||
|
||||
def setLayerHeight(self, layer, height):
|
||||
if layer not in self._layers:
|
||||
self.addLayer(layer)
|
||||
|
||||
self._layers[layer].setHeight(height)
|
||||
|
||||
def setLayerThickness(self, layer, thickness):
|
||||
if layer not in self._layers:
|
||||
self.addLayer(layer)
|
||||
|
||||
self._layers[layer].setThickness(thickness)
|
||||
|
||||
def build(self):
|
||||
for layer, data in self._layers.items():
|
||||
if layer not in self._element_counts:
|
||||
self._element_counts[layer] = []
|
||||
data.build()
|
||||
|
||||
for polygon in data:
|
||||
polygon.build()
|
||||
self._element_counts[layer].append(polygon.elementCount)
|
||||
self._element_counts[layer] = data.elementCount
|
||||
|
||||
class Layer():
|
||||
def __init__(self, id):
|
||||
self._id = id
|
||||
self._height = 0.0
|
||||
self._thickness = 0.0
|
||||
self._polygons = []
|
||||
self._element_count = 0
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
return self._height
|
||||
|
||||
@property
|
||||
def thickness(self):
|
||||
return self._thickness
|
||||
|
||||
@property
|
||||
def polygons(self):
|
||||
return self._polygons
|
||||
|
||||
@property
|
||||
def elementCount(self):
|
||||
return self._element_count
|
||||
|
||||
def setHeight(self, height):
|
||||
self._height = height
|
||||
|
||||
def setThickness(self, thickness):
|
||||
self._thickness = thickness
|
||||
|
||||
def build(self):
|
||||
for polygon in self._polygons:
|
||||
if polygon._type == Polygon.InfillType or polygon._type == Polygon.SupportInfillType:
|
||||
continue
|
||||
|
||||
polygon.build()
|
||||
self._element_count += polygon.elementCount
|
||||
|
||||
def createMesh(self):
|
||||
builder = MeshBuilder()
|
||||
|
||||
for polygon in self._polygons:
|
||||
poly_color = polygon.getColor()
|
||||
poly_color = Color(poly_color[0], poly_color[1], poly_color[2], poly_color[3])
|
||||
|
||||
points = numpy.copy(polygon.data)
|
||||
if polygon.type == Polygon.InfillType or polygon.type == Polygon.SkinType or polygon.type == Polygon.SupportInfillType:
|
||||
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
|
||||
|
||||
# Scale all by the line width of the polygon so we can easily offset.
|
||||
normals *= (polygon.lineWidth / 2)
|
||||
|
||||
#TODO: Use numpy magic to perform the vertex creation to speed up things.
|
||||
for i in range(len(points)):
|
||||
start = points[i - 1]
|
||||
end = points[i]
|
||||
|
||||
normal = normals[i - 1]
|
||||
|
||||
point1 = Vector(data = start - normal)
|
||||
point2 = Vector(data = start + normal)
|
||||
point3 = Vector(data = end + normal)
|
||||
point4 = Vector(data = end - normal)
|
||||
|
||||
builder.addQuad(point1, point2, point3, point4, color = poly_color)
|
||||
|
||||
return builder.getData()
|
||||
|
||||
class Polygon():
|
||||
NoneType = 0
|
||||
@ -42,34 +149,26 @@ class Polygon():
|
||||
SkinType = 3
|
||||
SupportType = 4
|
||||
SkirtType = 5
|
||||
InfillType = 6
|
||||
SupportInfillType = 7
|
||||
|
||||
def __init__(self, mesh, type, data):
|
||||
def __init__(self, mesh, type, data, line_width):
|
||||
super().__init__()
|
||||
self._mesh = mesh
|
||||
self._type = type
|
||||
self._data = data
|
||||
self._line_width = line_width / 1000
|
||||
|
||||
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]
|
||||
color = self.getColor()
|
||||
color[3] = 2.0
|
||||
|
||||
colors = [color for i in range(len(self._data))]
|
||||
self._mesh.addColors(numpy.array(colors, dtype=numpy.float32))
|
||||
self._mesh.addColors(numpy.array(colors, dtype=numpy.float32) * 0.5)
|
||||
|
||||
indices = []
|
||||
for i in range(self._begin, self._end):
|
||||
@ -80,6 +179,24 @@ class Polygon():
|
||||
indices.append(self._begin)
|
||||
self._mesh.addIndices(numpy.array(indices, dtype=numpy.int32))
|
||||
|
||||
def getColor(self):
|
||||
if self._type == self.Inset0Type:
|
||||
return [1.0, 0.0, 0.0, 1.0]
|
||||
elif self._type == self.InsetXType:
|
||||
return [0.0, 1.0, 0.0, 1.0]
|
||||
elif self._type == self.SkinType:
|
||||
return [1.0, 1.0, 0.0, 1.0]
|
||||
elif self._type == self.SupportType:
|
||||
return [0.0, 1.0, 1.0, 1.0]
|
||||
elif self._type == self.SkirtType:
|
||||
return [0.0, 1.0, 1.0, 1.0]
|
||||
elif self._type == self.InfillType:
|
||||
return [1.0, 1.0, 0.0, 1.0]
|
||||
elif self._type == self.SupportInfillType:
|
||||
return [0.0, 1.0, 1.0, 1.0]
|
||||
else:
|
||||
return [1.0, 1.0, 1.0, 1.0]
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
@ -90,4 +207,8 @@ class Polygon():
|
||||
|
||||
@property
|
||||
def elementCount(self):
|
||||
return (self._end - self._begin) * 2 #The range of vertices multiplied by 2 since each vertex is used twice
|
||||
return ((self._end - self._begin) + 1) * 2 #The range of vertices multiplied by 2 since each vertex is used twice
|
||||
|
||||
@property
|
||||
def lineWidth(self):
|
||||
return self._line_width
|
||||
|
@ -32,22 +32,24 @@ class ProcessSlicedObjectListJob(Job):
|
||||
settings = Application.getInstance().getActiveMachine()
|
||||
layerHeight = settings.getSettingValueByKey("layer_height")
|
||||
|
||||
mesh = MeshData()
|
||||
for object in self._message.objects:
|
||||
try:
|
||||
try:
|
||||
node = objectIdMap[object.id]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
mesh = MeshData()
|
||||
|
||||
layerData = LayerData.LayerData()
|
||||
for layer in object.layers:
|
||||
layerData.addLayer(layer.id)
|
||||
layerData.setLayerHeight(layer.id, layer.height)
|
||||
layerData.setLayerThickness(layer.id, layer.thickness)
|
||||
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 = numpy.insert(points, 1, (layer.height / 1000), axis = 1)
|
||||
|
||||
points[:,2] *= -1
|
||||
|
||||
@ -55,16 +57,11 @@ class ProcessSlicedObjectListJob(Job):
|
||||
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, polygon.line_width)
|
||||
|
||||
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
|
||||
|
||||
# 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())
|
||||
|
@ -7,9 +7,13 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Resources import Resources
|
||||
from UM.Event import Event, KeyEvent
|
||||
from UM.Signal import Signal
|
||||
from . import LayerViewProxy
|
||||
from UM.Scene.Selection import Selection
|
||||
from UM.Math.Color import Color
|
||||
from UM.Mesh.MeshData import MeshData
|
||||
|
||||
from cura.ConvexHullNode import ConvexHullNode
|
||||
|
||||
from . import LayerViewProxy
|
||||
|
||||
## View used to display g-code paths.
|
||||
class LayerView(View):
|
||||
@ -22,6 +26,9 @@ class LayerView(View):
|
||||
self._controller.getScene().sceneChanged.connect(self._onSceneChanged)
|
||||
self._max_layers = 10
|
||||
self._current_layer_num = 10
|
||||
self._current_layer_mesh = None
|
||||
|
||||
self._solid_layers = 5
|
||||
|
||||
def getCurrentLayer(self):
|
||||
return self._current_layer_num
|
||||
@ -45,6 +52,11 @@ class LayerView(View):
|
||||
self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128))
|
||||
|
||||
for node in DepthFirstIterator(scene.getRoot()):
|
||||
# We do not want to render ConvexHullNode as it conflicts with the bottom layers.
|
||||
# However, it is somewhat relevant when the node is selected, so do render it then.
|
||||
if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()):
|
||||
continue
|
||||
|
||||
if not node.render(renderer):
|
||||
if node.getMeshData() and node.isVisible():
|
||||
if Selection.isSelected(node):
|
||||
@ -55,19 +67,39 @@ class LayerView(View):
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
start = 0
|
||||
end = 0
|
||||
# Render all layers below a certain number as line mesh instead of vertices.
|
||||
if self._current_layer_num - self._solid_layers > -1:
|
||||
start = 0
|
||||
end = 0
|
||||
element_counts = layer_data.getElementCounts()
|
||||
for layer, counts in element_counts.items():
|
||||
if layer + self._solid_layers > self._current_layer_num:
|
||||
break
|
||||
end += counts
|
||||
|
||||
element_counts = layer_data.getElementCounts()
|
||||
for layer, counts in element_counts.items():
|
||||
end += sum(counts)
|
||||
## Hack to ensure the end is correct. Not quite sure what causes this
|
||||
end += 2 * len(counts)
|
||||
# This uses glDrawRangeElements internally to only draw a certain range of lines.
|
||||
renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end)
|
||||
|
||||
if layer >= self._current_layer_num:
|
||||
break
|
||||
# We currently recreate the current "solid" layers every time a
|
||||
if not self._current_layer_mesh:
|
||||
self._current_layer_mesh = MeshData()
|
||||
for i in range(self._solid_layers):
|
||||
layer = self._current_layer_num - i
|
||||
if layer < 0:
|
||||
continue
|
||||
|
||||
renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end)
|
||||
layer_mesh = layer_data.getLayer(layer).createMesh()
|
||||
if not layer_mesh or layer_mesh.getVertices() is None:
|
||||
continue
|
||||
|
||||
self._current_layer_mesh.addVertices(layer_mesh.getVertices())
|
||||
|
||||
# Scale layer color by a brightness factor based on the current layer number
|
||||
# This will result in a range of 0.5 - 1.0 to multiply colors by.
|
||||
brightness = (2.0 - (i / self._solid_layers)) / 2.0
|
||||
self._current_layer_mesh.addColors(layer_mesh.getColors() * brightness)
|
||||
|
||||
renderer.queueNode(node, mesh = self._current_layer_mesh, material = self._material)
|
||||
|
||||
def setLayer(self, value):
|
||||
if self._current_layer_num != value:
|
||||
@ -76,6 +108,8 @@ class LayerView(View):
|
||||
self._current_layer_num = 0
|
||||
if self._current_layer_num > self._max_layers:
|
||||
self._current_layer_num = self._max_layers
|
||||
|
||||
self._current_layer_mesh = None
|
||||
self.currentLayerNumChanged.emit()
|
||||
|
||||
currentLayerNumChanged = Signal()
|
||||
@ -96,7 +130,7 @@ class LayerView(View):
|
||||
except AttributeError:
|
||||
continue
|
||||
if new_max_layers < len(layer_data.getLayers()):
|
||||
new_max_layers = len(layer_data.getLayers())
|
||||
new_max_layers = len(layer_data.getLayers()) - 1
|
||||
|
||||
if new_max_layers > 0 and new_max_layers != self._old_max_layers:
|
||||
self._max_layers = new_max_layers
|
||||
|
Loading…
x
Reference in New Issue
Block a user