Exemple #1
0
    def __init__(self, app=None):
        QFrame.__init__(self, None)

        self.svgGLViewer = None

        self.layerSliderValue = 0.5

        # load the draft.ui, a UI defination created on QT Creator.
        self.currentCom = ""

        USE_QTUITOOLS=False
        if USE_QTUITOOLS:
            import PySide.QtUiTools as QtUiTools
            QUiLoader = QtUiTools.QUiLoader()
            self.ui = QUiLoader.load('draft.ui')
        else:
            self.ui = draft_ui.Ui_Frame()
            self.ui.setupUi( self )
            def __findChild( *args):
                global _self
                _self = self
                ret =  eval("_self.ui.%s" % args[1])
                return ret
            self.ui.findChild = __findChild

        # main reprap object to comunicate with arduino
        self.reprap = reprap.device() #.cartesianClass()

        # fill combobox with available serial device names
        self.coms = self.ui.findChild(QComboBox, 'COMS')
        for each in self.reprap.comList:
            self.coms.addItem ( each, userData=self.reprap.comList[each] )

        # fill combobox with available displays to use for print ( the display connected to the projector)
        self.displays = self.ui.findChild(QComboBox, 'printDisplay')
        displayCount=1
        for each in pyglet.window.get_platform().get_default_display().get_screens():
            try: name = each.get_device_name().replace('\\\\.\\','')
            except:
                name = 'Display%d' % displayCount
                displayCount += 1
            menuOption = 'use %s-%dx%d' % (name, each.width, each.height)
            #print dir(each)
            print self.displays
            self.displays.addItem ( menuOption, each )

        # connect buttons to methods on this class
        self.connect(self.ui.findChild(QPushButton, 'loadGeo') , SIGNAL('clicked()'), lambda: self.loadGeo() )
#        self.connect(self.ui.findChild(QPushButton, 'sliceButton') , SIGNAL('clicked()'), lambda: self.sliceButton() )
        self.connect(self.ui.findChild(QPushButton, 'printButton') , SIGNAL('clicked()'), lambda: self.printButton() )
        self.connect(self.ui.findChild(QPushButton, 'connect') , SIGNAL('clicked()'), lambda: self.connectButton() )
        self.connect(self.ui.findChild(QToolButton, 'refil') , SIGNAL('clicked()'), lambda: self.refilButton() )

        self.connect(self.ui.findChild(QDial, 'sliceDial') , SIGNAL('sliderMoved(int)'), self.layerSlider )
#        self.connect(self.ui.findChild(QSlider, 'layer') , SIGNAL('sliderMoved(int)'), self.layerSlider )
#        self.connect(self.ui.findChild(QSlider, 'layer') , SIGNAL('valueChanged(int)'), self.layerSlider )


        # store those as direct children for easy access and save in config file.
        self.invertNormals          = self.ui.findChild(QCheckBox, 'invertNormals')
        self.expTime                = self.ui.findChild(QDoubleSpinBox, 'expTime')
        self.sliceThickness         = self.ui.findChild(QDoubleSpinBox, 'sliceThickness')
        self.axisSpeedSpinBox       = self.ui.findChild(QDoubleSpinBox, 'axisSpeed')

        self.connect(self.sliceThickness, SIGNAL('valueChanged(double)'), self.refreshGPU )
        self.connect(self.invertNormals, SIGNAL('clicked()'), self.refreshGPU )

        self.connect(self.axisSpeedSpinBox , SIGNAL('valueChanged(double)'), lambda: self.axisSpeed() )
        #self.axisSpeedSpinBox.valueChanged[float].connect(lambda: self.axisSpeed())
        self.axisSpeed()

        self.connect(self.ui.findChild(QToolButton, 'm10') , SIGNAL('clicked()'), lambda: self.moveZ(-10, True) )
        self.connect(self.ui.findChild(QToolButton, 'm1')  , SIGNAL('clicked()'), lambda: self.moveZ(-1, True) )
        self.connect(self.ui.findChild(QToolButton, 'm01') , SIGNAL('clicked()'), lambda: self.moveZ(-0.1, True) )

        self.connect(self.ui.findChild(QToolButton, 'p10') , SIGNAL('clicked()'), lambda: self.moveZ(10, True) )
        self.connect(self.ui.findChild(QToolButton, 'p1')  , SIGNAL('clicked()'), lambda: self.moveZ(1, True) )
        self.connect(self.ui.findChild(QToolButton, 'p01') , SIGNAL('clicked()'), lambda: self.moveZ(0.1, True) )

        #translate model
        self.modelTransform = struct()
        self.modelTransform.tx = self.ui.findChild(QDoubleSpinBox, 'modelMoveX')
        self.modelTransform.ty = self.ui.findChild(QDoubleSpinBox, 'modelMoveY')
        self.modelTransform.tz = self.ui.findChild(QDoubleSpinBox, 'modelMoveZ')
        self.modelTransform.rx = self.ui.findChild(QDoubleSpinBox, 'modelRotateX')
        self.modelTransform.ry = self.ui.findChild(QDoubleSpinBox, 'modelRotateY')
        self.modelTransform.rz = self.ui.findChild(QDoubleSpinBox, 'modelRotateZ')
        self.modelTransform.s = self.ui.findChild(QDoubleSpinBox, 'modelScale')

        def resetFunction( method, value, *sliders ):
            method( value,value,value, set=True)
            for each in sliders:
                each.setValue( value )

        moveFunction = lambda: self.moveModel(self.modelTransform.tx.value(), self.modelTransform.tz.value(), self.modelTransform.ty.value())
        self.connect(self.modelTransform.tx , SIGNAL('valueChanged(double)'), moveFunction )
        self.connect(self.modelTransform.ty , SIGNAL('valueChanged(double)'), moveFunction )
        self.connect(self.modelTransform.tz , SIGNAL('valueChanged(double)'), moveFunction )
        self.connect(self.ui.findChild(QPushButton, 'modelMoveReset') , SIGNAL('clicked()'), lambda: resetFunction( self.moveModel, 0.0, self.modelTransform.tx, self.modelTransform.ty, self.modelTransform.tz ) )

        rotateFunction = lambda: self.rotateModel(self.modelTransform.rx.value(), self.modelTransform.rz.value(), self.modelTransform.ry.value())
        self.connect(self.modelTransform.rx , SIGNAL('valueChanged(double)'), rotateFunction )
        self.connect(self.modelTransform.ry , SIGNAL('valueChanged(double)'), rotateFunction )
        self.connect(self.modelTransform.rz , SIGNAL('valueChanged(double)'), rotateFunction )
        self.connect(self.ui.findChild(QPushButton, 'modelRotateReset') , SIGNAL('clicked()'), lambda: resetFunction( self.rotateModel, 0.0, self.modelTransform.rx, self.modelTransform.ry, self.modelTransform.rz ) )

        scaleFunction = lambda: self.scaleModel(self.modelTransform.s.value(), self.modelTransform.s.value(), self.modelTransform.s.value())
        self.connect(self.modelTransform.s , SIGNAL('valueChanged(double)'), scaleFunction )
        self.connect(self.ui.findChild(QPushButton, 'modelScaleReset') , SIGNAL('clicked()'), lambda: resetFunction( self.scaleModel, 1.0, self.modelTransform.s ) )



        # VERY IMPORTANT!!! we MUST schedule glFrame to be deleted or else we get a thread fatal error in python!
        # this fix "Fatal Python error: PyEval_SaveThread: NULL tstate" error when using QtOpenGl Widgets!!
        def fix_PyEval_SaveThread_Fatal_Error_on_exit():
            self.glFrame.deleteLater()
            self.saveConfig()
        app.connect( app, SIGNAL('aboutToQuit()'), fix_PyEval_SaveThread_Fatal_Error_on_exit )

        # get light icon...
        self.comLight = self.ui.findChild(QGroupBox, 'ConnectLight')
        self.comLightState = 0
        self.setComIcon()

        # create a new GLWidget, parented to the ui main frame
        self.glFrame = GLWidget( self.ui.findChild(QWidget, 'frame') )
        self.glFrame.app = app

        # unit setup
        self.modelUnit = self.ui.findChild(QComboBox, 'modelUnit')
        unitz = prefs.units()
        unitzIndez = unitz.keys()
        unitzIndez.sort()
        for each in unitzIndez:
            self.modelUnit.addItem ( each, unitz[each] )
        self.modelUnit.setCurrentIndex( self.modelUnit.findText( 'mm' ) )
        def setCurrentUnit():
            self.glFrame.unit = unitz[str(self.modelUnit.currentText())]
            self.refreshGPU()
        self.connect( self.modelUnit , SIGNAL('currentIndexChanged(QString)'), setCurrentUnit )


        # load a default mesh into the opengl viewport
#        self.glFrame.addMesh( mesh('meshes/teapot.obj') )

        # add the glWidget to the framelayout of the main frame, so it resizes correctly.
        self.ui.findChild(QObject, 'frameLayout').addWidget( self.glFrame )

#        self.status = QStatusBar()
#        self.ui.findChild(QObject, 'statusBar').addWidget( self.status )
#        self.status.showMessage("Ready")

        self.logWin = self.ui.findChild(QPlainTextEdit, 'log')
        self.connect(self.logWin , SIGNAL('textChanged()'), lambda: self.logAppended() )
        self.logWin.setWordWrapMode( QTextOption.NoWrap )

        self.fileName = 'meshes/.'
        self.configFile = 'draft.config'

        self.loadConfig()

#        stdoutLog = log()
#        stderrLog = log(error=True)

        self.moveModel(0,0,0, set=True)
        self.rotateModel(0,0,0, set=True)
        self.scaleModel(1,1,1, set=True)
Exemple #2
0
class win(QFrame):
    def __init__(self, app=None):
        QFrame.__init__(self, None)

        self.svgGLViewer = None

        self.layerSliderValue = 0.5

        # load the draft.ui, a UI defination created on QT Creator.
        self.currentCom = ""

        USE_QTUITOOLS=False
        if USE_QTUITOOLS:
            import PySide.QtUiTools as QtUiTools
            QUiLoader = QtUiTools.QUiLoader()
            self.ui = QUiLoader.load('draft.ui')
        else:
            self.ui = draft_ui.Ui_Frame()
            self.ui.setupUi( self )
            def __findChild( *args):
                global _self
                _self = self
                ret =  eval("_self.ui.%s" % args[1])
                return ret
            self.ui.findChild = __findChild

        # main reprap object to comunicate with arduino
        self.reprap = reprap.device() #.cartesianClass()

        # fill combobox with available serial device names
        self.coms = self.ui.findChild(QComboBox, 'COMS')
        for each in self.reprap.comList:
            self.coms.addItem ( each, userData=self.reprap.comList[each] )

        # fill combobox with available displays to use for print ( the display connected to the projector)
        self.displays = self.ui.findChild(QComboBox, 'printDisplay')
        displayCount=1
        for each in pyglet.window.get_platform().get_default_display().get_screens():
            try: name = each.get_device_name().replace('\\\\.\\','')
            except:
                name = 'Display%d' % displayCount
                displayCount += 1
            menuOption = 'use %s-%dx%d' % (name, each.width, each.height)
            #print dir(each)
            print self.displays
            self.displays.addItem ( menuOption, each )

        # connect buttons to methods on this class
        self.connect(self.ui.findChild(QPushButton, 'loadGeo') , SIGNAL('clicked()'), lambda: self.loadGeo() )
#        self.connect(self.ui.findChild(QPushButton, 'sliceButton') , SIGNAL('clicked()'), lambda: self.sliceButton() )
        self.connect(self.ui.findChild(QPushButton, 'printButton') , SIGNAL('clicked()'), lambda: self.printButton() )
        self.connect(self.ui.findChild(QPushButton, 'connect') , SIGNAL('clicked()'), lambda: self.connectButton() )
        self.connect(self.ui.findChild(QToolButton, 'refil') , SIGNAL('clicked()'), lambda: self.refilButton() )

        self.connect(self.ui.findChild(QDial, 'sliceDial') , SIGNAL('sliderMoved(int)'), self.layerSlider )
#        self.connect(self.ui.findChild(QSlider, 'layer') , SIGNAL('sliderMoved(int)'), self.layerSlider )
#        self.connect(self.ui.findChild(QSlider, 'layer') , SIGNAL('valueChanged(int)'), self.layerSlider )


        # store those as direct children for easy access and save in config file.
        self.invertNormals          = self.ui.findChild(QCheckBox, 'invertNormals')
        self.expTime                = self.ui.findChild(QDoubleSpinBox, 'expTime')
        self.sliceThickness         = self.ui.findChild(QDoubleSpinBox, 'sliceThickness')
        self.axisSpeedSpinBox       = self.ui.findChild(QDoubleSpinBox, 'axisSpeed')

        self.connect(self.sliceThickness, SIGNAL('valueChanged(double)'), self.refreshGPU )
        self.connect(self.invertNormals, SIGNAL('clicked()'), self.refreshGPU )

        self.connect(self.axisSpeedSpinBox , SIGNAL('valueChanged(double)'), lambda: self.axisSpeed() )
        #self.axisSpeedSpinBox.valueChanged[float].connect(lambda: self.axisSpeed())
        self.axisSpeed()

        self.connect(self.ui.findChild(QToolButton, 'm10') , SIGNAL('clicked()'), lambda: self.moveZ(-10, True) )
        self.connect(self.ui.findChild(QToolButton, 'm1')  , SIGNAL('clicked()'), lambda: self.moveZ(-1, True) )
        self.connect(self.ui.findChild(QToolButton, 'm01') , SIGNAL('clicked()'), lambda: self.moveZ(-0.1, True) )

        self.connect(self.ui.findChild(QToolButton, 'p10') , SIGNAL('clicked()'), lambda: self.moveZ(10, True) )
        self.connect(self.ui.findChild(QToolButton, 'p1')  , SIGNAL('clicked()'), lambda: self.moveZ(1, True) )
        self.connect(self.ui.findChild(QToolButton, 'p01') , SIGNAL('clicked()'), lambda: self.moveZ(0.1, True) )

        #translate model
        self.modelTransform = struct()
        self.modelTransform.tx = self.ui.findChild(QDoubleSpinBox, 'modelMoveX')
        self.modelTransform.ty = self.ui.findChild(QDoubleSpinBox, 'modelMoveY')
        self.modelTransform.tz = self.ui.findChild(QDoubleSpinBox, 'modelMoveZ')
        self.modelTransform.rx = self.ui.findChild(QDoubleSpinBox, 'modelRotateX')
        self.modelTransform.ry = self.ui.findChild(QDoubleSpinBox, 'modelRotateY')
        self.modelTransform.rz = self.ui.findChild(QDoubleSpinBox, 'modelRotateZ')
        self.modelTransform.s = self.ui.findChild(QDoubleSpinBox, 'modelScale')

        def resetFunction( method, value, *sliders ):
            method( value,value,value, set=True)
            for each in sliders:
                each.setValue( value )

        moveFunction = lambda: self.moveModel(self.modelTransform.tx.value(), self.modelTransform.tz.value(), self.modelTransform.ty.value())
        self.connect(self.modelTransform.tx , SIGNAL('valueChanged(double)'), moveFunction )
        self.connect(self.modelTransform.ty , SIGNAL('valueChanged(double)'), moveFunction )
        self.connect(self.modelTransform.tz , SIGNAL('valueChanged(double)'), moveFunction )
        self.connect(self.ui.findChild(QPushButton, 'modelMoveReset') , SIGNAL('clicked()'), lambda: resetFunction( self.moveModel, 0.0, self.modelTransform.tx, self.modelTransform.ty, self.modelTransform.tz ) )

        rotateFunction = lambda: self.rotateModel(self.modelTransform.rx.value(), self.modelTransform.rz.value(), self.modelTransform.ry.value())
        self.connect(self.modelTransform.rx , SIGNAL('valueChanged(double)'), rotateFunction )
        self.connect(self.modelTransform.ry , SIGNAL('valueChanged(double)'), rotateFunction )
        self.connect(self.modelTransform.rz , SIGNAL('valueChanged(double)'), rotateFunction )
        self.connect(self.ui.findChild(QPushButton, 'modelRotateReset') , SIGNAL('clicked()'), lambda: resetFunction( self.rotateModel, 0.0, self.modelTransform.rx, self.modelTransform.ry, self.modelTransform.rz ) )

        scaleFunction = lambda: self.scaleModel(self.modelTransform.s.value(), self.modelTransform.s.value(), self.modelTransform.s.value())
        self.connect(self.modelTransform.s , SIGNAL('valueChanged(double)'), scaleFunction )
        self.connect(self.ui.findChild(QPushButton, 'modelScaleReset') , SIGNAL('clicked()'), lambda: resetFunction( self.scaleModel, 1.0, self.modelTransform.s ) )



        # VERY IMPORTANT!!! we MUST schedule glFrame to be deleted or else we get a thread fatal error in python!
        # this fix "Fatal Python error: PyEval_SaveThread: NULL tstate" error when using QtOpenGl Widgets!!
        def fix_PyEval_SaveThread_Fatal_Error_on_exit():
            self.glFrame.deleteLater()
            self.saveConfig()
        app.connect( app, SIGNAL('aboutToQuit()'), fix_PyEval_SaveThread_Fatal_Error_on_exit )

        # get light icon...
        self.comLight = self.ui.findChild(QGroupBox, 'ConnectLight')
        self.comLightState = 0
        self.setComIcon()

        # create a new GLWidget, parented to the ui main frame
        self.glFrame = GLWidget( self.ui.findChild(QWidget, 'frame') )
        self.glFrame.app = app

        # unit setup
        self.modelUnit = self.ui.findChild(QComboBox, 'modelUnit')
        unitz = prefs.units()
        unitzIndez = unitz.keys()
        unitzIndez.sort()
        for each in unitzIndez:
            self.modelUnit.addItem ( each, unitz[each] )
        self.modelUnit.setCurrentIndex( self.modelUnit.findText( 'mm' ) )
        def setCurrentUnit():
            self.glFrame.unit = unitz[str(self.modelUnit.currentText())]
            self.refreshGPU()
        self.connect( self.modelUnit , SIGNAL('currentIndexChanged(QString)'), setCurrentUnit )


        # load a default mesh into the opengl viewport
#        self.glFrame.addMesh( mesh('meshes/teapot.obj') )

        # add the glWidget to the framelayout of the main frame, so it resizes correctly.
        self.ui.findChild(QObject, 'frameLayout').addWidget( self.glFrame )

#        self.status = QStatusBar()
#        self.ui.findChild(QObject, 'statusBar').addWidget( self.status )
#        self.status.showMessage("Ready")

        self.logWin = self.ui.findChild(QPlainTextEdit, 'log')
        self.connect(self.logWin , SIGNAL('textChanged()'), lambda: self.logAppended() )
        self.logWin.setWordWrapMode( QTextOption.NoWrap )

        self.fileName = 'meshes/.'
        self.configFile = 'draft.config'

        self.loadConfig()

#        stdoutLog = log()
#        stderrLog = log(error=True)

        self.moveModel(0,0,0, set=True)
        self.rotateModel(0,0,0, set=True)
        self.scaleModel(1,1,1, set=True)

    def saveConfig(self):
        checkBoxStates = {
            Qt.Unchecked        : 'Qt.Unchecked',
            Qt.PartiallyChecked : 'Qt.PartiallyChecked',
            Qt.Checked          : 'Qt.Checked',
        }
        f = open( self.configFile, 'w' )
        f.write( 'self.currentCom = "%s"\n' % self.currentCom )
        f.write( 'self.fileName = "%s"\n' % self.fileName )
        f.write( 'self.axisSpeedSpinBox.setValue(%s)\n' % str(self.axisSpeedSpinBox.value()) )
        f.write( 'self.sliceThickness.setValue(%s)\n' % str(self.sliceThickness.value()) )
        f.write( 'self.expTime.setValue(%s)\n' % str(self.expTime.value()) )
#        f.write( 'self.startPrintAfterSlice.setCheckState(%s)\n' % checkBoxStates[ self.startPrintAfterSlice.checkState() ] )

        f.flush()
        f.close()

    def loadConfig(self):
        if os.path.exists( self.configFile ):
            for l in open( self.configFile ):
                try:
                    exec( l )
                except:
                    pass

            self.refreshMesh()

    def moveModel(self, x, y, z, set=True):
        if set:
            self.glFrame.moveOBJ = [x,y,z]
        else:
            self.glFrame.moveOBJ[0] += x
            self.glFrame.moveOBJ[1] += y
            self.glFrame.moveOBJ[2] += z
        self.refreshGPU()

    def rotateModel(self, x, y, z, set=True):
        if set:
            self.glFrame.rotateOBJ = [x,y,z]
        else:
            self.glFrame.rotateOBJ[0] += x
            self.glFrame.rotateOBJ[1] += y
            self.glFrame.rotateOBJ[2] += z
        self.refreshGPU()

    def scaleModel(self, x, y, z, set=True):
        if set:
            self.glFrame.scaleOBJ = [x,y,z]
        else:
            self.glFrame.scaleOBJ[0] += x
            self.glFrame.scaleOBJ[1] += y
            self.glFrame.scaleOBJ[2] += z
        self.refreshGPU()


    def logAppended(self):
#        bar = self.logWin.verticalScrollBar()
#        x = bar.value()
#        bar.setValue(x-10)
#        bar.repaint()
#        self.logWin.moveCursor( QTextCursor.Start )
#        self.logWin.repaint()
        self.logWin.ensureCursorVisible()# ( QTextCursor.End )
#        self.logWin.repaint()

    def layerSlider(self, value):
        self.layerSliderValue = float(value)/100.0
        self.refreshGPU()


    def refilButton(self):
        self.glFrame.install_shaders( )
        self.refreshGPU()

    def axisSpeed( self ):
        self.reprap.z.speed( float(self.axisSpeedSpinBox.value()) )

    def moveZ(self, mm, relative=False):
        self.reprap.z.move( mm, relative )

    def arduinoException(self):
        self.disconnect()
        print "arduinoException!!" ; sys.stdout.flush()

    def setComIcon(self, state=None):
        if state:
            self.comLightState = state
        self.comLight.setStyleSheet( comIcon[self.comLightState ] )
#        self.comLight.repaint()

#    def show(self):
#        self.show()


    def disconnect(self):
        self.serialConnected = False
        self.setComIcon(self.serialConnected)
        try:
            self.reprap.close()
        except:
            pass

    def connectButton(self):
        self.currentCom = self.coms.currentText()

        self.disconnect()

        # Initialise serial port, here the first port (0) is used.
        try:
            self.reprap.connect( self.currentCom , 57600 )
        except:
            self.arduinoException()
            return

        self.serialConnected = True
        self.setComIcon(self.serialConnected)

    def homeButton(self):
        try:
            reprap.cartesian.homeReset()
        except:
            self.arduinoException()

    def sliceButton(self):
        pass
#        if not self.svgGLViewer:
#            self.svgGLViewer = glSVG.PygletApp( )

#        self.svgGLViewer.load( self.fileName )
#        self.svgGLViewer.run()

    def printButton(self):
        try:
            reprap.cartesian.homeReset()
        except:
            self.arduinoException()

        #self.glFrame.fullScreen()
        render = printModel.printModel( prefs.cs1, True, self.fileName, self.glFrame.meshs, self.displays.itemData( self.displays.currentIndex() ) )
        render.run()



    def loadGeo(self, *args):
        dialog = QFileDialog(self)
        #dialog.setFileMode(QFileDialog.AnyFile)
        if not self.fileName:
            dialog.setDirectory('meshes')
        else:
            dialog.setDirectory(os.path.dirname(self.fileName))

        dialog.setNameFilter("Images (*.obj *.stl)")

        if dialog.exec_():
            self.fileName = str(dialog.selectedFiles()[0])

            self.refreshMesh()


    def refreshGPU(self):
        if hasattr( self.glFrame, "shader" ):
            print "refreshGPU", self.layerSliderValue
            thickness = float(self.sliceThickness.value())/10000.0
            try:
                self.glFrame.s['slicer'].bind()
                self.glFrame.shader.uniformf( 'layer', self.layerSliderValue )
                self.glFrame.shader.uniformf( 'invertNormals', float(self.invertNormals.checkState()) )
                self.glFrame.s['slicer'].unbind()
            except:
                pass

        self.glFrame.updateGL()


    def refreshMesh( self ):
        if not os.path.exists(self.fileName):
            self.fileName = os.path.abspath( './%s' % self.fileName)
            if not os.path.exists( self.fileName ):
                return
        if not os.path.isfile(self.fileName):
            return
        self.glFrame.addMesh( mesh(self.fileName) )
        self.modelUnit.setCurrentIndex( self.modelUnit.findText( 'mm' ) )
        self.refreshGPU()