wx.EVT_CLOSE(self, self.OnClose)
- self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
+ self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.loadSupportedExtensions()))
self.normalModeOnlyItems = []
self.menubar = wx.MenuBar()
self.fileMenu = wx.Menu()
i = self.fileMenu.Append(-1, 'Load model file...\tCTRL+L')
- self.Bind(wx.EVT_MENU, lambda e: self.scene.ShowLoadModel(1), i)
+ self.Bind(wx.EVT_MENU, lambda e: self.scene.showLoadModel(), i)
+ i = self.fileMenu.Append(-1, 'Save model...\tCTRL+S')
+ self.Bind(wx.EVT_MENU, lambda e: self.scene.showSaveModel(), i)
+
+ self.fileMenu.AppendSeparator()
i = self.fileMenu.Append(-1, 'Print...\tCTRL+P')
- self.Bind(wx.EVT_MENU, lambda e: self.scene.ShowPrintWindow(), i)
+ self.Bind(wx.EVT_MENU, lambda e: self.scene.showPrintWindow(), i)
i = self.fileMenu.Append(-1, 'Save GCode...')
self.Bind(wx.EVT_MENU, lambda e: self.scene.showSaveGCode(), i)
if wx.TheClipboard.GetData(data):
data = data.GetText()
if re.match('^http://.*/.*$', data):
- if data.endswith(tuple(meshLoader.supportedExtensions())):
+ if data.endswith(tuple(meshLoader.loadSupportedExtensions())):
#Got an url on the clipboard with a model file.
pass
wx.TheClipboard.Close()
self.SetSizer(wx.BoxSizer(wx.VERTICAL))
self.GetSizer().Add(self.panel, 1, flag=wx.EXPAND)
- self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
+ self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.loadSupportedExtensions()))
self.list = []
self.selection = None
self._projMatrix = None
self.tempMatrix = None
- self.openFileButton = openglGui.glButton(self, 4, 'Load', (0,0), self.ShowLoadModel)
- self.printButton = openglGui.glButton(self, 6, 'Print', (1,0), self.ShowPrintWindow)
+ self.openFileButton = openglGui.glButton(self, 4, 'Load', (0,0), self.showLoadModel)
+ self.printButton = openglGui.glButton(self, 6, 'Print', (1,0), self.showPrintWindow)
self.printButton.setDisabled(True)
group = []
self.updateToolButtons()
self.updateProfileToControls()
- def ShowLoadModel(self, button):
+ def showLoadModel(self, button = 1):
if button == 1:
dlg=wx.FileDialog(self, 'Open 3D model', os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
- dlg.SetWildcard(meshLoader.wildcardFilter())
+ dlg.SetWildcard(meshLoader.loadWildcardFilter())
if dlg.ShowModal() != wx.ID_OK:
dlg.Destroy()
return
self.GetParent().GetParent().GetParent().addToModelMRU(filename)
self.loadScene([filename])
- def ShowPrintWindow(self, button):
+ def showSaveModel(self):
+ if len(self._scene.objects()) < 1:
+ return
+ dlg=wx.FileDialog(self, 'Save 3D model', os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
+ dlg.SetWildcard(meshLoader.saveWildcardFilter())
+ if dlg.ShowModal() != wx.ID_OK:
+ dlg.Destroy()
+ return
+ filename = dlg.GetPath()
+ dlg.Destroy()
+ meshLoader.saveMeshes(filename, self._scene.objects())
+
+ def showPrintWindow(self, button):
if button == 1:
if machineCom.machineIsConnected():
printWindow.printFile(self._slicer.getGCodeFilename())
self._selectedObj.resetRotation()
self._scene.pushFree()
self._selectObject(self._selectedObj)
+ self.sceneUpdated()
def OnLayFlat(self, button):
if self._selectedObj is None:
self._selectedObj.layFlat()
self._scene.pushFree()
self._selectObject(self._selectedObj)
+ self.sceneUpdated()
def OnScaleReset(self, button):
if self._selectedObj is None:
return
self._selectedObj.resetScale()
+ self._selectObject(self._selectedObj)
+ self.updateProfileToControls()
+ self.sceneUpdated()
def OnScaleMax(self, button):
if self._selectedObj is None:
self.list = []
- self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
+ self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.loadSupportedExtensions()))
wx.EVT_CLOSE(self, self.OnClose)
self.panel = wx.Panel(self, -1)
faceCount += 1
if y == sy - 1 or not self.isSolid[blocks[x, y + 1, z]]:
faceCount += 1
- m = mesh.mesh()
+
+ obj = mesh.printableObject()
+ m = obj._addMesh()
m._prepareFaceCount(faceCount * 2)
for x in xrange(0, sx):
for y in xrange(0, sy):
m._addFace(x+1, y+1, z+1, x+1, y+1, z, x, y+1, z+1)
- stlFilename = os.path.join(os.path.dirname(self.level.filename), 'export.stl')
- stl.saveAsSTL(m, stlFilename)
- self.GetParent().scene.loadScene([stlFilename])
+ obj._postProcessAfterLoad()
+ self.GetParent().scene._scene.add(obj)
glColor4ub(255,255,255,255)
opengl.glDrawStringCenter(self._tooltip)
glPopMatrix()
- if self._progressBar is not None:
+ progress = self._progressBar
+ if progress is not None:
glColor4ub(255,255,255,192)
opengl.glDrawTexturedQuad(pos[0]-bs/2, pos[1]+bs/2, bs, bs / 4, 0)
- opengl.glDrawTexturedQuad(pos[0]-bs/2, pos[1]+bs/2, bs * self._progressBar, bs / 4, 0)
+ opengl.glDrawTexturedQuad(pos[0]-bs/2, pos[1]+bs/2, bs * progress, bs / 4, 0)
elif len(self._altTooltip) > 0:
glPushMatrix()
glTranslatef(pos[0], pos[1], 0)
def copy(self):
ret = printableObject()
ret._matrix = self._matrix.copy()
- ret._meshList = self._meshList[:]
- ret._transformedMin = self._transformedMin
- ret._transformedMax = self._transformedMin
- ret._transformedSize = self._transformedSize
+ ret._transformedMin = self._transformedMin.copy()
+ ret._transformedMax = self._transformedMin.copy()
+ ret._transformedSize = self._transformedSize.copy()
ret._boundaryCircleSize = self._boundaryCircleSize
- ret._drawOffset = self._drawOffset
- for m in ret._meshList:
- m.vbo.incRef()
+ ret._drawOffset = self._drawOffset.copy()
+ for m in self._meshList[:]:
+ m2 = ret._addMesh()
+ m2.vertexes = m.vertexes
+ m2.vertexCount = m.vertexCount
+ m2.vbo = m.vbo
+ m2.vbo.incRef()
return ret
def _addMesh(self):
- m = mesh()
+ m = mesh(self)
self._meshList.append(m)
return m
self._boundaryCircleSize = 0
for m in self._meshList:
- transformedVertexes = (numpy.matrix(m.vertexes, copy = False) * numpy.matrix(self._matrix, numpy.float32)).getA()
+ transformedVertexes = m.getTransformedVertexes()
transformedMin = transformedVertexes.min(0)
transformedMax = transformedVertexes.max(0)
for n in xrange(0, 3):
self.processMatrix()
def layFlat(self):
- transformedVertexes = (numpy.matrix(self._meshList[0].vertexes, copy = False) * self._matrix).getA()
+ transformedVertexes = self.getTransformedVertexes()
minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
dotMin = 1.0
dotV = None
self._matrix *= numpy.matrix([[math.cos(rad), 0, math.sin(rad)], [0,1,0], [-math.sin(rad), 0, math.cos(rad)]], numpy.float64)
- transformedVertexes = (numpy.matrix(self._meshList[0].vertexes, copy = False) * self._matrix).getA()
+ transformedVertexes = self.getTransformedVertexes()
minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
dotMin = 1.0
dotV = None
def split(self, callback):
ret = []
for oriMesh in self._meshList:
- for m in oriMesh.split(callback):
- obj = printableObject()
- obj._meshList.append(m)
- obj._matrix = self._matrix.copy()
- obj._postProcessAfterLoad()
- ret.append(obj)
+ ret += oriMesh.split(callback)
return ret
class mesh(object):
- def __init__(self):
+ def __init__(self, obj):
self.vertexes = None
self.vertexCount = 0
self.vbo = None
+ self._obj = obj
def _addFace(self, x0, y0, z0, x1, y1, z1, x2, y2, z2):
n = self.vertexCount
if numpy.linalg.norm(self.vertexes[i] - self.vertexes[idx]) < 0.001:
return i
+ def getTransformedVertexes(self, applyOffsets = False):
+ if applyOffsets:
+ pos = self._obj._position.copy()
+ pos.resize((3))
+ pos[2] = self._obj.getSize()[2] / 2
+ offset = self._obj._drawOffset.copy()
+ offset[2] += self._obj.getSize()[2] / 2
+ return (numpy.matrix(self.vertexes, copy = False) * numpy.matrix(self._obj._matrix, numpy.float32)).getA() - offset + pos
+ return (numpy.matrix(self.vertexes, copy = False) * numpy.matrix(self._obj._matrix, numpy.float32)).getA()
+
def split(self, callback):
vertexMap = {}
doneSet.add(i)
todoList.append(i)
- m = mesh()
+ obj = printableObject()
+ obj._matrix = self._obj._matrix.copy()
+ m = obj._addMesh()
m._prepareFaceCount(len(meshFaceList))
for idx in meshFaceList:
m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][0]]
m.vertexCount += 1
m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][2]]
m.vertexCount += 1
- ret.append(m)
+ obj._postProcessAfterLoad()
+ ret.append(obj)
return ret
from Cura.util.meshLoaders import dae
from Cura.util.meshLoaders import amf
-def supportedExtensions():
+def loadSupportedExtensions():
return ['.stl', '.obj', '.dae', '.amf']
-def wildcardFilter():
- wildcardList = ';'.join(map(lambda s: '*' + s, supportedExtensions()))
+def saveSupportedExtensions():
+ return ['.amf', '.stl']
+
+def loadWildcardFilter():
+ wildcardList = ';'.join(map(lambda s: '*' + s, loadSupportedExtensions()))
+ return "Mesh files (%s)|%s;%s" % (wildcardList, wildcardList, wildcardList.upper())
+
+def saveWildcardFilter():
+ wildcardList = ';'.join(map(lambda s: '*' + s, saveSupportedExtensions()))
return "Mesh files (%s)|%s;%s" % (wildcardList, wildcardList, wildcardList.upper())
#loadMeshes loads 1 or more printableObjects from a file.
return amf.loadScene(filename)
print 'Error: Unknown model extension: %s' % (ext)
return []
+
+def saveMeshes(filename, objects):
+ ext = filename[filename.rfind('.'):].lower()
+ if ext == '.stl':
+ stl.saveScene(filename, objects)
+ return
+ if ext == '.amf':
+ amf.saveScene(filename, objects)
+ return
+ print 'Error: Unknown model extension: %s' % (ext)
obj._postProcessAfterLoad()
return [obj]
-def saveAsSTL(mesh, filename):
+def saveScene(filename, objects):
f = open(filename, 'wb')
#Write the STL binary header. This can contain any info, except for "SOLID" at the start.
f.write(("CURA BINARY STL EXPORT. " + time.strftime('%a %d %b %Y %H:%M:%S')).ljust(80, '\000'))
- #Next follow 4 binary bytes containing the amount of faces, and then the face information.
- f.write(struct.pack("<I", int(mesh.vertexCount / 3)))
- for idx in xrange(0, mesh.vertexCount, 3):
- v1 = mesh.vertexes[idx]
- v2 = mesh.vertexes[idx+1]
- v3 = mesh.vertexes[idx+2]
- f.write(struct.pack("<fff", 0.0, 0.0, 0.0))
- f.write(struct.pack("<fff", v1[0], v1[1], v1[2]))
- f.write(struct.pack("<fff", v2[0], v2[1], v2[2]))
- f.write(struct.pack("<fff", v3[0], v3[1], v3[2]))
- f.write(struct.pack("<H", 0))
- f.close()
-if __name__ == '__main__':
- for filename in sys.argv[1:]:
- m = stlModel().load(filename)
- print("Loaded %d faces" % (m.vertexCount / 3))
- parts = m.splitToParts()
- for p in parts:
- saveAsSTL(p, "export_%i.stl" % parts.index(p))
+ vertexCount = 0
+ for obj in objects:
+ for m in obj._meshList:
+ vertexCount += m.vertexCount
+ #Next follow 4 binary bytes containing the amount of faces, and then the face information.
+ f.write(struct.pack("<I", int(vertexCount / 3)))
+ for obj in objects:
+ for m in obj._meshList:
+ vertexes = m.getTransformedVertexes(True)
+ for idx in xrange(0, m.vertexCount, 3):
+ v1 = vertexes[idx]
+ v2 = vertexes[idx+1]
+ v3 = vertexes[idx+2]
+ f.write(struct.pack("<fff", 0.0, 0.0, 0.0))
+ f.write(struct.pack("<fff", v1[0], v1[1], v1[2]))
+ f.write(struct.pack("<fff", v2[0], v2[1], v2[2]))
+ f.write(struct.pack("<fff", v3[0], v3[1], v3[2]))
+ f.write(struct.pack("<H", 0))
+ f.close()