chiark / gitweb /
Make sure the print fits on the bed with dual-extrusion-support.
[cura.git] / Cura / gui / sceneView.py
index 15da8947dcd3cdf04604b454074c6880825d2667..c7ad9c8573819f808575fcee96846a2c1ae011fc 100644 (file)
@@ -16,6 +16,7 @@ from OpenGL.GLU import *
 from OpenGL.GL import *
 
 from Cura.gui import printWindow
+from Cura.gui import printWindow2
 from Cura.util import profile
 from Cura.util import meshLoader
 from Cura.util import objectScene
@@ -24,6 +25,7 @@ from Cura.util import sliceEngine
 from Cura.util import machineCom
 from Cura.util import removableStorage
 from Cura.util import gcodeInterpreter
+from Cura.util.printerConnection import printerConnectionManager
 from Cura.gui.util import previewTools
 from Cura.gui.util import opengl
 from Cura.gui.util import openglGui
@@ -54,8 +56,10 @@ class SceneView(openglGui.glGuiPanel):
                self._animView = None
                self._animZoom = None
                self._platformMesh = {}
+               self._platformTexture = None
                self._isSimpleMode = True
                self._usbPrintMonitor = printWindow.printProcessMonitor(lambda : self._queueRefresh())
+               self._printerConnectionManager = printerConnectionManager.PrinterConnectionManager()
 
                self._viewport = None
                self._modelMatrix = None
@@ -222,9 +226,10 @@ class SceneView(openglGui.glGuiPanel):
 
        def OnPrintButton(self, button):
                if button == 1:
+                       connectionEntry = self._printerConnectionManager.getAvailableConnection()
                        if machineCom.machineIsConnected():
                                self.showPrintWindow()
-                       elif len(removableStorage.getPossibleSDcardDrives()) > 0:
+                       elif len(removableStorage.getPossibleSDcardDrives()) > 0 and (connectionEntry is None or connectionEntry.priority < 0):
                                drives = removableStorage.getPossibleSDcardDrives()
                                if len(drives) > 1:
                                        dlg = wx.SingleChoiceDialog(self, "Select SD drive", "Multiple removable drives have been found,\nplease select your SD card drive", map(lambda n: n[0], drives))
@@ -237,6 +242,17 @@ class SceneView(openglGui.glGuiPanel):
                                        drive = drives[0]
                                filename = self._scene._objectList[0].getName() + '.gcode'
                                threading.Thread(target=self._copyFile,args=(self._gcodeFilename, drive[1] + filename, drive[1])).start()
+                       elif connectionEntry is not None:
+                               connection = connectionEntry.connection
+                               if connectionEntry.window is None or not connectionEntry.window:
+                                       connectionEntry.window = printWindow2.printWindow(connection)
+                               connectionEntry.window.Show()
+                               connectionEntry.window.Raise()
+                               if not connection.loadFile(self._gcodeFilename):
+                                       if connection.isPrinting():
+                                               self.notification.message("Cannot start print, because other print still running.")
+                                       else:
+                                               self.notification.message("Failed to start print...")
                        else:
                                self.showSaveGCode()
                if button == 3:
@@ -383,10 +399,10 @@ class SceneView(openglGui.glGuiPanel):
                self._scene.pushFree()
                #self.sceneUpdated()
                if machine == "ultimaker2":
-                       self._selectedObj.setPosition(numpy.array([0.0,-22.5]))
-
+                       #This is bad and Jaime should feel bad!
+                       self._selectedObj.setPosition(numpy.array([0.0,-10.0]))
                        self._selectedObj.scaleUpTo(self._machineSize - numpy.array(profile.calculateObjectSizeOffsets() + [0.0], numpy.float32) * 2 - numpy.array([1,1,1], numpy.float32))
-                       self._selectedObj.setPosition(numpy.array([0.0,-15]))
+                       self._selectedObj.setPosition(numpy.array([0.0,0.0]))
                        self._scene.pushFree()
                else:
                        self._selectedObj.setPosition(numpy.array([0.0, 0.0]))
@@ -495,7 +511,7 @@ class SceneView(openglGui.glGuiPanel):
        def sceneUpdated(self):
                self._sceneUpdateTimer.Start(500, True)
                self._slicer.abortSlicer()
-               self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
+               self._scene.updateSizeOffsets()
                self.QueueRefresh()
 
        def _onRunSlicer(self, e):
@@ -572,7 +588,8 @@ class SceneView(openglGui.glGuiPanel):
                                        else:
                                                obj._loadAnim = None
                                        self._scene.add(obj)
-                                       self._scene.centerAll()
+                                       if not self._scene.checkPlatform(obj):
+                                               self._scene.centerAll()
                                        self._selectObject(obj)
                                        if obj.getScale()[0] < 1.0:
                                                self.notification.message("Warning: Object scaled down.")
@@ -594,7 +611,7 @@ class SceneView(openglGui.glGuiPanel):
        def _selectObject(self, obj, zoom = True):
                if obj != self._selectedObj:
                        self._selectedObj = obj
-                       self.updateProfileToControls()
+                       self.updateModelSettingsToControls()
                        self.updateToolButtons()
                if zoom and obj is not None:
                        newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2])
@@ -610,15 +627,16 @@ class SceneView(openglGui.glGuiPanel):
                if self._isSimpleMode != oldSimpleMode:
                        self._scene.arrangeAll()
                        self.sceneUpdated()
+               self._scene.updateSizeOffsets(True)
                self._machineSize = numpy.array([profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')])
                self._objColors[0] = profile.getPreferenceColour('model_colour')
                self._objColors[1] = profile.getPreferenceColour('model_colour2')
                self._objColors[2] = profile.getPreferenceColour('model_colour3')
                self._objColors[3] = profile.getPreferenceColour('model_colour4')
-               self._scene.setMachineSize(self._machineSize)
-               self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
-               self._scene.setHeadSize(profile.getMachineSettingFloat('extruder_head_size_min_x'), profile.getMachineSettingFloat('extruder_head_size_max_x'), profile.getMachineSettingFloat('extruder_head_size_min_y'), profile.getMachineSettingFloat('extruder_head_size_max_y'), profile.getMachineSettingFloat('extruder_head_size_height'))
+               self._scene.updateMachineDimensions()
+               self.updateModelSettingsToControls()
 
+       def updateModelSettingsToControls(self):
                if self._selectedObj is not None:
                        scale = self._selectedObj.getScale()
                        size = self._selectedObj.getSize()
@@ -830,12 +848,16 @@ class SceneView(openglGui.glGuiPanel):
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
 
        def OnPaint(self,e):
+               connectionEntry = self._printerConnectionManager.getAvailableConnection()
                if machineCom.machineIsConnected():
                        self.printButton._imageID = 6
                        self.printButton._tooltip = _("Print")
-               elif len(removableStorage.getPossibleSDcardDrives()) > 0:
+               elif len(removableStorage.getPossibleSDcardDrives()) > 0 and (connectionEntry is None or connectionEntry.priority < 0):
                        self.printButton._imageID = 2
                        self.printButton._tooltip = _("Toolpath to SD")
+               elif connectionEntry is not None:
+                       self.printButton._imageID = connectionEntry.icon
+                       self.printButton._tooltip = _("Print with %s") % (connectionEntry.name)
                else:
                        self.printButton._imageID = 3
                        self.printButton._tooltip = _("Save toolpath")
@@ -1149,19 +1171,31 @@ void main(void)
                                glPopMatrix()
                else:
                        #Draw the object box-shadow, so you can see where it will collide with other objects.
-                       if self._selectedObj is not None and len(self._scene.objects()) > 1:
-                               size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
-                               glPushMatrix()
-                               glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0)
+                       if self._selectedObj is not None:
                                glEnable(GL_BLEND)
                                glEnable(GL_CULL_FACE)
-                               glColor4f(0,0,0,0.12)
-                               glBegin(GL_QUADS)
-                               glVertex3f(-size[0],  size[1], 0.1)
-                               glVertex3f(-size[0], -size[1], 0.1)
-                               glVertex3f( size[0], -size[1], 0.1)
-                               glVertex3f( size[0],  size[1], 0.1)
+                               glColor4f(0,0,0,0.16)
+                               glDepthMask(False)
+                               for obj in self._scene.objects():
+                                       glPushMatrix()
+                                       glTranslatef(obj.getPosition()[0], obj.getPosition()[1], 0)
+                                       glBegin(GL_TRIANGLE_FAN)
+                                       for p in obj._boundaryHull[::-1]:
+                                               glVertex3f(p[0], p[1], 0)
+                                       glEnd()
+                                       glPopMatrix()
+                               glPushMatrix()
+                               glColor4f(0,0,0,0.06)
+                               glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0)
+                               glBegin(GL_TRIANGLE_FAN)
+                               for p in self._selectedObj._printAreaHull[::-1]:
+                                       glVertex3f(p[0], p[1], 0)
+                               glEnd()
+                               glBegin(GL_TRIANGLE_FAN)
+                               for p in self._selectedObj._headAreaMinHull[::-1]:
+                                       glVertex3f(p[0], p[1], 0)
                                glEnd()
+                               glDepthMask(True)
                                glDisable(GL_CULL_FACE)
                                glPopMatrix()
 
@@ -1233,7 +1267,7 @@ void main(void)
                size = [profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')]
 
                machine = profile.getMachineSetting('machine_type')
-               if profile.getMachineSetting('machine_type').startswith('ultimaker'):
+               if machine.startswith('ultimaker'):
                        if machine not in self._platformMesh:
                                meshes = meshLoader.loadMeshes(resources.getPathForMesh(machine + '_platform.stl'))
                                if len(meshes) > 0:
@@ -1298,104 +1332,51 @@ void main(void)
                        glVertex3f(-size[0] / 2, -size[1] / 2+10, 0)
                        glEnd()
 
-               #Cornerpoints for big blue square
-               v0 = [ size[0] / 2, size[1] / 2, size[2]]
-               v1 = [ size[0] / 2,-size[1] / 2, size[2]]
-               v2 = [-size[0] / 2, size[1] / 2, size[2]]
-               v3 = [-size[0] / 2,-size[1] / 2, size[2]]
-               v4 = [ size[0] / 2, size[1] / 2, 0]
-               v5 = [ size[0] / 2,-size[1] / 2, 0]
-               v6 = [-size[0] / 2, size[1] / 2, 0]
-               v7 = [-size[0] / 2,-size[1] / 2, 0]
-
-               vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
-               glEnableClientState(GL_VERTEX_ARRAY)
-               glVertexPointer(3, GL_FLOAT, 3*4, vList)
-
-               glColor4ub(5, 171, 231, 64)
-               glDrawArrays(GL_QUADS, 0, 4)
-               glColor4ub(5, 171, 231, 96)
-               glDrawArrays(GL_QUADS, 4, 8)
+               glDepthMask(False)
+
+               polys = profile.getMachineSizePolygons()
+               height = profile.getMachineSettingFloat('machine_height')
+               glBegin(GL_QUADS)
+               for n in xrange(0, len(polys[0])):
+                       if n % 2 == 0:
+                               glColor4ub(5, 171, 231, 96)
+                       else:
+                               glColor4ub(5, 171, 231, 64)
+                       glVertex3f(polys[0][n][0], polys[0][n][1], height)
+                       glVertex3f(polys[0][n][0], polys[0][n][1], 0)
+                       glVertex3f(polys[0][n-1][0], polys[0][n-1][1], 0)
+                       glVertex3f(polys[0][n-1][0], polys[0][n-1][1], height)
+               glEnd()
                glColor4ub(5, 171, 231, 128)
-               glDrawArrays(GL_QUADS, 12, 8)
-               glDisableClientState(GL_VERTEX_ARRAY)
+               glBegin(GL_TRIANGLE_FAN)
+               for p in polys[0][::-1]:
+                       glVertex3f(p[0], p[1], height)
+               glEnd()
 
                #Draw checkerboard
-               sx = self._machineSize[0]
-               sy = self._machineSize[1]
-               for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
-                       for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
-                               x1 = x * 10
-                               x2 = x1 + 10
-                               y1 = y * 10
-                               y2 = y1 + 10
-                               x1 = max(min(x1, sx/2), -sx/2)
-                               y1 = max(min(y1, sy/2), -sy/2)
-                               x2 = max(min(x2, sx/2), -sx/2)
-                               y2 = max(min(y2, sy/2), -sy/2)
-                               #Black or "white"  checker
-                               if (x & 1) == (y & 1):
-                                       glColor4ub(5, 171, 231, 127)
-                               else:
-                                       glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
-                               glBegin(GL_QUADS)
-                               glVertex3f(x1, y1, -0.02) #Draw bit below z0 to prevent zfighting.
-                               glVertex3f(x2, y1, -0.02)
-                               glVertex3f(x2, y2, -0.02)
-                               glVertex3f(x1, y2, -0.02)
-                               glEnd()
-
-               if machine == 'ultimaker2':
-
-                       glColor4ub(127, 127, 127, 200)
-                       #if UM2, draw bat-area zone for head. THe head can't stop there, because its bat-area.
-                       #UpperRight
-                       clipWidth = 50
-                       clipHeight = 10
-                       posX = sx / 2 - clipWidth
-                       posY = sy / 2 - clipHeight
-                       glBegin(GL_QUADS)
-                       glVertex3f(posX, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY+clipHeight, 0.1)
-                       glVertex3f(posX, posY+clipHeight, 0.1)
-                       glEnd()
-                       #UpperLeft
-                       clipWidth = 55
-                       clipHeight = 10
-                       posX = -sx / 2
-                       posY = sy / 2 - clipHeight
-                       glBegin(GL_QUADS)
-                       glVertex3f(posX, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY+clipHeight, 0.1)
-                       glVertex3f(posX, posY+clipHeight, 0.1)
+               if self._platformTexture is None:
+                       self._platformTexture = opengl.loadGLTexture('checkerboard.png')
+                       glBindTexture(GL_TEXTURE_2D, self._platformTexture)
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
+               glColor4f(1,1,1,0.5)
+               glBindTexture(GL_TEXTURE_2D, self._platformTexture)
+               glEnable(GL_TEXTURE_2D)
+               glBegin(GL_TRIANGLE_FAN)
+               for p in polys[0]:
+                       glTexCoord2f(p[0]/20, p[1]/20)
+                       glVertex3f(p[0], p[1], 0)
+               glEnd()
+               glDisable(GL_TEXTURE_2D)
+               glColor4ub(127, 127, 127, 200)
+               for poly in polys[1:]:
+                       glBegin(GL_TRIANGLE_FAN)
+                       for p in poly:
+                               glTexCoord2f(p[0]/20, p[1]/20)
+                               glVertex3f(p[0], p[1], 0)
                        glEnd()
-                       #LowerRight
-                       clipWidth = 50
-                       clipHeight = 10
-                       posX = sx / 2 - clipWidth
-                       posY = -sy / 2
-                       glBegin(GL_QUADS)
-                       glVertex3f(posX, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY+clipHeight, 0.1)
-                       glVertex3f(posX, posY+clipHeight, 0.1)
-                       glEnd()
-                       #LowerLeft
-                       clipWidth = 55
-                       clipHeight = 10
-                       posX = -sx / 2
-                       posY = -sy / 2
-                       glBegin(GL_QUADS)
-                       glVertex3f(posX, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY, 0.1)
-                       glVertex3f(posX+clipWidth, posY+clipHeight, 0.1)
-                       glVertex3f(posX, posY+clipHeight, 0.1)
-                       glEnd()
-
-
 
+               glDepthMask(True)
                glDisable(GL_BLEND)
                glDisable(GL_CULL_FACE)