import traceback
import threading
import math
+import platform
import OpenGL
OpenGL.ERROR_CHECKING = False
from Cura.util import machineCom
from Cura.util import removableStorage
from Cura.util import gcodeInterpreter
+from Cura.util.printerConnection import printerConnectionManager
from Cura.gui.util import previewTools
from Cura.gui.util import opengl
from Cura.gui.util import openglGui
from Cura.gui.tools import youmagineGui
+from Cura.gui.tools import imageToMesh
class SceneView(openglGui.glGuiPanel):
def __init__(self, parent):
self._platformMesh = {}
self._isSimpleMode = True
self._usbPrintMonitor = printWindow.printProcessMonitor(lambda : self._queueRefresh())
+ self._printerConnectionManager = printerConnectionManager.PrinterConnectionManager()
self._viewport = None
self._modelMatrix = None
def loadSceneFiles(self, filenames):
self.youMagineButton.setDisabled(False)
- if self.viewSelection.getValue() == 4:
- self.viewSelection.setValue(0)
- self.OnViewChange()
+ #if self.viewSelection.getValue() == 4:
+ # self.viewSelection.setValue(0)
+ # self.OnViewChange()
self.loadScene(filenames)
def loadFiles(self, filenames):
+ mainWindow = self.GetParent().GetParent().GetParent()
+ # only one GCODE file can be active
+ # so if single gcode file, process this
+ # otherwise ignore all gcode files
gcodeFilename = None
- for filename in filenames:
- self.GetParent().GetParent().GetParent().addToModelMRU(filename)
- ext = filename[filename.rfind('.')+1:].upper()
- if ext == 'G' or ext == 'GCODE':
+ if len(filenames) == 1:
+ filename = filenames[0]
+ ext = os.path.splitext(filename)[1].lower()
+ if ext == '.g' or ext == '.gcode':
gcodeFilename = filename
+ mainWindow.addToModelMRU(filename)
if gcodeFilename is not None:
self.loadGCodeFile(gcodeFilename)
else:
- self.loadSceneFiles(filenames)
+ # process directories and special file types
+ # and keep scene files for later processing
+ scene_filenames = []
+ ignored_types = dict()
+ # use file list as queue
+ # pop first entry for processing and append new files at end
+ while filenames:
+ filename = filenames.pop(0)
+ if os.path.isdir(filename):
+ # directory: queue all included files and directories
+ filenames.extend(os.path.join(filename, f) for f in os.listdir(filename))
+ else:
+ ext = os.path.splitext(filename)[1].lower()
+ if ext == '.ini':
+ profile.loadProfile(filename)
+ mainWindow.addToProfileMRU(filename)
+ elif ext in meshLoader.loadSupportedExtensions() or ext in imageToMesh.supportedExtensions():
+ scene_filenames.append(filename)
+ mainWindow.addToModelMRU(filename)
+ else:
+ ignored_types[ext] = 1
+ if ignored_types:
+ ignored_types = ignored_types.keys()
+ ignored_types.sort()
+ self.notification.message("ignored: " + " ".join("*" + type for type in ignored_types))
+ mainWindow.updateProfileToAllControls()
+ # now process all the scene files
+ if scene_filenames:
+ self.loadSceneFiles(scene_filenames)
+ self._selectObject(None)
+ self.sceneUpdated()
+ newZoom = numpy.max(self._machineSize)
+ self._animView = openglGui.animation(self, self._viewTarget.copy(), numpy.array([0,0,0], numpy.float32), 0.5)
+ self._animZoom = openglGui.animation(self, self._zoom, newZoom, 0.5)
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|wx.FD_MULTIPLE)
- dlg.SetWildcard(meshLoader.loadWildcardFilter() + "|GCode file (*.gcode)|*.g;*.gcode;*.G;*.GCODE")
+ dlg.SetWildcard(meshLoader.loadWildcardFilter() + imageToMesh.wildcardList() + "|GCode file (*.gcode)|*.g;*.gcode;*.G;*.GCODE")
if dlg.ShowModal() != wx.ID_OK:
dlg.Destroy()
return
def OnPrintButton(self, button):
if button == 1:
+
+ connectionEntry = self._printerConnectionManager.getAvailableConnection()
if machineCom.machineIsConnected():
self.showPrintWindow()
- elif len(removableStorage.getPossibleSDcardDrives()) > 0:
+ elif len(removableStorage.getPossibleSDcardDrives()) > 0 and (connectionEntry is None or connectionEntry.priority < 0):
drives = removableStorage.getPossibleSDcardDrives()
if len(drives) > 1:
dlg = wx.SingleChoiceDialog(self, "Select SD drive", "Multiple removable drives have been found,\nplease select your SD card drive", map(lambda n: n[0], drives))
drive = drives[0]
filename = self._scene._objectList[0].getName() + '.gcode'
threading.Thread(target=self._copyFile,args=(self._gcodeFilename, drive[1] + filename, drive[1])).start()
+ elif connectionEntry is not None:
+ connectionEntry.connection.loadFile(self._gcodeFilename)
+ connectionEntry.connection.startPrint()
else:
self.showSaveGCode()
if button == 3:
def showPrintWindow(self):
if self._gcodeFilename is None:
return
+ if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
+ wx.MessageBox(_("USB printing on the Ultimaker2 is not supported."), _("USB Printing Error"), wx.OK | wx.ICON_WARNING)
+ return
self._usbPrintMonitor.loadFile(self._gcodeFilename, self._slicer.getID())
if self._gcodeFilename == self._slicer.getGCodeFilename():
self._slicer.submitSliceInfoOnline()
def showSaveGCode(self):
- defPath = profile.getPreference('lastFile')
- defPath = defPath[0:defPath.rfind('.')] + '.gcode'
- dlg=wx.FileDialog(self, _("Save toolpath"), defPath, style=wx.FD_SAVE)
- dlg.SetFilename(self._scene._objectList[0].getName())
+ if len(self._scene._objectList) < 1:
+ return
+ dlg=wx.FileDialog(self, _("Save toolpath"), os.path.dirname(profile.getPreference('lastFile')), style=wx.FD_SAVE)
+ filename = self._scene._objectList[0].getName() + '.gcode'
+ dlg.SetFilename(filename)
dlg.SetWildcard('Toolpath (*.gcode)|*.gcode;*.g')
if dlg.ShowModal() != wx.ID_OK:
dlg.Destroy()
def OnScaleMax(self, button):
if self._selectedObj is None:
return
- self._selectedObj.scaleUpTo(self._machineSize - numpy.array(profile.calculateObjectSizeOffsets() + [0.0], numpy.float32) * 2 - numpy.array([1,1,1], numpy.float32))
+ machine = profile.getMachineSetting('machine_type')
+ self._selectedObj.setPosition(numpy.array([0.0, 0.0]))
+ self._scene.pushFree()
+ #self.sceneUpdated()
+ if machine == "ultimaker2":
+ #This is bad and Jaime should feel bad!
+ self._selectedObj.setPosition(numpy.array([0.0,-10.0]))
+ self._selectedObj.scaleUpTo(self._machineSize - numpy.array(profile.calculateObjectSizeOffsets() + [0.0], numpy.float32) * 2 - numpy.array([1,1,1], numpy.float32))
+ self._selectedObj.setPosition(numpy.array([0.0,0.0]))
+ self._scene.pushFree()
+ else:
+ self._selectedObj.setPosition(numpy.array([0.0, 0.0]))
+ self._scene.pushFree()
+ self._selectedObj.scaleUpTo(self._machineSize - numpy.array(profile.calculateObjectSizeOffsets() + [0.0], numpy.float32) * 2 - numpy.array([1,1,1], numpy.float32))
self._scene.pushFree()
self._selectObject(self._selectedObj)
self.updateProfileToControls()
if self._focusObj is None:
return
obj = self._focusObj
- dlg = wx.NumberEntryDialog(self, "How many copies do you want?", "Copies", "Multiply", 1, 1, 100)
+ dlg = wx.NumberEntryDialog(self, _("How many copies do you want?"), _("Number of copies"), _("Multiply"), 1, 1, 100)
if dlg.ShowModal() != wx.ID_OK:
dlg.Destroy()
return
return
self._focusObj.setPosition(numpy.array([0.0, 0.0]))
self._scene.pushFree()
+ newViewPos = numpy.array([self._focusObj.getPosition()[0], self._focusObj.getPosition()[1], self._focusObj.getSize()[2] / 2])
+ self._animView = openglGui.animation(self, self._viewTarget.copy(), newViewPos, 0.5)
+ self.sceneUpdated()
def _splitCallback(self, progress):
print progress
def sceneUpdated(self):
self._sceneUpdateTimer.Start(500, True)
self._slicer.abortSlicer()
- self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
+ self._scene.updateSizeOffsets()
self.QueueRefresh()
def _onRunSlicer(self, e):
self._gcodeVBOs = []
if ready:
self.printButton.setProgressBar(None)
- cost = self._slicer.getFilamentCost()
- if cost is not None:
- self.printButton.setBottomText('%s\n%s\n%s' % (self._slicer.getPrintTime(), self._slicer.getFilamentAmount(), cost))
- else:
- self.printButton.setBottomText('%s\n%s' % (self._slicer.getPrintTime(), self._slicer.getFilamentAmount()))
+ text = '%s' % (self._slicer.getPrintTime())
+ for e in xrange(0, int(profile.getMachineSetting('extruder_amount'))):
+ amount = self._slicer.getFilamentAmount(e)
+ if amount is None:
+ continue
+ text += '\n%s' % (amount)
+ cost = self._slicer.getFilamentCost(e)
+ if cost is not None:
+ text += '\n%s' % (cost)
+ self.printButton.setBottomText(text)
self._gcode = gcodeInterpreter.gcode()
self._gcodeFilename = self._slicer.getGCodeFilename()
else:
self._gcode.load(self._gcodeFilename)
def _gcodeLoadCallback(self, progress):
- if self._gcode is None:
+ if not self or self._gcode is None:
return True
if len(self._gcode.layerList) % 15 == 0:
time.sleep(0.1)
def loadScene(self, fileList):
for filename in fileList:
try:
- objList = meshLoader.loadMeshes(filename)
+ ext = os.path.splitext(filename)[1].lower()
+ if ext in imageToMesh.supportedExtensions():
+ imageToMesh.convertImageDialog(self, filename).Show()
+ objList = []
+ else:
+ objList = meshLoader.loadMeshes(filename)
except:
traceback.print_exc()
else:
self.updateProfileToControls()
self.updateToolButtons()
if zoom and obj is not None:
- newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2])
+ newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2])
self._animView = openglGui.animation(self, self._viewTarget.copy(), newViewPos, 0.5)
newZoom = obj.getBoundaryCircle() * 6
if newZoom > numpy.max(self._machineSize) * 3:
self._objColors[2] = profile.getPreferenceColour('model_colour3')
self._objColors[3] = profile.getPreferenceColour('model_colour4')
self._scene.setMachineSize(self._machineSize)
- self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
self._scene.setHeadSize(profile.getMachineSettingFloat('extruder_head_size_min_x'), profile.getMachineSettingFloat('extruder_head_size_max_x'), profile.getMachineSettingFloat('extruder_head_size_min_y'), profile.getMachineSettingFloat('extruder_head_size_max_y'), profile.getMachineSettingFloat('extruder_head_size_height'))
if self._selectedObj is not None:
self.scaleZmmctrl.setValue(round(size[2], 2))
def OnKeyChar(self, keyCode):
- if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
+ if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE or (keyCode == wx.WXK_BACK and platform.system() == "Darwin"):
if self._selectedObj is not None:
self._deleteObject(self._selectedObj)
self.QueueRefresh()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
def OnPaint(self,e):
+ connectionEntry = self._printerConnectionManager.getAvailableConnection()
if machineCom.machineIsConnected():
self.printButton._imageID = 6
self.printButton._tooltip = _("Print")
- elif len(removableStorage.getPossibleSDcardDrives()) > 0:
+ elif len(removableStorage.getPossibleSDcardDrives()) > 0 and (connectionEntry is None or connectionEntry.priority < 0):
self.printButton._imageID = 2
self.printButton._tooltip = _("Toolpath to SD")
+ elif connectionEntry is not None:
+ self.printButton._imageID = connectionEntry.icon
+ self.printButton._tooltip = _("Print with %s") % (connectionEntry.name)
else:
self.printButton._imageID = 3
self.printButton._tooltip = _("Save toolpath")
gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
}
""")
- if self._objectShader == None or not self._objectShader.isValid():
+ if self._objectShader is None or not self._objectShader.isValid():
self._objectShader = opengl.GLFakeShader()
self._objectOverhangShader = opengl.GLFakeShader()
self._objectLoadShader = None
glPopMatrix()
else:
#Draw the object box-shadow, so you can see where it will collide with other objects.
- if self._selectedObj is not None and len(self._scene.objects()) > 1:
- size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
- glPushMatrix()
- glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0)
+ if self._selectedObj is not None:
glEnable(GL_BLEND)
glEnable(GL_CULL_FACE)
- glColor4f(0,0,0,0.12)
- glBegin(GL_QUADS)
- glVertex3f(-size[0], size[1], 0.1)
- glVertex3f(-size[0], -size[1], 0.1)
- glVertex3f( size[0], -size[1], 0.1)
- glVertex3f( size[0], size[1], 0.1)
+ glColor4f(0,0,0,0.16)
+ glDepthMask(False)
+ for obj in self._scene.objects():
+ glPushMatrix()
+ glTranslatef(obj.getPosition()[0], obj.getPosition()[1], 0)
+ glBegin(GL_TRIANGLE_FAN)
+ for p in obj._boundaryHull[::-1]:
+ glVertex3f(p[0], p[1], 0)
+ glEnd()
+ glPopMatrix()
+ glPushMatrix()
+ glColor4f(0,0,0,0.06)
+ glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0)
+ glBegin(GL_TRIANGLE_FAN)
+ for p in self._selectedObj._printAreaHull[::-1]:
+ glVertex3f(p[0], p[1], 0)
+ glEnd()
+ glBegin(GL_TRIANGLE_FAN)
+ for p in self._selectedObj._headAreaHull[::-1]:
+ glVertex3f(p[0], p[1], 0)
glEnd()
+ glDepthMask(True)
glDisable(GL_CULL_FACE)
glPopMatrix()
glVertex3f(-size[0] / 2, -size[1] / 2+10, 0)
glEnd()
+ #Cornerpoints for big blue square
v0 = [ size[0] / 2, size[1] / 2, size[2]]
v1 = [ size[0] / 2,-size[1] / 2, size[2]]
v2 = [-size[0] / 2, size[1] / 2, size[2]]
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, 3*4, vList)
+ glDepthMask(False)
glColor4ub(5, 171, 231, 64)
glDrawArrays(GL_QUADS, 0, 4)
glColor4ub(5, 171, 231, 96)
glDrawArrays(GL_QUADS, 12, 8)
glDisableClientState(GL_VERTEX_ARRAY)
+ #Draw checkerboard
sx = self._machineSize[0]
sy = self._machineSize[1]
for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
y1 = max(min(y1, sy/2), -sy/2)
x2 = max(min(x2, sx/2), -sx/2)
y2 = max(min(y2, sy/2), -sy/2)
+ #Black or "white" checker
if (x & 1) == (y & 1):
glColor4ub(5, 171, 231, 127)
else:
glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
glBegin(GL_QUADS)
- glVertex3f(x1, y1, -0.02)
- glVertex3f(x2, y1, -0.02)
- glVertex3f(x2, y2, -0.02)
- glVertex3f(x1, y2, -0.02)
+ glVertex3f(x1, y1, 0)
+ glVertex3f(x2, y1, 0)
+ glVertex3f(x2, y2, 0)
+ glVertex3f(x1, y2, 0)
glEnd()
+ if machine == 'ultimaker2':
+
+ glColor4ub(127, 127, 127, 200)
+ #if UM2, draw bat-area zone for head. THe head can't stop there, because its bat-area.
+ #UpperRight
+ clipWidth = 25
+ clipHeight = 10
+ posX = sx / 2 - clipWidth
+ posY = sy / 2 - clipHeight
+ glBegin(GL_QUADS)
+ glVertex3f(posX, posY, 0)
+ glVertex3f(posX+clipWidth, posY, 0)
+ glVertex3f(posX+clipWidth, posY+clipHeight, 0)
+ glVertex3f(posX, posY+clipHeight, 0)
+ glEnd()
+ #UpperLeft
+ clipWidth = 25
+ clipHeight = 10
+ posX = -sx / 2
+ posY = sy / 2 - clipHeight
+ glBegin(GL_QUADS)
+ glVertex3f(posX, posY, 0)
+ glVertex3f(posX+clipWidth, posY, 0)
+ glVertex3f(posX+clipWidth, posY+clipHeight, 0)
+ glVertex3f(posX, posY+clipHeight, 0)
+ glEnd()
+ #LowerRight
+ clipWidth = 25
+ clipHeight = 10
+ posX = sx / 2 - clipWidth
+ posY = -sy / 2
+ glBegin(GL_QUADS)
+ glVertex3f(posX, posY, 0)
+ glVertex3f(posX+clipWidth, posY, 0)
+ glVertex3f(posX+clipWidth, posY+clipHeight, 0)
+ glVertex3f(posX, posY+clipHeight, 0)
+ glEnd()
+ #LowerLeft
+ clipWidth = 25
+ clipHeight = 10
+ posX = -sx / 2
+ posY = -sy / 2
+ glBegin(GL_QUADS)
+ glVertex3f(posX, posY, 0)
+ glVertex3f(posX+clipWidth, posY, 0)
+ glVertex3f(posX+clipWidth, posY+clipHeight, 0)
+ glVertex3f(posX, posY+clipHeight, 0)
+ glEnd()
+
+ glDepthMask(True)
glDisable(GL_BLEND)
glDisable(GL_CULL_FACE)