chiark / gitweb /
Add an about box.
authordaid303 <daid303@gmail.com>
Thu, 16 May 2013 09:11:32 +0000 (11:11 +0200)
committerdaid303 <daid303@gmail.com>
Thu, 16 May 2013 09:11:32 +0000 (11:11 +0200)
Cura/gui/mainWindow.py
Cura/gui/preview3d.py [deleted file]
Cura/gui/projectPlanner.py [deleted file]
Cura/gui/sliceProgressPanel.py [deleted file]
Cura/gui/tools/superformula.py

index 0523889d97878b496a135408b4f6f2b9321f04a2..998f4b77af7ce06384296a331dc4b95970403fb5 100644 (file)
@@ -145,6 +145,8 @@ class mainWindow(wx.Frame):
                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, 'About Cura...')
+               self.Bind(wx.EVT_MENU, self.OnAbout, i)
                self.menubar.Append(helpMenu, 'Help')
                self.SetMenuBar(self.menubar)
 
@@ -409,6 +411,28 @@ class mainWindow(wx.Frame):
                else:
                        wx.MessageBox('You are running the latest version of Cura!', 'Awesome!', wx.ICON_INFORMATION)
 
+       def OnAbout(self, e):
+               info = wx.AboutDialogInfo()
+               info.SetName('Cura')
+               info.SetDescription('End solution for Open Source Fused Filament Fabrication 3D printing.')
+               info.SetWebSite('http://software.ultimaker.com/')
+               info.SetCopyright('Copyright (C) David Braam')
+               info.SetLicence("""
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+""")
+               wx.AboutBox(info)
+
        def OnClose(self, e):
                profile.saveProfile(profile.getDefaultProfilePath())
 
diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py
deleted file mode 100644 (file)
index 4a25ea3..0000000
+++ /dev/null
@@ -1,902 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-
-import math
-import threading
-import re
-import time
-import os
-import numpy
-import traceback
-import sys
-
-from wx import glcanvas
-import wx
-import OpenGL
-OpenGL.ERROR_CHECKING = False
-from OpenGL.GLU import *
-from OpenGL.GL import *
-
-from Cura.util import profile
-from Cura.util import gcodeInterpreter
-from Cura.util import meshLoader
-from Cura.util import util3d
-from Cura.util import sliceRun
-
-from Cura.gui.util import opengl
-from Cura.gui.util import previewTools
-from Cura.gui.util import openglGui
-
-class previewObject():
-       def __init__(self):
-               self.mesh = None
-               self.filename = None
-               self.displayList = None
-               self.dirty = False
-
-class previewPanel(wx.Panel):
-       def __init__(self, parent):
-               super(previewPanel, self).__init__(parent,-1)
-               
-               self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DDKSHADOW))
-               self.SetMinSize((440,320))
-
-               self.objectList = []
-               self.errorList = []
-               self.gcode = None
-               self.objectsMinV = None
-               self.objectsMaxV = None
-               self.objectsBoundaryCircleSize = None
-               self.loadThread = None
-               self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height'))
-               self.machineCenter = util3d.Vector3(self.machineSize.x / 2, self.machineSize.y / 2, 0)
-
-               self.glCanvas = PreviewGLCanvas(self)
-               #Create the popup window
-               self.warningPopup = wx.PopupWindow(self, flags=wx.BORDER_SIMPLE)
-               self.warningPopup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
-               self.warningPopup.text = wx.StaticText(self.warningPopup, -1, 'Reset scale, rotation and mirror?')
-               self.warningPopup.yesButton = wx.Button(self.warningPopup, -1, 'yes', style=wx.BU_EXACTFIT)
-               self.warningPopup.noButton = wx.Button(self.warningPopup, -1, 'no', style=wx.BU_EXACTFIT)
-               self.warningPopup.sizer = wx.BoxSizer(wx.HORIZONTAL)
-               self.warningPopup.SetSizer(self.warningPopup.sizer)
-               self.warningPopup.sizer.Add(self.warningPopup.text, 1, flag=wx.ALL|wx.ALIGN_CENTER_VERTICAL, border=1)
-               self.warningPopup.sizer.Add(self.warningPopup.yesButton, 0, flag=wx.EXPAND|wx.ALL, border=1)
-               self.warningPopup.sizer.Add(self.warningPopup.noButton, 0, flag=wx.EXPAND|wx.ALL, border=1)
-               self.warningPopup.Fit()
-               self.warningPopup.Layout()
-               self.warningPopup.timer = wx.Timer(self)
-               self.Bind(wx.EVT_TIMER, self.OnHideWarning, self.warningPopup.timer)
-               
-               self.Bind(wx.EVT_BUTTON, self.OnWarningPopup, self.warningPopup.yesButton)
-               self.Bind(wx.EVT_BUTTON, self.OnHideWarning, self.warningPopup.noButton)
-               parent.Bind(wx.EVT_MOVE, self.OnMove)
-               parent.Bind(wx.EVT_SIZE, self.OnMove)
-               
-               sizer = wx.BoxSizer(wx.VERTICAL)
-               sizer.Add(self.glCanvas, 1, flag=wx.EXPAND)
-               self.SetSizer(sizer)
-               
-               self.checkReloadFileTimer = wx.Timer(self)
-               self.Bind(wx.EVT_TIMER, self.OnCheckReloadFile, self.checkReloadFileTimer)
-               self.checkReloadFileTimer.Start(1000)
-
-               group = []
-               self.rotateToolButton = openglGui.glRadioButton(self.glCanvas, 8, 'Rotate', (0,-1), group, self.OnToolSelect)
-               self.scaleToolButton  = openglGui.glRadioButton(self.glCanvas, 9, 'Scale', (1,-1), group, self.OnToolSelect)
-               self.mirrorToolButton  = openglGui.glRadioButton(self.glCanvas, 10, 'Mirror', (2,-1), group, self.OnToolSelect)
-
-               self.resetRotationButton = openglGui.glButton(self.glCanvas, 12, 'Reset', (0,-2), self.OnRotateReset)
-               self.layFlatButton       = openglGui.glButton(self.glCanvas, 16, 'Lay flat', (0,-3), self.OnLayFlat)
-
-               self.resetScaleButton    = openglGui.glButton(self.glCanvas, 13, 'Reset', (1,-2), self.OnScaleReset)
-               self.scaleMaxButton      = openglGui.glButton(self.glCanvas, 17, 'To max', (1,-3), self.OnScaleMax)
-
-               self.mirrorXButton       = openglGui.glButton(self.glCanvas, 14, 'Mirror X', (2,-2), lambda : self.OnMirror(0))
-               self.mirrorYButton       = openglGui.glButton(self.glCanvas, 18, 'Mirror Y', (2,-3), lambda : self.OnMirror(1))
-               self.mirrorZButton       = openglGui.glButton(self.glCanvas, 22, 'Mirror Z', (2,-4), lambda : self.OnMirror(2))
-
-               self.openFileButton      = openglGui.glButton(self.glCanvas, 4, 'Load', (0,0), lambda : self.GetParent().GetParent().GetParent()._showModelLoadDialog(1))
-               self.sliceButton         = openglGui.glButton(self.glCanvas, 5, 'Prepare', (1,0), lambda : self.GetParent().GetParent().GetParent().OnSlice(None))
-               self.printButton         = openglGui.glButton(self.glCanvas, 6, 'Print', (2,0), lambda : self.GetParent().GetParent().GetParent().OnPrint(None))
-
-               self.rotateToolButton.setExpandArrow(True)
-               self.scaleToolButton.setExpandArrow(True)
-               self.mirrorToolButton.setExpandArrow(True)
-
-               extruderCount = int(profile.getPreference('extruder_amount'))
-               if extruderCount > 1:
-                       openglGui.glButton(self.glCanvas, 4, 'Load dual', (0,1), lambda : self.GetParent().GetParent().GetParent()._showModelLoadDialog(2))
-               if extruderCount > 2:
-                       openglGui.glButton(self.glCanvas, 4, 'Load triple', (0,2), lambda : self.GetParent().GetParent().GetParent()._showModelLoadDialog(3))
-               if extruderCount > 3:
-                       openglGui.glButton(self.glCanvas, 4, 'Load quad', (0,3), lambda : self.GetParent().GetParent().GetParent()._showModelLoadDialog(4))
-
-               self.scaleForm = openglGui.glFrame(self.glCanvas, (2, -2))
-               openglGui.glGuiLayoutGrid(self.scaleForm)
-               openglGui.glLabel(self.scaleForm, 'Scale X', (0,0))
-               self.scaleXctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,0), lambda value: self.OnScaleEntry(value, 0))
-               openglGui.glLabel(self.scaleForm, 'Scale Y', (0,1))
-               self.scaleYctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,1), lambda value: self.OnScaleEntry(value, 1))
-               openglGui.glLabel(self.scaleForm, 'Scale Z', (0,2))
-               self.scaleZctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,2), lambda value: self.OnScaleEntry(value, 2))
-               openglGui.glLabel(self.scaleForm, 'Size X (mm)', (0,4))
-               self.scaleXmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,4), lambda value: self.OnScaleEntryMM(value, 0))
-               openglGui.glLabel(self.scaleForm, 'Size Y (mm)', (0,5))
-               self.scaleYmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,5), lambda value: self.OnScaleEntryMM(value, 1))
-               openglGui.glLabel(self.scaleForm, 'Size Z (mm)', (0,6))
-               self.scaleZmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,6), lambda value: self.OnScaleEntryMM(value, 2))
-               openglGui.glLabel(self.scaleForm, 'Uniform scale', (0,8))
-               self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None)
-
-               self.viewSelection = openglGui.glComboButton(self.glCanvas, 'View mode', [7,11,15,19,23], ['Normal', 'Transparent', 'X-Ray', 'Overhang', 'Layers'], (-1,0), self.OnViewChange)
-               self.layerSelect = openglGui.glSlider(self.glCanvas, 0, 0, 100, (-1,-2), lambda : self.Refresh())
-
-               self.OnViewChange()
-               self.OnToolSelect()
-               self.updateModelTransform()
-
-               self.matrix = numpy.matrix(numpy.array(profile.getObjectMatrix(), numpy.float64).reshape((3,3,)))
-
-       def OnToolSelect(self):
-               if self.rotateToolButton.getSelected():
-                       self.tool = previewTools.toolRotate(self.glCanvas)
-               elif self.scaleToolButton.getSelected():
-                       self.tool = previewTools.toolScale(self.glCanvas)
-               elif self.mirrorToolButton.getSelected():
-                       self.tool = previewTools.toolNone(self.glCanvas)
-               else:
-                       self.tool = previewTools.toolNone(self.glCanvas)
-               self.resetRotationButton.setHidden(not self.rotateToolButton.getSelected())
-               self.layFlatButton.setHidden(not self.rotateToolButton.getSelected())
-               self.resetScaleButton.setHidden(not self.scaleToolButton.getSelected())
-               self.scaleMaxButton.setHidden(not self.scaleToolButton.getSelected())
-               self.scaleForm.setHidden(not self.scaleToolButton.getSelected())
-               self.mirrorXButton.setHidden(not self.mirrorToolButton.getSelected())
-               self.mirrorYButton.setHidden(not self.mirrorToolButton.getSelected())
-               self.mirrorZButton.setHidden(not self.mirrorToolButton.getSelected())
-               self.updateModelTransform()
-
-       def OnScaleEntry(self, value, axis):
-               try:
-                       value = float(value)
-               except:
-                       return
-               scale = numpy.linalg.norm(self.matrix[::,axis].getA().flatten())
-               scale = value / scale
-               if scale == 0:
-                       return
-               if self.scaleUniform.getValue():
-                       matrix = [[scale,0,0], [0, scale, 0], [0, 0, scale]]
-               else:
-                       matrix = [[1.0,0,0], [0, 1.0, 0], [0, 0, 1.0]]
-                       matrix[axis][axis] = scale
-               self.matrix *= numpy.matrix(matrix, numpy.float64)
-               self.updateModelTransform()
-
-       def OnScaleEntryMM(self, value, axis):
-               try:
-                       value = float(value)
-               except:
-                       return
-               scale = self.objectsSize[axis]
-               scale = value / scale
-               if scale == 0:
-                       return
-               if self.scaleUniform.getValue():
-                       matrix = [[scale,0,0], [0, scale, 0], [0, 0, scale]]
-               else:
-                       matrix = [[1,0,0], [0, 1, 0], [0, 0, 1]]
-                       matrix[axis][axis] = scale
-               self.matrix *= numpy.matrix(matrix, numpy.float64)
-               self.updateModelTransform()
-
-       def OnMirror(self, axis):
-               matrix = [[1,0,0], [0, 1, 0], [0, 0, 1]]
-               matrix[axis][axis] = -1
-               self.matrix *= numpy.matrix(matrix, numpy.float64)
-               for obj in self.objectList:
-                       obj.dirty = True
-                       obj.steepDirty = True
-               self.updateModelTransform()
-
-       def OnMove(self, e = None):
-               if e is not None:
-                       e.Skip()
-               x, y = self.glCanvas.ClientToScreenXY(0, 0)
-               sx, sy = self.glCanvas.GetClientSizeTuple()
-               self.warningPopup.SetPosition((x, y+sy-self.warningPopup.GetSize().height))
-
-       def OnScaleMax(self):
-               if self.objectsMinV is None:
-                       return
-               vMin = self.objectsMinV
-               vMax = self.objectsMaxV
-               skirtSize = 3
-               if profile.getProfileSettingFloat('skirt_line_count') > 0:
-                       skirtSize = 3 + profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
-               scaleX1 = (self.machineSize.x - self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2)
-               scaleY1 = (self.machineSize.y - self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2)
-               scaleX2 = (self.machineCenter.x - skirtSize) / ((vMax[0] - vMin[0]) / 2)
-               scaleY2 = (self.machineCenter.y - skirtSize) / ((vMax[1] - vMin[1]) / 2)
-               scaleZ = self.machineSize.z / (vMax[2] - vMin[2])
-               scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ)
-               self.matrix *= numpy.matrix([[scale,0,0],[0,scale,0],[0,0,scale]], numpy.float64)
-               if self.glCanvas.viewMode == 'GCode' or self.glCanvas.viewMode == 'Mixed':
-                       self.setViewMode('Normal')
-               self.updateModelTransform()
-
-       def OnRotateReset(self):
-               x = numpy.linalg.norm(self.matrix[::,0].getA().flatten())
-               y = numpy.linalg.norm(self.matrix[::,1].getA().flatten())
-               z = numpy.linalg.norm(self.matrix[::,2].getA().flatten())
-               self.matrix = numpy.matrix([[x,0,0],[0,y,0],[0,0,z]], numpy.float64)
-               for obj in self.objectList:
-                       obj.dirty = True
-                       obj.steepDirty = True
-               self.updateModelTransform()
-
-       def OnScaleReset(self):
-               x = 1/numpy.linalg.norm(self.matrix[::,0].getA().flatten())
-               y = 1/numpy.linalg.norm(self.matrix[::,1].getA().flatten())
-               z = 1/numpy.linalg.norm(self.matrix[::,2].getA().flatten())
-               self.matrix *= numpy.matrix([[x,0,0],[0,y,0],[0,0,z]], numpy.float64)
-               for obj in self.objectList:
-                       obj.steepDirty = True
-               self.updateModelTransform()
-
-       def OnLayFlat(self):
-               transformedVertexes = (numpy.matrix(self.objectList[0].mesh.vertexes, copy = False) * self.matrix).getA()
-               minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
-               dotMin = 1.0
-               dotV = None
-               for v in transformedVertexes:
-                       diff = v - minZvertex
-                       len = math.sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2])
-                       if len < 5:
-                               continue
-                       dot = (diff[2] / len)
-                       if dotMin > dot:
-                               dotMin = dot
-                               dotV = diff
-               if dotV is None:
-                       return
-               rad = -math.atan2(dotV[1], dotV[0])
-               self.matrix *= numpy.matrix([[math.cos(rad), math.sin(rad), 0], [-math.sin(rad), math.cos(rad), 0], [0,0,1]], numpy.float64)
-               rad = -math.asin(dotMin)
-               self.matrix *= numpy.matrix([[math.cos(rad), 0, math.sin(rad)], [0,1,0], [-math.sin(rad), 0, math.cos(rad)]], numpy.float64)
-
-
-               transformedVertexes = (numpy.matrix(self.objectList[0].mesh.vertexes, copy = False) * self.matrix).getA()
-               minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
-               dotMin = 1.0
-               dotV = None
-               for v in transformedVertexes:
-                       diff = v - minZvertex
-                       len = math.sqrt(diff[1] * diff[1] + diff[2] * diff[2])
-                       if len < 5:
-                               continue
-                       dot = (diff[2] / len)
-                       if dotMin > dot:
-                               dotMin = dot
-                               dotV = diff
-               if dotV is None:
-                       return
-               if dotV[1] < 0:
-                       rad = math.asin(dotMin)
-               else:
-                       rad = -math.asin(dotMin)
-               self.matrix *= numpy.matrix([[1,0,0], [0, math.cos(rad), math.sin(rad)], [0, -math.sin(rad), math.cos(rad)]], numpy.float64)
-
-               for obj in self.objectList:
-                       obj.steepDirty = True
-               self.updateModelTransform()
-
-       def setViewMode(self, mode):
-               if mode == "Normal":
-                       self.viewSelection.setValue(0)
-               if mode == "GCode":
-                       self.viewSelection.setValue(4)
-               wx.CallAfter(self.glCanvas.Refresh)
-
-       def loadModelFiles(self, filelist, showWarning = False):
-               while len(filelist) > len(self.objectList):
-                       self.objectList.append(previewObject())
-               for idx in xrange(len(filelist), len(self.objectList)):
-                       self.objectList[idx].mesh = None
-                       self.objectList[idx].filename = None
-               for idx in xrange(0, len(filelist)):
-                       obj = self.objectList[idx]
-                       if obj.filename != filelist[idx]:
-                               obj.fileTime = None
-                               self.gcodeFileTime = None
-                               self.logFileTime = None
-                               obj.mesh = None
-                       obj.filename = filelist[idx]
-
-               self.deselectTool()
-               self.gcodeFilename = sliceRun.getExportFilename(filelist[0])
-               self.gcode = None
-               #Do the STL file loading in a background thread so we don't block the UI.
-               if self.loadThread is not None and self.loadThread.isAlive():
-                       self.abortLoading = True
-                       self.loadThread.join()
-               self.abortLoading = False
-               self.loadThread = threading.Thread(target=self.doFileLoadThread)
-               self.loadThread.daemon = True
-               self.loadThread.start()
-               
-               if showWarning:
-                       if (self.matrix - numpy.matrix([[1,0,0],[0,1,0],[0,0,1]], numpy.float64)).any() or len(profile.getPluginConfig()) > 0:
-                               self.ShowWarningPopup('Reset scale, rotation, mirror and plugins?', self.OnResetAll)
-       
-       def OnCheckReloadFile(self, e):
-               #Only show the reload popup when the window has focus, because the popup goes over other programs.
-               if self.GetParent().FindFocus() is None:
-                       return
-               for obj in self.objectList:
-                       if obj.filename is not None and os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime:
-                               self.checkReloadFileTimer.Stop()
-                               self.ShowWarningPopup('File changed, reload?', self.reloadModelFiles)
-               if wx.TheClipboard.Open():
-                       data = wx.TextDataObject()
-                       if wx.TheClipboard.GetData(data):
-                               data = data.GetText()
-                               if re.match('^http://.*/.*$', data):
-                                       if data.endswith(tuple(meshLoader.loadSupportedExtensions())):
-                                               #Got an url on the clipboard with a model file.
-                                               pass
-                       wx.TheClipboard.Close()
-       
-       def reloadModelFiles(self, filelist = None):
-               if filelist is not None:
-                       #Only load this again if the filename matches the file we have already loaded (for auto loading GCode after slicing)
-                       for idx in xrange(0, len(filelist)):
-                               if self.objectList[idx].filename != filelist[idx]:
-                                       return False
-               else:
-                       filelist = []
-                       for idx in xrange(0, len(self.objectList)):
-                               filelist.append(self.objectList[idx].filename)
-               self.loadModelFiles(filelist)
-               return True
-       
-       def doFileLoadThread(self):
-               for obj in self.objectList:
-                       if obj.filename is not None and os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime:
-                               obj.fileTime = os.stat(obj.filename).st_mtime
-                               try:
-                                       mesh = meshLoader.loadMeshes(obj.filename)[0]
-                               except:
-                                       traceback.print_exc(file=sys.stdout)
-                                       wx.CallAfter(self.ShowWarningPopup, 'Failed to load %s' % (obj.filename))
-                                       obj.mesh = None
-                                       obj.filename = None
-                               else:
-                                       obj.mesh = mesh
-                               obj.dirty = True
-                               obj.steepDirty = True
-                               self.updateModelTransform()
-                               if self.objectsBoundaryCircleSize is not None:
-                                       self.glCanvas.zoom = self.objectsBoundaryCircleSize * 6.0
-                               self.errorList = []
-                               wx.CallAfter(self.updateToolbar)
-                               wx.CallAfter(self.glCanvas.Refresh)
-                       elif obj.filename is None or not os.path.isfile(obj.filename):
-                               obj.mesh = None
-                               obj.filename = None
-
-               if os.path.isfile(self.gcodeFilename) and self.gcodeFileTime != os.stat(self.gcodeFilename).st_mtime:
-                       self.gcodeFileTime = os.stat(self.gcodeFilename).st_mtime
-                       self.gcodeDirty = True
-                       self.gcode = gcodeInterpreter.gcode()
-                       self.gcode.progressCallback = self.loadProgress
-                       self.gcode.load(self.gcodeFilename)
-
-                       errorList = []
-                       for line in open(self.gcodeFilename, "rt"):
-                               res = re.search(';Model error\(([a-z ]*)\): \(([0-9\.\-e]*), ([0-9\.\-e]*), ([0-9\.\-e]*)\) \(([0-9\.\-e]*), ([0-9\.\-e]*), ([0-9\.\-e]*)\)', line)
-                               if res is not None:
-                                       v1 = util3d.Vector3(float(res.group(2)), float(res.group(3)), float(res.group(4)))
-                                       v2 = util3d.Vector3(float(res.group(5)), float(res.group(6)), float(res.group(7)))
-                                       errorList.append([v1, v2])
-                       self.errorList = errorList
-
-                       wx.CallAfter(self.updateToolbar)
-                       wx.CallAfter(self.glCanvas.Refresh)
-               elif not os.path.isfile(self.gcodeFilename):
-                       self.gcode = None
-               wx.CallAfter(self.checkReloadFileTimer.Start, 1000)
-       
-       def loadProgress(self, progress):
-               if self.gcode is None:
-                       return True
-               if self.layerSelect.getValue() == self.layerSelect.getMaxValue():
-                       self.layerSelect.setRange(1, len(self.gcode.layerList) - 1)
-                       self.layerSelect.setValue(self.layerSelect.getMaxValue())
-               else:
-                       self.layerSelect.setRange(1, len(self.gcode.layerList) - 1)
-               return self.abortLoading
-
-       def OnResetAll(self, e = None):
-               profile.putProfileSetting('model_matrix', '1,0,0,0,1,0,0,0,1')
-               profile.setPluginConfig([])
-               self.updateProfileToControls()
-
-       def ShowWarningPopup(self, text, callback = None):
-               self.warningPopup.text.SetLabel(text)
-               self.warningPopup.callback = callback
-               if callback is None:
-                       self.warningPopup.yesButton.Show(False)
-                       self.warningPopup.noButton.SetLabel('ok')
-               else:
-                       self.warningPopup.yesButton.Show(True)
-                       self.warningPopup.noButton.SetLabel('no')
-               self.warningPopup.Fit()
-               self.warningPopup.Layout()
-               self.OnMove()
-               self.warningPopup.Show(True)
-               self.warningPopup.timer.Start(5000)
-       
-       def OnWarningPopup(self, e):
-               self.warningPopup.Show(False)
-               self.warningPopup.timer.Stop()
-               self.warningPopup.callback()
-
-       def OnHideWarning(self, e):
-               self.warningPopup.Show(False)
-               self.warningPopup.timer.Stop()
-
-       def updateToolbar(self):
-               self.sliceButton.setDisabled(len(self.objectList) < 1 or self.objectList[0].mesh is None)
-               self.printButton.setDisabled(self.gcode is None)
-               self.rotateToolButton.setHidden(self.glCanvas.viewMode == "GCode")
-               self.scaleToolButton.setHidden(self.glCanvas.viewMode == "GCode")
-               self.mirrorToolButton.setHidden(self.glCanvas.viewMode == "GCode")
-               if self.gcode is not None:
-                       self.layerSelect.setRange(1, len(self.gcode.layerList) - 1)
-               self.Update()
-       
-       def OnViewChange(self):
-               selection = self.viewSelection.getValue()
-               self.glCanvas.drawSteepOverhang = False
-               self.glCanvas.drawBorders = False
-               if selection == 0:
-                       self.glCanvas.viewMode = "Normal"
-               elif selection == 1:
-                       self.glCanvas.viewMode = "Transparent"
-               elif selection == 2:
-                       self.glCanvas.viewMode = "X-Ray"
-               elif selection == 3:
-                       self.glCanvas.viewMode = "Normal"
-                       self.glCanvas.drawSteepOverhang = True
-               elif selection == 4:
-                       self.layerSelect.setValue(self.layerSelect.getMaxValue())
-                       self.glCanvas.viewMode = "GCode"
-               elif selection == 5:
-                       self.glCanvas.viewMode = "Mixed"
-               self.layerSelect.setHidden(self.glCanvas.viewMode != "GCode")
-               self.updateToolbar()
-               self.deselectTool()
-               self.glCanvas.Refresh()
-
-       def deselectTool(self):
-               self.rotateToolButton.setSelected(False)
-               self.scaleToolButton.setSelected(False)
-               self.mirrorToolButton.setSelected(False)
-               self.OnToolSelect()
-
-       def updateModelTransform(self, f=0):
-               if len(self.objectList) < 1 or self.objectList[0].mesh is None:
-                       return
-
-               profile.putProfileSetting('model_matrix', ','.join(map(str, list(self.matrix.getA().flatten()))))
-               for obj in self.objectList:
-                       if obj.mesh is None:
-                               continue
-                       obj.mesh.matrix = self.matrix
-                       obj.mesh.processMatrix()
-
-               minV = self.objectList[0].mesh.getMinimum()
-               maxV = self.objectList[0].mesh.getMaximum()
-               objectsBoundaryCircleSize = self.objectList[0].mesh.getBoundaryCircle()
-               for obj in self.objectList:
-                       if obj.mesh is None:
-                               continue
-
-                       minV = numpy.minimum(minV, obj.mesh.getMinimum())
-                       maxV = numpy.maximum(maxV, obj.mesh.getMaximum())
-                       objectsBoundaryCircleSize = max(objectsBoundaryCircleSize, obj.mesh.getBoundaryCircle())
-
-               self.objectsMaxV = maxV
-               self.objectsMinV = minV
-               self.objectsSize = self.objectsMaxV - self.objectsMinV
-               self.objectsBoundaryCircleSize = objectsBoundaryCircleSize
-
-               scaleX = numpy.linalg.norm(self.matrix[::,0].getA().flatten())
-               scaleY = numpy.linalg.norm(self.matrix[::,1].getA().flatten())
-               scaleZ = numpy.linalg.norm(self.matrix[::,2].getA().flatten())
-               self.scaleXctrl.setValue(round(scaleX, 2))
-               self.scaleYctrl.setValue(round(scaleY, 2))
-               self.scaleZctrl.setValue(round(scaleZ, 2))
-               self.scaleXmmctrl.setValue(round(self.objectsSize[0], 2))
-               self.scaleYmmctrl.setValue(round(self.objectsSize[1], 2))
-               self.scaleZmmctrl.setValue(round(self.objectsSize[2], 2))
-
-               self.glCanvas.Refresh()
-       
-       def updateProfileToControls(self):
-               self.matrix = numpy.matrix(numpy.array(profile.getObjectMatrix(), numpy.float64).reshape((3,3,)))
-               self.updateModelTransform()
-               for obj in self.objectList:
-                       obj.steepDirty = True
-               self.glCanvas.updateProfileToControls()
-
-class PreviewGLCanvas(openglGui.glGuiPanel):
-       def __init__(self, parent):
-               super(PreviewGLCanvas, self).__init__(parent)
-               wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
-               self.parent = parent
-               self.yaw = 30
-               self.pitch = 60
-               self.zoom = 300
-               self.viewTarget = [parent.machineCenter.x, parent.machineCenter.y, 0.0]
-               self.view3D = True
-               self.gcodeDisplayList = []
-               self.gcodeQuickDisplayList = []
-               self.gcodeDisplayListMade = 0
-               self.gcodeQuickDisplayListMade = 0
-               self.objColor = [[1.0, 0.8, 0.6, 1.0], [0.2, 1.0, 0.1, 1.0], [1.0, 0.2, 0.1, 1.0], [0.1, 0.2, 1.0, 1.0]]
-               self.oldX = 0
-               self.oldY = 0
-               self.dragType = ''
-               self.tempMatrix = None
-               self.viewport = None
-
-       def updateProfileToControls(self):
-               self.objColor[0] = profile.getPreferenceColour('model_colour')
-               self.objColor[1] = profile.getPreferenceColour('model_colour2')
-               self.objColor[2] = profile.getPreferenceColour('model_colour3')
-               self.objColor[3] = profile.getPreferenceColour('model_colour4')
-
-       def OnMouseMotion(self,e):
-               if self.parent.objectsMaxV is not None and self.viewport is not None and self.viewMode != 'GCode' and self.viewMode != 'Mixed':
-                       p0 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 0, self.modelMatrix, self.projMatrix, self.viewport)
-                       p1 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 1, self.modelMatrix, self.projMatrix, self.viewport)
-                       p0 -= self.viewTarget
-                       p1 -= self.viewTarget
-                       if not e.Dragging() or self.dragType != 'tool':
-                               self.parent.tool.OnMouseMove(p0, p1)
-               else:
-                       p0 = [0,0,0]
-                       p1 = [1,0,0]
-
-               if e.Dragging() and e.LeftIsDown():
-                       if self.dragType == '':
-                               #Define the drag type depending on the cursor position.
-                               self.dragType = 'viewRotate'
-                               if self.viewMode != 'GCode' and self.viewMode != 'Mixed':
-                                       if self.parent.tool.OnDragStart(p0, p1):
-                                               self.dragType = 'tool'
-
-                       if self.dragType == 'viewRotate':
-                               if self.view3D:
-                                       self.yaw += e.GetX() - self.oldX
-                                       self.pitch -= e.GetY() - self.oldY
-                                       if self.pitch > 170:
-                                               self.pitch = 170
-                                       if self.pitch < 10:
-                                               self.pitch = 10
-                               else:
-                                       self.viewTarget[0] -= float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2
-                                       self.viewTarget[1] += float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2
-                       elif self.dragType == 'tool':
-                               self.parent.tool.OnDrag(p0, p1)
-
-                       #Workaround for buggy ATI cards.
-                       size = self.GetSizeTuple()
-                       self.SetSize((size[0]+1, size[1]))
-                       self.SetSize((size[0], size[1]))
-                       self.Refresh()
-               else:
-                       if self.dragType != '':
-                               if self.tempMatrix is not None:
-                                       self.parent.matrix *= self.tempMatrix
-                                       self.parent.updateModelTransform()
-                                       self.tempMatrix = None
-                                       for obj in self.parent.objectList:
-                                               obj.steepDirty = True
-                               self.parent.tool.OnDragEnd()
-                               self.dragType = ''
-               if e.Dragging() and e.RightIsDown():
-                       self.zoom += e.GetY() - self.oldY
-                       if self.zoom < 1:
-                               self.zoom = 1
-                       if self.zoom > 500:
-                               self.zoom = 500
-               self.oldX = e.GetX()
-               self.oldY = e.GetY()
-
-       def getObjectBoundaryCircle(self):
-               return self.parent.objectsBoundaryCircleSize
-
-       def getObjectSize(self):
-               return self.parent.objectsSize
-
-       def getObjectMatrix(self):
-               return self.parent.matrix
-
-       def getObjectCenterPos(self):
-               return [self.parent.machineCenter.x, self.parent.machineCenter.y, self.parent.objectsSize[2] / 2 - profile.getProfileSettingFloat('object_sink')]
-
-       def OnMouseWheel(self,e):
-               self.zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
-               if self.zoom < 1.0:
-                       self.zoom = 1.0
-               if self.zoom > 500:
-                       self.zoom = 500
-               self.Refresh()
-
-       def OnKeyChar(self, keycode):
-               if keycode == wx.WXK_UP:
-                       self.parent.layerSelect.setValue(self.parent.layerSelect.getValue() + 1)
-                       self.Refresh()
-               elif keycode == wx.WXK_DOWN:
-                       self.parent.layerSelect.setValue(self.parent.layerSelect.getValue() - 1)
-                       self.Refresh()
-               elif keycode == wx.WXK_PAGEUP:
-                       self.parent.layerSelect.setValue(self.parent.layerSelect.getValue() + 10)
-                       self.Refresh()
-               elif keycode == wx.WXK_PAGEDOWN:
-                       self.parent.layerSelect.setValue(self.parent.layerSelect.getValue() - 10)
-                       self.Refresh()
-
-       def OnPaint(self,e):
-               opengl.InitGL(self, self.view3D, self.zoom)
-               if self.view3D:
-                       glTranslate(0,0,-self.zoom)
-                       glTranslate(self.zoom/20.0,0,0)
-                       glRotate(-self.pitch, 1,0,0)
-                       glRotate(self.yaw, 0,0,1)
-
-                       if self.viewMode == "GCode" or self.viewMode == "Mixed":
-                               n = min(self.gcodeQuickDisplayListMade, self.parent.layerSelect.getValue())
-                               if self.parent.gcode is not None and -1 < n < len(self.parent.gcode.layerList) and len(self.parent.gcode.layerList[n]) > 0:
-                                       self.viewTarget[2] = self.parent.gcode.layerList[n][0].list[-1].z
-                       else:
-                               if self.parent.objectsMaxV is not None:
-                                       self.viewTarget = self.getObjectCenterPos()
-               glTranslate(-self.viewTarget[0], -self.viewTarget[1], -self.viewTarget[2])
-
-               self.viewport = glGetIntegerv(GL_VIEWPORT)
-               self.modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
-               self.projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
-
-               self.OnDraw()
-
-               if len(self.parent.objectList) > 0 and self.parent.objectList[0].mesh is None and self.parent.objectList[0].filename is not None:
-                       glDisable(GL_DEPTH_TEST)
-                       glLoadIdentity()
-                       glColor3ub(255,255,255)
-                       glTranslate(0, -3, -10)
-                       opengl.glDrawStringCenter('Loading %s ...' % (os.path.basename(self.parent.objectList[0].filename)))
-
-       def OnDraw(self):
-               machineSize = self.parent.machineSize
-
-               if self.parent.gcode is not None and (self.viewMode == "GCode" or self.viewMode == "Mixed"):
-                       if self.parent.gcodeDirty:
-                               self.parent.gcodeDirty = False
-                               self.gcodeDisplayListMade = 0
-                               self.gcodeQuickDisplayListMade = 0
-
-                       if self.gcodeDisplayListMade < len(self.parent.gcode.layerList):
-                               gcodeGenStartTime = time.time()
-                               while time.time() - gcodeGenStartTime < 0.1 and self.gcodeQuickDisplayListMade < len(self.parent.gcode.layerList):
-                                       if len(self.gcodeQuickDisplayList) == self.gcodeQuickDisplayListMade:
-                                               self.gcodeQuickDisplayList.append(glGenLists(1))
-                                       glNewList(self.gcodeQuickDisplayList[self.gcodeQuickDisplayListMade], GL_COMPILE)
-                                       opengl.DrawGCodeLayer(self.parent.gcode.layerList[self.gcodeQuickDisplayListMade], True)
-                                       glEndList()
-                                       self.gcodeQuickDisplayListMade += 1
-                               while time.time() - gcodeGenStartTime < 0.1 and self.gcodeDisplayListMade < len(self.parent.gcode.layerList):
-                                       if len(self.gcodeDisplayList) == self.gcodeDisplayListMade:
-                                               self.gcodeDisplayList.append(glGenLists(1))
-                                       glNewList(self.gcodeDisplayList[self.gcodeDisplayListMade], GL_COMPILE)
-                                       opengl.DrawGCodeLayer(self.parent.gcode.layerList[self.gcodeDisplayListMade], False)
-                                       glEndList()
-                                       self.gcodeDisplayListMade += 1
-                               wx.CallAfter(self.Refresh)
-               
-               glPushMatrix()
-               glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, -profile.getProfileSettingFloat('object_sink'))
-               for obj in self.parent.objectList:
-                       if obj.mesh is None:
-                               continue
-                       if obj.displayList is None:
-                               obj.displayList = glGenLists(1)
-                               obj.steepDisplayList = glGenLists(1)
-                               obj.outlineDisplayList = glGenLists(1)
-                       if obj.dirty:
-                               obj.dirty = False
-                               glNewList(obj.displayList, GL_COMPILE)
-                               opengl.DrawMesh(obj.mesh, numpy.linalg.det(obj.mesh.matrix) < 0)
-                               glEndList()
-                               glNewList(obj.outlineDisplayList, GL_COMPILE)
-                               opengl.DrawMeshOutline(obj.mesh)
-                               glEndList()
-
-                       if self.viewMode == "Mixed":
-                               glDisable(GL_BLEND)
-                               glColor3f(0.0,0.0,0.0)
-                               self.drawModel(obj.displayList)
-                               glColor3f(1.0,1.0,1.0)
-                               glClear(GL_DEPTH_BUFFER_BIT)
-               
-               glPopMatrix()
-               
-               if self.parent.gcode is not None and (self.viewMode == "GCode" or self.viewMode == "Mixed"):
-                       glPushMatrix()
-                       if profile.getPreference('machine_center_is_zero') == 'True':
-                               glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, 0)
-                       glEnable(GL_COLOR_MATERIAL)
-                       glEnable(GL_LIGHTING)
-                       drawQuickUpToLayer = min(self.gcodeQuickDisplayListMade, self.parent.layerSelect.getValue() + 1)
-                       drawUpToLayer = min(self.gcodeDisplayListMade, self.parent.layerSelect.getValue() + 1)
-
-                       for i in xrange(drawQuickUpToLayer - 1, -1, -1):
-                               c = 1.0
-                               if i < self.parent.layerSelect.getValue():
-                                       c = 0.9 - (drawQuickUpToLayer - i) * 0.1
-                                       if c < 0.4:
-                                               c = (0.4 + c) / 2
-                                       if c < 0.1:
-                                               c = 0.1
-                               glLightfv(GL_LIGHT0, GL_DIFFUSE, [0,0,0,0])
-                               glLightfv(GL_LIGHT0, GL_AMBIENT, [c,c,c,c])
-                               if self.gcodeDisplayListMade > i and drawUpToLayer - i < 15:
-                                       glCallList(self.gcodeDisplayList[i])
-                               else:
-                                       glCallList(self.gcodeQuickDisplayList[i])
-
-                       glDisable(GL_LIGHTING)
-                       glDisable(GL_COLOR_MATERIAL)
-                       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]);
-                       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0]);
-                       glPopMatrix()
-
-               glColor3f(1.0,1.0,1.0)
-               glPushMatrix()
-               glTranslate(self.parent.machineCenter.x, self.parent.machineCenter.y, -profile.getProfileSettingFloat('object_sink'))
-               for obj in self.parent.objectList:
-                       if obj.mesh is None:
-                               continue
-
-                       if self.viewMode == "Transparent" or self.viewMode == "Mixed":
-                               glLightfv(GL_LIGHT0, GL_DIFFUSE, map(lambda x: x / 2, self.objColor[self.parent.objectList.index(obj)]))
-                               glLightfv(GL_LIGHT0, GL_AMBIENT, map(lambda x: x / 10, self.objColor[self.parent.objectList.index(obj)]))
-                               #If we want transparent, then first render a solid black model to remove the printer size lines.
-                               if self.viewMode != "Mixed":
-                                       glDisable(GL_BLEND)
-                                       glColor3f(0.0,0.0,0.0)
-                                       self.drawModel(obj.displayList)
-                                       glColor3f(1.0,1.0,1.0)
-                               #After the black model is rendered, render the model again but now with lighting and no depth testing.
-                               glDisable(GL_DEPTH_TEST)
-                               glEnable(GL_LIGHTING)
-                               glEnable(GL_BLEND)
-                               glBlendFunc(GL_ONE, GL_ONE)
-                               glEnable(GL_LIGHTING)
-                               self.drawModel(obj.displayList)
-                               glEnable(GL_DEPTH_TEST)
-                       elif self.viewMode == "X-Ray":
-                               glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
-                               glDisable(GL_LIGHTING)
-                               glDisable(GL_DEPTH_TEST)
-                               glEnable(GL_STENCIL_TEST)
-                               glStencilFunc(GL_ALWAYS, 1, 1)
-                               glStencilOp(GL_INCR, GL_INCR, GL_INCR)
-                               self.drawModel(obj.displayList)
-                               glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP)
-                               
-                               glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
-                               glStencilFunc(GL_EQUAL, 0, 1)
-                               glColor(1, 1, 1)
-                               self.drawModel(obj.displayList)
-                               glStencilFunc(GL_EQUAL, 1, 1)
-                               glColor(1, 0, 0)
-                               self.drawModel(obj.displayList)
-
-                               glPushMatrix()
-                               glLoadIdentity()
-                               for i in xrange(2, 15, 2):
-                                       glStencilFunc(GL_EQUAL, i, 0xFF);
-                                       glColor(float(i)/10, float(i)/10, float(i)/5)
-                                       glBegin(GL_QUADS)
-                                       glVertex3f(-1000,-1000,-1)
-                                       glVertex3f( 1000,-1000,-1)
-                                       glVertex3f( 1000, 1000,-1)
-                                       glVertex3f(-1000, 1000,-1)
-                                       glEnd()
-                               for i in xrange(1, 15, 2):
-                                       glStencilFunc(GL_EQUAL, i, 0xFF);
-                                       glColor(float(i)/10, 0, 0)
-                                       glBegin(GL_QUADS)
-                                       glVertex3f(-1000,-1000,-1)
-                                       glVertex3f( 1000,-1000,-1)
-                                       glVertex3f( 1000, 1000,-1)
-                                       glVertex3f(-1000, 1000,-1)
-                                       glEnd()
-                               glPopMatrix()
-
-                               glDisable(GL_STENCIL_TEST)
-                               glEnable(GL_DEPTH_TEST)
-                               
-                               #Fix the depth buffer
-                               glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
-                               self.drawModel(obj.displayList)
-                               glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
-                       elif self.viewMode == "Normal":
-                               glLightfv(GL_LIGHT0, GL_DIFFUSE, self.objColor[self.parent.objectList.index(obj)])
-                               glLightfv(GL_LIGHT0, GL_AMBIENT, map(lambda x: x * 0.4, self.objColor[self.parent.objectList.index(obj)]))
-                               glEnable(GL_LIGHTING)
-                               self.drawModel(obj.displayList)
-
-                       if self.drawBorders and (self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray"):
-                               glEnable(GL_DEPTH_TEST)
-                               glDisable(GL_LIGHTING)
-                               glColor3f(1,1,1)
-                               self.drawModel(obj.outlineDisplayList)
-
-                       if self.drawSteepOverhang:
-                               if obj.steepDirty:
-                                       obj.steepDirty = False
-                                       glNewList(obj.steepDisplayList, GL_COMPILE)
-                                       opengl.DrawMeshSteep(obj.mesh, self.parent.matrix, 60)
-                                       glEndList()
-                               glDisable(GL_LIGHTING)
-                               glColor3f(1,1,1)
-                               self.drawModel(obj.steepDisplayList)
-
-               glPopMatrix()   
-               #if self.viewMode == "Normal" or self.viewMode == "Transparent" or self.viewMode == "X-Ray":
-               #       glDisable(GL_LIGHTING)
-               #       glDisable(GL_DEPTH_TEST)
-               #       glDisable(GL_BLEND)
-               #       glColor3f(1,0,0)
-               #       glBegin(GL_LINES)
-               #       for err in self.parent.errorList:
-               #               glVertex3f(err[0].x, err[0].y, err[0].z)
-               #               glVertex3f(err[1].x, err[1].y, err[1].z)
-               #       glEnd()
-               #       glEnable(GL_DEPTH_TEST)
-
-               opengl.DrawMachine(machineSize)
-
-               #Draw the current selected tool
-               if self.parent.objectsMaxV is not None and self.viewMode != 'GCode' and self.viewMode != 'Mixed':
-                       glPushMatrix()
-                       pos = self.getObjectCenterPos()
-                       glTranslate(pos[0], pos[1], pos[2])
-                       self.parent.tool.OnDraw()
-                       glPopMatrix()
-
-       def drawModel(self, displayList):
-               vMin = self.parent.objectsMinV
-               vMax = self.parent.objectsMaxV
-               if vMin is None:
-                       return
-               offset = - vMin - (vMax - vMin) / 2
-
-               matrix = opengl.convert3x3MatrixTo4x4(self.parent.matrix)
-
-               glPushMatrix()
-               glTranslate(0, 0, self.parent.objectsSize[2]/2)
-               if self.tempMatrix is not None:
-                       tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
-                       glMultMatrixf(tempMatrix)
-               glTranslate(0, 0, -self.parent.objectsSize[2]/2)
-               glTranslate(offset[0], offset[1], -vMin[2])
-               glMultMatrixf(matrix)
-               glCallList(displayList)
-               glPopMatrix()
diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py
deleted file mode 100644 (file)
index 626e006..0000000
+++ /dev/null
@@ -1,1159 +0,0 @@
-from __future__ import absolute_import
-
-import wx
-import os
-import threading
-import time
-import re
-import shutil
-import ConfigParser
-import numpy
-import math
-
-import OpenGL
-OpenGL.ERROR_CHECKING = False
-from OpenGL.GLU import *
-from OpenGL.GL import *
-
-from Cura.gui.util import opengl
-from Cura.gui.util import toolbarUtil
-from Cura.gui import configBase
-from Cura.gui import printWindow
-from Cura.gui.util import dropTarget
-from Cura.gui.util import taskbar
-from Cura.gui.util import previewTools
-from Cura.gui.util import openglGui
-from Cura.util import validators
-from Cura.util import profile
-from Cura.util import util3d
-from Cura.util import meshLoader
-from Cura.util.meshLoaders import stl
-from Cura.util import mesh
-from Cura.util import sliceRun
-from Cura.util import gcodeInterpreter
-from Cura.util import explorer
-
-class Action(object):
-       pass
-
-class ProjectObject(object):
-       def __init__(self, parent, filename):
-               super(ProjectObject, self).__init__()
-
-               self.mesh = meshLoader.loadMesh(filename)
-
-               self.parent = parent
-               self.filename = filename
-               self.matrix = numpy.matrix([[1,0,0],[0,1,0],[0,0,1]], numpy.float64)
-               self.profile = None
-
-               self.modelDisplayList = None
-               self.modelDirty = True
-
-               self.centerX = self.getSize()[0]/2 + 5
-               self.centerY = self.getSize()[1]/2 + 5
-
-               self.updateMatrix()
-
-       def isSameExceptForPosition(self, other):
-               if self.filename != other.filename:
-                       return False
-               if self.matrix != other.matrix:
-                       return False
-               if self.profile != other.profile:
-                       return False
-               return True
-
-       def updateMatrix(self):
-               self.mesh.matrix = self.matrix
-               self.mesh.processMatrix()
-
-               scaleX = numpy.linalg.norm(self.matrix[::,0].getA().flatten())
-               scaleY = numpy.linalg.norm(self.matrix[::,1].getA().flatten())
-               scaleZ = numpy.linalg.norm(self.matrix[::,2].getA().flatten())
-               self.parent.scaleXctrl.setValue(round(scaleX, 2))
-               self.parent.scaleYctrl.setValue(round(scaleY, 2))
-               self.parent.scaleZctrl.setValue(round(scaleZ, 2))
-               self.parent.scaleXmmctrl.setValue(round(self.getSize()[0], 2))
-               self.parent.scaleYmmctrl.setValue(round(self.getSize()[1], 2))
-               self.parent.scaleZmmctrl.setValue(round(self.getSize()[2], 2))
-
-       def getMinimum(self):
-               return self.mesh.getMinimum()
-       def getMaximum(self):
-               return self.mesh.getMaximum()
-       def getSize(self):
-               return self.mesh.getSize()
-       def getBoundaryCircle(self):
-               return self.mesh.boundaryCircleSize
-
-       def clone(self):
-               p = ProjectObject(self.parent, self.filename)
-
-               p.centerX = self.centerX + 5
-               p.centerY = self.centerY + 5
-
-               p.filename = self.filename
-               p.matrix = self.matrix.copy()
-               p.profile = self.profile
-
-               p.updateMatrix()
-
-               return p
-
-       def clampXY(self):
-               size = self.getSize()
-               if self.centerX < size[0] / 2:
-                       self.centerX = size[0] / 2
-               if self.centerY < size[1] / 2:
-                       self.centerY = size[1] / 2
-               if self.centerX > self.parent.machineSize[0] - size[0] / 2:
-                       self.centerX = self.parent.machineSize[0] - size[0] / 2
-               if self.centerY > self.parent.machineSize[1] - size[1] / 2:
-                       self.centerY = self.parent.machineSize[1] - size[1] / 2
-
-class projectPlanner(wx.Frame):
-       "Main user interface window"
-       def __init__(self):
-               super(projectPlanner, self).__init__(None, title='Cura - Project Planner')
-
-               wx.EVT_CLOSE(self, self.OnClose)
-               self.panel = wx.Panel(self, -1)
-               self.SetSizer(wx.BoxSizer(wx.VERTICAL))
-               self.GetSizer().Add(self.panel, 1, flag=wx.EXPAND)
-
-               self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.loadSupportedExtensions()))
-
-               self.list = []
-               self.selection = None
-               self.printMode = 0
-               self.alwaysAutoPlace = profile.getPreference('planner_always_autoplace') == 'True'
-
-               self.machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
-               self.headSizeMin = numpy.array([profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0])
-               self.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
-
-               self.extruderOffset = [
-                       numpy.array([0,0,0]),
-                       numpy.array([profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0]),
-                       numpy.array([profile.getPreferenceFloat('extruder_offset_x2'), profile.getPreferenceFloat('extruder_offset_y2'), 0]),
-                       numpy.array([profile.getPreferenceFloat('extruder_offset_x3'), profile.getPreferenceFloat('extruder_offset_y3'), 0])]
-
-               self.toolbar = toolbarUtil.Toolbar(self.panel)
-
-               toolbarUtil.NormalButton(self.toolbar, self.OnLoadProject, 'open.png', 'Open project')
-               toolbarUtil.NormalButton(self.toolbar, self.OnSaveProject, 'save.png', 'Save project')
-               self.toolbar.AddSeparator()
-               group = []
-               toolbarUtil.RadioButton(self.toolbar, group, 'object-3d-on.png', 'object-3d-off.png', '3D view', callback=self.On3DClick).SetValue(self.alwaysAutoPlace)
-               toolbarUtil.RadioButton(self.toolbar, group, 'object-top-on.png', 'object-top-off.png', 'Topdown view', callback=self.OnTopClick).SetValue(not self.alwaysAutoPlace)
-               self.toolbar.AddSeparator()
-               toolbarUtil.NormalButton(self.toolbar, self.OnPreferences, 'preferences.png', 'Project planner preferences')
-               self.toolbar.AddSeparator()
-               toolbarUtil.NormalButton(self.toolbar, self.OnCutMesh, 'cut-mesh.png', 'Cut a plate STL into multiple STL files, and add those files to the project.\nNote: Splitting up plates sometimes takes a few minutes.')
-               toolbarUtil.NormalButton(self.toolbar, self.OnSaveCombinedSTL, 'save-combination.png', 'Save all the combined STL files into a single STL file as a plate.')
-               self.toolbar.AddSeparator()
-               group = []
-               self.printOneAtATime = toolbarUtil.RadioButton(self.toolbar, group, 'view-normal-on.png', 'view-normal-off.png', 'Print one object at a time', callback=self.OnPrintTypeChange)
-               self.printAllAtOnce = toolbarUtil.RadioButton(self.toolbar, group, 'all-at-once-on.png', 'all-at-once-off.png', 'Print all the objects at once', callback=self.OnPrintTypeChange)
-               self.toolbar.AddSeparator()
-               toolbarUtil.NormalButton(self.toolbar, self.OnQuit, 'exit.png', 'Close project planner')
-
-               self.toolbar.Realize()
-
-               self.toolbar2 = toolbarUtil.Toolbar(self.panel)
-
-               toolbarUtil.NormalButton(self.toolbar2, self.OnAddModel, 'object-add.png', 'Add model')
-               toolbarUtil.NormalButton(self.toolbar2, self.OnRemModel, 'object-remove.png', 'Remove model')
-               self.toolbar2.AddSeparator()
-               toolbarUtil.NormalButton(self.toolbar2, self.OnMoveUp, 'move-up.png', 'Move model up in print list')
-               toolbarUtil.NormalButton(self.toolbar2, self.OnMoveDown, 'move-down.png', 'Move model down in print list')
-               toolbarUtil.NormalButton(self.toolbar2, self.OnCopy, 'copy.png', 'Make a copy of the current selected object')
-               toolbarUtil.NormalButton(self.toolbar2, self.OnSetCustomProfile, 'set-profile.png', 'Set a custom profile to be used to prepare a specific object.')
-               self.toolbar2.AddSeparator()
-               if not self.alwaysAutoPlace:
-                       toolbarUtil.NormalButton(self.toolbar2, self.OnAutoPlace, 'autoplace.png', 'Automaticly organize the objects on the platform.')
-               toolbarUtil.NormalButton(self.toolbar2, self.OnSlice, 'slice.png', 'Prepare to project into a gcode file.')
-               self.toolbar2.Realize()
-
-               sizer = wx.GridBagSizer(2,2)
-               self.panel.SetSizer(sizer)
-               self.glCanvas = PreviewGLCanvas(self.panel, self)
-               self.listbox = wx.ListBox(self.panel, -1, choices=[])
-               self.addButton = wx.Button(self.panel, -1, "Add")
-               self.remButton = wx.Button(self.panel, -1, "Remove")
-               self.sliceButton = wx.Button(self.panel, -1, "Prepare")
-               if not self.alwaysAutoPlace:
-                       self.autoPlaceButton = wx.Button(self.panel, -1, "Auto Place")
-
-               sizer.Add(self.toolbar, (0,0), span=(1,1), flag=wx.EXPAND|wx.LEFT|wx.RIGHT)
-               sizer.Add(self.toolbar2, (0,1), span=(1,2), flag=wx.EXPAND|wx.LEFT|wx.RIGHT)
-               sizer.Add(self.glCanvas, (1,0), span=(5,1), flag=wx.EXPAND)
-               sizer.Add(self.listbox, (1,1), span=(1,2), flag=wx.EXPAND)
-               sizer.Add(self.addButton, (2,1), span=(1,1))
-               sizer.Add(self.remButton, (2,2), span=(1,1))
-               sizer.Add(self.sliceButton, (3,1), span=(1,1))
-               if not self.alwaysAutoPlace:
-                       sizer.Add(self.autoPlaceButton, (3,2), span=(1,1))
-               sizer.AddGrowableCol(0)
-               sizer.AddGrowableRow(1)
-
-               self.addButton.Bind(wx.EVT_BUTTON, self.OnAddModel)
-               self.remButton.Bind(wx.EVT_BUTTON, self.OnRemModel)
-               self.sliceButton.Bind(wx.EVT_BUTTON, self.OnSlice)
-               if not self.alwaysAutoPlace:
-                       self.autoPlaceButton.Bind(wx.EVT_BUTTON, self.OnAutoPlace)
-               self.listbox.Bind(wx.EVT_LISTBOX, self.OnListSelect)
-
-               panel = wx.Panel(self.panel, -1)
-               sizer.Add(panel, (5,1), span=(1,2))
-
-               sizer = wx.GridBagSizer(2,2)
-               panel.SetSizer(sizer)
-
-               group = []
-               self.rotateToolButton = openglGui.glRadioButton(self.glCanvas, 8, 'Rotate', (0,-1), group, self.OnToolSelect)
-               self.scaleToolButton  = openglGui.glRadioButton(self.glCanvas, 9, 'Scale', (1,-1), group, self.OnToolSelect)
-               self.mirrorToolButton  = openglGui.glRadioButton(self.glCanvas, 10, 'Mirror', (2,-1), group, self.OnToolSelect)
-
-               self.resetRotationButton = openglGui.glButton(self.glCanvas, 12, 'Reset', (0,-2), self.OnRotateReset)
-               self.layFlatButton       = openglGui.glButton(self.glCanvas, 16, 'Lay flat', (0,-3), self.OnLayFlat)
-
-               self.resetScaleButton    = openglGui.glButton(self.glCanvas, 13, 'Reset', (1,-2), self.OnScaleReset)
-
-               self.mirrorXButton       = openglGui.glButton(self.glCanvas, 14, 'Mirror X', (2,-2), lambda : self.OnMirror(0))
-               self.mirrorYButton       = openglGui.glButton(self.glCanvas, 18, 'Mirror Y', (2,-3), lambda : self.OnMirror(1))
-               self.mirrorZButton       = openglGui.glButton(self.glCanvas, 22, 'Mirror Z', (2,-4), lambda : self.OnMirror(2))
-
-               self.scaleForm = openglGui.glFrame(self.glCanvas, (2, -2))
-               openglGui.glGuiLayoutGrid(self.scaleForm)
-               openglGui.glLabel(self.scaleForm, 'Scale X', (0,0))
-               self.scaleXctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,0), lambda value: self.OnScaleEntry(value, 0))
-               openglGui.glLabel(self.scaleForm, 'Scale Y', (0,1))
-               self.scaleYctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,1), lambda value: self.OnScaleEntry(value, 1))
-               openglGui.glLabel(self.scaleForm, 'Scale Z', (0,2))
-               self.scaleZctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,2), lambda value: self.OnScaleEntry(value, 2))
-               openglGui.glLabel(self.scaleForm, 'Size X (mm)', (0,4))
-               self.scaleXmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,4), lambda value: self.OnScaleEntryMM(value, 0))
-               openglGui.glLabel(self.scaleForm, 'Size Y (mm)', (0,5))
-               self.scaleYmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,5), lambda value: self.OnScaleEntryMM(value, 1))
-               openglGui.glLabel(self.scaleForm, 'Size Z (mm)', (0,6))
-               self.scaleZmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,6), lambda value: self.OnScaleEntryMM(value, 2))
-               openglGui.glLabel(self.scaleForm, 'Uniform scale', (0,8))
-               self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None)
-
-               self.SetSize((800,600))
-
-               self.OnToolSelect()
-
-       def OnToolSelect(self):
-               if self.rotateToolButton.getSelected():
-                       self.tool = previewTools.toolRotate(self.glCanvas)
-               elif self.scaleToolButton.getSelected():
-                       self.tool = previewTools.toolScale(self.glCanvas)
-               elif self.mirrorToolButton.getSelected():
-                       self.tool = previewTools.toolNone(self.glCanvas)
-               else:
-                       self.tool = previewTools.toolNone(self.glCanvas)
-               self.resetRotationButton.setHidden(not self.rotateToolButton.getSelected())
-               self.layFlatButton.setHidden(not self.rotateToolButton.getSelected())
-               self.resetScaleButton.setHidden(not self.scaleToolButton.getSelected())
-               self.scaleForm.setHidden(not self.scaleToolButton.getSelected())
-               self.mirrorXButton.setHidden(not self.mirrorToolButton.getSelected())
-               self.mirrorYButton.setHidden(not self.mirrorToolButton.getSelected())
-               self.mirrorZButton.setHidden(not self.mirrorToolButton.getSelected())
-               self.glCanvas.Refresh()
-
-       def OnRotateReset(self):
-               if self.selection is None:
-                       return
-               x = numpy.linalg.norm(self.selection.matrix[::,0].getA().flatten())
-               y = numpy.linalg.norm(self.selection.matrix[::,1].getA().flatten())
-               z = numpy.linalg.norm(self.selection.matrix[::,2].getA().flatten())
-               self.selection.matrix = numpy.matrix([[x,0,0],[0,y,0],[0,0,z]], numpy.float64)
-               self.selection.updateMatrix()
-
-       def OnLayFlat(self):
-               if self.selection is None:
-                       return
-               transformedVertexes = (numpy.matrix(self.selection.mesh.vertexes, copy = False) * self.selection.matrix).getA()
-               minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
-               dotMin = 1.0
-               dotV = None
-               for v in transformedVertexes:
-                       diff = v - minZvertex
-                       len = math.sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2])
-                       if len < 5:
-                               continue
-                       dot = (diff[2] / len)
-                       if dotMin > dot:
-                               dotMin = dot
-                               dotV = diff
-               if dotV is None:
-                       return
-               rad = -math.atan2(dotV[1], dotV[0])
-               self.selection.matrix *= numpy.matrix([[math.cos(rad), math.sin(rad), 0], [-math.sin(rad), math.cos(rad), 0], [0,0,1]], numpy.float64)
-               rad = -math.asin(dotMin)
-               self.selection.matrix *= numpy.matrix([[math.cos(rad), 0, math.sin(rad)], [0,1,0], [-math.sin(rad), 0, math.cos(rad)]], numpy.float64)
-
-
-               transformedVertexes = (numpy.matrix(self.selection.mesh.vertexes, copy = False) * self.selection.matrix).getA()
-               minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
-               dotMin = 1.0
-               dotV = None
-               for v in transformedVertexes:
-                       diff = v - minZvertex
-                       len = math.sqrt(diff[1] * diff[1] + diff[2] * diff[2])
-                       if len < 5:
-                               continue
-                       dot = (diff[2] / len)
-                       if dotMin > dot:
-                               dotMin = dot
-                               dotV = diff
-               if dotV is None:
-                       return
-               if dotV[1] < 0:
-                       rad = math.asin(dotMin)
-               else:
-                       rad = -math.asin(dotMin)
-               self.selection.matrix *= numpy.matrix([[1,0,0], [0, math.cos(rad), math.sin(rad)], [0, -math.sin(rad), math.cos(rad)]], numpy.float64)
-
-               self.selection.updateMatrix()
-
-       def OnScaleReset(self):
-               if self.selection is None:
-                       return
-               x = 1/numpy.linalg.norm(self.selection.matrix[::,0].getA().flatten())
-               y = 1/numpy.linalg.norm(self.selection.matrix[::,1].getA().flatten())
-               z = 1/numpy.linalg.norm(self.selection.matrix[::,2].getA().flatten())
-               self.selection.matrix *= numpy.matrix([[x,0,0],[0,y,0],[0,0,z]], numpy.float64)
-               self.selection.updateMatrix()
-
-       def OnMirror(self, axis):
-               if self.selection is None:
-                       return
-               matrix = [[1,0,0], [0, 1, 0], [0, 0, 1]]
-               matrix[axis][axis] = -1
-               self.selection.matrix *= numpy.matrix(matrix, numpy.float64)
-
-       def OnScaleEntry(self, value, axis):
-               if self.selection is None:
-                       return
-               try:
-                       value = float(value)
-               except:
-                       return
-               scale = numpy.linalg.norm(self.selection.matrix[::,axis].getA().flatten())
-               scale = value / scale
-               if scale == 0:
-                       return
-               if self.scaleUniform.getValue():
-                       matrix = [[scale,0,0], [0, scale, 0], [0, 0, scale]]
-               else:
-                       matrix = [[1.0,0,0], [0, 1.0, 0], [0, 0, 1.0]]
-                       matrix[axis][axis] = scale
-               self.selection.matrix *= numpy.matrix(matrix, numpy.float64)
-               self.selection.updateMatrix()
-
-       def OnScaleEntryMM(self, value, axis):
-               try:
-                       value = float(value)
-               except:
-                       return
-               scale = self.selection.getSize()[axis]
-               scale = value / scale
-               if scale == 0:
-                       return
-               if self.scaleUniform.getValue():
-                       matrix = [[scale,0,0], [0, scale, 0], [0, 0, scale]]
-               else:
-                       matrix = [[1,0,0], [0, 1, 0], [0, 0, 1]]
-                       matrix[axis][axis] = scale
-               self.selection.matrix *= numpy.matrix(matrix, numpy.float64)
-               self.selection.updateMatrix()
-
-       def OnClose(self, e):
-               self.Destroy()
-
-       def OnQuit(self, e):
-               self.Close()
-
-       def OnPreferences(self, e):
-               prefDialog = preferencesDialog(self)
-               prefDialog.Centre()
-               prefDialog.Show(True)
-
-       def OnCutMesh(self, e):
-               dlg=wx.FileDialog(self, "Open file to cut", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
-               dlg.SetWildcard(meshLoader.wildcardFilter())
-               if dlg.ShowModal() == wx.ID_OK:
-                       filename = dlg.GetPath()
-                       model = meshLoader.loadMesh(filename)
-                       pd = wx.ProgressDialog('Splitting model.', 'Splitting model into multiple parts.', model.vertexCount, self, wx.PD_ELAPSED_TIME | wx.PD_REMAINING_TIME | wx.PD_SMOOTH)
-                       parts = model.splitToParts(pd.Update)
-                       for part in parts:
-                               partFilename = filename[:filename.rfind('.')] + "_part%d.stl" % (parts.index(part))
-                               stl.saveAsSTL(part, partFilename)
-                               item = ProjectObject(self, partFilename)
-                               self.list.append(item)
-                               self.selection = item
-                               self._updateListbox()
-                               self.OnListSelect(None)
-                       pd.Destroy()
-               self.glCanvas.Refresh()
-               dlg.Destroy()
-
-       def OnDropFiles(self, filenames):
-               for filename in filenames:
-                       item = ProjectObject(self, filename)
-                       profile.putPreference('lastFile', item.filename)
-                       self.list.append(item)
-                       self.selection = item
-                       self._updateListbox()
-               self.OnListSelect(None)
-               self.glCanvas.Refresh()
-
-       def OnPrintTypeChange(self):
-               self.printMode = 0
-               if self.printAllAtOnce.GetValue():
-                       self.printMode = 1
-               if self.alwaysAutoPlace:
-                       self.OnAutoPlace(None)
-               self.glCanvas.Refresh()
-
-       def OnSaveCombinedSTL(self, e):
-               dlg=wx.FileDialog(self, "Save as STL", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)
-               dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")
-               if dlg.ShowModal() == wx.ID_OK:
-                       self._saveCombinedSTL(dlg.GetPath())
-               dlg.Destroy()
-
-       def _saveCombinedSTL(self, filename):
-               totalCount = 0
-               for item in self.list:
-                       totalCount += item.mesh.vertexCount
-               output = mesh.mesh()
-               output._prepareVertexCount(totalCount)
-               for item in self.list:
-                       vMin = item.getMinimum()
-                       vMax = item.getMaximum()
-                       offset = - vMin - (vMax - vMin) / 2
-                       offset += numpy.array([item.centerX, item.centerY, (vMax[2] - vMin[2]) / 2])
-                       vertexes = (item.mesh.vertexes * item.matrix).getA() + offset
-                       for v in vertexes:
-                               output.addVertex(v[0], v[1], v[2])
-               stl.saveAsSTL(output, filename)
-
-       def OnSaveProject(self, e):
-               dlg=wx.FileDialog(self, "Save project file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)
-               dlg.SetWildcard("Project files (*.curaproject)|*.curaproject")
-               if dlg.ShowModal() == wx.ID_OK:
-                       cp = ConfigParser.ConfigParser()
-                       i = 0
-                       for item in self.list:
-                               section = 'model_%d' % (i)
-                               cp.add_section(section)
-                               cp.set(section, 'filename', item.filename.encode("utf-8"))
-                               cp.set(section, 'centerX', str(item.centerX))
-                               cp.set(section, 'centerY', str(item.centerY))
-                               cp.set(section, 'matrix', ','.join(map(str, item.matrix.getA().flatten())))
-                               if item.profile != None:
-                                       cp.set(section, 'profile', item.profile)
-                               i += 1
-                       cp.write(open(dlg.GetPath(), "w"))
-               dlg.Destroy()
-
-       def OnLoadProject(self, e):
-               dlg=wx.FileDialog(self, "Open project file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
-               dlg.SetWildcard("Project files (*.curaproject)|*.curaproject")
-               if dlg.ShowModal() == wx.ID_OK:
-                       cp = ConfigParser.ConfigParser()
-                       cp.read(dlg.GetPath())
-                       self.list = []
-                       i = 0
-                       while cp.has_section('model_%d' % (i)):
-                               section = 'model_%d' % (i)
-
-                               item = ProjectObject(self, unicode(cp.get(section, 'filename'), "utf-8"))
-                               item.centerX = float(cp.get(section, 'centerX'))
-                               item.centerY = float(cp.get(section, 'centerY'))
-                               item.matrix = numpy.matrix(numpy.array(map(float, cp.get(section, 'matrix').split(',')), numpy.float64).reshape((3,3,)))
-                               if cp.has_option(section, 'extruder'):
-                                       item.extuder = int(cp.get(section, 'extruder')) - 1
-                               if cp.has_option(section, 'profile'):
-                                       item.profile = cp.get(section, 'profile')
-                               item.updateMatrix()
-                               i += 1
-
-                               self.list.append(item)
-
-                       self.selected = self.list[0]
-                       self._updateListbox()
-                       self.OnListSelect(None)
-                       self.glCanvas.Refresh()
-
-               dlg.Destroy()
-
-       def On3DClick(self):
-               self.glCanvas.yaw = 30
-               self.glCanvas.pitch = 60
-               self.glCanvas.zoom = 300
-               self.glCanvas.view3D = True
-               self.glCanvas.Refresh()
-
-       def OnTopClick(self):
-               self.glCanvas.view3D = False
-               self.glCanvas.zoom = self.machineSize[0] / 2 + 10
-               self.glCanvas.offsetX = 0
-               self.glCanvas.offsetY = 0
-               self.glCanvas.Refresh()
-
-       def OnListSelect(self, e):
-               if self.listbox.GetSelection() == -1:
-                       return
-               self.selection = self.list[self.listbox.GetSelection()]
-               self.glCanvas.Refresh()
-
-       def OnAddModel(self, e):
-               dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST|wx.FD_MULTIPLE)
-               dlg.SetWildcard(meshLoader.wildcardFilter())
-               if dlg.ShowModal() == wx.ID_OK:
-                       for filename in dlg.GetPaths():
-                               item = ProjectObject(self, filename)
-                               profile.putPreference('lastFile', item.filename)
-                               self.list.append(item)
-                               self.selection = item
-                               self._updateListbox()
-                               self.OnListSelect(None)
-               self.glCanvas.Refresh()
-               dlg.Destroy()
-
-       def OnRemModel(self, e):
-               if self.selection is None:
-                       return
-               self.list.remove(self.selection)
-               self._updateListbox()
-               self.glCanvas.Refresh()
-
-       def OnMoveUp(self, e):
-               if self.selection is None:
-                       return
-               i = self.listbox.GetSelection()
-               if i == 0:
-                       return
-               self.list.remove(self.selection)
-               self.list.insert(i-1, self.selection)
-               self._updateListbox()
-               self.glCanvas.Refresh()
-
-       def OnMoveDown(self, e):
-               if self.selection is None:
-                       return
-               i = self.listbox.GetSelection()
-               if i == len(self.list) - 1:
-                       return
-               self.list.remove(self.selection)
-               self.list.insert(i+1, self.selection)
-               self._updateListbox()
-               self.glCanvas.Refresh()
-
-       def OnCopy(self, e):
-               if self.selection is None:
-                       return
-
-               item = self.selection.clone()
-               self.list.insert(self.list.index(self.selection), item)
-               self.selection = item
-
-               self._updateListbox()
-               self.glCanvas.Refresh()
-
-       def OnSetCustomProfile(self, e):
-               if self.selection is None:
-                       return
-
-               dlg=wx.FileDialog(self, "Select profile", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
-               dlg.SetWildcard("Profile files (*.ini)|*.ini;*.INI")
-               if dlg.ShowModal() == wx.ID_OK:
-                       self.selection.profile = dlg.GetPath()
-               else:
-                       self.selection.profile = None
-               self._updateListbox()
-               dlg.Destroy()
-
-       def _updateListbox(self):
-               self.listbox.Clear()
-               for item in self.list:
-                       if item.profile is not None:
-                               self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1] + " *")
-                       else:
-                               self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1])
-               if self.selection in self.list:
-                       self.listbox.SetSelection(self.list.index(self.selection))
-               elif len(self.list) > 0:
-                       self.selection = self.list[0]
-                       self.listbox.SetSelection(0)
-               else:
-                       self.selection = None
-                       self.listbox.SetSelection(-1)
-               if self.alwaysAutoPlace:
-                       self.OnAutoPlace(None)
-
-       def OnAutoPlace(self, e):
-               bestAllowedSize = int(self.machineSize[1])
-               bestArea = self._doAutoPlace(bestAllowedSize)
-               for i in xrange(10, int(self.machineSize[1]), 10):
-                       area = self._doAutoPlace(i)
-                       if area < bestArea:
-                               bestAllowedSize = i
-                               bestArea = area
-               self._doAutoPlace(bestAllowedSize)
-               if not self.alwaysAutoPlace:
-                       for item in self.list:
-                               item.clampXY()
-               self.glCanvas.Refresh()
-
-       def _doAutoPlace(self, allowedSizeY):
-               extraSizeMin, extraSizeMax = self.getExtraHeadSize()
-
-               if extraSizeMin[0] > extraSizeMax[0]:
-                       posX = self.machineSize[0]
-                       dirX = -1
-               else:
-                       posX = 0
-                       dirX = 1
-               posY = 0
-               dirY = 1
-
-               minX = self.machineSize[0]
-               minY = self.machineSize[1]
-               maxX = 0
-               maxY = 0
-               for item in self.list:
-                       item.centerX = posX + item.getSize()[0] / 2 * dirX
-                       item.centerY = posY + item.getSize()[1] / 2 * dirY
-                       if item.centerY + item.getSize()[1] >= allowedSizeY:
-                               if dirX < 0:
-                                       posX = minX - extraSizeMax[0] - 1
-                               else:
-                                       posX = maxX + extraSizeMin[0] + 1
-                               posY = 0
-                               item.centerX = posX + item.getSize()[0] / 2 * dirX
-                               item.centerY = posY + item.getSize()[1] / 2 * dirY
-                       posY += item.getSize()[1]  * dirY + extraSizeMin[1] + 1
-                       minX = min(minX, item.centerX - item.getSize()[0] / 2)
-                       minY = min(minY, item.centerY - item.getSize()[1] / 2)
-                       maxX = max(maxX, item.centerX + item.getSize()[0] / 2)
-                       maxY = max(maxY, item.centerY + item.getSize()[1] / 2)
-
-               for item in self.list:
-                       if dirX < 0:
-                               item.centerX -= minX / 2
-                       else:
-                               item.centerX += (self.machineSize[0] - maxX) / 2
-                       item.centerY += (self.machineSize[1] - maxY) / 2
-
-               if minX < 0 or maxX > self.machineSize[0]:
-                       return ((maxX - minX) + (maxY - minY)) * 100
-
-               return (maxX - minX) + (maxY - minY)
-
-       def OnSlice(self, e):
-               dlg=wx.FileDialog(self, "Save project gcode file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)
-               dlg.SetWildcard("GCode file (*.gcode)|*.gcode")
-               if dlg.ShowModal() != wx.ID_OK:
-                       dlg.Destroy()
-                       return
-               resultFilename = dlg.GetPath()
-               dlg.Destroy()
-
-               put = profile.setTempOverride
-               oldProfile = profile.getGlobalProfileString()
-
-               if self.printMode == 0:
-                       fileList = []
-                       positionList = []
-                       for item in self.list:
-                               fileList.append(item.filename)
-                               if profile.getPreference('machine_center_is_zero') == 'True':
-                                       pos = [item.centerX - self.machineSize[0] / 2, item.centerY - self.machineSize[1] / 2]
-                               else:
-                                       pos = [item.centerX, item.centerY]
-                               positionList.append(pos + item.matrix.getA().flatten().tolist())
-                       print positionList
-                       sliceCommand = sliceRun.getSliceCommand(resultFilename, fileList, positionList)
-               else:
-                       self._saveCombinedSTL(resultFilename + "_temp_.stl")
-                       sliceCommand = sliceRun.getSliceCommand(resultFilename, [resultFilename + "_temp_.stl"], [profile.getMachineCenterCoords()])
-
-               pspw = ProjectSliceProgressWindow(sliceCommand, resultFilename, len(self.list))
-               pspw.Centre()
-               pspw.Show(True)
-
-       def getExtraHeadSize(self):
-               extraSizeMin = self.headSizeMin
-               extraSizeMax = self.headSizeMax
-               if profile.getProfileSettingFloat('skirt_line_count') > 0:
-                       skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
-                       extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0])
-                       extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0])
-               if profile.getProfileSetting('enable_raft') != 'False':
-                       raftSize = profile.getProfileSettingFloat('raft_margin') * 2
-                       extraSizeMin = extraSizeMin + numpy.array([raftSize, raftSize, 0])
-                       extraSizeMax = extraSizeMax + numpy.array([raftSize, raftSize, 0])
-               if profile.getProfileSetting('support') != 'None':
-                       extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0])
-                       extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0])
-
-               if self.printMode == 1:
-                       extraSizeMin = numpy.array([6.0, 6.0, 0])
-                       extraSizeMax = numpy.array([6.0, 6.0, 0])
-
-               return extraSizeMin, extraSizeMax
-
-class PreviewGLCanvas(openglGui.glGuiPanel):
-       def __init__(self, parent, projectPlannerWindow):
-               super(PreviewGLCanvas, self).__init__(parent)
-               self.parent = projectPlannerWindow
-               wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
-               self.yaw = 30
-               self.pitch = 60
-               self.offsetX = 0
-               self.offsetY = 0
-               self.view3D = self.parent.alwaysAutoPlace
-               if self.view3D:
-                       self.zoom = 300
-               else:
-                       self.zoom = self.parent.machineSize[0] / 2 + 10
-               self.dragType = ''
-               self.viewport = None
-               self.allowDrag = False
-               self.tempMatrix = None
-
-               self.objColor = profile.getPreferenceColour('model_colour')
-
-       def OnMouseLeftDown(self,e):
-               self.allowDrag = True
-               if not self.parent.alwaysAutoPlace and not self.view3D:
-                       p0 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 0, self.modelMatrix, self.projMatrix, self.viewport)
-                       p1 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 1, self.modelMatrix, self.projMatrix, self.viewport)
-                       p0 -= self.viewTarget
-                       p1 -= self.viewTarget
-                       p0 -= self.getObjectCenterPos() - self.viewTarget
-                       p1 -= self.getObjectCenterPos() - self.viewTarget
-                       cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
-
-                       for item in self.parent.list:
-                               iMin =-item.getSize() / 2 + numpy.array([item.centerX, item.centerY, 0])
-                               iMax = item.getSize() / 2 + numpy.array([item.centerX, item.centerY, 0])
-                               if iMin[0] <= cursorZ0[0] <= iMax[0] and iMin[1] <= cursorZ0[1] <= iMax[1]:
-                                       self.parent.selection = item
-                                       self.parent._updateListbox()
-                                       self.parent.OnListSelect(None)
-
-       def OnMouseMotion(self,e):
-               if self.viewport is not None:
-                       p0 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 0, self.modelMatrix, self.projMatrix, self.viewport)
-                       p1 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 1, self.modelMatrix, self.projMatrix, self.viewport)
-                       p0 -= self.viewTarget
-                       p1 -= self.viewTarget
-                       p0 -= self.getObjectCenterPos() - self.viewTarget
-                       p1 -= self.getObjectCenterPos() - self.viewTarget
-                       if not e.Dragging() or self.dragType != 'tool':
-                               self.parent.tool.OnMouseMove(p0, p1)
-               else:
-                       p0 = [0,0,0]
-                       p1 = [1,0,0]
-
-               if self.allowDrag and e.Dragging() and e.LeftIsDown():
-                       if self.dragType == '':
-                               #Define the drag type depending on the cursor position.
-                               self.dragType = 'viewRotate'
-                               if self.parent.tool.OnDragStart(p0, p1):
-                                       self.dragType = 'tool'
-                       if self.dragType == 'viewRotate':
-                               if self.view3D:
-                                       self.yaw += e.GetX() - self.oldX
-                                       self.pitch -= e.GetY() - self.oldY
-                                       if self.pitch > 170:
-                                               self.pitch = 170
-                                       if self.pitch < 10:
-                                               self.pitch = 10
-                               elif not self.parent.alwaysAutoPlace:
-                                       item = self.parent.selection
-                                       if item is not None:
-                                               item.centerX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2
-                                               item.centerY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2
-                                               item.clampXY()
-                       elif self.dragType == 'tool':
-                               self.parent.tool.OnDrag(p0, p1)
-               else:
-                       if self.dragType != '':
-                               if self.tempMatrix is not None:
-                                       self.parent.selection.matrix *= self.tempMatrix
-                                       self.parent.selection.updateMatrix()
-                                       self.tempMatrix = None
-                               self.parent.tool.OnDragEnd()
-                               self.dragType = ''
-                       self.allowDrag = False
-               if e.Dragging() and e.RightIsDown():
-                       if self.view3D:
-                               self.zoom += e.GetY() - self.oldY
-                               if self.zoom < 1:
-                                       self.zoom = 1
-                       self.Refresh()
-               self.oldX = e.GetX()
-               self.oldY = e.GetY()
-
-       def OnMouseWheel(self,e):
-               if self.view3D:
-                       self.zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
-                       if self.zoom < 1.0:
-                               self.zoom = 1.0
-                       self.Refresh()
-
-       def OnEraseBackground(self,event):
-               #Workaround for windows background redraw flicker.
-               pass
-
-       def OnSize(self,event):
-               self.Refresh()
-
-       def OnPaint(self,event):
-               opengl.InitGL(self, self.view3D, self.zoom)
-               if self.view3D:
-                       glTranslate(0,0,-self.zoom)
-                       glRotate(-self.pitch, 1,0,0)
-                       glRotate(self.yaw, 0,0,1)
-               self.viewTarget = self.parent.machineSize / 2
-               self.viewTarget[2] = 0
-               glTranslate(-self.viewTarget[0], -self.viewTarget[1], -self.viewTarget[2])
-
-               self.viewport = glGetIntegerv(GL_VIEWPORT)
-               self.modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
-               self.projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
-
-               self.OnDraw()
-
-       def OnDraw(self):
-               machineSize = self.parent.machineSize
-               extraSizeMin, extraSizeMax = self.parent.getExtraHeadSize()
-
-               for item in self.parent.list:
-                       item.validPlacement = True
-                       item.gotHit = False
-
-               for idx1 in xrange(0, len(self.parent.list)):
-                       item = self.parent.list[idx1]
-                       iMin1 =-item.getSize() / 2 + numpy.array([item.centerX, item.centerY, 0]) - extraSizeMin #- self.parent.extruderOffset[item.extruder]
-                       iMax1 = item.getSize() / 2 + numpy.array([item.centerX, item.centerY, 0]) + extraSizeMax #- self.parent.extruderOffset[item.extruder]
-                       if iMin1[0] < -self.parent.headSizeMin[0] or iMin1[1] < -self.parent.headSizeMin[1]:
-                               item.validPlacement = False
-                       if iMax1[0] > machineSize[0] + self.parent.headSizeMax[0] or iMax1[1] > machineSize[1] + self.parent.headSizeMax[1]:
-                               item.validPlacement = False
-                       for idx2 in xrange(0, idx1):
-                               item2 = self.parent.list[idx2]
-                               iMin2 =-item2.getSize() / 2 + numpy.array([item2.centerX, item2.centerY, 0])
-                               iMax2 = item2.getSize() / 2 + numpy.array([item2.centerX, item2.centerY, 0])
-                               if item != item2 and iMax1[0] >= iMin2[0] and iMin1[0] <= iMax2[0] and iMax1[1] >= iMin2[1] and iMin1[1] <= iMax2[1]:
-                                       item.validPlacement = False
-                                       item2.gotHit = True
-
-               seenSelected = False
-               for item in self.parent.list:
-                       if item == self.parent.selection:
-                               seenSelected = True
-                       if item.modelDisplayList is None:
-                               item.modelDisplayList = glGenLists(1);
-                       if item.modelDirty:
-                               item.modelDirty = False
-                               glNewList(item.modelDisplayList, GL_COMPILE)
-                               opengl.DrawMesh(item.mesh)
-                               glEndList()
-
-                       if item.validPlacement:
-                               if self.parent.selection == item:
-                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  map(lambda x: x + 0.2, self.objColor))
-                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  map(lambda x: x / 2, self.objColor))
-                               else:
-                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  self.objColor)
-                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  map(lambda x: x / 2, self.objColor))
-                       else:
-                               if self.parent.selection == item:
-                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  [1.0, 0.0, 0.0, 0.0])
-                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  [0.2, 0.0, 0.0, 0.0])
-                               else:
-                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  [1.0, 0.0, 0.0, 0.0])
-                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  [0.2, 0.0, 0.0, 0.0])
-                       glPushMatrix()
-
-                       glEnable(GL_LIGHTING)
-                       glTranslate(item.centerX, item.centerY, 0)
-                       vMin = item.getMinimum()
-                       vMax = item.getMaximum()
-                       offset = - vMin - (vMax - vMin) / 2
-                       matrix = opengl.convert3x3MatrixTo4x4(item.matrix)
-                       glPushMatrix()
-                       glTranslate(0, 0, item.getSize()[2]/2)
-                       if self.tempMatrix is not None and item == self.parent.selection:
-                               tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
-                               glMultMatrixf(tempMatrix)
-                       glTranslate(0, 0, -item.getSize()[2]/2)
-                       glTranslate(offset[0], offset[1], -vMin[2])
-                       glMultMatrixf(matrix)
-                       glCallList(item.modelDisplayList)
-                       glPopMatrix()
-
-                       vMin =-item.getSize() / 2
-                       vMax = item.getSize() / 2
-                       vMax[2] -= vMin[2]
-                       vMin[2] = 0
-                       vMinHead = vMin - extraSizeMin# - self.parent.extruderOffset[item.extruder]
-                       vMaxHead = vMax + extraSizeMax# - self.parent.extruderOffset[item.extruder]
-
-                       glDisable(GL_LIGHTING)
-
-                       if not self.parent.alwaysAutoPlace:
-                               glLineWidth(1)
-                               if self.parent.selection == item:
-                                       if item.gotHit:
-                                               glColor3f(1.0,0.0,0.3)
-                                       else:
-                                               glColor3f(1.0,0.0,1.0)
-                                       opengl.DrawBox(vMin, vMax)
-                                       if item.gotHit:
-                                               glColor3f(1.0,0.3,0.0)
-                                       else:
-                                               glColor3f(1.0,1.0,0.0)
-                                       opengl.DrawBox(vMinHead, vMaxHead)
-                               elif seenSelected:
-                                       if item.gotHit:
-                                               glColor3f(0.5,0.0,0.1)
-                                       else:
-                                               glColor3f(0.5,0.0,0.5)
-                                       opengl.DrawBox(vMinHead, vMaxHead)
-                               else:
-                                       if item.gotHit:
-                                               glColor3f(0.7,0.1,0.0)
-                                       else:
-                                               glColor3f(0.7,0.7,0.0)
-                                       opengl.DrawBox(vMin, vMax)
-
-                       glPopMatrix()
-
-               opengl.DrawMachine(util3d.Vector3(machineSize[0], machineSize[1], machineSize[2]))
-
-               if self.parent.selection is not None:
-                       glPushMatrix()
-                       glTranslate(self.parent.selection.centerX, self.parent.selection.centerY, self.parent.selection.getSize()[2]/2)
-                       self.parent.tool.OnDraw()
-                       glPopMatrix()
-
-       def getObjectSize(self):
-               if self.parent.selection is not None:
-                       return self.parent.selection.getSize()
-               return [0.0,0.0,0.0]
-       def getObjectBoundaryCircle(self):
-               if self.parent.selection is not None:
-                       return self.parent.selection.getBoundaryCircle()
-               return 0.0
-       def getObjectMatrix(self):
-               return self.parent.selection.matrix
-       def getObjectCenterPos(self):
-               if self.parent.selection is None:
-                       return [0,0,0]
-               return [self.parent.selection.centerX, self.parent.selection.centerY, self.getObjectSize()[2] / 2]
-
-class ProjectSliceProgressWindow(wx.Frame):
-       def __init__(self, sliceCommand, resultFilename, fileCount):
-               super(ProjectSliceProgressWindow, self).__init__(None, title='Cura')
-               self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
-
-               self.sliceCommand = sliceCommand
-               self.resultFilename = resultFilename
-               self.fileCount = fileCount
-               self.abort = False
-               self.prevStep = 'start'
-               self.totalDoneFactor = 0.0
-               self.startTime = time.time()
-               self.sliceStartTime = time.time()
-
-               self.sizer = wx.GridBagSizer(2, 2)
-               self.statusText = wx.StaticText(self, -1, "Building: %s" % (resultFilename))
-               self.progressGauge = wx.Gauge(self, -1)
-               self.progressGauge.SetRange(10000)
-               self.progressGauge2 = wx.Gauge(self, -1)
-               self.progressGauge2.SetRange(self.fileCount)
-               self.progressGauge2.SetValue(-1)
-               self.abortButton = wx.Button(self, -1, "Abort")
-               self.sizer.Add(self.statusText, (0,0), span=(1,5))
-               self.sizer.Add(self.progressGauge, (1, 0), span=(1,5), flag=wx.EXPAND)
-               self.sizer.Add(self.progressGauge2, (2, 0), span=(1,5), flag=wx.EXPAND)
-
-               self.sizer.Add(self.abortButton, (3,0), span=(1,5), flag=wx.ALIGN_CENTER)
-               self.sizer.AddGrowableCol(0)
-               self.sizer.AddGrowableRow(0)
-
-               self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton)
-               self.SetSizer(self.sizer)
-               self.Layout()
-               self.Fit()
-
-               threading.Thread(target=self.OnRun).start()
-
-       def OnAbort(self, e):
-               if self.abort:
-                       self.Close()
-               else:
-                       self.abort = True
-                       self.abortButton.SetLabel('Close')
-
-       def SetProgress(self, stepName, layer, maxLayer):
-               if self.prevStep != stepName:
-                       if stepName == 'slice':
-                               self.progressGauge2.SetValue(self.progressGauge2.GetValue() + 1)
-                               self.totalDoneFactor = 0
-                       self.totalDoneFactor += sliceRun.sliceStepTimeFactor[self.prevStep]
-                       newTime = time.time()
-                       #print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName
-                       self.startTime = newTime
-                       self.prevStep = stepName
-
-               progresValue = ((self.totalDoneFactor + sliceRun.sliceStepTimeFactor[stepName] * layer / maxLayer) / sliceRun.totalRunTimeFactor) * 10000
-               self.progressGauge.SetValue(int(progresValue))
-               self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]")
-               taskbar.setProgress(self, 10000 * self.progressGauge2.GetValue() + int(progresValue), 10000 * self.fileCount)
-
-       def OnRun(self):
-               self.progressLog = []
-               p = sliceRun.startSliceCommandProcess(self.sliceCommand)
-               line = p.stdout.readline()
-               while(len(line) > 0):
-                       line = line.rstrip()
-                       if line[0:9] == "Progress[" and line[-1:] == "]":
-                               progress = line[9:-1].split(":")
-                               if len(progress) > 2:
-                                       maxValue = int(progress[2])
-                               wx.CallAfter(self.SetProgress, progress[0], int(progress[1]), maxValue)
-                       else:
-                               self.progressLog.append(line)
-                               wx.CallAfter(self.statusText.SetLabel, line)
-                       if self.abort:
-                               p.terminate()
-                               wx.CallAfter(self.statusText.SetLabel, "Aborted by user.")
-                               return
-                       line = p.stdout.readline()
-               line = p.stderr.readline()
-               while len(line) > 0:
-                       line = line.rstrip()
-                       self.progressLog.append(line)
-                       line = p.stderr.readline()
-               self.returnCode = p.wait()
-               self.progressGauge2.SetValue(self.fileCount)
-
-               gcode = gcodeInterpreter.gcode()
-               gcode.load(self.resultFilename)
-
-               self.abort = True
-               sliceTime = time.time() - self.sliceStartTime
-               status = "Build: %s" % (self.resultFilename)
-               status += "\nSlicing took: %02d:%02d" % (sliceTime / 60, sliceTime % 60)
-               status += "\nFilament: %.2fm %.2fg" % (gcode.extrusionAmount / 1000, gcode.calculateWeight() * 1000)
-               status += "\nPrint time: %02d:%02d" % (int(gcode.totalMoveTimeMinute / 60), int(gcode.totalMoveTimeMinute % 60))
-               cost = gcode.calculateCost()
-               if cost is not None:
-                       status += "\nCost: %s" % (cost)
-               profile.replaceGCodeTags(self.resultFilename, gcode)
-               wx.CallAfter(self.statusText.SetLabel, status)
-               wx.CallAfter(self.OnSliceDone)
-
-       def _adjustNumberInLine(self, line, tag, f):
-               m = re.search('^(.*'+tag+')([0-9\.]*)(.*)$', line)
-               return m.group(1) + str(float(m.group(2)) + f) + m.group(3) + '\n'
-
-       def OnSliceDone(self):
-               self.abortButton.Destroy()
-               self.closeButton = wx.Button(self, -1, "Close")
-               self.printButton = wx.Button(self, -1, "Print")
-               self.logButton = wx.Button(self, -1, "Show log")
-               self.sizer.Add(self.closeButton, (3,0), span=(1,1))
-               self.sizer.Add(self.printButton, (3,1), span=(1,1))
-               self.sizer.Add(self.logButton, (3,2), span=(1,1))
-               if explorer.hasExplorer():
-                       self.openFileLocationButton = wx.Button(self, -1, "Open file location")
-                       self.Bind(wx.EVT_BUTTON, self.OnOpenFileLocation, self.openFileLocationButton)
-                       self.sizer.Add(self.openFileLocationButton, (3,3), span=(1,1))
-               if profile.getPreference('sdpath') != '':
-                       self.copyToSDButton = wx.Button(self, -1, "To SDCard")
-                       self.Bind(wx.EVT_BUTTON, self.OnCopyToSD, self.copyToSDButton)
-                       self.sizer.Add(self.copyToSDButton, (3,4), span=(1,1))
-               self.Bind(wx.EVT_BUTTON, self.OnAbort, self.closeButton)
-               self.Bind(wx.EVT_BUTTON, self.OnPrint, self.printButton)
-               self.Bind(wx.EVT_BUTTON, self.OnShowLog, self.logButton)
-               self.Layout()
-               self.Fit()
-               taskbar.setBusy(self, False)
-
-       def OnCopyToSD(self, e):
-               filename = os.path.basename(self.resultFilename)
-               if profile.getPreference('sdshortnames') == 'True':
-                       filename = sliceRun.getShortFilename(filename)
-               shutil.copy(self.resultFilename, os.path.join(profile.getPreference('sdpath'), filename))
-
-       def OnOpenFileLocation(self, e):
-               explorer.openExplorer(self.resultFilename)
-
-       def OnPrint(self, e):
-               printWindow.printFile(self.resultFilename)
-
-       def OnShowLog(self, e):
-               LogWindow('\n'.join(self.progressLog))
-
-class preferencesDialog(wx.Frame):
-       def __init__(self, parent):
-               super(preferencesDialog, self).__init__(None, title="Project Planner Preferences", style=wx.DEFAULT_DIALOG_STYLE)
-
-               self.parent = parent
-               wx.EVT_CLOSE(self, self.OnClose)
-
-               self.panel = configBase.configPanelBase(self)
-               extruderAmount = int(profile.getPreference('extruder_amount'))
-
-               left, right, main = self.panel.CreateConfigPanel(self)
-               configBase.TitleRow(left, 'User interface settings')
-               c = configBase.SettingRow(left, 'Always auto place objects in planner', 'planner_always_autoplace', True, 'Disable this to allow manual placement in the project planner (requires restart).', type = 'preference')
-               configBase.TitleRow(left, 'Machine head size')
-               c = configBase.SettingRow(left, 'Head size - X towards home (mm)', 'extruder_head_size_min_x', '0', 'Size of your printer head in the X direction, on the Ultimaker your fan is in this direction.', type = 'preference')
-               validators.validFloat(c, 0.1)
-               c = configBase.SettingRow(left, 'Head size - X towards end (mm)', 'extruder_head_size_max_x', '0', 'Size of your printer head in the X direction.', type = 'preference')
-               validators.validFloat(c, 0.1)
-               c = configBase.SettingRow(left, 'Head size - Y towards home (mm)', 'extruder_head_size_min_y', '0', 'Size of your printer head in the Y direction.', type = 'preference')
-               validators.validFloat(c, 0.1)
-               c = configBase.SettingRow(left, 'Head size - Y towards end (mm)', 'extruder_head_size_max_y', '0', 'Size of your printer head in the Y direction.', type = 'preference')
-               validators.validFloat(c, 0.1)
-               c = configBase.SettingRow(left, 'Head gantry height (mm)', 'extruder_head_size_height', '0', 'The tallest object height that will always fit under your printers gantry system when the printer head is at the lowest Z position.', type = 'preference')
-               validators.validFloat(c)
-
-               self.okButton = wx.Button(left, -1, 'Ok')
-               left.GetSizer().Add(self.okButton, (left.GetSizer().GetRows(), 1))
-               self.okButton.Bind(wx.EVT_BUTTON, self.OnClose)
-
-               self.MakeModal(True)
-               main.Fit()
-               self.Fit()
-
-       def OnClose(self, e):
-               self.parent.headSizeMin = numpy.array([profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0])
-               self.parent.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
-               self.parent.Refresh()
-
-               self.MakeModal(False)
-               self.Destroy()
-
-class LogWindow(wx.Frame):
-       def __init__(self, logText):
-               super(LogWindow, self).__init__(None, title="Slice log")
-               self.textBox = wx.TextCtrl(self, -1, logText, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_READONLY)
-               self.SetSize((400,300))
-               self.Centre()
-               self.Show(True)
diff --git a/Cura/gui/sliceProgressPanel.py b/Cura/gui/sliceProgressPanel.py
deleted file mode 100644 (file)
index c53371f..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-from __future__ import absolute_import
-
-import wx
-import os
-import shutil
-import threading
-import time
-import re
-import platform
-
-from Cura.gui import preferencesDialog
-from Cura.gui.util import taskbar
-from Cura.util import profile
-from Cura.util import sliceRun
-from Cura.util import explorer
-from Cura.util import gcodeInterpreter
-
-class sliceProgressPanel(wx.Panel):
-       def __init__(self, mainWindow, parent, filelist):
-               wx.Panel.__init__(self, parent, -1)
-               self.mainWindow = mainWindow
-               self.filelist = filelist
-               self.abort = False
-               
-               box = wx.StaticBox(self, -1, filelist[0])
-               self.sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
-
-               mainSizer = wx.BoxSizer(wx.VERTICAL) 
-               mainSizer.Add(self.sizer, 0, flag=wx.EXPAND)
-
-               self.statusText = wx.StaticText(self, -1, "Starting...")
-               self.progressGauge = wx.Gauge(self, -1)
-               self.progressGauge.SetRange(10000 * len(filelist))
-               self.abortButton = wx.Button(self, -1, "X", style=wx.BU_EXACTFIT)
-               self.sizer.Add(self.statusText, 2, flag=wx.ALIGN_CENTER )
-               self.sizer.Add(self.progressGauge, 2)
-               self.sizer.Add(self.abortButton, 0)
-
-               self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton)
-
-               self.SetSizer(mainSizer)
-               self.prevStep = 'start'
-               self.totalDoneFactor = 0.0
-               self.startTime = time.time()
-               if profile.getPreference('save_profile') == 'True':
-                       profile.saveProfile(self.filelist[0][: self.filelist[0].rfind('.')] + "_profile.ini")
-               center = profile.getMachineCenterCoords() + profile.getObjectMatrix()
-               cmdList = [sliceRun.getSliceCommand(sliceRun.getExportFilename(self.filelist[0]), ['|'.join(self.filelist)], [center])]
-               self.thread = WorkerThread(self, filelist, cmdList)
-       
-       def OnAbort(self, e):
-               if self.abort:
-                       self.mainWindow.removeSliceProgress(self)
-               else:
-                       self.abort = True
-       
-       def OnShowGCode(self, e):
-               self.mainWindow.preview3d.loadModelFiles(self.filelist)
-               self.mainWindow.preview3d.setViewMode("GCode")
-       
-       def OnShowLog(self, e):
-               LogWindow('\n'.join(self.progressLog))
-       
-       def OnOpenFileLocation(self, e):
-               explorer.openExplorer(sliceRun.getExportFilename(self.filelist[0]))
-       
-       def OnCopyToSD(self, e):
-               if profile.getPreference('sdpath') == '':
-                       wx.MessageBox("You need to configure your SD card drive first before you can copy files to it.\nOpening the preferences now.", 'No SD card drive.', wx.OK | wx.ICON_INFORMATION)
-                       prefDialog = preferencesDialog.preferencesDialog(self.GetParent())
-                       prefDialog.Centre()
-                       prefDialog.Show(True)
-                       if profile.getPreference('sdpath') == '':
-                               print "No path set"
-                               return
-               exportFilename = sliceRun.getExportFilename(self.filelist[0])
-               filename = os.path.basename(exportFilename)
-               if profile.getPreference('sdshortnames') == 'True':
-                       filename = sliceRun.getShortFilename(filename)
-               try:
-                       shutil.copy(exportFilename, os.path.join(profile.getPreference('sdpath'), filename))
-               except:
-                       self.GetParent().preview3d.ShowWarningPopup("Failed to copy file to SD card, card out of space or locked?")
-                       return
-               self.GetParent().preview3d.ShowWarningPopup("Copy finished, safely remove SD card?", self.OnSafeRemove)
-       
-       def OnSafeRemove(self):
-               if platform.system() == "Windows":
-                       cmd = '"%s" %s>NUL' % (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'EjectMedia.exe')), profile.getPreference('sdpath'))
-               elif platform.system() == "Darwin":
-                       cmd = "diskutil eject '%s' > /dev/null 2>&1" % (profile.getPreference('sdpath'))
-               else:
-                       cmd = "umount '%s' > /dev/null 2>&1" % (profile.getPreference('sdpath'))
-               if os.system(cmd):
-                       self.GetParent().preview3d.ShowWarningPopup("Safe remove failed.")
-               else:
-                       self.GetParent().preview3d.ShowWarningPopup("You can now eject the card.")
-
-       def OnSliceDone(self, result):
-               self.progressGauge.Destroy()
-               self.abortButton.Destroy()
-               self.progressLog = result.progressLog
-               self.logButton = wx.Button(self, -1, "Show Log")
-               self.abortButton = wx.Button(self, -1, "X", style=wx.BU_EXACTFIT)
-               self.Bind(wx.EVT_BUTTON, self.OnShowLog, self.logButton)
-               self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton)
-               self.sizer.Add(self.logButton, 0)
-               if result.returnCode == 0:
-                       status = "Ready: Filament: %.2fm %.2fg" % (result.gcode.extrusionAmount / 1000, result.gcode.calculateWeight() * 1000)
-                       status += " Print time: %02d:%02d" % (int(result.gcode.totalMoveTimeMinute / 60), int(result.gcode.totalMoveTimeMinute % 60))
-                       cost = result.gcode.calculateCost()
-                       if cost is not None:
-                               status += " Cost: %s" % (cost)
-                       self.statusText.SetLabel(status)
-                       if explorer.hasExplorer():
-                               self.openFileLocationButton = wx.Button(self, -1, "Open file location")
-                               self.Bind(wx.EVT_BUTTON, self.OnOpenFileLocation, self.openFileLocationButton)
-                               self.sizer.Add(self.openFileLocationButton, 0)
-                       if len(profile.getSDcardDrives()) > 0:
-                               self.copyToSDButton = wx.Button(self, -1, "Copy to SDCard")
-                               self.Bind(wx.EVT_BUTTON, self.OnCopyToSD, self.copyToSDButton)
-                               self.sizer.Add(self.copyToSDButton, 0)
-                       self.showButton = wx.Button(self, -1, "Show result")
-                       self.Bind(wx.EVT_BUTTON, self.OnShowGCode, self.showButton)
-                       self.sizer.Add(self.showButton, 0)
-               else:
-                       self.statusText.SetLabel("Something went wrong during slicing!")
-               self.sizer.Add(self.abortButton, 0)
-               self.sizer.Layout()
-               self.Layout()
-               self.abort = True
-               if self.mainWindow.preview3d.reloadModelFiles(self.filelist):
-                       self.mainWindow.preview3d.setViewMode("GCode")
-               self.thread = None
-               del result.gcode
-               taskbar.setBusy(self.GetParent(), False)
-       
-       def SetProgress(self, stepName, layer, maxLayer):
-               if self.prevStep != stepName:
-                       self.totalDoneFactor += sliceRun.sliceStepTimeFactor[self.prevStep]
-                       newTime = time.time()
-                       #print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName
-                       self.startTime = newTime
-                       self.prevStep = stepName
-               
-               progresValue = ((self.totalDoneFactor + sliceRun.sliceStepTimeFactor[stepName] * layer / maxLayer) / sliceRun.totalRunTimeFactor) * 10000
-               self.progressGauge.SetValue(int(progresValue))
-               taskbar.setProgress(self.GetParent(), int(progresValue), self.progressGauge.GetRange())
-               self.statusText.SetLabel("Preparing: processing %s [%d/%d]" % (stepName, layer, maxLayer))
-
-class WorkerThread(threading.Thread):
-       def __init__(self, notifyWindow, filelist, cmdList):
-               threading.Thread.__init__(self)
-               self.filelist = filelist
-               self.notifyWindow = notifyWindow
-               self.cmdList = cmdList
-               self.fileIdx = 0
-               self.start()
-
-       def run(self):
-               p = sliceRun.startSliceCommandProcess(self.cmdList[self.fileIdx])
-               line = p.stdout.readline()
-               self.progressLog = []
-               maxValue = 1
-               starttime = time.time()
-               while len(line) > 0:
-                       line = line.rstrip()
-                       if line[0:9] == "Progress[" and line[-1:] == "]":
-                               progress = line[9:-1].split(":")
-                               if len(progress) > 2:
-                                       maxValue = int(progress[2])
-                               wx.CallAfter(self.notifyWindow.SetProgress, progress[0], int(progress[1]), maxValue)
-                       else:
-                               self.progressLog.append("%0.2f: %s" % (time.time() - starttime, line))
-                               wx.CallAfter(self.notifyWindow.statusText.SetLabel, line)
-                       if self.notifyWindow.abort:
-                               p.terminate()
-                               wx.CallAfter(self.notifyWindow.mainWindow.removeSliceProgress, self.notifyWindow)
-                               return
-                       line = p.stdout.readline()
-               line = p.stderr.readline()
-               while len(line) > 0:
-                       line = line.rstrip()
-                       self.progressLog.append(line)
-                       line = p.stderr.readline()
-               self.returnCode = p.wait()
-               self.fileIdx += 1
-               if self.fileIdx == len(self.cmdList):
-                       gcodeFilename = sliceRun.getExportFilename(self.filelist[0])
-                       gcodefile = open(gcodeFilename, "a")
-                       for logLine in self.progressLog:
-                               if logLine.startswith('Model error('):
-                                       gcodefile.write(';%s\n' % (logLine))
-                       gcodefile.close()
-                       self.gcode = gcodeInterpreter.gcode()
-                       self.gcode.load(gcodeFilename)
-                       profile.replaceGCodeTags(gcodeFilename, self.gcode)
-                       wx.CallAfter(self.notifyWindow.OnSliceDone, self)
-               else:
-                       self.run()
-
-class LogWindow(wx.Frame):
-       def __init__(self, logText):
-               super(LogWindow, self).__init__(None, title="Slice log")
-               self.textBox = wx.TextCtrl(self, -1, logText, style=wx.TE_MULTILINE|wx.TE_DONTWRAP|wx.TE_READONLY)
-               self.SetSize((400,300))
-               self.Centre()
-               self.Show(True)
-
index 9517fccbba9009fc57a5f2c706cddca2a0923e9b..3d53b4aef93e35d5a0ea30db37ef660b756a9013 100644 (file)
@@ -361,6 +361,7 @@ class superformulaWindow(wx.Frame):
                m.vertexCount = self._shape._obj._meshList[0].vertexCount
                obj._postProcessAfterLoad()
                self.GetParent().scene._scene.add(obj)
+               self.GetParent().scene.sceneUpdated()
 
        def _updateShape(self):
                if self._shape is not None: