chiark / gitweb /
Update the doodle3d class to auto-detect local network boxes, as well as access point...
[cura.git] / Cura / gui / sceneView.py
index 916eaa0262bd92bcca8ead1add297dfa0b14e984..01ce44a03da8d3791f7108503fec3ba7870964bf 100644 (file)
@@ -8,6 +8,7 @@ import os
 import traceback
 import threading
 import math
+import platform
 
 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.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):
@@ -51,9 +54,10 @@ class SceneView(openglGui.glGuiPanel):
                self._viewTarget = numpy.array([0,0,0], numpy.float32)
                self._animView = None
                self._animZoom = None
-               self._platformMesh = None
+               self._platformMesh = {}
                self._isSimpleMode = True
                self._usbPrintMonitor = printWindow.printProcessMonitor(lambda : self._queueRefresh())
+               self._printerConnectionManager = printerConnectionManager.PrinterConnectionManager()
 
                self._viewport = None
                self._modelMatrix = None
@@ -119,10 +123,83 @@ class SceneView(openglGui.glGuiPanel):
                self.updateToolButtons()
                self.updateProfileToControls()
 
+       def loadGCodeFile(self, filename):
+               self.OnDeleteAll(None)
+               if self._gcode is not None:
+                       self._gcode = None
+                       for layerVBOlist in self._gcodeVBOs:
+                               for vbo in layerVBOlist:
+                                       self.glReleaseList.append(vbo)
+                       self._gcodeVBOs = []
+               self._gcode = gcodeInterpreter.gcode()
+               self._gcodeFilename = filename
+               self.printButton.setBottomText('')
+               self.viewSelection.setValue(4)
+               self.printButton.setDisabled(False)
+               self.youMagineButton.setDisabled(True)
+               self.OnViewChange()
+
+       def loadSceneFiles(self, filenames):
+               self.youMagineButton.setDisabled(False)
+               #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
+               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:
+                       # 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
@@ -131,32 +208,7 @@ class SceneView(openglGui.glGuiPanel):
                        if len(filenames) < 1:
                                return False
                        profile.putPreference('lastFile', filenames[0])
-                       gcodeFilename = None
-                       for filename in filenames:
-                               self.GetParent().GetParent().GetParent().addToModelMRU(filename)
-                               ext = filename[filename.rfind('.')+1:].upper()
-                               if ext == 'G' or ext == 'GCODE':
-                                       gcodeFilename = filename
-                       if gcodeFilename is not None:
-                               if self._gcode is not None:
-                                       self._gcode = None
-                                       for layerVBOlist in self._gcodeVBOs:
-                                               for vbo in layerVBOlist:
-                                                       self.glReleaseList.append(vbo)
-                                       self._gcodeVBOs = []
-                               self._gcode = gcodeInterpreter.gcode()
-                               self._gcodeFilename = gcodeFilename
-                               self.printButton.setBottomText('')
-                               self.viewSelection.setValue(4)
-                               self.printButton.setDisabled(False)
-                               self.youMagineButton.setDisabled(True)
-                               self.OnViewChange()
-                       else:
-                               self.youMagineButton.setDisabled(False)
-                               if self.viewSelection.getValue() == 4:
-                                       self.viewSelection.setValue(0)
-                                       self.OnViewChange()
-                               self.loadScene(filenames)
+                       self.loadFiles(filenames)
 
        def showSaveModel(self):
                if len(self._scene.objects()) < 1:
@@ -172,9 +224,11 @@ class SceneView(openglGui.glGuiPanel):
 
        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))
@@ -187,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()
+                       elif connectionEntry is not None:
+                               connectionEntry.connection.loadFile(self._gcodeFilename)
+                               connectionEntry.connection.startPrint()
                        else:
                                self.showSaveGCode()
                if button == 3:
@@ -200,15 +257,19 @@ class SceneView(openglGui.glGuiPanel):
        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()
@@ -324,7 +385,20 @@ class SceneView(openglGui.glGuiPanel):
        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()
@@ -371,7 +445,7 @@ class SceneView(openglGui.glGuiPanel):
                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
@@ -404,11 +478,23 @@ class SceneView(openglGui.glGuiPanel):
                self._selectObject(None)
                self.sceneUpdated()
 
+       def OnCenter(self, e):
+               if self._focusObj is None:
+                       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 OnMergeObjects(self, e):
                if self._selectedObj is None or self._focusObj is None or self._selectedObj == self._focusObj:
+                       if len(self._scene.objects()) == 2:
+                               self._scene.merge(self._scene.objects()[0], self._scene.objects()[1])
+                               self.sceneUpdated()
                        return
                self._scene.merge(self._selectedObj, self._focusObj)
                self.sceneUpdated()
@@ -416,7 +502,7 @@ class SceneView(openglGui.glGuiPanel):
        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):
@@ -443,11 +529,16 @@ class SceneView(openglGui.glGuiPanel):
                        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:
@@ -459,7 +550,7 @@ class SceneView(openglGui.glGuiPanel):
                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)
@@ -473,7 +564,12 @@ class SceneView(openglGui.glGuiPanel):
        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:
@@ -508,7 +604,7 @@ class SceneView(openglGui.glGuiPanel):
                        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:
@@ -521,14 +617,13 @@ class SceneView(openglGui.glGuiPanel):
                if self._isSimpleMode != oldSimpleMode:
                        self._scene.arrangeAll()
                        self.sceneUpdated()
-               self._machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
+               self._machineSize = numpy.array([profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')])
                self._objColors[0] = profile.getPreferenceColour('model_colour')
                self._objColors[1] = profile.getPreferenceColour('model_colour2')
                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.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_min_y'), profile.getPreferenceFloat('extruder_head_size_max_y'), profile.getPreferenceFloat('extruder_head_size_height'))
+               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:
                        scale = self._selectedObj.getScale()
@@ -541,7 +636,7 @@ class SceneView(openglGui.glGuiPanel):
                        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()
@@ -614,13 +709,14 @@ class SceneView(openglGui.glGuiPanel):
                        if e.GetButton() == 3:
                                        menu = wx.Menu()
                                        if self._focusObj is not None:
-                                               self.Bind(wx.EVT_MENU, lambda e: self._deleteObject(self._focusObj), menu.Append(-1, _("Delete")))
-                                               self.Bind(wx.EVT_MENU, self.OnMultiply, menu.Append(-1, _("Multiply")))
-                                               self.Bind(wx.EVT_MENU, self.OnSplitObject, menu.Append(-1, _("Split")))
-                                       if self._selectedObj != self._focusObj and self._focusObj is not None and int(profile.getPreference('extruder_amount')) > 1:
+                                               self.Bind(wx.EVT_MENU, lambda e: self._deleteObject(self._focusObj), menu.Append(-1, _("Delete object")))
+                                               self.Bind(wx.EVT_MENU, self.OnCenter, menu.Append(-1, _("Center on platform")))
+                                               self.Bind(wx.EVT_MENU, self.OnMultiply, menu.Append(-1, _("Multiply object")))
+                                               self.Bind(wx.EVT_MENU, self.OnSplitObject, menu.Append(-1, _("Split object into parts")))
+                                       if ((self._selectedObj != self._focusObj and self._focusObj is not None and self._selectedObj is not None) or len(self._scene.objects()) == 2) and int(profile.getMachineSetting('extruder_amount')) > 1:
                                                self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, _("Dual extrusion merge")))
                                        if len(self._scene.objects()) > 0:
-                                               self.Bind(wx.EVT_MENU, self.OnDeleteAll, menu.Append(-1, _("Delete all")))
+                                               self.Bind(wx.EVT_MENU, self.OnDeleteAll, menu.Append(-1, _("Delete all objects")))
                                        if menu.MenuItemCount > 0:
                                                self.PopupMenu(menu)
                                        menu.Destroy()
@@ -740,12 +836,16 @@ class SceneView(openglGui.glGuiPanel):
                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")
@@ -839,7 +939,7 @@ void main(void)
        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
@@ -887,7 +987,7 @@ void main(void)
                                self._gcodeLoadThread.start()
                        if self._gcode is not None and self._gcode.layerList is not None:
                                glPushMatrix()
-                               if profile.getPreference('machine_center_is_zero') != 'True':
+                               if profile.getMachineSetting('machine_center_is_zero') != 'True':
                                        glTranslate(-self._machineSize[0] / 2, -self._machineSize[1] / 2, 0)
                                t = time.time()
                                drawUpTill = min(len(self._gcode.layerList), self.layerSelect.getValue() + 1)
@@ -1059,19 +1159,31 @@ void main(void)
                                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()
 
@@ -1140,16 +1252,62 @@ void main(void)
                glEnable(GL_CULL_FACE)
                glEnable(GL_BLEND)
 
-               size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
+               size = [profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')]
 
-               if profile.getPreference('machine_type').startswith('ultimaker'):
-                       if self._platformMesh is None:
-                               self._platformMesh = meshLoader.loadMeshes(resources.getPathForMesh('ultimaker_platform.stl'))[0]
-                               self._platformMesh._drawOffset = numpy.array([0,0,2.5], numpy.float32)
+               machine = profile.getMachineSetting('machine_type')
+               if profile.getMachineSetting('machine_type').startswith('ultimaker'):
+                       if machine not in self._platformMesh:
+                               meshes = meshLoader.loadMeshes(resources.getPathForMesh(machine + '_platform.stl'))
+                               if len(meshes) > 0:
+                                       self._platformMesh[machine] = meshes[0]
+                               else:
+                                       self._platformMesh[machine] = None
+                               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)
                        glColor4f(1,1,1,0.5)
                        self._objectShader.bind()
-                       self._renderObject(self._platformMesh, False, False)
+                       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)
@@ -1162,6 +1320,7 @@ void main(void)
                        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]]
@@ -1175,6 +1334,7 @@ void main(void)
                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)
@@ -1183,6 +1343,7 @@ void main(void)
                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):
@@ -1195,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)
+                               #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)
 
@@ -1230,7 +1442,7 @@ void main(void)
        def _generateGCodeVBOs2(self, layer):
                filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
                filamentArea = math.pi * filamentRadius * filamentRadius
-               useFilamentArea = profile.getPreference('gcode_flavor') == 'UltiGCode'
+               useFilamentArea = profile.getMachineSetting('gcode_flavor') == 'UltiGCode'
 
                ret = []
                for extrudeType in ['WALL-OUTER:0', 'WALL-OUTER:1', 'WALL-OUTER:2', 'WALL-OUTER:3', 'WALL-INNER', 'FILL', 'SUPPORT', 'SKIRT']: