コード例 #1
0
 def set_label(self, new_name):
     if self.initSize == Vector():
         self.size = Vector()
     self.name = new_name
     self.buildCaption()        
     #  It's after buildCaption() because self.size is decided only after buildCaption() if size=(0,0,0)
     self.radius = self.size.length()/2
コード例 #2
0
ファイル: Particles3D.py プロジェクト: thangduong/kamaelia
    def draw(self):
        """Draw sphere particle."""
        hs = self.radius
        glColor4f(self.sidecurcolour[0] / 256.0, self.sidecurcolour[1] / 256.0,
                  self.sidecurcolour[2] / 256.0, 0.5)

        # Create a quadratic object for sphere rendering
        quadratic = gluNewQuadric()
        gluQuadricNormals(quadratic, GLU_SMOOTH)
        gluQuadricTexture(quadratic, GL_TRUE)

        # Add texture
        glEnable(GL_TEXTURE_2D)
        glBindTexture(GL_TEXTURE_2D, self.texID)
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)

        # Draw sphere
        gluSphere(quadratic, hs, 32, 32)
        #glutSolidSphere(hs,32,32)

        glDisable(GL_TEXTURE_2D)

        # Draw links
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadMatrixf(self.linkTransform.getMatrix())
        for p in self.bondedTo:
            glBegin(GL_LINES)
            glVertex3f(*self.initialpos.toTuple())
            glVertex3f(*(Vector(*p.pos) - Vector(*self.pos)).toTuple())
            glEnd()
        glPopMatrix()
コード例 #3
0
    def buildCaption(self):
        """Pre-render the text to go on the label."""
        # Text is rendered to self.image
        if self.pic is not None:
            if self.pic.find('://') != -1 and not os.path.exists(self.pic):
                """ FIXME: either use thread to wrap urlopen or kamaelia HTTP components 
                in case urlopen is blocked """
                fObject = urlopen(self.pic)
                picData = fObject.read()
                pic = StringIO(picData)
            else:
                pic = self.pic
            self.image = pygame.image.load(pic).convert()
        else:
            pygame.font.init()
            font = pygame.font.Font(None, self.fontsize)
            self.image = font.render(self.name,True, self.foregroundColour, )
        
        if self.size != Vector(0,0,0):
            texsize = (self.size.x*self.pixelscaling, self.size.y*self.pixelscaling)
        else:
            texsize = ( self.image.get_width()+2*self.margin, self.image.get_height()+2*self.margin )
            self.size=Vector(texsize[0]/float(self.pixelscaling), texsize[1]/float(self.pixelscaling), self.thickness)

        # create power of 2 dimensioned surface
        pow2size = (int(2**(math.ceil(math.log(texsize[0]+2*self.margin, 2)))), int(2**(math.ceil(math.log(texsize[1]+2*self.margin, 2)))))
        textureSurface = pygame.Surface(pow2size)
        textureSurface.fill( self.backgroundColour )
        # determine texture coordinates
        self.tex_w = float(texsize[0])/pow2size[0]
        self.tex_h = float(texsize[1])/pow2size[1]
        # copy image data to pow2surface
        dest = ( max((texsize[0]-self.image.get_width())/2, 0), max((texsize[1]-self.image.get_height())/2, 0) )
        textureSurface.blit(self.image, dest)
#        textureSurface.set_alpha(128)
        textureSurface = textureSurface.convert_alpha()

        # read pixel data
        textureData = pygame.image.tostring(textureSurface, "RGBX", 1)
        #print self.image.get_width(), self.image.get_height()
        #print textureSurface.get_width(), textureSurface.get_height()
        #print textureData

        self.texID = glGenTextures(1)
        # create texture
        glEnable(GL_TEXTURE_2D)
        glBindTexture(GL_TEXTURE_2D, self.texID)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureSurface.get_width(), textureSurface.get_height(), 0,
                        GL_RGBA, GL_UNSIGNED_BYTE, textureData );
        glDisable(GL_TEXTURE_2D)
コード例 #4
0
ファイル: Particles3D.py プロジェクト: thangduong/kamaelia
    def __init__(self, position=(-1, 0, -10), ID='', **argd):
        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
        super(Particle3D, self).__init__(position=position, ID=ID)

        self.pos = position
        self.initSize = Vector(*argd.get("size", (0, 0, 0)))

        self.selected = False

        self.bgcolour = argd.get("bgcolour", (230, 230, 230))
        self.fgcolour = argd.get("fgcolour", (0, 0, 0))
        self.sidecolour = argd.get("sidecolour", (200, 200, 244))

        self.bgcolourselected = argd.get("bgcolourselected", (0, 0, 0))
        self.fgcolourselected = argd.get("fgcolourselected", (244, 244, 244))
        self.sidecolourselected = argd.get("sidecolourselected", (0, 0, 100))

        self.margin = argd.get("margin", 8)
        self.fontsize = argd.get("fontsize", 50)
        self.pixelscaling = argd.get("pixelscaling", 100)
        self.thickness = argd.get("thickness", 0.3)

        # For picture texture
        self.image = argd.get("image", None)
        # For remote picture
        self.imageIO = None

        name = argd.get("name", "NoName")
        self.set_label(name)

        # For rotation and scaling
        self.drotation = Vector()
        self.scaling = Vector(*argd.get("scaling", (1, 1, 1)))

        # For detection of changes
        self.oldpos = self.initialpos = Vector()
        self.oldscaling = Vector()

        # For transformation matrix multiplication
        # Store all transformations
        self.transform = Transform()
        # Specially store link transformations because link doesn't do rotation and scaling
        self.linkTransform = Transform()
        # Store all previous transformations to be multiplied with the current one
        self.oldrotTransform = Transform()

        # For redraw detection
        self.needRedraw = True

        # For drag handling
        self.oldpoint = None
コード例 #5
0
 def rotateParticles(self, particles, dAngle):
     """\
     Rotate the particles around their common centre dAngle degree.
     Particles is a list; dAngle is a triple tuple of degree.
     If particles are given an empty list, rotate all particles instead.
     """
     if particles == []:
         particles = self.currentDisplayedPhysics.particles
     centrePoint = Vector()
     for particle in particles:
         posVector = Vector(*particle.pos)
         centrePoint += posVector
     centrePoint /= len(particles)
     if dAngle[0] != 0:  # Rotate around x axis
         for particle in particles:
             posVector = Vector(*particle.pos)
             relativePosVector = posVector - centrePoint
             radius = (relativePosVector.z * relativePosVector.z +
                       relativePosVector.y * relativePosVector.y)**0.5
             newAngle = (
                 math.atan2(relativePosVector.z, relativePosVector.y) +
                 dAngle[0] * math.pi / 180)
             particle.pos = (posVector.x,
                             radius * math.cos(newAngle) + centrePoint.y,
                             radius * math.sin(newAngle) + centrePoint.z)
             particle.drotation += Vector(dAngle[0], 0, 0)
     if dAngle[1] != 0:  # Rotate around y axis
         for particle in particles:
             posVector = Vector(*particle.pos)
             relativePosVector = posVector - centrePoint
             radius = (relativePosVector.z * relativePosVector.z +
                       relativePosVector.x * relativePosVector.x)**0.5
             newAngle = (
                 math.atan2(relativePosVector.z, relativePosVector.x) +
                 dAngle[1] * math.pi / 180)
             particle.pos = (radius * math.cos(newAngle) + centrePoint.x,
                             posVector.y,
                             radius * math.sin(newAngle) + centrePoint.z)
             particle.drotation += Vector(0, -dAngle[1], 0)
     if dAngle[2] != 0:  # Rotate around z axis
         for particle in particles:
             posVector = Vector(*particle.pos)
             relativePosVector = posVector - centrePoint
             radius = (relativePosVector.x * relativePosVector.x +
                       relativePosVector.y * relativePosVector.y)**0.5
             newAngle = (
                 math.atan2(relativePosVector.y, relativePosVector.x) +
                 dAngle[2] * math.pi / 180)
             particle.pos = (radius * math.cos(newAngle) + centrePoint.x,
                             radius * math.sin(newAngle) + centrePoint.y,
                             posVector.z)
             particle.drotation += Vector(0, 0, dAngle[2])
     # An angle keeps the same with when it minus muptiple 360
     particle.drotation %= 360
コード例 #6
0
    def __init__(self, position = (-1,0,-10), ID='', **argd):
        super(Particle3D, self).__init__(position=position, ID = ID)
        
        self.pos = position
        self.initSize = Vector(*argd.get("size", (0,0,0)))

        self.backgroundColourWhenUnselected = self.backgroundColour = argd.get("bgcolour", (230,230,230))
        self.foregroundColourWhenUnselected = self.foregroundColour = argd.get("fgcolour", (0,0,0))
        self.sideColourWhenUnselected = self.sideColour = argd.get("sidecolour", (200,200,244))
        
        self.backgroundColourWhenSelected = argd.get("bgcolourselected", (0,0,0))
        self.foregroundColourWhenSelected = argd.get("fgcolourselected", (244,244,244))
        self.sideColourWhenSelected = argd.get("sidecolourselected", (200,200,244))
        
        self.margin = argd.get("margin", 8)
        self.fontsize = argd.get("fontsize", 50)
        self.pixelscaling = argd.get("pixelscaling", 100)
        self.thickness = argd.get("thickness", 0.3)
        
        # For picture texture
        self.pic = argd.get("image", None)
        
        name = argd.get("name","NoName")
        self.set_label(name)
        
        # For rotation and scaling
        self.drotation = Vector()
        self.scaling = Vector( *argd.get("scaling", (1,1,1) ) )
        
        # For detection of changes
        self.oldpos = self.initialpos = Vector()
        self.oldscaling = Vector()
        
        # For transformation matrix multiplication
        self.transform = Transform()
        self.linkTransform = Transform()
        self.oldrotTransform = Transform()
        
        # For redraw detection
        self.needRedraw = True
        
        # For drag handling
        self.oldpoint = None
コード例 #7
0
ファイル: Particles3D.py プロジェクト: thangduong/kamaelia
    def draw(self):
        """Draw teapot particle."""
        hs = self.radius
        glColor4f(self.sidecurcolour[0] / 256.0, self.sidecurcolour[1] / 256.0,
                  self.sidecurcolour[2] / 256.0, 0.5)

        # Add texture
        glMatrixMode(GL_TEXTURE)
        glPushMatrix()
        glLoadIdentity()
        glRotatef(180.0, 0.0, 0.0, 1.0)
        glMatrixMode(GL_MODELVIEW)

        glEnable(GL_TEXTURE_2D)
        glBindTexture(GL_TEXTURE_2D, self.texID)
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)

        # Draw teapot
        glFrontFace(GL_CW)
        glutSolidTeapot(hs)
        glFrontFace(GL_CCW)

        glDisable(GL_TEXTURE_2D)

        glMatrixMode(GL_TEXTURE)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

        # Draw links
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadMatrixf(self.linkTransform.getMatrix())
        for p in self.bondedTo:
            glBegin(GL_LINES)
            glVertex3f(*self.initialpos.toTuple())
            glVertex3f(*(Vector(*p.pos) - Vector(*self.pos)).toTuple())
            glEnd()
        glPopMatrix()


# Licensed to the BBC under a Contributor Agreement: CL
コード例 #8
0
    def applyTransforms(self):
        """ Use the objects translation/rotation/scaling values to generate a new transformation Matrix if changes have happened. """
        # generate new transformation matrix if needed
        if self.oldscaling != self.scaling or self.drotation != Vector() or self.oldpos != Vector(*self.pos):
            self.transform = Transform()
            self.linkTransform = Transform()
            drotationTransform = Transform()
            drotationTransform.applyRotation(self.drotation)
            
            self.transform.applyScaling(self.scaling)
            self.linkTransform.applyScaling(self.scaling)
            
            self.transform = self.transform*self.oldrotTransform*drotationTransform
            self.oldrotTransform = self.oldrotTransform*drotationTransform
            
            self.transform.applyTranslation(Vector(*self.pos))
            self.linkTransform.applyTranslation(Vector(*self.pos))

            if self.oldscaling != self.scaling:
                self.oldscaling = self.scaling.copy()
            
            self.drotation = Vector()    
            
            if self.oldpos != Vector(*self.pos):
                self.oldpos = Vector(*self.pos)
            
            # send new transform to display service
            transform_update = { "TRANSFORM_UPDATE": True,
                                 "objectid": id(self),
                                 "transform": self.transform
                               }
            return transform_update
        else:
            return None
コード例 #9
0
    def handleEvents(self):
        while self.dataReady("events"):
            setPullPoint = False
            event = self.recv("events")
            if (event.type == pygame.MOUSEBUTTONDOWN and event.button == 1
                    and self.identifier in event.hitobjects):
                self.pulling = True
                setPullPoint = True

            if (event.type == pygame.MOUSEBUTTONUP and self.pulling):
                self.pulling = False
                self.foldpoint, self.folddelta = calcFoldLine(
                    (0.0, 0.0), (0.0, 0.0), self.radius)

            if self.pulling:

                # transform vertices for intersection test
                transformedPoly = [
                    self.transform.transformVector(Vector(x, y, 0.0))
                    for ((x, y), _) in self.polys[0]
                ]
                # calculate distance of intersection
                t = Intersect.ray_Plane(Vector(0, 0, 0), event.direction,
                                        transformedPoly[0:3])
                # point of intersection
                p = event.direction * t

                point = mapPlaneToPoly(
                    transformedPoly[0].toTuple(),
                    transformedPoly[1].toTuple(),
                    transformedPoly[2].toTuple(),
                    self.polys[0][0][0],
                    self.polys[0][1][0],
                    self.polys[0][2][0],
                    p.toTuple(),
                )
                if setPullPoint:
                    self.pullpoint = point[0], point[1]
                self.foldpoint, self.folddelta = calcFoldLine(
                    self.pullpoint, point, self.radius)
コード例 #10
0
 def draw(self):
     """ DRAW teapot particle."""
     hs = self.radius
     
     # Add texture
     glMatrixMode(GL_TEXTURE)
     glPushMatrix()
     glLoadIdentity()
     glRotatef(180.0,0.0,0.0,1.0)
     glMatrixMode(GL_MODELVIEW)
     
     glEnable(GL_TEXTURE_2D)
     glBindTexture(GL_TEXTURE_2D, self.texID)
     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
     
     
     
     # Draw teapot
     glFrontFace(GL_CW)
     glutSolidTeapot(hs)
     glFrontFace(GL_CCW)
     
     glDisable(GL_TEXTURE_2D)
     
     glMatrixMode(GL_TEXTURE)
     glPopMatrix()
     glMatrixMode(GL_MODELVIEW)
     
     # Draw links        
     glMatrixMode(GL_MODELVIEW)
     glPushMatrix()
     glLoadMatrixf(self.linkTransform.getMatrix())
     for p in self.bondedTo:
         glBegin(GL_LINES)
         glVertex3f(*self.initialpos.toTuple())
         glVertex3f(*(Vector(*p.pos)-Vector(*self.pos)).toTuple())
         glEnd()
     glPopMatrix()
コード例 #11
0
    def frame(self):
        while self.dataReady("position"):
            self.position = Vector(*self.recv("position"))
            if self.lastValidPos is None:
                self.lastValidPos = self.position.copy()

        while self.dataReady("inbox"):

            msg = self.recv("inbox")
            if msg == "ACK":
                self.lastValidPos = self.position.copy()
            elif msg == "INVALID":
                diff = self.lastValidPos - self.position
                diff.z = 0
                self.send(diff.toTuple(), "movement")
コード例 #12
0
 def gotoDisplayLevel(self, dlevel):
     # Save current level's viewer position
     self.levelViewerPos[
         self.currentLevel] = self.display.viewerposition.copy()
     # Display next level
     self.currentLevel += dlevel
     # Reset viewer position to previous
     try:
         self.display.viewerposition = self.levelViewerPos[
             self.currentLevel].copy()
     except KeyError:
         self.display.viewerposition = self.levelViewerPos[
             self.currentLevel] = Vector()
     # Remove current displayed particles
     for particle in self.currentDisplayedPhysics.particles:
         self.display.ogl_displaylists.pop(id(particle))
         self.display.ogl_transforms.pop(id(particle))
     self.currentDisplayedPhysics.removeByID(
         *self.currentDisplayedPhysics.particleDict.keys())
コード例 #13
0
 def __init__(self, **argd):
     super(SphereParticle3D, self).__init__(**argd)
     self.drotation = Vector(0,0,90)
コード例 #14
0
ファイル: Particles3D.py プロジェクト: thangduong/kamaelia
 def __init__(self, **argd):
     """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
     super(SphereParticle3D, self).__init__(**argd)
     self.drotation = Vector(0, 0, 90)
コード例 #15
0
ファイル: Particles3D.py プロジェクト: thangduong/kamaelia
    def draw(self):
        """Draw CUBOID Particle."""
        hs = self.size / 2

        # draw faces
        glBegin(GL_QUADS)
        glColor4f(self.sidecurcolour[0] / 256.0, self.sidecurcolour[1] / 256.0,
                  self.sidecurcolour[2] / 256.0, 0.5)

        glVertex3f(hs.x, hs.y, hs.z)
        glVertex3f(hs.x, -hs.y, hs.z)
        glVertex3f(hs.x, -hs.y, -hs.z)
        glVertex3f(hs.x, hs.y, -hs.z)

        glVertex3f(-hs.x, hs.y, hs.z)
        glVertex3f(-hs.x, -hs.y, hs.z)
        glVertex3f(-hs.x, -hs.y, -hs.z)
        glVertex3f(-hs.x, hs.y, -hs.z)

        glVertex3f(hs.x, hs.y, hs.z)
        glVertex3f(-hs.x, hs.y, hs.z)
        glVertex3f(-hs.x, hs.y, -hs.z)
        glVertex3f(hs.x, hs.y, -hs.z)

        glVertex3f(hs.x, -hs.y, hs.z)
        glVertex3f(-hs.x, -hs.y, hs.z)
        glVertex3f(-hs.x, -hs.y, -hs.z)
        glVertex3f(hs.x, -hs.y, -hs.z)
        glEnd()

        glEnable(GL_TEXTURE_2D)
        glBindTexture(GL_TEXTURE_2D, self.texID)
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)

        glBegin(GL_QUADS)
        # back plane
        glTexCoord2f(self.tex_w, 1.0 - self.tex_h)
        glVertex3f(hs.x, hs.y, -hs.z)
        glTexCoord2f(0.0, 1.0 - self.tex_h)
        glVertex3f(-hs.x, hs.y, -hs.z)
        glTexCoord2f(0.0, 1.0)
        glVertex3f(-hs.x, -hs.y, -hs.z)
        glTexCoord2f(self.tex_w, 1.0)
        glVertex3f(hs.x, -hs.y, -hs.z)
        # front plane
        glTexCoord2f(0.0, 1.0 - self.tex_h)
        glVertex3f(-hs.x, -hs.y, hs.z)
        glTexCoord2f(self.tex_w, 1.0 - self.tex_h)
        glVertex3f(hs.x, -hs.y, hs.z)
        glTexCoord2f(self.tex_w, 1.0)
        glVertex3f(hs.x, hs.y, hs.z)
        glTexCoord2f(0.0, 1.0)
        glVertex3f(-hs.x, hs.y, hs.z)

        glEnd()

        glDisable(GL_TEXTURE_2D)

        # Draw links
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadMatrixf(self.linkTransform.getMatrix())
        for p in self.bondedTo:
            glBegin(GL_LINES)
            glVertex3f(*self.initialpos.toTuple())
            glVertex3f(*(Vector(*p.pos) - Vector(*self.pos)).toTuple())
            glEnd()
        glPopMatrix()
コード例 #16
0
ファイル: Particles3D.py プロジェクト: thangduong/kamaelia
    def buildCaption(self):
        """Pre-render the text to go on the label."""
        # Text is rendered to self.image
        if self.image is not None:
            if self.imageIO is not None:
                self.imageSurface = pygame.image.load(self.imageIO).convert()
                self.imageIO = None
            elif os.path.exists(self.image):
                self.imageSurface = pygame.image.load(self.image).convert()
            # Image texture is used instead of label texture if 'image' argument is specified
            elif self.image.find('://') != -1:
                # Use text label for notification of waiting before the picture is available
                pygame.font.init()
                font = pygame.font.Font(None, self.fontsize)
                self.imageSurface = font.render(
                    "Loading image...",
                    True,
                    self.fgcurcolour,
                )
                # Use thread to wrap urlopen in case urlopen is blocked
                import thread
                thread.start_new(self.readURLFile, ())
        else:
            # Label texture is used if 'image' argument is not specified
            pygame.font.init()
            font = pygame.font.Font(None, self.fontsize)
            self.imageSurface = font.render(
                self.name,
                True,
                self.fgcurcolour,
            )

        if self.size != Vector(0, 0, 0):
            texsize = (self.size.x * self.pixelscaling,
                       self.size.y * self.pixelscaling)
        else:
            texsize = (self.imageSurface.get_width() + 2 * self.margin,
                       self.imageSurface.get_height() + 2 * self.margin)
            self.size = Vector(texsize[0] / float(self.pixelscaling),
                               texsize[1] / float(self.pixelscaling),
                               self.thickness)

        # create power of 2 dimensioned surface
        pow2size = (int(2**(math.ceil(math.log(texsize[0] + 2 * self.margin,
                                               2)))),
                    int(2**(math.ceil(math.log(texsize[1] + 2 * self.margin,
                                               2)))))
        textureSurface = pygame.Surface(pow2size)
        textureSurface.fill(self.bgcurcolour)
        # determine texture coordinates
        self.tex_w = float(texsize[0]) / pow2size[0]
        self.tex_h = float(texsize[1]) / pow2size[1]
        # copy image data to pow2surface
        dest = (max((texsize[0] - self.imageSurface.get_width()) / 2, 0),
                max((texsize[1] - self.imageSurface.get_height()) / 2, 0))
        textureSurface.blit(self.imageSurface, dest)
        textureSurface = textureSurface.convert_alpha()

        # read pixel data
        textureData = pygame.image.tostring(textureSurface, "RGBX", 1)

        self.texID = glGenTextures(1)
        # create texture
        glEnable(GL_TEXTURE_2D)
        glBindTexture(GL_TEXTURE_2D, self.texID)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureSurface.get_width(),
                     textureSurface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
                     textureData)
        glDisable(GL_TEXTURE_2D)
コード例 #17
0
    def gotoDisplayLevel(self, dlevel):
        """Switch to another display level."""
        isValid = False
        if self.currentLevel + dlevel > self.maxLevel:
            print("Warning: max hierarchy level has reached!")
        elif self.currentLevel + dlevel < 0:
            print("Warning: The first hierarchy level has reached!")
        else:
            if dlevel < 0:  # Go to the last dlevel level
                self.previousParentParticleID = self.currentParentParticleID
                items = self.currentParentParticleID.split(':')
                for _ in xrange(-dlevel):
                    items.pop()
                self.currentParentParticleID = ':'.join(items)
                isValid = True
            if dlevel == 1:  # It only makes sense if dlevel == 1 when go to next dlevel level
                if len(self.selectedParticles) == 1:
                    hasChildParticles = False
                    for particle in self.physics.particles:
                        if particle.ID.find(
                                self.selectedParticles[0].ID
                        ) == 0 and particle.ID != self.selectedParticles[0].ID:
                            hasChildParticles = True
                            break
                    if hasChildParticles:
                        self.previousParentParticleID = self.currentParentParticleID
                        self.currentParentParticleID = self.selectedParticles[
                            0].ID
                        isValid = True
                    else:
                        print(
                            'Warning: The particle you double-clicked has no children!'
                        )
                else:
                    print(
                        "Tips: To extend a node, please double-click the node you want to extend"
                    )
        # Show the specified display level if valid
        if isValid:
            # Save current level's viewer position
            self.levelViewerPos[
                self.currentLevel, self.
                previousParentParticleID] = self.display.viewerposition.copy()
            # Deselect all
            self.deselectAll()
            # Display next level
            self.currentLevel += dlevel
            # Reset viewer position to previous
            try:
                self.display.viewerposition = self.levelViewerPos[
                    self.currentLevel, self.currentParentParticleID].copy()
            except KeyError:
                self.display.viewerposition = self.levelViewerPos[
                    self.currentLevel,
                    self.currentParentParticleID] = Vector()
            # Remove current displayed particles
            for particle in self.currentDisplayedPhysics.particles:
                self.display.ogl_displaylists.pop(id(particle))
                self.display.ogl_transforms.pop(id(particle))
            self.currentDisplayedPhysics.removeByID(
                *self.currentDisplayedPhysics.particleDict.keys())

            # Add current level's particles to self.currentDisplayedPhysics.particles for display
            self.currentDisplayedPhysics.particles = []
            if self.physics.particles != []:
                for particle in self.physics.particles:
                    if self.currentParentParticleID == '':  # If no parent, it's the top level
                        if ':' not in particle.ID:
                            self.currentDisplayedPhysics.add(particle)
                            particle.oldpos = particle.initialpos
                    # The child particles of self.currentParentParticleID
                    elif particle.ID.find(
                            self.currentParentParticleID
                    ) == 0 and particle.ID.count(':') == self.currentLevel:
                        self.currentDisplayedPhysics.add(particle)
                        particle.oldpos = particle.initialpos
コード例 #18
0
    def main(self):
        """\
 
        
        """
        # create display request for itself
        self.size = Vector(0, 0, 0)
        disprequest = {
            "OGL_DISPLAYREQUEST": True,
            "objectid": id(self),
            "callback": (self, "callback"),
            "events": (self, "events"),
            "size": self.size
        }
        # send display request
        self.send(disprequest, "display_signal")
        # wait for response on displayrequest and get identifier of the viewer
        while not self.dataReady("callback"):
            yield 1
        self.identifier = self.recv("callback")

        self.addListenEvents([
            pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP, pygame.MOUSEMOTION,
            pygame.KEYDOWN, pygame.KEYUP
        ])
        pygame.key.set_repeat(100, 100)

        while True:
            # process incoming messages
            if self.dataReady("inbox"):
                message = self.recv("inbox")
                self.doCommand(message)
                #print message

                # wait for response on displayrequest and get identifier of the particle
                if self.isNewNode:
                    while not self.dataReady("callback"):
                        yield 1
                    self.physics.particles[-1].identifier = self.recv(
                        "callback")
                    self.isNewNode = False
            else:
                self.lastIdleTime = 0

            yield 1

            if self.lastIdleTime + 1.0 < time.time():
                #print [particle.pos for particle in self.physics.particles]
                avoidedList = []
                avoidedList.extend(self.hitParticles)
                avoidedList.extend(self.selectedParticles)

                #self.currentDisplayedPhysics.particleDict[ident].breakAllBonds()
                self.currentDisplayedPhysics.particles = []
                if self.physics.particles != []:
                    for particle in self.physics.particles:
                        if self.currentParentParticleID == '':
                            if ':' not in particle.ID:
                                self.currentDisplayedPhysics.add(particle)
                                particle.oldpos = particle.initialpos
                        elif particle.ID.find(
                                self.currentParentParticleID
                        ) == 0 and particle.ID.count(':') == self.currentLevel:
                            self.currentDisplayedPhysics.add(particle)
                            particle.oldpos = particle.initialpos
                self.currentDisplayedPhysics.run(self.simCyclesPerRedraw,
                                                 avoidedList=avoidedList)
                #print [particle.pos for particle in self.physics.particles]

                # Draw particles if new or updated
                for particle in self.currentDisplayedPhysics.particles:
                    if particle.needRedraw:
                        self.drawParticles(particle)
                        #particle.needRedraw = False

                self.handleEvents()

                # Perform transformation
                for particle in self.currentDisplayedPhysics.particles:
                    transform_update = particle.applyTransforms()
                    if transform_update is not None:
                        self.send(transform_update, "display_signal")
                        #print transform_update
                        #print [particle.pos for particle in self.physics.particles]

                self.lastIdleTime = time.time()
            else:
                yield 1
            if self.dataReady("control"):
                msg = self.recv("control")
                if isinstance(msg, Axon.Ipc.shutdownMicroprocess):
                    self.quit(msg)
コード例 #19
0
    def handleMouseEvents(self, event):
        """Handle mouse events."""
        if event.type == pygame.MOUSEBUTTONDOWN or pygame.MOUSEMOTION and self.grabbed:
            if not self.rotationMode:
                for particle in self.hitParticles:
                    p1 = Vector(*particle.pos).copy()
                    p1.x += 10
                    p2 = Vector(*particle.pos).copy()
                    p2.y += 10
                    # Get the position of mouse
                    z = Intersect.ray_Plane(Vector(0, 0, 0), event.direction, [
                        Vector(*particle.pos) -
                        Vector(0, 0, self.display.viewerposition.z),
                        p1 - Vector(0, 0, self.display.viewerposition.z),
                        p2 - Vector(0, 0, self.display.viewerposition.z)
                    ])
                    newpoint = event.direction * z
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                # Handle double click
                clickPos = event.pos
                currentTime = time.time()
                elapsedTime = currentTime - self.lastClickTime
                # If it's a double-click
                if clickPos == self.lastClickPos and elapsedTime < self.dClickRes:
                    self.gotoDisplayLevel(1)
                else:  # Single click
                    if not self.rotationMode:  # Select particle
                        for particle in self.currentDisplayedPhysics.particles:
                            if particle.identifier in event.hitobjects:
                                self.grabbed = True
                                self.hitParticles.append(particle)
                                self.selectParticle(particle)
                        # If click places other than particles in non multiSelectMode, deselect all
                        if not self.hitParticles and not self.multiSelectMode:
                            self.deselectAll()
                self.lastClickPos = clickPos
                self.lastClickTime = currentTime
            elif event.button == 3:  # Right-clicked
                self.gotoDisplayLevel(-1)
            elif event.button == 4:  # Scrolled-up: zoom out
                if self.selectedParticles:
                    particles = self.selectedParticles
                else:
                    particles = self.currentDisplayedPhysics.particles
                for particle in particles:
                    posVector = Vector(*particle.pos)
                    posVector.z -= 1
                    particle.pos = posVector.toTuple()
            elif event.button == 5:  # Scrolled-down: zoom in
                if self.selectedParticles:
                    particles = self.selectedParticles
                else:
                    particles = self.currentDisplayedPhysics.particles
                for particle in particles:
                    posVector = Vector(*particle.pos)
                    posVector.z += 1
                    particle.pos = posVector.toTuple()
        if event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                for particle in self.hitParticles:
                    self.grabbed = False
                    particle.oldpoint = None
                    self.hitParticles.pop(self.hitParticles.index(particle))
        if event.type == pygame.MOUSEMOTION:
            if not self.rotationMode and self.grabbed:  # Drag particles
                for particle in self.hitParticles:
                    try:
                        if particle.oldpoint is not None:
                            diff = newpoint - particle.oldpoint
                            amount = (diff.x, diff.y)
                            particle.pos = (Vector(*particle.pos) +
                                            Vector(*amount)).toTuple()
                    except NameError:
                        pass

                    # Redraw the link so that the link can move with the particle
                    for p in particle.bondedFrom:
                        p.needRedraw = True
            elif self.rotationMode:  # Rotate particles
                dAnglex = float(event.rel[1])
                dAngley = -float(event.rel[0])
                self.rotateParticles(self.selectedParticles,
                                     (dAnglex, dAngley, 0))

        try:
            for particle in self.hitParticles:
                particle.oldpoint = newpoint
        except NameError:
            pass
コード例 #20
0
    def main(self):
        """Main loop."""
        # Make display request for event listening purpose
        self.size = Vector(0, 0, 0)
        disprequest = {
            "OGL_DISPLAYREQUEST": True,
            "objectid": id(self),
            "callback": (self, "callback"),
            "events": (self, "events"),
            "size": self.size
        }
        # send display request
        self.send(disprequest, "display_signal")
        # Wait for response on displayrequest and get identifier of the viewer
        while not self.dataReady("callback"):
            yield 1
        self.identifier = self.recv("callback")

        self.initialiseComponent()

        while True:
            # Process incoming messages
            if self.dataReady("inbox"):
                message = self.recv("inbox")
                self.doCommand(message)

                # Wait for response on displayrequest and get identifier of the particle
                if self.isNewNode:
                    while not self.dataReady("callback"):
                        yield 1
                    self.physics.particles[-1].identifier = self.recv(
                        "callback")
                    self.isNewNode = False
            else:
                self.lastIdleTime = 0

            yield 1

            if self.lastIdleTime + 1.0 < time.time():
                #Freeze selected particles so that they are not subject to the physics law
                for particle in self.selectedParticles:
                    particle.freeze()
                # Do interaction between particles
                self.currentDisplayedPhysics.run(self.simCyclesPerRedraw)
                # Unfreeze selected particles
                for particle in self.selectedParticles:
                    particle.unFreeze()

                # Draw particles if new or updated
                for particle in self.currentDisplayedPhysics.particles:
                    if particle.needRedraw:
                        self.drawParticles(particle)

                self.handleEvents()

                # Perform transformation
                for particle in self.currentDisplayedPhysics.particles:
                    transform_update = particle.applyTransforms()
                    if transform_update is not None:
                        self.send(transform_update, "display_signal")

                self.lastIdleTime = time.time()
            else:
                yield 1
            if self.dataReady("control"):
                msg = self.recv("control")
                if isinstance(msg, Axon.Ipc.shutdownMicroprocess):
                    self.quit(msg)
コード例 #21
0
    def __init__(self,
                 screensize=(800, 600),
                 fullscreen=False,
                 caption="3D Topology Viewer",
                 particleTypes=None,
                 initialTopology=None,
                 laws=None,
                 simCyclesPerRedraw=1,
                 border=0):
        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""

        super(TopologyViewer3D, self).__init__()

        glutInit(sys.argv)

        tracker = _cat.coordinatingassistanttracker.getcat()
        try:
            self.display = tracker.retrieveService("ogl_display")[0]
        except KeyError:
            self.display = OpenGLDisplay(width=screensize[0],
                                         height=screensize[1],
                                         fullscreen=fullscreen,
                                         title=caption)
            self.display.activate()
            OpenGLDisplay.setDisplayService(self.display, tracker)
        self.display = OpenGLDisplay.getDisplayService()[0]
        self.link((self, "display_signal"), (self.display, "notify"))
        self.link((self.display, "signal"), (self, "control"))

        self.border = border

        if particleTypes == None:
            self.particleTypes = {
                "-": CuboidParticle3D,
                "cuboid": CuboidParticle3D,
                "sphere": SphereParticle3D,
                "teapot": TeapotParticle3D
            }
        else:
            self.particleTypes = particleTypes

        if initialTopology == None:
            initialTopology = ([], [])
        self.initialNodes = list(initialTopology[0])
        self.initialBonds = list(initialTopology[1])

        self.hitParticles = []
        self.multiSelectMode = False
        self.selectedParticles = []
        self.grabbed = False
        self.rotationMode = False

        if laws == None:
            self.laws = Kamaelia.Support.Particles.SimpleLaws(bondLength=2)
        else:
            self.laws = laws

        self.physics = ParticleSystem(self.laws, [], 0)
        self.biggestRadius = 0

        # Do interaction
        self.simCyclesPerRedraw = simCyclesPerRedraw
        self.lastIdleTime = time.time()

        # Tell if new node is added; if true, new id needs adding to OpenGLDisplay list
        self.isNewNode = False

        # For hierarchy structure
        self.maxLevel = 0
        self.currentLevel = 0
        self.previousParentParticleID = self.currentParentParticleID = ''
        self.viewerOldPos = Vector()
        self.levelViewerPos = {}
        # The Physics particle system of current display level for display
        self.currentDisplayedPhysics = ParticleSystem(self.laws, [], 0)

        # For double click
        self.lastClickPos = (0, 0)
        self.lastClickTime = time.time()
        self.dClickRes = 0.3
コード例 #22
0
 def handleEvents(self):
     while self.dataReady("events"):
         event = self.recv("events")
         if event.type == pygame.MOUSEBUTTONDOWN and self.identifier in event.hitobjects:
             self.rotation += Vector(0, 0, 10)
             self.rotation %= 360
コード例 #23
0
    def handleEvents(self):
        """ Handle events. """
        while self.dataReady("events"):
            event = self.recv("events")
            if event.type == pygame.MOUSEBUTTONDOWN or pygame.MOUSEMOTION and self.grabbed:
                if not self.rotationMode:
                    for particle in self.hitParticles:
                        p1 = Vector(*particle.pos).copy()
                        p1.x += 10
                        p2 = Vector(*particle.pos).copy()
                        p2.y += 10
                        #z = Intersect.ray_Plane(Vector(0,0,0), event.direction, [Vector(*particle.pos)-self.display.viewerposition, p1, p2])
                        z = Intersect.ray_Plane(Vector(
                            0, 0, 0), event.direction, [
                                Vector(*particle.pos) -
                                Vector(0, 0, self.display.viewerposition.z),
                                p1 -
                                Vector(0, 0, self.display.viewerposition.z),
                                p2 -
                                Vector(0, 0, self.display.viewerposition.z)
                            ])
                        newpoint = event.direction * z
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    # Handle double click
                    clickPos = event.pos
                    currentTime = time.time()
                    elapsedTime = currentTime - self.lastClickTime
                    if clickPos == self.lastClickPos and elapsedTime < self.dClickRes:
                        if self.currentLevel < self.maxLevel and len(
                                self.selectedParticles) == 1:
                            hasChildParticles = False
                            for particle in self.physics.particles:
                                if particle.ID.find(
                                        self.selectedParticles[0].ID
                                ) == 0 and particle.ID != self.selectedParticles[
                                        0].ID:
                                    hasChildParticles = True
                                    break
                            if hasChildParticles:
                                self.currentParentParticleID = self.selectedParticles[
                                    0].ID
                                self.gotoDisplayLevel(1)
                            else:
                                print 'Warning: The particle you double-clicked has no children!'

                        else:
                            if self.currentLevel == self.maxLevel:
                                print "Warning: max hierarchy level has reached!"
                            if len(self.selectedParticles) != 1:
                                print "Tips: To extend a node, please double-click the node you want to extend"
                    else:
                        if not self.rotationMode:
                            for particle in self.currentDisplayedPhysics.particles:
                                if particle.identifier in event.hitobjects:
                                    #particle.oldpos = particle.oldpos - self.display.viewerposition
                                    self.grabbed = True
                                    #particle.scaling = Vector(0.9,0.9,0.9)
                                    self.hitParticles.append(particle)
                                    self.selectParticle(particle)
                                    #print str(id(particle))+'hit'
                                    #print self.hitParticles
                            # If click places other than particles in non multiSelectMode, deselect all
                            if not self.hitParticles and not self.multiSelectMode:
                                self.deselectAll()
                    self.lastClickPos = clickPos
                    self.lastClickTime = currentTime
                if event.button == 3:
                    if self.currentLevel > 0:
                        items = self.currentParentParticleID.split(':')
                        items.pop()
                        self.currentParentParticleID = ':'.join(items)
                        self.gotoDisplayLevel(-1)
                    else:
                        print "Warning: The first hierarchy level has reached!"
                if event.button == 4:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        posVector.z -= 1
                        particle.pos = posVector.toTuple()
                if event.button == 5:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        posVector.z += 1
                        particle.pos = posVector.toTuple()
            if event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    for particle in self.hitParticles:
                        self.grabbed = False
                        particle.oldpoint = None
                        #particle.scaling = Vector(1,1,1)
                        self.hitParticles.pop(
                            self.hitParticles.index(particle))
                        #print self.hitParticles
            if event.type == pygame.MOUSEMOTION:
                if not self.rotationMode and self.grabbed:
                    for particle in self.hitParticles:
                        try:
                            if particle.oldpoint is not None:
                                #print particle.pos
                                diff = newpoint - particle.oldpoint
                                amount = (diff.x, diff.y)
                                particle.pos = (Vector(*particle.pos) +
                                                Vector(*amount)).toTuple()
                        except NameError:
                            pass

                        # Redraw the link so that the link can move with the particle
                        for p in particle.bondedFrom:
                            p.needRedraw = True
                elif self.rotationMode:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles

                    centrePoint = Vector()
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        centrePoint += posVector
                    centrePoint /= len(particles)
                    dAnglex = float(event.rel[1]) * math.pi / 180
                    dAngley = -float(event.rel[0]) * math.pi / 180
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.z * relativePosVector.z +
                            relativePosVector.y * relativePosVector.y)**0.5
                        newAnglex = (math.atan2(relativePosVector.z,
                                                relativePosVector.y) + dAnglex)
                        particle.pos = (posVector.x,
                                        radius * math.cos(newAnglex) +
                                        centrePoint.y,
                                        radius * math.sin(newAnglex) +
                                        centrePoint.z)
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.z * relativePosVector.z +
                            relativePosVector.x * relativePosVector.x)**0.5
                        newAngley = (math.atan2(relativePosVector.z,
                                                relativePosVector.x) + dAngley)
                        particle.pos = (radius * math.cos(newAngley) +
                                        centrePoint.x, posVector.y,
                                        radius * math.sin(newAngley) +
                                        centrePoint.z)
                        particle.drotation.y = float(event.rel[0])
                        particle.drotation.x = float(event.rel[1])
                        particle.drotation %= 360

            try:
                for particle in self.hitParticles:
                    particle.oldpoint = newpoint
            except NameError:
                pass

            # Keyboard events handling
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.quit()
                elif event.key == pygame.K_BACKSPACE:
                    if self.currentLevel > 0:
                        items = self.currentParentParticleID.split(':')
                        items.pop()
                        self.currentParentParticleID = ':'.join(items)
                        self.gotoDisplayLevel(-1)
                    else:
                        print "Warning: The first hierarchy level has reached!"
                elif event.key == pygame.K_RETURN:
                    if self.currentLevel < self.maxLevel and len(
                            self.selectedParticles) == 1:
                        hasChildParticles = False
                        for particle in self.physics.particles:
                            if particle.ID.find(
                                    self.selectedParticles[0].ID
                            ) == 0 and particle.ID != self.selectedParticles[
                                    0].ID:
                                hasChildParticles = True
                                break
                        if hasChildParticles:
                            self.currentParentParticleID = self.selectedParticles[
                                0].ID
                            self.gotoDisplayLevel(1)
                        else:
                            print 'Warning: The particle you double-clicked has no children!'
                    else:
                        if self.currentLevel == self.maxLevel:
                            print "Warning: max hierarchy level has reached!"
                        if len(self.selectedParticles) != 1:
                            print "Tips: To extend a node, please click to select the node (only one) you want to extend first."

                elif event.key == pygame.K_LSHIFT or event.key == pygame.K_RSHIFT:
                    self.multiSelectMode = True
                elif event.key == pygame.K_LCTRL or event.key == pygame.K_RCTRL:
                    self.rotationMode = True
                elif event.key == pygame.K_PAGEUP:
                    self.display.viewerposition.z -= 0.5
                elif event.key == pygame.K_PAGEDOWN:
                    self.display.viewerposition.z += 0.5
                elif event.key == pygame.K_w:
                    self.display.viewerposition.y += 0.5
                elif event.key == pygame.K_s:
                    self.display.viewerposition.y -= 0.5
                elif event.key == pygame.K_a:
                    self.display.viewerposition.x -= 0.5
                elif event.key == pygame.K_d:
                    self.display.viewerposition.x += 0.5
                elif event.key == pygame.K_UP:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    centrePoint = Vector()
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        centrePoint += posVector
                    centrePoint /= len(particles)
                    dAngle = -20 * math.pi / 180
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.z * relativePosVector.z +
                            relativePosVector.y * relativePosVector.y)**0.5
                        newAngle = (math.atan2(relativePosVector.z,
                                               relativePosVector.y) + dAngle)
                        particle.pos = (posVector.x,
                                        radius * math.cos(newAngle) +
                                        centrePoint.y,
                                        radius * math.sin(newAngle) +
                                        centrePoint.z)
                        particle.drotation = Vector(dAngle * 180 / math.pi, 0,
                                                    0)
                elif event.key == pygame.K_DOWN:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    centrePoint = Vector()
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        centrePoint += posVector
                    centrePoint /= len(particles)
                    dAngle = 20 * math.pi / 180
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.z * relativePosVector.z +
                            relativePosVector.y * relativePosVector.y)**0.5
                        newAngle = (math.atan2(relativePosVector.z,
                                               relativePosVector.y) + dAngle)
                        particle.pos = (posVector.x,
                                        radius * math.cos(newAngle) +
                                        centrePoint.y,
                                        radius * math.sin(newAngle) +
                                        centrePoint.z)
                        particle.drotation = Vector(dAngle * 180 / math.pi, 0,
                                                    0)
                elif event.key == pygame.K_LEFT:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    centrePoint = Vector()
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        centrePoint += posVector
                    centrePoint /= len(particles)
                    dAngle = 20 * math.pi / 180
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.z * relativePosVector.z +
                            relativePosVector.x * relativePosVector.x)**0.5
                        newAngle = (math.atan2(relativePosVector.z,
                                               relativePosVector.x) + dAngle)
                        particle.pos = (radius * math.cos(newAngle) +
                                        centrePoint.x, posVector.y,
                                        radius * math.sin(newAngle) +
                                        centrePoint.z)
                        particle.drotation = Vector(0, -dAngle * 180 / math.pi,
                                                    0)
                elif event.key == pygame.K_RIGHT:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    centrePoint = Vector()
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        centrePoint += posVector
                    centrePoint /= len(particles)
                    dAngle = -20 * math.pi / 180
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.z * relativePosVector.z +
                            relativePosVector.x * relativePosVector.x)**0.5
                        newAngle = (math.atan2(relativePosVector.z,
                                               relativePosVector.x) + dAngle)
                        particle.pos = (radius * math.cos(newAngle) +
                                        centrePoint.x, posVector.y,
                                        radius * math.sin(newAngle) +
                                        centrePoint.z)
                        particle.drotation = Vector(0, -dAngle * 180 / math.pi,
                                                    0)
                elif event.key == pygame.K_COMMA:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    centrePoint = Vector()
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        centrePoint += posVector
                    centrePoint /= len(particles)
                    dAngle = 20 * math.pi / 180
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.x * relativePosVector.x +
                            relativePosVector.y * relativePosVector.y)**0.5
                        newAngle = (math.atan2(relativePosVector.y,
                                               relativePosVector.x) + dAngle)
                        particle.pos = (radius * math.cos(newAngle) +
                                        centrePoint.x,
                                        radius * math.sin(newAngle) +
                                        centrePoint.y, posVector.z)
                        particle.drotation = Vector(0, 0,
                                                    dAngle * 180 / math.pi)
                elif event.key == pygame.K_PERIOD:
                    if self.selectedParticles:
                        particles = self.selectedParticles
                    else:
                        particles = self.currentDisplayedPhysics.particles
                    centrePoint = Vector()
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        centrePoint += posVector
                    centrePoint /= len(particles)
                    dAngle = -20 * math.pi / 180
                    for particle in particles:
                        posVector = Vector(*particle.pos)
                        relativePosVector = posVector - centrePoint
                        radius = (
                            relativePosVector.x * relativePosVector.x +
                            relativePosVector.y * relativePosVector.y)**0.5
                        newAngle = (math.atan2(relativePosVector.y,
                                               relativePosVector.x) + dAngle)
                        particle.pos = (radius * math.cos(newAngle) +
                                        centrePoint.x,
                                        radius * math.sin(newAngle) +
                                        centrePoint.y, posVector.z)
                        particle.drotation = Vector(0, 0,
                                                    dAngle * 180 / math.pi)

            #print self.display.viewerposition
            # Scroll if self.display.viewerposition changes
            if self.display.viewerposition.copy() != self.viewerOldPos:
                self.scroll()
                self.viewerOldPos = self.display.viewerposition.copy()
#                for particle in self.currentDisplayedPhysics.particles:
#                    particle.oldpoint = None
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LSHIFT or event.key == pygame.K_RSHIFT:
                    self.multiSelectMode = False
                elif event.key == pygame.K_LCTRL or event.key == pygame.K_RCTRL:
                    self.rotationMode = False