chiark / gitweb /
Fix for bug caused by offloading scaling to the 3D card
authorDaid <daid303@gmail.com>
Wed, 18 Apr 2012 20:51:19 +0000 (22:51 +0200)
committerDaid <daid303@gmail.com>
Wed, 18 Apr 2012 20:51:19 +0000 (22:51 +0200)
Cura/gui/preview3d.py
Cura/gui/projectPlanner.py [new file with mode: 0644]

index 8ec9585fe7b41a31f994ef0eac6936ddf655e5ef..c421c900fc6a3511388e74cf03dd2bd0718dc267 100644 (file)
@@ -140,9 +140,8 @@ class previewPanel(wx.Panel):
        def OnScaleMax(self, e):\r
                if self.triangleMesh == None:\r
                        return\r
-               scale = float(self.scale.GetValue())\r
-               vMin = self.triangleMesh.getMinimum() / scale\r
-               vMax = self.triangleMesh.getMaximum() / scale\r
+               vMin = self.triangleMesh.getMinimum()\r
+               vMax = self.triangleMesh.getMaximum()\r
                scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax.x - vMin.x) / 2)\r
                scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax.y - vMin.y) / 2)\r
                scaleX2 = (self.machineCenter.x) / ((vMax.x - vMin.x) / 2)\r
@@ -400,7 +399,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
                        glRotate(-self.pitch, 1,0,0)\r
                        glRotate(self.yaw, 0,0,1)\r
                        if self.parent.triangleMesh != None:\r
-                               glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2)\r
+                               glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z * profile.getProfileSettingFloat('model_scale') / 2)\r
                else:\r
                        glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)\r
                        glTranslate(self.offsetX, self.offsetY, 0.0)\r
diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py
new file mode 100644 (file)
index 0000000..d9756c8
--- /dev/null
@@ -0,0 +1,507 @@
+from __future__ import absolute_import\r
+import __init__\r
+\r
+import wx, os, platform, types, webbrowser, math, subprocess\r
+import ConfigParser\r
+\r
+from wx import glcanvas\r
+import wx\r
+try:\r
+       import OpenGL\r
+       OpenGL.ERROR_CHECKING = False\r
+       from OpenGL.GLU import *\r
+       from OpenGL.GL import *\r
+       hasOpenGLlibs = True\r
+except:\r
+       print "Failed to find PyOpenGL: http://pyopengl.sourceforge.net/"\r
+       hasOpenGLlibs = False\r
+\r
+from gui import opengl\r
+from gui import icon\r
+from util import profile\r
+from util import util3d\r
+from util import stl\r
+from util import sliceRun\r
+\r
+class projectPlanner(wx.Frame):\r
+       "Main user interface window"\r
+       def __init__(self):\r
+               super(projectPlanner, self).__init__(None, title='Cura')\r
+               \r
+               self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))\r
+               wx.EVT_CLOSE(self, self.OnClose)\r
+               #self.SetIcon(icon.getMainIcon())\r
+               \r
+               menubar = wx.MenuBar()\r
+               fileMenu = wx.Menu()\r
+               i = fileMenu.Append(-1, 'Open Project...')\r
+               self.Bind(wx.EVT_MENU, self.OnLoadProject, i)\r
+               i = fileMenu.Append(-1, 'Save Project...')\r
+               self.Bind(wx.EVT_MENU, self.OnSaveProject, i)\r
+               fileMenu.AppendSeparator()\r
+               i = fileMenu.Append(wx.ID_EXIT, 'Quit')\r
+               self.Bind(wx.EVT_MENU, self.OnQuit, i)\r
+               menubar.Append(fileMenu, '&File')\r
+               self.SetMenuBar(menubar)\r
+               \r
+               self.list = []\r
+               self.selection = None\r
+\r
+               self.machineSize = util3d.Vector3(float(profile.getPreference('machine_width')), float(profile.getPreference('machine_depth')), float(profile.getPreference('machine_height')))\r
+               self.headSizeMin = util3d.Vector3(70,16,0)\r
+               self.headSizeMax = util3d.Vector3(16,35,0)\r
+\r
+               self.toolbar = wx.ToolBar( self, -1 )\r
+               self.toolbar.SetToolBitmapSize( ( 21, 21 ) )\r
+\r
+               button = wx.Button(self.toolbar, -1, "3D", size=(21*2,21))\r
+               self.toolbar.AddControl(button)\r
+               self.Bind(wx.EVT_BUTTON, self.On3DClick, button)\r
+               \r
+               button = wx.Button(self.toolbar, -1, "Top", size=(21*2,21))\r
+               self.toolbar.AddControl(button)\r
+               self.Bind(wx.EVT_BUTTON, self.OnTopClick, button)\r
+               self.toolbar.Realize()\r
+               \r
+               sizer = wx.GridBagSizer(2,2)\r
+               self.SetSizer(sizer)\r
+               self.preview = PreviewGLCanvas(self)\r
+               self.listbox = wx.ListBox(self, -1, choices=[])\r
+               self.addButton = wx.Button(self, -1, "Add")\r
+               self.remButton = wx.Button(self, -1, "Remove")\r
+               self.sliceButton = wx.Button(self, -1, "Slice")\r
+               \r
+               sizer.Add(self.toolbar, (0,0), span=(1,1), flag=wx.EXPAND)\r
+               sizer.Add(self.preview, (1,0), span=(3,1), flag=wx.EXPAND)\r
+               sizer.Add(self.listbox, (0,1), span=(2,2), flag=wx.EXPAND)\r
+               sizer.Add(self.addButton, (2,1), span=(1,1))\r
+               sizer.Add(self.remButton, (2,2), span=(1,1))\r
+               sizer.Add(self.sliceButton, (3,1), span=(1,1))\r
+               sizer.AddGrowableCol(0)\r
+               sizer.AddGrowableRow(1)\r
+               \r
+               self.addButton.Bind(wx.EVT_BUTTON, self.OnAddModel)\r
+               self.remButton.Bind(wx.EVT_BUTTON, self.OnRemModel)\r
+               self.sliceButton.Bind(wx.EVT_BUTTON, self.OnSlice)\r
+               self.listbox.Bind(wx.EVT_LISTBOX, self.OnListSelect)\r
+               \r
+               self.SetSize((800,600))\r
+\r
+       def OnClose(self, e):\r
+               self.Destroy()\r
+\r
+       def OnQuit(self, e):\r
+               self.Close()\r
+       \r
+       def OnSaveProject(self, e):\r
+               dlg=wx.FileDialog(self, "Save project file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)\r
+               dlg.SetWildcard("Project files (*.curaproject)|*.curaproject")\r
+               if dlg.ShowModal() == wx.ID_OK:\r
+                       cp = ConfigParser.ConfigParser()\r
+                       i = 0\r
+                       for item in self.list:\r
+                               section = 'model_%d' % (i)\r
+                               cp.add_section(section)\r
+                               cp.set(section, 'filename', item.filename.encode("utf-8"))\r
+                               cp.set(section, 'centerX', str(item.centerX))\r
+                               cp.set(section, 'centerY', str(item.centerY))\r
+                               cp.set(section, 'scale', str(item.scale))\r
+                               cp.set(section, 'rotate', str(item.rotate))\r
+                               cp.set(section, 'flipX', str(item.flipX))\r
+                               cp.set(section, 'flipY', str(item.flipY))\r
+                               cp.set(section, 'flipZ', str(item.flipZ))\r
+                               cp.set(section, 'swapXZ', str(item.swapXZ))\r
+                               cp.set(section, 'swapYZ', str(item.swapYZ))\r
+                               i += 1\r
+                       cp.write(open(dlg.GetPath(), "w"))\r
+               dlg.Destroy()\r
+\r
+       def OnLoadProject(self, e):\r
+               dlg=wx.FileDialog(self, "Open project file", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)\r
+               dlg.SetWildcard("Project files (*.curaproject)|*.curaproject")\r
+               if dlg.ShowModal() == wx.ID_OK:\r
+                       cp = ConfigParser.ConfigParser()\r
+                       cp.read(dlg.GetPath())\r
+                       self.list = []\r
+                       self.listbox.Clear()\r
+                       i = 0\r
+                       while cp.has_section('model_%d' % (i)):\r
+                               section = 'model_%d' % (i)\r
+                               \r
+                               item = stl.stlModel()\r
+                               item.filename = unicode(cp.get(section, 'filename'), "utf-8")\r
+                               self.loadModelFile(item)\r
+                               item.centerX = float(cp.get(section, 'centerX'))\r
+                               item.centerY = float(cp.get(section, 'centerY'))\r
+                               item.scale = float(cp.get(section, 'scale'))\r
+                               item.rotate = float(cp.get(section, 'rotate'))\r
+                               cp.get(section, 'flipX')\r
+                               cp.get(section, 'flipY')\r
+                               cp.get(section, 'flipZ')\r
+                               cp.get(section, 'swapXZ')\r
+                               cp.get(section, 'swapYZ')\r
+                               i += 1\r
+                               \r
+                               self.list.append(item)\r
+                               self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1])\r
+                       \r
+                       self.listbox.SetSelection(len(self.list)-1)\r
+                       self.OnListSelect(None)\r
+\r
+               dlg.Destroy()\r
+\r
+       def On3DClick(self, e):\r
+               self.preview.yaw = 30\r
+               self.preview.pitch = 60\r
+               self.preview.zoom = 300\r
+               self.preview.view3D = True\r
+               self.preview.Refresh()\r
+\r
+       def OnTopClick(self, e):\r
+               self.preview.view3D = False\r
+               self.preview.zoom = self.machineSize.x / 2 + 10\r
+               self.preview.offsetX = 0\r
+               self.preview.offsetY = 0\r
+               self.preview.Refresh()\r
+\r
+       def OnListSelect(self, e):\r
+               self.selection = self.list[self.listbox.GetSelection()]\r
+               self.preview.Refresh()\r
+\r
+       def OnAddModel(self, e):\r
+               dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)\r
+               dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")\r
+               if dlg.ShowModal() == wx.ID_OK:\r
+                       item = stl.stlModel()\r
+                       item.filename=dlg.GetPath()\r
+                       profile.putPreference('lastFile', item.filename)\r
+                       if not(os.path.exists(item.filename)):\r
+                               return\r
+                       self.loadModelFile(item)\r
+                       self.list.append(item)\r
+                       self.listbox.AppendAndEnsureVisible(os.path.split(item.filename)[1])\r
+                       self.listbox.SetSelection(len(self.list)-1)\r
+                       self.OnListSelect(None)\r
+               dlg.Destroy()\r
+       \r
+       def OnRemModel(self, e):\r
+               if self.selection == None:\r
+                       return\r
+               self.list.remove(self.selection)\r
+               self.listbox.Delete(self.listbox.GetSelection())\r
+               self.selection = None\r
+               self.preview.Refresh()\r
+\r
+       def OnSlice(self, e):\r
+               oldProfile = profile.getGlobalProfileString()\r
+               \r
+               put = profile.putProfileSetting\r
+\r
+               put('model_multiply_x', '1')\r
+               put('model_multiply_y', '1')\r
+               put('skirt_line_count', '0')\r
+               put('enable_raft', 'False')\r
+               put('add_start_end_gcode', 'False')\r
+               put('gcode_extension', 'project_tmp')\r
+               \r
+               for item in self.list:\r
+                       put('machine_center_x', item.centerX)\r
+                       put('machine_center_y', item.centerY)\r
+                       put('model_scale', item.scale)\r
+                       put('flip_x', item.flipX)\r
+                       put('flip_y', item.flipY)\r
+                       put('flip_z', item.flipZ)\r
+                       put('model_rotate_base', item.rotate)\r
+                       put('swap_xz', item.swapXZ)\r
+                       put('swap_yz', item.swapYZ)\r
+                       \r
+                       item.sliceCmd = sliceRun.getSliceCommand(item.filename)\r
+               \r
+               #Restore the old profile.\r
+               profile.loadGlobalProfileFromString(oldProfile)\r
+               \r
+               resultFile = open("D:/Printing/result_export.gcode", "w")\r
+               resultFile.write(';TYPE:CUSTOM\n')\r
+               resultFile.write(profile.getAlterationFileContents('start.gcode'))\r
+               i = 1\r
+               maxZ = 0\r
+               prevItem = None\r
+               for item in self.list:\r
+                       subprocess.call(item.sliceCmd)\r
+                       \r
+                       if prevItem != None:\r
+                               #reset the extrusion length, and move to the next object center.\r
+                               resultFile.write(';PRINTNR:%d\n' % (i))\r
+                               resultFile.write(';TYPE:CUSTOM\n')\r
+                               resultFile.write('G1 Z%f F%f\n' % (maxZ + 5, profile.getProfileSettingFloat('travel_speed') * 60))\r
+                               resultFile.write('G92 E0\n')\r
+                               resultFile.write('G1 X%f Y%f F%f\n' % (item.centerX, item.centerY, profile.getProfileSettingFloat('travel_speed') * 60))\r
+                               resultFile.write('G1 Z0 F%f\n' % (profile.getProfileSettingFloat('max_z_speed') * 60))\r
+                       \r
+                       f = open(item.filename[: item.filename.rfind('.')] + "_export.project_tmp", "r")\r
+                       data = f.read(4096)\r
+                       while data != '':\r
+                               resultFile.write(data)\r
+                               data = f.read(4096)\r
+                       f.close()\r
+                       os.remove(item.filename[: item.filename.rfind('.')] + "_export.project_tmp")\r
+                       i += 1\r
+                       \r
+                       prevItem = item\r
+                       maxZ = max(maxZ, item.getMaximum().z * item.scale)\r
+               \r
+               resultFile.write(';TYPE:CUSTOM\n')\r
+               resultFile.write(profile.getAlterationFileContents('end.gcode'))\r
+               resultFile.close()      \r
+       \r
+       def loadModelFile(self, item):\r
+               item.load(item.filename)\r
+               item.origonalVertexes = list(item.vertexes)\r
+               for i in xrange(0, len(item.origonalVertexes)):\r
+                       item.origonalVertexes[i] = item.origonalVertexes[i].copy()\r
+               item.getMinimumZ()\r
+               \r
+               item.centerX = -item.getMinimum().x + 5\r
+               item.centerY = -item.getMinimum().y + 5\r
+               item.scale = 1.0\r
+               item.rotate = 0.0\r
+               item.flipX = False\r
+               item.flipY = False\r
+               item.flipZ = False\r
+               item.swapXZ = False\r
+               item.swapYZ = False\r
+               \r
+               item.modelDisplayList = None\r
+               item.modelDirty = False\r
+               \r
+               self.updateModelTransform(item)\r
+\r
+       def updateModelTransform(self, item):\r
+               scale = item.scale\r
+               rotate = item.rotate\r
+               scaleX = scale\r
+               scaleY = scale\r
+               scaleZ = scale\r
+               if item.flipX:\r
+                       scaleX = -scaleX\r
+               if item.flipY:\r
+                       scaleY = -scaleY\r
+               if item.flipZ:\r
+                       scaleZ = -scaleZ\r
+               swapXZ = item.swapXZ\r
+               swapYZ = item.swapYZ\r
+               mat00 = math.cos(rotate) * scaleX\r
+               mat01 =-math.sin(rotate) * scaleY\r
+               mat10 = math.sin(rotate) * scaleX\r
+               mat11 = math.cos(rotate) * scaleY\r
+               \r
+               for i in xrange(0, len(item.origonalVertexes)):\r
+                       x = item.origonalVertexes[i].x\r
+                       y = item.origonalVertexes[i].y\r
+                       z = item.origonalVertexes[i].z\r
+                       if swapXZ:\r
+                               x, z = z, x\r
+                       if swapYZ:\r
+                               y, z = z, y\r
+                       item.vertexes[i].x = x * mat00 + y * mat01\r
+                       item.vertexes[i].y = x * mat10 + y * mat11\r
+                       item.vertexes[i].z = z * scaleZ\r
+\r
+               for face in item.faces:\r
+                       v1 = face.v[0]\r
+                       v2 = face.v[1]\r
+                       v3 = face.v[2]\r
+                       face.normal = (v2 - v1).cross(v3 - v1)\r
+                       face.normal.normalize()\r
+\r
+               self.moveModel(item)\r
+       \r
+       def moveModel(self, item):\r
+               minZ = item.getMinimumZ()\r
+               min = item.getMinimum()\r
+               max = item.getMaximum()\r
+               for v in item.vertexes:\r
+                       v.z -= minZ\r
+                       v.x -= min.x + (max.x - min.x) / 2\r
+                       v.y -= min.y + (max.y - min.y) / 2\r
+               item.getMinimumZ()\r
+               item.modelDirty = True\r
+               self.preview.Refresh()\r
+\r
+class PreviewGLCanvas(glcanvas.GLCanvas):\r
+       def __init__(self, parent):\r
+               attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)\r
+               glcanvas.GLCanvas.__init__(self, parent, attribList = attribList)\r
+               self.parent = parent\r
+               self.context = glcanvas.GLContext(self)\r
+               wx.EVT_PAINT(self, self.OnPaint)\r
+               wx.EVT_SIZE(self, self.OnSize)\r
+               wx.EVT_ERASE_BACKGROUND(self, self.OnEraseBackground)\r
+               wx.EVT_LEFT_DOWN(self, self.OnMouseLeftDown)\r
+               wx.EVT_MOTION(self, self.OnMouseMotion)\r
+               wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)\r
+               self.yaw = 30\r
+               self.pitch = 60\r
+               self.zoom = self.parent.machineSize.x / 2 + 10\r
+               self.offsetX = 0\r
+               self.offsetY = 0\r
+               self.view3D = False\r
+               self.allowDrag = False\r
+       \r
+       def OnMouseLeftDown(self,e):\r
+               self.allowDrag = True\r
+       \r
+       def OnMouseMotion(self,e):\r
+               if self.allowDrag and e.Dragging() and e.LeftIsDown():\r
+                       if self.view3D:\r
+                               self.yaw += e.GetX() - self.oldX\r
+                               self.pitch -= e.GetY() - self.oldY\r
+                               if self.pitch > 170:\r
+                                       self.pitch = 170\r
+                               if self.pitch < 10:\r
+                                       self.pitch = 10\r
+                       else:\r
+                               #self.offsetX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2\r
+                               #self.offsetY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2\r
+                               item = self.parent.selection\r
+                               if item != None:\r
+                                       item.centerX += float(e.GetX() - self.oldX) * self.zoom / self.GetSize().GetHeight() * 2\r
+                                       item.centerY -= float(e.GetY() - self.oldY) * self.zoom / self.GetSize().GetHeight() * 2\r
+                                       if item.centerX < -item.getMinimum().x * item.scale:\r
+                                               item.centerX = -item.getMinimum().x * item.scale\r
+                                       if item.centerY < -item.getMinimum().y * item.scale:\r
+                                               item.centerY = -item.getMinimum().y * item.scale\r
+                                       if item.centerX > self.parent.machineSize.x - item.getMaximum().x * item.scale:\r
+                                               item.centerX = self.parent.machineSize.x - item.getMaximum().x * item.scale\r
+                                       if item.centerY > self.parent.machineSize.y - item.getMaximum().y * item.scale:\r
+                                               item.centerY = self.parent.machineSize.y - item.getMaximum().y * item.scale\r
+                       self.Refresh()\r
+               else:\r
+                       self.allowDrag = False\r
+               if e.Dragging() and e.RightIsDown():\r
+                       if self.view3D:\r
+                               self.zoom += e.GetY() - self.oldY\r
+                               if self.zoom < 1:\r
+                                       self.zoom = 1\r
+                       self.Refresh()\r
+               self.oldX = e.GetX()\r
+               self.oldY = e.GetY()\r
+       \r
+       def OnMouseWheel(self,e):\r
+               if self.view3D:\r
+                       self.zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0\r
+                       if self.zoom < 1.0:\r
+                               self.zoom = 1.0\r
+                       self.Refresh()\r
+       \r
+       def OnEraseBackground(self,event):\r
+               #Workaround for windows background redraw flicker.\r
+               pass\r
+       \r
+       def OnSize(self,event):\r
+               self.Refresh()\r
+\r
+       def OnPaint(self,event):\r
+               dc = wx.PaintDC(self)\r
+               if not hasOpenGLlibs:\r
+                       dc.Clear()\r
+                       dc.DrawText("No PyOpenGL installation found.\nNo preview window available.", 10, 10)\r
+                       return\r
+               self.SetCurrent(self.context)\r
+               opengl.InitGL(self, self.view3D, self.zoom)\r
+               if self.view3D:\r
+                       glTranslate(0,0,-self.zoom)\r
+                       glRotate(-self.pitch, 1,0,0)\r
+                       glRotate(self.yaw, 0,0,1)\r
+                       if False: #self.parent.triangleMesh != None:\r
+                               glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2)\r
+               else:\r
+                       glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)\r
+                       glTranslate(self.offsetX, self.offsetY, 0.0)\r
+               glTranslate(-self.parent.machineSize.x/2, -self.parent.machineSize.y/2, 0)\r
+\r
+               self.OnDraw()\r
+               self.SwapBuffers()\r
+\r
+       def OnDraw(self):\r
+               machineSize = self.parent.machineSize\r
+               opengl.DrawMachine(machineSize)\r
+\r
+               for item in self.parent.list:\r
+                       item.validPlacement = True\r
+                       item.gotHit = False\r
+               \r
+               for idx1 in xrange(0, len(self.parent.list)):\r
+                       item = self.parent.list[idx1]\r
+                       iMin1 = item.getMinimum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) - self.parent.headSizeMin\r
+                       iMax1 = item.getMaximum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) + self.parent.headSizeMax\r
+                       for idx2 in xrange(0, idx1):\r
+                               item2 = self.parent.list[idx2]\r
+                               iMin2 = item2.getMinimum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0)\r
+                               iMax2 = item2.getMaximum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0)\r
+                               if item != item2 and iMax1.x >= iMin2.x and iMin1.x <= iMax2.x and iMax1.y >= iMin2.y and iMin1.y <= iMax2.y:\r
+                                       item.validPlacement = False\r
+                                       item2.gotHit = True\r
+               \r
+               for item in self.parent.list:\r
+                       if item.modelDisplayList == None:\r
+                               item.modelDisplayList = glGenLists(1);\r
+                       if item.modelDirty:\r
+                               item.modelDirty = False\r
+                               modelSize = item.getMaximum() - item.getMinimum()\r
+                               glNewList(item.modelDisplayList, GL_COMPILE)\r
+                               opengl.DrawSTL(item)\r
+                               glEndList()\r
+                       \r
+                       if item.validPlacement:\r
+                               if self.parent.selection == item:\r
+                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  [1.0, 0.9, 0.7, 1.0])\r
+                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  [0.2, 0.3, 0.2, 0.0])\r
+                               else:\r
+                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  [1.0, 0.8, 0.6, 1.0])\r
+                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  [0.2, 0.1, 0.1, 0.0])\r
+                       else:\r
+                               if self.parent.selection == item:\r
+                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  [1.0, 0.0, 0.0, 0.0])\r
+                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  [0.2, 0.0, 0.0, 0.0])\r
+                               else:\r
+                                       glLightfv(GL_LIGHT0, GL_DIFFUSE,  [1.0, 0.0, 0.0, 0.0])\r
+                                       glLightfv(GL_LIGHT0, GL_AMBIENT,  [0.2, 0.0, 0.0, 0.0])\r
+                       glPushMatrix()\r
+                       \r
+                       glEnable(GL_LIGHTING)\r
+                       glTranslate(item.centerX, item.centerY, 0)\r
+                       glPushMatrix()\r
+                       glEnable(GL_NORMALIZE)\r
+                       glScalef(item.scale, item.scale, item.scale)\r
+                       glCallList(item.modelDisplayList)\r
+                       glPopMatrix()\r
+                       \r
+                       vMin = item.getMinimum() * item.scale\r
+                       vMax = item.getMaximum() * item.scale\r
+                       glDisable(GL_LIGHTING)\r
+                       if item.gotHit:\r
+                               glColor3f(1.0,0.3,0.0)\r
+                       else:\r
+                               glColor3f(1.0,1.0,0.0)\r
+                       opengl.DrawBox(vMin, vMax)\r
+                       \r
+                       vMin = vMin - self.parent.headSizeMin\r
+                       vMax = vMax + self.parent.headSizeMax\r
+                       if item.validPlacement:\r
+                               glColor3f(1.0,0.0,1.0)\r
+                       else:\r
+                               glColor3f(1.0,0.0,0.3)\r
+                       opengl.DrawBox(vMin, vMax)\r
+                       \r
+                       glPopMatrix()\r
+               \r
+               glFlush()\r
+\r
+def main():\r
+       app = wx.App(False)\r
+       projectPlanner().Show(True)\r
+       app.MainLoop()\r
+\r
+if __name__ == '__main__':\r
+       main()\r