chiark / gitweb /
Merge tag '15.01-RC7' into upstream
[cura.git] / Cura / gui / sceneView.py
index 799e92c67c08b98e28b9a049391d0693f75d92b5..3d5bfa280f18f7cf16923b36706c6fd868f7debe 100644 (file)
@@ -49,9 +49,11 @@ class SceneView(openglGui.glGuiPanel):
                self._mouseY = -1
                self._mouseState = None
                self._viewTarget = numpy.array([0,0,0], numpy.float32)
+               self._mouse3Dpos = numpy.array([0,0,0], numpy.float32)
                self._animView = None
                self._animZoom = None
                self._platformMesh = {}
+               self.glReleaseList = []
                self._platformTexture = None
                self._isSimpleMode = True
                self._printerConnectionManager = printerConnectionManager.PrinterConnectionManager()
@@ -101,10 +103,10 @@ class SceneView(openglGui.glGuiPanel):
                openglGui.glLabel(self.scaleForm, _("Uniform scale"), (0,8))
                self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None)
 
-               self.viewSelection = openglGui.glComboButton(self, _("View mode"), [7,19,11,15,23], [_("Normal"), _("Overhang"), _("Transparent"), _("X-Ray"), _("Layers")], (-1,0), self.OnViewChange)
-
-               self.youMagineButton = openglGui.glButton(self, 26, _("Share on YouMagine"), (2,0), lambda button: youmagineGui.youmagineManager(self.GetTopLevelParent(), self._scene))
-               self.youMagineButton.setDisabled(True)
+               self.viewSelection = openglGui.glComboButton(self, _("View mode"), 7, [26,19,11,15,23], [_("Normal"), _("Overhang"), _("Transparent"), _("X-Ray"), _("Layers")], (-1,0), self.OnViewChange, self.OnViewStateChange)
+               self.viewSelection.setDisabled(True)
+               #self.youMagineButton = openglGui.glButton(self, 26, _("Share on YouMagine"), (2,0), lambda button: youmagineGui.youmagineManager(self.GetTopLevelParent(), self._scene))
+               #self.youMagineButton.setDisabled(True)
 
                self.notification = openglGui.glNotification(self, (0, 0))
 
@@ -120,6 +122,19 @@ class SceneView(openglGui.glGuiPanel):
                self.updateToolButtons()
                self.updateProfileToControls()
 
+       def cleanup(self):
+               # Delete all objects first
+               self.OnDeleteAll(None)
+               self._engine.cleanup()
+               if self._objectShader is not None:
+                       self._objectShader.release()
+               if self._objectLoadShader is not None:
+                       self._objectLoadShader.release()
+               if self._objectOverhangShader is not None:
+                       self._objectOverhangShader.release()
+               for obj in self.glReleaseList:
+                       obj.release()
+
        def loadGCodeFile(self, filename):
                self.OnDeleteAll(None)
                #Cheat the engine results to load a GCode file into it.
@@ -129,13 +144,14 @@ class SceneView(openglGui.glGuiPanel):
                self._engine._result.setFinished(True)
                self._engineResultView.setResult(self._engine._result)
                self.printButton.setBottomText('')
+               self.viewSelection.setDisabled(False)
                self.viewSelection.setValue(4)
                self.printButton.setDisabled(False)
-               self.youMagineButton.setDisabled(True)
+               #self.youMagineButton.setDisabled(True)
                self.OnViewChange()
 
        def loadSceneFiles(self, filenames):
-               self.youMagineButton.setDisabled(False)
+               #self.youMagineButton.setDisabled(False)
                #if self.viewSelection.getValue() == 4:
                #       self.viewSelection.setValue(0)
                #       self.OnViewChange()
@@ -180,7 +196,7 @@ class SceneView(openglGui.glGuiPanel):
                        if ignored_types:
                                ignored_types = ignored_types.keys()
                                ignored_types.sort()
-                               self.notification.message("ignored: " + " ".join("*" + type for type in ignored_types))
+                               self.notification.message(_("ignored: ") + " ".join("*" + type for type in ignored_types))
                        mainWindow.updateProfileToAllControls()
                        # now process all the scene files
                        if scene_filenames:
@@ -244,22 +260,34 @@ class SceneView(openglGui.glGuiPanel):
                        if len(removableStorage.getPossibleSDcardDrives()) > 0 and (connectionGroup is None or connectionGroup.getPriority() < 0):
                                drives = removableStorage.getPossibleSDcardDrives()
                                if len(drives) > 1:
-                                       dlg = wx.SingleChoiceDialog(self, "Select SD drive", "Multiple removable drives have been found,\nplease select your SD card drive", map(lambda n: n[0], drives))
-                                       if dlg.ShowModal() != wx.ID_OK:
-                                               dlg.Destroy()
-                                               return
-                                       drive = drives[dlg.GetSelection()]
+                                       choices = map(lambda n: n[0], drives)
+                                       choices += (_("Custom file destination"), )
+                                       title = _("Multiple removable drives have been found")
+                               else:
+                                       choices = [drives[0][0], _("Custom file destination")]
+                                       title = _("A removable drive has been found")
+
+                               dlg = wx.SingleChoiceDialog(self, _("Select destination SD card drive\nYou can also select a custom file to save to"), title, choices)
+                               if dlg.ShowModal() != wx.ID_OK:
                                        dlg.Destroy()
+                                       return
+                               try:
+                                       drive = drives[dlg.GetSelection()]
+                               except:
+                                       drive = None
+                               dlg.Destroy()
+
+                               if drive is None:
+                                       self.showSaveGCode()
                                else:
-                                       drive = drives[0]
-                               filename = self._scene._objectList[0].getName() + profile.getGCodeExtension()
-                               threading.Thread(target=self._saveGCode,args=(drive[1] + filename, drive[1])).start()
+                                       filename = self._scene._objectList[0].getName() + profile.getGCodeExtension()
+                                       threading.Thread(target=self._saveGCode,args=(drive[1] + filename, drive[1])).start()
                        elif connectionGroup is not None:
                                connections = connectionGroup.getAvailableConnections()
                                if len(connections) < 2:
                                        connection = connections[0]
                                else:
-                                       dlg = wx.SingleChoiceDialog(self, "Select the %s connection to use" % (connectionGroup.getName()), "Multiple %s connections found" % (connectionGroup.getName()), map(lambda n: n.getName(), connections))
+                                       dlg = wx.SingleChoiceDialog(self, _("Select the %s connection to use") % (connectionGroup.getName()), _("Multiple %s connections found") % (connectionGroup.getName()), map(lambda n: n.getName(), connections))
                                        if dlg.ShowModal() != wx.ID_OK:
                                                dlg.Destroy()
                                                return
@@ -295,9 +323,9 @@ class SceneView(openglGui.glGuiPanel):
                connection.window.Raise()
                if not connection.loadGCodeData(self._engine.getResult().getGCode()):
                        if connection.isPrinting():
-                               self.notification.message("Cannot start print, because other print still running.")
+                               self.notification.message(_("Cannot start print, because other print still running."))
                        else:
-                               self.notification.message("Failed to start print...")
+                               self.notification.message(_("Failed to start print..."))
 
        def showSaveGCode(self):
                if len(self._scene._objectList) < 1:
@@ -331,22 +359,21 @@ class SceneView(openglGui.glGuiPanel):
                except:
                        import sys, traceback
                        traceback.print_exc()
-                       self.notification.message("Failed to save")
+                       self.notification.message(_("Failed to save"))
                else:
                        if ejectDrive:
-                               self.notification.message("Saved as %s" % (targetFilename), lambda : self._doEjectSD(ejectDrive), 31, 'Eject')
+                               self.notification.message(_("Saved as %s") % (targetFilename), lambda : self._doEjectSD(ejectDrive), 31, 'Eject')
                        elif explorer.hasExplorer():
-                               self.notification.message("Saved as %s" % (targetFilename), lambda : explorer.openExplorer(targetFilename), 4, 'Open folder')
+                               self.notification.message(_("Saved as %s") % (targetFilename), lambda : explorer.openExplorer(targetFilename), 4, _('Open folder'))
                        else:
-                               self.notification.message("Saved as %s" % (targetFilename))
+                               self.notification.message(_("Saved as %s") % (targetFilename))
                self.printButton.setProgressBar(None)
-               self._engine.getResult().submitInfoOnline()
 
        def _doEjectSD(self, drive):
                if removableStorage.ejectDrive(drive):
-                       self.notification.message('You can now eject the card.')
+                       self.notification.message(_('You can now eject the card.'))
                else:
-                       self.notification.message('Safe remove failed...')
+                       self.notification.message(_('Safe remove failed...'))
 
        def _showEngineLog(self):
                dlg = wx.TextEntryDialog(self, _("The slicing engine reported the following"), _("Engine log..."), '\n'.join(self._engine.getResult().getLog()), wx.TE_MULTILINE | wx.OK | wx.CENTRE)
@@ -400,6 +427,9 @@ class SceneView(openglGui.glGuiPanel):
                self._engineResultView.setEnabled(self.viewMode == 'gcode')
                self.QueueRefresh()
 
+       def OnViewStateChange(self, state):
+               self._engineResultView.layerSelect.setHidden(self.viewMode != 'gcode' or state)
+
        def OnRotateReset(self, button):
                if self._selectedObj is None:
                        return
@@ -483,6 +513,8 @@ class SceneView(openglGui.glGuiPanel):
                        self._deleteObject(self._scene.objects()[0])
                self._animView = openglGui.animation(self, self._viewTarget.copy(), numpy.array([0,0,0], numpy.float32), 0.5)
                self._engineResultView.setResult(None)
+               self.viewSelection.setDisabled(True)
+               self.printButton.setDisabled(True)
 
        def OnMultiply(self, e):
                if self._focusObj is None:
@@ -505,7 +537,8 @@ class SceneView(openglGui.glGuiPanel):
                        if n > cnt:
                                break
                if n <= cnt:
-                       self.notification.message("Could not create more than %d items" % (n - 1))
+                       self.notification.message(_("Could not create more than %d items") % (n - 1))
+               self.notification.message(_("Could not create more than %d items") % (n - 1))
                self._scene.remove(newObj)
                self._scene.centerAll()
                self.sceneUpdated()
@@ -561,6 +594,7 @@ class SceneView(openglGui.glGuiPanel):
                        if self.printButton.getProgressBar() is not None and progressValue >= 0.0 and abs(self.printButton.getProgressBar() - progressValue) < 0.01:
                                return
                self.printButton.setDisabled(not finished)
+               self.viewSelection.setDisabled(not finished)
                if progressValue >= 0.0:
                        self.printButton.setProgressBar(progressValue)
                else:
@@ -604,7 +638,7 @@ class SceneView(openglGui.glGuiPanel):
                                                self._scene.centerAll()
                                        self._selectObject(obj)
                                        if obj.getScale()[0] < 1.0:
-                                               self.notification.message("Warning: Object scaled down.")
+                                               self.notification.message(_("Warning: Object scaled down."))
                self.sceneUpdated()
 
        def _deleteObject(self, obj):
@@ -618,6 +652,9 @@ class SceneView(openglGui.glGuiPanel):
                                self.glReleaseList.append(m.vbo)
                if len(self._scene.objects()) == 0:
                        self._engineResultView.setResult(None)
+                       self.printButton.setDisabled(True)
+                       self.viewSelection.setDisabled(True)
+                       self.printButton.setBottomText('')
                import gc
                gc.collect()
                self.sceneUpdated()
@@ -893,7 +930,8 @@ class SceneView(openglGui.glGuiPanel):
                glDisable(GL_BLEND)
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
 
-               glClearColor(0.8, 0.8, 0.8, 1.0)
+               #scene background color
+               glClearColor(0.85, 0.85, 0.85, 1.0)
                glClearStencil(0)
                glClearDepth(1.0)
 
@@ -913,7 +951,8 @@ class SceneView(openglGui.glGuiPanel):
                        self.printButton._tooltip = _("Toolpath to SD")
                elif connectionGroup is not None:
                        self.printButton._imageID = connectionGroup.getIconID()
-                       self.printButton._tooltip = _("Print with %s") % (connectionGroup.getName())
+                       #self.printButton._tooltip = _("Print with %s") % (connectionGroup.getName())
+                       self.printButton._tooltip = _("Print/Control")
                else:
                        self.printButton._imageID = 3
                        self.printButton._tooltip = _("Save toolpath")
@@ -1130,7 +1169,8 @@ class SceneView(openglGui.glGuiPanel):
                        glEnable(GL_BLEND)
                        if self._objectLoadShader is not None:
                                self._objectLoadShader.bind()
-                               glColor4f(0.2, 0.6, 1.0, 1.0)
+                               #Model color during load animation
+                               glColor4ub(177, 205, 54, 255)
                                for obj in self._scene.objects():
                                        if obj._loadAnim is None:
                                                continue
@@ -1238,7 +1278,8 @@ class SceneView(openglGui.glGuiPanel):
 
                size = [profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'), profile.getMachineSettingFloat('machine_height')]
 
-               machine_type = profile.getMachineSetting('machine_type')
+               #Due to NC licensing of the stl files, temporarily removing platform mesh loading for Ultimaker and Witbox
+               '''machine_type = profile.getMachineSetting('machine_type')
                if machine_type not in self._platformMesh:
                        self._platformMesh[machine_type] = None
 
@@ -1325,17 +1366,18 @@ class SceneView(openglGui.glGuiPanel):
                                glDisable(GL_TEXTURE_2D)
                                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                                glPopMatrix()
-               else:
-                       glColor4f(0,0,0,1)
-                       glLineWidth(3)
-                       glBegin(GL_LINES)
-                       glVertex3f(-size[0] / 2, -size[1] / 2, 0)
-                       glVertex3f(-size[0] / 2, -size[1] / 2, 10)
-                       glVertex3f(-size[0] / 2, -size[1] / 2, 0)
-                       glVertex3f(-size[0] / 2+10, -size[1] / 2, 0)
-                       glVertex3f(-size[0] / 2, -size[1] / 2, 0)
-                       glVertex3f(-size[0] / 2, -size[1] / 2+10, 0)
-                       glEnd()
+               else:'''
+               # until glEnd() goes inside the else
+               glColor4f(0,0,0,1)
+               glLineWidth(3)
+               glBegin(GL_LINES)
+               glVertex3f(-size[0] / 2, -size[1] / 2, 0)
+               glVertex3f(-size[0] / 2, -size[1] / 2, 10)
+               glVertex3f(-size[0] / 2, -size[1] / 2, 0)
+               glVertex3f(-size[0] / 2+10, -size[1] / 2, 0)
+               glVertex3f(-size[0] / 2, -size[1] / 2, 0)
+               glVertex3f(-size[0] / 2, -size[1] / 2+10, 0)
+               glEnd()
 
                glDepthMask(False)
 
@@ -1347,11 +1389,11 @@ class SceneView(openglGui.glGuiPanel):
                for n in xrange(0, len(polys[0])):
                        if not circular:
                                if n % 2 == 0:
-                                       glColor4ub(5, 171, 231, 96)
+                                       glColor4ub(210, 235, 103, 100)
                                else:
-                                       glColor4ub(5, 171, 231, 64)
+                                       glColor4ub(223, 241, 145, 100)
                        else:
-                               glColor4ub(5, 171, 231, 96)
+                               glColor4ub(223, 241, 145, 100)
 
                        glVertex3f(polys[0][n][0], polys[0][n][1], height)
                        glVertex3f(polys[0][n][0], polys[0][n][1], 0)
@@ -1360,7 +1402,7 @@ class SceneView(openglGui.glGuiPanel):
                glEnd()
 
                #Draw top of build volume.
-               glColor4ub(5, 171, 231, 128)
+               glColor4ub(183, 209, 90, 100)
                glBegin(GL_TRIANGLE_FAN)
                for p in polys[0][::-1]:
                        glVertex3f(p[0], p[1], height)
@@ -1372,7 +1414,8 @@ class SceneView(openglGui.glGuiPanel):
                        glBindTexture(GL_TEXTURE_2D, self._platformTexture)
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
-               glColor4f(1,1,1,0.5)
+               #Dark checkerboard color
+               glColor4f(1,1,1,0.7)
                glBindTexture(GL_TEXTURE_2D, self._platformTexture)
                glEnable(GL_TEXTURE_2D)
                glBegin(GL_TRIANGLE_FAN)
@@ -1420,7 +1463,7 @@ class SceneView(openglGui.glGuiPanel):
 #TODO: Remove this or put it in a seperate file
 class shaderEditor(wx.Frame):
        def __init__(self, parent, callback, v, f):
-               super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+               super(shaderEditor, self).__init__(parent, title=_("Shader editor"), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
                self._callback = callback
                s = wx.BoxSizer(wx.VERTICAL)
                self.SetSizer(s)