From f891b3a18c952b88967f7408bb942ef3c0cd111f Mon Sep 17 00:00:00 2001 From: Rodrigo Perez Fulloni Date: Mon, 17 Dec 2012 22:24:44 +0000 Subject: Final version 1.0 --- diff --git a/QR.png b/QR.png new file mode 100644 index 0000000..021bdfe --- /dev/null +++ b/QR.png Binary files differ diff --git a/Ropa.png b/Ropa.png new file mode 100644 index 0000000..5fbaf39 --- /dev/null +++ b/Ropa.png Binary files differ diff --git a/nbproject/private/private.properties b/nbproject/private/private.properties new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/nbproject/private/private.properties diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..66119ee --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,5 @@ +java.lib.path= +main.file=queviaje.py +platform.active=Python_2.6.6 +python.lib.path= +src.dir=src diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..506961d --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,13 @@ + + + org.netbeans.modules.python.project + + + QueViaje + + + + + + + diff --git a/src/QueViaje.py b/src/QueViaje.py new file mode 100644 index 0000000..64ca694 --- /dev/null +++ b/src/QueViaje.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- + +__author__ = "rodripf" +__date__ = "$17/10/2012 10:30:27 AM$" + +import sys +sys.path.insert(0,"/home/olpc/Activities/QueViaje.activity") + +import pygame.camera + +import pygame +from pygame.locals import * +pygame.init() + +pygame.mixer.init() + +import os +import random +from SugarBar import SugarBar + +from threading import Timer + +from data.playa import Playa +from data.ciudad import Ciudad +from data.nieve import Nieve + +from sugar.activity import activity +import sugargame.canvas + +class QueViaje(activity.Activity): + RESOLUCION = (1200, 900) + ACIERTOS_PARA_GANAR = 3 + LUGAR_MUESTRA = (10,10) + + def __init__(self, handle): + activity.Activity.__init__(self, handle) + + self.camara = True + self.mostrandoPista = False + self.mostrandoInfo = False + self.mostrandoPresentacion = False + + self.cosas = [] #cosas que se estan mostrando + self.sb = SugarBar(); + + self.puntos = 0 #numero de aciertos + self.nivel = 0 + + self.sonidoError = pygame.mixer.Sound("audio/error.ogg") + self.sonidoAcierto = pygame.mixer.Sound("audio/acierto.ogg") + self.sonidoVictoria = pygame.mixer.Sound("audio/victoria.ogg") + self.sonidoPasraPantalla = pygame.mixer.Sound("audio/pasarPantalla.ogg") + + self.IMGGenial = pygame.image.load("carteles/genial.png") + self.IMGBien = pygame.image.load("carteles/bien.png") + self.IMGGanaste = pygame.image.load("carteles/ganaste.png") + + self.pistaActual = 1 + self.pistas = [] + self.pistas.append("carteles/conoces_este_lugar.png") + self.pistas.append("carteles/que_objeto_llevarias.png") + self.pistas.append("carteles/que_te_pondrias_en_las_piernas.png") + self.pistas.append("carteles/que_te_pondrias_en_los_pies.png") + self.pistas.append("carteles/que_te_pondrias_para_ir_a_este_lugar.png") + self.pistas.append("carteles/te_parece_que_hace_frio_o_calor.png") + + self.info = [] + self.info.append("carteles/Presentacion.png") + self.info.append("carteles/info_verano.png") + self.info.append("carteles/info_nieve.png") + self.info.append("carteles/info_ciudad.png") + + + #canvas + self.canv = sugargame.canvas.PygameCanvas(self) + self.set_canvas(self.canv) + self.canv.run_pygame(self.iniciar) + + + + def iniciar(self): + self.screen = pygame.display.set_mode(self.RESOLUCION) + pygame.display.toggle_fullscreen() + pygame.mouse.set_visible(False) + + self.mainLoop() + + def mainLoop(self): + self.pl = Playa(self.screen, (0, 0)) + self.musicaFondo() + going = True + while going: + events = pygame.event.get() + + + if self.camara: + self.sb.blitCameraImage(self.screen, (10,600)) + + result = self.sb.getAndAnalize() + + for dato in result: + self.leido(dato) + + pygame.display.update() + pygame.event.pump() + for e in events: + if e.type == QUIT or (e.type == KEYDOWN and e.key == pygame.K_ESCAPE): + self.sb.stop() + pygame.mixer.music.stop() + going = False + sys.exit() + if e.type == KEYDOWN and e.key == pygame.K_SPACE: + + self.camara = not self.camara + if not self.camara: + self.pasarArriba() + elif e.type == KEYDOWN and e.key == K_p: + self.mostrandoPista = not self.mostrandoPista + if self.mostrandoPista: + self.mostrarPista() + else: + self.pasarArriba() +# + elif e.type == KEYDOWN and e.key == K_i: + self.mostrandoInfo = not self.mostrandoInfo + if self.mostrandoInfo: + self.mostrarInfo() + else: + self.pasarArriba() + elif e.type == KEYDOWN and e.key == K_q: + self.mostrandoPresentacion = not self.mostrandoPresentacion + if self.mostrandoPresentacion: + self.mostrarPresentacion() + else: + self.pasarArriba() + + def mostrarCosa(self, img): + cosa = pygame.image.load(os.path.join("cosas", img + ".jpg")).convert() + self.cosas.append(cosa) + self.screen.blit(cosa, self.LUGAR_MUESTRA) + t = Timer(3, self.pasarArriba) + t.start() + + def pasarArriba(self): + self.pl.repaint() + i = 1 + for c in self.cosas: + i += 1 + self.screen.blit(c, (i * 200 + 10, 10)) + + def cambiarLugar(self, lugar): + if lugar == 0: + self.pl = Playa(self.screen, (0, 0)) + elif lugar == 1: + self.pl = Nieve(self.screen, (0, 0)) + elif lugar == 2: + self.pl = Ciudad(self.screen, (0, 0)) + elif lugar == 3: + self.sonidoVictoria.play() + self.screen.blit(self.IMGGanaste, (50, 300)) + + + + self.pl.cargarDatos() + self.puntos = 0 + self.cosas = [] + self.sonidoPasraPantalla.play() + + + + + def leido(self, dato): + if self.pl.chequear(dato): + self.mostrarCosa(dato) + self.acierto() + self.puntos += 1 + if self.puntos >= self.ACIERTOS_PARA_GANAR: + self.nivel += 1 + t = Timer(3, self.cambiarLugar, [self.nivel,]) + t.start() + else: + self.error() + + + def musicaFondo(self): + pygame.mixer.music.load("audio/fondo.ogg") + pygame.mixer.music.set_volume(0.6) + pygame.mixer.music.play(-1) + + def error(self): + self.sonidoError.play() + + def acierto(self): + self.sonidoAcierto.play() + r = random.randint(0, 1) + if r==0: + self.screen.blit(self.IMGGenial, (50, 300)) + else: + self.screen.blit(self.IMGBien, (50, 300)) + t = Timer(3, self.pasarArriba) + t.start() + + def mostrarPista(self): + self.screen.blit(pygame.image.load(self.pistas[self.pistaActual]), (0,0)) + self.pistaActual += 1 + if self.pistaActual > len(self.pistas) - 1: + self.pistaActual = 0 + + + def mostrarInfo(self): + self.screen.blit(pygame.image.load(self.info[self.nivel + 1]),(0,0)) + + def mostrarPresentacion(self): + self.screen.blit(pygame.image.load(self.info[0]), (0,0)) + + + +if __name__ == "__main__": + qv = QueViaje() + + qv.mainLoop() diff --git a/src/QueViaje.pyo b/src/QueViaje.pyo new file mode 100644 index 0000000..2c3a8d4 --- /dev/null +++ b/src/QueViaje.pyo Binary files differ diff --git a/src/SugarBar.py b/src/SugarBar.py new file mode 100644 index 0000000..cb4b388 --- /dev/null +++ b/src/SugarBar.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +from ctypes import * +cdll.LoadLibrary("./libzbar.so.0.2.0") +import zbar + +import pygame +import pygame.camera +from pygame.locals import * + + + +pygame.init() +pygame.camera.init() + +class SugarBar: + SIZE = (320, 240) + + def __init__(self): + self.nueva = False + self.zImg = [] + self.cam = pygame.camera.Camera("/dev/video0", self.SIZE, "YUV") + self.cam.start() + + self.scanner = zbar.ImageScanner() + self.scanner.parse_config('disable') + self.scanner.parse_config('qrcode.enable') + self.scanner.enable_cache(True) + + self.grayImg = pygame.Surface(self.SIZE, depth=8) + self.grayImg.set_palette([(x, x, x) for x in xrange(255)]) + self.image = pygame.Surface(self.SIZE, depth=24) + + self.mostrarCam = False + + + def getAndAnalize(self): + if self.cam.query_image(): + self.nueva = True + self.cam.get_image(self.image) + arr3d = pygame.surfarray.pixels3d(self.image) + lumi = arr3d[0:self.SIZE[0], 0:self.SIZE[1], 0] + pygame.surfarray.blit_array(self.grayImg, lumi) + + imgString = pygame.image.tostring(self.grayImg, "P") + + self.zImg = zbar.Image(self.SIZE[0], self.SIZE[1], "Y800", imgString) + self.scanner.scan(self.zImg) + + decoded = [] + + for symbol in self.zImg: + decoded.append(symbol.data) + + return decoded + + def blitCameraImage(self, display, position): + if self.nueva: + display.blit(self.grayImg, position) + self.nueva = False + + def stop(self): + self.cam.stop() + + def main(self): + display = pygame.display.set_mode(self.SIZE) + going = True + while going: + events = pygame.event.get() + for e in events: + if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE): + # close the camera safely + self.cam.stop() + going = False + + elif e.type == KEYDOWN and e.key == pygame.K_c: + self.mostrarCam = not self.mostrarCam + + res = self.getAndAnalize() + if not res == []: + print res + if self.mostrarCam: + self.blitCameraImage(display, (0, 0)) + pygame.display.flip() + + +if __name__ == "__main__": + d = SugarBar() + d.main() diff --git a/src/SugarBar.py.bak b/src/SugarBar.py.bak new file mode 100644 index 0000000..65232f1 --- /dev/null +++ b/src/SugarBar.py.bak Binary files differ diff --git a/src/SugarBar.pyo b/src/SugarBar.pyo new file mode 100644 index 0000000..2d2232d --- /dev/null +++ b/src/SugarBar.pyo Binary files differ diff --git a/src/activity/activity-QueViaje.svg b/src/activity/activity-QueViaje.svg new file mode 100644 index 0000000..49f4508 --- /dev/null +++ b/src/activity/activity-QueViaje.svg @@ -0,0 +1,98 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/src/activity/activity.info b/src/activity/activity.info new file mode 100644 index 0000000..9101d86 --- /dev/null +++ b/src/activity/activity.info @@ -0,0 +1,8 @@ +[Activity] +name = QueViaje +service_name = uy.edu.fing.QueViaje +exec = sugar-activity QueViaje.QueViaje +icon = activity-QueViaje +activity_version = 1 +license = GPLv3+ +show_launcher = yes diff --git a/src/audio/acierto.ogg b/src/audio/acierto.ogg new file mode 100644 index 0000000..108a40d --- /dev/null +++ b/src/audio/acierto.ogg Binary files differ diff --git a/src/audio/error.ogg b/src/audio/error.ogg new file mode 100644 index 0000000..9456bc2 --- /dev/null +++ b/src/audio/error.ogg Binary files differ diff --git a/src/audio/fondo.ogg b/src/audio/fondo.ogg new file mode 100644 index 0000000..8b926fd --- /dev/null +++ b/src/audio/fondo.ogg Binary files differ diff --git a/src/audio/pasarPantalla.ogg b/src/audio/pasarPantalla.ogg new file mode 100644 index 0000000..b05bf49 --- /dev/null +++ b/src/audio/pasarPantalla.ogg Binary files differ diff --git a/src/audio/victoria.ogg b/src/audio/victoria.ogg new file mode 100644 index 0000000..cd5b5f6 --- /dev/null +++ b/src/audio/victoria.ogg Binary files differ diff --git a/src/carteles/Presentacion.png b/src/carteles/Presentacion.png new file mode 100644 index 0000000..c519b66 --- /dev/null +++ b/src/carteles/Presentacion.png Binary files differ diff --git a/src/carteles/bien.png b/src/carteles/bien.png new file mode 100644 index 0000000..2abdc70 --- /dev/null +++ b/src/carteles/bien.png Binary files differ diff --git a/src/carteles/conoces_este_lugar.png b/src/carteles/conoces_este_lugar.png new file mode 100644 index 0000000..61c37da --- /dev/null +++ b/src/carteles/conoces_este_lugar.png Binary files differ diff --git a/src/carteles/ganaste.png b/src/carteles/ganaste.png new file mode 100644 index 0000000..87a2663 --- /dev/null +++ b/src/carteles/ganaste.png Binary files differ diff --git a/src/carteles/genial.png b/src/carteles/genial.png new file mode 100644 index 0000000..3a8daa7 --- /dev/null +++ b/src/carteles/genial.png Binary files differ diff --git a/src/carteles/info_ciudad.png b/src/carteles/info_ciudad.png new file mode 100644 index 0000000..39816fc --- /dev/null +++ b/src/carteles/info_ciudad.png Binary files differ diff --git a/src/carteles/info_nieve.png b/src/carteles/info_nieve.png new file mode 100644 index 0000000..a9e5a11 --- /dev/null +++ b/src/carteles/info_nieve.png Binary files differ diff --git a/src/carteles/info_verano.png b/src/carteles/info_verano.png new file mode 100644 index 0000000..ddb1e60 --- /dev/null +++ b/src/carteles/info_verano.png Binary files differ diff --git a/src/carteles/que_objeto_llevarias.png b/src/carteles/que_objeto_llevarias.png new file mode 100644 index 0000000..2245c56 --- /dev/null +++ b/src/carteles/que_objeto_llevarias.png Binary files differ diff --git a/src/carteles/que_te_pondrias_en_las_piernas.png b/src/carteles/que_te_pondrias_en_las_piernas.png new file mode 100644 index 0000000..25955bb --- /dev/null +++ b/src/carteles/que_te_pondrias_en_las_piernas.png Binary files differ diff --git a/src/carteles/que_te_pondrias_en_los_pies.png b/src/carteles/que_te_pondrias_en_los_pies.png new file mode 100644 index 0000000..8c725a0 --- /dev/null +++ b/src/carteles/que_te_pondrias_en_los_pies.png Binary files differ diff --git a/src/carteles/que_te_pondrias_para_ir_a_este_lugar.png b/src/carteles/que_te_pondrias_para_ir_a_este_lugar.png new file mode 100644 index 0000000..30c40d5 --- /dev/null +++ b/src/carteles/que_te_pondrias_para_ir_a_este_lugar.png Binary files differ diff --git a/src/carteles/te_parece_que_hace_frio_o_calor.png b/src/carteles/te_parece_que_hace_frio_o_calor.png new file mode 100644 index 0000000..b5bb1a4 --- /dev/null +++ b/src/carteles/te_parece_que_hace_frio_o_calor.png Binary files differ diff --git a/src/cosas/biquini.jpg b/src/cosas/biquini.jpg new file mode 100644 index 0000000..0c2ddb9 --- /dev/null +++ b/src/cosas/biquini.jpg Binary files differ diff --git a/src/cosas/botas.jpg b/src/cosas/botas.jpg new file mode 100644 index 0000000..0ed646d --- /dev/null +++ b/src/cosas/botas.jpg Binary files differ diff --git a/src/cosas/buzo.jpg b/src/cosas/buzo.jpg new file mode 100644 index 0000000..e18bd60 --- /dev/null +++ b/src/cosas/buzo.jpg Binary files differ diff --git a/src/cosas/camisa.jpg b/src/cosas/camisa.jpg new file mode 100644 index 0000000..bdea36c --- /dev/null +++ b/src/cosas/camisa.jpg Binary files differ diff --git a/src/cosas/championes.jpg b/src/cosas/championes.jpg new file mode 100644 index 0000000..82e4638 --- /dev/null +++ b/src/cosas/championes.jpg Binary files differ diff --git a/src/cosas/chancletas.jpg b/src/cosas/chancletas.jpg new file mode 100644 index 0000000..c19fb4e --- /dev/null +++ b/src/cosas/chancletas.jpg Binary files differ diff --git a/src/cosas/gorrolana.jpg b/src/cosas/gorrolana.jpg new file mode 100644 index 0000000..7a6f747 --- /dev/null +++ b/src/cosas/gorrolana.jpg Binary files differ diff --git a/src/cosas/gorrosol.jpg b/src/cosas/gorrosol.jpg new file mode 100644 index 0000000..99e3678 --- /dev/null +++ b/src/cosas/gorrosol.jpg Binary files differ diff --git a/src/cosas/jeans.jpg b/src/cosas/jeans.jpg new file mode 100644 index 0000000..32bbc82 --- /dev/null +++ b/src/cosas/jeans.jpg Binary files differ diff --git a/src/cosas/lentes.jpg b/src/cosas/lentes.jpg new file mode 100644 index 0000000..d96445c --- /dev/null +++ b/src/cosas/lentes.jpg Binary files differ diff --git a/src/cosas/paraguas.jpg b/src/cosas/paraguas.jpg new file mode 100644 index 0000000..208a3be --- /dev/null +++ b/src/cosas/paraguas.jpg Binary files differ diff --git a/src/cosas/short.jpg b/src/cosas/short.jpg new file mode 100644 index 0000000..c6d5c8d --- /dev/null +++ b/src/cosas/short.jpg Binary files differ diff --git a/src/cosas/sombrero.JPG b/src/cosas/sombrero.JPG new file mode 100644 index 0000000..b02f37f --- /dev/null +++ b/src/cosas/sombrero.JPG Binary files differ diff --git a/src/cosas/vestido.jpg b/src/cosas/vestido.jpg new file mode 100644 index 0000000..11493ec --- /dev/null +++ b/src/cosas/vestido.jpg Binary files differ diff --git a/src/cosas/zapatos.jpg b/src/cosas/zapatos.jpg new file mode 100644 index 0000000..a2d6b1d --- /dev/null +++ b/src/cosas/zapatos.jpg Binary files differ diff --git a/src/data/__init__.py b/src/data/__init__.py new file mode 100644 index 0000000..d0b43b7 --- /dev/null +++ b/src/data/__init__.py @@ -0,0 +1,2 @@ +__author__="nexo" +__date__ ="$17/10/2012 06:23:15 PM$" \ No newline at end of file diff --git a/src/data/__init__.pyo b/src/data/__init__.pyo new file mode 100644 index 0000000..7d41e79 --- /dev/null +++ b/src/data/__init__.pyo Binary files differ diff --git a/src/data/ciudad.py b/src/data/ciudad.py new file mode 100644 index 0000000..f9f5cf7 --- /dev/null +++ b/src/data/ciudad.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- + +__author__="rodripf" +__date__ ="$31/10/2012 12:43:47 PM$" + +from lugar import Lugar + +class Ciudad(Lugar): + def cargarDatos(self): + self.nombre = "ciudad" + self.cosasPermitidas = [("camisa", 2), ("championes", 1), ("jeans", 1), ("vestido", 1), ("zapatos", 1)] diff --git a/src/data/ciudad.pyo b/src/data/ciudad.pyo new file mode 100644 index 0000000..87d1e45 --- /dev/null +++ b/src/data/ciudad.pyo Binary files differ diff --git a/src/data/lugar.py b/src/data/lugar.py new file mode 100644 index 0000000..b394344 --- /dev/null +++ b/src/data/lugar.py @@ -0,0 +1,43 @@ +__author__="nexo" +__date__ ="$17/10/2012 06:24:01 PM$" + +import pygame +from pygame.locals import * +pygame.init() + +import os + +class Lugar(): + def __init__(self, surfDest, posDest): + self.nombre = None + self.cosasPermitidas = [] + + self.cargarDatos() + + self.img = pygame.image.load(os.path.join("lugares", self.nombre + ".jpg")).convert() + + self.posDest = posDest + self.surfDest = surfDest + + surfDest.blit(self.img, posDest) + + + def repaint(self): + self.surfDest.blit(self.img, self.posDest) + + def cargarDatos(self): + """Abstracta""" + pass + + + def chequear(self, objeto): + """Chequea si es correcto un objeto corresponde al lugar""" + for o in self.cosasPermitidas: + if o[0] == objeto: + return True + + return False + + +if __name__ == "__main__": + print "Hello World" diff --git a/src/data/lugar.pyo b/src/data/lugar.pyo new file mode 100644 index 0000000..c6f52a3 --- /dev/null +++ b/src/data/lugar.pyo Binary files differ diff --git a/src/data/lugar.py~ b/src/data/lugar.py~ new file mode 100644 index 0000000..26f9730 --- /dev/null +++ b/src/data/lugar.py~ @@ -0,0 +1,26 @@ +__author__="nexo" +__date__ ="$17/10/2012 06:24:01 PM$" + +import pygame +from pygame.locals import * +pygame.init() + +import os + +class Lugar(): + def __init__(self, surfDest, posDest): + self.nombre = None + self.cosasPermitidas = [] + + self.cargarDatos() + + img = pygame.image.load(os.path.join("lugares", self.nombre + ".jpg")).convert() + surfDest.blit(img, posDest) + + def cargarDatos(self): + """Abstracta""" + pass + + +if __name__ == "__main__": + print "Hello World" diff --git a/src/data/nieve.py b/src/data/nieve.py new file mode 100644 index 0000000..0821195 --- /dev/null +++ b/src/data/nieve.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +from lugar import Lugar + +class Nieve(Lugar): + def cargarDatos(self): + self.nombre = "nieve" + self.cosasPermitidas = [("gorrolana", 2), ("bufanda", 1), ("guantes", 1), ("campera", 1), ("buzo", 2), ("orejeras", 2), ("paraguas", 2)] \ No newline at end of file diff --git a/src/data/nieve.pyo b/src/data/nieve.pyo new file mode 100644 index 0000000..301be00 --- /dev/null +++ b/src/data/nieve.pyo Binary files differ diff --git a/src/data/playa.py b/src/data/playa.py new file mode 100644 index 0000000..2962e41 --- /dev/null +++ b/src/data/playa.py @@ -0,0 +1,15 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="nexo" +__date__ ="$17/10/2012 06:32:45 PM$" + +from lugar import Lugar + +class Playa(Lugar): + def cargarDatos(self): + self.nombre = "playa" + self.cosasPermitidas = [("chancletas", 2), ("gorrosol", 1), ("short", 1), ("biquini", 1), ("lentes", 2), ("sombrero", 3)] + +if __name__ == "__main__": + print "Hello World" diff --git a/src/data/playa.pyo b/src/data/playa.pyo new file mode 100644 index 0000000..f5090b5 --- /dev/null +++ b/src/data/playa.pyo Binary files differ diff --git a/src/dist/QueViaje-1.xo b/src/dist/QueViaje-1.xo new file mode 100644 index 0000000..520eefb --- /dev/null +++ b/src/dist/QueViaje-1.xo Binary files differ diff --git a/src/libzbar.a b/src/libzbar.a new file mode 100644 index 0000000..35f0888 --- /dev/null +++ b/src/libzbar.a Binary files differ diff --git a/src/libzbar.la b/src/libzbar.la new file mode 100644 index 0000000..0f639d6 --- /dev/null +++ b/src/libzbar.la @@ -0,0 +1,41 @@ +# libzbar.la - a libtool library file +# Generated by ltmain.sh (GNU libtool) 2.2.6 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libzbar.so.0' + +# Names of this library. +library_names='libzbar.so.0.2.0 libzbar.so.0 libzbar.so' + +# The name of the static archive. +old_library='libzbar.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -lSM -lICE -lX11 -ljpeg -lpthread -lrt' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libzbar. +current=2 +age=2 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib' diff --git a/src/libzbar.so.0.2.0 b/src/libzbar.so.0.2.0 new file mode 100644 index 0000000..efbf8ba --- /dev/null +++ b/src/libzbar.so.0.2.0 Binary files differ diff --git a/src/lugares/ciudad.jpg b/src/lugares/ciudad.jpg new file mode 100644 index 0000000..3d135af --- /dev/null +++ b/src/lugares/ciudad.jpg Binary files differ diff --git a/src/lugares/nieve.jpg b/src/lugares/nieve.jpg new file mode 100644 index 0000000..98bf62e --- /dev/null +++ b/src/lugares/nieve.jpg Binary files differ diff --git a/src/lugares/playa.jpg b/src/lugares/playa.jpg new file mode 100644 index 0000000..1fcc204 --- /dev/null +++ b/src/lugares/playa.jpg Binary files differ diff --git a/src/pygame/.gitignore b/src/pygame/.gitignore new file mode 100644 index 0000000..a74b07a --- /dev/null +++ b/src/pygame/.gitignore @@ -0,0 +1 @@ +/*.pyc diff --git a/src/pygame/LGPL b/src/pygame/LGPL new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/src/pygame/LGPL @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/pygame/__init__.py b/src/pygame/__init__.py new file mode 100644 index 0000000..1e8727e --- /dev/null +++ b/src/pygame/__init__.py @@ -0,0 +1,304 @@ +## pygame - Python Game Library +## Copyright (C) 2000-2001 Pete Shinners +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Pete Shinners +## pete@shinners.org +"""Pygame is a set of Python modules designed for writing games. +It is written on top of the excellent SDL library. This allows you +to create fully featured games and multimedia programs in the python +language. The package is highly portable, with games running on +Windows, MacOS, OS X, BeOS, FreeBSD, IRIX, and Linux. +""" + +import sys, os, string + +# check if is old windows... if so use directx video driver by default. +# if someone sets this respect their setting... +if not 'SDL_VIDEODRIVER' in os.environ: + # http://docs.python.org/lib/module-sys.html + # 0 (VER_PLATFORM_WIN32s) Win32s on Windows 3.1 + # 1 (VER_PLATFORM_WIN32_WINDOWS) Windows 95/98/ME + # 2 (VER_PLATFORM_WIN32_NT) Windows NT/2000/XP + # 3 (VER_PLATFORM_WIN32_CE) Windows CE + if hasattr(sys, "getwindowsversion"): + try: + if (sys.getwindowsversion()[3] in [1,2] and + sys.getwindowsversion()[0] in [0,1,2,3,4,5]): + os.environ['SDL_VIDEODRIVER'] = 'directx' + except: + pass + + +class MissingModule: + _NOT_IMPLEMENTED_ = True + def __init__(self, name, info='', urgent=0): + self.name = name + self.info = str(info) + try: + exc = sys.exc_info() + if exc[0] != None: + self.reason = "%s: %s" % (exc[0].__name__, str(exc[1])) + else: + self.reason = "" + finally: + del exc + self.urgent = urgent + if urgent: + self.warn() + + def __getattr__(self, var): + if not self.urgent: + self.warn() + self.urgent = 1 + MissingPygameModule = "%s module not available" % self.name + if self.reason: + MissingPygameModule += "\n(%s)" % self.reason + raise NotImplementedError(MissingPygameModule) + + def __nonzero__(self): + return 0 + + def warn(self): + if self.urgent: type = 'import' + else: type = 'use' + message = '%s %s: %s' % (type, self.name, self.info) + if self.reason: + message += "\n(%s)" % self.reason + try: + import warnings + if self.urgent: level = 4 + else: level = 3 + warnings.warn(message, RuntimeWarning, level) + except ImportError: + print (message) + + + +#we need to import like this, each at a time. the cleanest way to import +#our modules is with the import command (not the __import__ function) + +#first, the "required" modules +from pygame.base import * +from pygame.constants import * +from pygame.version import * +from pygame.rect import Rect +from pygame.compat import geterror +import pygame.rwobject +import pygame.surflock +import pygame.color +Color = color.Color +__version__ = ver + +#next, the "standard" modules +#we still allow them to be missing for stripped down pygame distributions +try: import pygame.cdrom +except (ImportError,IOError):cdrom=MissingModule("cdrom", geterror(), 1) + +try: import pygame.cursors +except (ImportError,IOError):cursors=MissingModule("cursors", geterror(), 1) + +try: import pygame.display +except (ImportError,IOError):display=MissingModule("display", geterror(), 1) + +try: import pygame.draw +except (ImportError,IOError):draw=MissingModule("draw", geterror(), 1) + +try: import pygame.event +except (ImportError,IOError):event=MissingModule("event", geterror(), 1) + +try: import pygame.image +except (ImportError,IOError):image=MissingModule("image", geterror(), 1) + +try: import pygame.joystick +except (ImportError,IOError):joystick=MissingModule("joystick", geterror(), 1) + +try: import pygame.key +except (ImportError,IOError):key=MissingModule("key", geterror(), 1) + +try: import pygame.mouse +except (ImportError,IOError):mouse=MissingModule("mouse", geterror(), 1) + +try: import pygame.sprite +except (ImportError,IOError):sprite=MissingModule("sprite", geterror(), 1) + + +try: import pygame.threads +except (ImportError,IOError):threads=MissingModule("threads", geterror(), 1) + + +def warn_unwanted_files(): + """ Used to warn about unneeded old files. + """ + + # a temporary hack to warn about camera.so and camera.pyd. + install_path= os.path.split(pygame.base.__file__)[0] + extension_ext = os.path.splitext(pygame.base.__file__)[1] + + # here are the .so/.pyd files we need to ask to remove. + ext_to_remove = ["camera"] + + # here are the .py/.pyo/.pyc files we need to ask to remove. + py_to_remove = ["color"] + + if os.name == "e32": # Don't warn on Symbian. The color.py is used as a wrapper. + py_to_remove = [] + + # See if any of the files are there. + extension_files = ["%s%s" % (x, extension_ext) for x in ext_to_remove] + + py_files = ["%s%s" % (x, py_ext) + for py_ext in [".py", ".pyc", ".pyo"] + for x in py_to_remove] + + files = py_files + extension_files + + unwanted_files = [] + for f in files: + unwanted_files.append( os.path.join( install_path, f ) ) + + + + ask_remove = [] + for f in unwanted_files: + if os.path.exists(f): + ask_remove.append(f) + + + if ask_remove: + message = "Detected old file(s). Please remove the old files:\n" + + for f in ask_remove: + message += "%s " % f + message += "\nLeaving them there might break pygame. Cheers!\n\n" + + try: + import warnings + level = 4 + warnings.warn(message, RuntimeWarning, level) + except ImportError: + print (message) + + +# disable, because we hopefully don't need it. +#warn_unwanted_files() + + + +try: from pygame.surface import * +except (ImportError,IOError):Surface = lambda:Missing_Function + + +try: + import pygame.mask + from pygame.mask import Mask +except (ImportError,IOError):Mask = lambda:Missing_Function + +try: from pygame.pixelarray import * +except (ImportError,IOError): PixelArray = lambda:Missing_Function + +try: from pygame.overlay import * +except (ImportError,IOError):Overlay = lambda:Missing_Function + +try: import pygame.time +except (ImportError,IOError):time=MissingModule("time", geterror(), 1) + +try: import pygame.transform +except (ImportError,IOError):transform=MissingModule("transform", geterror(), 1) + +#lastly, the "optional" pygame modules +try: + import pygame.font + import pygame.sysfont + pygame.font.SysFont = pygame.sysfont.SysFont + pygame.font.get_fonts = pygame.sysfont.get_fonts + pygame.font.match_font = pygame.sysfont.match_font +except (ImportError,IOError):font=MissingModule("font", geterror(), 0) + +# try and load pygame.mixer_music before mixer, for py2app... +try: + import pygame.mixer_music + #del pygame.mixer_music + #print ("NOTE2: failed importing pygame.mixer_music in lib/__init__.py") +except (ImportError,IOError): + pass + +try: import pygame.mixer +except (ImportError,IOError):mixer=MissingModule("mixer", geterror(), 0) + +try: import pygame.movie +except (ImportError,IOError):movie=MissingModule("movie", geterror(), 0) + +#try: import pygame.movieext +#except (ImportError,IOError):movieext=MissingModule("movieext", geterror(), 0) + +try: import pygame.scrap +except (ImportError,IOError):scrap=MissingModule("scrap", geterror(), 0) + +try: import pygame.surfarray +except (ImportError,IOError):surfarray=MissingModule("surfarray", geterror(), 0) + +try: import pygame.sndarray +except (ImportError,IOError):sndarray=MissingModule("sndarray", geterror(), 0) + +try: import pygame.fastevent +except (ImportError,IOError):fastevent=MissingModule("fastevent", geterror(), 0) + +#there's also a couple "internal" modules not needed +#by users, but putting them here helps "dependency finder" +#programs get everything they need (like py2exe) +try: import pygame.imageext; del pygame.imageext +except (ImportError,IOError):pass + +def packager_imports(): + """ + Some additional things that py2app/py2exe will want to see + """ + import atexit + import Numeric + import numpy + import OpenGL.GL + import pygame.macosx + import pygame.mac_scrap + import pygame.bufferproxy + import pygame.colordict + +#make Rects pickleable +try: + import copy_reg +except ImportError: + import copyreg as copy_reg +def __rect_constructor(x,y,w,h): + return Rect(x,y,w,h) +def __rect_reduce(r): + assert type(r) == Rect + return __rect_constructor, (r.x, r.y, r.w, r.h) +copy_reg.pickle(Rect, __rect_reduce, __rect_constructor) + + +#make Colors pickleable +def __color_constructor(r,g,b,a): + return Color(r,g,b,a) +def __color_reduce(c): + assert type(c) == Color + return __color_constructor, (c.r, c.g, c.b, c.a) +copy_reg.pickle(Color, __color_reduce, __color_constructor) + + + + +#cleanup namespace +del pygame, os, sys, rwobject, surflock, MissingModule, copy_reg, geterror diff --git a/src/pygame/__init__.pyo b/src/pygame/__init__.pyo new file mode 100644 index 0000000..e510208 --- /dev/null +++ b/src/pygame/__init__.pyo Binary files differ diff --git a/src/pygame/_arraysurfarray.so b/src/pygame/_arraysurfarray.so new file mode 100644 index 0000000..19e18a5 --- /dev/null +++ b/src/pygame/_arraysurfarray.so Binary files differ diff --git a/src/pygame/_camera.so b/src/pygame/_camera.so new file mode 100644 index 0000000..a6ab840 --- /dev/null +++ b/src/pygame/_camera.so Binary files differ diff --git a/src/pygame/_camera_opencv_highgui.py b/src/pygame/_camera_opencv_highgui.py new file mode 100644 index 0000000..7709c3c --- /dev/null +++ b/src/pygame/_camera_opencv_highgui.py @@ -0,0 +1,98 @@ + +import pygame +import numpy + +import opencv +#this is important for capturing/displaying images +from opencv import highgui + + + +def list_cameras(): + """ + """ + # -1 for opencv means get any of them. + return [-1] + +def init(): + pass + +def quit(): + pass + + +class Camera: + + def __init__(self, device =0, size = (640,480), mode = "RGB"): + """ + """ + self.camera = highgui.cvCreateCameraCapture(device) + if not self.camera: + raise ValueError ("Could not open camera. Sorry.") + + + def set_controls(self, **kwargs): + """ + """ + + + def set_resolution(self, width, height): + """Sets the capture resolution. (without dialog) + """ + # nothing to do here. + pass + def query_image(self): + return True + + def stop(self): + pass + + def start(self): + # do nothing here... since the camera is already open. + pass + + def get_buffer(self): + """Returns a string containing the raw pixel data. + """ + return self.get_surface().get_buffer() + + def get_image(self, dest_surf = None): + return self.get_surface(dest_surf) + + def get_surface(self, dest_surf = None): + camera = self.camera + + im = highgui.cvQueryFrame(camera) + #convert Ipl image to PIL image + #print type(im) + if im: + xx = opencv.adaptors.Ipl2NumPy(im) + #print type(xx) + #print xx.iscontiguous() + #print dir(xx) + #print xx.shape + xxx = numpy.reshape(xx, (numpy.product(xx.shape),)) + + if xx.shape[2] != 3: + raise ValueError("not sure what to do about this size") + + pg_img = pygame.image.frombuffer(xxx, (xx.shape[1],xx.shape[0]), "RGB") + + # if there is a destination surface given, we blit onto that. + if dest_surf: + dest_surf.blit(pg_img, (0,0)) + return dest_surf + #return pg_img + + + +if __name__ == "__main__": + + # try and use this camera stuff with the pygame camera example. + import pygame.examples.camera + + pygame.camera.Camera = Camera + pygame.camera.list_cameras = list_cameras + pygame.examples.camera.main() + + diff --git a/src/pygame/_camera_vidcapture.py b/src/pygame/_camera_vidcapture.py new file mode 100644 index 0000000..5b6a4f3 --- /dev/null +++ b/src/pygame/_camera_vidcapture.py @@ -0,0 +1,133 @@ + +import pygame + +def list_cameras(): + return [0] + + # this just cycles through all the cameras trying to open them + cameras = [] + for x in range(256): + try: + c = Camera(x) + except: + break + cameras.append(x) + + return cameras + + +def init(): + global vidcap + import vidcap as vc + vidcap = vc + +def quit(): + global vidcap + pass + del vidcap + + + +class Camera: + + def __init__(self, device =0, + size = (640,480), + mode = "RGB", + show_video_window=0): + """device: VideoCapture enumerates the available video capture devices + on your system. If you have more than one device, specify + the desired one here. The device number starts from 0. + + show_video_window: 0 ... do not display a video window (the default) + 1 ... display a video window + + Mainly used for debugging, since the video window + can not be closed or moved around. + """ + self.dev = vidcap.new_Dev(device, show_video_window) + width, height = size + self.dev.setresolution(width, height) + + def display_capture_filter_properties(self): + """Displays a dialog containing the property page of the capture filter. + + For VfW drivers you may find the option to select the resolution most + likely here. + """ + self.dev.displaycapturefilterproperties() + + def display_capture_pin_properties(self): + """Displays a dialog containing the property page of the capture pin. + + For WDM drivers you may find the option to select the resolution most + likely here. + """ + self.dev.displaycapturepinproperties() + + def set_resolution(self, width, height): + """Sets the capture resolution. (without dialog) + """ + self.dev.setresolution(width, height) + + def get_buffer(self): + """Returns a string containing the raw pixel data. + """ + return self.dev.getbuffer() + + def start(self): + """ + """ + def set_controls(self, **kwargs): + """ + """ + + def stop(self): + """ + """ + + def get_image(self, dest_surf = None): + return self.get_surface(dest_surf) + + def get_surface(self, dest_surf = None): + """Returns a pygame Surface. + """ + abuffer, width, height = self.get_buffer() + if abuffer: + if 1: + surf = pygame.image.frombuffer(abuffer, (width, height), "RGB") + + # swap it from a BGR surface to an RGB surface. + r,g,b,a = surf.get_masks() + surf.set_masks((b,g,r,a)) + + r,g,b,a = surf.get_shifts() + surf.set_shifts((b,g,r,a)) + + surf = pygame.transform.flip(surf, 0,1) + + # if there is a destination surface given, we blit onto that. + if dest_surf: + dest_surf.blit(surf, (0,0)) + return dest_surf + + else: + + # Need to flip the image. + surf = pygame.image.fromstring(abuffer, (width, height), "RGB", 1) + # swap it from a BGR surface to an RGB surface. + r,g,b,a = surf.get_masks() + surf.set_masks((b,g,r,a)) + + r,g,b,a = surf.get_shifts() + surf.set_shifts((b,g,r,a)) + return surf + + +if __name__ == "__main__": + import pygame.examples.camera + + pygame.camera.Camera = Camera + pygame.camera.list_cameras = list_cameras + pygame.examples.camera.main() + + diff --git a/src/pygame/_numericsndarray.so b/src/pygame/_numericsndarray.so new file mode 100644 index 0000000..2f23e3c --- /dev/null +++ b/src/pygame/_numericsndarray.so Binary files differ diff --git a/src/pygame/_numericsurfarray.so b/src/pygame/_numericsurfarray.so new file mode 100644 index 0000000..697748f --- /dev/null +++ b/src/pygame/_numericsurfarray.so Binary files differ diff --git a/src/pygame/_numpysndarray.py b/src/pygame/_numpysndarray.py new file mode 100644 index 0000000..58c7fba --- /dev/null +++ b/src/pygame/_numpysndarray.py @@ -0,0 +1,136 @@ +## pygame - Python Game Library +## Copyright (C) 2008 Marcus von Appen +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Marcus von Appen +## mva@sysfault.org + +"""pygame module for accessing sound sample data using numpy + +Functions to convert between numpy arrays and Sound objects. This module +will only be available when pygame can use the external numpy package. + +Sound data is made of thousands of samples per second, and each sample +is the amplitude of the wave at a particular moment in time. For +example, in 22-kHz format, element number 5 of the array is the +amplitude of the wave after 5/22000 seconds. + +Each sample is an 8-bit or 16-bit integer, depending on the data format. +A stereo sound file has two values per sample, while a mono sound file +only has one. +""" + +import pygame +import pygame.mixer as mixer +import numpy + +def _array_samples(sound, raw): + # Info is a (freq, format, stereo) tuple + info = mixer.get_init () + if not info: + raise pygame.error("Mixer not initialized") + fmtbytes = (abs (info[1]) & 0xff) >> 3 + channels = info[2] + if raw: + data = sound.get_buffer ().raw + else: + data = sound.get_buffer () + + shape = (len (data) // fmtbytes, ) + if channels > 1: + shape = (shape[0] // channels, channels) + + # mixer.init () does not support different formats from the ones below, + # so MSB/LSB stuff is silently ignored. + typecode = { 8 : numpy.uint8, # AUDIO_U8 + 16 : numpy.uint16, # AUDIO_U16 / AUDIO_U16SYS + -8 : numpy.int8, # AUDIO_S8 + -16 : numpy.int16 # AUDUI_S16 / AUDIO_S16SYS + }[info[1]] + + array = numpy.fromstring (data, typecode) + array.shape = shape + return array + +def array (sound): + """pygame._numpysndarray.array(Sound): return array + + Copy Sound samples into an array. + + Creates a new array for the sound data and copies the samples. The + array will always be in the format returned from + pygame.mixer.get_init(). + """ + return _array_samples(sound, True) + +def samples (sound): + """pygame._numpysndarray.samples(Sound): return array + + Reference Sound samples into an array. + + Creates a new array that directly references the samples in a Sound + object. Modifying the array will change the Sound. The array will + always be in the format returned from pygame.mixer.get_init(). + """ + # Info is a (freq, format, stereo) tuple + info = pygame.mixer.get_init () + if not info: + raise pygame.error("Mixer not initialized") + fmtbytes = (abs (info[1]) & 0xff) >> 3 + channels = info[2] + data = sound.get_buffer () + + shape = (data.length // fmtbytes, ) + if channels > 1: + shape = (shape[0] // channels, channels) + + # mixer.init () does not support different formats from the ones below, + # so MSB/LSB stuff is silently ignored. + typecode = { 8 : numpy.uint8, # AUDIO_U8 + 16 : numpy.uint16, # AUDIO_U16 + -8 : numpy.int8, # AUDIO_S8 + -16 : numpy.int16 # AUDUI_S16 + }[info[1]] + + array = numpy.frombuffer (data, typecode) + array.shape = shape + return array + +def make_sound (array): + """pygame._numpysndarray.make_sound(array): return Sound + + Convert an array into a Sound object. + + Create a new playable Sound object from an array. The mixer module + must be initialized and the array format must be similar to the mixer + audio format. + """ + # Info is a (freq, format, stereo) tuple + info = pygame.mixer.get_init () + if not info: + raise pygame.error("Mixer not initialized") + channels = info[2] + + shape = array.shape + if channels == 1: + if len (shape) != 1: + raise ValueError("Array must be 1-dimensional for mono mixer") + else: + if len (shape) != 2: + raise ValueError("Array must be 2-dimensional for stereo mixer") + elif shape[1] != channels: + raise ValueError("Array depth must match number of mixer channels") + return mixer.Sound (array) diff --git a/src/pygame/_numpysndarray.pyo b/src/pygame/_numpysndarray.pyo new file mode 100644 index 0000000..85f4e01 --- /dev/null +++ b/src/pygame/_numpysndarray.pyo Binary files differ diff --git a/src/pygame/_numpysurfarray.py b/src/pygame/_numpysurfarray.py new file mode 100644 index 0000000..8eac04d --- /dev/null +++ b/src/pygame/_numpysurfarray.py @@ -0,0 +1,472 @@ +## pygame - Python Game Library +## Copyright (C) 2007 Marcus von Appen +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Marcus von Appen +## mva@sysfault.org + +"""pygame module for accessing surface pixel data using numpy + +Functions to convert pixel data between pygame Surfaces and Numpy +arrays. This module will only be available when pygame can use the +external Numpy package. + +Note, that numpyarray is an optional module. It requires that Numpy is +installed to be used. If not installed, an exception will be raised when +it is used. eg. ImportError: no module named numpy + +Every pixel is stored as a single integer value to represent the red, +green, and blue colors. The 8bit images use a value that looks into a +colormap. Pixels with higher depth use a bit packing process to place +three or four values into a single number. + +The Numpy arrays are indexed by the X axis first, followed by the Y +axis. Arrays that treat the pixels as a single integer are referred to +as 2D arrays. This module can also separate the red, green, and blue +color values into separate indices. These types of arrays are referred +to as 3D arrays, and the last index is 0 for red, 1 for green, and 2 for +blue. + +In contrast to Numeric Numpy does use unsigned 16bit integers, images +with 16bit data will be treated as unsigned integers. +""" + +import pygame +import numpy +import re + +def array2d (surface): + """pygame.numpyarray.array2d (Surface): return array + + copy pixels into a 2d array + + Copy the pixels from a Surface into a 2D array. The bit depth of the + surface will control the size of the integer values, and will work + for any type of pixel format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + bpp = surface.get_bytesize () + if bpp <= 0 or bpp > 4: + raise ValueError("unsupported bit depth for 2D array") + + # Taken from Alex Holkner's pygame-ctypes package. Thanks a lot. + data = surface.get_buffer ().raw + + # Remove extra pitch from each row. + width = surface.get_width () + pitchdiff = surface.get_pitch () - width * bpp + if pitchdiff > 0: + pattern = re.compile ('(%s)%s' % ('.' * width * bpp, '.' * pitchdiff), + flags=re.DOTALL) + data = ''.join (pattern.findall (data)) + + if bpp == 3: + # Pad each triplet of bytes with another zero + pattern = re.compile ('...', flags=re.DOTALL) + data = '\0'.join (pattern.findall (data)) + if pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN: + data += '\0' + else: + data = '\0' + data + bpp = 4 + + typecode = (numpy.uint8, numpy.uint16, None, numpy.int32)[bpp - 1] + array = numpy.fromstring (data, typecode) + array.shape = (surface.get_height (), width) + array = numpy.transpose (array) + return array + + +def pixels2d (surface): + """pygame.numpyarray.pixels2d (Surface): return array + + reference pixels into a 2d array + + Create a new 2D array that directly references the pixel values in a + Surface. Any changes to the array will affect the pixels in the + Surface. This is a fast operation since no data is copied. + + Pixels from a 24-bit Surface cannot be referenced, but all other + Surface bit depths can. + + The Surface this references will remain locked for the lifetime of + the array (see the Surface.lock - lock the Surface memory for pixel + access method). + """ + bpp = surface.get_bytesize () + if bpp == 3 or bpp < 1 or bpp > 4: + raise ValueError("unsupported bit depth for 2D reference array") + + typecode = (numpy.uint8, numpy.uint16, None, numpy.int32)[bpp - 1] + array = numpy.frombuffer (surface.get_buffer (), typecode) + array.shape = surface.get_height (), surface.get_pitch () / bpp + + # Padding correction for certain depth due to padding bytes. + array = array[:,:surface.get_width ()] + array = numpy.transpose (array) + return array + +def array3d (surface): + """pygame.numpyarray.array3d (Surface): return array + + copy pixels into a 3d array + + Copy the pixels from a Surface into a 3D array. The bit depth of the + surface will control the size of the integer values, and will work + for any type of pixel format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + bpp = surface.get_bytesize () + array = array2d (surface) + + # Taken from from Alex Holkner's pygame-ctypes package. Thanks a + # lot. + if bpp == 1: + palette = surface.get_palette () + # Resolve the correct values using the color palette + pal_r = numpy.array ([c[0] for c in palette]) + pal_g = numpy.array ([c[1] for c in palette]) + pal_b = numpy.array ([c[2] for c in palette]) + planes = [numpy.choose (array, pal_r), + numpy.choose (array, pal_g), + numpy.choose (array, pal_b)] + array = numpy.array (planes, numpy.uint8) + array = numpy.transpose (array, (1, 2, 0)) + return array + elif bpp == 2: + # Taken from SDL_GetRGBA. + masks = surface.get_masks () + shifts = surface.get_shifts () + losses = surface.get_losses () + vr = (array & masks[0]) >> shifts[0] + vg = (array & masks[1]) >> shifts[1] + vb = (array & masks[2]) >> shifts[2] + planes = [(vr << losses[0]) + (vr >> (8 - (losses[0] << 1))), + (vg << losses[1]) + (vg >> (8 - (losses[1] << 1))), + (vb << losses[2]) + (vb >> (8 - (losses[2] << 1)))] + array = numpy.array (planes, numpy.uint8) + return numpy.transpose (array, (1, 2, 0)) + else: + masks = surface.get_masks () + shifts = surface.get_shifts () + losses = surface.get_losses () + planes = [((array & masks[0]) >> shifts[0]), # << losses[0], Assume 0 + ((array & masks[1]) >> shifts[1]), # << losses[1], + ((array & masks[2]) >> shifts[2])] # << losses[2]] + array = numpy.array (planes, numpy.uint8) + return numpy.transpose (array, (1, 2, 0)) + +def pixels3d (surface): + """pygame.numpyarray.pixels3d (Surface): return array + + reference pixels into a 3d array + + Create a new 3D array that directly references the pixel values in a + Surface. Any changes to the array will affect the pixels in the + Surface. This is a fast operation since no data is copied. + + This will only work on Surfaces that have 24-bit or 32-bit + formats. Lower pixel formats cannot be referenced. + + The Surface this references will remain locked for the lifetime of + the array (see the Surface.lock - lock the Surface memory for pixel + access method). + """ + bpp = surface.get_bytesize () + if bpp < 3 or bpp > 4: + raise ValueError("unsupported bit depth for 3D reference array") + lilendian = pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN + + start = 0 + step = 0 + + # Check for RGB or BGR surface. + shifts = surface.get_shifts () + if shifts[0] == 16 and shifts[1] == 8 and shifts[2] == 0: + # RGB + if lilendian: + start = 2 + step = -1 + else: + start = 0 + step = 1 + elif shifts[2] == 16 and shifts[1] == 8 and shifts[0] == 0: + # BGR + if lilendian: + start = 0 + step = 1 + else: + start = 2 + step = -1 + else: + raise ValueError("unsupported colormasks for 3D reference array") + + if bpp == 4 and not lilendian: + start += 1 + + array = numpy.ndarray \ + (shape=(surface.get_width (), surface.get_height (), 3), + dtype=numpy.uint8, buffer=surface.get_buffer (), + offset=start, strides=(bpp, surface.get_pitch (),step)) + return array + +def array_alpha (surface): + """pygame.numpyarray.array_alpha (Surface): return array + + copy pixel alphas into a 2d array + + Copy the pixel alpha values (degree of transparency) from a Surface + into a 2D array. This will work for any type of Surface + format. Surfaces without a pixel alpha will return an array with all + opaque values. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + if (surface.get_bytesize () == 1 or + surface.get_alpha () is None or + surface.get_masks ()[3] == 0): + # 1 bpp surfaces and surfaces without per-pixel alpha are always + # fully opaque. + array = numpy.empty (surface.get_width () * surface.get_height (), + numpy.uint8) + array.fill (0xff) + array.shape = surface.get_width (), surface.get_height () + return array + + array = array2d (surface) + if surface.get_bytesize () == 2: + # Taken from SDL_GetRGBA. + va = (array & surface.get_masks ()[3]) >> surface.get_shifts ()[3] + array = ((va << surface.get_losses ()[3]) + + (va >> (8 - (surface.get_losses ()[3] << 1)))) + else: + # Taken from _numericsurfarray.c. + array = array >> surface.get_shifts ()[3] << surface.get_losses ()[3] + array = array.astype (numpy.uint8) + return array + +def pixels_alpha (surface): + """pygame.numpyarray.pixels_alpha (Surface): return array + + reference pixel alphas into a 2d array + + Create a new 2D array that directly references the alpha values + (degree of transparency) in a Surface. Any changes to the array will + affect the pixels in the Surface. This is a fast operation since no + data is copied. + + This can only work on 32-bit Surfaces with a per-pixel alpha value. + + The Surface this array references will remain locked for the + lifetime of the array. + """ + if surface.get_bytesize () != 4: + raise ValueError("unsupported bit depth for alpha reference array") + lilendian = pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN + + # ARGB surface. + start = 0 + + if surface.get_shifts ()[3] == 24 and lilendian: + # RGBA surface. + start = 3 + elif surface.get_shifts ()[3] == 0 and not lilendian: + start = 3 + else: + raise ValueError("unsupported colormasks for alpha reference array") + + array = numpy.ndarray \ + (shape=(surface.get_width (), surface.get_height ()), + dtype=numpy.uint8, buffer=surface.get_buffer (), + offset=start, strides=(4, surface.get_pitch ())) + return array + +def array_colorkey (surface): + """pygame.numpyarray.array_colorkey (Surface): return array + + copy the colorkey values into a 2d array + + Create a new array with the colorkey transparency value from each + pixel. If the pixel matches the colorkey it will be fully + tranparent; otherwise it will be fully opaque. + + This will work on any type of Surface format. If the image has no + colorkey a solid opaque array will be returned. + + This function will temporarily lock the Surface as pixels are + copied. + """ + colorkey = surface.get_colorkey () + if colorkey == None: + # No colorkey, return a solid opaque array. + array = numpy.empty (surface.get_width () * surface.get_height (), + numpy.uint8) + array.fill (0xff) + array.shape = surface.get_width (), surface.get_height () + return array + + # Taken from from Alex Holkner's pygame-ctypes package. Thanks a + # lot. + array = array2d (surface) + # Check each pixel value for the colorkey and mark it as opaque or + # transparent as needed. + val = surface.map_rgb (colorkey) + array = numpy.choose (numpy.equal (array, val), + (numpy.uint8 (0xff), numpy.uint8 (0))) + array.shape = surface.get_width (), surface.get_height () + return array + +def make_surface (array): + """pygame.numpyarray.make_surface (array): return Surface + + copy an array to a new surface + + Create a new Surface that best resembles the data and format on the + array. The array can be 2D or 3D with any sized integer values. + """ + # Taken from from Alex Holkner's pygame-ctypes package. Thanks a + # lot. + bpp = 0 + r = g = b = 0 + shape = array.shape + if len (shape) == 2: + # 2D array + bpp = 8 + r = 0xFF >> 6 << 5 + g = 0xFF >> 5 << 2 + b = 0xFF >> 6 + elif len (shape) == 3 and shape[2] == 3: + bpp = 32 + r = 0xff << 16 + g = 0xff << 8 + b = 0xff + else: + raise ValueError("must be a valid 2d or 3d array") + + surface = pygame.Surface ((shape[0], shape[1]), 0, bpp, (r, g, b, 0)) + blit_array (surface, array) + return surface + +def blit_array (surface, array): + """pygame.numpyarray.blit_array (Surface, array): return None + + blit directly from a array values + + Directly copy values from an array into a Surface. This is faster + than converting the array into a Surface and blitting. The array + must be the same dimensions as the Surface and will completely + replace all pixel values. + + This function will temporarily lock the Surface as the new values + are copied. + """ + bpp = surface.get_bytesize () + if bpp <= 0 or bpp > 4: + raise ValueError("unsupported bit depth for surface") + + shape = array.shape + width = surface.get_width () + + typecode = (numpy.uint8, numpy.uint16, None, numpy.uint32)[bpp - 1] + array = array.astype (typecode) + + # Taken from from Alex Holkner's pygame-ctypes package. Thanks a + # lot. + if len(shape) == 3 and shape[2] == 3: + array = numpy.transpose (array, (1, 0, 2)) + shifts = surface.get_shifts () + losses = surface.get_losses () + array = (array[:,:,::3] >> losses[0] << shifts[0]) | \ + (array[:,:,1::3] >> losses[1] << shifts[1]) | \ + (array[:,:,2::3] >> losses[2] << shifts[2]) + elif len (shape) == 2: + array = numpy.transpose (array) + else: + raise ValueError("must be a valid 2d or 3d array") + + if width != shape[0] or surface.get_height () != shape[1]: + raise ValueError("array must match the surface dimensions") + + itemsize = array.itemsize + data = array.tostring () + + if itemsize > bpp: + # Trim bytes from each element, keep least significant byte(s) + pattern = '%s(%s)' % ('.' * (itemsize - bpp), '.' * bpp) + if pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN: + pattern = '(%s)%s' % ('.' * bpp, '.' * (itemsize - bpp)) + data = ''.join (re.compile (pattern, flags=re.DOTALL).findall (data)) + elif itemsize < bpp: + # Add pad bytes to each element, at most significant end + pad = '\0' * (bpp - itemsize) + pixels = re.compile ('.' * itemsize, flags=re.DOTALL).findall (data) + data = pad.join (pixels) + if pygame.get_sdl_byteorder () == pygame.LIL_ENDIAN: + data = data + pad + else: + data = pad + data + + # Add zeros pad for pitch correction + pitchdiff = surface.get_pitch () - width * bpp + if pitchdiff > 0: + pad = '\0' * pitchdiff + rows = re.compile ('.' * width * bpp, flags=re.DOTALL).findall (data) + data = pad.join (rows) + pad + + surface.get_buffer ().write (data, 0) + +def map_array (surface, array): + """pygame.numpyarray.map_array (Surface, array3d): return array2d + + map a 3d array into a 2d array + + Convert a 3D array into a 2D array. This will use the given Surface + format to control the conversion. Palette surface formats are not + supported. + + Note: arrays do not need to be 3D, as long as the minor axis has + three elements giving the component colours, any array shape can be + used (for example, a single colour can be mapped, or an array of + colours). + """ + # Taken from from Alex Holkner's pygame-ctypes package. Thanks a + # lot. + bpp = surface.get_bytesize () + if bpp <= 1 or bpp > 4: + raise ValueError("unsupported bit depth for surface array") + + shape = array.shape + if shape[-1] != 3: + raise ValueError("array must be a 3d array of 3-value color data") + + shifts = surface.get_shifts () + losses = surface.get_losses () + if array.dtype != numpy.int32: + array = array.astype(numpy.int32) + out = array[...,0] >> losses[0] << shifts[0] + out[...] |= array[...,1] >> losses[1] << shifts[1] + out[...] |= array[...,2] >> losses[2] << shifts[2] + if surface.get_flags() & pygame.SRCALPHA: + out[...] |= numpy.int32(255) >> losses[3] << shifts[3] + return out diff --git a/src/pygame/_numpysurfarray.pyo b/src/pygame/_numpysurfarray.pyo new file mode 100644 index 0000000..612068a --- /dev/null +++ b/src/pygame/_numpysurfarray.pyo Binary files differ diff --git a/src/pygame/base.so b/src/pygame/base.so new file mode 100644 index 0000000..6d7d135 --- /dev/null +++ b/src/pygame/base.so Binary files differ diff --git a/src/pygame/bufferproxy.so b/src/pygame/bufferproxy.so new file mode 100644 index 0000000..623e1c7 --- /dev/null +++ b/src/pygame/bufferproxy.so Binary files differ diff --git a/src/pygame/camera.py b/src/pygame/camera.py new file mode 100644 index 0000000..618e012 --- /dev/null +++ b/src/pygame/camera.py @@ -0,0 +1,144 @@ + +_is_init = 0 + + + +def init(): + global list_cameras, Camera, colorspace, _is_init + + + import os,sys + + use_opencv = False + use_vidcapture = False + use__camera = True + + + if sys.platform == 'win32': + use_vidcapture = True + + elif "linux" in sys.platform: + use__camera = True + + else: + use_opencv = True + + + + # see if we have any user specified defaults in environments. + camera_env = os.environ.get("PYGAME_CAMERA", "") + if camera_env == "opencv": + use_opencv = True + if camera_env == "vidcapture": + use_vidcapture = True + + + + # select the camera module to import here. + + # the _camera module has some code which can be reused by other modules. + # it will also be the default one. + import _camera + colorspace = _camera.colorspace + + if use__camera: + list_cameras = _camera.list_cameras + Camera = _camera.Camera + + if use_opencv: + try: + import _camera_opencv_highgui + except: + _camera_opencv_highgui = None + + if _camera_opencv_highgui: + _camera_opencv_highgui.init() + + list_cameras = _camera_opencv_highgui.list_cameras + Camera = _camera_opencv_highgui.Camera + + if use_vidcapture: + try: + import _camera_vidcapture + except: + _camera_vidcapture = None + + if _camera_vidcapture: + _camera_vidcapture.init() + list_cameras = _camera_vidcapture.list_cameras + Camera = _camera_vidcapture.Camera + + + + _is_init = 1 + pass + + +def quit(): + global _is_init + _is_init = 0 + pass + + +def _check_init(): + global _is_init + if not _is_init: + raise ValueError("Need to call camera.init() before using.") + +def list_cameras(): + """ + """ + _check_init() + raise NotImplementedError() + + +class Camera: + + def __init__(self, device =0, size = (320, 200), mode = "RGB"): + """ + """ + _check_init() + raise NotImplementedError() + + def set_resolution(self, width, height): + """Sets the capture resolution. (without dialog) + """ + pass + + def start(self): + """ + """ + + def stop(self): + """ + """ + + def get_buffer(self): + """ + """ + + def set_controls(self, **kwargs): + """ + """ + + def get_image(self, dest_surf = None): + """ + """ + + def get_surface(self, dest_surf = None): + """ + """ + + + +if __name__ == "__main__": + + # try and use this camera stuff with the pygame camera example. + import pygame.examples.camera + + #pygame.camera.Camera = Camera + #pygame.camera.list_cameras = list_cameras + pygame.examples.camera.main() + + + diff --git a/src/pygame/camera.pyo b/src/pygame/camera.pyo new file mode 100644 index 0000000..8e30504 --- /dev/null +++ b/src/pygame/camera.pyo Binary files differ diff --git a/src/pygame/cdrom.so b/src/pygame/cdrom.so new file mode 100644 index 0000000..228df21 --- /dev/null +++ b/src/pygame/cdrom.so Binary files differ diff --git a/src/pygame/color.so b/src/pygame/color.so new file mode 100644 index 0000000..931bb31 --- /dev/null +++ b/src/pygame/color.so Binary files differ diff --git a/src/pygame/colordict.py b/src/pygame/colordict.py new file mode 100644 index 0000000..75a83d3 --- /dev/null +++ b/src/pygame/colordict.py @@ -0,0 +1,679 @@ +## pygame - Python Game Library +## Copyright (C) 2000-2003 Pete Shinners +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Pete Shinners +## pete@shinners.org + +THECOLORS = { +'gray17' : (43, 43, 43, 255) , +'gold' : (255, 215, 0, 255) , +'gray10' : (26, 26, 26, 255) , +'yellow' : (255, 255, 0, 255) , +'gray11' : (28, 28, 28, 255) , +'grey61' : (156, 156, 156, 255) , +'grey60' : (153, 153, 153, 255) , +'darkseagreen' : (143, 188, 143, 255) , +'grey62' : (158, 158, 158, 255) , +'grey65' : (166, 166, 166, 255) , +'gray12' : (31, 31, 31, 255) , +'grey67' : (171, 171, 171, 255) , +'grey66' : (168, 168, 168, 255) , +'grey69' : (176, 176, 176, 255) , +'gray21' : (54, 54, 54, 255) , +'lightsalmon4' : (139, 87, 66, 255) , +'lightsalmon2' : (238, 149, 114, 255) , +'lightsalmon3' : (205, 129, 98, 255) , +'lightsalmon1' : (255, 160, 122, 255) , +'gray32' : (82, 82, 82, 255) , +'green4' : (0, 139, 0, 255) , +'gray30' : (77, 77, 77, 255) , +'gray31' : (79, 79, 79, 255) , +'green1' : (0, 255, 0, 255) , +'gray37' : (94, 94, 94, 255) , +'green3' : (0, 205, 0, 255) , +'green2' : (0, 238, 0, 255) , +'darkslategray1' : (151, 255, 255, 255) , +'darkslategray2' : (141, 238, 238, 255) , +'darkslategray3' : (121, 205, 205, 255) , +'aquamarine1' : (127, 255, 212, 255) , +'aquamarine3' : (102, 205, 170, 255) , +'aquamarine2' : (118, 238, 198, 255) , +'papayawhip' : (255, 239, 213, 255) , +'black' : (0, 0, 0, 255) , +'darkorange3' : (205, 102, 0, 255) , +'oldlace' : (253, 245, 230, 255) , +'lightgoldenrod4' : (139, 129, 76, 255) , +'gray90' : (229, 229, 229, 255) , +'orchid1' : (255, 131, 250, 255) , +'orchid2' : (238, 122, 233, 255) , +'orchid3' : (205, 105, 201, 255) , +'grey68' : (173, 173, 173, 255) , +'brown' : (165, 42, 42, 255) , +'purple2' : (145, 44, 238, 255) , +'gray80' : (204, 204, 204, 255) , +'antiquewhite3' : (205, 192, 176, 255) , +'antiquewhite2' : (238, 223, 204, 255) , +'antiquewhite1' : (255, 239, 219, 255) , +'palevioletred3' : (205, 104, 137, 255) , +'hotpink' : (255, 105, 180, 255) , +'lightcyan' : (224, 255, 255, 255) , +'coral3' : (205, 91, 69, 255) , +'gray8' : (20, 20, 20, 255) , +'gray9' : (23, 23, 23, 255) , +'grey32' : (82, 82, 82, 255) , +'bisque4' : (139, 125, 107, 255) , +'cyan' : (0, 255, 255, 255) , +'gray0' : (0, 0, 0, 255) , +'gray1' : (3, 3, 3, 255) , +'gray6' : (15, 15, 15, 255) , +'bisque1' : (255, 228, 196, 255) , +'bisque2' : (238, 213, 183, 255) , +'bisque3' : (205, 183, 158, 255) , +'skyblue' : (135, 206, 235, 255) , +'gray' : (190, 190, 190, 255) , +'darkturquoise' : (0, 206, 209, 255) , +'rosybrown4' : (139, 105, 105, 255) , +'deepskyblue3' : (0, 154, 205, 255) , +'grey63' : (161, 161, 161, 255) , +'indianred1' : (255, 106, 106, 255) , +'grey78' : (199, 199, 199, 255) , +'lightpink' : (255, 182, 193, 255) , +'gray88' : (224, 224, 224, 255) , +'gray22' : (56, 56, 56, 255) , +'red' : (255, 0, 0, 255) , +'grey11' : (28, 28, 28, 255) , +'lemonchiffon3' : (205, 201, 165, 255) , +'lemonchiffon2' : (238, 233, 191, 255) , +'lemonchiffon1' : (255, 250, 205, 255) , +'indianred3' : (205, 85, 85, 255) , +'violetred1' : (255, 62, 150, 255) , +'plum2' : (238, 174, 238, 255) , +'plum1' : (255, 187, 255, 255) , +'lemonchiffon4' : (139, 137, 112, 255) , +'gray99' : (252, 252, 252, 255) , +'grey13' : (33, 33, 33, 255) , +'grey55' : (140, 140, 140, 255) , +'darkcyan' : (0, 139, 139, 255) , +'chocolate4' : (139, 69, 19, 255) , +'lightgoldenrodyellow' : (250, 250, 210, 255) , +'gray54' : (138, 138, 138, 255) , +'lavender' : (230, 230, 250, 255) , +'chartreuse3' : (102, 205, 0, 255) , +'chartreuse2' : (118, 238, 0, 255) , +'chartreuse1' : (127, 255, 0, 255) , +'grey48' : (122, 122, 122, 255) , +'grey16' : (41, 41, 41, 255) , +'thistle' : (216, 191, 216, 255) , +'chartreuse4' : (69, 139, 0, 255) , +'darkorchid4' : (104, 34, 139, 255) , +'grey42' : (107, 107, 107, 255) , +'grey41' : (105, 105, 105, 255) , +'grey17' : (43, 43, 43, 255) , +'dimgrey' : (105, 105, 105, 255) , +'dodgerblue4' : (16, 78, 139, 255) , +'darkorchid2' : (178, 58, 238, 255) , +'darkorchid3' : (154, 50, 205, 255) , +'blue' : (0, 0, 255, 255) , +'rosybrown2' : (238, 180, 180, 255) , +'honeydew' : (240, 255, 240, 255) , +'gray18' : (46, 46, 46, 255) , +'cornflowerblue' : (100, 149, 237, 255) , +'grey91' : (232, 232, 232, 255) , +'gray14' : (36, 36, 36, 255) , +'gray15' : (38, 38, 38, 255) , +'gray16' : (41, 41, 41, 255) , +'maroon4' : (139, 28, 98, 255) , +'maroon3' : (205, 41, 144, 255) , +'maroon2' : (238, 48, 167, 255) , +'maroon1' : (255, 52, 179, 255) , +'gray13' : (33, 33, 33, 255) , +'gold3' : (205, 173, 0, 255) , +'gold2' : (238, 201, 0, 255) , +'gold1' : (255, 215, 0, 255) , +'grey79' : (201, 201, 201, 255) , +'palevioletred1' : (255, 130, 171, 255) , +'palevioletred2' : (238, 121, 159, 255) , +'gold4' : (139, 117, 0, 255) , +'gray41' : (105, 105, 105, 255) , +'gray84' : (214, 214, 214, 255) , +'mediumpurple' : (147, 112, 219, 255) , +'rosybrown1' : (255, 193, 193, 255) , +'lightblue2' : (178, 223, 238, 255) , +'lightblue3' : (154, 192, 205, 255) , +'grey57' : (145, 145, 145, 255) , +'lightblue1' : (191, 239, 255, 255) , +'lightblue4' : (104, 131, 139, 255) , +'gray33' : (84, 84, 84, 255) , +'skyblue4' : (74, 112, 139, 255) , +'grey97' : (247, 247, 247, 255) , +'skyblue1' : (135, 206, 255, 255) , +'gray27' : (69, 69, 69, 255) , +'skyblue3' : (108, 166, 205, 255) , +'skyblue2' : (126, 192, 238, 255) , +'lavenderblush1' : (255, 240, 245, 255) , +'darkgrey' : (169, 169, 169, 255) , +'lavenderblush3' : (205, 193, 197, 255) , +'darkslategrey' : (47, 79, 79, 255) , +'lavenderblush4' : (139, 131, 134, 255) , +'deeppink4' : (139, 10, 80, 255) , +'grey99' : (252, 252, 252, 255) , +'gray36' : (92, 92, 92, 255) , +'coral4' : (139, 62, 47, 255) , +'magenta3' : (205, 0, 205, 255) , +'lightskyblue4' : (96, 123, 139, 255) , +'mediumturquoise' : (72, 209, 204, 255) , +'gray34' : (87, 87, 87, 255) , +'floralwhite' : (255, 250, 240, 255) , +'grey39' : (99, 99, 99, 255) , +'grey36' : (92, 92, 92, 255) , +'grey37' : (94, 94, 94, 255) , +'grey34' : (87, 87, 87, 255) , +'gray26' : (66, 66, 66, 255) , +'royalblue2' : (67, 110, 238, 255) , +'grey33' : (84, 84, 84, 255) , +'turquoise1' : (0, 245, 255, 255) , +'grey31' : (79, 79, 79, 255) , +'steelblue1' : (99, 184, 255, 255) , +'sienna4' : (139, 71, 38, 255) , +'steelblue3' : (79, 148, 205, 255) , +'lavenderblush2' : (238, 224, 229, 255) , +'sienna1' : (255, 130, 71, 255) , +'steelblue4' : (54, 100, 139, 255) , +'sienna3' : (205, 104, 57, 255) , +'aquamarine4' : (69, 139, 116, 255) , +'lightyellow1' : (255, 255, 224, 255) , +'lightyellow2' : (238, 238, 209, 255) , +'lightsteelblue' : (176, 196, 222, 255) , +'lightyellow4' : (139, 139, 122, 255) , +'magenta2' : (238, 0, 238, 255) , +'lightskyblue1' : (176, 226, 255, 255) , +'lightgoldenrod' : (238, 221, 130, 255) , +'magenta4' : (139, 0, 139, 255) , +'gray87' : (222, 222, 222, 255) , +'greenyellow' : (173, 255, 47, 255) , +'navajowhite4' : (139, 121, 94, 255) , +'darkslategray4' : (82, 139, 139, 255) , +'olivedrab' : (107, 142, 35, 255) , +'navajowhite1' : (255, 222, 173, 255) , +'navajowhite2' : (238, 207, 161, 255) , +'darkgoldenrod1' : (255, 185, 15, 255) , +'sienna' : (160, 82, 45, 255) , +'blue1' : (0, 0, 255, 255) , +'yellow1' : (255, 255, 0, 255) , +'gray61' : (156, 156, 156, 255) , +'magenta1' : (255, 0, 255, 255) , +'grey52' : (133, 133, 133, 255) , +'orangered4' : (139, 37, 0, 255) , +'palegreen' : (152, 251, 152, 255) , +'gray86' : (219, 219, 219, 255) , +'grey80' : (204, 204, 204, 255) , +'seashell' : (255, 245, 238, 255) , +'royalblue' : (65, 105, 225, 255) , +'firebrick3' : (205, 38, 38, 255) , +'blue4' : (0, 0, 139, 255) , +'peru' : (205, 133, 63, 255) , +'gray60' : (153, 153, 153, 255) , +'aquamarine' : (127, 255, 212, 255) , +'grey53' : (135, 135, 135, 255) , +'tan4' : (139, 90, 43, 255) , +'darkgoldenrod' : (184, 134, 11, 255) , +'tan2' : (238, 154, 73, 255) , +'tan1' : (255, 165, 79, 255) , +'darkslategray' : (47, 79, 79, 255) , +'royalblue3' : (58, 95, 205, 255) , +'red2' : (238, 0, 0, 255) , +'red1' : (255, 0, 0, 255) , +'dodgerblue' : (30, 144, 255, 255) , +'violetred4' : (139, 34, 82, 255) , +'lightyellow' : (255, 255, 224, 255) , +'paleturquoise1' : (187, 255, 255, 255) , +'firebrick2' : (238, 44, 44, 255) , +'mediumaquamarine' : (102, 205, 170, 255) , +'lemonchiffon' : (255, 250, 205, 255) , +'chocolate' : (210, 105, 30, 255) , +'orchid4' : (139, 71, 137, 255) , +'maroon' : (176, 48, 96, 255) , +'gray38' : (97, 97, 97, 255) , +'darkorange4' : (139, 69, 0, 255) , +'mintcream' : (245, 255, 250, 255) , +'darkorange1' : (255, 127, 0, 255) , +'antiquewhite' : (250, 235, 215, 255) , +'darkorange2' : (238, 118, 0, 255) , +'grey18' : (46, 46, 46, 255) , +'grey19' : (48, 48, 48, 255) , +'grey38' : (97, 97, 97, 255) , +'moccasin' : (255, 228, 181, 255) , +'grey10' : (26, 26, 26, 255) , +'chocolate1' : (255, 127, 36, 255) , +'chocolate2' : (238, 118, 33, 255) , +'chocolate3' : (205, 102, 29, 255) , +'saddlebrown' : (139, 69, 19, 255) , +'grey15' : (38, 38, 38, 255) , +'darkslateblue' : (72, 61, 139, 255) , +'lightskyblue' : (135, 206, 250, 255) , +'gray69' : (176, 176, 176, 255) , +'gray68' : (173, 173, 173, 255) , +'deeppink' : (255, 20, 147, 255) , +'gray65' : (166, 166, 166, 255) , +'gray64' : (163, 163, 163, 255) , +'gray67' : (171, 171, 171, 255) , +'gray66' : (168, 168, 168, 255) , +'gray25' : (64, 64, 64, 255) , +'coral' : (255, 127, 80, 255) , +'gray63' : (161, 161, 161, 255) , +'gray62' : (158, 158, 158, 255) , +'goldenrod4' : (139, 105, 20, 255) , +'grey35' : (89, 89, 89, 255) , +'gray89' : (227, 227, 227, 255) , +'goldenrod1' : (255, 193, 37, 255) , +'goldenrod2' : (238, 180, 34, 255) , +'goldenrod3' : (205, 155, 29, 255) , +'springgreen1' : (0, 255, 127, 255) , +'springgreen2' : (0, 238, 118, 255) , +'springgreen3' : (0, 205, 102, 255) , +'springgreen4' : (0, 139, 69, 255) , +'mistyrose1' : (255, 228, 225, 255) , +'sandybrown' : (244, 164, 96, 255) , +'grey30' : (77, 77, 77, 255) , +'seashell2' : (238, 229, 222, 255) , +'seashell3' : (205, 197, 191, 255) , +'tan' : (210, 180, 140, 255) , +'seashell1' : (255, 245, 238, 255) , +'mistyrose3' : (205, 183, 181, 255) , +'magenta' : (255, 0, 255, 255) , +'pink' : (255, 192, 203, 255) , +'ivory2' : (238, 238, 224, 255) , +'ivory1' : (255, 255, 240, 255) , +'lightcyan2' : (209, 238, 238, 255) , +'mediumseagreen' : (60, 179, 113, 255) , +'ivory4' : (139, 139, 131, 255) , +'darkorange' : (255, 140, 0, 255) , +'powderblue' : (176, 224, 230, 255) , +'dodgerblue1' : (30, 144, 255, 255) , +'gray95' : (242, 242, 242, 255) , +'firebrick1' : (255, 48, 48, 255) , +'gray7' : (18, 18, 18, 255) , +'mistyrose4' : (139, 125, 123, 255) , +'tomato' : (255, 99, 71, 255) , +'indianred2' : (238, 99, 99, 255) , +'steelblue2' : (92, 172, 238, 255) , +'gray100' : (255, 255, 255, 255) , +'seashell4' : (139, 134, 130, 255) , +'grey89' : (227, 227, 227, 255) , +'grey88' : (224, 224, 224, 255) , +'grey87' : (222, 222, 222, 255) , +'grey86' : (219, 219, 219, 255) , +'grey85' : (217, 217, 217, 255) , +'grey84' : (214, 214, 214, 255) , +'midnightblue' : (25, 25, 112, 255) , +'grey82' : (209, 209, 209, 255) , +'grey81' : (207, 207, 207, 255) , +'yellow3' : (205, 205, 0, 255) , +'ivory3' : (205, 205, 193, 255) , +'grey22' : (56, 56, 56, 255) , +'gray85' : (217, 217, 217, 255) , +'violetred3' : (205, 50, 120, 255) , +'dodgerblue2' : (28, 134, 238, 255) , +'gray42' : (107, 107, 107, 255) , +'sienna2' : (238, 121, 66, 255) , +'grey72' : (184, 184, 184, 255) , +'grey73' : (186, 186, 186, 255) , +'grey70' : (179, 179, 179, 255) , +'palevioletred' : (219, 112, 147, 255) , +'lightslategray' : (119, 136, 153, 255) , +'grey77' : (196, 196, 196, 255) , +'grey74' : (189, 189, 189, 255) , +'slategray1' : (198, 226, 255, 255) , +'pink1' : (255, 181, 197, 255) , +'mediumpurple1' : (171, 130, 255, 255) , +'pink3' : (205, 145, 158, 255) , +'antiquewhite4' : (139, 131, 120, 255) , +'lightpink1' : (255, 174, 185, 255) , +'honeydew2' : (224, 238, 224, 255) , +'khaki4' : (139, 134, 78, 255) , +'darkolivegreen4' : (110, 139, 61, 255) , +'gray45' : (115, 115, 115, 255) , +'slategray3' : (159, 182, 205, 255) , +'darkolivegreen1' : (202, 255, 112, 255) , +'khaki1' : (255, 246, 143, 255) , +'khaki2' : (238, 230, 133, 255) , +'khaki3' : (205, 198, 115, 255) , +'lavenderblush' : (255, 240, 245, 255) , +'honeydew4' : (131, 139, 131, 255) , +'salmon3' : (205, 112, 84, 255) , +'salmon2' : (238, 130, 98, 255) , +'gray92' : (235, 235, 235, 255) , +'salmon4' : (139, 76, 57, 255) , +'gray49' : (125, 125, 125, 255) , +'gray48' : (122, 122, 122, 255) , +'linen' : (250, 240, 230, 255) , +'burlywood1' : (255, 211, 155, 255) , +'green' : (0, 255, 0, 255) , +'gray47' : (120, 120, 120, 255) , +'blueviolet' : (138, 43, 226, 255) , +'brown2' : (238, 59, 59, 255) , +'brown3' : (205, 51, 51, 255) , +'peachpuff' : (255, 218, 185, 255) , +'brown4' : (139, 35, 35, 255) , +'firebrick4' : (139, 26, 26, 255) , +'azure1' : (240, 255, 255, 255) , +'azure3' : (193, 205, 205, 255) , +'azure2' : (224, 238, 238, 255) , +'azure4' : (131, 139, 139, 255) , +'tomato4' : (139, 54, 38, 255) , +'orange4' : (139, 90, 0, 255) , +'firebrick' : (178, 34, 34, 255) , +'indianred' : (205, 92, 92, 255) , +'orange1' : (255, 165, 0, 255) , +'orange3' : (205, 133, 0, 255) , +'orange2' : (238, 154, 0, 255) , +'darkolivegreen' : (85, 107, 47, 255) , +'gray2' : (5, 5, 5, 255) , +'slategrey' : (112, 128, 144, 255) , +'gray81' : (207, 207, 207, 255) , +'darkred' : (139, 0, 0, 255) , +'gray3' : (8, 8, 8, 255) , +'lightsteelblue1' : (202, 225, 255, 255) , +'lightsteelblue2' : (188, 210, 238, 255) , +'lightsteelblue3' : (162, 181, 205, 255) , +'lightsteelblue4' : (110, 123, 139, 255) , +'tomato3' : (205, 79, 57, 255) , +'gray43' : (110, 110, 110, 255) , +'darkgoldenrod4' : (139, 101, 8, 255) , +'grey50' : (127, 127, 127, 255) , +'yellow4' : (139, 139, 0, 255) , +'mediumorchid' : (186, 85, 211, 255) , +'yellow2' : (238, 238, 0, 255) , +'darkgoldenrod2' : (238, 173, 14, 255) , +'darkgoldenrod3' : (205, 149, 12, 255) , +'chartreuse' : (127, 255, 0, 255) , +'mediumblue' : (0, 0, 205, 255) , +'gray4' : (10, 10, 10, 255) , +'springgreen' : (0, 255, 127, 255) , +'orange' : (255, 165, 0, 255) , +'gray5' : (13, 13, 13, 255) , +'lightsalmon' : (255, 160, 122, 255) , +'gray19' : (48, 48, 48, 255) , +'turquoise' : (64, 224, 208, 255) , +'lightseagreen' : (32, 178, 170, 255) , +'grey8' : (20, 20, 20, 255) , +'grey9' : (23, 23, 23, 255) , +'grey6' : (15, 15, 15, 255) , +'grey7' : (18, 18, 18, 255) , +'grey4' : (10, 10, 10, 255) , +'grey5' : (13, 13, 13, 255) , +'grey2' : (5, 5, 5, 255) , +'grey3' : (8, 8, 8, 255) , +'grey0' : (0, 0, 0, 255) , +'grey1' : (3, 3, 3, 255) , +'gray50' : (127, 127, 127, 255) , +'goldenrod' : (218, 165, 32, 255) , +'grey58' : (148, 148, 148, 255) , +'grey59' : (150, 150, 150, 255) , +'gray51' : (130, 130, 130, 255) , +'grey54' : (138, 138, 138, 255) , +'mediumorchid4' : (122, 55, 139, 255) , +'grey56' : (143, 143, 143, 255) , +'navajowhite3' : (205, 179, 139, 255) , +'mediumorchid1' : (224, 102, 255, 255) , +'grey51' : (130, 130, 130, 255) , +'mediumorchid3' : (180, 82, 205, 255) , +'mediumorchid2' : (209, 95, 238, 255) , +'cyan2' : (0, 238, 238, 255) , +'cyan3' : (0, 205, 205, 255) , +'gray23' : (59, 59, 59, 255) , +'cyan1' : (0, 255, 255, 255) , +'darkgreen' : (0, 100, 0, 255) , +'gray24' : (61, 61, 61, 255) , +'cyan4' : (0, 139, 139, 255) , +'darkviolet' : (148, 0, 211, 255) , +'peachpuff4' : (139, 119, 101, 255) , +'gray28' : (71, 71, 71, 255) , +'slateblue4' : (71, 60, 139, 255) , +'slateblue3' : (105, 89, 205, 255) , +'peachpuff1' : (255, 218, 185, 255) , +'peachpuff2' : (238, 203, 173, 255) , +'peachpuff3' : (205, 175, 149, 255) , +'gray29' : (74, 74, 74, 255) , +'paleturquoise' : (175, 238, 238, 255) , +'darkgray' : (169, 169, 169, 255) , +'grey25' : (64, 64, 64, 255) , +'darkmagenta' : (139, 0, 139, 255) , +'palegoldenrod' : (238, 232, 170, 255) , +'grey64' : (163, 163, 163, 255) , +'grey12' : (31, 31, 31, 255) , +'deeppink3' : (205, 16, 118, 255) , +'gray79' : (201, 201, 201, 255) , +'gray83' : (212, 212, 212, 255) , +'deeppink2' : (238, 18, 137, 255) , +'burlywood4' : (139, 115, 85, 255) , +'palevioletred4' : (139, 71, 93, 255) , +'deeppink1' : (255, 20, 147, 255) , +'slateblue2' : (122, 103, 238, 255) , +'grey46' : (117, 117, 117, 255) , +'royalblue4' : (39, 64, 139, 255) , +'yellowgreen' : (154, 205, 50, 255) , +'royalblue1' : (72, 118, 255, 255) , +'slateblue1' : (131, 111, 255, 255) , +'lightgoldenrod3' : (205, 190, 112, 255) , +'lightgoldenrod2' : (238, 220, 130, 255) , +'navy' : (0, 0, 128, 255) , +'orchid' : (218, 112, 214, 255) , +'ghostwhite' : (248, 248, 255, 255) , +'purple' : (160, 32, 240, 255) , +'darkkhaki' : (189, 183, 107, 255) , +'grey45' : (115, 115, 115, 255) , +'gray94' : (240, 240, 240, 255) , +'wheat4' : (139, 126, 102, 255) , +'gray96' : (245, 245, 245, 255) , +'gray97' : (247, 247, 247, 255) , +'wheat1' : (255, 231, 186, 255) , +'gray91' : (232, 232, 232, 255) , +'wheat3' : (205, 186, 150, 255) , +'wheat2' : (238, 216, 174, 255) , +'indianred4' : (139, 58, 58, 255) , +'coral2' : (238, 106, 80, 255) , +'coral1' : (255, 114, 86, 255) , +'violetred' : (208, 32, 144, 255) , +'rosybrown3' : (205, 155, 155, 255) , +'deepskyblue2' : (0, 178, 238, 255) , +'deepskyblue1' : (0, 191, 255, 255) , +'bisque' : (255, 228, 196, 255) , +'grey49' : (125, 125, 125, 255) , +'khaki' : (240, 230, 140, 255) , +'wheat' : (245, 222, 179, 255) , +'lightslateblue' : (132, 112, 255, 255) , +'mediumpurple3' : (137, 104, 205, 255) , +'gray55' : (140, 140, 140, 255) , +'deepskyblue' : (0, 191, 255, 255) , +'gray98' : (250, 250, 250, 255) , +'steelblue' : (70, 130, 180, 255) , +'aliceblue' : (240, 248, 255, 255) , +'lightskyblue2' : (164, 211, 238, 255) , +'lightskyblue3' : (141, 182, 205, 255) , +'lightslategrey' : (119, 136, 153, 255) , +'blue3' : (0, 0, 205, 255) , +'blue2' : (0, 0, 238, 255) , +'gainsboro' : (220, 220, 220, 255) , +'grey76' : (194, 194, 194, 255) , +'purple3' : (125, 38, 205, 255) , +'plum4' : (139, 102, 139, 255) , +'gray56' : (143, 143, 143, 255) , +'plum3' : (205, 150, 205, 255) , +'plum' : (221, 160, 221, 255) , +'lightgrey' : (211, 211, 211, 255) , +'mediumslateblue' : (123, 104, 238, 255) , +'mistyrose' : (255, 228, 225, 255) , +'lightcyan1' : (224, 255, 255, 255) , +'grey71' : (181, 181, 181, 255) , +'darksalmon' : (233, 150, 122, 255) , +'beige' : (245, 245, 220, 255) , +'grey24' : (61, 61, 61, 255) , +'azure' : (240, 255, 255, 255) , +'honeydew1' : (240, 255, 240, 255) , +'slategray2' : (185, 211, 238, 255) , +'dodgerblue3' : (24, 116, 205, 255) , +'slategray4' : (108, 123, 139, 255) , +'grey27' : (69, 69, 69, 255) , +'lightcyan3' : (180, 205, 205, 255) , +'cornsilk' : (255, 248, 220, 255) , +'tomato1' : (255, 99, 71, 255) , +'gray57' : (145, 145, 145, 255) , +'mediumvioletred' : (199, 21, 133, 255) , +'tomato2' : (238, 92, 66, 255) , +'snow4' : (139, 137, 137, 255) , +'grey75' : (191, 191, 191, 255) , +'snow2' : (238, 233, 233, 255) , +'snow3' : (205, 201, 201, 255) , +'snow1' : (255, 250, 250, 255) , +'grey23' : (59, 59, 59, 255) , +'cornsilk3' : (205, 200, 177, 255) , +'lightcoral' : (240, 128, 128, 255) , +'orangered' : (255, 69, 0, 255) , +'navajowhite' : (255, 222, 173, 255) , +'mediumpurple2' : (159, 121, 238, 255) , +'slategray' : (112, 128, 144, 255) , +'pink2' : (238, 169, 184, 255) , +'grey29' : (74, 74, 74, 255) , +'grey28' : (71, 71, 71, 255) , +'gray82' : (209, 209, 209, 255) , +'burlywood' : (222, 184, 135, 255) , +'mediumpurple4' : (93, 71, 139, 255) , +'mediumspringgreen' : (0, 250, 154, 255) , +'grey26' : (66, 66, 66, 255) , +'grey21' : (54, 54, 54, 255) , +'grey20' : (51, 51, 51, 255) , +'blanchedalmond' : (255, 235, 205, 255) , +'pink4' : (139, 99, 108, 255) , +'gray78' : (199, 199, 199, 255) , +'tan3' : (205, 133, 63, 255) , +'gray76' : (194, 194, 194, 255) , +'gray77' : (196, 196, 196, 255) , +'white' : (255, 255, 255, 255) , +'gray75' : (191, 191, 191, 255) , +'gray72' : (184, 184, 184, 255) , +'gray73' : (186, 186, 186, 255) , +'gray70' : (179, 179, 179, 255) , +'gray71' : (181, 181, 181, 255) , +'lightgray' : (211, 211, 211, 255) , +'ivory' : (255, 255, 240, 255) , +'gray46' : (117, 117, 117, 255) , +'gray74' : (189, 189, 189, 255) , +'lightyellow3' : (205, 205, 180, 255) , +'lightpink2' : (238, 162, 173, 255) , +'lightpink3' : (205, 140, 149, 255) , +'paleturquoise4' : (102, 139, 139, 255) , +'lightpink4' : (139, 95, 101, 255) , +'paleturquoise3' : (150, 205, 205, 255) , +'seagreen4' : (46, 139, 87, 255) , +'seagreen3' : (67, 205, 128, 255) , +'seagreen2' : (78, 238, 148, 255) , +'seagreen1' : (84, 255, 159, 255) , +'paleturquoise2' : (174, 238, 238, 255) , +'gray52' : (133, 133, 133, 255) , +'cornsilk4' : (139, 136, 120, 255) , +'cornsilk2' : (238, 232, 205, 255) , +'darkolivegreen3' : (162, 205, 90, 255) , +'cornsilk1' : (255, 248, 220, 255) , +'limegreen' : (50, 205, 50, 255) , +'darkolivegreen2' : (188, 238, 104, 255) , +'grey' : (190, 190, 190, 255) , +'violetred2' : (238, 58, 140, 255) , +'salmon1' : (255, 140, 105, 255) , +'grey92' : (235, 235, 235, 255) , +'grey93' : (237, 237, 237, 255) , +'grey94' : (240, 240, 240, 255) , +'grey95' : (242, 242, 242, 255) , +'grey96' : (245, 245, 245, 255) , +'grey83' : (212, 212, 212, 255) , +'grey98' : (250, 250, 250, 255) , +'lightgoldenrod1' : (255, 236, 139, 255) , +'palegreen1' : (154, 255, 154, 255) , +'red3' : (205, 0, 0, 255) , +'palegreen3' : (124, 205, 124, 255) , +'palegreen2' : (144, 238, 144, 255) , +'palegreen4' : (84, 139, 84, 255) , +'cadetblue' : (95, 158, 160, 255) , +'violet' : (238, 130, 238, 255) , +'mistyrose2' : (238, 213, 210, 255) , +'slateblue' : (106, 90, 205, 255) , +'grey43' : (110, 110, 110, 255) , +'grey90' : (229, 229, 229, 255) , +'gray35' : (89, 89, 89, 255) , +'turquoise3' : (0, 197, 205, 255) , +'turquoise2' : (0, 229, 238, 255) , +'burlywood3' : (205, 170, 125, 255) , +'burlywood2' : (238, 197, 145, 255) , +'lightcyan4' : (122, 139, 139, 255) , +'rosybrown' : (188, 143, 143, 255) , +'turquoise4' : (0, 134, 139, 255) , +'whitesmoke' : (245, 245, 245, 255) , +'lightblue' : (173, 216, 230, 255) , +'grey40' : (102, 102, 102, 255) , +'gray40' : (102, 102, 102, 255) , +'honeydew3' : (193, 205, 193, 255) , +'dimgray' : (105, 105, 105, 255) , +'grey47' : (120, 120, 120, 255) , +'seagreen' : (46, 139, 87, 255) , +'red4' : (139, 0, 0, 255) , +'grey14' : (36, 36, 36, 255) , +'snow' : (255, 250, 250, 255) , +'darkorchid1' : (191, 62, 255, 255) , +'gray58' : (148, 148, 148, 255) , +'gray59' : (150, 150, 150, 255) , +'cadetblue4' : (83, 134, 139, 255) , +'cadetblue3' : (122, 197, 205, 255) , +'cadetblue2' : (142, 229, 238, 255) , +'cadetblue1' : (152, 245, 255, 255) , +'olivedrab4' : (105, 139, 34, 255) , +'purple4' : (85, 26, 139, 255) , +'gray20' : (51, 51, 51, 255) , +'grey44' : (112, 112, 112, 255) , +'purple1' : (155, 48, 255, 255) , +'olivedrab1' : (192, 255, 62, 255) , +'olivedrab2' : (179, 238, 58, 255) , +'olivedrab3' : (154, 205, 50, 255) , +'orangered3' : (205, 55, 0, 255) , +'orangered2' : (238, 64, 0, 255) , +'orangered1' : (255, 69, 0, 255) , +'darkorchid' : (153, 50, 204, 255) , +'thistle3' : (205, 181, 205, 255) , +'thistle2' : (238, 210, 238, 255) , +'thistle1' : (255, 225, 255, 255) , +'salmon' : (250, 128, 114, 255) , +'gray93' : (237, 237, 237, 255) , +'thistle4' : (139, 123, 139, 255) , +'gray39' : (99, 99, 99, 255) , +'lawngreen' : (124, 252, 0, 255) , +'hotpink3' : (205, 96, 144, 255) , +'hotpink2' : (238, 106, 167, 255) , +'hotpink1' : (255, 110, 180, 255) , +'lightgreen' : (144, 238, 144, 255) , +'hotpink4' : (139, 58, 98, 255) , +'darkseagreen4' : (105, 139, 105, 255) , +'darkseagreen3' : (155, 205, 155, 255) , +'darkseagreen2' : (180, 238, 180, 255) , +'darkseagreen1' : (193, 255, 193, 255) , +'deepskyblue4' : (0, 104, 139, 255) , +'gray44' : (112, 112, 112, 255) , +'navyblue' : (0, 0, 128, 255) , +'darkblue' : (0, 0, 139, 255) , +'forestgreen' : (34, 139, 34, 255) , +'gray53' : (135, 135, 135, 255) , +'grey100' : (255, 255, 255, 255) , +'brown1' : (255, 64, 64, 255) , +} diff --git a/src/pygame/colordict.pyo b/src/pygame/colordict.pyo new file mode 100644 index 0000000..44f5ad3 --- /dev/null +++ b/src/pygame/colordict.pyo Binary files differ diff --git a/src/pygame/compat.py b/src/pygame/compat.py new file mode 100644 index 0000000..49cefc1 --- /dev/null +++ b/src/pygame/compat.py @@ -0,0 +1,47 @@ +"""Python 2.x/3.x compatibility tools""" + +import sys + +__all__ = ['geterror', 'long_', 'xrange_', 'ord_', 'unichr_', + 'unicode_', 'raw_input_'] + +def geterror (): + return sys.exc_info()[1] + +try: + long_ = long +except NameError: + long_ = int + +try: + xrange_ = xrange +except NameError: + xrange_ = range + +def get_BytesIO(): + try: + from cStringIO import StringIO as BytesIO + except ImportError: + from io import BytesIO + return BytesIO + +def ord_(o): + try: + return ord(o) + except TypeError: + return o + +try: + unichr_ = unichr +except NameError: + unichr_ = chr + +try: + unicode_ = unicode +except NameError: + unicode_ = str + +try: + raw_input_ = raw_input +except NameError: + raw_input_ = input diff --git a/src/pygame/compat.pyo b/src/pygame/compat.pyo new file mode 100644 index 0000000..6494a76 --- /dev/null +++ b/src/pygame/compat.pyo Binary files differ diff --git a/src/pygame/constants.so b/src/pygame/constants.so new file mode 100644 index 0000000..e985921 --- /dev/null +++ b/src/pygame/constants.so Binary files differ diff --git a/src/pygame/cursors.py b/src/pygame/cursors.py new file mode 100644 index 0000000..80e20df --- /dev/null +++ b/src/pygame/cursors.py @@ -0,0 +1,300 @@ +## pygame - Python Game Library +## Copyright (C) 2000-2003 Pete Shinners +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Pete Shinners +## pete@shinners.org + +"""Set of cursor resources available for use. These cursors come +in a sequence of values that are needed as the arguments for +pygame.mouse.set_cursor(). to dereference the sequence in place +and create the cursor in one step, call like this; +pygame.mouse.set_cursor(*pygame.cursors.arrow). + +Here is a list of available cursors; arrow, diamond, ball, + broken_x, tri_left, tri_right + +There is also a sample string cursor named 'thickarrow_strings'. +The compile() function can convert these string cursors into cursor byte data. +""" + +#default pygame black arrow +arrow = ((16, 16), (0, 0), + (0x00,0x00,0x40,0x00,0x60,0x00,0x70,0x00,0x78,0x00,0x7C,0x00,0x7E,0x00,0x7F,0x00, + 0x7F,0x80,0x7C,0x00,0x6C,0x00,0x46,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x00,0x00), + (0x40,0x00,0xE0,0x00,0xF0,0x00,0xF8,0x00,0xFC,0x00,0xFE,0x00,0xFF,0x00,0xFF,0x80, + 0xFF,0xC0,0xFF,0x80,0xFE,0x00,0xEF,0x00,0x4F,0x00,0x07,0x80,0x07,0x80,0x03,0x00)) + +diamond = ((16, 16), (7, 7), + (0, 0, 1, 0, 3, 128, 7, 192, 14, 224, 28, 112, 56, 56, 112, 28, 56, + 56, 28, 112, 14, 224, 7, 192, 3, 128, 1, 0, 0, 0, 0, 0), + (1, 0, 3, 128, 7, 192, 15, 224, 31, 240, 62, 248, 124, 124, 248, 62, + 124, 124, 62, 248, 31, 240, 15, 224, 7, 192, 3, 128, 1, 0, 0, 0)) + +ball = ((16, 16), (7, 7), + (0, 0, 3, 192, 15, 240, 24, 248, 51, 252, 55, 252, 127, 254, 127, 254, + 127, 254, 127, 254, 63, 252, 63, 252, 31, 248, 15, 240, 3, 192, 0, 0), + (3, 192, 15, 240, 31, 248, 63, 252, 127, 254, 127, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 127, 254, 127, 254, 63, 252, 31, 248, 15, 240, + 3, 192)) + +broken_x = ((16, 16), (7, 7), + (0, 0, 96, 6, 112, 14, 56, 28, 28, 56, 12, 48, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 48, 28, 56, 56, 28, 112, 14, 96, 6, 0, 0), + (224, 7, 240, 15, 248, 31, 124, 62, 62, 124, 30, 120, 14, 112, 0, 0, 0, + 0, 14, 112, 30, 120, 62, 124, 124, 62, 248, 31, 240, 15, 224, 7)) + + +tri_left = ((16, 16), (1, 1), + (0, 0, 96, 0, 120, 0, 62, 0, 63, 128, 31, 224, 31, 248, 15, 254, 15, 254, + 7, 128, 7, 128, 3, 128, 3, 128, 1, 128, 1, 128, 0, 0), + (224, 0, 248, 0, 254, 0, 127, 128, 127, 224, 63, 248, 63, 254, 31, 255, + 31, 255, 15, 254, 15, 192, 7, 192, 7, 192, 3, 192, 3, 192, 1, 128)) + +tri_right = ((16, 16), (14, 1), + (0, 0, 0, 6, 0, 30, 0, 124, 1, 252, 7, 248, 31, 248, 127, 240, 127, 240, + 1, 224, 1, 224, 1, 192, 1, 192, 1, 128, 1, 128, 0, 0), + (0, 7, 0, 31, 0, 127, 1, 254, 7, 254, 31, 252, 127, 252, 255, 248, 255, + 248, 127, 240, 3, 240, 3, 224, 3, 224, 3, 192, 3, 192, 1, 128)) + + + +#here is an example string resource cursor. to use this; +# curs, mask = pygame.cursors.compile_cursor(pygame.cursors.thickarrow_strings, 'X', '.') +# pygame.mouse.set_cursor((24, 24), (0, 0), curs, mask) + +thickarrow_strings = ( #sized 24x24 + "XX ", + "XXX ", + "XXXX ", + "XX.XX ", + "XX..XX ", + "XX...XX ", + "XX....XX ", + "XX.....XX ", + "XX......XX ", + "XX.......XX ", + "XX........XX ", + "XX........XXX ", + "XX......XXXXX ", + "XX.XXX..XX ", + "XXXX XX..XX ", + "XX XX..XX ", + " XX..XX ", + " XX..XX ", + " XX..XX ", + " XXXX ", + " XX ", + " ", + " ", + " ", +) + +sizer_x_strings = ( #sized 24x16 + " X X ", + " XX XX ", + " X.X X.X ", + " X..X X..X ", + " X...XXXXXXXX...X ", + "X................X ", + " X...XXXXXXXX...X ", + " X..X X..X ", + " X.X X.X ", + " XX XX ", + " X X ", + " ", + " ", + " ", + " ", + " ", +) +sizer_y_strings = ( #sized 16x24 + " X ", + " X.X ", + " X...X ", + " X.....X ", + " X.......X ", + "XXXXX.XXXXX ", + " X.X ", + " X.X ", + " X.X ", + " X.X ", + " X.X ", + " X.X ", + " X.X ", + "XXXXX.XXXXX ", + " X.......X ", + " X.....X ", + " X...X ", + " X.X ", + " X ", + " ", + " ", + " ", + " ", + " ", +) +sizer_xy_strings = ( #sized 24x16 + "XXXXXXXX ", + "X.....X ", + "X....X ", + "X...X ", + "X..X.X ", + "X.X X.X ", + "XX X.X X ", + "X X.X XX ", + " X.XX.X ", + " X...X ", + " X...X ", + " X....X ", + " X.....X ", + " XXXXXXXX ", + " ", + " ", +) +textmarker_strings = ( #sized 8x16 + "ooo ooo ", + " o ", + " o ", + " o ", + " o ", + " o ", + " o ", + " o ", + " o ", + " o ", + " o ", + "ooo ooo ", + " ", + " ", + " ", + " ", +) + + + +def compile(strings, black='X', white='.',xor='o'): + """pygame.cursors.compile(strings, black, white,xor) -> data, mask +compile cursor strings into cursor data + +This takes a set of strings with equal length and computes +the binary data for that cursor. The string widths must be +divisible by 8. + +The black and white arguments are single letter strings that +tells which characters will represent black pixels, and which +characters represent white pixels. All other characters are +considered clear. + +This returns a tuple containing the cursor data and cursor mask +data. Both these arguments are used when setting a cursor with +pygame.mouse.set_cursor(). +""" + + #first check for consistent lengths + size = len(strings[0]), len(strings) + if size[0] % 8 or size[1] % 8: + raise ValueError("cursor string sizes must be divisible by 8 %s" % + size) + for s in strings[1:]: + if len(s) != size[0]: + raise ValueError("Cursor strings are inconsistent lengths") + + #create the data arrays. + #this could stand a little optimizing + maskdata = [] + filldata = [] + maskitem = fillitem = 0 + step = 8 + for s in strings: + for c in s: + maskitem = maskitem << 1 + fillitem = fillitem << 1 + step = step - 1 + if c == black: + maskitem = maskitem | 1 + elif c == white: + maskitem = maskitem | 1 + fillitem = fillitem | 1 + elif c == xor: + fillitem = fillitem | 1 + if not step: + maskdata.append(maskitem) + filldata.append(fillitem) + maskitem = fillitem = 0 + step = 8 + return tuple(filldata), tuple(maskdata) + + + + +def load_xbm(curs, mask): + """pygame.cursors.load_xbm(cursorfile, maskfile) -> cursor_args +reads a pair of XBM files into set_cursor arguments + +Arguments can either be filenames or filelike objects +with the readlines method. Not largely tested, but +should work with typical XBM files. +""" + def bitswap(num): + val = 0 + for x in range(8): + b = num&(1< 1: + os.chdir(os.path.dirname(sys.argv[0])) + return True diff --git a/src/pygame/mask.so b/src/pygame/mask.so new file mode 100644 index 0000000..1d5b787 --- /dev/null +++ b/src/pygame/mask.so Binary files differ diff --git a/src/pygame/midi.py b/src/pygame/midi.py new file mode 100644 index 0000000..4620b92 --- /dev/null +++ b/src/pygame/midi.py @@ -0,0 +1,615 @@ +"""pygame.midi +pygame module for interacting with midi input and output. + +The midi module can send output to midi devices, and get input +from midi devices. It can also list midi devices on the system. + +Including real midi devices, and virtual ones. + +It uses the portmidi library. Is portable to which ever platforms +portmidi supports (currently windows, OSX, and linux). + +This uses pyportmidi for now, but may use its own bindings at some +point in the future. The pyportmidi bindings are included with pygame. + +New in pygame 1.9.0. +""" + + +#TODO: +# - finish writing tests. +# - likely as interactive tests... so you'd need to plug in a midi device. +# - create a background thread version for input threads. +# - that can automatically inject input into the event queue +# once the input object is running. Like joysticks. + + + + +import pygame +import pygame.locals + +import atexit + + +# +MIDIIN = pygame.locals.USEREVENT + 10 +MIDIOUT = pygame.locals.USEREVENT + 11 + +_init = False +_pypm = None + + +__all__ = [ "Input", + "MIDIIN", + "MIDIOUT", + "MidiException", + "Output", + "get_count", + "get_default_input_id", + "get_default_output_id", + "get_device_info", + "init", + "midis2events", + "quit", + "time", + ] + +__theclasses__ = ["Input", "Output"] + + +def init(): + """initialize the midi module + pygame.midi.init(): return None + + Call the initialisation function before using the midi module. + + It is safe to call this more than once. + """ + global _init, _pypm + if not _init: + import pygame.pypm + _pypm = pygame.pypm + + _pypm.Initialize() + _init = True + atexit.register(quit) + + +def quit(): + """uninitialize the midi module + pygame.midi.quit(): return None + + + Called automatically atexit if you don't call it. + + It is safe to call this function more than once. + """ + global _init, _pypm + if _init: + # TODO: find all Input and Output classes and close them first? + _pypm.Terminate() + _init = False + del _pypm + #del pygame._pypm + +def _check_init(): + if not _init: + raise RuntimeError("pygame.midi not initialised.") + +def get_count(): + """gets the number of devices. + pygame.midi.get_count(): return num_devices + + + Device ids range from 0 to get_count() -1 + """ + _check_init() + return _pypm.CountDevices() + + + + +def get_default_input_id(): + """gets default input device number + pygame.midi.get_default_input_id(): return default_id + + + Return the default device ID or -1 if there are no devices. + The result can be passed to the Input()/Ouput() class. + + On the PC, the user can specify a default device by + setting an environment variable. For example, to use device #1. + + set PM_RECOMMENDED_INPUT_DEVICE=1 + + The user should first determine the available device ID by using + the supplied application "testin" or "testout". + + In general, the registry is a better place for this kind of info, + and with USB devices that can come and go, using integers is not + very reliable for device identification. Under Windows, if + PM_RECOMMENDED_OUTPUT_DEVICE (or PM_RECOMMENDED_INPUT_DEVICE) is + *NOT* found in the environment, then the default device is obtained + by looking for a string in the registry under: + HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Input_Device + and HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Output_Device + for a string. The number of the first device with a substring that + matches the string exactly is returned. For example, if the string + in the registry is "USB", and device 1 is named + "In USB MidiSport 1x1", then that will be the default + input because it contains the string "USB". + + In addition to the name, get_device_info() returns "interf", which + is the interface name. (The "interface" is the underlying software + system or API used by PortMidi to access devices. Examples are + MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.) + At present, the only Win32 interface is "MMSystem", the only Linux + interface is "ALSA", and the only Max OS X interface is "CoreMIDI". + To specify both the interface and the device name in the registry, + separate the two with a comma and a space, e.g.: + MMSystem, In USB MidiSport 1x1 + In this case, the string before the comma must be a substring of + the "interf" string, and the string after the space must be a + substring of the "name" name string in order to match the device. + + Note: in the current release, the default is simply the first device + (the input or output device with the lowest PmDeviceID). + """ + return _pypm.GetDefaultInputDeviceID() + + + + +def get_default_output_id(): + """gets default output device number + pygame.midi.get_default_output_id(): return default_id + + + Return the default device ID or -1 if there are no devices. + The result can be passed to the Input()/Ouput() class. + + On the PC, the user can specify a default device by + setting an environment variable. For example, to use device #1. + + set PM_RECOMMENDED_OUTPUT_DEVICE=1 + + The user should first determine the available device ID by using + the supplied application "testin" or "testout". + + In general, the registry is a better place for this kind of info, + and with USB devices that can come and go, using integers is not + very reliable for device identification. Under Windows, if + PM_RECOMMENDED_OUTPUT_DEVICE (or PM_RECOMMENDED_INPUT_DEVICE) is + *NOT* found in the environment, then the default device is obtained + by looking for a string in the registry under: + HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Input_Device + and HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Output_Device + for a string. The number of the first device with a substring that + matches the string exactly is returned. For example, if the string + in the registry is "USB", and device 1 is named + "In USB MidiSport 1x1", then that will be the default + input because it contains the string "USB". + + In addition to the name, get_device_info() returns "interf", which + is the interface name. (The "interface" is the underlying software + system or API used by PortMidi to access devices. Examples are + MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.) + At present, the only Win32 interface is "MMSystem", the only Linux + interface is "ALSA", and the only Max OS X interface is "CoreMIDI". + To specify both the interface and the device name in the registry, + separate the two with a comma and a space, e.g.: + MMSystem, In USB MidiSport 1x1 + In this case, the string before the comma must be a substring of + the "interf" string, and the string after the space must be a + substring of the "name" name string in order to match the device. + + Note: in the current release, the default is simply the first device + (the input or output device with the lowest PmDeviceID). + """ + _check_init() + return _pypm.GetDefaultOutputDeviceID() + + +def get_device_info(an_id): + """ returns information about a midi device + pygame.midi.get_device_info(an_id): return (interf, name, input, output, opened) + + interf - a text string describing the device interface, eg 'ALSA'. + name - a text string for the name of the device, eg 'Midi Through Port-0' + input - 0, or 1 if the device is an input device. + output - 0, or 1 if the device is an output device. + opened - 0, or 1 if the device is opened. + + If the id is out of range, the function returns None. + """ + _check_init() + return _pypm.GetDeviceInfo(an_id) + + +class Input(object): + """Input is used to get midi input from midi devices. + Input(device_id) + Input(device_id, buffer_size) + + buffer_size -the number of input events to be buffered waiting to + be read using Input.read() + """ + + def __init__(self, device_id, buffer_size=4096): + """ + The buffer_size specifies the number of input events to be buffered + waiting to be read using Input.read(). + """ + _check_init() + + if device_id == -1: + raise MidiException("Device id is -1, not a valid output id. -1 usually means there were no default Output devices.") + + try: + r = get_device_info(device_id) + except TypeError: + raise TypeError("an integer is required") + except OverflowError: + raise OverflowError("long int too large to convert to int") + + # and now some nasty looking error checking, to provide nice error + # messages to the kind, lovely, midi using people of whereever. + if r: + interf, name, input, output, opened = r + if input: + try: + self._input = _pypm.Input(device_id, buffer_size) + except TypeError: + raise TypeError("an integer is required") + self.device_id = device_id + + elif output: + raise MidiException("Device id given is not a valid input id, it is an output id.") + else: + raise MidiException("Device id given is not a valid input id.") + else: + raise MidiException("Device id invalid, out of range.") + + + + + def _check_open(self): + if self._input is None: + raise MidiException("midi not open.") + + + + def close(self): + """ closes a midi stream, flushing any pending buffers. + Input.close(): return None + + PortMidi attempts to close open streams when the application + exits -- this is particularly difficult under Windows. + """ + _check_init() + if not (self._input is None): + self._input.Close() + self._input = None + + + + def read(self, num_events): + """reads num_events midi events from the buffer. + Input.read(num_events): return midi_event_list + + Reads from the Input buffer and gives back midi events. + [[[status,data1,data2,data3],timestamp], + [[status,data1,data2,data3],timestamp],...] + """ + _check_init() + self._check_open() + return self._input.Read(num_events) + + + def poll(self): + """returns true if there's data, or false if not. + Input.poll(): return Bool + + raises a MidiException on error. + """ + _check_init() + self._check_open() + + r = self._input.Poll() + if r == _pypm.TRUE: + return True + elif r == _pypm.FALSE: + return False + else: + err_text = GetErrorText(r) + raise MidiException( (r, err_text) ) + + + + +class Output(object): + """Output is used to send midi to an output device + Output(device_id) + Output(device_id, latency = 0) + Output(device_id, buffer_size = 4096) + Output(device_id, latency, buffer_size) + + The buffer_size specifies the number of output events to be + buffered waiting for output. (In some cases -- see below -- + PortMidi does not buffer output at all and merely passes data + to a lower-level API, in which case buffersize is ignored.) + + latency is the delay in milliseconds applied to timestamps to determine + when the output should actually occur. (If latency is < 0, 0 is + assumed.) + + If latency is zero, timestamps are ignored and all output is delivered + immediately. If latency is greater than zero, output is delayed until + the message timestamp plus the latency. (NOTE: time is measured + relative to the time source indicated by time_proc. Timestamps are + absolute, not relative delays or offsets.) In some cases, PortMidi + can obtain better timing than your application by passing timestamps + along to the device driver or hardware. Latency may also help you + to synchronize midi data to audio data by matching midi latency to + the audio buffer latency. + + """ + + def __init__(self, device_id, latency = 0, buffer_size = 4096): + """Output(device_id) + Output(device_id, latency = 0) + Output(device_id, buffer_size = 4096) + Output(device_id, latency, buffer_size) + + The buffer_size specifies the number of output events to be + buffered waiting for output. (In some cases -- see below -- + PortMidi does not buffer output at all and merely passes data + to a lower-level API, in which case buffersize is ignored.) + + latency is the delay in milliseconds applied to timestamps to determine + when the output should actually occur. (If latency is < 0, 0 is + assumed.) + + If latency is zero, timestamps are ignored and all output is delivered + immediately. If latency is greater than zero, output is delayed until + the message timestamp plus the latency. (NOTE: time is measured + relative to the time source indicated by time_proc. Timestamps are + absolute, not relative delays or offsets.) In some cases, PortMidi + can obtain better timing than your application by passing timestamps + along to the device driver or hardware. Latency may also help you + to synchronize midi data to audio data by matching midi latency to + the audio buffer latency. + """ + + _check_init() + self._aborted = 0 + + if device_id == -1: + raise MidiException("Device id is -1, not a valid output id. -1 usually means there were no default Output devices.") + + try: + r = get_device_info(device_id) + except TypeError: + raise TypeError("an integer is required") + except OverflowError: + raise OverflowError("long int too large to convert to int") + + # and now some nasty looking error checking, to provide nice error + # messages to the kind, lovely, midi using people of whereever. + if r: + interf, name, input, output, opened = r + if output: + try: + self._output = _pypm.Output(device_id, latency) + except TypeError: + raise TypeError("an integer is required") + self.device_id = device_id + + elif input: + raise MidiException("Device id given is not a valid output id, it is an input id.") + else: + raise MidiException("Device id given is not a valid output id.") + else: + raise MidiException("Device id invalid, out of range.") + + def _check_open(self): + if self._output is None: + raise MidiException("midi not open.") + + if self._aborted: + raise MidiException("midi aborted.") + + + def close(self): + """ closes a midi stream, flushing any pending buffers. + Output.close(): return None + + PortMidi attempts to close open streams when the application + exits -- this is particularly difficult under Windows. + """ + _check_init() + if not (self._output is None): + self._output.Close() + self._output = None + + def abort(self): + """terminates outgoing messages immediately + Output.abort(): return None + + The caller should immediately close the output port; + this call may result in transmission of a partial midi message. + There is no abort for Midi input because the user can simply + ignore messages in the buffer and close an input device at + any time. + """ + + _check_init() + if self._output: + self._output.Abort() + self._aborted = 1 + + + + + + def write(self, data): + """writes a list of midi data to the Output + Output.write(data) + + writes series of MIDI information in the form of a list: + write([[[status <,data1><,data2><,data3>],timestamp], + [[status <,data1><,data2><,data3>],timestamp],...]) + fields are optional + example: choose program change 1 at time 20000 and + send note 65 with velocity 100 500 ms later. + write([[[0xc0,0,0],20000],[[0x90,60,100],20500]]) + notes: + 1. timestamps will be ignored if latency = 0. + 2. To get a note to play immediately, send MIDI info with + timestamp read from function Time. + 3. understanding optional data fields: + write([[[0xc0,0,0],20000]]) is equivalent to + write([[[0xc0],20000]]) + + Can send up to 1024 elements in your data list, otherwise an + IndexError exception is raised. + """ + _check_init() + self._check_open() + + self._output.Write(data) + + + def write_short(self, status, data1 = 0, data2 = 0): + """write_short(status <, data1><, data2>) + Output.write_short(status) + Output.write_short(status, data1 = 0, data2 = 0) + + output MIDI information of 3 bytes or less. + data fields are optional + status byte could be: + 0xc0 = program change + 0x90 = note on + etc. + data bytes are optional and assumed 0 if omitted + example: note 65 on with velocity 100 + write_short(0x90,65,100) + """ + _check_init() + self._check_open() + self._output.WriteShort(status, data1, data2) + + + def write_sys_ex(self, when, msg): + """writes a timestamped system-exclusive midi message. + Output.write_sys_ex(when, msg) + + msg - can be a *list* or a *string* + when - a timestamp in miliseconds + example: + (assuming o is an onput MIDI stream) + o.write_sys_ex(0,'\\xF0\\x7D\\x10\\x11\\x12\\x13\\xF7') + is equivalent to + o.write_sys_ex(pygame.midi.time(), + [0xF0,0x7D,0x10,0x11,0x12,0x13,0xF7]) + """ + _check_init() + self._check_open() + self._output.WriteSysEx(when, msg) + + + def note_on(self, note, velocity=None, channel = 0): + """turns a midi note on. Note must be off. + Output.note_on(note, velocity=None, channel = 0) + + Turn a note on in the output stream. The note must already + be off for this to work correctly. + """ + if velocity is None: + velocity = 0 + + if not (0 <= channel <= 15): + raise ValueError("Channel not between 0 and 15.") + + self.write_short(0x90+channel, note, velocity) + + def note_off(self, note, velocity=None, channel = 0): + """turns a midi note off. Note must be on. + Output.note_off(note, velocity=None, channel = 0) + + Turn a note off in the output stream. The note must already + be on for this to work correctly. + """ + if velocity is None: + velocity = 0 + + if not (0 <= channel <= 15): + raise ValueError("Channel not between 0 and 15.") + + self.write_short(0x80 + channel, note, velocity) + + + def set_instrument(self, instrument_id, channel = 0): + """select an instrument, with a value between 0 and 127 + Output.set_instrument(instrument_id, channel = 0) + + """ + if not (0 <= instrument_id <= 127): + raise ValueError("Undefined instrument id: %d" % instrument_id) + + if not (0 <= channel <= 15): + raise ValueError("Channel not between 0 and 15.") + + self.write_short(0xc0+channel, instrument_id) + + + +def time(): + """returns the current time in ms of the PortMidi timer + pygame.midi.time(): return time + + The time is reset to 0, when the module is inited. + """ + return _pypm.Time() + + + +def midis2events(midis, device_id): + """converts midi events to pygame events + pygame.midi.midis2events(midis, device_id): return [Event, ...] + + Takes a sequence of midi events and returns list of pygame events. + """ + evs = [] + for midi in midis: + + ((status,data1,data2,data3),timestamp) = midi + + e = pygame.event.Event(MIDIIN, + status=status, + data1=data1, + data2=data2, + data3=data3, + timestamp=timestamp, + vice_id = device_id) + evs.append( e ) + + + return evs + + + + + +class MidiException(Exception): + """exception that pygame.midi functions and classes can raise + MidiException(errno) + """ + def __init__(self, value): + self.parameter = value + def __str__(self): + return repr(self.parameter) + + + diff --git a/src/pygame/mixer.so b/src/pygame/mixer.so new file mode 100644 index 0000000..292a3b4 --- /dev/null +++ b/src/pygame/mixer.so Binary files differ diff --git a/src/pygame/mixer_music.so b/src/pygame/mixer_music.so new file mode 100644 index 0000000..81b6ed2 --- /dev/null +++ b/src/pygame/mixer_music.so Binary files differ diff --git a/src/pygame/mouse.so b/src/pygame/mouse.so new file mode 100644 index 0000000..fd3ffc6 --- /dev/null +++ b/src/pygame/mouse.so Binary files differ diff --git a/src/pygame/overlay.so b/src/pygame/overlay.so new file mode 100644 index 0000000..b5668a1 --- /dev/null +++ b/src/pygame/overlay.so Binary files differ diff --git a/src/pygame/pixelarray.so b/src/pygame/pixelarray.so new file mode 100644 index 0000000..8439472 --- /dev/null +++ b/src/pygame/pixelarray.so Binary files differ diff --git a/src/pygame/pkgdata.py b/src/pygame/pkgdata.py new file mode 100644 index 0000000..3882ad0 --- /dev/null +++ b/src/pygame/pkgdata.py @@ -0,0 +1,66 @@ +""" +pkgdata is a simple, extensible way for a package to acquire data file +resources. + +The getResource function is equivalent to the standard idioms, such as +the following minimal implementation: + + import sys, os + + def getResource(identifier, pkgname=__name__): + pkgpath = os.path.dirname(sys.modules[pkgname].__file__) + path = os.path.join(pkgpath, identifier) + return file(os.path.normpath(path), mode='rb') + +When a __loader__ is present on the module given by __name__, it will defer +getResource to its get_data implementation and return it as a file-like +object (such as StringIO). +""" + +__all__ = ['getResource'] +import sys +import os +from pygame.compat import get_BytesIO +BytesIO = get_BytesIO() + +try: + from pkg_resources import resource_stream, resource_exists +except ImportError: + def resource_exists(package_or_requirement, resource_name): + return False + def resource_stream(package_of_requirement, resource_name): + raise NotImplementedError + +def getResource(identifier, pkgname=__name__): + """ + Acquire a readable object for a given package name and identifier. + An IOError will be raised if the resource can not be found. + + For example: + mydata = getResource('mypkgdata.jpg').read() + + Note that the package name must be fully qualified, if given, such + that it would be found in sys.modules. + + In some cases, getResource will return a real file object. In that + case, it may be useful to use its name attribute to get the path + rather than use it as a file-like object. For example, you may + be handing data off to a C API. + """ + if resource_exists(pkgname, identifier): + return resource_stream(pkgname, identifier) + + mod = sys.modules[pkgname] + fn = getattr(mod, '__file__', None) + if fn is None: + raise IOError("%s has no __file__!" % repr(mod)) + path = os.path.join(os.path.dirname(fn), identifier) + loader = getattr(mod, '__loader__', None) + if loader is not None: + try: + data = loader.get_data(path) + except IOError: + pass + else: + return BytesIO(data) + return open(os.path.normpath(path), 'rb') diff --git a/src/pygame/pkgdata.pyo b/src/pygame/pkgdata.pyo new file mode 100644 index 0000000..68eb279 --- /dev/null +++ b/src/pygame/pkgdata.pyo Binary files differ diff --git a/src/pygame/pygame.ico b/src/pygame/pygame.ico new file mode 100644 index 0000000..9444140 --- /dev/null +++ b/src/pygame/pygame.ico Binary files differ diff --git a/src/pygame/pygame_icon.bmp b/src/pygame/pygame_icon.bmp new file mode 100644 index 0000000..74aea77 --- /dev/null +++ b/src/pygame/pygame_icon.bmp Binary files differ diff --git a/src/pygame/pygame_icon.icns b/src/pygame/pygame_icon.icns new file mode 100644 index 0000000..2610a8d --- /dev/null +++ b/src/pygame/pygame_icon.icns Binary files differ diff --git a/src/pygame/pygame_icon.svg b/src/pygame/pygame_icon.svg new file mode 100644 index 0000000..bbee79d --- /dev/null +++ b/src/pygame/pygame_icon.svg @@ -0,0 +1,259 @@ + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pygame/pygame_icon.tiff b/src/pygame/pygame_icon.tiff new file mode 100644 index 0000000..e779143 --- /dev/null +++ b/src/pygame/pygame_icon.tiff Binary files differ diff --git a/src/pygame/rect.so b/src/pygame/rect.so new file mode 100644 index 0000000..6f158e6 --- /dev/null +++ b/src/pygame/rect.so Binary files differ diff --git a/src/pygame/rwobject.so b/src/pygame/rwobject.so new file mode 100644 index 0000000..5bb0b8d --- /dev/null +++ b/src/pygame/rwobject.so Binary files differ diff --git a/src/pygame/scrap.so b/src/pygame/scrap.so new file mode 100644 index 0000000..b852608 --- /dev/null +++ b/src/pygame/scrap.so Binary files differ diff --git a/src/pygame/sndarray.py b/src/pygame/sndarray.py new file mode 100644 index 0000000..90a1142 --- /dev/null +++ b/src/pygame/sndarray.py @@ -0,0 +1,187 @@ +## pygame - Python Game Library +## Copyright (C) 2008 Marcus von Appen +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Marcus von Appen +## mva@sysfault.org + +"""pygame module for accessing sound sample data + +Functions to convert between Numeric or numpy arrays and Sound +objects. This module will only be available when pygame can use the +external numpy or Numeric package. + +Sound data is made of thousands of samples per second, and each sample +is the amplitude of the wave at a particular moment in time. For +example, in 22-kHz format, element number 5 of the array is the +amplitude of the wave after 5/22000 seconds. + +Each sample is an 8-bit or 16-bit integer, depending on the data format. +A stereo sound file has two values per sample, while a mono sound file +only has one. + +Supported array systems are + + numpy + numeric + +The default will be numpy, if installed. Otherwise, Numeric will be set +as default if installed. If neither numpy nor Numeric are installed, the +module will raise an ImportError. + +The array type to use can be changed at runtime using the use_arraytype() +method, which requires one of the above types as string. + +Note: numpy and Numeric are not completely compatible. Certain array +manipulations, which work for one type, might behave differently or even +completely break for the other. + +Additionally, in contrast to Numeric numpy can use unsigned 16-bit +integers. Sounds with 16-bit data will be treated as unsigned integers, +if the sound sample type requests this. Numeric instead always uses +signed integers for the representation, which is important to keep in +mind, if you use the module's functions and wonder about the values. +""" + +import pygame + +# Global array type setting. See use_arraytype(). +__arraytype = None + +# Try to import the necessary modules. +try: + import pygame._numpysndarray as numpysnd + __hasnumpy = True + __arraytype = "numpy" +except ImportError: + __hasnumpy = False + +try: + import pygame._numericsndarray as numericsnd + __hasnumeric = True + if not __hasnumpy: + __arraytype = "numeric" +except ImportError: + __hasnumeric = False + +if not __hasnumpy and not __hasnumeric: + raise ImportError("no module named numpy or Numeric found") + +def array (sound): + """pygame.sndarray.array(Sound): return array + + Copy Sound samples into an array. + + Creates a new array for the sound data and copies the samples. The + array will always be in the format returned from + pygame.mixer.get_init(). + """ + if __arraytype == "numeric": + return numericsnd.array (sound) + elif __arraytype == "numpy": + return numpysnd.array (sound) + raise NotImplementedError("sound arrays are not supported") + +def samples (sound): + """pygame.sndarray.samples(Sound): return array + + Reference Sound samples into an array. + + Creates a new array that directly references the samples in a Sound + object. Modifying the array will change the Sound. The array will + always be in the format returned from pygame.mixer.get_init(). + """ + if __arraytype == "numeric": + return numericsnd.samples (sound) + elif __arraytype == "numpy": + return numpysnd.samples (sound) + raise NotImplementedError("sound arrays are not supported") + +def make_sound (array): + """pygame.sndarray.make_sound(array): return Sound + + Convert an array into a Sound object. + + Create a new playable Sound object from an array. The mixer module + must be initialized and the array format must be similar to the mixer + audio format. + """ + if __arraytype == "numeric": + return numericsnd.make_sound (array) + elif __arraytype == "numpy": + return numpysnd.make_sound (array) + raise NotImplementedError("sound arrays are not supported") + +def use_arraytype (arraytype): + """pygame.sndarray.use_arraytype (arraytype): return None + + Sets the array system to be used for sound arrays. + + Uses the requested array type for the module functions. + Currently supported array types are: + + numeric + numpy + + If the requested type is not available, a ValueError will be raised. + """ + global __arraytype + + arraytype = arraytype.lower () + if arraytype == "numeric": + if __hasnumeric: + __arraytype = arraytype + else: + raise ValueError("Numeric arrays are not available") + + elif arraytype == "numpy": + if __hasnumpy: + __arraytype = arraytype + else: + raise ValueError("numpy arrays are not available") + else: + raise ValueError("invalid array type") + +def get_arraytype (): + """pygame.sndarray.get_arraytype (): return str + + Gets the currently active array type. + + Returns the currently active array type. This will be a value of the + get_arraytypes() tuple and indicates which type of array module is + used for the array creation. + """ + return __arraytype + +def get_arraytypes (): + """pygame.sndarray.get_arraytypes (): return tuple + + Gets the array system types currently supported. + + Checks, which array system types are available and returns them as a + tuple of strings. The values of the tuple can be used directly in + the use_arraytype () method. + + If no supported array system could be found, None will be returned. + """ + vals = [] + if __hasnumeric: + vals.append ("numeric") + if __hasnumpy: + vals.append ("numpy") + if len (vals) == 0: + return None + return tuple (vals) diff --git a/src/pygame/sndarray.pyo b/src/pygame/sndarray.pyo new file mode 100644 index 0000000..d094140 --- /dev/null +++ b/src/pygame/sndarray.pyo Binary files differ diff --git a/src/pygame/sprite.py b/src/pygame/sprite.py new file mode 100644 index 0000000..5ed2af4 --- /dev/null +++ b/src/pygame/sprite.py @@ -0,0 +1,1423 @@ +## pygame - Python Game Library +## Copyright (C) 2000-2003, 2007 Pete Shinners +## (C) 2004 Joe Wreschnig +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Pete Shinners +## pete@shinners.org + +"""pygame module with basic game object classes + +This module contains several simple classes to be used within games. There +is the main Sprite class and several Group classes that contain Sprites. +The use of these classes is entirely optional when using Pygame. The classes +are fairly lightweight and only provide a starting place for the code +that is common to most games. + +The Sprite class is intended to be used as a base class for the different +types of objects in the game. There is also a base Group class that simply +stores sprites. A game could create new types of Group classes that operate +on specially customized Sprite instances they contain. + +The basic Sprite class can draw the Sprites it contains to a Surface. The +Group.draw() method requires that each Sprite have a Surface.image attribute +and a Surface.rect. The Group.clear() method requires these same attributes, +and can be used to erase all the Sprites with background. There are also +more advanced Groups: pygame.sprite.RenderUpdates() and +pygame.sprite.OrderedUpdates(). + +Lastly, this module contains several collision functions. These help find +sprites inside multiple groups that have intersecting bounding rectangles. +To find the collisions, the Sprites are required to have a Surface.rect +attribute assigned. + +The groups are designed for high efficiency in removing and adding Sprites +to them. They also allow cheap testing to see if a Sprite already exists in +a Group. A given Sprite can exist in any number of groups. A game could use +some groups to control object rendering, and a completely separate set of +groups to control interaction or player movement. Instead of adding type +attributes or bools to a derived Sprite class, consider keeping the +Sprites inside organized Groups. This will allow for easier lookup later +in the game. + +Sprites and Groups manage their relationships with the add() and remove() +methods. These methods can accept a single or multiple targets for +membership. The default initializers for these classes also takes a +single or list of targets for initial membership. It is safe to repeatedly +add and remove the same Sprite from a Group. + +While it is possible to design sprite and group classes that don't derive +from the Sprite and AbstractGroup classes below, it is strongly recommended +that you extend those when you add a Sprite or Group class. + +Sprites are not thread safe. So lock them yourself if using threads. +""" + +##todo +## a group that holds only the 'n' most recent elements. +## sort of like the GroupSingle class, but holding more +## than one sprite +## +## drawing groups that can 'automatically' store the area +## underneath, so the can "clear" without needing a background +## function. obviously a little slower than normal, but nice +## to use in many situations. (also remember it must "clear" +## in the reverse order that it draws :]) +## +## the drawing groups should also be able to take a background +## function, instead of just a background surface. the function +## would take a surface and a rectangle on that surface to erase. +## +## perhaps more types of collision functions? the current two +## should handle just about every need, but perhaps more optimized +## specific ones that aren't quite so general but fit into common +## specialized cases. + +import pygame +from pygame import Rect +from pygame.time import get_ticks + +# Don't depend on pygame.mask if it's not there... +try: + from pygame.mask import from_surface +except: + pass + + +class Sprite(object): + """simple base class for visible game objects + pygame.sprite.Sprite(*groups): return Sprite + + The base class for visible game objects. Derived classes will want to + override the Sprite.update() and assign a Sprite.image and + Sprite.rect attributes. The initializer can accept any number of + Group instances to be added to. + + When subclassing the Sprite, be sure to call the base initializer before + adding the Sprite to Groups. + """ + + def __init__(self, *groups): + self.__g = {} # The groups the sprite is in + if groups: self.add(groups) + + def add(self, *groups): + """add the sprite to groups + Sprite.add(*groups): return None + + Any number of Group instances can be passed as arguments. The + Sprite will be added to the Groups it is not already a member of. + """ + has = self.__g.__contains__ + for group in groups: + if hasattr(group, '_spritegroup'): + if not has(group): + group.add_internal(self) + self.add_internal(group) + else: self.add(*group) + + def remove(self, *groups): + """remove the sprite from groups + Sprite.remove(*groups): return None + + Any number of Group instances can be passed as arguments. The Sprite will + be removed from the Groups it is currently a member of. + """ + has = self.__g.__contains__ + for group in groups: + if hasattr(group, '_spritegroup'): + if has(group): + group.remove_internal(self) + self.remove_internal(group) + else: self.remove(*group) + + def add_internal(self, group): + self.__g[group] = 0 + + def remove_internal(self, group): + del self.__g[group] + + def update(self, *args): + """method to control sprite behavior + Sprite.update(*args): + + The default implementation of this method does nothing; it's just a + convenient "hook" that you can override. This method is called by + Group.update() with whatever arguments you give it. + + There is no need to use this method if not using the convenience + method by the same name in the Group class. + """ + pass + + def kill(self): + """remove the Sprite from all Groups + Sprite.kill(): return None + + The Sprite is removed from all the Groups that contain it. This won't + change anything about the state of the Sprite. It is possible to continue + to use the Sprite after this method has been called, including adding it + to Groups. + """ + for c in self.__g.keys(): + c.remove_internal(self) + self.__g.clear() + + def groups(self): + """list of Groups that contain this Sprite + Sprite.groups(): return group_list + + Return a list of all the Groups that contain this Sprite. + """ + return self.__g.keys() + + def alive(self): + """does the sprite belong to any groups + Sprite.alive(): return bool + + Returns True when the Sprite belongs to one or more Groups. + """ + return (len(self.__g) != 0) + + def __repr__(self): + return "<%s sprite(in %d groups)>" % (self.__class__.__name__, len(self.__g)) + + +class DirtySprite(Sprite): + """a more featureful subclass of Sprite with more attributes + pygame.sprite.DirtySprite(*groups): return DirtySprite + + Extra DirtySprite attributes with their default values: + + dirty = 1 + if set to 1, it is repainted and then set to 0 again + if set to 2 then it is always dirty ( repainted each frame, + flag is not reset) + 0 means that it is not dirty and therefor not repainted again + + blendmode = 0 + its the special_flags argument of blit, blendmodes + + source_rect = None + source rect to use, remember that it is relative to + topleft (0,0) of self.image + + visible = 1 + normally 1, if set to 0 it will not be repainted + (you must set it dirty too to be erased from screen) + + layer = 0 + (READONLY value, it is read when adding it to the + LayeredUpdates, for details see doc of LayeredUpdates) + """ + + def __init__(self, *groups): + + self.dirty = 1 + self.blendmode = 0 # pygame 1.8, reffered as special_flags in + # the documentation of blit + self._visible = 1 + self._layer = 0 # READ ONLY by LayeredUpdates or LayeredDirty + self.source_rect = None + Sprite.__init__(self, *groups) + + def _set_visible(self, val): + """set the visible value (0 or 1) and makes the sprite dirty""" + self._visible = val + if self.dirty < 2: + self.dirty = 1 + + def _get_visible(self): + """returns the visible value of that sprite""" + return self._visible + visible = property(lambda self: self._get_visible(),\ + lambda self, value:self._set_visible(value), \ + doc="you can make this sprite disappear without removing it from the group,\n"+ + "values 0 for invisible and 1 for visible") + + def __repr__(self): + return "<%s DirtySprite(in %d groups)>" % (self.__class__.__name__, len(self.groups())) + + + +class AbstractGroup(object): + """A base for containers for sprites. It does everything + needed to behave as a normal group. You can easily inherit + a new group class from this, or the other groups below, + if you want to add more features. + + Any AbstractGroup-derived sprite groups act like sequences, + and support iteration, len, and so on.""" + + # dummy val to identify sprite groups, and avoid infinite recursion. + _spritegroup = True + + def __init__(self): + self.spritedict = {} + self.lostsprites = [] + + def sprites(self): + """sprites() + get a list of sprites in the group + + Returns an object that can be looped over with a 'for' loop. + (For now it is always a list, but newer version of Python + could return different iterators.) You can also iterate directly + over the sprite group.""" + return list(self.spritedict.keys()) + + def add_internal(self, sprite): + self.spritedict[sprite] = 0 + + def remove_internal(self, sprite): + r = self.spritedict[sprite] + if r is not 0: + self.lostsprites.append(r) + del(self.spritedict[sprite]) + + def has_internal(self, sprite): + return sprite in self.spritedict + + def copy(self): + """copy() + copy a group with all the same sprites + + Returns a copy of the group that is the same class + type, and has the same sprites in it.""" + return self.__class__(self.sprites()) + + def __iter__(self): + return iter(self.sprites()) + + def __contains__(self, sprite): + return self.has(sprite) + + def add(self, *sprites): + """add(sprite, list, or group, ...) + add sprite to group + + Add a sprite or sequence of sprites to a group.""" + for sprite in sprites: + # It's possible that some sprite is also an iterator. + # If this is the case, we should add the sprite itself, + # and not the objects it iterates over. + if isinstance(sprite, Sprite): + if not self.has_internal(sprite): + self.add_internal(sprite) + sprite.add_internal(self) + else: + try: + # See if sprite is an iterator, like a list or sprite + # group. + for spr in sprite: + self.add(spr) + except (TypeError, AttributeError): + # Not iterable, this is probably a sprite that happens + # to not subclass Sprite. Alternately, it could be an + # old-style sprite group. + if hasattr(sprite, '_spritegroup'): + for spr in sprite.sprites(): + if not self.has_internal(spr): + self.add_internal(spr) + spr.add_internal(self) + elif not self.has_internal(sprite): + self.add_internal(sprite) + sprite.add_internal(self) + + def remove(self, *sprites): + """remove(sprite, list, or group, ...) + remove sprite from group + + Remove a sprite or sequence of sprites from a group.""" + # This function behaves essentially the same as Group.add. + # Check for Spritehood, check for iterability, check for + # old-style sprite group, and fall back to assuming + # spritehood. + for sprite in sprites: + if isinstance(sprite, Sprite): + if self.has_internal(sprite): + self.remove_internal(sprite) + sprite.remove_internal(self) + else: + try: + for spr in sprite: self.remove(spr) + except (TypeError, AttributeError): + if hasattr(sprite, '_spritegroup'): + for spr in sprite.sprites(): + if self.has_internal(spr): + self.remove_internal(spr) + spr.remove_internal(self) + elif self.has_internal(sprite): + self.remove_internal(sprite) + sprite.remove_internal(self) + + def has(self, *sprites): + """has(sprite or group, ...) + ask if group has a sprite or sprites + + Returns true if the given sprite or sprites are + contained in the group. You can also use 'sprite in group' + or 'subgroup in group'.""" + # Again, this follows the basic pattern of Group.add and + # Group.remove. + for sprite in sprites: + if isinstance(sprite, Sprite): + return self.has_internal(sprite) + + try: + for spr in sprite: + if not self.has(spr): + return False + return True + except (TypeError, AttributeError): + if hasattr(sprite, '_spritegroup'): + for spr in sprite.sprites(): + if not self.has_internal(spr): + return False + return True + else: + return self.has_internal(sprite) + + def update(self, *args): + """update(*args) + call update for all member sprites + + calls the update method for all sprites in the group. + Passes all arguments on to the Sprite update function.""" + for s in self.sprites(): s.update(*args) + + def draw(self, surface): + """draw(surface) + draw all sprites onto the surface + + Draws all the sprites onto the given surface.""" + sprites = self.sprites() + surface_blit = surface.blit + for spr in sprites: + self.spritedict[spr] = surface_blit(spr.image, spr.rect) + self.lostsprites = [] + + def clear(self, surface, bgd): + """clear(surface, bgd) + erase the previous position of all sprites + + Clears the area of all drawn sprites. the bgd + argument should be Surface which is the same + dimensions as the surface. The bgd can also be + a function which gets called with the passed + surface and the area to be cleared.""" + try: + bgd.__call__ + except AttributeError: + pass + else: + for r in self.lostsprites: + bgd(surface, r) + for r in self.spritedict.values(): + if r is not 0: bgd(surface, r) + return + surface_blit = surface.blit + for r in self.lostsprites: + surface_blit(bgd, r, r) + for r in self.spritedict.values(): + if r is not 0: surface_blit(bgd, r, r) + + def empty(self): + """empty() + remove all sprites + + Removes all the sprites from the group.""" + for s in self.sprites(): + self.remove_internal(s) + s.remove_internal(self) + + def __nonzero__(self): + return (len(self.sprites()) != 0) + + def __len__(self): + """len(group) + number of sprites in group + + Returns the number of sprites contained in the group.""" + return len(self.sprites()) + + def __repr__(self): + return "<%s(%d sprites)>" % (self.__class__.__name__, len(self)) + +class Group(AbstractGroup): + """container class for many Sprites + pygame.sprite.Group(*sprites): return Group + + A simple container for Sprite objects. This class can be inherited to + create containers with more specific behaviors. The constructor takes any + number of Sprite arguments to add to the Group. The group supports the + following standard Python operations: + + in test if a Sprite is contained + len the number of Sprites contained + bool test if any Sprites are contained + iter iterate through all the Sprites + + The Sprites in the Group are not ordered, so drawing and iterating the + Sprites is in no particular order. + """ + + def __init__(self, *sprites): + AbstractGroup.__init__(self) + self.add(*sprites) + +RenderPlain = Group +RenderClear = Group + +class RenderUpdates(Group): + """Group class that tracks dirty updates + pygame.sprite.RenderUpdates(*sprites): return RenderUpdates + + This class is derived from pygame.sprite.Group(). It has an extended draw() + method that tracks the changed areas of the screen. + """ + + def draw(self, surface): + spritedict = self.spritedict + surface_blit = surface.blit + dirty = self.lostsprites + self.lostsprites = [] + dirty_append = dirty.append + for s in self.sprites(): + r = spritedict[s] + newrect = surface_blit(s.image, s.rect) + if r is 0: + dirty_append(newrect) + else: + if newrect.colliderect(r): + dirty_append(newrect.union(r)) + else: + dirty_append(newrect) + dirty_append(r) + spritedict[s] = newrect + return dirty + +class OrderedUpdates(RenderUpdates): + """RenderUpdates class that draws Sprites in order of addition + pygame.sprite.OrderedUpdates(*spites): return OrderedUpdates + + This class derives from pygame.sprite.RenderUpdates(). It maintains + the order in which the Sprites were added to the Group for rendering. + This makes adding and removing Sprites from the Group a little + slower than regular Groups. + """ + + def __init__(self, *sprites): + self._spritelist = [] + RenderUpdates.__init__(self, *sprites) + + def sprites(self): + return list(self._spritelist) + + def add_internal(self, sprite): + RenderUpdates.add_internal(self, sprite) + self._spritelist.append(sprite) + + def remove_internal(self, sprite): + RenderUpdates.remove_internal(self, sprite) + self._spritelist.remove(sprite) + + +class LayeredUpdates(AbstractGroup): + """LayeredUpdates Group handles layers, that draws like OrderedUpdates. + pygame.sprite.LayeredUpdates(*spites, **kwargs): return LayeredUpdates + + This group is fully compatible with pygame.sprite.Sprite. + + New in pygame 1.8.0 + """ + + def __init__(self, *sprites, **kwargs): + """ + You can set the default layer through kwargs using 'default_layer' + and an integer for the layer. The default layer is 0. + + If the sprite you add has an attribute layer then that layer will + be used. + If the **kwarg contains 'layer' then the sprites passed will be + added to that layer (overriding the sprite.layer attribute). + If neither sprite has attribute layer nor kwarg then the default + layer is used to add the sprites. + """ + self._spritelayers = {} + self._spritelist = [] + AbstractGroup.__init__(self) + self._default_layer = kwargs.get('default_layer', 0) + + self.add(*sprites, **kwargs) + + def add_internal(self, sprite, layer=None): + """ + Do not use this method directly. It is used by the group to add a + sprite internally. + """ + self.spritedict[sprite] = Rect(0, 0, 0, 0) # add a old rect + + if layer is None: + try: + layer = sprite._layer + except AttributeError: + layer = self._default_layer + + + self._spritelayers[sprite] = layer + if hasattr(sprite, '_layer'): + sprite._layer = layer + + # add the sprite at the right position + # bisect algorithmus + sprites = self._spritelist # speedup + sprites_layers = self._spritelayers + leng = len(sprites) + low = 0 + high = leng-1 + mid = low + while(low<=high): + mid = low + (high-low)//2 + if(sprites_layers[sprites[mid]]<=layer): + low = mid+1 + else: + high = mid-1 + # linear search to find final position + while(midlayer:# break after because no other will + # follow with same layer + break + return sprites + + def switch_layer(self, layer1_nr, layer2_nr): + """switches the sprites from layer1 to layer2 + LayeredUpdates.switch_layer(layer1_nr, layer2_nr): return None + + The layers number must exist, it is not checked. + """ + sprites1 = self.remove_sprites_of_layer(layer1_nr) + for spr in self.get_sprites_from_layer(layer2_nr): + self.change_layer(spr, layer1_nr) + self.add(sprites1, layer=layer2_nr) + + +class LayeredDirty(LayeredUpdates): + """LayeredDirty Group is for DirtySprites. Subclasses LayeredUpdates. + pygame.sprite.LayeredDirty(*spites, **kwargs): return LayeredDirty + + This group requires pygame.sprite.DirtySprite or any sprite that + has the following attributes: + image, rect, dirty, visible, blendmode (see doc of DirtySprite). + + It uses the dirty flag technique and is therefore faster than the + pygame.sprite.RenderUpdates if you have many static sprites. It + also switches automatically between dirty rect update and full + screen drawing, so you do no have to worry what would be faster. + + Same as for the pygame.sprite.Group. + You can specify some additional attributes through kwargs: + _use_update: True/False default is False + _default_layer: default layer where sprites without a layer are added. + _time_threshold: treshold time for switching between dirty rect mode + and fullscreen mode, defaults to 1000./80 == 1000./fps + + New in pygame 1.8.0 + """ + + def __init__(self, *sprites, **kwargs): + """Same as for the pygame.sprite.Group. + pygame.sprite.LayeredDirty(*spites, **kwargs): return LayeredDirty + + You can specify some additional attributes through kwargs: + _use_update: True/False default is False + _default_layer: the default layer where the sprites without a layer are + added. + _time_threshold: treshold time for switching between dirty rect mode and + fullscreen mode, defaults to 1000./80 == 1000./fps + """ + LayeredUpdates.__init__(self, *sprites, **kwargs) + self._clip = None + + self._use_update = False + + self._time_threshold = 1000./80. # 1000./ fps + + + self._bgd = None + for key, val in kwargs.items(): + if key in ['_use_update', '_time_threshold', '_default_layer']: + if hasattr(self, key): + setattr(self, key, val) + + def add_internal(self, sprite, layer=None): + """Do not use this method directly. It is used by the group to add a + sprite internally. + """ + # check if all attributes needed are set + if not hasattr(sprite, 'dirty'): + raise AttributeError() + if not hasattr(sprite, "visible"): + raise AttributeError() + if not hasattr(sprite, "blendmode"): + raise AttributeError() + + if not isinstance(sprite, DirtySprite): + raise TypeError() + + if sprite.dirty == 0: # set it dirty if it is not + sprite.dirty = 1 + + LayeredUpdates.add_internal(self, sprite, layer) + + def draw(self, surface, bgd=None): + """draw all sprites in the right order onto the passed surface. + LayeredDirty.draw(surface, bgd=None): return Rect_list + + You can pass the background too. If a background is already set, + then the bgd argument has no effect. + """ + # speedups + _orig_clip = surface.get_clip() + _clip = self._clip + if _clip is None: + _clip = _orig_clip + + + _surf = surface + _sprites = self._spritelist + _old_rect = self.spritedict + _update = self.lostsprites + _update_append = _update.append + _ret = None + _surf_blit = _surf.blit + _rect = Rect + if bgd is not None: + self._bgd = bgd + _bgd = self._bgd + + _surf.set_clip(_clip) + # ------- + # 0. deside if normal render of flip + start_time = get_ticks() + if self._use_update: # dirty rects mode + # 1. find dirty area on screen and put the rects into _update + # still not happy with that part + for spr in _sprites: + if 0 < spr.dirty: + # chose the right rect + if spr.source_rect: + _union_rect = _rect(spr.rect.topleft, spr.source_rect.size) + else: + _union_rect = _rect(spr.rect) + + _union_rect_collidelist = _union_rect.collidelist + _union_rect_union_ip = _union_rect.union_ip + i = _union_rect_collidelist(_update) + while -1 < i: + _union_rect_union_ip(_update[i]) + del _update[i] + i = _union_rect_collidelist(_update) + _update_append(_union_rect.clip(_clip)) + + _union_rect = _rect(_old_rect[spr]) + _union_rect_collidelist = _union_rect.collidelist + _union_rect_union_ip = _union_rect.union_ip + i = _union_rect_collidelist(_update) + while -1 < i: + _union_rect_union_ip(_update[i]) + del _update[i] + i = _union_rect_collidelist(_update) + _update_append(_union_rect.clip(_clip)) + # can it be done better? because that is an O(n**2) algorithm in + # worst case + + # clear using background + if _bgd is not None: + for rec in _update: + _surf_blit(_bgd, rec, rec) + + # 2. draw + for spr in _sprites: + if 1 > spr.dirty: + if spr._visible: + # sprite not dirty, blit only the intersecting part + _spr_rect = spr.rect + if spr.source_rect is not None: + _spr_rect = Rect(spr.rect.topleft, spr.source_rect.size) + _spr_rect_clip = _spr_rect.clip + for idx in _spr_rect.collidelistall(_update): + # clip + clip = _spr_rect_clip(_update[idx]) + _surf_blit(spr.image, clip, \ + (clip[0]-_spr_rect[0], \ + clip[1]-_spr_rect[1], \ + clip[2], \ + clip[3]), spr.blendmode) + else: # dirty sprite + if spr._visible: + _old_rect[spr] = _surf_blit(spr.image, spr.rect, \ + spr.source_rect, spr.blendmode) + if spr.dirty == 1: + spr.dirty = 0 + _ret = list(_update) + else: # flip, full screen mode + if _bgd is not None: + _surf_blit(_bgd, (0, 0)) + for spr in _sprites: + if spr._visible: + _old_rect[spr] = _surf_blit(spr.image, spr.rect, spr.source_rect,spr.blendmode) + _ret = [_rect(_clip)] # return only the part of the screen changed + + + # timing for switching modes + # how to find a good treshold? it depends on the hardware it runs on + end_time = get_ticks() + if end_time-start_time > self._time_threshold: + self._use_update = False + else: + self._use_update = True + +## # debug +## print " check: using dirty rects:", self._use_update + + # emtpy dirty reas list + _update[:] = [] + + # ------- + # restore original clip + _surf.set_clip(_orig_clip) + return _ret + + def clear(self, surface, bgd): + """used to set background + Group.clear(surface, bgd): return None + """ + self._bgd = bgd + + def repaint_rect(self, screen_rect): + """repaints the given area + LayeredDirty.repaint_rect(screen_rect): return None + + screen_rect is in screencoordinates. + """ + self.lostsprites.append(screen_rect.clip(self._clip)) + + def set_clip(self, screen_rect=None): + """ clip the area where to draw. Just pass None (default) to reset the clip + LayeredDirty.set_clip(screen_rect=None): return None + """ + if screen_rect is None: + self._clip = pygame.display.get_surface().get_rect() + else: + self._clip = screen_rect + self._use_update = False + + def get_clip(self): + """clip the area where to draw. Just pass None (default) to reset the clip + LayeredDirty.get_clip(): return Rect + """ + return self._clip + + def change_layer(self, sprite, new_layer): + """changes the layer of the sprite + change_layer(sprite, new_layer): return None + + sprite must have been added to the renderer. It is not checked. + """ + LayeredUpdates.change_layer(self, sprite, new_layer) + if sprite.dirty == 0: + sprite.dirty = 1 + + + def set_timing_treshold(self, time_ms): + """sets the treshold in milliseconds + set_timing_treshold(time_ms): return None + + Default is 1000./80 where 80 is the fps I want to switch to full screen mode. + """ + self._time_threshold = time_ms + + + + + + + +class GroupSingle(AbstractGroup): + """A group container that holds a single most recent item. + This class works just like a regular group, but it only + keeps a single sprite in the group. Whatever sprite has + been added to the group last, will be the only sprite in + the group. + + You can access its one sprite as the .sprite attribute. + Assigning to this attribute will properly remove the old + sprite and then add the new one.""" + + def __init__(self, sprite = None): + AbstractGroup.__init__(self) + self.__sprite = None + if sprite is not None: self.add(sprite) + + def copy(self): + return GroupSingle(self.__sprite) + + def sprites(self): + if self.__sprite is not None: return [self.__sprite] + else: return [] + + def add_internal(self, sprite): + if self.__sprite is not None: + self.__sprite.remove_internal(self) + self.__sprite = sprite + + def __nonzero__(self): return (self.__sprite is not None) + + def _get_sprite(self): + return self.__sprite + + def _set_sprite(self, sprite): + self.add_internal(sprite) + sprite.add_internal(self) + return sprite + + sprite = property(_get_sprite, _set_sprite, None, + "The sprite contained in this group") + + def remove_internal(self, sprite): + if sprite is self.__sprite: self.__sprite = None + + def has_internal(self, sprite): + return (self.__sprite is sprite) + + # Optimizations... + def __contains__(self, sprite): return (self.__sprite is sprite) + + + + + +# some different collision detection functions that could be used. + +def collide_rect(left, right): + """collision detection between two sprites, using rects. + pygame.sprite.collide_rect(left, right): return bool + + Tests for collision between two sprites. Uses the + pygame rect colliderect function to calculate the + collision. Intended to be passed as a collided + callback function to the *collide functions. + Sprites must have a "rect" attributes. + + New in pygame 1.8.0 + """ + return left.rect.colliderect(right.rect) + +class collide_rect_ratio: + """A callable class that checks for collisions between + two sprites, using a scaled version of the sprites + rects. + + Is created with a ratio, the instance is then intended + to be passed as a collided callback function to the + *collide functions. + + New in pygame 1.8.1 + """ + + def __init__( self, ratio ): + """Creates a new collide_rect_ratio callable. ratio is + expected to be a floating point value used to scale + the underlying sprite rect before checking for + collisions. + """ + + self.ratio = ratio + + def __call__( self, left, right ): + """pygame.sprite.collide_rect_ratio(ratio)(left, right): bool + collision detection between two sprites, using scaled rects. + + Tests for collision between two sprites. Uses the + pygame rect colliderect function to calculate the + collision, after scaling the rects by the stored ratio. + Sprites must have a "rect" attributes. + """ + + ratio = self.ratio + + leftrect = left.rect + width = leftrect.width + height = leftrect.height + leftrect = leftrect.inflate( width * ratio - width, height * ratio - height ) + + rightrect = right.rect + width = rightrect.width + height = rightrect.height + rightrect = rightrect.inflate( width * ratio - width, height * ratio - height ) + + return leftrect.colliderect( rightrect ) + +def collide_circle( left, right ): + """collision detection between two sprites, using circles. + pygame.sprite.collide_circle(left, right): return bool + + Tests for collision between two sprites, by testing to + see if two circles centered on the sprites overlap. If + the sprites have a "radius" attribute, that is used to + create the circle, otherwise a circle is created that + is big enough to completely enclose the sprites rect as + given by the "rect" attribute. Intended to be passed as + a collided callback function to the *collide functions. + Sprites must have a "rect" and an optional "radius" + attribute. + + New in pygame 1.8.0 + """ + + xdistance = left.rect.centerx - right.rect.centerx + ydistance = left.rect.centery - right.rect.centery + distancesquared = xdistance ** 2 + ydistance ** 2 + try: + leftradiussquared = left.radius ** 2 + except AttributeError: + leftrect = left.rect + leftradiussquared = ( leftrect.width ** 2 + leftrect.height ** 2 ) / 4 + try: + rightradiussquared = right.radius ** 2 + except AttributeError: + rightrect = right.rect + rightradiussquared = ( rightrect.width ** 2 + rightrect.height ** 2 ) / 4 + return distancesquared < leftradiussquared + rightradiussquared + +class collide_circle_ratio( object ): + """A callable class that checks for collisions between + two sprites, using a scaled version of the sprites radius. + + Is created with a ratio, the instance is then intended + to be passed as a collided callback function to the + *collide functions. + + New in pygame 1.8.1 + """ + + def __init__( self, ratio ): + """Creates a new collide_circle_ratio callable. ratio is + expected to be a floating point value used to scale + the underlying sprite radius before checking for + collisions. + """ + self.ratio = ratio + # Constant value that folds in division for diameter to radius, + # when calculating from a rect. + self.halfratio = ratio ** 2 / 4.0 + + def __call__( self, left, right ): + """pygame.sprite.collide_circle_radio(ratio)(left, right): return bool + collision detection between two sprites, using scaled circles. + + Tests for collision between two sprites, by testing to + see if two circles centered on the sprites overlap, after + scaling the circles radius by the stored ratio. If + the sprites have a "radius" attribute, that is used to + create the circle, otherwise a circle is created that + is big enough to completely enclose the sprites rect as + given by the "rect" attribute. Intended to be passed as + a collided callback function to the *collide functions. + Sprites must have a "rect" and an optional "radius" + attribute. + """ + + ratio = self.ratio + xdistance = left.rect.centerx - right.rect.centerx + ydistance = left.rect.centery - right.rect.centery + distancesquared = xdistance ** 2 + ydistance ** 2 + # Optimize for not containing radius attribute, as if radius was + # set consistently, would probably be using collide_circle instead. + if hasattr( left, "radius" ): + leftradiussquared = (left.radius * ratio) ** 2 + + if hasattr( right, "radius" ): + rightradiussquared = (right.radius * ratio) ** 2 + else: + halfratio = self.halfratio + rightrect = right.rect + rightradiussquared = (rightrect.width ** 2 + rightrect.height ** 2) * halfratio + else: + halfratio = self.halfratio + leftrect = left.rect + leftradiussquared = (leftrect.width ** 2 + leftrect.height ** 2) * halfratio + + if hasattr( right, "radius" ): + rightradiussquared = (right.radius * ratio) ** 2 + else: + rightrect = right.rect + rightradiussquared = (rightrect.width ** 2 + rightrect.height ** 2) * halfratio + return distancesquared < leftradiussquared + rightradiussquared + +def collide_mask(left, right): + """collision detection between two sprites, using masks. + pygame.sprite.collide_mask(SpriteLeft, SpriteRight): bool + + Tests for collision between two sprites, by testing if + thier bitmasks overlap. If the sprites have a "mask" + attribute, that is used as the mask, otherwise a mask is + created from the sprite image. Intended to be passed as + a collided callback function to the *collide functions. + Sprites must have a "rect" and an optional "mask" + attribute. + + New in pygame 1.8.0 + """ + xoffset = right.rect[0] - left.rect[0] + yoffset = right.rect[1] - left.rect[1] + try: + leftmask = left.mask + except AttributeError: + leftmask = from_surface(left.image) + try: + rightmask = right.mask + except AttributeError: + rightmask = from_surface(right.image) + return leftmask.overlap(rightmask, (xoffset, yoffset)) + +def spritecollide(sprite, group, dokill, collided = None): + """find Sprites in a Group that intersect another Sprite + pygame.sprite.spritecollide(sprite, group, dokill, collided = None): return Sprite_list + + Return a list containing all Sprites in a Group that intersect with another + Sprite. Intersection is determined by comparing the Sprite.rect attribute + of each Sprite. + + The dokill argument is a bool. If set to True, all Sprites that collide + will be removed from the Group. + + The collided argument is a callback function used to calculate if two sprites + are colliding. it should take two sprites as values, and return a bool + value indicating if they are colliding. If collided is not passed, all sprites + must have a "rect" value, which is a rectangle of the sprite area, which will + be used to calculate the collision. + """ + crashed = [] + if collided is None: + # Special case old behaviour for speed. + spritecollide = sprite.rect.colliderect + if dokill: + for s in group.sprites(): + if spritecollide(s.rect): + s.kill() + crashed.append(s) + else: + for s in group: + if spritecollide(s.rect): + crashed.append(s) + else: + if dokill: + for s in group.sprites(): + if collided(sprite, s): + s.kill() + crashed.append(s) + else: + for s in group: + if collided(sprite, s): + crashed.append(s) + return crashed + +def groupcollide(groupa, groupb, dokilla, dokillb, collided = None): + """pygame.sprite.groupcollide(groupa, groupb, dokilla, dokillb) -> dict + collision detection between group and group + + given two groups, this will find the intersections + between all sprites in each group. it returns a + dictionary of all sprites in the first group that + collide. the value for each item in the dictionary + is a list of the sprites in the second group it + collides with. the two dokill arguments control if + the sprites from either group will be automatically + removed from all groups. + collided is a callback function used to calculate if + two sprites are colliding. it should take two sprites + as values, and return a bool value indicating if + they are colliding. if collided is not passed, all + sprites must have a "rect" value, which is a + rectangle of the sprite area, which will be used + to calculate the collision.""" + crashed = {} + SC = spritecollide + if dokilla: + for s in groupa.sprites(): + c = SC(s, groupb, dokillb, collided) + if c: + crashed[s] = c + s.kill() + else: + for s in groupa: + c = SC(s, groupb, dokillb, collided) + if c: + crashed[s] = c + return crashed + +def spritecollideany(sprite, group, collided = None): + """pygame.sprite.spritecollideany(sprite, group) -> sprite + finds any sprites that collide + + given a sprite and a group of sprites, this will + return return any single sprite that collides with + with the given sprite. If there are no collisions + this returns None. + + if you don't need all the features of the + spritecollide function, this function will be a + bit quicker. + + collided is a callback function used to calculate if + two sprites are colliding. it should take two sprites + as values, and return a bool value indicating if + they are colliding. if collided is not passed, all + sprites must have a "rect" value, which is a + rectangle of the sprite area, which will be used + to calculate the collision.""" + if collided is None: + # Special case old behaviour for speed. + spritecollide = sprite.rect.colliderect + for s in group: + if spritecollide(s.rect): + return s + else: + for s in group: + if collided(sprite, s): + return s + return None diff --git a/src/pygame/sprite.pyo b/src/pygame/sprite.pyo new file mode 100644 index 0000000..68cf225 --- /dev/null +++ b/src/pygame/sprite.pyo Binary files differ diff --git a/src/pygame/surface.so b/src/pygame/surface.so new file mode 100644 index 0000000..d827d3e --- /dev/null +++ b/src/pygame/surface.so Binary files differ diff --git a/src/pygame/surfarray.py b/src/pygame/surfarray.py new file mode 100644 index 0000000..33e2cb1 --- /dev/null +++ b/src/pygame/surfarray.py @@ -0,0 +1,340 @@ +## pygame - Python Game Library +## Copyright (C) 2007 Marcus von Appen +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Marcus von Appen +## mva@sysfault.org + +"""pygame module for accessing surface pixel data using array interfaces + +Functions to convert pixel data between pygame Surfaces and arrays. This +module will only be functional when pygame can use the external Numpy or +Numeric packages. + +Every pixel is stored as a single integer value to represent the red, +green, and blue colors. The 8bit images use a value that looks into a +colormap. Pixels with higher depth use a bit packing process to place +three or four values into a single number. + +The arrays are indexed by the X axis first, followed by the Y +axis. Arrays that treat the pixels as a single integer are referred to +as 2D arrays. This module can also separate the red, green, and blue +color values into separate indices. These types of arrays are referred +to as 3D arrays, and the last index is 0 for red, 1 for green, and 2 for +blue. + +Supported array types are + + numpy + numeric + +The default will be numpy, if installed. Otherwise, Numeric will be set +as default if installed. If neither numpy nor Numeric are installed, the +module will raise an ImportError. + +The array type to use can be changed at runtime using the use_arraytype() +method, which requires one of the above types as string. + +Note: numpy and Numeric are not completely compatible. Certain array +manipulations, which work for one type, might behave differently or even +completely break for the other. + +Additionally, in contrast to Numeric numpy does use unsigned 16-bit +integers. Images with 16-bit data will be treated as unsigned +integers. Numeric instead uses signed integers for the representation, +which is important to keep in mind, if you use the module's functions +and wonder about the values. +""" + +import pygame + +# Global array type setting. See use_arraytype(). +__arraytype = None + +# Try to import the necessary modules. +try: + import pygame._numpysurfarray as numpysf + __hasnumpy = True + __arraytype = "numpy" +except ImportError: + __hasnumpy = False + +try: + import pygame._numericsurfarray as numericsf + __hasnumeric = True + if not __hasnumpy: + __arraytype = "numeric" +except ImportError: + __hasnumeric = False + +if not __hasnumpy and not __hasnumeric: + raise ImportError("no module named numpy or Numeric found") + +from _arraysurfarray import blit_array + +def array2d (surface): + """pygame.surfarray.array2d (Surface): return array + + Copy pixels into a 2d array. + + Copy the pixels from a Surface into a 2D array. The bit depth of the + surface will control the size of the integer values, and will work + for any type of pixel format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + if __arraytype == "numeric": + return numericsf.array2d (surface) + elif __arraytype == "numpy": + return numpysf.array2d (surface) + raise NotImplementedError("surface arrays are not supported") + +def pixels2d (surface): + """pygame.surfarray.pixels2d (Surface): return array + + Reference pixels into a 2d array. + + Create a new 2D array that directly references the pixel values in a + Surface. Any changes to the array will affect the pixels in the + Surface. This is a fast operation since no data is copied. + + Pixels from a 24-bit Surface cannot be referenced, but all other + Surface bit depths can. + + The Surface this references will remain locked for the lifetime of + the array (see the Surface.lock - lock the Surface memory for pixel + access method). + """ + if __arraytype == "numeric": + return numericsf.pixels2d (surface) + elif __arraytype == "numpy": + return numpysf.pixels2d (surface) + raise NotImplementedError("surface arrays are not supported") + +def array3d (surface): + """pygame.surfarray.array3d (Surface): return array + + Copy pixels into a 3d array. + + Copy the pixels from a Surface into a 3D array. The bit depth of the + surface will control the size of the integer values, and will work + for any type of pixel format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + if __arraytype == "numeric": + return numericsf.array3d (surface) + elif __arraytype == "numpy": + return numpysf.array3d (surface) + raise NotImplementedError("surface arrays are not supported") + +def pixels3d (surface): + """pygame.surfarray.pixels3d (Surface): return array + + Reference pixels into a 3d array. + + Create a new 3D array that directly references the pixel values in a + Surface. Any changes to the array will affect the pixels in the + Surface. This is a fast operation since no data is copied. + + This will only work on Surfaces that have 24-bit or 32-bit + formats. Lower pixel formats cannot be referenced. + + The Surface this references will remain locked for the lifetime of + the array (see the Surface.lock - lock the Surface memory for pixel + access method). + """ + if __arraytype == "numeric": + return numericsf.pixels3d (surface) + elif __arraytype == "numpy": + return numpysf.pixels3d (surface) + raise NotImplementedError("surface arrays are not supported") + +def array_alpha (surface): + """pygame.surfarray.array_alpha (Surface): return array + + Copy pixel alphas into a 2d array. + + Copy the pixel alpha values (degree of transparency) from a Surface + into a 2D array. This will work for any type of Surface + format. Surfaces without a pixel alpha will return an array with all + opaque values. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + if __arraytype == "numeric": + return numericsf.array_alpha (surface) + elif __arraytype == "numpy": + return numpysf.array_alpha (surface) + raise NotImplementedError("surface arrays are not supported") + +def pixels_alpha (surface): + """pygame.surfarray.pixels_alpha (Surface): return array + + Reference pixel alphas into a 2d array. + + Create a new 2D array that directly references the alpha values + (degree of transparency) in a Surface. Any changes to the array will + affect the pixels in the Surface. This is a fast operation since no + data is copied. + + This can only work on 32-bit Surfaces with a per-pixel alpha value. + + The Surface this array references will remain locked for the + lifetime of the array. + """ + if __arraytype == "numeric": + return numericsf.pixels_alpha (surface) + elif __arraytype == "numpy": + return numpysf.pixels_alpha (surface) + raise NotImplementedError("surface arrays are not supported") + +def array_colorkey (surface): + """pygame.surfarray.array_colorkey (Surface): return array + + Copy the colorkey values into a 2d array. + + Create a new array with the colorkey transparency value from each + pixel. If the pixel matches the colorkey it will be fully + tranparent; otherwise it will be fully opaque. + + This will work on any type of Surface format. If the image has no + colorkey a solid opaque array will be returned. + + This function will temporarily lock the Surface as pixels are + copied. + """ + if __arraytype == "numeric": + return numericsf.array_colorkey (surface) + elif __arraytype == "numpy": + return numpysf.array_colorkey (surface) + raise NotImplementedError("surface arrays are not supported") + +def make_surface (array): + """pygame.surfarray.make_surface (array): return Surface + + Copy an array to a new surface. + + Create a new Surface that best resembles the data and format on the + array. The array can be 2D or 3D with any sized integer values. + """ + if __arraytype == "numeric": + return numericsf.make_surface (array) + elif __arraytype == "numpy": + return numpysf.make_surface (array) + raise NotImplementedError("surface arrays are not supported") + +##def blit_array (surface, array): +## """pygame.surfarray.blit_array (Surface, array): return None +## +## Blit directly from a array values. +## +## Directly copy values from an array into a Surface. This is faster +## than converting the array into a Surface and blitting. The array +## must be the same dimensions as the Surface and will completely +## replace all pixel values. +## +## This function will temporarily lock the Surface as the new values +## are copied. +## """ +## if __arraytype == "numeric": +## return numericsf.blit_array (surface, array) +## elif __arraytype == "numpy": +## return numpysf.blit_array (surface, array) +## raise NotImplementedError("surface arrays are not supported") + +def map_array (surface, array): + """pygame.surfarray.map_array (Surface, array3d): return array2d + + Map a 3D array into a 2D array. + + Convert a 3D array into a 2D array. This will use the given Surface + format to control the conversion. Palette surface formats are not + supported. + """ + if __arraytype == "numeric": + return numericsf.map_array (surface, array) + elif __arraytype == "numpy": + return numpysf.map_array (surface, array) + raise NotImplementedError("surface arrays are not supported") + +def use_arraytype (arraytype): + """pygame.surfarray.use_arraytype (arraytype): return None + + Sets the array system to be used for surface arrays. + + Uses the requested array type for the module functions. + Currently supported array types are: + + numeric + numpy + + If the requested type is not available, a ValueError will be raised. + """ + global __arraytype + + arraytype = arraytype.lower () + if arraytype == "numeric": + if __hasnumeric: + __arraytype = arraytype + else: + raise ValueError("Numeric arrays are not available") + + elif arraytype == "numpy": + if __hasnumpy: + __arraytype = arraytype + else: + raise ValueError("numpy arrays are not available") + else: + raise ValueError("invalid array type") + +def get_arraytype (): + """pygame.surfarray.get_arraytype (): return str + + Gets the currently active array type. + + Returns the currently active array type. This will be a value of the + get_arraytypes() tuple and indicates which type of array module is + used for the array creation. + """ + return __arraytype + +def get_arraytypes (): + """pygame.surfarray.get_arraytypes (): return tuple + + Gets the array system types currently supported. + + Checks, which array system types are available and returns them as a + tuple of strings. The values of the tuple can be used directly in + the use_arraytype () method. + + If no supported array system could be found, None will be returned. + """ + vals = [] + if __hasnumeric: + vals.append ("numeric") + if __hasnumpy: + vals.append ("numpy") + if len (vals) == 0: + return None + return tuple (vals) + diff --git a/src/pygame/surfarray.pyo b/src/pygame/surfarray.pyo new file mode 100644 index 0000000..2852ccb --- /dev/null +++ b/src/pygame/surfarray.pyo Binary files differ diff --git a/src/pygame/surflock.so b/src/pygame/surflock.so new file mode 100644 index 0000000..2b58744 --- /dev/null +++ b/src/pygame/surflock.so Binary files differ diff --git a/src/pygame/sysfont.py b/src/pygame/sysfont.py new file mode 100644 index 0000000..175879a --- /dev/null +++ b/src/pygame/sysfont.py @@ -0,0 +1,633 @@ +## pygame - Python Game Library +## Copyright (C) 2000-2003 Pete Shinners +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Pete Shinners +## pete@shinners.org + +"sysfont, used in the font module to find system fonts" + +import os, sys + +#Python 3 compatibility +try: + bytes +except NameError: + def toascii(raw): + return raw.decode('ascii', 'ignore').encode('ascii') +else: + def toascii(raw): + return raw.decode('ascii', 'ignore') + +#create simple version of the font name +def _simplename(name): + return ''.join([c.lower() for c in name if c.isalnum()]) + + +#insert a font and style into the font dictionary +def _addfont(name, bold, italic, font, fontdict): + if name not in fontdict: + fontdict[name] = {} + fontdict[name][bold, italic] = font + + +#read the fonts on windows +# Info taken from: +# http://www.microsoft.com/typography/fonts/winxp.htm +# with extra files added from: +# http://www.ampsoft.net/webdesign-l/windows-fonts-by-version.html +# File name, family, (Bold, Italic) +_XP_default_font_files = [ + ('ahronbd.ttf', 'Aharoni', True, False), + ('andlso.ttf', 'Andalus', False, False), + ('angsa.ttf', 'Angsana New', False, False), + ('angsab.ttf', 'Angsana New', True, False), + ('angsai.ttf', 'Angsana New', False, True), + ('angsaz.ttf', 'Angsana New', True, True), + ('angsau.ttf', 'AngsanaUPC', False, False), + ('angsaub.ttf', 'AngsanaUPC', True, False), + ('angsaui.ttf', 'AngsanaUPC', False, True), + ('angsauz.ttf', 'AngsanaUPC', True, True), + ('artro.ttf', 'Arabic Transparent', False, False), + ('artrbdo.ttf', 'Arabic Transparent', True, False), + ('agatha.ttf', 'Agatha', False, False), + ('arial.ttf', 'Arial', False, False), + ('arialbd.ttf', 'Arial', True, False), + ('ariali.ttf', 'Arial', False, True), + ('arialbi.ttf', 'Arial', True, True), + ('ariblk.ttf', 'Arial Black', False, False), + ('browa.ttf', 'Browallia New', False, False), + ('browab.ttf', 'Browallia New', True, False), + ('browai.ttf', 'Browallia New', False, True), + ('browaz.ttf', 'Browallia New', True, True), + ('browau.ttf', 'BrowalliaUPC', False, False), + ('browaub.ttf', 'BrowalliaUPC', True, False), + ('browaui.ttf', 'BrowalliaUPC', False, True), + ('browauz.ttf', 'BrowalliaUPC', True, True), + ('comic.ttf', 'Comic Sans MS', False, False), + ('comicbd.ttf', 'Comic Sans MS', True, False), + ('cordia.ttf', 'Cordia New', False, False), + ('cordiab.ttf', 'Cordia New', True, False), + ('cordiai.ttf', 'Cordia New', False, True), + ('cordiaz.ttf', 'Cordia New', True, True), + ('cordiau.ttf', 'CordiaUPC', False, False), + ('cordiaub.ttf', 'CordiaUPC', True, False), + ('cordiaui.ttf', 'CordiaUPC', False, True), + ('cordiauz.ttf', 'CordiaUPC', True, True), + ('cour.ttf', 'Courier New', False, False), + ('courbd.ttf', 'Courier New', True, False), + ('couri.ttf', 'Courier New', False, True), + ('courbi.ttf', 'Courier New', True, True), + ('david.ttf', 'David', False, False), + ('davidbd.ttf', 'David', True, False), + ('davidtr.ttf', 'David Transparent', False, False), + ('upcdl.ttf', 'DilleniaUPC', False, False), + ('upcdb.ttf', 'DilleniaUPC', True, False), + ('upcdi.ttf', 'DilleniaUPC', False, True), + ('upcdbi.ttf', 'DilleniaUPC', True, True), + ('estre.ttf', 'Estrangelo Edessa', False, False), + ('upcel.ttf', 'EucrosialUPC', False, False), + ('upceb.ttf', 'EucrosialUPC', True, False), + ('upcei.ttf', 'EucrosialUPC', False, True), + ('upcebi.ttf', 'EucrosialUPC', True, True), + ('mriamfx.ttf', 'Fixed Miriam Transparent', False, False), + ('framd.ttf', 'Franklin Gothic Medium', False, False), + ('framdit.ttf', 'Franklin Gothic Medium', False, True), + ('frank.ttf', 'FrankRuehl', False, False), + ('upcfl.ttf', 'FreesialUPC', False, False), + ('upcfb.ttf', 'FreesialUPC', True, False), + ('upcfi.ttf', 'FreesialUPC', False, True), + ('upcfbi.ttf', 'FreesialUPC', True, True), + ('gautami.ttf', 'Gautami', False, False), + ('georgia.ttf', 'Georgia', False, False), + ('georgiab.ttf', 'Georgia', True, False), + ('georgiai.ttf', 'Georgia', False, True), + ('georgiaz.ttf', 'Georgia', True, True), + ('impact.ttf', 'Impact', False, False), + ('upcil.ttf', 'IrisUPC', False, False), + ('upcib.ttf', 'IrisUPC', True, False), + ('upcii.ttf', 'IrisUPC', False, True), + ('upcibi.ttf', 'IrisUPC', True, True), + ('upcjl.ttf', 'JasmineUPC', False, False), + ('upcjb.ttf', 'JasmineUPC', True, False), + ('upcji.ttf', 'JasmineUPC', False, True), + ('upcjbi.ttf', 'JasmineUPC', True, True), + ('upckl.ttf', 'KodchiangUPC', False, False), + ('upckb.ttf', 'KodchiangUPC', True, False), + ('upcki.ttf', 'KodchiangUPC', False, True), + ('upckbi.ttf', 'KodchiangUPC', True, True), + ('latha.ttf', 'Latha', False, False), + ('lvnm.ttf', 'Levenim MT', False, False), + ('lvnmbd.ttf', 'Levenim MT', True, False), + ('upcll.ttf', 'LilyUPC', False, False), + ('upclb.ttf', 'LilyUPC', True, False), + ('upcli.ttf', 'LilyUPC', False, True), + ('upclbi.ttf', 'LilyUPC', True, True), + ('lucon.ttf', 'Lucida Console', False, False), + ('l_10646.ttf', 'Lucida Sans Unicode', False, False), + ('mangal.ttf', 'Mangal', False, False), + ('marlett.ttf', 'Marlett', False, False), + ('micross.ttf', 'Microsoft Sans Serif', False, False), + ('mriam.ttf', 'Miriam', False, False), + ('mriamc.ttf', 'Miriam Fixed', False, False), + ('mriamtr.ttf', 'Miriam Transparent', False, False), + ('mvboli.ttf', 'MV Boli', False, False), + ('nrkis.ttf', 'Narkisim', False, False), + ('pala.ttf', 'Falatino Linotype', False, False), + ('palab.ttf', 'Falatino Linotype', True, False), + ('palai.ttf', 'Falatino Linotype', False, True), + ('palabi.ttf', 'Falatino Linotype', True, True), + ('raavi.ttf', 'Raavi', False, False), + ('rod.ttf', 'Rod', False, False), + ('rodtr.ttf', 'Rod Transparent', False, False), + ('shruti.ttf', 'Shruti', False, False), + ('simpo.ttf', 'Simplified Arabic', False, False), + ('simpbdo.ttf', 'Simplified Arabic', True, False), + ('simpfxo.ttf', 'Simplified Arabic Fixed', False, False), + ('sylfaen.ttf', 'Sylfaen', False, False), + ('symbol.ttf', 'Symbol', False, False), + ('tahoma.ttf', 'Tahoma', False, False), + ('tahomabd.ttf', 'Tahoma', True, False), + ('times.ttf', 'Times New Roman', False, False), + ('timesbd.ttf', 'Times New Roman', True, False), + ('timesi.ttf', 'Times New Roman', False, True), + ('timesbi.ttf', 'Times New Roman', True, True), + ('trado.ttf', 'Traditional Arabic', False, False), + ('tradbdo.ttf', 'Traditional Arabic', True, False), + ('Trebuc.ttf', 'Trebuchet MS', False, False), + ('Trebucbd.ttf', 'Trebuchet MS', True, False), + ('Trebucit.ttf', 'Trebuchet MS', False, True), + ('Trebucbi.ttf', 'Trebuchet MS', True, True), + ('tunga.ttf', 'Tunga', False, False), + ('verdana.ttf', 'Verdana', False, False), + ('verdanab.ttf', 'Verdana', True, False), + ('verdanai.ttf', 'Verdana', False, True), + ('verdanaz.ttf', 'Verdana', True, True), + ('webdings.ttf', 'Webdings', False, False), + ('wingding.ttf', 'Wingdings', False, False), + ('simhei.ttf', 'SimHei', False, False), + ('simfang.ttf', 'FangSong_GB2312', False, False), + ('kaiu.ttf', 'DFKai-SB', False, False), + ('simkai.ttf', 'KaiTi_GB2312', False, False), + ('msgothic.ttc', 'MS Gothic', False, False), + ('msmincho.ttc', 'MS Mincho', False, False), + ('gulim.ttc', 'Gulim', False, False), + ('mingliu.ttc', 'Mingliu', False, False), + ('simsun.ttc', 'Simsun', False, False), + ('batang.ttc', 'Batang', False, False), + ] + + + + +def initsysfonts_win32(): + try: + import _winreg + except ImportError: + import winreg as _winreg + + if 'WINDIR' in os.environ: + windir = os.environ['WINDIR'] + elif 'windir' in os.environ: + windir = os.environ['windir'] + else: + windir = "C:\\Windows\\" + + + fonts = {} + mods = 'demibold', 'narrow', 'light', 'unicode', 'bt', 'mt' + fontdir = os.path.join(windir, "Fonts") + + #this is a list of registry keys containing information + #about fonts installed on the system. + keys = [] + + #add recognized fonts from the fonts directory because the default + #fonts may not be entered in the registry. + win_font_files_mapping = dict( + [(file_name.lower(), (_simplename(name), bold, italic)) + for file_name, name, bold, italic in _XP_default_font_files]) + + font_dir_path = os.path.join(windir, 'fonts') + try: + font_file_paths = glob.glob(os.path.join(font_dir_path, '*.tt?')) + except Exception: + pass + else: + for font in font_file_paths: + file_name = os.path.basename(font) + try: + name, bold, italic = win_font_file_mapping[file_name] + except KeyError: + pass + else: + _addfont(name, bold, italic, font, fonts) + + #add additional fonts entered in the registry. + + #find valid registry keys containing font information. + possible_keys = [ + r"SOFTWARE\Microsoft\Windows\CurrentVersion\Fonts", + r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", + r"SOFTWARE\Microsoft\Windows[NT]\CurrentVersion\Fonts", + ] + + for key_name in possible_keys: + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key_name) + keys.append(key) + except WindowsError: + pass + + for key in keys: + fontdict = {} + for i in range(_winreg.QueryInfoKey(key)[1]): + try: name, font, t = _winreg.EnumValue(key,i) + except EnvironmentError: break + + # try and handle windows unicode strings for some file names. + + # here are two documents with some information about it: + # http://www.python.org/peps/pep-0277.html + # https://www.microsoft.com/technet/archive/interopmigration/linux/mvc/lintowin.mspx#ECAA + try: + font = str(font) + except UnicodeEncodeError: + # MBCS is the windows encoding for unicode file names. + try: + font = font.encode('MBCS') + except: + # no goodness with str or MBCS encoding... skip this font. + continue + + if font[-4:].lower() not in [".ttf", ".ttc"]: + continue + if os.sep not in font: + font = os.path.join(fontdir, font) + + if name[-10:] == '(TrueType)': + name = name[:-11] + name = name.lower().split() + + bold = italic = 0 + for m in mods: + if m in name: + name.remove(m) + if 'bold' in name: + name.remove('bold') + bold = 1 + if 'italic' in name: + name.remove('italic') + italic = 1 + name = ''.join(name) + + name=_simplename(name) + + _addfont(name, bold, italic, font, fonts) + + return fonts + + + + + +_OSX_default_font_files = { + 'albayan': {(False, False): '/Library/Fonts/AlBayan.ttf', + (True, False): '/Library/Fonts/AlBayanBold.ttf'}, + 'andalemono': {(False, False): '/Library/Fonts/Andale Mono.ttf'}, + 'applebraille': {(False, False): '/System/Library/Fonts/Apple Braille Outline 6 Dot.ttf'}, + 'applegothic': {(False, False): '/System/Library/Fonts/AppleGothic.ttf'}, + 'applesymbols': {(False, False): '/System/Library/Fonts/Apple Symbols.ttf'}, + 'arial': {(False, False): '/Library/Fonts/Arial.ttf', + (False, True): '/Library/Fonts/Arial Italic.ttf', + (True, False): '/Library/Fonts/Arial Bold.ttf', + (True, True): '/Library/Fonts/Arial Bold Italic.ttf'}, + 'arialblack': {(False, False): '/Library/Fonts/Arial Black.ttf'}, + 'arialhebrew': {(False, False): '/Library/Fonts/ArialHB.ttf', + (True, False): '/Library/Fonts/ArialHBBold.ttf'}, + 'arialnarrow': {(False, False): '/Library/Fonts/Arial Narrow.ttf', + (False, True): '/Library/Fonts/Arial Narrow Italic.ttf', + (True, False): '/Library/Fonts/Arial Narrow Bold.ttf', + (True, True): '/Library/Fonts/Arial Narrow Bold Italic.ttf'}, + 'arialroundedmtbold': {(False, False): '/Library/Fonts/Arial Rounded Bold.ttf'}, + 'arialunicodems': {(False, False): '/Library/Fonts/Arial Unicode.ttf'}, + 'ayuthaya': {(False, False): '/Library/Fonts/Ayuthaya.ttf'}, + 'baghdad': {(False, False): '/Library/Fonts/Baghdad.ttf'}, + 'brushscriptmt': {(False, True): '/Library/Fonts/Brush Script.ttf'}, + 'chalkboard': {(False, False): '/Library/Fonts/Chalkboard.ttf', + (True, False): '/Library/Fonts/ChalkboardBold.ttf'}, + 'comicsansms': {(False, False): '/Library/Fonts/Comic Sans MS.ttf', + (True, False): '/Library/Fonts/Comic Sans MS Bold.ttf'}, + 'corsivahebrew': {(False, False): '/Library/Fonts/Corsiva.ttf', + (True, False): '/Library/Fonts/CorsivaBold.ttf'}, + 'couriernew': {(False, False): '/Library/Fonts/Courier New.ttf', + (False, True): '/Library/Fonts/Courier New Italic.ttf', + (True, False): '/Library/Fonts/Courier New Bold.ttf', + (True, True): '/Library/Fonts/Courier New Bold Italic.ttf'}, + 'decotypenaskh': {(False, False): '/Library/Fonts/DecoTypeNaskh.ttf'}, + 'devanagarimt': {(False, False): '/Library/Fonts/DevanagariMT.ttf', + (True, False): '/Library/Fonts/DevanagariMTBold.ttf'}, + 'euphemiaucas': {(False, False): '/Library/Fonts/EuphemiaCASRegular.ttf', + (False, True): '/Library/Fonts/EuphemiaCASItalic.ttf', + (True, False): '/Library/Fonts/EuphemiaCASBold.ttf'}, + 'gb18030bitmap': {(False, False): '/Library/Fonts/NISC18030.ttf'}, + 'geezapro': {(False, False): '/System/Library/Fonts/Geeza Pro.ttf', + (True, False): '/System/Library/Fonts/Geeza Pro Bold.ttf'}, + 'georgia': {(False, False): '/Library/Fonts/Georgia.ttf', + (False, True): '/Library/Fonts/Georgia Italic.ttf', + (True, False): '/Library/Fonts/Georgia Bold.ttf', + (True, True): '/Library/Fonts/Georgia Bold Italic.ttf'}, + 'gujaratimt': {(False, False): '/Library/Fonts/GujaratiMT.ttf', + (True, False): '/Library/Fonts/GujaratiMTBold.ttf'}, + 'gurmukhimt': {(False, False): '/Library/Fonts/Gurmukhi.ttf'}, + 'impact': {(False, False): '/Library/Fonts/Impact.ttf'}, + 'inaimathi': {(False, False): '/Library/Fonts/InaiMathi.ttf'}, + 'kailasa': {(False, False): '/Library/Fonts/Kailasa.ttf'}, + 'kokonor': {(False, False): '/Library/Fonts/Kokonor.ttf'}, + 'krungthep': {(False, False): '/Library/Fonts/Krungthep.ttf'}, + 'kufistandardgk': {(False, False): '/Library/Fonts/KufiStandardGK.ttf'}, + 'liheipro': {(False, False): '/System/Library/Fonts/ Pro.ttf'}, + 'lisongpro': {(False, False): '/Library/Fonts/ Pro.ttf'}, + 'microsoftsansserif': {(False, False): '/Library/Fonts/Microsoft Sans Serif.ttf'}, + 'mshtakan': {(False, False): '/Library/Fonts/MshtakanRegular.ttf', + (False, True): '/Library/Fonts/MshtakanOblique.ttf', + (True, False): '/Library/Fonts/MshtakanBold.ttf', + (True, True): '/Library/Fonts/MshtakanBoldOblique.ttf'}, + 'nadeem': {(False, False): '/Library/Fonts/Nadeem.ttf'}, + 'newpeninimmt': {(False, False): '/Library/Fonts/NewPeninimMT.ttf', + (True, False): '/Library/Fonts/NewPeninimMTBoldInclined.ttf'}, + 'plantagenetcherokee': {(False, False): '/Library/Fonts/PlantagenetCherokee.ttf'}, + 'raanana': {(False, False): '/Library/Fonts/Raanana.ttf', + (True, False): '/Library/Fonts/RaananaBold.ttf'}, + 'sathu': {(False, False): '/Library/Fonts/Sathu.ttf'}, + 'silom': {(False, False): '/Library/Fonts/Silom.ttf'}, + 'stfangsong': {(False, False): '/Library/Fonts/.ttf'}, + 'stheiti': {(False, False): '/System/Library/Fonts/.ttf'}, + 'stkaiti': {(False, False): '/Library/Fonts/.ttf'}, + 'stsong': {(False, False): '/Library/Fonts/.ttf'}, + 'tahoma': {(False, False): '/Library/Fonts/Tahoma.ttf', + (True, False): '/Library/Fonts/Tahoma Bold.ttf'}, + 'thonburi': {(False, False): '/System/Library/Fonts/Thonburi.ttf', + (True, False): '/System/Library/Fonts/ThonburiBold.ttf'}, + 'timesnewroman': {(False, False): '/Library/Fonts/Times New Roman.ttf', + (False, True): '/Library/Fonts/Times New Roman Italic.ttf', + (True, False): '/Library/Fonts/Times New Roman Bold.ttf', + (True, True): '/Library/Fonts/Times New Roman Bold Italic.ttf'}, + 'trebuchetms': {(False, False): '/Library/Fonts/Trebuchet MS.ttf', + (False, True): '/Library/Fonts/Trebuchet MS Italic.ttf', + (True, False): '/Library/Fonts/Trebuchet MS Bold.ttf', + (True, True): '/Library/Fonts/Trebuchet MS Bold Italic.ttf'}, + 'verdana': {(False, False): '/Library/Fonts/Verdana.ttf', + (False, True): '/Library/Fonts/Verdana Italic.ttf', + (True, False): '/Library/Fonts/Verdana Bold.ttf', + (True, True): '/Library/Fonts/Verdana Bold Italic.ttf'}, + 'webdings': {(False, False): '/Library/Fonts/Webdings.ttf'}, + 'wingdings': {(False, False): '/Library/Fonts/Wingdings.ttf'}, + 'wingdings2': {(False, False): '/Library/Fonts/Wingdings 2.ttf'}, + 'wingdings3': {(False, False): '/Library/Fonts/Wingdings 3.ttf'}} + + +def _search_osx_font_paths(fonts): + + for name, details in _OSX_default_font_files.items(): + for k, apath in details.items(): + if os.path.exists(apath): + bold, italic = k + _addfont(name, bold, italic, apath, fonts) + + +def initsysfonts_darwin(): + """ read the fonts on OSX. + """ + # if the X11 binary exists... try and use that. + # Not likely to be there on pre 10.4.x ... + # so still need to do other OSX specific method below. + if os.path.exists("/usr/X11/bin/fc-list"): + fonts = initsysfonts_unix() + + # we look for the default paths. + _search_osx_font_paths(fonts) + + return fonts + + + + + + paths = ['/Library/Fonts', + '~/Library/Fonts', + '/Local/Library/Fonts', + '/Network/Library/Fonts'] + fonts = {} + for p in paths: + if os.path.isdir(p): + pass + #os.path.walk(p, _fontwalk, fonts) + return fonts + + + + +#read the fonts on unix +def initsysfonts_unix(): + import subprocess + + fonts = {} + + # we use the fc-list from fontconfig to get a list of fonts. + + try: + # note, we capture stderr so if fc-list isn't there to stop stderr printing. + flout, flerr = subprocess.Popen('fc-list : file family style', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + close_fds=True).communicate() + except Exception: + return fonts + + entries = toascii(flout) + try: + for line in entries.split('\n'): + try: + filename, family, style = line.split(':', 2) + if filename[-4:].lower() in ['.ttf', '.ttc']: + bold = style.find('Bold') >= 0 + italic = style.find('Italic') >= 0 + oblique = style.find('Oblique') >= 0 + for name in family.split(','): + if name: + break + else: + name = os.path.splitext(os.path.basename(filename))[0] + _addfont(_simplename(name), + bold, italic or oblique, filename, fonts) + except Exception: + # try the next one. + pass + except Exception: + pass + + return fonts + + + +#create alias entries +def create_aliases(): + aliases = ( + ('monospace', 'misc-fixed', 'courier', 'couriernew', 'console', + 'fixed', 'mono', 'freemono', 'bitstreamverasansmono', + 'verasansmono', 'monotype', 'lucidaconsole'), + ('sans', 'arial', 'helvetica', 'swiss', 'freesans', + 'bitstreamverasans', 'verasans', 'verdana', 'tahoma'), + ('serif', 'times', 'freeserif', 'bitstreamveraserif', 'roman', + 'timesroman', 'timesnewroman', 'dutch', 'veraserif', + 'georgia'), + ('wingdings', 'wingbats'), + ) + for set in aliases: + found = None + fname = None + for name in set: + if name in Sysfonts: + found = Sysfonts[name] + fname = name + break + if not found: + continue + for name in set: + if name not in Sysfonts: + Sysalias[name] = found + + +Sysfonts = {} +Sysalias = {} + +#initialize it all, called once +def initsysfonts(): + if sys.platform == 'win32': + fonts = initsysfonts_win32() + elif sys.platform == 'darwin': + fonts = initsysfonts_darwin() + else: + fonts = initsysfonts_unix() + Sysfonts.update(fonts) + create_aliases() + if not Sysfonts: #dummy so we don't try to reinit + Sysfonts[None] = None + + + +#the exported functions + +def SysFont(name, size, bold=False, italic=False): + """pygame.font.SysFont(name, size, bold=False, italic=False) -> Font + create a pygame Font from system font resources + + This will search the system fonts for the given font + name. You can also enable bold or italic styles, and + the appropriate system font will be selected if available. + + This will always return a valid Font object, and will + fallback on the builtin pygame font if the given font + is not found. + + Name can also be a comma separated list of names, in + which case set of names will be searched in order. Pygame + uses a small set of common font aliases, if the specific + font you ask for is not available, a reasonable alternative + may be used. + """ + import pygame.font + + if not Sysfonts: + initsysfonts() + + gotbold = gotitalic = False + fontname = None + if name: + allnames = name + for name in allnames.split(','): + name = _simplename(name) + styles = Sysfonts.get(name) + if not styles: + styles = Sysalias.get(name) + if styles: + while not fontname: + plainname = styles.get((False, False)) + fontname = styles.get((bold, italic)) + if not fontname: + fontname = plainname + elif plainname != fontname: + gotbold = bold + gotitalic = italic + if fontname: break + + font = pygame.font.Font(fontname, size) + if bold and not gotbold: + font.set_bold(1) + if italic and not gotitalic: + font.set_italic(1) + + return font + + +def get_fonts(): + """pygame.font.get_fonts() -> list + get a list of system font names + + Returns the list of all found system fonts. Note that + the names of the fonts will be all lowercase with spaces + removed. This is how pygame internally stores the font + names for matching. + """ + if not Sysfonts: + initsysfonts() + return list(Sysfonts.keys()) + + +def match_font(name, bold=0, italic=0): + """pygame.font.match_font(name, bold=0, italic=0) -> name + find the filename for the named system font + + This performs the same font search as the SysFont() + function, only it returns the path to the TTF file + that would be loaded. The font name can be a comma + separated list of font names to try. + + If no match is found, None is returned. + """ + if not Sysfonts: + initsysfonts() + + fontname = None + allnames = name + for name in allnames.split(','): + name = _simplename(name) + styles = Sysfonts.get(name) + if not styles: + styles = Sysalias.get(name) + if styles: + while not fontname: + fontname = styles.get((bold, italic)) + if italic: + italic = 0 + elif bold: + bold = 0 + elif not fontname: + fontname = list(styles.values())[0] + if fontname: break + return fontname + + diff --git a/src/pygame/threads/.gitignore b/src/pygame/threads/.gitignore new file mode 100644 index 0000000..a74b07a --- /dev/null +++ b/src/pygame/threads/.gitignore @@ -0,0 +1 @@ +/*.pyc diff --git a/src/pygame/threads/Py25Queue.py b/src/pygame/threads/Py25Queue.py new file mode 100644 index 0000000..603c1bd --- /dev/null +++ b/src/pygame/threads/Py25Queue.py @@ -0,0 +1,216 @@ +"""A multi-producer, multi-consumer queue.""" + +from time import time as _time + +from collections import deque + +__all__ = ['Empty', 'Full', 'Queue'] + +class Empty(Exception): + "Exception raised by Queue.get(block=0)/get_nowait()." + pass + +class Full(Exception): + "Exception raised by Queue.put(block=0)/put_nowait()." + pass + +class Queue: + """Create a queue object with a given maximum size. + + If maxsize is <= 0, the queue size is infinite. + """ + def __init__(self, maxsize=0): + try: + import threading + except ImportError: + import dummy_threading as threading + self._init(maxsize) + # mutex must be held whenever the queue is mutating. All methods + # that acquire mutex must release it before returning. mutex + # is shared between the three conditions, so acquiring and + # releasing the conditions also acquires and releases mutex. + self.mutex = threading.Lock() + # Notify not_empty whenever an item is added to the queue; a + # thread waiting to get is notified then. + self.not_empty = threading.Condition(self.mutex) + # Notify not_full whenever an item is removed from the queue; + # a thread waiting to put is notified then. + self.not_full = threading.Condition(self.mutex) + # Notify all_tasks_done whenever the number of unfinished tasks + # drops to zero; thread waiting to join() is notified to resume + self.all_tasks_done = threading.Condition(self.mutex) + self.unfinished_tasks = 0 + + def task_done(self): + """Indicate that a formerly enqueued task is complete. + + Used by Queue consumer threads. For each get() used to fetch a task, + a subsequent call to task_done() tells the queue that the processing + on the task is complete. + + If a join() is currently blocking, it will resume when all items + have been processed (meaning that a task_done() call was received + for every item that had been put() into the queue). + + Raises a ValueError if called more times than there were items + placed in the queue. + """ + self.all_tasks_done.acquire() + try: + unfinished = self.unfinished_tasks - 1 + if unfinished <= 0: + if unfinished < 0: + raise ValueError('task_done() called too many times') + self.all_tasks_done.notifyAll() + self.unfinished_tasks = unfinished + finally: + self.all_tasks_done.release() + + def join(self): + """Blocks until all items in the Queue have been gotten and processed. + + The count of unfinished tasks goes up whenever an item is added to the + queue. The count goes down whenever a consumer thread calls task_done() + to indicate the item was retrieved and all work on it is complete. + + When the count of unfinished tasks drops to zero, join() unblocks. + """ + self.all_tasks_done.acquire() + try: + while self.unfinished_tasks: + self.all_tasks_done.wait() + finally: + self.all_tasks_done.release() + + def qsize(self): + """Return the approximate size of the queue (not reliable!).""" + self.mutex.acquire() + n = self._qsize() + self.mutex.release() + return n + + def empty(self): + """Return True if the queue is empty, False otherwise (not reliable!).""" + self.mutex.acquire() + n = self._empty() + self.mutex.release() + return n + + def full(self): + """Return True if the queue is full, False otherwise (not reliable!).""" + self.mutex.acquire() + n = self._full() + self.mutex.release() + return n + + def put(self, item, block=True, timeout=None): + """Put an item into the queue. + + If optional args 'block' is true and 'timeout' is None (the default), + block if necessary until a free slot is available. If 'timeout' is + a positive number, it blocks at most 'timeout' seconds and raises + the Full exception if no free slot was available within that time. + Otherwise ('block' is false), put an item on the queue if a free slot + is immediately available, else raise the Full exception ('timeout' + is ignored in that case). + """ + self.not_full.acquire() + try: + if not block: + if self._full(): + raise Full + elif timeout is None: + while self._full(): + self.not_full.wait() + else: + if timeout < 0: + raise ValueError("'timeout' must be a positive number") + endtime = _time() + timeout + while self._full(): + remaining = endtime - _time() + if remaining <= 0.0: + raise Full + self.not_full.wait(remaining) + self._put(item) + self.unfinished_tasks += 1 + self.not_empty.notify() + finally: + self.not_full.release() + + def put_nowait(self, item): + """Put an item into the queue without blocking. + + Only enqueue the item if a free slot is immediately available. + Otherwise raise the Full exception. + """ + return self.put(item, False) + + def get(self, block=True, timeout=None): + """Remove and return an item from the queue. + + If optional args 'block' is true and 'timeout' is None (the default), + block if necessary until an item is available. If 'timeout' is + a positive number, it blocks at most 'timeout' seconds and raises + the Empty exception if no item was available within that time. + Otherwise ('block' is false), return an item if one is immediately + available, else raise the Empty exception ('timeout' is ignored + in that case). + """ + self.not_empty.acquire() + try: + if not block: + if self._empty(): + raise Empty + elif timeout is None: + while self._empty(): + self.not_empty.wait() + else: + if timeout < 0: + raise ValueError("'timeout' must be a positive number") + endtime = _time() + timeout + while self._empty(): + remaining = endtime - _time() + if remaining <= 0.0: + raise Empty + self.not_empty.wait(remaining) + item = self._get() + self.not_full.notify() + return item + finally: + self.not_empty.release() + + def get_nowait(self): + """Remove and return an item from the queue without blocking. + + Only get an item if one is immediately available. Otherwise + raise the Empty exception. + """ + return self.get(False) + + # Override these methods to implement other queue organizations + # (e.g. stack or priority queue). + # These will only be called with appropriate locks held + + # Initialize the queue representation + def _init(self, maxsize): + self.maxsize = maxsize + self.queue = deque() + + def _qsize(self): + return len(self.queue) + + # Check whether the queue is empty + def _empty(self): + return not self.queue + + # Check whether the queue is full + def _full(self): + return self.maxsize > 0 and len(self.queue) == self.maxsize + + # Put a new item in the queue + def _put(self, item): + self.queue.append(item) + + # Get an item from the queue + def _get(self): + return self.queue.popleft() diff --git a/src/pygame/threads/__init__.py b/src/pygame/threads/__init__.py new file mode 100644 index 0000000..4931865 --- /dev/null +++ b/src/pygame/threads/__init__.py @@ -0,0 +1,310 @@ +""" +* Experimental * + +Like the map function, but can use a pool of threads. + +Really easy to use threads. eg. tmap(f, alist) + +If you know how to use the map function, you can use threads. +""" + +__author__ = "Rene Dudfield" +__version__ = "0.3.0" +__license__ = 'Python license' + +import traceback, sys + +from pygame.compat import geterror + +if sys.version_info[0] == 3: + from multiprocessing import JoinableQueue as Queue + from queue import Empty +elif (sys.version_info[0] == 2 and sys.version_info[1] < 5): + from Py25Queue import Queue + from Py25Queue import Empty +else: + # use up to date version + from Queue import Queue + from Queue import Empty + +import threading +Thread = threading.Thread + +STOP = object() +FINISH = object() + +# DONE_ONE = object() +# DONE_TWO = object() + +# a default worker queue. +_wq = None + +# if we are using threads or not. This is the number of workers. +_use_workers = 0 + +# Set this to the maximum for the amount of Cores/CPUs +# Note, that the tests early out. +# So it should only test the best number of workers +2 +MAX_WORKERS_TO_TEST = 64 + + + +def init(number_of_workers = 0): + """ Does a little test to see if threading is worth it. + Sets up a global worker queue if it's worth it. + + Calling init() is not required, but is generally better to do. + """ + global _wq, _use_workers + + if number_of_workers: + _use_workers = number_of_workers + else: + _use_workers = benchmark_workers() + + # if it is best to use zero workers, then use that. + _wq = WorkerQueue(_use_workers) + + + + +def quit(): + """ cleans up everything. + """ + global _wq, _use_workers + _wq.stop() + _wq = None + _use_workers = False + + +def benchmark_workers(a_bench_func = None, the_data = None): + """ does a little test to see if workers are at all faster. + Returns the number of workers which works best. + Takes a little bit of time to run, so you should only really call + it once. + You can pass in benchmark data, and functions if you want. + a_bench_func - f(data) + the_data - data to work on. + """ + global _use_workers + + #TODO: try and make this scale better with slower/faster cpus. + # first find some variables so that using 0 workers takes about 1.0 seconds. + # then go from there. + + + # note, this will only work with pygame 1.8rc3+ + # replace the doit() and the_data with something that releases the GIL + + + import pygame + import pygame.transform + import time + + if not a_bench_func: + def doit(x): + return pygame.transform.scale(x, (544, 576)) + else: + doit = a_bench_func + + if not the_data: + thedata = [] + for x in range(10): + thedata.append(pygame.Surface((155,155), 0, 32)) + else: + thedata = the_data + + best = time.time() + 100000000 + best_number = 0 + last_best = -1 + + for num_workers in range(0, MAX_WORKERS_TO_TEST): + + wq = WorkerQueue(num_workers) + t1 = time.time() + for xx in range(20): + print ("active count:%s" % threading.activeCount()) + results = tmap(doit, thedata, worker_queue = wq) + t2 = time.time() + + wq.stop() + + + total_time = t2 - t1 + print ("total time num_workers:%s: time:%s:" % (num_workers, total_time)) + + if total_time < best: + last_best = best_number + best_number =num_workers + best = total_time + + if num_workers - best_number > 1: + # We tried to add more, but it didn't like it. + # so we stop with testing at this number. + break + + + return best_number + + + + +class WorkerQueue(object): + + def __init__(self, num_workers = 20): + self.queue = Queue() + self.pool = [] + self._setup_workers(num_workers) + + def _setup_workers(self, num_workers): + """ Sets up the worker threads + NOTE: undefined behaviour if you call this again. + """ + self.pool = [] + + for _ in range(num_workers): + self.pool.append(Thread(target=self.threadloop)) + + for a_thread in self.pool: + a_thread.setDaemon(True) + a_thread.start() + + + def do(self, f, *args, **kwArgs): + """ puts a function on a queue for running later. + """ + self.queue.put((f, args, kwArgs)) + + + def stop(self): + """ Stops the WorkerQueue, waits for all of the threads to finish up. + """ + self.queue.put(STOP) + for thread in self.pool: + thread.join() + + + def threadloop(self): #, finish = False): + """ Loops until all of the tasks are finished. + """ + while True: + args = self.queue.get() + if args is STOP: + self.queue.put(STOP) + self.queue.task_done() + break + else: + try: + args[0](*args[1], **args[2]) + finally: + # clean up the queue, raise the exception. + self.queue.task_done() + #raise + + + def wait(self): + """ waits until all tasks are complete. + """ + self.queue.join() + +class FuncResult: + """ Used for wrapping up a function call so that the results are stored + inside the instances result attribute. + """ + def __init__(self, f, callback = None, errback = None): + """ f - is the function we that we call + callback(result) - this is called when the function(f) returns + errback(exception) - this is called when the function(f) raises + an exception. + """ + self.f = f + self.exception = None + self.callback = callback + self.errback = errback + + def __call__(self, *args, **kwargs): + + #we try to call the function here. If it fails we store the exception. + try: + self.result = self.f(*args, **kwargs) + if self.callback: + self.callback(self.result) + except Exception: + self.exception = geterror() + if self.errback: + self.errback(self.exception) + + +def tmap(f, seq_args, num_workers = 20, worker_queue = None, wait = True, stop_on_error = True): + """ like map, but uses a thread pool to execute. + num_workers - the number of worker threads that will be used. If pool + is passed in, then the num_workers arg is ignored. + worker_queue - you can optionally pass in an existing WorkerQueue. + wait - True means that the results are returned when everything is finished. + False means that we return the [worker_queue, results] right away instead. + results, is returned as a list of FuncResult instances. + stop_on_error - + """ + + if worker_queue: + wq = worker_queue + else: + # see if we have a global queue to work with. + if _wq: + wq = _wq + else: + if num_workers == 0: + return map(f, seq_args) + + wq = WorkerQueue(num_workers) + + # we short cut it here if the number of workers is 0. + # normal map should be faster in this case. + if len(wq.pool) == 0: + return map(f, seq_args) + + #print ("queue size:%s" % wq.queue.qsize()) + + + #TODO: divide the data (seq_args) into even chunks and + # then pass each thread a map(f, equal_part(seq_args)) + # That way there should be less locking, and overhead. + + + + results = [] + for sa in seq_args: + results.append(FuncResult(f)) + wq.do(results[-1], sa) + + + #wq.stop() + + if wait: + #print ("wait") + wq.wait() + #print ("after wait") + #print ("queue size:%s" % wq.queue.qsize()) + if wq.queue.qsize(): + raise Exception("buggy threadmap") + # if we created a worker queue, we need to stop it. + if not worker_queue and not _wq: + #print ("stoping") + wq.stop() + if wq.queue.qsize(): + um = wq.queue.get() + if not um is STOP: + raise Exception("buggy threadmap") + + + # see if there were any errors. If so raise the first one. This matches map behaviour. + # TODO: the traceback doesn't show up nicely. + # NOTE: TODO: we might want to return the results anyway? This should be an option. + if stop_on_error: + error_ones = filter(lambda x:x.exception, results) + if error_ones: + raise error_ones[0].exception + + return map(lambda x:x.result, results) + else: + return [wq, results] diff --git a/src/pygame/threads/__init__.pyo b/src/pygame/threads/__init__.pyo new file mode 100644 index 0000000..6d335ba --- /dev/null +++ b/src/pygame/threads/__init__.pyo Binary files differ diff --git a/src/pygame/time.so b/src/pygame/time.so new file mode 100644 index 0000000..1dcaf56 --- /dev/null +++ b/src/pygame/time.so Binary files differ diff --git a/src/pygame/transform.so b/src/pygame/transform.so new file mode 100644 index 0000000..79863b5 --- /dev/null +++ b/src/pygame/transform.so Binary files differ diff --git a/src/pygame/version.py b/src/pygame/version.py new file mode 100644 index 0000000..283fb65 --- /dev/null +++ b/src/pygame/version.py @@ -0,0 +1,31 @@ +## pygame - Python Game Library +## Copyright (C) 2000-2003 Pete Shinners +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Pete Shinners +## pete@shinners.org + +"""Simply the current installed pygame version. The version information is +stored in the regular pygame module as 'pygame.ver'. Keeping the version +information also available in a separate module allows you to test the +pygame version without importing the main pygame module. + +The python version information should always compare greater than any previous +releases. (hmm, until we get to versions > 10) +""" + +ver = '1.9.1release' +vernum = 1,9,1 diff --git a/src/pygame/version.pyo b/src/pygame/version.pyo new file mode 100644 index 0000000..ad10b80 --- /dev/null +++ b/src/pygame/version.pyo Binary files differ diff --git a/src/setup.py b/src/setup.py new file mode 100644 index 0000000..6ea61a6 --- /dev/null +++ b/src/setup.py @@ -0,0 +1,3 @@ +#!/usr/bin/python +from sugar.activity import bundlebuilder +bundlebuilder.start() diff --git a/src/sugargame/__init__.py b/src/sugargame/__init__.py new file mode 100644 index 0000000..439eb0c --- /dev/null +++ b/src/sugargame/__init__.py @@ -0,0 +1 @@ +__version__ = '1.1' diff --git a/src/sugargame/__init__.pyo b/src/sugargame/__init__.pyo new file mode 100644 index 0000000..a097d95 --- /dev/null +++ b/src/sugargame/__init__.pyo Binary files differ diff --git a/src/sugargame/canvas.py b/src/sugargame/canvas.py new file mode 100644 index 0000000..980cb73 --- /dev/null +++ b/src/sugargame/canvas.py @@ -0,0 +1,62 @@ +import os +import gtk +import gobject +import pygame +import event + +CANVAS = None + +class PygameCanvas(gtk.EventBox): + + """ + mainwindow is the activity intself. + """ + def __init__(self, mainwindow, pointer_hint = True): + gtk.EventBox.__init__(self) + + global CANVAS + assert CANVAS == None, "Only one PygameCanvas can be created, ever." + CANVAS = self + + # Initialize Events translator before widget gets "realized". + self.translator = event.Translator(mainwindow, self) + + self._mainwindow = mainwindow + + self.set_flags(gtk.CAN_FOCUS) + + self._socket = gtk.Socket() + self.add(self._socket) + self.show_all() + + def run_pygame(self, main_fn): + # Run the main loop after a short delay. The reason for the delay is that the + # Sugar activity is not properly created until after its constructor returns. + # If the Pygame main loop is called from the activity constructor, the + # constructor never returns and the activity freezes. + gobject.idle_add(self._run_pygame_cb, main_fn) + + def _run_pygame_cb(self, main_fn): + assert pygame.display.get_surface() is None, "PygameCanvas.run_pygame can only be called once." + + # Preinitialize Pygame with the X window ID. + assert pygame.display.get_init() == False, "Pygame must not be initialized before calling PygameCanvas.run_pygame." + os.environ['SDL_WINDOWID'] = str(self._socket.get_id()) + pygame.init() + + # Restore the default cursor. + self._socket.window.set_cursor(None) + + # Initialize the Pygame window. + r = self.get_allocation() + pygame.display.set_mode((r.width, r.height), pygame.RESIZABLE) + + # Hook certain Pygame functions with GTK equivalents. + self.translator.hook_pygame() + + # Run the Pygame main loop. + main_fn() + return False + + def get_pygame_widget(self): + return self._socket diff --git a/src/sugargame/canvas.pyo b/src/sugargame/canvas.pyo new file mode 100644 index 0000000..9dc8f47 --- /dev/null +++ b/src/sugargame/canvas.pyo Binary files differ diff --git a/src/sugargame/event.py b/src/sugargame/event.py new file mode 100644 index 0000000..4cc3be8 --- /dev/null +++ b/src/sugargame/event.py @@ -0,0 +1,243 @@ +import gtk +import gobject +import pygame +import pygame.event +import logging + +class _MockEvent(object): + def __init__(self, keyval): + self.keyval = keyval + +class Translator(object): + key_trans = { + 'Alt_L': pygame.K_LALT, + 'Alt_R': pygame.K_RALT, + 'Control_L': pygame.K_LCTRL, + 'Control_R': pygame.K_RCTRL, + 'Shift_L': pygame.K_LSHIFT, + 'Shift_R': pygame.K_RSHIFT, + 'Super_L': pygame.K_LSUPER, + 'Super_R': pygame.K_RSUPER, + 'KP_Page_Up' : pygame.K_KP9, + 'KP_Page_Down' : pygame.K_KP3, + 'KP_End' : pygame.K_KP1, + 'KP_Home' : pygame.K_KP7, + 'KP_Up' : pygame.K_KP8, + 'KP_Down' : pygame.K_KP2, + 'KP_Left' : pygame.K_KP4, + 'KP_Right' : pygame.K_KP6, + + } + + mod_map = { + pygame.K_LALT: pygame.KMOD_LALT, + pygame.K_RALT: pygame.KMOD_RALT, + pygame.K_LCTRL: pygame.KMOD_LCTRL, + pygame.K_RCTRL: pygame.KMOD_RCTRL, + pygame.K_LSHIFT: pygame.KMOD_LSHIFT, + pygame.K_RSHIFT: pygame.KMOD_RSHIFT, + } + + def __init__(self, mainwindow, inner_evb): + """Initialise the Translator with the windows to which to listen""" + self._mainwindow = mainwindow + self._inner_evb = inner_evb + + # Enable events + # (add instead of set here because the main window is already realized) + self._mainwindow.add_events( + gtk.gdk.KEY_PRESS_MASK | \ + gtk.gdk.KEY_RELEASE_MASK \ + ) + + self._inner_evb.set_events( + gtk.gdk.POINTER_MOTION_MASK | \ + gtk.gdk.POINTER_MOTION_HINT_MASK | \ + gtk.gdk.BUTTON_MOTION_MASK | \ + gtk.gdk.BUTTON_PRESS_MASK | \ + gtk.gdk.BUTTON_RELEASE_MASK + ) + + self._mainwindow.set_flags(gtk.CAN_FOCUS) + self._inner_evb.set_flags(gtk.CAN_FOCUS) + + # Callback functions to link the event systems + self._mainwindow.connect('unrealize', self._quit_cb) + self._inner_evb.connect('key_press_event', self._keydown_cb) + self._inner_evb.connect('key_release_event', self._keyup_cb) + self._inner_evb.connect('button_press_event', self._mousedown_cb) + self._inner_evb.connect('button_release_event', self._mouseup_cb) + self._inner_evb.connect('motion-notify-event', self._mousemove_cb) + self._inner_evb.connect('expose-event', self._expose_cb) + self._inner_evb.connect('configure-event', self._resize_cb) + + # Internal data + self.__stopped = False + self.__keystate = [0] * 323 + self.__button_state = [0,0,0] + self.__mouse_pos = (0,0) + self.__repeat = (None, None) + self.__held = set() + self.__held_time_left = {} + self.__held_last_time = {} + self.__tick_id = None + + def hook_pygame(self): + pygame.key.get_pressed = self._get_pressed + pygame.key.set_repeat = self._set_repeat + pygame.mouse.get_pressed = self._get_mouse_pressed + pygame.mouse.get_pos = self._get_mouse_pos + + def _expose_cb(self, event, widget): + if pygame.display.get_init(): + pygame.event.post(pygame.event.Event(pygame.VIDEOEXPOSE)) + return True + + def _resize_cb(self, widget, event): + evt = pygame.event.Event(pygame.VIDEORESIZE, + size=(event.width,event.height), width=event.width, height=event.height) + pygame.event.post(evt) + return False # continue processing + + def _quit_cb(self, data=None): + self.__stopped = True + pygame.event.post(pygame.event.Event(pygame.QUIT)) + + def _keydown_cb(self, widget, event): + key = event.keyval + if key in self.__held: + return True + else: + if self.__repeat[0] is not None: + self.__held_last_time[key] = pygame.time.get_ticks() + self.__held_time_left[key] = self.__repeat[0] + self.__held.add(key) + + return self._keyevent(widget, event, pygame.KEYDOWN) + + def _keyup_cb(self, widget, event): + key = event.keyval + if self.__repeat[0] is not None: + if key in self.__held: + # This is possibly false if set_repeat() is called with a key held + del self.__held_time_left[key] + del self.__held_last_time[key] + self.__held.discard(key) + + return self._keyevent(widget, event, pygame.KEYUP) + + def _keymods(self): + mod = 0 + for key_val, mod_val in self.mod_map.iteritems(): + mod |= self.__keystate[key_val] and mod_val + return mod + + def _keyevent(self, widget, event, type): + key = gtk.gdk.keyval_name(event.keyval) + if key is None: + # No idea what this key is. + return False + + keycode = None + if key in self.key_trans: + keycode = self.key_trans[key] + elif hasattr(pygame, 'K_'+key.upper()): + keycode = getattr(pygame, 'K_'+key.upper()) + elif hasattr(pygame, 'K_'+key.lower()): + keycode = getattr(pygame, 'K_'+key.lower()) + elif key == 'XF86Start': + # view source request, specially handled... + self._mainwindow.view_source() + else: + print 'Key %s unrecognized' % key + + if keycode is not None: + if type == pygame.KEYDOWN: + mod = self._keymods() + self.__keystate[keycode] = type == pygame.KEYDOWN + if type == pygame.KEYUP: + mod = self._keymods() + ukey = unichr(gtk.gdk.keyval_to_unicode(event.keyval)) + if ukey == '\000': + ukey = '' + evt = pygame.event.Event(type, key=keycode, unicode=ukey, mod=mod) + self._post(evt) + + return True + + def _get_pressed(self): + return self.__keystate + + def _get_mouse_pressed(self): + return self.__button_state + + def _mousedown_cb(self, widget, event): + self.__button_state[event.button-1] = 1 + return self._mouseevent(widget, event, pygame.MOUSEBUTTONDOWN) + + def _mouseup_cb(self, widget, event): + self.__button_state[event.button-1] = 0 + return self._mouseevent(widget, event, pygame.MOUSEBUTTONUP) + + def _mouseevent(self, widget, event, type): + evt = pygame.event.Event(type, button=event.button, pos=(event.x, event.y)) + self._post(evt) + return True + + def _mousemove_cb(self, widget, event): + # From http://www.learningpython.com/2006/07/25/writing-a-custom-widget-using-pygtk/ + # if this is a hint, then let's get all the necessary + # information, if not it's all we need. + if event.is_hint: + x, y, state = event.window.get_pointer() + else: + x = event.x + y = event.y + state = event.state + + rel = (x - self.__mouse_pos[0], y - self.__mouse_pos[1]) + self.__mouse_pos = (x, y) + + self.__button_state = [ + state & gtk.gdk.BUTTON1_MASK and 1 or 0, + state & gtk.gdk.BUTTON2_MASK and 1 or 0, + state & gtk.gdk.BUTTON3_MASK and 1 or 0, + ] + + evt = pygame.event.Event(pygame.MOUSEMOTION, + pos=self.__mouse_pos, rel=rel, buttons=self.__button_state) + self._post(evt) + return True + + def _tick_cb(self): + cur_time = pygame.time.get_ticks() + for key in self.__held: + delta = cur_time - self.__held_last_time[key] + self.__held_last_time[key] = cur_time + + self.__held_time_left[key] -= delta + if self.__held_time_left[key] <= 0: + self.__held_time_left[key] = self.__repeat[1] + self._keyevent(None, _MockEvent(key), pygame.KEYDOWN) + + return True + + def _set_repeat(self, delay=None, interval=None): + if delay is not None and self.__repeat[0] is None: + self.__tick_id = gobject.timeout_add(10, self._tick_cb) + elif delay is None and self.__repeat[0] is not None: + gobject.source_remove(self.__tick_id) + self.__repeat = (delay, interval) + + def _get_mouse_pos(self): + return self.__mouse_pos + + def _post(self, evt): + try: + pygame.event.post(evt) + except pygame.error, e: + if str(e) == 'Event queue full': + print "Event queue full!" + pass + else: + raise e diff --git a/src/sugargame/event.pyo b/src/sugargame/event.pyo new file mode 100644 index 0000000..e0ca3e6 --- /dev/null +++ b/src/sugargame/event.pyo Binary files differ diff --git a/src/zbar.so b/src/zbar.so new file mode 100644 index 0000000..93842c8 --- /dev/null +++ b/src/zbar.so Binary files differ -- cgit v0.9.1