chiark / gitweb /
Update the doodle3d class to auto-detect local network boxes, as well as access point...
[cura.git] / Cura / gui / sceneView.py
index 25dcffe9e8fb91598104b3a7d8b27a7eb17af029..01ce44a03da8d3791f7108503fec3ba7870964bf 100644 (file)
@@ -8,6 +8,7 @@ import os
 import traceback
 import threading
 import math
 import traceback
 import threading
 import math
+import platform
 
 import OpenGL
 OpenGL.ERROR_CHECKING = False
 
 import OpenGL
 OpenGL.ERROR_CHECKING = False
@@ -23,10 +24,12 @@ from Cura.util import sliceEngine
 from Cura.util import machineCom
 from Cura.util import removableStorage
 from Cura.util import gcodeInterpreter
 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.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):
 
 class SceneView(openglGui.glGuiPanel):
        def __init__(self, parent):
@@ -54,6 +57,7 @@ class SceneView(openglGui.glGuiPanel):
                self._platformMesh = {}
                self._isSimpleMode = True
                self._usbPrintMonitor = printWindow.printProcessMonitor(lambda : self._queueRefresh())
                self._platformMesh = {}
                self._isSimpleMode = True
                self._usbPrintMonitor = printWindow.printProcessMonitor(lambda : self._queueRefresh())
+               self._printerConnectionManager = printerConnectionManager.PrinterConnectionManager()
 
                self._viewport = None
                self._modelMatrix = None
 
                self._viewport = None
                self._modelMatrix = None
@@ -137,27 +141,65 @@ class SceneView(openglGui.glGuiPanel):
 
        def loadSceneFiles(self, filenames):
                self.youMagineButton.setDisabled(False)
 
        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):
                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
                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
                                gcodeFilename = filename
+                               mainWindow.addToModelMRU(filename)
                if gcodeFilename is not None:
                        self.loadGCodeFile(gcodeFilename)
                else:
                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)
 
        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
                        if dlg.ShowModal() != wx.ID_OK:
                                dlg.Destroy()
                                return
@@ -182,9 +224,11 @@ class SceneView(openglGui.glGuiPanel):
 
        def OnPrintButton(self, button):
                if button == 1:
 
        def OnPrintButton(self, button):
                if button == 1:
+
+                       connectionEntry = self._printerConnectionManager.getAvailableConnection()
                        if machineCom.machineIsConnected():
                                self.showPrintWindow()
                        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))
                                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))
@@ -197,6 +241,9 @@ class SceneView(openglGui.glGuiPanel):
                                        drive = drives[0]
                                filename = self._scene._objectList[0].getName() + '.gcode'
                                threading.Thread(target=self._copyFile,args=(self._gcodeFilename, drive[1] + filename, drive[1])).start()
                                        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:
                        else:
                                self.showSaveGCode()
                if button == 3:
@@ -210,15 +257,19 @@ class SceneView(openglGui.glGuiPanel):
        def showPrintWindow(self):
                if self._gcodeFilename is None:
                        return
        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):
                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()
                dlg.SetWildcard('Toolpath (*.gcode)|*.gcode;*.g')
                if dlg.ShowModal() != wx.ID_OK:
                        dlg.Destroy()
@@ -334,7 +385,20 @@ class SceneView(openglGui.glGuiPanel):
        def OnScaleMax(self, button):
                if self._selectedObj is None:
                        return
        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()
                self._scene.pushFree()
                self._selectObject(self._selectedObj)
                self.updateProfileToControls()
@@ -381,7 +445,7 @@ class SceneView(openglGui.glGuiPanel):
                if self._focusObj is None:
                        return
                obj = self._focusObj
                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
                if dlg.ShowModal() != wx.ID_OK:
                        dlg.Destroy()
                        return
@@ -419,6 +483,9 @@ class SceneView(openglGui.glGuiPanel):
                        return
                self._focusObj.setPosition(numpy.array([0.0, 0.0]))
                self._scene.pushFree()
                        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 _splitCallback(self, progress):
                print progress
@@ -435,7 +502,7 @@ class SceneView(openglGui.glGuiPanel):
        def sceneUpdated(self):
                self._sceneUpdateTimer.Start(500, True)
                self._slicer.abortSlicer()
        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.QueueRefresh()
 
        def _onRunSlicer(self, e):
@@ -462,11 +529,16 @@ class SceneView(openglGui.glGuiPanel):
                        self._gcodeVBOs = []
                if ready:
                        self.printButton.setProgressBar(None)
                        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 = gcodeInterpreter.gcode()
                        self._gcodeFilename = self._slicer.getGCodeFilename()
                else:
@@ -478,7 +550,7 @@ class SceneView(openglGui.glGuiPanel):
                self._gcode.load(self._gcodeFilename)
 
        def _gcodeLoadCallback(self, progress):
                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)
                        return True
                if len(self._gcode.layerList) % 15 == 0:
                        time.sleep(0.1)
@@ -492,7 +564,12 @@ class SceneView(openglGui.glGuiPanel):
        def loadScene(self, fileList):
                for filename in fileList:
                        try:
        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:
                        except:
                                traceback.print_exc()
                        else:
@@ -527,7 +604,7 @@ class SceneView(openglGui.glGuiPanel):
                        self.updateProfileToControls()
                        self.updateToolButtons()
                if zoom and obj is not None:
                        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._animView = openglGui.animation(self, self._viewTarget.copy(), newViewPos, 0.5)
                        newZoom = obj.getBoundaryCircle() * 6
                        if newZoom > numpy.max(self._machineSize) * 3:
@@ -546,7 +623,6 @@ class SceneView(openglGui.glGuiPanel):
                self._objColors[2] = profile.getPreferenceColour('model_colour3')
                self._objColors[3] = profile.getPreferenceColour('model_colour4')
                self._scene.setMachineSize(self._machineSize)
                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._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:
@@ -560,7 +636,7 @@ class SceneView(openglGui.glGuiPanel):
                        self.scaleZmmctrl.setValue(round(size[2], 2))
 
        def OnKeyChar(self, keyCode):
                        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()
                        if self._selectedObj is not None:
                                self._deleteObject(self._selectedObj)
                                self.QueueRefresh()
@@ -760,12 +836,16 @@ class SceneView(openglGui.glGuiPanel):
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
 
        def OnPaint(self,e):
                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")
                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")
                        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")
                else:
                        self.printButton._imageID = 3
                        self.printButton._tooltip = _("Save toolpath")
@@ -859,7 +939,7 @@ void main(void)
        gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
 }
                                """)
        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
                                self._objectShader = opengl.GLFakeShader()
                                self._objectOverhangShader = opengl.GLFakeShader()
                                self._objectLoadShader = None
@@ -1079,19 +1159,31 @@ void main(void)
                                glPopMatrix()
                else:
                        #Draw the object box-shadow, so you can see where it will collide with other objects.
                                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)
                                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()
                                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()
 
                                glDisable(GL_CULL_FACE)
                                glPopMatrix()
 
@@ -1170,7 +1262,7 @@ void main(void)
                                        self._platformMesh[machine] = meshes[0]
                                else:
                                        self._platformMesh[machine] = None
                                        self._platformMesh[machine] = meshes[0]
                                else:
                                        self._platformMesh[machine] = None
-                               if profile.getMachineSetting('machine_type') == 'ultimaker2':
+                               if machine == 'ultimaker2':
                                        self._platformMesh[machine]._drawOffset = numpy.array([0,-37,145], numpy.float32)
                                else:
                                        self._platformMesh[machine]._drawOffset = numpy.array([0,0,2.5], numpy.float32)
                                        self._platformMesh[machine]._drawOffset = numpy.array([0,-37,145], numpy.float32)
                                else:
                                        self._platformMesh[machine]._drawOffset = numpy.array([0,0,2.5], numpy.float32)
@@ -1178,6 +1270,44 @@ void main(void)
                        self._objectShader.bind()
                        self._renderObject(self._platformMesh[machine], False, False)
                        self._objectShader.unbind()
                        self._objectShader.bind()
                        self._renderObject(self._platformMesh[machine], False, False)
                        self._objectShader.unbind()
+
+                       #For the Ultimaker 2 render the texture on the back plate to show the Ultimaker2 text.
+                       if machine == 'ultimaker2':
+                               if not hasattr(self._platformMesh[machine], 'texture'):
+                                       self._platformMesh[machine].texture = opengl.loadGLTexture('Ultimaker2backplate.png')
+                               glBindTexture(GL_TEXTURE_2D, self._platformMesh[machine].texture)
+                               glEnable(GL_TEXTURE_2D)
+                               glPushMatrix()
+                               glColor4f(1,1,1,1)
+
+                               glTranslate(0,150,-5)
+                               h = 50
+                               d = 8
+                               w = 100
+                               glEnable(GL_BLEND)
+                               glBlendFunc(GL_DST_COLOR, GL_ZERO)
+                               glBegin(GL_QUADS)
+                               glTexCoord2f(1, 0)
+                               glVertex3f( w, 0, h)
+                               glTexCoord2f(0, 0)
+                               glVertex3f(-w, 0, h)
+                               glTexCoord2f(0, 1)
+                               glVertex3f(-w, 0, 0)
+                               glTexCoord2f(1, 1)
+                               glVertex3f( w, 0, 0)
+
+                               glTexCoord2f(1, 0)
+                               glVertex3f(-w, d, h)
+                               glTexCoord2f(0, 0)
+                               glVertex3f( w, d, h)
+                               glTexCoord2f(0, 1)
+                               glVertex3f( w, d, 0)
+                               glTexCoord2f(1, 1)
+                               glVertex3f(-w, d, 0)
+                               glEnd()
+                               glDisable(GL_TEXTURE_2D)
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+                               glPopMatrix()
                else:
                        glColor4f(0,0,0,1)
                        glLineWidth(3)
                else:
                        glColor4f(0,0,0,1)
                        glLineWidth(3)
@@ -1190,6 +1320,7 @@ void main(void)
                        glVertex3f(-size[0] / 2, -size[1] / 2+10, 0)
                        glEnd()
 
                        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]]
                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]]
@@ -1203,6 +1334,7 @@ void main(void)
                glEnableClientState(GL_VERTEX_ARRAY)
                glVertexPointer(3, GL_FLOAT, 3*4, vList)
 
                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)
                glColor4ub(5, 171, 231, 64)
                glDrawArrays(GL_QUADS, 0, 4)
                glColor4ub(5, 171, 231, 96)
@@ -1211,6 +1343,7 @@ void main(void)
                glDrawArrays(GL_QUADS, 12, 8)
                glDisableClientState(GL_VERTEX_ARRAY)
 
                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):
                sx = self._machineSize[0]
                sy = self._machineSize[1]
                for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
@@ -1223,17 +1356,68 @@ void main(void)
                                y1 = max(min(y1, sy/2), -sy/2)
                                x2 = max(min(x2, sx/2), -sx/2)
                                y2 = max(min(y2, sy/2), -sy/2)
                                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)
                                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()
 
                                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)
 
                glDisable(GL_BLEND)
                glDisable(GL_CULL_FACE)