Merge branch '15.06'

* 15.06:
  Update changelog
  Correct the bottom offset we add when setting the volume for scale to max
  Display progress information during processing of layer data
  If findObject returns none but object_id != 0 use the selected object
  Offset the displayed rotation angle so it does not overlap the mouse cursor
  Abort attempts to connect if an error is thrown when connecting to the serial port
  Fix recent files on Windows
  Defer opening the webbrowser until the next run of the event loop
  Disable slicing and platform physics when an operation is being performed
  Rework LayerData mesh generation for improved performance
  Performance: Only calculate the platform center once, not for every poly
  Add application icons for all three platforms
This commit is contained in:
Arjen Hiemstra 2015-06-24 12:06:39 +02:00
commit a429e362ad
16 changed files with 190 additions and 51 deletions

View file

@ -59,6 +59,8 @@ class CuraEngineBackend(Backend):
self._save_polygons = True
self._report_progress = True
self._enabled = True
self.backendConnected.connect(self._onBackendConnected)
def getEngineCommand(self):
@ -86,6 +88,9 @@ class CuraEngineBackend(Backend):
# 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 not self._enabled:
return
if self._slicing:
if not kwargs.get("force_restart", True):
return
@ -235,3 +240,10 @@ class CuraEngineBackend(Backend):
if self._restart:
self._onChanged()
self._restart = False
def _onToolOperationStarted(self, tool):
self._enabled = False
def _onToolOperationStopped(self, tool):
self._enabled = True
self._onChanged()

View file

@ -8,6 +8,7 @@ from UM.Math.Vector import Vector
import numpy
import math
import copy
class LayerData(MeshData):
def __init__(self):
@ -48,11 +49,23 @@ class LayerData(MeshData):
self._layers[layer].setThickness(thickness)
def build(self):
vertex_count = 0
for layer, data in self._layers.items():
data.build()
vertex_count += data.vertexCount()
vertices = numpy.empty((vertex_count, 3), numpy.float32)
colors = numpy.empty((vertex_count, 4), numpy.float32)
indices = numpy.empty((vertex_count, 2), numpy.int32)
offset = 0
for layer, data in self._layers.items():
offset = data.build(offset, vertices, colors, indices)
self._element_counts[layer] = data.elementCount
self.addVertices(vertices)
self.addColors(colors)
self.addIndices(indices.flatten())
class Layer():
def __init__(self, id):
self._id = id
@ -83,20 +96,30 @@ class Layer():
def setThickness(self, thickness):
self._thickness = thickness
def build(self):
def vertexCount(self):
result = 0
for polygon in self._polygons:
result += polygon.vertexCount()
return result
def build(self, offset, vertices, colors, indices):
result = offset
for polygon in self._polygons:
if polygon._type == Polygon.InfillType or polygon._type == Polygon.SupportInfillType:
continue
polygon.build()
polygon.build(result, vertices, colors, indices)
result += polygon.vertexCount()
self._element_count += polygon.elementCount
return result
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:
@ -159,43 +182,48 @@ class Polygon():
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
def build(self, offset, vertices, colors, indices):
self._begin = offset
color = self.getColor()
color[3] = 2.0
color.setValues(color.r * 0.5, color.g * 0.5, color.b * 0.5, color.a)
colors = [color for i in range(len(self._data))]
self._mesh.addColors(numpy.array(colors, dtype=numpy.float32) * 0.5)
for i in range(len(self._data)):
vertices[offset + i, :] = self._data[i, :]
colors[offset + i, 0] = color.r
colors[offset + i, 1] = color.g
colors[offset + i, 2] = color.b
colors[offset + i, 3] = color.a
self._end = self._begin + len(self._data) - 1
indices = []
for i in range(self._begin, self._end):
indices.append(i)
indices.append(i + 1)
indices[i, 0] = i
indices[i, 1] = i + 1
indices.append(self._end)
indices.append(self._begin)
self._mesh.addIndices(numpy.array(indices, dtype=numpy.int32))
indices[self._end, 0] = self._end
indices[self._end, 1] = self._begin
def getColor(self):
if self._type == self.Inset0Type:
return [1.0, 0.0, 0.0, 1.0]
return Color(1.0, 0.0, 0.0, 1.0)
elif self._type == self.InsetXType:
return [0.0, 1.0, 0.0, 1.0]
return Color(0.0, 1.0, 0.0, 1.0)
elif self._type == self.SkinType:
return [1.0, 1.0, 0.0, 1.0]
return Color(1.0, 1.0, 0.0, 1.0)
elif self._type == self.SupportType:
return [0.0, 1.0, 1.0, 1.0]
return Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.SkirtType:
return [0.0, 1.0, 1.0, 1.0]
return Color(0.0, 1.0, 1.0, 1.0)
elif self._type == self.InfillType:
return [1.0, 1.0, 0.0, 1.0]
return Color(1.0, 1.0, 0.0, 1.0)
elif self._type == self.SupportInfillType:
return [0.0, 1.0, 1.0, 1.0]
return Color(0.0, 1.0, 1.0, 1.0)
else:
return [1.0, 1.0, 1.0, 1.0]
return Color(1.0, 1.0, 1.0, 1.0)
def vertexCount(self):
return len(self._data)
@property
def type(self):

View file

@ -7,18 +7,30 @@ from UM.Scene.SceneNode import SceneNode
from UM.Application import Application
from UM.Mesh.MeshData import MeshData
from UM.Message import Message
from UM.i18n import i18nCatalog
from . import LayerData
import numpy
import struct
catalog = i18nCatalog("cura")
class ProcessSlicedObjectListJob(Job):
def __init__(self, message):
super().__init__()
self._message = message
self._scene = Application.getInstance().getController().getScene()
self._progress = None
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
def run(self):
if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView":
self._progress = Message(catalog.i18nc("Layers View mode", "Layers"), 0, False, 0)
self._progress.show()
objectIdMap = {}
new_node = SceneNode()
## Put all nodes in a dict identified by ID
@ -32,6 +44,15 @@ class ProcessSlicedObjectListJob(Job):
settings = Application.getInstance().getActiveMachine()
layerHeight = settings.getSettingValueByKey("layer_height")
center = None
if not settings.getSettingValueByKey("machine_center_is_zero"):
center = numpy.array([settings.getSettingValueByKey("machine_width") / 2, 0.0, -settings.getSettingValueByKey("machine_depth") / 2])
else:
center = numpy.array([0.0, 0.0, 0.0])
if self._progress:
self._progress.setProgress(2)
mesh = MeshData()
for object in self._message.objects:
try:
@ -53,15 +74,37 @@ class ProcessSlicedObjectListJob(Job):
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.array(center)
layerData.addPolygon(layer.id, polygon.type, points, polygon.line_width)
if self._progress:
self._progress.setProgress(50)
# 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
if self._progress:
self._progress.setProgress(100)
new_node.setMeshData(mesh)
new_node.setParent(self._scene.getRoot())
view = Application.getInstance().getController().getActiveView()
if view.getPluginId() == "LayerView":
view.resetLayerData()
if self._progress:
self._progress.hide()
def _onActiveViewChanged(self):
if self.isRunning():
if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView":
if not self._progress:
self._progress = Message(catalog.i18nc("Layers View mode", "Layers"), 0, False, 0)
self._progress.show()
else:
if self._progress:
self._progress.hide()

View file

@ -39,6 +39,9 @@ class LayerView(View):
def getMaxLayers(self):
return self._max_layers
def resetLayerData(self):
self._current_layer_mesh = None
def beginRendering(self):
scene = self.getController().getScene()
renderer = self.getRenderer()

View file

@ -173,6 +173,10 @@ class PrinterConnection(SignalEmitter):
Logger.log("i", "Could not establish connection on %s: %s. Device is not arduino based." %(self._serial_port,str(e)))
except Exception as e:
Logger.log("i", "Could not establish connection on %s, unknown reasons. Device is not arduino based." % self._serial_port)
if not self._serial or not programmer.serial:
self._is_connecting = False
return
# If the programmer connected, we know its an atmega based version. Not all that usefull, but it does give some debugging information.
for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect)