chiark / gitweb /
Merge tag '15.01-RC7' into upstream
authorYouness Alaoui <kakaroto@kakaroto.homelinux.net>
Fri, 6 Mar 2015 17:31:47 +0000 (12:31 -0500)
committerYouness Alaoui <kakaroto@kakaroto.homelinux.net>
Fri, 6 Mar 2015 17:31:47 +0000 (12:31 -0500)
Conflicts:
Cura/gui/firmwareInstall.py
Cura/gui/mainWindow.py
Cura/gui/sceneView.py
Cura/util/profile.py

1  2 
Cura/gui/configWizard.py
Cura/gui/firmwareInstall.py
Cura/gui/mainWindow.py
Cura/gui/sceneView.py
Cura/util/profile.py
package.sh

diff --combined Cura/gui/configWizard.py
index dfa1e003f42c562d4cc978f699308195c39d44b0,f7800911850f5534faae10a4530af41793c82fd8..a4fb81ca01d3527994ef39a6d8afb31de39bb4ec
@@@ -224,6 -224,38 +224,6 @@@ class InfoPage(wx.wizard.WizardPageSimp
        def StoreData(self):
                pass
  
 -
 -class FirstInfoPage(InfoPage):
 -      def __init__(self, parent, addNew):
 -              if addNew:
 -                      super(FirstInfoPage, self).__init__(parent, _("Add new machine wizard"))
 -              else:
 -                      super(FirstInfoPage, self).__init__(parent, _("First time run wizard"))
 -                      self.AddText(_("Welcome, and thanks for trying Cura!"))
 -                      self.AddSeperator()
 -              self.AddText(_("This wizard will help you in setting up Cura for your machine."))
 -              if not addNew:
 -                      self.AddSeperator()
 -                      self._language_option = self.AddCombo(_("Select your language:"), map(lambda o: o[1], resources.getLanguageOptions()))
 -              else:
 -                      self._language_option = None
 -              # self.AddText(_("This wizard will help you with the following steps:"))
 -              # self.AddText(_("* Configure Cura for your machine"))
 -              # self.AddText(_("* Optionally upgrade your firmware"))
 -              # self.AddText(_("* Optionally check if your machine is working safely"))
 -              # self.AddText(_("* Optionally level your printer bed"))
 -
 -              #self.AddText('* Calibrate your machine')
 -              #self.AddText('* Do your first print')
 -
 -      def AllowBack(self):
 -              return False
 -
 -      def StoreData(self):
 -              if self._language_option is not None:
 -                      profile.putPreference('language', self._language_option.GetValue())
 -                      resources.setupLocalization(self._language_option.GetValue())
 -
  class PrintrbotPage(InfoPage):
        def __init__(self, parent):
                self._printer_info = [
@@@ -386,23 -418,31 +386,27 @@@ class MachineSelectPage(InfoPage)
                super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
                self.AddText(_("What kind of machine do you have:"))
  
 -              self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2", style=wx.RB_GROUP)
 -              self.Ultimaker2Radio.SetValue(True)
 +              self.LulzbotMiniRadio = self.AddRadioButton("LulzBot Mini", style=wx.RB_GROUP)
 +              self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
 +              self.LulzbotMiniRadio.SetValue(True)
 +              self.LulzbotTaz5Radio = self.AddRadioButton("LulzBot TAZ 5")
 +              self.LulzbotTaz5Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
 +              self.LulzbotTaz4Radio = self.AddRadioButton("LulzBot TAZ 4")
 +              self.LulzbotTaz4Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
 +              self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
                self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
+               self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
+               self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
+               self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
+               self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
                self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
                self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
                self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
                self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
                self.PrintrbotRadio = self.AddRadioButton("Printrbot")
                self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
 -              self.LulzbotTazRadio = self.AddRadioButton("Lulzbot TAZ")
 -              self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
 -              self.LulzbotMiniRadio = self.AddRadioButton("Lulzbot Mini")
 -              self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
                self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
                self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
 -              self.AddSeperator()
 -              self.AddText(_("The collection of anonymous usage information helps with the continued improvement of Cura."))
 -              self.AddText(_("This does NOT submit your models online nor gathers any privacy related information."))
 -              self.SubmitUserStats = self.AddCheckbox(_("Submit anonymous usage information:"))
 -              self.AddText(_("For full details see: http://wiki.ultimaker.com/Cura:stats"))
 -              self.SubmitUserStats.SetValue(True)
  
        def OnUltimaker2Select(self, e):
                wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
                wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
  
        def AllowNext(self):
 -              wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
 +              wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
                return True
  
        def StoreData(self):
                profile.putProfileSetting('retraction_enable', 'True')
-               if self.Ultimaker2Radio.GetValue():
-                       profile.putMachineSetting('machine_width', '230')
-                       profile.putMachineSetting('machine_depth', '225')
-                       profile.putMachineSetting('machine_height', '205')
-                       profile.putMachineSetting('machine_name', 'ultimaker2')
-                       profile.putMachineSetting('machine_type', 'ultimaker2')
+               if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
+                       if self.Ultimaker2Radio.GetValue():
+                               profile.putMachineSetting('machine_width', '230')
+                               profile.putMachineSetting('machine_depth', '225')
+                               profile.putMachineSetting('machine_height', '205')
+                               profile.putMachineSetting('machine_name', 'ultimaker2')
+                               profile.putMachineSetting('machine_type', 'ultimaker2')
+                               profile.putMachineSetting('has_heated_bed', 'True')
+                       if self.Ultimaker2GoRadio.GetValue():
+                               profile.putMachineSetting('machine_width', '120')
+                               profile.putMachineSetting('machine_depth', '120')
+                               profile.putMachineSetting('machine_height', '115')
+                               profile.putMachineSetting('machine_name', 'ultimaker2go')
+                               profile.putMachineSetting('machine_type', 'ultimaker2go')
+                               profile.putMachineSetting('has_heated_bed', 'False')
+                       if self.Ultimaker2ExtRadio.GetValue():
+                               profile.putMachineSetting('machine_width', '230')
+                               profile.putMachineSetting('machine_depth', '225')
+                               profile.putMachineSetting('machine_height', '305')
+                               profile.putMachineSetting('machine_name', 'ultimaker2extended')
+                               profile.putMachineSetting('machine_type', 'ultimaker2extended')
+                               profile.putMachineSetting('has_heated_bed', 'False')
                        profile.putMachineSetting('machine_center_is_zero', 'False')
-                       profile.putMachineSetting('has_heated_bed', 'True')
                        profile.putMachineSetting('gcode_flavor', 'UltiGCode')
                        profile.putMachineSetting('extruder_head_size_min_x', '40.0')
                        profile.putMachineSetting('extruder_head_size_min_y', '10.0')
                        profile.putMachineSetting('has_heated_bed', 'True')
                        profile.putMachineSetting('extruder_amount', '1')
                        profile.putProfileSetting('retraction_enable', 'True')
 -              elif self.LulzbotTazRadio.GetValue() or self.LulzbotMiniRadio.GetValue():
 -                      if self.LulzbotTazRadio.GetValue():
 +              elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
 +                      if self.LulzbotTaz4Radio.GetValue():
                                profile.putMachineSetting('machine_width', '298')
                                profile.putMachineSetting('machine_depth', '275')
                                profile.putMachineSetting('machine_height', '250')
                                profile.putProfileSetting('nozzle_size', '0.35')
 -                              profile.putMachineSetting('machine_name', 'Lulzbot TAZ')
 +                              profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
 +                              profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
 +                              profile.putMachineSetting('serial_baud', '115200')
 +                      elif self.LulzbotTaz5Radio.GetValue():
 +                              profile.putMachineSetting('machine_width', '298')
 +                              profile.putMachineSetting('machine_depth', '275')
 +                              profile.putMachineSetting('machine_height', '250')
 +                              profile.putProfileSetting('nozzle_size', '0.35')
 +                              profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
 +                              profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
 +                              profile.putMachineSetting('serial_baud', '115200')
                        else:
 -                              profile.putMachineSetting('machine_width', '160')
 -                              profile.putMachineSetting('machine_depth', '160')
 -                              profile.putMachineSetting('machine_height', '160')
 +                              profile.putMachineSetting('machine_width', '155')
 +                              profile.putMachineSetting('machine_depth', '155')
 +                              profile.putMachineSetting('machine_height', '163')
                                profile.putProfileSetting('nozzle_size', '0.5')
 -                              profile.putMachineSetting('machine_name', 'Lulzbot Mini')
 -                      profile.putMachineSetting('machine_type', 'Aleph Objects')
 +                              profile.putMachineSetting('machine_name', 'LulzBot Mini')
 +                              profile.putMachineSetting('machine_type', 'lulzbot_mini')
 +                              profile.putMachineSetting('serial_baud', '115200')
                        profile.putMachineSetting('machine_center_is_zero', 'False')
                        profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
                        profile.putMachineSetting('has_heated_bed', 'True')
                        profile.putMachineSetting('extruder_head_size_max_x', '0.0')
                        profile.putMachineSetting('extruder_head_size_max_y', '0.0')
                        profile.putMachineSetting('extruder_head_size_height', '0.0')
 +                      profile.putPreference('startMode', 'Simple')
                else:
                        profile.putMachineSetting('machine_width', '80')
                        profile.putMachineSetting('machine_depth', '80')
                        profile.putProfileSetting('nozzle_size', '0.5')
                profile.checkAndUpdateMachineName()
                profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
 -              if self.SubmitUserStats.GetValue():
 -                      profile.putPreference('submit_slice_information', 'True')
 -              else:
 -                      profile.putPreference('submit_slice_information', 'False')
 -
  
  class SelectParts(InfoPage):
        def __init__(self, parent):
@@@ -562,7 -610,7 +581,7 @@@ class UltimakerFirmwareUpgradePage(Info
                self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
                self.AddHiddenSeperator()
                self.AddText(_("Cura requires these new features and thus\nyour firmware will most likely need to be upgraded.\nYou will get the chance to do so now."))
 -              upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
 +              upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
                upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
                skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
                self.AddHiddenSeperator()
@@@ -980,11 -1028,8 +999,11 @@@ class Ultimaker2ReadyPage(InfoPage)
  
  class LulzbotReadyPage(InfoPage):
        def __init__(self, parent):
 -              super(LulzbotReadyPage, self).__init__(parent, _("Lulzbot TAZ/Mini"))
 -              self.AddText(_('Cura is now ready to be used with your Lulzbot.'))
 +              super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
 +              self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
 +              self.AddSeperator()
 +              self.AddText(_('For more information about using Cura with your LulzBot'))
 +              self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
                self.AddSeperator()
  
  class ConfigWizard(wx.wizard.Wizard):
                self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
                self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
  
 -              self.firstInfoPage = FirstInfoPage(self, addNew)
                self.machineSelectPage = MachineSelectPage(self)
                self.ultimakerSelectParts = SelectParts(self)
                self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
                self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
                self.lulzbotReadyPage = LulzbotReadyPage(self)
  
 -              wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
                #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
                wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
                wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
                wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
                wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
  
 -              self.FitToPage(self.firstInfoPage)
 -              self.GetPageAreaSizer().Add(self.firstInfoPage)
 +              self.FitToPage(self.machineSelectPage)
 +              self.GetPageAreaSizer().Add(self.machineSelectPage)
  
 -              self.RunWizard(self.firstInfoPage)
 +              self.RunWizard(self.machineSelectPage)
                self.Destroy()
  
        def OnPageChanging(self, e):
@@@ -1278,7 -1325,7 +1297,7 @@@ class bedLevelWizardMain(InfoPage)
  
  class headOffsetCalibrationPage(InfoPage):
        def __init__(self, parent):
 -              super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
 +              super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
  
                self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
                self.AddSeperator()
index 4dd751e709d42e57053b5f2617aef8bdb6b328ea,0b101c82a4fde09d5489f79115cf310fef71041e..03a2d693b50ce84cdc6a2a13d3baa7cf2866515b
@@@ -17,47 -17,52 +17,54 @@@ from Cura.util import profil
  from Cura.util import resources
  
  def getDefaultFirmware(machineIndex = None):
-       if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker':
+       machine_type = profile.getMachineSetting('machine_type', machineIndex)
+       extruders = profile.getMachineSettingFloat('extruder_amount', machineIndex)
+       heated_bed = profile.getMachineSetting('has_heated_bed', machineIndex) == 'True'
+       baudrate = 250000
+       if sys.platform.startswith('linux'):
+               baudrate = 115200
+       if machine_type == 'ultimaker':
                name = 'MarlinUltimaker'
-               if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
+               if extruders > 2:
                        return None
-               if profile.getMachineSetting('has_heated_bed', machineIndex) == 'True':
+               if heated_bed:
                        name += '-HBK'
-               if sys.platform.startswith('linux'):
-                       name += '-115200'
-               else:
-                       name += '-250000'
-               if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 1:
+               name += '-%d' % (baudrate)
+               if extruders > 1:
                        name += '-dual'
                return resources.getPathForFirmware(name + '.hex')
  
-       if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker_plus':
-               name = 'MarlinUltimaker-UMOP'
-               if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
+       if machine_type == 'ultimaker_plus':
+               name = 'MarlinUltimaker-UMOP-%d' % (baudrate)
+               if extruders > 2:
                        return None
-               if sys.platform.startswith('linux'):
-                       name += '-115200'
-               else:
-                       name += '-250000'
-               if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 1:
+               if extruders > 1:
                        name += '-dual'
                return resources.getPathForFirmware(name + '.hex')
  
-       if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker2':
-               if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
+       if machine_type == 'ultimaker2':
+               if extruders > 2:
                        return None
-               if profile.getMachineSettingFloat('extruder_amount', machineIndex) == 2:
+               if extruders > 1:
                        return resources.getPathForFirmware("MarlinUltimaker2-dual.hex")
                return resources.getPathForFirmware("MarlinUltimaker2.hex")
-       if profile.getMachineSetting('machine_type', machineIndex) == 'lulzbot_mini':
++      if machine_type == 'lulzbot_mini':
 +              return resources.getPathForFirmware("marlin_mini_2014Q4.hex")
-       if profile.getMachineSetting('machine_type', machineIndex) == 'Witbox':
+       if machine_type == 'ultimaker2go':
+               return resources.getPathForFirmware("MarlinUltimaker2go.hex")
+       if machine_type == 'ultimaker2extended':
+               if extruders > 2:
+                       return None
+               if extruders > 1:
+                       return resources.getPathForFirmware("MarlinUltimaker2extended-dual.hex")
+               return resources.getPathForFirmware("MarlinUltimaker2extended.hex")
+       if machine_type == 'Witbox':
                return resources.getPathForFirmware("MarlinWitbox.hex")
        return None
  
  class InstallFirmware(wx.Dialog):
        def __init__(self, parent = None, filename = None, port = None, machineIndex = None):
 -              super(InstallFirmware, self).__init__(parent=parent, title="Firmware install for %s" % (profile.getMachineSetting('machine_name', machineIndex).title()), size=(250, 100))
 +              super(InstallFirmware, self).__init__(parent=parent, title=_("Firmware install for %s") % (profile.getMachineSetting('machine_name', machineIndex).title()), size=(250, 100))
                if port is None:
                        port = profile.getMachineSetting('serial_port')
                if filename is None:
  
  class AutoUpdateFirmware(wx.Dialog):
        def __init__(self, parent, filename = None, port = None, machineIndex = None):
 -              super(AutoUpdateFirmware, self).__init__(parent=parent, title="Auto Firmware install", size=(250, 500))
 +              super(AutoUpdateFirmware, self).__init__(parent=parent, title=_("Auto Firmware install"), size=(250, 500))
                if port is None:
                        port = profile.getMachineSetting('serial_port')
                self._serial = None
diff --combined Cura/gui/mainWindow.py
index 16c215c898f63c55e24e8c714b6c8be0ec23ad77,cc44fb235a6e454291e935f6f45a137551007653..9808ae25658adc38085edd91a47e235cfea18192
@@@ -33,7 -33,7 +33,7 @@@ except
  
  class mainWindow(wx.Frame):
        def __init__(self):
 -              super(mainWindow, self).__init__(None, title='Cura - ' + version.getVersion())
 +              super(mainWindow, self).__init__(None, title=_('Cura - ') + version.getVersion())
  
                wx.EVT_CLOSE(self, self.OnClose)
  
  
                helpMenu = wx.Menu()
                i = helpMenu.Append(-1, _("Online documentation..."))
 -              self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('http://daid.github.com/Cura'), i)
 +              self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('http://lulzbot.com/cura'), i)
                i = helpMenu.Append(-1, _("Report a problem..."))
 -              self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
 -              i = helpMenu.Append(-1, _("Check for update..."))
 -              self.Bind(wx.EVT_MENU, self.OnCheckForUpdate, i)
 -              i = helpMenu.Append(-1, _("Open YouMagine website..."))
 -              self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://www.youmagine.com/'), i)
 +              self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/alephobjects/Cura/issues'), i)
 +              #i = helpMenu.Append(-1, _("Check for update..."))
 +              #self.Bind(wx.EVT_MENU, self.OnCheckForUpdate, i)
 +              #i = helpMenu.Append(-1, _("Open YouMagine website..."))
 +              #self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://www.youmagine.com/'), i)
                i = helpMenu.Append(-1, _("About Cura..."))
                self.Bind(wx.EVT_MENU, self.OnAbout, i)
                self.menubar.Append(helpMenu, _("Help"))
                                                print profileString
                                                self.lastTriedClipboard = profileString
                                                profile.setProfileFromString(profileString)
 -                                              self.scene.notification.message("Loaded new profile from clipboard.")
 +                                              self.scene.notification.message(_("Loaded new profile from clipboard."))
                                                self.updateProfileToAllControls()
                except:
                        print "Unable to read from clipboard"
  
  
 -      def updateSliceMode(self):
 +      def updateSliceMode(self, changedMode = True):
                isSimple = profile.getPreference('startMode') == 'Simple'
  
                self.normalSettingsPanel.Show(not isSimple)
  
                # Set splitter sash position & size
                if isSimple:
 -                      # Save normal mode sash
 -                      self.normalSashPos = self.splitter.GetSashPosition()
 +                      # Save normal mode sash (only if we changed mode from normal
 +                      # to simple)
 +                      if changedMode:
 +                              self.normalSashPos = self.splitter.GetSashPosition()
  
                        # Change location of sash to width of quick mode pane
                        (width, height) = self.simpleSettingsPanel.GetSizer().GetSize()
                        # Disable sash
                        self.splitter.SetSashSize(0)
                else:
 -                      self.splitter.SetSashPosition(self.normalSashPos, True)
 +                      # Only change the sash position if we changed mode from simple
 +                      if changedMode:
 +                              self.splitter.SetSashPosition(self.normalSashPos, True)
                        # Enabled sash
                        self.splitter.SetSashSize(4)
                self.defaultFirmwareInstallMenuItem.Enable(firmwareInstall.getDefaultFirmware() is not None)
-               if profile.getMachineSetting('machine_type') == 'ultimaker2' or \
-                  profile.getMachineSetting('machine_type') == 'lulzbot_mini' or \
-                  profile.getMachineSetting('machine_type') == 'lulzbot_TAZ_4' or \
-                  profile.getMachineSetting('machine_type') == 'lulzbot_TAZ_5' or \
-                  profile.getMachineSetting('machine_type') == 'lulzbot_TAZ':
 -              if profile.getMachineSetting('machine_type').startswith('ultimaker2'):
++              if profile.getMachineSetting('machine_type').startswith('ultimaker2') or \
++                 profile.getMachineSetting('machine_type').startswith('lulzbot_'):
                        self.bedLevelWizardMenuItem.Enable(False)
                        self.headOffsetWizardMenuItem.Enable(False)
 +              else:
 +                      self.bedLevelWizardMenuItem.Enable(True)
 +                      self.headOffsetWizardMenuItem.Enable(False)
                if int(profile.getMachineSetting('extruder_amount')) < 2:
                        self.headOffsetWizardMenuItem.Enable(False)
                self.scene.updateProfileToControls()
                prefDialog.Centre()
                prefDialog.Show()
                prefDialog.Raise()
 -              wx.CallAfter(prefDialog.Show)
  
        def OnMachineSettings(self, e):
                prefDialog = preferencesDialog.machineSettingsDialog(self)
                self.normalSettingsPanel.updateProfileToControls()
                self.simpleSettingsPanel.updateProfileToControls()
  
 -      def reloadSettingPanels(self):
 +      def reloadSettingPanels(self, changedSliceMode = False):
                self.leftSizer.Detach(self.simpleSettingsPanel)
                self.leftSizer.Detach(self.normalSettingsPanel)
                self.simpleSettingsPanel.Destroy()
                self.normalSettingsPanel = normalSettingsPanel(self.leftPane, lambda : self.scene.sceneUpdated())
                self.leftSizer.Add(self.simpleSettingsPanel, 1)
                self.leftSizer.Add(self.normalSettingsPanel, 1, wx.EXPAND)
 -              self.updateSliceMode()
 +              self.updateSliceMode(changedSliceMode)
                self.updateProfileToAllControls()
  
        def updateMachineMenu(self):
  
        def OnAddNewMachine(self, e):
                self.Hide()
 +              wasSimple = profile.getPreference('startMode') == 'Simple'
                configWizard.ConfigWizard(True)
 +              isSimple = profile.getPreference('startMode') == 'Simple'
                self.Show()
 -              self.reloadSettingPanels()
 +              self.reloadSettingPanels(isSimple != wasSimple)
                self.updateMachineMenu()
  
        def OnSelectMachine(self, index):
                profile.setActiveMachine(index)
 -              self.reloadSettingPanels()
 +              self.reloadSettingPanels(False)
  
        def OnBedLevelWizard(self, e):
                configWizard.bedLevelWizard()
                        wx.MessageBox(_("You are running the latest version of Cura!"), _("Awesome!"), wx.ICON_INFORMATION)
  
        def OnAbout(self, e):
 -              aboutBox = aboutWindow.aboutWindow()
 +              aboutBox = aboutWindow.aboutWindow(self)
                aboutBox.Centre()
                aboutBox.Show()
 +              aboutBox.Raise()
  
        def OnClose(self, e):
                profile.saveProfile(profile.getDefaultProfilePath(), True)
                #HACK: Set the paint function of the glCanvas to nothing so it won't keep refreshing. Which can keep wxWidgets from quiting.
                print "Closing down"
                self.scene.OnPaint = lambda e : e
 -              self.scene._engine.cleanup()
 +              self.scene.cleanup()
                self.Destroy()
  
        def OnQuit(self, e):
@@@ -710,7 -697,7 +707,7 @@@ class normalSettingsPanel(configBase.co
                        self.alterationPanel = None
                else:
                        self.alterationPanel = alterationPanel.alterationPanel(self.nb, callback)
 -                      self.nb.AddPage(self.alterationPanel, "Start/End-GCode")
 +                      self.nb.AddPage(self.alterationPanel, _("Start/End-GCode"))
  
                self.Bind(wx.EVT_SIZE, self.OnSize)
  
diff --combined Cura/gui/sceneView.py
index 2b1ac3c65a9e02a89aad0466d80bcb4106d8ab4e,799e92c67c08b98e28b9a049391d0693f75d92b5..3d5bfa280f18f7cf16923b36706c6fd868f7debe
@@@ -49,11 -49,9 +49,11 @@@ class SceneView(openglGui.glGuiPanel)
                self._mouseY = -1
                self._mouseState = None
                self._viewTarget = numpy.array([0,0,0], numpy.float32)
 +              self._mouse3Dpos = numpy.array([0,0,0], numpy.float32)
                self._animView = None
                self._animZoom = None
                self._platformMesh = {}
 +              self.glReleaseList = []
                self._platformTexture = None
                self._isSimpleMode = True
                self._printerConnectionManager = printerConnectionManager.PrinterConnectionManager()
                openglGui.glLabel(self.scaleForm, _("Uniform scale"), (0,8))
                self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None)
  
 -              self.viewSelection = openglGui.glComboButton(self, _("View mode"), [7,19,11,15,23], [_("Normal"), _("Overhang"), _("Transparent"), _("X-Ray"), _("Layers")], (-1,0), self.OnViewChange)
 -
 -              self.youMagineButton = openglGui.glButton(self, 26, _("Share on YouMagine"), (2,0), lambda button: youmagineGui.youmagineManager(self.GetTopLevelParent(), self._scene))
 -              self.youMagineButton.setDisabled(True)
 +              self.viewSelection = openglGui.glComboButton(self, _("View mode"), 7, [26,19,11,15,23], [_("Normal"), _("Overhang"), _("Transparent"), _("X-Ray"), _("Layers")], (-1,0), self.OnViewChange, self.OnViewStateChange)
 +              self.viewSelection.setDisabled(True)
 +              #self.youMagineButton = openglGui.glButton(self, 26, _("Share on YouMagine"), (2,0), lambda button: youmagineGui.youmagineManager(self.GetTopLevelParent(), self._scene))
 +              #self.youMagineButton.setDisabled(True)
  
                self.notification = openglGui.glNotification(self, (0, 0))
  
                self.updateToolButtons()
                self.updateProfileToControls()
  
 +      def cleanup(self):
 +              # Delete all objects first
 +              self.OnDeleteAll(None)
 +              self._engine.cleanup()
 +              if self._objectShader is not None:
 +                      self._objectShader.release()
 +              if self._objectLoadShader is not None:
 +                      self._objectLoadShader.release()
 +              if self._objectOverhangShader is not None:
 +                      self._objectOverhangShader.release()
 +              for obj in self.glReleaseList:
 +                      obj.release()
 +
        def loadGCodeFile(self, filename):
                self.OnDeleteAll(None)
                #Cheat the engine results to load a GCode file into it.
                self._engine._result.setFinished(True)
                self._engineResultView.setResult(self._engine._result)
                self.printButton.setBottomText('')
 +              self.viewSelection.setDisabled(False)
                self.viewSelection.setValue(4)
                self.printButton.setDisabled(False)
 -              self.youMagineButton.setDisabled(True)
 +              #self.youMagineButton.setDisabled(True)
                self.OnViewChange()
  
        def loadSceneFiles(self, filenames):
 -              self.youMagineButton.setDisabled(False)
 +              #self.youMagineButton.setDisabled(False)
                #if self.viewSelection.getValue() == 4:
                #       self.viewSelection.setValue(0)
                #       self.OnViewChange()
                        if ignored_types:
                                ignored_types = ignored_types.keys()
                                ignored_types.sort()
 -                              self.notification.message("ignored: " + " ".join("*" + type for type in ignored_types))
 +                              self.notification.message(_("ignored: ") + " ".join("*" + type for type in ignored_types))
                        mainWindow.updateProfileToAllControls()
                        # now process all the scene files
                        if scene_filenames:
                        if len(removableStorage.getPossibleSDcardDrives()) > 0 and (connectionGroup is None or connectionGroup.getPriority() < 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))
 -                                      if dlg.ShowModal() != wx.ID_OK:
 -                                              dlg.Destroy()
 -                                              return
 -                                      drive = drives[dlg.GetSelection()]
 +                                      choices = map(lambda n: n[0], drives)
 +                                      choices += (_("Custom file destination"), )
 +                                      title = _("Multiple removable drives have been found")
 +                              else:
 +                                      choices = [drives[0][0], _("Custom file destination")]
 +                                      title = _("A removable drive has been found")
 +
 +                              dlg = wx.SingleChoiceDialog(self, _("Select destination SD card drive\nYou can also select a custom file to save to"), title, choices)
 +                              if dlg.ShowModal() != wx.ID_OK:
                                        dlg.Destroy()
 +                                      return
 +                              try:
 +                                      drive = drives[dlg.GetSelection()]
 +                              except:
 +                                      drive = None
 +                              dlg.Destroy()
 +
 +                              if drive is None:
 +                                      self.showSaveGCode()
                                else:
 -                                      drive = drives[0]
 -                              filename = self._scene._objectList[0].getName() + profile.getGCodeExtension()
 -                              threading.Thread(target=self._saveGCode,args=(drive[1] + filename, drive[1])).start()
 +                                      filename = self._scene._objectList[0].getName() + profile.getGCodeExtension()
 +                                      threading.Thread(target=self._saveGCode,args=(drive[1] + filename, drive[1])).start()
                        elif connectionGroup is not None:
                                connections = connectionGroup.getAvailableConnections()
                                if len(connections) < 2:
                                        connection = connections[0]
                                else:
 -                                      dlg = wx.SingleChoiceDialog(self, "Select the %s connection to use" % (connectionGroup.getName()), "Multiple %s connections found" % (connectionGroup.getName()), map(lambda n: n.getName(), connections))
 +                                      dlg = wx.SingleChoiceDialog(self, _("Select the %s connection to use") % (connectionGroup.getName()), _("Multiple %s connections found") % (connectionGroup.getName()), map(lambda n: n.getName(), connections))
                                        if dlg.ShowModal() != wx.ID_OK:
                                                dlg.Destroy()
                                                return
                connection.window.Raise()
                if not connection.loadGCodeData(self._engine.getResult().getGCode()):
                        if connection.isPrinting():
 -                              self.notification.message("Cannot start print, because other print still running.")
 +                              self.notification.message(_("Cannot start print, because other print still running."))
                        else:
 -                              self.notification.message("Failed to start print...")
 +                              self.notification.message(_("Failed to start print..."))
  
        def showSaveGCode(self):
                if len(self._scene._objectList) < 1:
                except:
                        import sys, traceback
                        traceback.print_exc()
 -                      self.notification.message("Failed to save")
 +                      self.notification.message(_("Failed to save"))
                else:
                        if ejectDrive:
 -                              self.notification.message("Saved as %s" % (targetFilename), lambda : self._doEjectSD(ejectDrive), 31, 'Eject')
 +                              self.notification.message(_("Saved as %s") % (targetFilename), lambda : self._doEjectSD(ejectDrive), 31, 'Eject')
                        elif explorer.hasExplorer():
 -                              self.notification.message("Saved as %s" % (targetFilename), lambda : explorer.openExplorer(targetFilename), 4, 'Open folder')
 +                              self.notification.message(_("Saved as %s") % (targetFilename), lambda : explorer.openExplorer(targetFilename), 4, _('Open folder'))
                        else:
 -                              self.notification.message("Saved as %s" % (targetFilename))
 +                              self.notification.message(_("Saved as %s") % (targetFilename))
                self.printButton.setProgressBar(None)
 -              self._engine.getResult().submitInfoOnline()
  
        def _doEjectSD(self, drive):
                if removableStorage.ejectDrive(drive):
 -                      self.notification.message('You can now eject the card.')
 +                      self.notification.message(_('You can now eject the card.'))
                else:
 -                      self.notification.message('Safe remove failed...')
 +                      self.notification.message(_('Safe remove failed...'))
  
        def _showEngineLog(self):
                dlg = wx.TextEntryDialog(self, _("The slicing engine reported the following"), _("Engine log..."), '\n'.join(self._engine.getResult().getLog()), wx.TE_MULTILINE | wx.OK | wx.CENTRE)
                self._engineResultView.setEnabled(self.viewMode == 'gcode')
                self.QueueRefresh()
  
 +      def OnViewStateChange(self, state):
 +              self._engineResultView.layerSelect.setHidden(self.viewMode != 'gcode' or state)
 +
        def OnRotateReset(self, button):
                if self._selectedObj is None:
                        return
                        self._deleteObject(self._scene.objects()[0])
                self._animView = openglGui.animation(self, self._viewTarget.copy(), numpy.array([0,0,0], numpy.float32), 0.5)
                self._engineResultView.setResult(None)
 +              self.viewSelection.setDisabled(True)
 +              self.printButton.setDisabled(True)
  
        def OnMultiply(self, e):
                if self._focusObj is None:
                        if n > cnt:
                                break
                if n <= cnt:
 -                      self.notification.message("Could not create more than %d items" % (n - 1))
 +                      self.notification.message(_("Could not create more than %d items") % (n - 1))
 +              self.notification.message(_("Could not create more than %d items") % (n - 1))
                self._scene.remove(newObj)
                self._scene.centerAll()
                self.sceneUpdated()
                        if self.printButton.getProgressBar() is not None and progressValue >= 0.0 and abs(self.printButton.getProgressBar() - progressValue) < 0.01:
                                return
                self.printButton.setDisabled(not finished)
 +              self.viewSelection.setDisabled(not finished)
                if progressValue >= 0.0:
                        self.printButton.setProgressBar(progressValue)
                else:
                                                self._scene.centerAll()
                                        self._selectObject(obj)
                                        if obj.getScale()[0] < 1.0:
 -                                              self.notification.message("Warning: Object scaled down.")
 +                                              self.notification.message(_("Warning: Object scaled down."))
                self.sceneUpdated()
  
        def _deleteObject(self, obj):
                                self.glReleaseList.append(m.vbo)
                if len(self._scene.objects()) == 0:
                        self._engineResultView.setResult(None)
 +                      self.printButton.setDisabled(True)
 +                      self.viewSelection.setDisabled(True)
 +                      self.printButton.setBottomText('')
                import gc
                gc.collect()
                self.sceneUpdated()
                self._objColors[2] = profile.getPreferenceColour('model_colour3')
                self._objColors[3] = profile.getPreferenceColour('model_colour4')
                self._scene.updateMachineDimensions()
+               if self._zoom > numpy.max(self._machineSize) * 3:
+                       self._animZoom = openglGui.animation(self, self._zoom, numpy.max(self._machineSize) * 3, 0.5)
                self.updateModelSettingsToControls()
  
        def updateModelSettingsToControls(self):
                glDisable(GL_BLEND)
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  
 -              glClearColor(0.8, 0.8, 0.8, 1.0)
 +              #scene background color
 +              glClearColor(0.85, 0.85, 0.85, 1.0)
                glClearStencil(0)
                glClearDepth(1.0)
  
                        self.printButton._tooltip = _("Toolpath to SD")
                elif connectionGroup is not None:
                        self.printButton._imageID = connectionGroup.getIconID()
 -                      self.printButton._tooltip = _("Print with %s") % (connectionGroup.getName())
 +                      #self.printButton._tooltip = _("Print with %s") % (connectionGroup.getName())
 +                      self.printButton._tooltip = _("Print/Control")
                else:
                        self.printButton._imageID = 3
                        self.printButton._tooltip = _("Save toolpath")
                        glEnable(GL_BLEND)
                        if self._objectLoadShader is not None:
                                self._objectLoadShader.bind()
 -                              glColor4f(0.2, 0.6, 1.0, 1.0)
 +                              #Model color during load animation
 +                              glColor4ub(177, 205, 54, 255)
                                for obj in self._scene.objects():
                                        if obj._loadAnim is None:
                                                continue
  
                size = [profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')]
  
-               machine = profile.getMachineSetting('machine_type')
-       
 -              machine_type = profile.getMachineSetting('machine_type')
 +              #Due to NC licensing of the stl files, temporarily removing platform mesh loading for Ultimaker and Witbox
-               '''if machine.startswith('ultimaker'):
-                       if machine not in self._platformMesh:
-                               meshes = meshLoader.loadMeshes(resources.getPathForMesh(machine + '_platform.stl'))
++              '''machine_type = profile.getMachineSetting('machine_type')
+               if machine_type not in self._platformMesh:
+                       self._platformMesh[machine_type] = None
+                       filename = None
+                       texture_name = None
+                       offset = [0,0,0]
+                       texture_offset = [0,0,0]
+                       texture_scale = 1.0
+                       if machine_type == 'ultimaker2' or machine_type == 'ultimaker2extended':
+                               filename = resources.getPathForMesh('ultimaker2_platform.stl')
+                               offset = [0,-37,145]
+                               texture_name = 'Ultimaker2backplate.png'
+                               texture_offset = [0,150,-5]
+                       elif machine_type == 'ultimaker2go':
+                               filename = resources.getPathForMesh('ultimaker2go_platform.stl')
+                               offset = [0,-42,145]
+                               texture_offset = [0,105,-5]
+                               texture_name = 'Ultimaker2backplate.png'
+                               texture_scale = 0.9
+                       elif machine_type == 'ultimaker_plus':
+                               filename = resources.getPathForMesh('ultimaker2_platform.stl')
+                               offset = [0,-37,145]
+                               texture_offset = [0,150,-5]
+                               texture_name = 'UltimakerPlusbackplate.png'
+                       elif machine_type == 'ultimaker':
+                               filename = resources.getPathForMesh('ultimaker_platform.stl')
+                               offset = [0,0,2.5]
+                       elif machine_type == 'Witbox':
+                               filename = resources.getPathForMesh('Witbox_platform.stl')
+                               offset = [0,-37,145]
+                       if filename is not None:
+                               meshes = meshLoader.loadMeshes(filename)
                                if len(meshes) > 0:
-                                       self._platformMesh[machine] = meshes[0]
-                               else:
-                                       self._platformMesh[machine] = None
-                               if machine == 'ultimaker2' or machine == 'ultimaker_plus':
-                                       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_type] = meshes[0]
+                                       self._platformMesh[machine_type]._drawOffset = numpy.array(offset, numpy.float32)
+                                       self._platformMesh[machine_type].texture = None
+                                       if texture_name is not None:
+                                               self._platformMesh[machine_type].texture = openglHelpers.loadGLTexture(texture_name)
+                                               self._platformMesh[machine_type].texture_offset = texture_offset
+                                               self._platformMesh[machine_type].texture_scale = texture_scale
+               if self._platformMesh[machine_type] is not None:
+                       mesh = self._platformMesh[machine_type]
                        glColor4f(1,1,1,0.5)
                        self._objectShader.bind()
-                       self._renderObject(self._platformMesh[machine], False, False)
+                       self._renderObject(mesh, False, False)
                        self._objectShader.unbind()
  
                        #For the Ultimaker 2 render the texture on the back plate to show the Ultimaker2 text.
-                       if machine == 'ultimaker2' or machine == 'ultimaker_plus':
-                               if not hasattr(self._platformMesh[machine], 'texture'):
-                                       if machine == 'ultimaker2':
-                                               self._platformMesh[machine].texture = openglHelpers.loadGLTexture('Ultimaker2backplate.png')
-                                       else:
-                                               self._platformMesh[machine].texture = openglHelpers.loadGLTexture('UltimakerPlusbackplate.png')
-                               glBindTexture(GL_TEXTURE_2D, self._platformMesh[machine].texture)
+                       if mesh.texture is not None:
+                               glBindTexture(GL_TEXTURE_2D, mesh.texture)
                                glEnable(GL_TEXTURE_2D)
                                glPushMatrix()
                                glColor4f(1,1,1,1)
  
-                               glTranslate(0,150,-5)
+                               glTranslate(mesh.texture_offset[0], mesh.texture_offset[1], mesh.texture_offset[2])
+                               glScalef(mesh.texture_scale, mesh.texture_scale, mesh.texture_scale)
                                h = 50
                                d = 8
                                w = 100
                                glEnable(GL_BLEND)
-                               glBlendFunc(GL_DST_COLOR, GL_ZERO)
+                               glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA)
+                               glEnable(GL_ALPHA_TEST)
+                               glAlphaFunc(GL_GREATER, 0.0)
                                glBegin(GL_QUADS)
                                glTexCoord2f(1, 0)
                                glVertex3f( w, 0, h)
                                glDisable(GL_TEXTURE_2D)
                                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                                glPopMatrix()
-                               
-               elif machine.startswith('Witbox'):
-                       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 == 'Witbox':
-                                       self._platformMesh[machine]._drawOffset = numpy.array([0,-37,145], numpy.float32)
-                       glColor4f(1,1,1,0.5)
-                       self._objectShader.bind()
-                       self._renderObject(self._platformMesh[machine], False, False)
-                       self._objectShader.unbind()
-               '''
-               
 -              else:
 -                      glColor4f(0,0,0,1)
 -                      glLineWidth(3)
 -                      glBegin(GL_LINES)
 -                      glVertex3f(-size[0] / 2, -size[1] / 2, 0)
 -                      glVertex3f(-size[0] / 2, -size[1] / 2, 10)
 -                      glVertex3f(-size[0] / 2, -size[1] / 2, 0)
 -                      glVertex3f(-size[0] / 2+10, -size[1] / 2, 0)
 -                      glVertex3f(-size[0] / 2, -size[1] / 2, 0)
 -                      glVertex3f(-size[0] / 2, -size[1] / 2+10, 0)
 -                      glEnd()
++              else:'''
++              # until glEnd() goes inside the else
 +              glColor4f(0,0,0,1)
 +              glLineWidth(3)
 +              glBegin(GL_LINES)
 +              glVertex3f(-size[0] / 2, -size[1] / 2, 0)
 +              glVertex3f(-size[0] / 2, -size[1] / 2, 10)
 +              glVertex3f(-size[0] / 2, -size[1] / 2, 0)
 +              glVertex3f(-size[0] / 2+10, -size[1] / 2, 0)
 +              glVertex3f(-size[0] / 2, -size[1] / 2, 0)
 +              glVertex3f(-size[0] / 2, -size[1] / 2+10, 0)
 +              glEnd()
  
                glDepthMask(False)
  
                for n in xrange(0, len(polys[0])):
                        if not circular:
                                if n % 2 == 0:
 -                                      glColor4ub(5, 171, 231, 96)
 +                                      glColor4ub(210, 235, 103, 100)
                                else:
 -                                      glColor4ub(5, 171, 231, 64)
 +                                      glColor4ub(223, 241, 145, 100)
                        else:
 -                              glColor4ub(5, 171, 231, 96)
 +                              glColor4ub(223, 241, 145, 100)
  
                        glVertex3f(polys[0][n][0], polys[0][n][1], height)
                        glVertex3f(polys[0][n][0], polys[0][n][1], 0)
                glEnd()
  
                #Draw top of build volume.
 -              glColor4ub(5, 171, 231, 128)
 +              glColor4ub(183, 209, 90, 100)
                glBegin(GL_TRIANGLE_FAN)
                for p in polys[0][::-1]:
                        glVertex3f(p[0], p[1], height)
                        glBindTexture(GL_TEXTURE_2D, self._platformTexture)
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
 -              glColor4f(1,1,1,0.5)
 +              #Dark checkerboard color
 +              glColor4f(1,1,1,0.7)
                glBindTexture(GL_TEXTURE_2D, self._platformTexture)
                glEnable(GL_TEXTURE_2D)
                glBegin(GL_TRIANGLE_FAN)
  #TODO: Remove this or put it in a seperate file
  class shaderEditor(wx.Frame):
        def __init__(self, parent, callback, v, f):
 -              super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
 +              super(shaderEditor, self).__init__(parent, title=_("Shader editor"), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
                self._callback = callback
                s = wx.BoxSizer(wx.VERTICAL)
                self.SetSizer(s)
diff --combined Cura/util/profile.py
index 2351a24b6489f2aa0d736de32ce61030203348cf,86f003053284340823907c86d9f73491cda2d216..914245e30434f191e0c8b023f84548a98a8c769b
@@@ -175,19 -175,19 +175,19 @@@ class setting(object)
  def _(n):
        return n
  
 -setting('layer_height',              0.1, float, 'basic',    _('Quality')).setRange(0.0001).setLabel(_("Layer height (mm)"), _("Layer height in millimeters.\nThis is the most important setting to determine the quality of your print. Normal quality prints are 0.1mm, high quality is 0.06mm. You can go up to 0.25mm with an Ultimaker for very fast prints at low quality."))
 +setting('layer_height',              0.1, float, 'basic',    _('Quality')).setRange(0.0001).setLabel(_("Layer height (mm)"), _("Layer height in millimeters.\nThis is the most important setting to determine the quality of your print. Smaller layer heights will give a finer surface but will give longer print time. Larger layer heights will provide fast prints but a rougher surface."))
  setting('wall_thickness',            0.8, float, 'basic',    _('Quality')).setRange(0.0).setLabel(_("Shell thickness (mm)"), _("Thickness of the outside shell in the horizontal direction.\nThis is used in combination with the nozzle size to define the number\nof perimeter lines and the thickness of those perimeter lines."))
  setting('retraction_enable',        True, bool,  'basic',    _('Quality')).setExpertSubCategory(_('Retraction')).setLabel(_("Enable retraction"), _("Retract the filament when the nozzle is moving over a none-printed area. Details about the retraction can be configured in the advanced tab."))
  setting('solid_layer_thickness',     0.6, float, 'basic',    _('Fill')).setRange(0).setLabel(_("Bottom/Top thickness (mm)"), _("This controls the thickness of the bottom and top layers, the amount of solid layers put down is calculated by the layer thickness and this value.\nHaving this value a multiple of the layer thickness makes sense. And keep it near your wall thickness to make an evenly strong part."))
 -setting('fill_density',               20, float, 'basic',    _('Fill')).setExpertSubCategory(_('Infill')).setRange(0, 100).setLabel(_("Fill Density (%)"), _("This controls how densely filled the insides of your print will be. For a solid part use 100%, for an empty part use 0%. A value around 20% is usually enough.\nThis won't affect the outside of the print and only adjusts how strong the part becomes."))
 +setting('fill_density',               20, float, 'basic',    _('Fill')).setExpertSubCategory(_('Infill')).setRange(0, 100).setLabel(_("Fill Density (%)"), _("This controls how densely filled the insides of your print will be. For a solid part use 100%, for an empty part use 0%. A value around 20% is usually enough.\nThis will not affect the outside of the print and only adjusts how strong the part becomes."))
  setting('nozzle_size',               0.4, float, 'advanced', _('Machine')).setRange(0.1,10).setLabel(_("Nozzle size (mm)"), _("The nozzle size is very important, this is used to calculate the line width of the infill, and used to calculate the amount of outside wall lines and thickness for the wall thickness you entered in the print settings."))
 -setting('print_speed',                50, float, 'basic',    _('Speed and Temperature')).setRange(1).setLabel(_("Print speed (mm/s)"), _("Speed at which printing happens. A well adjusted Ultimaker can reach 150mm/s, but for good quality prints you want to print slower. Printing speed depends on a lot of factors. So you will be experimenting with optimal settings for this."))
 -setting('print_temperature',         210, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("Printing temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA a value of 210C is usually used.\nFor ABS a value of 230C or higher is required."))
 -setting('print_temperature2',          0, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("2nd nozzle temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA a value of 210C is usually used.\nFor ABS a value of 230C or higher is required."))
 -setting('print_temperature3',          0, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("3th nozzle temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA a value of 210C is usually used.\nFor ABS a value of 230C or higher is required."))
 -setting('print_temperature4',          0, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("4th nozzle temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA a value of 210C is usually used.\nFor ABS a value of 230C or higher is required."))
 -setting('print_bed_temperature',      70, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("Bed temperature (C)"), _("Temperature used for the heated printer bed. Set at 0 to pre-heat yourself."))
 -setting('support',                'None', [_('None'), _('Touching buildplate'), _('Everywhere')], 'basic', _('Support')).setExpertSubCategory(_('Support')).setLabel(_("Support type"), _("Type of support structure build.\n\"Touching buildplate\" is the most commonly used support setting.\n\nNone does not do any support.\nTouching buildplate only creates support where the support structure will touch the build platform.\nEverywhere creates support even on top of parts of the model."))
 +setting('print_speed',                50, float, 'basic',    _('Speed and Temperature')).setRange(1).setLabel(_("Print speed (mm/s)"), _("Speed at which printing happens. A well adjusted 3D printer can reach high speeds. However, for high quality prints slower speeds are required. Printing speed depends on a lot of factors. You will be experimenting with optimal settings for this."))
- setting('print_temperature',         220, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("Printing temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA 205C is recommended.\nFor ABS and HIPS 240C is recommended."))
++setting('print_temperature',         210, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("Printing temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA 205C is recommended.\nFor ABS and HIPS 240C is recommended."))
 +setting('print_temperature2',          0, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("2nd nozzle temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA 205C is recommended.\nFor ABS and HIPS 240C is recommended."))
 +setting('print_temperature3',          0, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("3th nozzle temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA 205C is recommended.\nFor ABS and HIPS 240C is recommended."))
 +setting('print_temperature4',          0, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("4th nozzle temperature (C)"), _("Temperature used for printing. Set at 0 to pre-heat yourself.\nFor PLA 205C is recommended.\nFor ABS and HIPS 240C is recommended."))
 +setting('print_bed_temperature',      70, int,   'basic',    _('Speed and Temperature')).setRange(0,340).setLabel(_("Bed temperature (C)"), _("Temperature used for the heated printer bed. Set at 0 to pre-heat yourself.\nFor PLA 60C is recommended.\nFor ABS and HIPS 110C is recommended."))
 +setting('support',                'None', [_('None'), _('Touching buildplate'), _('Everywhere')], 'basic', _('Support')).setExpertSubCategory(_('Support')).setLabel(_("Support type"), _("Type of support structure build.\n\"Support is useful when a model has severe over hangs. Using this option does require some finishing of the print, including removing the support material.\n\"Touching buildplate\" is the most commonly used support setting.\n\nNone does not do any support.\nTouching buildplate only creates support where the support structure will touch the build platform.\nEverywhere creates support even on top of parts of the model."))
  setting('platform_adhesion',      'None', [_('None'), _('Brim'), _('Raft')], 'basic', _('Support')).setExpertSubCategory([_('Skirt'), _('Brim'), _('Raft')]).setLabel(_("Platform adhesion type"), _("Different options that help in preventing corners from lifting due to warping.\nBrim adds a single layer thick flat area around your object which is easy to cut off afterwards, and it is the recommended option.\nRaft adds a thick raster below the object and a thin interface between this and your object.\n(Note that enabling the brim or raft disables the skirt)"))
  setting('support_dual_extrusion',  'Both', [_('Both'), _('First extruder'), _('Second extruder')], 'basic', _('Support')).setLabel(_("Support dual extrusion"), _("Which extruder to use for support material, for break-away support you can use both extruders.\nBut if one of the materials is more expensive then the other you could select an extruder to use for support material. This causes more extruder switches.\nYou can also use the 2nd extruder for soluble support materials."))
  setting('wipe_tower',              False, bool,  'basic',    _('Dual extrusion')).setLabel(_("Wipe&prime tower"), _("The wipe-tower is a tower printed on every layer when switching between nozzles.\nThe old nozzle is wiped off on the tower before the new nozzle is used to print the 2nd color."))
@@@ -199,9 -199,9 +199,9 @@@ setting('filament_diameter3',          
  setting('filament_diameter4',          0, float, 'basic',    _('Filament')).setRange(0).setLabel(_("Diameter4 (mm)"), _("Diameter of your filament for the 4th nozzle. Use 0 to use the same diameter as for nozzle 1."))
  setting('filament_flow',            100., float, 'basic',    _('Filament')).setRange(5,300).setLabel(_("Flow (%)"), _("Flow compensation, the amount of material extruded is multiplied by this value"))
  setting('retraction_speed',         40.0, float, 'advanced', _('Retraction')).setRange(0.1).setLabel(_("Speed (mm/s)"), _("Speed at which the filament is retracted, a higher retraction speed works better. But a very high retraction speed can lead to filament grinding."))
 -setting('retraction_amount',         4.5, float, 'advanced', _('Retraction')).setRange(0).setLabel(_("Distance (mm)"), _("Amount of retraction, set at 0 for no retraction at all. A value of 4.5mm seems to generate good results."))
 +setting('retraction_amount',         4.5, float, 'advanced', _('Retraction')).setRange(0).setLabel(_("Distance (mm)"), _("Amount of retraction, set at 0 for no retraction at all. A value between 1 and 2 millimeters provides good results for most materials."))
  setting('retraction_dual_amount',   16.5, float, 'advanced', _('Retraction')).setRange(0).setLabel(_("Dual extrusion switch amount (mm)"), _("Amount of retraction when switching nozzle with dual-extrusion, set at 0 for no retraction at all. A value of 16.0mm seems to generate good results."))
 -setting('retraction_min_travel',     1.5, float, 'expert',   _('Retraction')).setRange(0).setLabel(_("Minimum travel (mm)"), _("Minimum amount of travel needed for a retraction to happen at all. To make sure you do not get a lot of retractions in a small area."))
 +setting('retraction_min_travel',     1.5, float, 'expert',   _('Retraction')).setRange(0).setLabel(_("Minimum travel (mm)"), _("Minimum amount of travel needed for a retraction to happen at all. This setting is used to prevent from having too many retractions in a small area."))
  setting('retraction_combing',       True, bool,  'expert',   _('Retraction')).setLabel(_("Enable combing"), _("Combing is the act of avoiding holes in the print for the head to travel over. If combing is disabled the printer head moves straight from the start point to the end point and it will always retract."))
  setting('retraction_minimal_extrusion',0.02, float,'expert', _('Retraction')).setRange(0).setLabel(_("Minimal extrusion before retracting (mm)"), _("The minimal amount of extrusion that needs to be done before retracting again if a retraction needs to happen before this minimal is reached the retraction is ignored.\nThis avoids retracting a lot on the same piece of filament which flattens the filament and causes grinding issues."))
  setting('retraction_hop',            0.0, float, 'expert',   _('Retraction')).setRange(0).setLabel(_("Z hop when retracting (mm)"), _("When a retraction is done, the head is lifted by this amount to travel over the print. A value of 0.075 works well. This feature has a lot of positive effect on delta towers."))
@@@ -210,14 -210,14 +210,14 @@@ setting('layer0_width_factor',       10
  setting('object_sink',               0.0, float, 'advanced', _('Quality')).setRange(0).setLabel(_("Cut off object bottom (mm)"), _("Sinks the object into the platform, this can be used for objects that do not have a flat bottom and thus create a too small first layer."))
  #setting('enable_skin',             False, bool,  'advanced', _('Quality')).setLabel(_("Duplicate outlines"), _("Skin prints the outer lines of the prints twice, each time with half the thickness. This gives the illusion of a higher print quality."))
  setting('overlap_dual',             0.15, float, 'advanced', _('Quality')).setLabel(_("Dual extrusion overlap (mm)"), _("Add a certain amount of overlapping extrusion on dual-extrusion prints. This bonds the different colors together."))
 -setting('travel_speed',            150.0, float, 'advanced', _('Speed')).setRange(0.1).setLabel(_("Travel speed (mm/s)"), _("Speed at which travel moves are done, a well built Ultimaker can reach speeds of 250mm/s. But some machines might miss steps then."))
 -setting('bottom_layer_speed',         20, float, 'advanced', _('Speed')).setRange(0.1).setLabel(_("Bottom layer speed (mm/s)"), _("Print speed for the bottom layer, you want to print the first layer slower so it sticks better to the printer bed."))
 -setting('infill_speed',              0.0, float, 'advanced', _('Speed')).setRange(0.0).setLabel(_("Infill speed (mm/s)"), _("Speed at which infill parts are printed. If set to 0 then the print speed is used for the infill. Printing the infill faster can greatly reduce printing time, but this can negatively affect print quality."))
 +setting('travel_speed',            150.0, float, 'advanced', _('Speed')).setRange(0.1).setLabel(_("Travel speed (mm/s)"), _("Speed at which travel moves are done. A higher value will provide faster print times. Beware that too fast of a speed can reduce print reliability. Most high quality printers can handle 150mm/s to 200mm/s with no problems."))
 +setting('bottom_layer_speed',         20, float, 'advanced', _('Speed')).setRange(0.1).setLabel(_("Bottom layer speed (mm/s)"), _("Print speed for the bottom layer. It is generally best to print the first layer slower so it sticks better to the printer bed."))
 +setting('infill_speed',              0.0, float, 'advanced', _('Speed')).setRange(0.0).setLabel(_("Infill speed (mm/s)"), _("Speed at which infill parts are printed. If set to 0 then the print speed is used for the infill. Printing the infill faster can greatly reduce printing time, but this can negatively affect print quality if made too fast."))
  setting('solidarea_speed',           0.0, float, 'advanced', _('Speed')).setRange(0.0).setLabel(_("Top/bottom speed (mm/s)"), _("Speed at which top/bottom parts are printed. If set to 0 then the print speed is used for the infill. Printing the top/bottom faster can greatly reduce printing time, but this can negatively affect print quality."))
  setting('inset0_speed',              0.0, float, 'advanced', _('Speed')).setRange(0.0).setLabel(_("Outer shell speed (mm/s)"), _("Speed at which outer shell is printed. If set to 0 then the print speed is used. Printing the outer shell at a lower speed improves the final skin quality. However, having a large difference between the inner shell speed and the outer shell speed will effect quality in a negative way."))
  setting('insetx_speed',              0.0, float, 'advanced', _('Speed')).setRange(0.0).setLabel(_("Inner shell speed (mm/s)"), _("Speed at which inner shells are printed. If set to 0 then the print speed is used. Printing the inner shell faster then the outer shell will reduce printing time. It is good to set this somewhere in between the outer shell speed and the infill/printing speed."))
  setting('cool_min_layer_time',         5, float, 'advanced', _('Cool')).setRange(0).setLabel(_("Minimal layer time (sec)"), _("Minimum time spent in a layer, gives the layer time to cool down before the next layer is put on top. If the layer will be placed down too fast the printer will slow down to make sure it has spent at least this amount of seconds printing this layer."))
 -setting('fan_enabled',              True, bool,  'advanced', _('Cool')).setExpertSubCategory(_('Cool')).setLabel(_("Enable cooling fan"), _("Enable the cooling fan during the print. The extra cooling from the cooling fan is essential during faster prints."))
 +setting('fan_enabled',              True, bool,  'advanced', _('Cool')).setExpertSubCategory(_('Cool')).setLabel(_("Enable cooling fan"), _("Enable the cooling fan during the print. The extra cooling from the cooling fan is essential during faster prints and with PLA."))
  
  setting('skirt_line_count',            1, int,   'expert', _('Skirt')).setRange(0).setLabel(_("Line count"), _("The skirt is a line drawn around the object at the first layer. This helps to prime your extruder, and to see if the object fits on your platform.\nSetting this to 0 will disable the skirt. Multiple skirt lines can help priming your extruder better for small objects."))
  setting('skirt_gap',                 3.0, float, 'expert', _('Skirt')).setRange(0).setLabel(_("Start distance (mm)"), _("The distance between the skirt and the first layer.\nThis is the minimal distance, multiple skirt lines will be put outwards from this distance."))
@@@ -259,8 -259,6 +259,8 @@@ setting('plugin_config', '', str, 'hidd
  setting('object_center_x', -1, float, 'hidden', 'hidden')
  setting('object_center_y', -1, float, 'hidden', 'hidden')
  
 +setting('simpleModeSettings', '', str, 'hidden', 'hidden')
 +
  setting('start.gcode', """;Sliced at: {day} {date} {time}
  ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
  ;Print time: {print_time}
@@@ -482,23 -480,23 +482,23 @@@ setting('startMode', 'Simple', ['Simple
  setting('simpleModeProfile', '2_normal', str, 'preference', 'hidden')
  setting('simpleModeMaterial', '1_pla', str, 'preference', 'hidden')
  setting('oneAtATime', 'True', bool, 'preference', 'hidden')
 -setting('lastFile', os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'resources', 'example', 'UltimakerRobot_support.stl')), str, 'preference', 'hidden')
 +setting('lastFile', os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'resources', 'example', 'Rocktopus.stl')), str, 'preference', 'hidden')
  setting('save_profile', 'False', bool, 'preference', 'hidden').setLabel(_("Save profile on slice"), _("When slicing save the profile as [stl_file]_profile.ini next to the model."))
  setting('filament_cost_kg', '0', float, 'preference', 'hidden').setLabel(_("Cost (price/kg)"), _("Cost of your filament per kg, to estimate the cost of the final print."))
  setting('filament_cost_meter', '0', float, 'preference', 'hidden').setLabel(_("Cost (price/m)"), _("Cost of your filament per meter, to estimate the cost of the final print."))
  setting('auto_detect_sd', 'True', bool, 'preference', 'hidden').setLabel(_("Auto detect SD card drive"), _("Auto detect the SD card. You can disable this because on some systems external hard-drives or USB sticks are detected as SD card."))
 -setting('check_for_updates', 'True', bool, 'preference', 'hidden').setLabel(_("Check for updates"), _("Check for newer versions of Cura on startup"))
 +setting('check_for_updates', 'False', bool, 'preference', 'hidden').setLabel(_("Check for updates"), _("Check for newer versions of Cura on startup"))
  setting('submit_slice_information', 'False', bool, 'preference', 'hidden').setLabel(_("Send usage statistics"), _("Submit anonymous usage information to improve future versions of Cura"))
  setting('youmagine_token', '', str, 'preference', 'hidden')
  setting('filament_physical_density', '1240', float, 'preference', 'hidden').setRange(500.0, 3000.0).setLabel(_("Density (kg/m3)"), _("Weight of the filament per m3. Around 1240 for PLA. And around 1040 for ABS. This value is used to estimate the weight if the filament used for the print."))
 -setting('language', 'English', str, 'preference', 'hidden').setLabel(_('Language'), _('Change the language in which Cura runs. Switching language requires a restart of Cura'))
 +setting('language', 'Autodetect', str, 'preference', 'hidden').setLabel(_('Language'), _('Change the language in which Cura runs. Switching language requires a restart of Cura'))
  setting('active_machine', '0', int, 'preference', 'hidden')
  
 -setting('model_colour', '#FFC924', str, 'preference', 'hidden').setLabel(_('Model colour'), _('Display color for first extruder'))
 +setting('model_colour', '#C9E240', str, 'preference', 'hidden').setLabel(_('Model colour'), _('Display color for first extruder'))
  setting('model_colour2', '#CB3030', str, 'preference', 'hidden').setLabel(_('Model colour (2)'), _('Display color for second extruder'))
  setting('model_colour3', '#DDD93C', str, 'preference', 'hidden').setLabel(_('Model colour (3)'), _('Display color for third extruder'))
  setting('model_colour4', '#4550D3', str, 'preference', 'hidden').setLabel(_('Model colour (4)'), _('Display color for forth extruder'))
 -setting('printing_window', 'Basic', ['Basic'], 'preference', 'hidden').setLabel(_('Printing window type'), _('Select the interface used for USB printing.'))
 +setting('printing_window', 'Pronterface UI', ['Basic'], 'preference', 'hidden').setLabel(_('Printing window type'), _('Select the interface used for USB printing.'))
  
  setting('window_maximized', 'True', bool, 'preference', 'hidden')
  setting('window_pos_x', '-1', float, 'preference', 'hidden')
@@@ -510,13 -508,13 +510,13 @@@ setting('last_run_version', '', str, 'p
  
  setting('machine_name', '', str, 'machine', 'hidden')
  setting('machine_type', 'unknown', str, 'machine', 'hidden') #Ultimaker, Ultimaker2, RepRap
 -setting('machine_width', '205', float, 'machine', 'hidden').setLabel(_("Maximum width (mm)"), _("Size of the machine in mm"))
 -setting('machine_depth', '205', float, 'machine', 'hidden').setLabel(_("Maximum depth (mm)"), _("Size of the machine in mm"))
 -setting('machine_height', '200', float, 'machine', 'hidden').setLabel(_("Maximum height (mm)"), _("Size of the machine in mm"))
 +setting('machine_width', '205', float, 'machine', 'hidden').setLabel(_("Maximum width (mm)"), _("Maximum width of the machine print area in mm"))
 +setting('machine_depth', '205', float, 'machine', 'hidden').setLabel(_("Maximum depth (mm)"), _("Maximum depth of the machine print area in mm"))
 +setting('machine_height', '200', float, 'machine', 'hidden').setLabel(_("Maximum height (mm)"), _("Maximum height of the machine print area in mm"))
  setting('machine_center_is_zero', 'False', bool, 'machine', 'hidden').setLabel(_("Machine center 0,0"), _("Machines firmware defines the center of the bed as 0,0 instead of the front left corner."))
  setting('machine_shape', 'Square', ['Square','Circular'], 'machine', 'hidden').setLabel(_("Build area shape"), _("The shape of machine build area."))
  setting('ultimaker_extruder_upgrade', 'False', bool, 'machine', 'hidden')
 -setting('has_heated_bed', 'False', bool, 'machine', 'hidden').setLabel(_("Heated bed"), _("If you have an heated bed, this enabled heated bed settings (requires restart)"))
 +setting('has_heated_bed', 'False', bool, 'machine', 'hidden').setLabel(_("Heated bed"), _("If you have a heated bed, this enabled heated bed settings (requires restart)"))
  setting('gcode_flavor', 'RepRap (Marlin/Sprinter)', ['RepRap (Marlin/Sprinter)', 'RepRap (Volumetric)', 'UltiGCode', 'MakerBot', 'BFB', 'Mach3'], 'machine', 'hidden').setLabel(_("GCode Flavor"), _("Flavor of generated GCode.\nRepRap is normal 5D GCode which works on Marlin/Sprinter based firmwares.\nUltiGCode is a variation of the RepRap GCode which puts more settings in the machine instead of the slicer.\nMakerBot GCode has a few changes in the way GCode is generated, but still requires MakerWare to generate to X3G.\nBFB style generates RPM based code.\nMach3 uses A,B,C instead of E for extruders."))
  setting('extruder_amount', '1', ['1','2','3','4'], 'machine', 'hidden').setLabel(_("Extruder count"), _("Amount of extruders in your machine."))
  setting('extruder_offset_x1', '0.0', float, 'machine', 'hidden').setLabel(_("Offset X"), _("The offset of your secondary extruder compared to the primary."))
@@@ -525,19 -523,17 +525,19 @@@ setting('extruder_offset_x2', '0.0', fl
  setting('extruder_offset_y2', '0.0', float, 'machine', 'hidden').setLabel(_("Offset Y"), _("The offset of your tertiary extruder compared to the primary."))
  setting('extruder_offset_x3', '0.0', float, 'machine', 'hidden').setLabel(_("Offset X"), _("The offset of your forth extruder compared to the primary."))
  setting('extruder_offset_y3', '0.0', float, 'machine', 'hidden').setLabel(_("Offset Y"), _("The offset of your forth extruder compared to the primary."))
 +setting('extruder_z_offset', '0.0', float, 'machine', 'hidden').setLabel(_("Z-Offset (mm)"), _("This value will be added to the Z coordinate of every line in the output G-Code to compensate for a badly calibrate Z height endstop."))
 +
  setting('steps_per_e', '0', float, 'machine', 'hidden').setLabel(_("E-Steps per 1mm filament"), _("Amount of steps per mm filament extrusion. If set to 0 then this value is ignored and the value in your firmware is used."))
  setting('serial_port', 'AUTO', str, 'machine', 'hidden').setLabel(_("Serial port"), _("Serial port to use for communication with the printer"))
  setting('serial_port_auto', '', str, 'machine', 'hidden')
  setting('serial_baud', 'AUTO', str, 'machine', 'hidden').setLabel(_("Baudrate"), _("Speed of the serial port communication\nNeeds to match your firmware settings\nCommon values are 250000, 115200, 57600"))
  setting('serial_baud_auto', '', int, 'machine', 'hidden')
  
 -setting('extruder_head_size_min_x', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards X min (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head. 75mm for an Ultimaker if the fan is on the left side."))
 -setting('extruder_head_size_min_y', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards Y min (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head. 18mm for an Ultimaker if the fan is on the left side."))
 -setting('extruder_head_size_max_x', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards X max (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head. 18mm for an Ultimaker if the fan is on the left side."))
 -setting('extruder_head_size_max_y', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards Y max (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head. 35mm for an Ultimaker if the fan is on the left side."))
 -setting('extruder_head_size_height', '0.0', float, 'machine', 'hidden').setLabel(_("Printer gantry height (mm)"), _("The height of the gantry holding up the printer head. If an object is higher then this then you cannot print multiple objects one for one. 60mm for an Ultimaker."))
 +setting('extruder_head_size_min_x', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards X min (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head."))
 +setting('extruder_head_size_min_y', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards Y min (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head."))
 +setting('extruder_head_size_max_x', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards X max (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head."))
 +setting('extruder_head_size_max_y', '0.0', float, 'machine', 'hidden').setLabel(_("Head size towards Y max (mm)"), _("The head size when printing multiple objects, measured from the tip of the nozzle towards the outer part of the head."))
 +setting('extruder_head_size_height', '0.0', float, 'machine', 'hidden').setLabel(_("Printer gantry height (mm)"), _("The height of the gantry holding up the printer head. If an object is higher then this then you cannot print multiple objects one for one."))
  
  validators.warningAbove(settingsDictionary['filament_flow'], 150, _("More flow than 150% is rare and usually not recommended."))
  validators.warningBelow(settingsDictionary['filament_flow'], 50, _("Less flow than 50% is rare and usually not recommended."))
@@@ -780,7 -776,7 +780,7 @@@ def resetProfile()
        elif getMachineSetting('machine_type') == 'ultimaker_plus':
                putProfileSetting('nozzle_size', '0.4')
                putProfileSetting('retraction_enable', 'True')
-       elif getMachineSetting('machine_type') == 'ultimaker2':
+       elif getMachineSetting('machine_type').startswith('ultimaker2'):
                putProfileSetting('nozzle_size', '0.4')
                putProfileSetting('retraction_enable', 'True')
        else:
@@@ -1157,8 -1153,6 +1157,8 @@@ def calculateObjectSizeOffsets()
  def getMachineCenterCoords():
        if getMachineSetting('machine_center_is_zero') == 'True':
                return [0, 0]
 +      elif getMachineSetting('machine_type') == 'lulzbot_mini':
 +              return [(getMachineSettingFloat('machine_width') / 2) + 2.5, (getMachineSettingFloat('machine_width') / 2) + 0.5]
        return [getMachineSettingFloat('machine_width') / 2, getMachineSettingFloat('machine_depth') / 2]
  
  #Returns a list of convex polygons, first polygon is the allowed area of the machine,
@@@ -1176,10 -1170,10 +1176,10 @@@ def getMachineSizePolygons()
        else:
                ret.append(numpy.array([[-size[0]/2,-size[1]/2],[size[0]/2,-size[1]/2],[size[0]/2, size[1]/2], [-size[0]/2, size[1]/2]], numpy.float32))
  
-       if getMachineSetting('machine_type') == 'ultimaker2':
+       if getMachineSetting('machine_type').startswith('ultimaker2'):
                #UM2 no-go zones
                w = 25
-               h = 10
+               h = 8
                ret.append(numpy.array([[-size[0]/2,-size[1]/2],[-size[0]/2+w+2,-size[1]/2], [-size[0]/2+w,-size[1]/2+h], [-size[0]/2,-size[1]/2+h]], numpy.float32))
                ret.append(numpy.array([[ size[0]/2-w-2,-size[1]/2],[ size[0]/2,-size[1]/2], [ size[0]/2,-size[1]/2+h],[ size[0]/2-w,-size[1]/2+h]], numpy.float32))
                ret.append(numpy.array([[-size[0]/2+w+2, size[1]/2],[-size[0]/2, size[1]/2], [-size[0]/2, size[1]/2-h],[-size[0]/2+w, size[1]/2-h]], numpy.float32))
diff --combined package.sh
index 7330f7ac6e94e92f73a0360ef18b4c692481276e,c1dd3947e6bf2d7b0a9ad2a0e1bbe8ded04b6662..1969b9deb7e471bedf477665d634e9b11b32e975
@@@ -19,21 -19,15 +19,21 @@@ BUILD_TARGET=${1:-none
  ##Do we need to create the final archive
  ARCHIVE_FOR_DISTRIBUTION=1
  ##Which version name are we appending to the final archive
- export BUILD_NAME=15.01-RC6
+ export BUILD_NAME=15.01-RC7
  TARGET_DIR=Cura-${BUILD_NAME}-${BUILD_TARGET}
  
 +##Revision
 +export REVISION=1.19
 +
 +##Git commit
 +GIT_HASH=$(git rev-parse --short=4 HEAD)
 +
  ##Which versions of external programs to use
  WIN_PORTABLE_PY_VERSION=2.7.2.1
  
  ##Which CuraEngine to use
  if [ -z ${CURA_ENGINE_REPO} ] ; then
 -      CURA_ENGINE_REPO="git@github.com:Ultimaker/CuraEngine.git"
 +      CURA_ENGINE_REPO="git@github.com:alephobjects/CuraEngine.git"
  fi
  
  #############################
@@@ -164,8 -158,14 +164,14 @@@ cd 
  
  gitClone git@github.com:Ultimaker/Ultimaker2Marlin.git _Ultimaker2Marlin
  cd _Ultimaker2Marlin/Marlin
+ git checkout master
  $MAKE -j 3 HARDWARE_MOTHERBOARD=72 ARDUINO_INSTALL_DIR=${ARDUINO_PATH} ARDUINO_VERSION=${ARDUINO_VERSION} BUILD_DIR=_Ultimaker2 DEFINES="'STRING_CONFIG_H_AUTHOR=\"Version:_${BUILD_NAME}\"' TEMP_SENSOR_1=0 EXTRUDERS=1"
  $MAKE -j 3 HARDWARE_MOTHERBOARD=72 ARDUINO_INSTALL_DIR=${ARDUINO_PATH} ARDUINO_VERSION=${ARDUINO_VERSION} BUILD_DIR=_Ultimaker2Dual DEFINES="'STRING_CONFIG_H_AUTHOR=\"Version:_${BUILD_NAME}\"' TEMP_SENSOR_1=20 EXTRUDERS=2"
+ git checkout UM2go
+ $MAKE -j 3 HARDWARE_MOTHERBOARD=72 ARDUINO_INSTALL_DIR=${ARDUINO_PATH} ARDUINO_VERSION=${ARDUINO_VERSION} BUILD_DIR=_Ultimaker2go DEFINES="'STRING_CONFIG_H_AUTHOR=\"Version:_${BUILD_NAME}go\"' TEMP_SENSOR_1=0 EXTRUDERS=1"
+ git checkout UM2extended
+ $MAKE -j 3 HARDWARE_MOTHERBOARD=72 ARDUINO_INSTALL_DIR=${ARDUINO_PATH} ARDUINO_VERSION=${ARDUINO_VERSION} BUILD_DIR=_Ultimaker2extended DEFINES="'STRING_CONFIG_H_AUTHOR=\"Version:_${BUILD_NAME}ex\"' TEMP_SENSOR_1=0 EXTRUDERS=1"
+ $MAKE -j 3 HARDWARE_MOTHERBOARD=72 ARDUINO_INSTALL_DIR=${ARDUINO_PATH} ARDUINO_VERSION=${ARDUINO_VERSION} BUILD_DIR=_Ultimaker2extendedDual DEFINES="'STRING_CONFIG_H_AUTHOR=\"Version:_${BUILD_NAME}ex\"' TEMP_SENSOR_1=20 EXTRUDERS=2"
  cd -
  
  cp _UltimakerMarlin/Marlin/_UltimakerMarlin_250000/Marlin.hex resources/firmware/MarlinUltimaker-250000.hex
@@@ -182,6 -182,9 +188,9 @@@ cp _UltimakerMarlin/Marlin/_UltimakerMa
  cp _UltimakerMarlin/Marlin/_UltimakerMarlin_Plus_Dual_115200/Marlin.hex resources/firmware/MarlinUltimaker-UMOP-115200-dual.hex
  cp _Ultimaker2Marlin/Marlin/_Ultimaker2/Marlin.hex resources/firmware/MarlinUltimaker2.hex
  cp _Ultimaker2Marlin/Marlin/_Ultimaker2Dual/Marlin.hex resources/firmware/MarlinUltimaker2-dual.hex
+ cp _Ultimaker2Marlin/Marlin/_Ultimaker2go/Marlin.hex resources/firmware/MarlinUltimaker2go.hex
+ cp _Ultimaker2Marlin/Marlin/_Ultimaker2extended/Marlin.hex resources/firmware/MarlinUltimaker2extended.hex
+ cp _Ultimaker2Marlin/Marlin/_Ultimaker2extendedDual/Marlin.hex resources/firmware/MarlinUltimaker2extended-dual.hex
  
  #############################
  # Darwin
@@@ -221,13 -224,13 +230,13 @@@ if [ "$BUILD_TARGET" = "darwin" ]; the
        cd ..
  
        # Create sparse image for distribution
 -      hdiutil detach /Volumes/Cura\ -\ Ultimaker/
 +      hdiutil detach /Volumes/Cura\ -\ Lulzbot/
        rm -rf Cura.dmg.sparseimage
        hdiutil convert DmgTemplateCompressed.dmg -format UDSP -o Cura.dmg
        hdiutil resize -size 500m Cura.dmg.sparseimage
        hdiutil attach Cura.dmg.sparseimage
 -      cp -a dist/Cura.app /Volumes/Cura\ -\ Ultimaker/Cura/
 -      hdiutil detach /Volumes/Cura\ -\ Ultimaker
 +      cp -a dist/Cura.app /Volumes/Cura\ -\ Lulzbot/Cura/
 +      hdiutil detach /Volumes/Cura\ -\ Lulzbot
        hdiutil convert Cura.dmg.sparseimage -format UDZO -imagekey zlib-level=9 -ov -o ../../${TARGET_DIR}.dmg
        exit
  fi
@@@ -303,7 -306,7 +312,7 @@@ if [ "$BUILD_TARGET" = "debian_i386" ]
        sudo chmod 755 scripts/linux/${BUILD_TARGET}/usr -R
        sudo chmod 755 scripts/linux/${BUILD_TARGET}/DEBIAN -R
        cd scripts/linux
 -      dpkg-deb --build ${BUILD_TARGET} $(dirname ${TARGET_DIR})/cura_${BUILD_NAME}-${BUILD_TARGET}.deb
 +      dpkg-deb -Zgzip --build ${BUILD_TARGET} $(dirname ${TARGET_DIR})/cura_${BUILD_NAME}-${REVISION}-${GIT_HASH}_i386.deb
        sudo chown `id -un`:`id -gn` ${BUILD_TARGET} -R
        exit
  fi
@@@ -333,7 -336,7 +342,7 @@@ if [ "$BUILD_TARGET" = "debian_amd64" ]
        sudo chmod 755 scripts/linux/${BUILD_TARGET}/usr -R
        sudo chmod 755 scripts/linux/${BUILD_TARGET}/DEBIAN -R
        cd scripts/linux
 -      dpkg-deb --build ${BUILD_TARGET} $(dirname ${TARGET_DIR})/cura_${BUILD_NAME}-${BUILD_TARGET}.deb
 +      dpkg-deb -Zgzip --build ${BUILD_TARGET} $(dirname ${TARGET_DIR})/cura_${BUILD_NAME}-${REVISION}-${GIT_HASH}_amd64.deb
        sudo chown `id -un`:`id -gn` ${BUILD_TARGET} -R
        exit
  fi
@@@ -433,8 -436,6 +442,8 @@@ if [ $BUILD_TARGET = "win32" ]; the
        #mv ffmpeg-20120927-git-13f0cd6-win32-static/bin/ffmpeg.exe ${TARGET_DIR}/Cura/
        #mv ffmpeg-20120927-git-13f0cd6-win32-static/licenses ${TARGET_DIR}/Cura/ffmpeg-licenses/
        mv Win32/EjectMedia.exe ${TARGET_DIR}/Cura/
 +      cp -a scripts/win32/nsisPlugins/libgcc_s_dw2-1.dll ${TARGET_DIR}
 +      cp -a scripts/win32/nsisPlugins/libstdc++-6.dll ${TARGET_DIR}
        
        rm -rf Power/
        rm -rf \$_OUTDIR
@@@ -492,7 -493,7 +501,7 @@@ if (( ${ARCHIVE_FOR_DISTRIBUTION} )); t
                        ln -sf `pwd`/${TARGET_DIR} scripts/win32/dist
                        wine ~/.wine/drive_c/Program\ Files\ \(x86\)/NSIS/makensis.exe /DVERSION=${BUILD_NAME} scripts/win32/installer.nsi
              if [ $? != 0 ]; then echo "Failed to package NSIS installer"; exit 1; fi
 -                      mv scripts/win32/Cura_${BUILD_NAME}.exe ./
 +                      mv scripts/win32/Cura_${BUILD_NAME}-${REVISION}-${GIT_HASH}.exe ./
                fi
                if [ -f '/c/Program Files (x86)/NSIS/makensis.exe' ]; then
                        rm -rf scripts/win32/dist