new_rdpyg/0000755000175100017510000000000010225416076012765 5ustar renerene00000000000000new_rdpyg/build/0000755000175100017510000000000010076374156014072 5ustar renerene00000000000000new_rdpyg/build/lib/0000755000175100017510000000000010076374157014641 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/0000755000175100017510000000000010076374156015765 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/app/0000755000175100017510000000000010076374156016545 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/app/the_app_gl.py0000644000175100017510000001045310065303172021210 0ustar renerene00000000000000import the_app import pygame from pygame.locals import DOUBLEBUF, OPENGL, FULLSCREEN, QUIT, KEYDOWN, K_ESCAPE from OpenGL.GL import glMatrixMode, GL_PROJECTION, glLoadIdentity, glClearColor, glClear, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, glGetFloatv, GL_PROJECTION_MATRIX, GL_MODELVIEW, glViewport, glGetDoublev, GL_MODELVIEW_MATRIX from OpenGL.GLU import gluPerspective, gluUnProject class TheAppGL(the_app.TheApp): def Display(self): """ A default display. Which clears the color buffer and depth buffer. """ self._debug("running display", 4) glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) def InitDisplay(self, width, height, first_time = 0): """ A default InitDisplay. """ self._debug("initializing display", 4) if first_time: full_display_flags = DOUBLEBUF | OPENGL | FULLSCREEN display_flags = DOUBLEBUF | OPENGL if self.full_screen: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") if pygame.display.mode_ok((width, height), full_display_flags ): self.screen = pygame.display.set_mode((width, height), full_display_flags) else: raise ValueError("error initializing display, can not get mode") else: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") else: if self.full_screen: display_flags = DOUBLEBUF | OPENGL | FULLSCREEN else: display_flags = DOUBLEBUF | OPENGL if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") def Start(self): """ """ self._debug("starting", 4) width, height = 640, 480 #width, height = 1024, 768 self.width, self.height = width, height self.InitDisplay(width, height, first_time = 1) glViewport(0,0, width, height) # sets up the projection matrix. self.SetupProjection(width, height) self.Load() def SetupProjection(self, width = 640, height = 480, zNear = 5., zFar = 300.): """ Sets up the projection matrix for opengl. """ # set the projection transformation glMatrixMode(GL_PROJECTION) glLoadIdentity() #TODO: replace the glu call with something else. #gluPerspective(45.0, float(width) / height, scale * 50.0, scale * 1000.0) #gluPerspective(45.0, float(self.width) / float(self.height), 5.0, 1000.0) self.zNear = zNear self.zFar = zFar self.buffer_calc_a = self.zFar / ( self.zFar - self.zNear ) self.buffer_calc_b = self.zFar * self.zNear / ( self.zNear - self.zFar ) gluPerspective(45.0, float(width) / float(height), self.zNear, self.zFar) self.gl_projection_matrix = glGetFloatv(GL_PROJECTION_MATRIX) # set the model transformation glMatrixMode(GL_MODELVIEW) def GetWorldCoords(self, x,y, camera_z): """ returns (x,y,z) given x,y pygame screen coords. NOTE: try and get the model view matrix back to the camera position when using. """ y = self.height - y mod = glGetDoublev(GL_MODELVIEW_MATRIX) proj = glGetDoublev(GL_PROJECTION_MATRIX) #view = glGetIntegerv(GL_VIEWPORT) view = (0, 0, self.width, self.height) z = abs(camera_z) z_buffer_value = self.buffer_calc_a +self.buffer_calc_b / z objx, objy, objz = gluUnProject(x,y,z_buffer_value, mod, proj,view) return (objx, objy, objz) new_rdpyg/build/lib/rdpyg/app/__init__.py0000644000175100017510000000000010065306042020627 0ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/app/the_app.py0000644000175100017510000002062610067272533020541 0ustar renerene00000000000000#file: the_app.py #purpose: a base class for making applications from. """ TODO: a way to chose between display flip and update. without overriding the whole method. TheApp is a class for making a game like application, implementing functionality common in many games. The idea is to make constructing games and demos quick, with minimal code. There are a number of different methods with default implementations to save work. Most of these can be overridden if you need to specialise any parts. = How the main loop works. = TheApp class has a couple of different ways which it handles the main loop internally. It can use a while loop or the twisted reactor. However by using the methods provided you should not have to modify this. It can be instructional to have at a look at the source for different methods, so that overriding them can be easy. This is the 2d pygame version of the class. There is an opengl version named rdpyg.app.the_app_gl.TheAppGL = Commonly overridden methods = * Display * Your drawing code. * Update * Updating your game logic, game play, and game ai. * HandleEvents * Code to handle user input, operating system interaction, and other events. * Load * Code to load your game data. Like images, sounds etc. = Order of operation = The order in which the different methods get called is to update your game objects, handle user input, do your display changes. Start() InitDislpay() Load() Loop() Before loops starts looping: LoopInit() SetupTiming() Every 'tic' or frame of loop: Update() HandleEvents() DoBeforeDisplay() Display() DoAfterFlip() """ try: import config except: class blablablabla: USE_TWISTED = 0 full_screen = 0 config = blablablabla() import time import pygame from pygame.locals import DOUBLEBUF, OPENGL, FULLSCREEN, QUIT, KEYDOWN, K_ESCAPE # TODO: speed up loading time. this takes 0.2959 to load. if config.USE_TWISTED: import twisted.internet.reactor import traceback import sys class TheApp: """ An application class to handle lots of common things within games, and game like applications, using pygame. A lot of the methods are meant to be overrided. However they all come with sane default implementations. Useage: a = TheApp() a.Start() a.Loop() a.Stop() """ def __init__(self, debug_level = 0): self._debug_level = debug_level self.frames = 0 self.full_screen = config.full_screen def _debug(self, x, debug_level = 0): """ """ if self._debug_level > debug_level: print x def Display(self): """ This is called before the display is flipped(or updated). Your drawing code should go in here. """ self._debug("running display", 4) def InitDisplay(self, width, height, first_time = 0): """ A default InitDisplay. first_time - useful for working around some buggy systems. make it true if this is the first time calling it. """ self._debug("initializing display", 4) if first_time: full_display_flags = DOUBLEBUF | FULLSCREEN display_flags = DOUBLEBUF if self.full_screen: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") if pygame.display.mode_ok((width, height), full_display_flags ): self.screen = pygame.display.set_mode((width, height), full_display_flags) else: raise ValueError("error initializing display, can not get mode") else: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") else: if self.full_screen: display_flags = DOUBLEBUF | FULLSCREEN else: display_flags = DOUBLEBUF if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") def Stop(self): """ Called when we want to stop. """ pygame.quit() def Start(self): """ Do the game loading. """ self._debug("starting", 4) width, height = 640, 480 #width, height = 1024, 768 self.width, self.height = width, height self.InitDisplay(width, height, first_time = 1) self.Load() def Load(self): """ For loading stuff. """ def HandleEvents(self, event_list): """ should handle the events every game tic. """ for event in event_list: if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): self.Stop() return 0 return 1 def Update(self, elapsed_time): """ update any game state. """ def OneTic(self): """ Does one game 'tic' worth of stuff. Should return 1 if not wanting to quit. If wanting to quit return 0. """ try: self.current_time, self.elapsed_time = self.TicTiming() if not self.DoBeforeHandlingEvents(): if config.USE_TWISTED: twisted.internet.reactor.stop() #self.Stop() return 0 else: return 0 self.Update(self.elapsed_time) event_list = pygame.event.get() if not self.HandleEvents(event_list): if config.USE_TWISTED: twisted.internet.reactor.stop() #self.Stop() return 0 else: return 0 self.DoBeforeDisplay() self.Display() #flip_time1 = time.time() pygame.display.flip() #flip_time2 = time.time() #flip_time = flip_time2 - flip_time1 #print "flip_time:", flip_time self.DoAfterFlip() self.frames += 1 self.last_time = self.current_time if config.USE_TWISTED: # run as fast as it can. twisted.internet.reactor.callLater(0.0, self.OneTic) else: return 1 except: traceback.print_exc(sys.stderr) # we have an error, quit instead. if config.USE_TWISTED: twisted.internet.reactor.stop() return 0 def DoAfterFlip(self): """ Called after flip is done. """ def DoBeforeDisplay(self): """ Stuff done before Display() is called. """ def DoBeforeHandlingEvents(self): """ Stuff done before we handle the events. Should return 0 to quit. """ return 1 def TicTiming(self): """ Call this once per tic to update the timing. """ current_time = time.time() elapsed_time = current_time - self.last_time self.total_elapsed_time += elapsed_time return (current_time, elapsed_time) def GetFps(self): """ Returns the frames per second since the timing has begun. """ if self.total_elapsed_time == 0: return 0. return self.frames/self.total_elapsed_time def LoopInit(self): """ Should put use loop initialisation stuff here. """ def SetupTiming(self): """ Sets up some timing code. """ self.last_time = time.time() self.total_elapsed_time = 0. def Loop(self): """ Starts the game looping. Will eventually return. """ self.LoopInit() self.SetupTiming() if config.USE_TWISTED: twisted.internet.reactor.callLater(0.0, self.OneTic) twisted.internet.reactor.run() else: while 1: if not self.OneTic(): break new_rdpyg/build/lib/rdpyg/draw/0000755000175100017510000000000010076374156016722 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/draw/pygame/0000755000175100017510000000000010076374156020204 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/draw/pygame/__init__.py0000644000175100017510000000000010065304046022270 0ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/draw/pyopengl/0000755000175100017510000000000010076374156020557 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/draw/pyopengl/__init__.py0000644000175100017510000000000010065304046022643 0ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/draw/pyopengl/particles.py0000644000175100017510000002221410072755676023126 0ustar renerene00000000000000# purpose: particles. from OpenGL.GL import * #from OpenGL.GLU import gluPerspective import random from random import randint import os import pygame import pygame.image class Particle: def __init__(self): self.active = 0 self.life = 0. # fade speed. self.ifade = 0. # Red, green, blue values. self.r = 0. self.g = 0. self.b = 0. # x,y,z position. self.x = 0. self.y = 0. self.z = 0. # x,y,z direction. self.xi = 0. self.yi = 0. self.zi = 0. # x,y,z gravity. self.xg = 0. self.yg = 0. self.zg = 0. class cached_random: #def __init__(self, size_of_cache = 500): # self.size_of_cache = size_of_cache size_of_cache = 5000 rands100 = [] for x in range(size_of_cache): rands100.append(float(random.randint(1,100))) rands60 = [] for x in range(size_of_cache): rands60.append(float(random.randint(1,60))) rands30 = [] for x in range(size_of_cache): rands30.append(float(random.randint(1,30))) cursor30 = 0 cursor60 = 0 cursor100 = 0 def GetRandom100(self): self.cursor100 += 1 if(self.cursor100 >= self.size_of_cache): self.cursor100 = 0 return self.rands100[self.cursor100] def GetRandom60(self): #print self.cursor60 self.cursor60 += 1 if(self.cursor60 >= self.size_of_cache): self.cursor60 = 0 #print self.rands60[self.cursor60] return self.rands60[self.cursor60] def GetRandom30(self): self.cursor30 += 1 if(self.cursor30 >= self.size_of_cache): self.cursor30 = 0 return self.rands30[self.cursor30] class Particles: """ This is a set of particles baby. """ def __init__(self, num_particles): self.num_particles = num_particles if self.num_particles < 11: self.num_particles = 11 self.window = 0 self.zoom = -10 self.slowdown=2.0 self.xspeed = 5. self.yspeed = 2. self.col = 0 self.cube = None self.top = None self.rainbow = 1 self.delay = 0 self.particles = [] for x in range(self.num_particles): self.particles.append(Particle()) self.rand = cached_random() self.rand100 = self.rand.GetRandom100 self.rand60 = self.rand.GetRandom60 self.rand30 = self.rand.GetRandom30 self.colors = [ [1.0,0.5,0.5],[1.0,0.75,0.5],[1.0,1.0,0.5],[0.75,1.0,0.5], [0.5,1.0,0.5],[0.5,1.0,0.75],[0.5,1.0,1.0],[0.5,0.75,1.0], [0.5,0.5,1.0],[0.75,0.5,1.0],[1.0,0.5,1.0],[1.0,0.5,0.75] ] def _debug(self, s, x): pass def DisplayStateBegin(self): glEnable(GL_TEXTURE_2D) glDisable(GL_DEPTH_TEST) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA,GL_ONE) glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST) glHint(GL_POINT_SMOOTH_HINT,GL_NICEST) glBindTexture(GL_TEXTURE_2D, self.tex) def DisplayStateEnd(self): glDisable(GL_BLEND) glEnable(GL_DEPTH_TEST) glDisable(GL_TEXTURE_2D) def Update(self, elapsed_time): """ TODO: """ pass def Display(self): """ A default display. Which clears the color buffer and depth buffer. """ # Disables depth testing. #self.DisplayStateBegin() #TODO translate/rotate for position. self._debug("running display", 4) col0 = self.colors[self.col][0] col1 = self.colors[self.col][1] col2 = self.colors[self.col][2] rand100 = self.rand100 rand60 = self.rand60 slowdown1000 = self.slowdown * 1000 #particle = self.particles #for loop in range(len(self.particles)): for particle in self.particles: #if (particle.active): # Get our x,y,z x = particle.x y = particle.y #z = particle.z + self.zoom z = particle.z # Color it using our particles colors. glColor4f(particle.r,particle.g,particle.b,particle.life) glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex3f(x+0.5,y+0.5,z); glTexCoord2d(0,1); glVertex3f(x-0.5,y+0.5,z); glTexCoord2d(1,0); glVertex3f(x+0.5,y-0.5,z); glTexCoord2d(0,0); glVertex3f(x-0.5,y-0.5,z); glEnd() particle.x+=particle.xi/(slowdown1000) particle.y+=particle.yi/(slowdown1000) #particle.z+=particle.zi/(slowdown1000) particle.xi+=particle.xg particle.yi+=particle.yg particle.zi+=particle.zg particle.life-=particle.fade if (particle.life<0.0): particle.life=1.0 particle.fade=(rand100())/1000.0+0.003 particle.x=0.0 particle.y=0.0 particle.z=0.0 particle.xi=self.xspeed+(rand60())-32.0 particle.yi=self.yspeed+(rand60())-30.0 particle.zi=(rand60())-30.0 particle.r=self.colors[self.col][0] particle.g=self.colors[self.col][1] particle.b=self.colors[self.col][2] particle.r=col0 particle.g=col1 particle.b=col2 self.delay += 1 if self.rainbow and self.delay > 25: self.delay = 0 self.col += 1 if self.col >= len(self.colors): self.col = 0 #self.col += 1 #if(self.col == 11): # self.col = 0 ##glTranslatef(0., 0., self.ztranslate) ##glRotatef(self.xrot, 1.0, 0.0, 0.0) ##glRotatef(self.yrot, 0.0, 1.0, 0.0) #glColor3fv(boxcol[yloop-1]) ##glCallList(self.cube); #glColor3fv(topcol[yloop-1]); ##glCallList(self.top); ##self.xrot+=1.0 ##if(self.xrot >= 360): ## self.xrot = 0. ##self.yrot+=1.0 ##if(self.yrot >= 360): ## self.yrot = 0. ##self.zrot+=1.0 ##if(self.zrot >= 360): ## self.zrot = 0. #self.DisplayStateEnd() def Load(self, with_tex = None, file_name = None): """ with_tex can be an opengl texture. """ if with_tex == None: if file_name == None: self.LoadImagePng(os.path.join("data", "images", "particle.png")) else: self.LoadImagePng(file_name) self.MakeTexture() else: self.tex = with_tex self.InitParticles() def InitParticles(self): particle = self.particles for loop in range(len(self.particles)): particle[loop].active=1 particle[loop].life=1.0 particle[loop].fade= (random.random() * 100) /1000.0+0.003 particle[loop].r=self.colors[loop/(self.num_particles/11)][0] particle[loop].g=self.colors[loop/(self.num_particles/11)][1] particle[loop].b=self.colors[loop/(self.num_particles/11)][2] particle[loop].xi=float( (random.random()*50)-26.0 )*10.0 particle[loop].yi=float( (random.random()*50)-26.0 )*10.0 particle[loop].zi=float( (random.random()*50)-26.0 )*10.0 particle[loop].xg=0.0 particle[loop].yg=-0.8 particle[loop].zg=0.0 def LoadImagePng(self, filename): im_surf = pygame.image.load(filename) self.imageWidth, self.imageHeight = im_surf.get_size() print "image size is:", im_surf.get_size() self.image = pygame.image.tostring(im_surf, "RGBX", 1) #self.image = pygame.image.tostring(im_surf, "RGBA", 1) def MakeTexture(self): #return self.tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.tex) #scale linearly when image bigger than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) #scale linearly when image smalled than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) # 2d texture, level of detail 0 (normal), # 3 components (red, green, blue), # x size from image, # y size from image, # border 0 (normal), # rgb color data, # unsigned byte data, # and finally the data itself. glTexImage2D(GL_TEXTURE_2D, 0, 3, self.imageWidth, self.imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, self.image) #glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.imageWidth, self.imageHeight, 0, # GL_RGBA, GL_UNSIGNED_BYTE, self.image) new_rdpyg/build/lib/rdpyg/draw/pyopengl/paths.py0000644000175100017510000000207410067262621022244 0ustar renerene00000000000000 from OpenGL.GL import glBegin, GL_LINES, glVertex3f, glEnd, glPushAttrib, GL_ALL_ATTRIB_BITS, glMatrixMode, GL_MODELVIEW, glLoadIdentity, glScale, glTranslatef, glPopAttrib from OpenGL.GLUT import glutSolidTeapot def draw_path(a_path): """ draws a path with opengl lines. """ glBegin(GL_LINES) try: last = 0 for x,y,z in a_path.points: if last: glVertex3f(lx,ly,lz) glVertex3f(x,y,z) lx, ly, lz = x,y,z else: last = 1 lx, ly, lz = x,y,z finally: glEnd() def draw_path_with_traveler(a_path): """ draws a box where the position of the traveler is on the path. """ #TODO: speed this up. take out the scale as well. draw_path(a_path) # Get where the traveler is, and draw something there. x,y,z = a_path.Where() ##glPushAttrib(GL_ALL_ATTRIB_BITS) ##glMatrixMode(GL_MODELVIEW) ##glLoadIdentity() ##glScale(0.2, 0.2, 0.2) glTranslatef(x,y,z) # now draw a teapot there. glutSolidTeapot(0.1) glTranslatef(-x,-y,-z) ##glPopAttrib() new_rdpyg/build/lib/rdpyg/draw/__init__.py0000644000175100017510000000000010065305160021004 0ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/sprites/0000755000175100017510000000000010076374156017456 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/sprites/__init__.py0000644000175100017510000000000010065312357021546 0ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/sprites/spritegl.py0000644000175100017510000005470510073743546021674 0ustar renerene00000000000000""" Opengl drawing of pygame.sprite objects. With hopefully minimal/no changes to programs, and big speed increases. Rene Dudfield. illumen@yahoo.com TODO: First compatibilty, optimization, then next gen. NOTE: there are some more TODO's sprinkled througout the code Compatibilty. - need to implement all of screens methods. - test on more games. - chimp(works). - pyddr(doesn't work). - I think it has to do with the different format images. - I think a conversion may not be working properly. - bleten(works). - works, but is kinda slow when lots of images change. - need to work on a scaling method which uses opengl. - need to not use tostring() for making textures(slow). - work on caching some more, so that there is a texture cache as well. - so that images don't need to be uploaded to the card all the time. - yass(don't know). - a better way to detect when an images contents have changed. - probably a wrapper around surface, and surfarray which marks the image as dirty. - split sprites larger than 256x256 into multiple smaller textures. - for some older 3d cards. - should figure out how to detect max texture size. - support 8 and 16 bit and color keyed textures. - Make sure textures are cleaned up correctly in all cases. - Beta test on a wide number of machines. - Make it work correctly when the screen size changes. Optimization. - Put multiple sprites onto the same texture, and use uv coords for drawing particular sprites. This is a *big* optimization. - especially for animation. - move all texture management into the group, so as to optimize texture drawing more easily. - Have a set max number of textures to use in a texture cache. - Cache textures - optimize the screen.blit function, and some others: - with blit, only update a certain part of the texture which was actually blitted. - screen.fill - Group drawing by the same texture(less texture binds). - Try display lists to see if better performing. - try vertex buffers for better performance. - Make 1000+ sprite test case, and optimize for this case. - Update texture instead of replacing it when: - some pixels change in an image. - when the image changes and the old one isn't to be used anymore. - How to know this? Next gen. - Add scaling, rotation, other effects to a sprite class. - use caching of images for sdl, and straight opengl calls(eg glRotate etc). - shadows from sprites onto the background. - Make classes/optimize existing classes for drawing: - scrollers, tile maps, height maps, - 3d animated characters (http://www.py3d.org/py3d_zwiki/milkshape3d_animation) - doomIII clone ;) """ # search and replace this for __debug__ for a bit of a speed increase in -O _debug__ = 0 #Import Modules import os, pygame from pygame.locals import * from OpenGL.GL import * #from OpenGL.GLUT import * from OpenGL.GLU import * import time """ old_glMatrixMode = glMatrixMode def glMatrixMode(*args): modes = {GL_PROJECTION: "GL_PROJECTION", GL_MODELVIEW: "GL_MODELVIEW"} if _debug__: printw( glMatrixMode, modes[args[0]]) return apply(old_glMatrixMode, args) old_glTexSubImage2D = glTexSubImage2D def glTexSubImage2D(*args): if _debug__: printw( "glTexSubImage2D"+ str(args[:-1])) apply(old_glTexSubImage2D, args) """ #from _opengl2 import glVertexPointer, glColorPointer, glNormalPointer, glTexCoordPointer #from _opengl2 import glVertexPointer, glColorPointer, glNormalPointer#, glTexCoordPointer #from _opengl2 import glTexCoordPointer """ In order of easyness. make a draw method for the group. replace screen.blit with one which will work. make an update method. """ POWERS = (32, 64, 128, 256, 512, 1024, 2048, 4096) def nextPower(x): for y in POWERS: if y >= x: return y def printw(*args): print args from rdpyg.util import pack_textures #NOTE: TODO: maybe we shouldn't be using a subclass of Surface... pygame.old_Surface = pygame.Surface #class SurfaceGL(pygame.old_Surface): class SurfaceGL: """ This is useful for tracking changes in a surface. It takes a surface as a keyword initializer: eg s = SurfaceGL(initialize_with_this = a_surf) Or you can initialize it like a normal surface. Once the pixel data is changed, either is_dirty will be true, or changed_rects will not be empty. If is_dirty is true: then the whole image needs to be updated. Else: if changed_rects is not empty: update the rects which have been changed. """ def __init__(self, *args, **kwargs): if kwargs.has_key("initialize_with_this"): self.__dict__["realone"] = kwargs["initialize_with_this"] else: self.__dict__["realone"] = pygame.old_Surface(*args, **kwargs) # If this is dirty(ie has changed) then the whole image should # be reuploaded. Otherwise the rects from self.changed_rects will # be used for updating the image. self.__dict__["is_dirty"] = 0 # this is a list of rects to use when you only want to update a small # part of the image. self.__dict__["changed_areas"] = [] def __getattr__(self, name): if name == "realone": if self.__dict__.has_key("realone"): return self.__dict__["realone"] else: raise AttributeError(name) elif self.__dict__.has_key("realone"): if hasattr(self.__dict__["realone"], name): return getattr(self.__dict__["realone"], name) else: raise AttributeError(name) elif self.__dict__.has_key(name): return self.__dict__[name] else: print self.__dict__ raise AttributeError(name) def __setattr__(self, name, value): #print "ASDDFFAFDF", name, value if name in ["realone", "is_dirty", "changed_rects"]: self.__dict__[name] = value else: setattr(self.__dict__["realone"],name, value) def blit(self, *args): """ TODO: needs to keep track of which parts have been changed. For now marking the whole image as dirty. """ self.__dict__["is_dirty"] = 1 print type(args[0]) print dir(args[0]) # we need a real surface type for blit. if hasattr(args[0], "realone"): new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) if hasattr(args[0], "screen_gl"): new_args = list(args) new_args[0] = args[0].screen_gl.image args = tuple(new_args) return self.__dict__["realone"].blit(*args) def fill(self, *args): """ like a normal surface fill, but marks the thing as dirty. """ self.__dict__["is_dirty"] = 1 return self.__dict__["realone"].fill(*args) #pygame.sprite.Group_orig = pygame.sprite.Group #pygame.sprite.Sprite_orig = pygame.sprite.Sprite class GroupGL(pygame.sprite.Group) : def setup_draw_texture(self, screen_rect): """ Sets up opengl for drawing the textures. """ self.old_matrix_mode = glGetIntegerv(GL_MATRIX_MODE); if _debug__: printw( type(self.old_matrix_mode), self.old_matrix_mode) self.old_projection_matrix = glGetDoublev( GL_PROJECTION_MATRIX ) self.old_modelview_matrix = glGetDoublev( GL_MODELVIEW_MATRIX ) self.set_up_2d_projection(screen_rect) glEnable(GL_TEXTURE_2D) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) if _debug__: printw( "setup_draw_texture") glMatrixMode( GL_MODELVIEW ) self.has_setup = 1 def un_setup_draw_texture(self): """ resets the opengl state to what it was before drawing. """ if _debug__: printw( type(self.old_matrix_mode), self.old_matrix_mode) if self.old_matrix_mode: glMatrixMode( self.old_matrix_mode ) glDisable(GL_BLEND) glDisable(GL_TEXTURE_2D) if _debug__: printw( "un_setup_draw_texture1") glMatrixMode( GL_PROJECTION ) glLoadMatrixd(self.old_projection_matrix ) if _debug__: printw( "un_setup_draw_texture2") glMatrixMode( GL_MODELVIEW ) glLoadMatrixd( self.old_modelview_matrix ) self.has_setup = 0 def draw_gl(self, spr ): """ Assumes glMatrixMode( GL_MODELVIEW ) """ #glLoadIdentity() glBindTexture(GL_TEXTURE_2D, spr.tex) x = spr.rect[0] y = spr.rect[1] glTranslatef(x, y, 0) wv, hv = float(spr.rect.width)/float(spr.pow2_image_width), float(spr.rect.height)/float(spr.pow2_image_height) glBegin(GL_QUADS) glTexCoord2f(0.0, 0.0) glVertex2f(0.0, 0.0) glTexCoord2f(0.0, hv) glVertex2f(0, spr.rect.height) glTexCoord2f(wv, hv) glVertex2f(spr.rect.width, spr.rect.height) glTexCoord2f(wv, 0.0) glVertex2f(spr.rect.width, 0) glEnd() glTranslatef(-x, -y, 0) #(x, y), texid, (owidth, oheight), (width, height), #(xres, yres)): def set_up_2d_projection(self, a_rect): """ a_rect - the area to set up the projection for. """ if _debug__: printw( "set_up_2d_projection") glMatrixMode( GL_PROJECTION ) glLoadIdentity() gluOrtho2D( a_rect[0], a_rect.width, a_rect.height, a_rect[1]) def load_2d_projection(self): if _debug__: printw( "load_2d_projection") glMatrixMode( GL_PROJECTION ) glLoadMatrixd(self.projection_matrix_2d) def draw(self, surface ): """ supposed to draw to the given surface. Problem is it is an opengl screen. so we get the size of it, and draw to the screen. """ # TODO: OPTIMIZATION: order the sprites into ones which share the same textures. # TODO: OPTIMIZATION: make sure the texture is only loaded once for each image. if not hasattr(self, 'has_setup'): self.setup_draw_texture(surface.get_rect()) #damn, if not hasattr(self, 'has_setup') or not self.has_setup: # doesn't work. if not self.has_setup: self.setup_draw_texture(surface.get_rect()) glLoadIdentity() for spr,k in self.spritedict.items(): # see if the texture has been made for the things, if not # make them. if not hasattr(spr, 'image_string'): spr.LoadImage() if not hasattr(spr, 'tex'): spr.MakeTexture() if not hasattr(spr, 'old_rect'): spr.old_rect = pygame.Rect( spr.rect ) if not hasattr(spr, 'old_image_id'): spr.old_image_id = id( spr.image ) reload_the_texture = 0 # TODO: BUG: if the if spr.old_rect[2:] != spr.rect[2:] or spr.old_image_id != id( spr.image ): reload_the_texture = 1 if reload_the_texture: # TODO: FIXME: should probably check if the screen changes too. spr.DeleteTexture() spr.LoadImage() spr.MakeTexture() spr.old_rect = pygame.Rect( spr.rect ) spr.old_image_id = id( spr.image ) spr.pow2_image_width, spr.pow2_image_height = tuple(map( nextPower,(spr.rect.width, spr.rect.height) )) self.set_up_2d_projection(surface.get_rect()) glMatrixMode( GL_MODELVIEW ) self.draw_gl(spr) # this is here for compatibility with RenderUpdates return [] #self.un_setup_draw_texture() def MakeTextures(self): """ For all of the sprites in this group we will make textures for them. """ # TODO: make list of pack_textures.Textures for all the surfaces. # Figure out how big a texture we want to make. # Find the maximum texture size we can make. # find the smallest sized textures we can fit all the little # ones inside. # TODO: to draw we need to: # Bind the gl texture for each main texture. # Draw a bunch of quads using the x/y in the sub textures as # the uv coordinates. # def FitSpritesOnTextures(self): """ """ # get the max texture size. self.max_texture_size = (256, 256) class SpriteGL(pygame.sprite.Sprite): """ A sprite class which uses opengl. Should be able to use it in the place of the pygame sprite class. """ # a shared image cache. image_cache = {} max_image = 30 def update(self): pass def LoadImage(self): # The image should allready be loaded, and rect allready there. #self.image = pygame.image.load(filename) if _debug__: printw( "SpriteGL.LoadImage start") if not hasattr(self, 'rect'): self.rect = self.image.get_rect() # check if it is an alpha image. self.masks = self.image.get_masks() alpha_mask = self.masks[3] if _debug__: printw( self.masks, id(self)) #TODO: FIXME: better detection, and manipulation of different image # types. if _debug__: printw( "byte_size") printw( self.image.get_bytesize()) printw( self.masks) # DEPENDENCY - self.image # See if the image has changed. # If it has we need to update the texture. # # if self.image_cache.has_key((id(self.image),tuple(self.rect[2:])) ): if _debug__: printw( "SpriteGL.LoadImage: image_cache") self.image_string, rect, self.cache_tex = self.image_cache[(id(self.image),tuple(self.rect[2:]))] self.cache_hit = 1 elif not alpha_mask: if _debug__: printw( "SpriteGL.LoadImage: not alpha_mask") ##raise "ummmmm... not implemented, sorry" ##self.image_string = pygame.image.tostring(self.image, "RGB", 0) ##self.image_cache[(id(self.image),tuple(self.rect[2:]))] = [self.image_string, self.image.get_rect(), -1] ##self.cache_hit = 0 #TODO: OPTIMIZATION: need to have this handle non alpha images. # for now we convert it to an alpha one. #TODO: I don't think this works with 8 bit images. # need to test with different images. self.image = self.image.convert_alpha() if _debug__: printw( "self.image", self.image) self.masks = self.image.get_masks() alpha_mask = self.masks[3] if _debug__: if not alpha_mask: raise "problem here" self.image_string = pygame.image.tostring(self.image, "RGBA", 0) self.image_cache[(id(self.image),tuple(self.rect[2:]))] = [self.image_string, self.image.get_rect(), -1] self.cache_hit = 0 else: if _debug__: printw( "SpriteGL.LoadImage: else") self.image_string = pygame.image.tostring(self.image, "RGBA", 0) self.image_cache[(id(self.image),tuple(self.rect[2:]))] = [self.image_string, self.image.get_rect(), -1] self.cache_hit = 0 if hasattr(self, 'pow2_image_width') and hasattr(self, 'pow2_image_height'): self.old_pow2_image_width, self.old_pow2_image_height = self.pow2_image_width, self.pow2_image_height self.pow2_image_width, self.pow2_image_height = tuple(map(nextPower,self.image.get_size())) if self.old_pow2_image_width > self.pow2_image_width: self.pow2_image_width = self.old_pow2_image_width if self.old_pow2_image_height> self.pow2_image_height: self.pow2_image_height= self.old_pow2_image_height else: self.pow2_image_width, self.pow2_image_height = tuple(map(nextPower,self.image.get_size())) #TODO: make glTexImage2D version which can take surfaces directly. def DeleteTexture(self): if hasattr(self, 'tex'): if _debug__: printw( self.tex) glDeleteTextures([self.tex]) def load_del_make(self): """ """ def MakeTexture(self): #return if _debug__: printw( "SpriteGL.MakeTexture start") #if self.cache_tex != -1: # TODO: probably need to move texture making into the group. # need to keep a dict of cached textures. # delete those which are not needed etc. # For grouping textures, need to discover a list of texids, with images. # pass #self._debug("making texture") self.tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.tex) #glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) #scale linearly when image bigger than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) #scale linearly when image smalled than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) # 2d texture, level of detail 0 (normal), # 3 components (red, green, blue), # x size from image, # y size from image, # border 0 (normal), # rgb color data, # unsigned byte data, # and finally the data itself. #TODO: check to see what type of image was loaded, and make # and appropriate glTexImage2D call. #TODO: use the rect for the image size, width etc. #TODO: need to take power of 2 into account here. """ if _debug__: printw( self.rect.width) printw( self.rect.height) printw( self.image.get_width()) printw( self.image.get_height()) printw( len(self.image_string)) printw( type(self.image_string)) printw( GL_RGB) printw( GL_RGBA) """ self.pow2_image_width, self.pow2_image_height = tuple(map(nextPower,self.image.get_size())) if _debug__: printw( self.pow2_image_width, self.pow2_image_height) if not self.masks[3]: if _debug__: printw( "glTexImage2D RGB") glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.pow2_image_width, self.pow2_image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, None) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, self.rect.width, self.rect.height, GL_RGB, GL_UNSIGNED_BYTE, self.image_string) else: if _debug__: printw( "glTexImage2D RGBA") glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.pow2_image_width, self.pow2_image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, self.rect.width, self.rect.height, GL_RGBA, GL_UNSIGNED_BYTE, self.image_string) #glTexImage2D(GL_TEXTURE_2D, 0, 4, self.image_width, self.image_height, 0, # GL_RGBA, GL_UNSIGNED_BYTE, self.image_string) # GL_RGBA, GL_UNSIGNED_BYTE, self.image) """ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, owidth, oheight, GL_RGBA, GL_UNSIGNED_BYTE, imgstring) """ #self._debug("finished making texture") class ScreenGL: """ TODO: - Fill in missing functions. - Work correctly when screen size changes. - only update the texture when blitting. - An optimization might be to not update the texture until the screen has been flipped, or updated. - This could work quite nicely with RenderUpdates :) """ def __init__(self, screen): self.screen = screen self.screen_gl = SpriteGL() self.screen_gl.image = pygame.Surface(screen.get_size()) self.screen_gl.image.convert_alpha() self.screen_gl.rect = self.screen_gl.image.get_rect() self.screen_sprites= GroupGL((self.screen_gl)) #TODO: automatically add all the methods of surface # What's a nice way to do this in python? # def get_size(self, *args): return apply(self.screen_gl.image.get_size, args) def get_rect(self, *args): return apply(self.screen_gl.image.get_rect, args) def set_clip(self, *args): return apply(self.screen_gl.image.set_clip, args) def get_clip(self, *args): return apply(self.screen_gl.image.get_clip, args) def get_flags(self, *args): return apply(self.screen_gl.image.get_flags, args) def fill(self, *args): apply(self.screen_gl.image.fill, args) self.blit(None) def blit(self, *args): """ meant as a replacement for screen.blit You really should consider making your background a seperate Sprite, and Group. useage: gl_screen_blit """ ##print "blit" #print "args", args[0:1], args # blit to the internal software image here. if (None,) != args[0:1]: if hasattr(args[0], "realone"): new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) self.screen_gl.image.blit(*args) if _debug__: printw( "blitting to ScreenGL, with args :%s:" % (args,)) #screen_sprites.update() # write the internal image to disk. """ pygame.image.save(self.screen_gl.image, "/tmp/screen.tga") printw("sleeping for 2") time.sleep(20) printw("finished sleeping") """ self.screen_gl.DeleteTexture() self.screen_gl.LoadImage() self.screen_gl.MakeTexture() #self.screen_sprites.setup_draw_texture(self.screen_gl.image.get_rect()) self.screen_sprites.update() self.screen_sprites.draw(self.screen) ##print "done draw" #self.screen_sprites.un_setup_draw_texture() #screen_gl.DeleteTexture() def gl_display_get_surface(): return pygame.display.old_get_surface() def gl_display_set_mode(*args): # TODO: Add check to see if a GL screen is infact being requested. return ScreenGL( pygame.display.old_set_mode(args[0], OPENGL|DOUBLEBUF) ) #return ScreenGL( apply(pygame.display.old_set_mode, args) ) def gl_display_update(*args): pygame.display.flip() def gl_draw_line(*args): if hasattr(args[0], "realone"): args[0].is_dirty = 1 new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) return pygame.draw.old_line(*args) def gl_transform_scale(*args, **kwargs): print "len args", len(args) if hasattr(args[0], "realone"): new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) elif hasattr(args[0], "screen_gl"): new_args = list(args) new_args[0] = args[0].screen_gl.image args = tuple(new_args) #print kwargs, args if len(args) > 2: new_surface = pygame.transform.old_scale(*args[1:], **kwargs) else: new_surface = pygame.transform.old_scale(*args, **kwargs) return pygame.Surface(initialize_with_this = new_surface) #pygame.display.get_surface() and pygame.display.set_mode((height,width), OPENGL|DOUBLEBUF) new_rdpyg/build/lib/rdpyg/util/0000755000175100017510000000000010076400310016720 5ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/util/cyclic_list.py0000644000175100017510000000225510076400066021607 0ustar renerene00000000000000# file: cycling list. # purpose: a pointer to the current item is needed. # A goto_next method is needed. Which cycles over the next idx. import UserList class cyclic_list(UserList.UserList): def __init__(self, *args, **kwargs): UserList.UserList.__init__(self, *args, **kwargs) self.idx = 0 def next(self): """ increments the cursor, and returns the new current idx. """ self.idx += 1 if self.idx >= len(self.data): self.idx = 0 return self.idx def prev(self): """ decrements the cursor, and returns the new current idx. """ self.idx -= 1 if self.idx < 0: self.idx = len(self.data) -1 return self.idx def cur(self): """ returns the element at the current cursor. """ return self.data[self.idx] def set_cur(self, idx): """ Sets the current cursor to the given idx. """ self.idx = idx if __name__ == "__main__": c = cyclic_list([1,2,3,4]) print c.idx c.next() print c.idx c.next() print c.idx c.next() print c.idx c.next() print c.idx for x in range(5): c.prev() print c.idx new_rdpyg/build/lib/rdpyg/util/__init__.py0000644000175100017510000000000010065303761021031 0ustar renerene00000000000000new_rdpyg/build/lib/rdpyg/util/pack_textures.py0000644000175100017510000002074010071457647022202 0ustar renerene00000000000000""" TODO: need to return UV coordinates and pixel coordinates for the packing/cutting functions for where the images are located on the textures. Code to pack multiple textures into larger ones. As well as to cut up bigger textures into smaller ones. This is useful for eg opengl where there are textures size limits. Also it can speed up rendering as you need to do less texture binding calls, and you can reduce geometry calls too. Power of 2 textures can be a waste of memory if you have non power of 2 sized images. The more video memory saved the faster a game can go. To make this code more useful it will work with rectangles. So that it can be used to update texture memory as well as to update images. There will also need to be possibly multiple big output textures. So that you can specify a maximum size output texture. """ #import psyco #psyco.full() class Texture: """ One texture which holds multiple smaller ones packed in. x,y bottom left is 0,0. Which is like opengl, and not like sdl. """ def __init__(self, x,y, height,width): self.x = x self.y = y self.height = height self.width = width self.sub_textures= [] def __repr__(self): return "<%s,%s,%s,%s>" % (self.x, self.y, self.height, self.width) def try_fit(self, other_texture): """ Tries to fit the texture into itself. Returns true if successful. """ if not self.could_fit(other_texture): return False # an early in. if there are no other textures, then just put it in. if(self.sub_textures == []): self.sub_textures.append(other_texture) return True # Do a search for a place to put it. return self.search_for_fit(other_texture) def try_fit_batch(self, other_textures): """ Tries to fit the textures into itself. Returns true if successful???. Or returns the unfitted ones? """ # see if they are the same size. same_size = 0 o=other_textures[0] x,y,height,width = o.x, o.y, o.height, o.width r = filter(lambda oo:(oo.height == height and oo.width == width), other_textures) if len(r) == len(other_textures): same_size = 1 # If they are all the same size, and the texture is empty we # can optimize it. unfitted = [] if same_size and self.sub_textures == []: # See how many in a row we could fit along the x. # then raise along the y. number_on_x = int(round(self.width / width)) number_on_y = int(round(self.height / height)) x_pos = 0 y_pos = 0 for o in other_textures: if(y_pos > number_on_y): # not anymore room. unfitted.append(o) else: o.x = x_pos * width o.y = y_pos * height self.sub_textures.append(o) x_pos += 1 if(x_pos > number_on_x): y_pos += 1 x_pos = 0 else: # TODO: sort the textures into batches of the same size. # could be able to be fairly fast then. # try fitting them one at a time. for other_texture in other_textures: r = self.try_fit(other_texture) if not r: unfitted.append(other_texture) return unfitted def collide(self, other_texture): """ checks this texture only to see if it collides. Returns True if it does collide. """ sx = self.x sy = self.y ox = other_texture.x oy = other_texture.y s_right = sx + self.width s_top = sy + self.height o_right = ox + other_texture.width o_top = oy + other_texture.height # check that it is not within the x or y. if(ox >= s_right): return False if(o_right < sx): return False if(o_top <= sy): return False if(oy > s_top): return False return True def could_fit(self, other_texture): """ checks this texture only to see if it fits. Does not care about any textures inside. """ # some early outs. if(other_texture.height > self.height): return False if(other_texture.width > self.width): return False if(other_texture.x != 0 or other_texture.y != 0 or self.x != 0 or self.y != 0): # if the x,y is not zero then need to adjust for that. s_right = self.x + self.width s_top = self.y + self.height o_right = other_texture.x + other_texture.width o_top = other_texture.y + other_texture.height if(o_top > s_top or o_right > s_right or other_texture.x < self.x or other_texture.y < self.y): return False return True def search_for_fit(self, o): """ do a search for a place to put the texture, and place it. Return True if successful, else false. o - other texture. """ #TODO: try and optimize this. #return self._brute_force(o) return self._bottom_left_first(o) def _brute_force(self, o): """ do a brute force search from bottom left to top right. Return True if successful, else false. o - other texture. """ x_try = self.x y_try = self.y x_end = self.x + self.width y_end = self.y + self.height # go from x_try -> x_end seeing if it fits, # then increment y_try and go again. hits = 0 for y in range(y_try, y_end): for x in range(x_try, x_end): o.x = x o.y = y hits = 0 for sub in self.sub_textures: # if we can fit inside a sub texture, # then we need to keep looking. if sub.collide(o): hits = 1 break if not hits: break if not hits: break if not hits: self.sub_textures.append(o) return True else: return False def _bottom_left_first(self, o): """ do a search from bottom left. Return True if successful, else false. o - other texture. """ x_try = self.x y_try = self.y x_end = self.x + self.width y_end = self.y + self.height # go from x_try -> x_end seeing if it fits, # then increment y_try and go again. hits = 0 for y in range(y_try, y_end): x = x_try while x < x_end: #for x in range(x_try, x_end): o.x = x o.y = y hits = 0 for sub in self.sub_textures: # if we can fit inside a sub texture, # then we need to keep looking. if sub.collide(o): hits = 1 # move accross to the x of the sub. x = sub.x + sub.width break if not hits: break x += 1 if not hits: break if not hits: self.sub_textures.append(o) return True else: return False def clear(self): """ clears all the textures in this one. """ self.sub_textures= [] def pack_images_into_multiple(small_list, max_size, use_pow2 = 1): """ returns a list of Texture objects with the textures from the small_list packed into them. small_list - list of Texture objects max_size - of the output Textures. use_pow2 - if 0 then we do not have to limit ourselves to power of 2. """ raise NotImplementedError def split_big_image(big_image, max_size, use_pow2 = 1): """ returns a list of Textures which the big_image is split into. big_image - a Texture object. TODO: how to determine where the small bits are placed? """ raise NotImplementedError new_rdpyg/build/lib/rdpyg/util/paths.py0000644000175100017510000003224210065305521020422 0ustar renerene00000000000000#file: paths.py #purpose: for 3d objects to follow paths. # NOTE: follows the opengl coordinate system. # distance units are in meters # time units are in seconds. import math # these are the types of loop the path can follow. LOOP_TYPES = ["stop", "loop", "backwards"] class Path: """ Used for storing the path from one point to another. For working out where an object following that path at a certain speed would be. p = Path() p.SetPoints([[0., 0., 0.], [0., 1., 0.], [1., 1., 0.], [2., 2., 0.], [3., 3., 0.]]) This creates a path of straight lines. Now whatever is traveling along the path can use: point_along_path = p.Travel(speed=0.5, elapsed_time=5) Which will travel along the path 0.5 * 5 units, and give you the point where it is up to. """ def __init__(self, points = [], loop_type = "stop"): """ points - defaults to []. should be like [[0.,0.,0.],[0.,1.,0.]] """ self.elapsed_time = 0. self.SetPoints(points) self.SetLoopType(loop_type) def SetLoopType(self, loop_type): """ SetLoopType("stop") -> None Can be set to one of LOOP_TYPES, ["stop", "loop", "backwards"] """ if loop_type in LOOP_TYPES: self.loop_type = loop_type else: raise NotImplementedError, loop_type def length(self): """ length() -> length of the path. TODO: why isn't this __len__() ? """ return length_line(self.points) def SetPoints(self, point_list): """ SetPoints(point_list) -> None Sets the points along the path. point_list - eg [[1., 1., 1.], [2., 2., 2.]] With each sublist being a point (x,y,z) in 3d space. """ #TODO: should we make the points a tuple? # this would allow the path to be used as a hash value. if len(point_list) == 0: point_list = [[0.,0.,0.], [0.,0.,0.]] if len(point_list) == 1: point_list = [point_list[0], point_list[0]] self.points = point_list if len(self.points) > 1: # we start at the beginning. self.current_point = self.points[0] # Where we are going to. self.current_heading_to_idx = 1 self.current_idx = 0 def SetNewPoint(self, point): """ SetNewPoint([x,y,z]) -> None Sets the current point that the traveller is on. """ self.current_point = point def GotoNextLine(self): """ GotoNextLine() -> None Starts heading to the next line in path. """ # what happens if we get to the end? self.current_heading_to_idx += 1 self.current_idx = self.current_heading_to_idx - 1 if len(self.points) == self.current_heading_to_idx: if self.loop_type == "stop": pass elif self.loop_type == "loop": self.current_heading_to_idx = 0 elif self.loop_type == "backwards": self.points.reverse() self.current_heading_to_idx = 1 self.current_idx = 0 def ShouldStop(self): """ ShouldStop() -> Bool Are we at the end and is the loop_type "stop" """ if self.loop_type == "stop": if self.current_idx >= len(self.points) -1: return 1 else: return 0 else: return 0 def Where(self): """ Where() -> position. Returns the current position of the traveler. """ return self.current_point[:] def GetHeadingToPoint(self): """ GetHeadingToPoint() -> position Returns the point which the traveler is heading to. """ return self.points[self.current_heading_to_idx] def __str__(self): return str(self.points) def __eq__(self, other): #print self.points == other.points #print self.elapsed_time == other.elapsed_time #print self.loop_type == other.loop_type #print self.current_point == other.current_point #print self.current_heading_to_idx == other.current_heading_to_idx #print self.current_idx == other.current_idx if not other.__class__ == self.__class__: return 0 if ((self.points == other.points) and (self.elapsed_time == other.elapsed_time) and (self.loop_type == other.loop_type) and (self.current_point == other.current_point) and (self.current_heading_to_idx == other.current_heading_to_idx) and (self.current_idx == other.current_idx)): return 1 else: return 0 def __ne__(self, other): return not self.__eq__(other) def GetBackwardsPoint(self, distance): """ GetBackwardsPoint(distance) -> position Returns a point backwards from the current direction along the path. distance - backwards along the path. """ #FIXME: I think this may be broken for the case where the traveler # is not moving. cur_point = self.Where() if self.ShouldStop(): #print self.current_heading_to_idx, "current_heading_to_idx" next_point = cur_point cur_point= self.points[0] else: next_point = self.points[self.current_heading_to_idx] backwards_point = backwards(cur_point, next_point, distance) return backwards_point def Travel(self, speed, elapsed_time): """ Travel(float, float) -> position Returns the point along the path that the traveler is at. speed - units per second. Average since the last call to this. elapsed_time - since the last call to this. """ if self.ShouldStop(): return self.Where() end_point = self.points[self.current_heading_to_idx] start_point = self.Where() time_left, new_point = travel_line(start_point, end_point, speed, elapsed_time) self.SetNewPoint(new_point) # to prevent an infinite loop incase this code is buggy. MAXIMUM_ITERATIONS = 100 c = 0 while not within(time_left, 0.0, 0.00001): # there is some time left. elapsed_time = time_left self.GotoNextLine() if self.ShouldStop(): break start_point = self.Where() end_point = self.points[self.current_heading_to_idx] time_left, new_point = travel_line(start_point, end_point, speed, elapsed_time) self.SetNewPoint(new_point) c += 1 # a sanity check to avoid maybe possible infinite loops. if c >= MAXIMUM_ITERATIONS: raise RuntimeError("too many iterations trying to find new place on path") return new_point # Some support for paths which can be copied with twisted. # TODO: remove this?? try: import config if config.USE_TWISTED: from twisted.spread import pb class CopyPath(Path, pb.Copyable, pb.RemoteCopy): pass pb.setUnjellyableForClass('paths.CopyPath', CopyPath) except: pass # Some helper functions. def within(a,b, error_range): """ within(num, num, num) -> bool check if a is with error_range of b. """ return abs(a - b) < error_range def travel_line(start_point, end_point, speed, elapsed_time): """ travel_lines(point, point, num, num) -> (time_left, new_point) Travels along the line given at a given speed, for a given time. """ distance = speed * elapsed_time distance_to_end = distance_between_points(start_point, end_point) reached_end = 0 if within(distance, distance_to_end, 0.00000001): # right on the end. return (0.0, end_point) elif within(distance_to_end, 0.0, 0.00000001): return (elapsed_time, end_point) elif distance > distance_to_end: reached_end = 1 if reached_end: # we have reached the end, so we figure out how much time we have left. # The new_point is the end_point ##t=elapsed_time-(elapsed_time-((distance - distance_to_end) / speed)) #time_left = elapsed_time - (elapsed_time / distance) t = elapsed_time-(elapsed_time-((distance - distance_to_end) / speed)) time_left = t return (time_left, end_point) else: # need to figure out where we are on the line between start and end. ratio = distance / distance_to_end if within(ratio, 1.0, 0.00000001): return (0.0, end_point) else: time_left = 0.0 new_point = interpolate_line(start_point, end_point, ratio) return (time_left, new_point) def interpolate_line(start_point, end_point, t): """ interpolate_line(point, point, num) -> point returns the new point along the line given. start_point - of the line. end_point - of the line. t - ratio between 0. - 1. along the line. """ # numeric: # (e - s) * t # other formula. probably faster if I make a line class, # or cache results in some other way. # # sx,sy = start # ex,ey = end # stepx = (ex-sx) / total_length # stepy = (ey-sy) / total_length # midx = sx + stepx * length # midy = sy + stepy * length # # another formular: # # (1 - t)*s + t * e #assert( t <= 1.0 ) if len(start_point) == 3: one_minus_t = 1 -t x = (start_point[0] * one_minus_t) + (end_point[0] * t) y = (start_point[1] * one_minus_t) + (end_point[1] * t) z = (start_point[2] * one_minus_t) + (end_point[2] * t) return [x,y,z] elif len(start_point) == 2: one_minus_t = 1 -t x = (start_point[0] * one_minus_t) + (end_point[0] * t) y = (start_point[1] * one_minus_t) + (end_point[1] * t) return [x,y] else: raise NotImplementedError def length_line(points): """ length([point]) -> num returns the length of the line represented by the points. """ len_points = len(points) if len_points < 1: return 0. elif len_points == 2: return distance_between_points(points[0], points[1]) else: total_length = 0 last_point = points[0] # go through all but the first point. for point in points[1:]: total_length += distance_between_points(last_point, point) last_point = point return total_length def distance_between_points(p1, p2): """ distance_between_points(point, point) -> num Returns the distance between two points. """ if len(p1) == 3: return math.sqrt( (p1[0] - p2[0])**2 + (p1[1] - p2[1])**2 + (p1[2] - p2[2])**2 ) elif len(p1) == 2: return math.sqrt( (p1[0] - p2[0])**2 + (p1[1] - p2[1])**2 ) else: raise NotImplementedError def backwards(cur_point, next_point, distance): """ backwards(point, point, num) -> point Returns the point backwards along the given line. """ # Find the distance between the current and next point. distance_to_next = distance_between_points(cur_point, next_point) # normalise that value to 1.0 normalised_distance = 1. / distance_to_next # multiply the distance wanted to travel by the normalised value. interpolated_num = distance * normalised_distance backwards_point = interpolate_line(cur_point, next_point, -interpolated_num) return backwards_point def forwards(cur_point, next_point, distance): """ forwards(point, point, num) -> point Returns the point forwards the distance along the given line. From the current point! """ # Find the distance between the current and next point. distance_to_next = distance_between_points(cur_point, next_point) # normalise that value to 1.0 normalised_distance = 1. / distance_to_next # multiply the distance wanted to travel by the normalised value. interpolated_num = distance * normalised_distance forwards_point = interpolate_line(cur_point, next_point, interpolated_num) return forwards_point def forwards_from_next(cur_point, next_point, distance): """ forwards(point, point, num) -> point Returns the point forwards the distance along the given line. From the next point! """ forwards_point = interpolate_line(cur_point, next_point, 1.2) cur_point = next_point next_point = forwards_point # Find the distance between the current and next point. distance_to_next = distance_between_points(cur_point, next_point) # normalise that value to 1.0 normalised_distance = 1. / distance_to_next # multiply the distance wanted to travel by the normalised value. interpolated_num = distance * normalised_distance forwards_point = interpolate_line(cur_point, next_point, interpolated_num) return forwards_point def point_within(point, a_rect): """ point_within([x,y], rectstyle) -> true if a point is within the rect. """ x,y,w,h = a_rect px, py = point[:2] if px < x: return 0 if px > x + w: return 0 if py < y: return 0 if py > y + h: return 0 return 1 new_rdpyg/build/lib/rdpyg/util/quaternion.py0000644000175100017510000002671310065303034021473 0ustar renerene00000000000000"""Simple module providing a quaternion class for manipulating rotations easily. NOTE: unittest in quaternion_test.py NOTE: a lot of this code is taken from various places, including OpenglContext. Note: all angles are assumed to be specified in radians. Note: this is an entirely separate implementation from the PyOpenGL quaternion class. This implementation assumes that Numeric python will be available, and provides only those methods and helpers commonly needed for manipulating rotations. TODO: Make all functions use an array instead of a quat class. Make a quat class which uses the functions. Make a c version of for the python functions. - based off amd lib, gamasutra article, and CS quats. """ import Numeric, Matrix import math N = Numeric # some common math ones. pi = math.pi cos = math.cos acos = math.acos sin= math.sin atan= math.atan sqrt= math.sqrt def magnitude_vectors( vectors ): """Calculate the magnitudes of the given vectors vectors -- sequence object with 1 or more 3-item vector values. returns a double array with x elements, where x is the number of 3-element vectors """ vectors = N.asarray( vectors,'d', savespace = 1) vectors = N.reshape( vectors, (-1,3)) vectors = vectors*vectors result = vectors[:,0] N.add( result, vectors[:,1], result ) N.add( result, vectors[:,2], result ) N.sqrt( result, result ) return result def normalise_vectors( vectors ): """Get normalised versions of the vectors. vectors -- sequence object with 1 or more 3-item vector values. returns a double array with x 3-element vectors, where x is the number of 3-element vectors in "vectors" Will raise ZeroDivisionError if there are 0-magnitude vectors in the set. """ vectors = N.asarray( vectors, 'd', savespace = 1) vectors = N.reshape( vectors, (-1,3)) mags = N.reshape( magnitude_vectors( vectors ), (-1, 1)) return N.divide_safe( vectors, mags) def normalise_vector( vector ): """Given a 3 or 4-item vector, return a 3-item unit vector""" """ x,y,z = vector sqlen = x * x + y * y + z * z if (sqlen < SMALL_EPSILON): return vector invlen = sqrt (sqlen) return vector * invlen """ return normalise_vectors( vector[:3] )[0] def length_quat(quat): """ """ #w,x,y,z = quat.internal #length = x**2 + y**2 + z**2 + w**2 #return length return N.sum(quat.internal ** 2) def slerp_quat(quat_a, quat_b, slerp): """ Returns a quaternion spherically interpolated between quat_a, quat_b. quat_a, quat_b - quaternions to interpolate between. slerp - interp factor (0.0 = quat_a, 1.0 = quat_b) """ # TODO: FIXME: This is wrong! #raise NotImplementedError("broken implementation") # Difference at which to lerp instead of slerp DELTA = 0.0001 HALF_PI = math.pi /2 # DOT the quats to get the cosine of the angle between them cosom = N.sum(quat_a.internal * quat_b.internal) result = [0., 0., 0.,0.] # Two special cases: # Quats are exactly opposite, within DELTA? if (cosom > DELTA - 1.0): # make sure they are different enough to avoid a divide by 0 if (cosom < 1.0 - DELTA): # SLERP away omega = math.acos(cosom); isinom = 1.0 / math.sin(omega); scale0 = math.sin( (1.0 - slerp)*omega ) * isinom; scale1 = math.sin(slerp * omega) * isinom; else: # LERP is good enough at this distance scale0 = 1.0 - slerp; scale1 = slerp; result[0] = scale0 * quat_a.internal[0] + scale1 * quat_b.internal[0]; result[1] = scale0 * quat_a.internal[1] + scale1 * quat_b.internal[1]; result[2] = scale0 * quat_a.internal[2] + scale1 * quat_b.internal[2]; result[3] = scale0 * quat_a.internal[3] + scale1 * quat_b.internal[3]; else: # SLERP towards a perpendicular quat # Set slerp parameters #scale0 = math.sin ((1.0 - slerp) * HALF_PI); #scale1 = math.sin (slerp * HALF_PI); #q2w, q2x, q2y, q2z = quat_b.internal * N.array([-0.5,0.5,-0.5,0.5]) #result[0] = -quat_b.internal[1]; #result[1] = quat_b.internal[0]; #result[2] = -quat_b.internal[3]; #result[3] = quat_b.internal[2]; scale0 = sin((1.0 - slerp) * HALF_PI); scale1 = sin(slerp * HALF_PI); result[0] = scale0 * quat_a.internal[0] + scale1 * quat_b.internal[0]; result[1] = scale0 * quat_a.internal[1] + scale1 * quat_b.internal[1]; result[2] = scale0 * quat_a.internal[2] + scale1 * quat_b.internal[2]; result[3] = scale0 * quat_a.internal[3] + scale1 * quat_b.internal[3]; # Compute the result return Quaternion( result ) def get_angles_from_two_points(a,b): """ returns the angles along the x,y,z axis. this is direction of the two points. """ p1,p2 = N.array(a), N.array(b) origin = N.array([0.,0.,0.]) p2 = (origin - p1) + p2 p1 = origin v = N.absolute(p2 - p1) x,y,z = p2 if x >=0 and y >= 0: to_add = -180 elif x >= 0 and y < 0: to_add = 0 elif x < 0 and y >= 0: to_add = 180 elif x < 0 and y < 0: to_add = -360 else: # shouldn't get here. raise ValueError("shouldn't get here x:%s: y :%s: " % (x,y) ) #v = p2 - p1 # atan(Vy/Vx) if v[0] == 0: x_angle = 0. else: x_angle = atan(v[1] / v[0]) # atan(Vx/Vz) if v[1] == 0: y_angle = 0. else: y_angle = atan(v[0] / v[1]) # atan(Vy/Vx) if v[2] == 0: z_angle = 0. else: z_angle = atan(v[0] / v[2]) angles = map(radians_to_angle, (x_angle, y_angle, z_angle) ) new_angles = map(lambda x, y=to_add: x + y, angles) return map(abs, new_angles) #return (x_angle, y_angle, z_angle) def euler_to_quats(rotations): """ Returns a sequence of quats. It is an array where each quat is four floats. w,x,y,z is the order. rotations- an array of rotations. where each rotation is three floats. """ tmp = map(from_euler_list, rotations) return map(lambda x:x.internal, tmp) def fromMatrix(matrix): """ from a 4x4 matrix return a quaternion. These are the orders of the matrix: [00,01,02,03] [10,11,12,13] [20,21,22,23] [30,31,32,33] [0 , 1, 2, 3] [4 , 5, 6, 7] [8 , 9,10,11] [12,13,14,15] Which is the opengl order. """ m = matrix trace = matrix[0][0]+matrix[1][1]+matrix[2][2] s = sqrt (trace + 1.0); quat_s = (s * 0.5); s = 0.5 / s; q = Quaternion( [quat_s, (m[1][2]-m[2][1])*s, (m[2][0]-m[0][2])*s, (m[0][1]-m[1][0])*s ] ) return q def angle_to_radians(angle): pi_div_180 = pi / 180. return pi_div_180 * (angle % 360.) def radians_to_angle(radians): if radians == 0: return 0. return (180. / (pi / radians)) % 360. def fromAXYZ(a,x,y,z): return fromXYZR(x,y,z,angle_to_radians(a)) def fromXYZR( x,y,z, r ): """Create a new quaternion from a VRML-style rotation x,y,z are the axis of rotation r is the rotation in radians.""" x,y,z = normalise_vector( (x,y,z) ) return Quaternion ( N.array( [ cos(r/2.0), x*(sin(r/2.0)), y*(sin(r/2.0)), z*(sin(r/2.0)), ]) ) def from_euler_list( l ): return apply(fromEuler, l) def fromEuler_angle(x=0, y=0, z=0): """ From x,y,z angles in degrees create a quat. """ radians = map(angle_to_radians, (x,y,z)) return fromEuler(*radians) def fromEuler( x=0,y=0,z=0 ): """Create a new quaternion from a 3-element euler-angle rotation about x, then y, then z """ if x: base = fromXYZR( 1,0,0,x) if y: base = base * fromXYZR( 0,1,0,y) if z: base = base * fromXYZR( 0,0,1,z) return base elif y: base = fromXYZR( 0,1,0,y) if z: base = base * fromXYZR( 0,0,1,z) return base else: return fromXYZR( 0,0,1,z) class Quaternion: """Quaternion object implementing those methods required to be useful for OpenGL rendering (and not many others)""" def __init__ (self, elements = [1,0,0,0] ): """The initializer is a four-element array, w, x,y,z -- all elements should be doubles/floats the default values are those for a unit multiplication quaternion. """ elements = N.asarray( elements, 'd') length = sqrt( N.sum( elements * elements)) if length != 1: # print 'fixing quaternion length', repr(length) elements = elements/length self.internal = elements self.cache = {} def __mul__( self, other ): """Multiply this quaternion by another quaternion, generating a new quaternion which is the combination of the rotations represented by the two source quaternions. Other is interpreted as taking place within the coordinate space defined by this quaternion. Alternately, if "other" is a matrix, return the dot-product of that matrix with our matrix (i.e. rotate the coordinate) """ if hasattr( other, 'internal' ): w1,x1,y1,z1 = self.internal w2,x2,y2,z2 = other.internal w = w1*w2 - x1*x2 - y1*y2 - z1*z2 x = w1*x2 + x1*w2 + y1*z2 - z1*y2 y = w1*y2 + y1*w2 + z1*x2 - x1*z2 z = w1*z2 + z1*w2 + x1*y2 - y1*x2 return Quaternion( N.array([w,x,y,z],'d')) else: return N.dot( self.matrix (), other ) def AXYZ(self): """ returns the angle, and x,y,z as a vector. as used by glRotate. """ x,y,z,r = self.XYZR() return [radians_to_angle(r), x,y,z] def XYZR( self ): """Get a VRML-style axis plus rotation form of the rotation. Note that this is in radians, not degrees, and that the angle is the last, not the first item... (x,y,z,radians) """ w,x,y,z = self.internal try: aw = acos(w) except ValueError: # catches errors where w == 1.00000000002 aw = 0 scale = sin(aw) if not scale: return (0,1,0,0) return (x / scale, y / scale, z / scale, 2 * aw ) def matrix( self ): """Get a rotation matrix representing this rotation""" # TODO: should cache this. w,x,y,z = self.internal return Numeric.array([ [ 1-2*y*y-2*z*z, 2*x*y+2*w*z, 2*x*z-2*w*y, 0], [ 2*x*y-2*w*z, 1-2*x*x-2*z*z, 2*y*z+2*w*x, 0], [ 2*x*z+2*w*y, 2*y*z-2*w*x, 1-2*x*x-2*y*y, 0], [ 0,0,0,1], ]) def __getitem__( self, x ): return self.internal[x] def __len__( self ): return len( self.internal) def __repr__( self ): """Return a human-friendly representation of the quaternion Currently this representation is as an axis plus rotation (in radians) """ return """<%s XYZR=%s>"""%( self.__class__.__name__, list(self.XYZR())) def delta( self, other ): """Return the angle in radians between this quaternion and another. Return value is a positive angle in the range 0-pi representing the minimum angle between the two quaternion rotations. From code by Halldor Fannar on the 3D game development algos list """ #first get the dot-product of the two vectors cosValue = N.sum(self.internal + other.internal) # now get the positive angle in range 0-pi return acos( cosValue ) def __neg__(self): #return Quaternion(-self.a, -self.b, -self.c, -self.d) return Quaternion(-self.internal) #try: # import config # # if config.USE_TWISTED: # from twisted.spread import pb # # class CopyQuaternion(Quaternion, pb.Copyable, pb.RemoteCopy): # pass # # pb.setUnjellyableForClass('quaternion.CopyQuaternion', CopyQuaternion) #except: # pass #D3DRMQUATERNION is four floats x, y, z, s if __name__== "__main__": pass new_rdpyg/build/lib/rdpyg/util/vtimer.py0000644000175100017510000000711107774203450020621 0ustar renerene00000000000000# file: virtual_timer.py # purpose: to be able to do things once a time is up. # or to keep track of something which lasts a given time. class vtimer: """ times something. when it is done it is equal to 1, else equal to 0. Useage: v = VirtTimer(5.) if v: dosomething() v.Update(elapsed_time) OR with a callback. v = VirtTimer(5., dosomething) v.Update(elapsed_time) Call Update on each game tick. Passing in elapsed time in seconds allows you to have timers running on different time. So pausing, and things like bullet time are easy. Also has some other features. You can be notified on the "edge" of time. That is when a timer is just_started or just_finished. if v.just_finished: do_some_other_thing() You can find how much time is left. As well as get a normalised amount of time left(between 0. and 1.). eg. time_before_powerup_runs_out = powerup_timer.left() """ def __init__(self, length, callback = None): """ length - of time to run for. callback - optional callback function to call. """ self.length = length self.callback = callback self.reset() self.update = self.Update self.is_not_used = 0 def Update(self, elapsed_time): """Update(1.0) -> None To be called on every game tic. elapsed_time - since last update. """ if self.just_started: self.just_started = 0 if self.just_finished: self.just_finished = 0 self.total_elapsed_time += elapsed_time if self.total_elapsed_time >= self.length: if self.done == 0: self.just_finished = 1 self.done = 1 if self.callback != None: if not self.called_callback: self.callback() self.called_callback = 1 def reset(self): """ reset() -> None Resets the timer to the beginning. """ self.total_elapsed_time = 0. self.done = 0 self.called_callback = 0 self.just_started = 1 self.just_finished = 0 self.is_not_used = 0 def set_finished_no_callback(self): """ set_finished_no_callback() -> None Sets it to finished, without calling callback. not just finished. """ self.total_elapsed_time = 10000000000000L self.done = 1 self.called_callback = 1 self.just_started = 0 self.just_finished = 0 self.is_not_used = 1 def not_used(self): """ not_used -> None For if the timer is not being used. This is useful for one time, timers. """ self.is_not_used = 1 # equality methods used for testing the timer. def __eq__(self, other): return self.done == other def __ne__(self, other): return not self.__eq__(other) def __nonzero__(self): return self.done def left(self): """ left() -> time left until finished. """ left = self.length - self.total_elapsed_time if left < 0.: return 0. else: return left def left_normalised(self): """ left_normalised() -> the time left normalized to 0. - 1. """ left = self.left() if left == 0.: return 0. else: return (1. / self.length) * left new_rdpyg/build/lib/rdpyg/__init__.py0000644000175100017510000000000010065303761020054 0ustar renerene00000000000000new_rdpyg/build/lib/urdpyg/0000755000175100017510000000000010076374355016153 5ustar renerene00000000000000new_rdpyg/build/lib/urdpyg/converters/0000755000175100017510000000000010076374157020345 5ustar renerene00000000000000new_rdpyg/build/lib/urdpyg/converters/cal3d_exporter.py0000644000175100017510000001236507743744517023654 0ustar renerene00000000000000 from math import cos, sin import os, sys, time import quaternion import py3d.milk_skeleton def strl(a_list): """ makes each element in a list a string. """ return map(str, a_list) def ms3d_euler__to__cal3d_quat(x,y,z): """ returns a quat suitable for cal3d ie a list [x,y,z,w]. """ r_quaternion = [0,0,0,0] cosx = cos(x * 0.5) cosy = cos(y * 0.5) cosz = cos(z * 0.5) sinx = sin(x * 0.5) siny = sin(y * 0.5) sinz = sin(z * 0.5) cosc = cosx * cosz; coss = cosx * sinz; sinc = sinx * cosz; sins = sinx * sinz; r_quaternion[0] = (cosy * sinc) - (siny * coss) r_quaternion[1] = (cosy * sins) + (siny * cosc) r_quaternion[2] = (cosy * coss) - (siny * sinc) # why do we have to negate this??? # hmmm ... "milkshape style"... well it works this way =) r_quaternion[3] = -((cosy * cosc) + (siny * sins)) return r_quaternion def test_some_shit(): a_milk_rotation = [-0.00014899999999999999, -0.046429999999999999, -0.017059000000000001] q = ms3d_euler__to__cal3d_quat(*a_milk_rotation) print "w,x,y,z",q q2 = quaternion.fromEuler(*a_milk_rotation) print "x,y,z,w", q2.internal milk_as_angles = map(quaternion.radians_to_angle, a_milk_rotation) q3 = ms3d_euler__to__cal3d_quat(*milk_as_angles) print "x,y,z,w",q3 q_forquat = [q[1], q[2], q[3], q[0]] q3_forquat = [q3[1], q3[2], q3[3], q3[0]] q4 = quaternion.Quaternion(q_forquat) q5 = quaternion.Quaternion(q3_forquat) print q4.internal print "q2", q2.AXYZ() print "q4", q4.AXYZ() print "q5", q5.AXYZ() # Conclusion. What the fuck!?!?? weirdro quaternions. # Going to need to test somewhat. class Cal3dBone: """ a class representing a cal3d bone. """ def __init__(self): """ """ self.bone_id = 0 self.name = "initial_bone_name" self.translation = [-14440., -14440., -14440.] # rotation is a quaternion. self.rotation = [-24440., -24440.,-24440., -24441.] self.local_translation = [-34440., -34440., -34440.] # local rotation is a quaternion. self.local_rotation = [-44440., -44440.,-44440., -44441.] # an index into which bone is the parent. # -1 means there is no parent to this self.parent_id = -54441 # a list of child ids for this bone. They are ints. self.child_ids = [] def to_xml(self, indentation=4): """ returns a string of xml representing this bone. """ indent_text = indentation * " " start_bone = """"""%(self.bone_id, self.name, len(self.child_ids)) start_bone = indent_text + start_bone trans = "%s" % (" ".join( strl(self.translation) )) rot = "%s" % (" ".join( strl(self.rotation) )) local_trans = "%s" % (" ".join( strl(self.local_translation) )) local_rot = "%s" % (" ".join( strl(self.local_rotation) )) parent_id = "%s" % (self.parent_id) child_ids = map(lambda x:"%s" %x, self.child_ids) bits = [trans, rot, local_trans, local_rot, parent_id] bits.extend(child_ids) print bits bits_text = "\n".join(map(lambda x: indent_text*2 + x, bits)) end_bone = indent_text + "" return "\n".join([start_bone, bits_text, end_bone]) class Cal3dSkeleton: def __init__(self): self.bones = [] def to_xml(self, indentation=0): """ returns a string with the xml for the cal3d skeleton. """ indent = indentation * " " start_skeleton = indent + """""" % len(self.bones) bones = "\n".join( map(lambda x: x.to_xml(), self.bones) ) end_skeleton = indent + "" return "\n".join([start_skeleton, bones, end_skeleton]) def read_milk( file_name ): import ms3d_ascii_importer data = ms3d_ascii_importer.convert_milkshape( file_name ) #print dir(data['bones'][0]) cal3d_skeleton = Cal3dSkeleton() bone_heirarchy = py3d.milk_skeleton.BoneHeirarchy(data['bones']) for milk_bone in data['bones']: cb = Cal3dBone() cb.name = milk_bone.name cb.bone_id = bone_heirarchy.bone_name_to_idx[milk_bone.name] cb.child_ids = bone_heirarchy.GetChildren_idx(milk_bone.name) if not bone_heirarchy.bone_name_to_idx.has_key( milk_bone.parent_name ): print "milk_bone.parent_name :%s:" % milk_bone.parent_name if milk_bone.parent_name == "": # has no parent. cb.parent_id = -1 else: cb.parent_id = bone_heirarchy.bone_name_to_idx[milk_bone.parent_name] cal3d_skeleton.bones.append(cb) print cal3d_skeleton.to_xml() if __name__ == "__main__": read_milk(sys.argv[1]) #test_some_shit() new_rdpyg/build/lib/urdpyg/converters/__init__.py0000644000175100017510000000000007743744517022454 0ustar renerene00000000000000new_rdpyg/build/lib/urdpyg/converters/ms3d_ascii_exporter.py0000644000175100017510000000214207743744517024674 0ustar renerene00000000000000from middle_obj import * #from features import import string from string import split from string import join import re from monkey import * """ Milkshape 3d ascii format notes: Basic outline of format: --- Start of file --- Frames: Frame: Meshes: Materials: Bones: --- End of file --- A material index of -1 means no material. """ def export_milk( points, indices, normals, out_file ): """ """ fw = out_file.write fw("// MilkShape 3D ASCII\n\n") fw("Frames: 30\n") fw("Frame: 1\n\n") fw("Meshes: 1\n") fw('"Bla" 0 -1\n') # num verts fw("%s\n" % len(points) ) for p in points: fw("0 %s %s %s 1.0 1.0 0\n" % (p[0], p[1], p[2]) ) # num normals fw("%s\n" % len(normals) ) for n in normals: fw("%s %s %s\n" % (n[0], n[1], n[2]) ) # num faces fw("%s\n" % len(indices) ) for i in indices: fw("0 %s %s %s 0 0 0\n" % (i[0], i[1], i[2]) ) fw("\nMaterials: 0\n\nBones: 0\n") f = open("bla2", "w") export_milk( points, indices, normals, f ) f.close() new_rdpyg/build/lib/urdpyg/converters/md2_importer.py0000644000175100017510000002556007743744517023342 0ustar renerene00000000000000""" Copyright (C) 2002, 2003 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ """ For reading md2 files. A description of the MD2 file format can be found here: http://www.ugrad.cs.jhu.edu/~dansch/md2/ """ import array import struct import Numeric N = Numeric # some maximums for the md2 format. MD2_MAX_TRIANGLES = 4096 MD2_MAX_VERTICES = 2048 MD2_MAX_TEXCOORDS = 2048 MD2_MAX_FRAMES = 512 MD2_MAX_SKINS = 32 MD2_MAX_FRAMESIZE = (MD2_MAX_VERTICES * 4 + 128) tMd2Header = { "magic":0, # Used to identify the file. "version":0, # Version number of the file (Must be 8). "skinWidth":0, # Skin width in pixels. "skinHeight":0, # Skin height in pixels. "frameSize":0, # Size in bytes the frames are. "numSkins":0, # Number of skins associated with the model. "numVertices":0, # Number of vertices (constant for each frame). "numTexCoords":0, # Number of texture coordinates. "numTriangles":0, # Number of faces (polygons). "numGlCommands":0, # Number of gl commands. "numFrames":0, # Number of animation frames. "offsetSkins":0, # Offset in the file for the skin data. "offsetTexCoords":0, # Offset in the file for the texture data. "offsetTriangles":0, # Offset in the file for the face data. "offsetFrames":0, # Offset in the file for the frames data. "offsetGlCommands":0, # Offset in the file for the gl commands data. "offsetEnd":0} # End of the file offset. def from_c_string(c_string): """ Returns a python string from a c string. Ie it looks for a null character in the string and returns everything before that. """ to_return = [] for x in c_string: if ord(x) == 0: return "".join(to_return) else: to_return.append(x) return "".join(to_return) class Md2Model: def __init__(self, md2_file_name = None, md2_texture_file_name = None): """ """ if md2_file_name == None and md2_texture_file_name == None: # Don't open anything! pass else: # open the file name given. self.f = open(md2_file_name) self.md2_file_name = md2_file_name self.md2_texture_file_name = md2_texture_file_name self.image_name = md2_texture_file_name #tMd2Header m_Header; // The header data #tMd2Skin *m_pSkins; // The skin data #tMd2TexCoord *m_pTexCoords; // The texture coordinates #tMd2Face *m_pTriangles; // Face index information #tMd2Frame *m_pFrames; // The frames of animation (vertices) # List of skin strings. self.skins = [] # The texture coordinates. string of shorts, u,v self.tex_coords = "" # Face index information. # [[vertexIndices,textureIndices], ...] # [[[0,0,0], [0,0,0]], ...] self.triangles = [] #vertex_indices = [] #texture_indices = [] # The frames of animation (vertices) # [[frame_name, vertices, normals], ...] self.frames = [] self.header = {} # copy the header as 0. self.header.update(tMd2Header) def Load(self, md2_file_name = None, md2_texture_file_name = None): if md2_file_name == None and md2_texture_file_name == None: # Use the internal names. if self.md2_file_name == None: raise "Object has no file to load." pass else: # Set self.md2_file_name = md2_file_name self.md2_texture_file_name = md2_texture_file_name self.f = open(self.md2_file_name) self._ReadHeader() if self.header["version"] != 8: raise "file corrupt, version is not 8" self._ReadMd2Data() def _ReadMd2Data(self, md2_file_name = None, md2_texture_file_name = None): """ """ if md2_file_name == None and md2_texture_file_name == None: # Use the opened file. f = self.f else: # open the file name given. f = open(md2_file_name) header = self.header # Next, we start reading in the data by seeking to our skin names offset. f.seek(header['offsetSkins']) # Depending on the skin count, we read in each skin for this model. s = f.read(64 * header['numSkins']) self.skins = [s[x:x+64] for x in range(0,len(s),64)] # Seek to the texture coordinates. f.seek(header['offsetTexCoords']) # Read in all the texture coordinates in one fell swoop self.texcoords = f.read(2* 2 * header['numTexCoords']) tcoords = struct.unpack('%sh' % (header['numTexCoords'] *2), self.texcoords) self.texcoords= Numeric.array(tcoords, 's') del tcoords # Move the file pointer to the triangles/face data offset f.seek(header['offsetTriangles']) # Read in the face data for each triangle (vertex and texCoord indices) self.triangles = f.read(12 * header['numTriangles']) tris = struct.unpack('%sh' % (header['numTriangles'] * 2 * 3), self.triangles) # vertex_indices 3 shorts, texture_indices 3 shorts. triangle_data = Numeric.array(tris, 's') del tris triangle_data = Numeric.reshape(triangle_data, (len(triangle_data) /3, 3)).astype('s') # make two seperate arrays. One for vertex_indices, other for texture_indices. # every second set of three. self.vertex_indices = triangle_data[::2] self.texture_indices= triangle_data[1::2] # Move the file pointer to the vertices (frames) f.seek(header['offsetFrames']) # Read in the first frame of animation self.frames = f.read(header['frameSize']) # I think the first part of this is: # 12 bytes, 0 - 11, float scale[3] # 12 bytes, 12 - 23, float translate[3] # 16 bytes, 24 - 39, char name[16] scale = Numeric.array(struct.unpack('fff', self.frames[0:12]), 'f') translate = Numeric.array(struct.unpack('fff', self.frames[12:24]), 'f') print scale print translate frame_name = from_c_string(self.frames[24:39]) # Make an array of the bytes. byte vertex[3]; byte lightNormalIndex; # vertex_light_data = Numeric.array(self.frames[40:], 'b') print vertex_light_data[0], "vertex_light_data" print vertex_light_data[1], "vertex_light_data" print vertex_light_data[2], "vertex_light_data" print vertex_light_data[3], "vertex_light_data" vertex_light_data = Numeric.reshape(vertex_light_data, (len(vertex_light_data)/4, 4)).astype('b') # Need to seperate the lightNormalIndex from the rest of the shite. # that is get rid of every 4th element. # We won't use the lightNormalIndex, as that requires a 1.7MB quake2 specific normals file. # Make a new array with 3 elements instead of 4. vertex_data = Numeric.zeros((len(vertex_light_data),3), 'f') # loop over vertex_data, and put the first 3 elems in there. #TODO: there has to be a faster way to do this... # Maybe the code I'm copying from is wrong. count = 0 print vertex_light_data[0], "vertex_light_data" for vert_light in vertex_light_data: # we swap the second, and third elem to match opengls coord system. vertex_data[count] = Numeric.array([vert_light[0] * scale[0] + translate[0], vert_light[2] * scale[2] + + translate[2], -1 * (vert_light[1] * scale[1] + translate[1])], 'f') count += 1 # Multiply the array by the scale, then add the translate to the array. # This will transform it into an array of floats. #vertex_floats = vertex_data * scale #vertex_floats = vertex_data + translate #print vertex_floats[0] print vertex_data[0] print len(vertex_data) print vertex_data[156] print vertex_data[476] # We have at the end. #TODO: read in the rest of the frames. # Numeric array of floats, there will be one array for each frame. self.vertex_data = vertex_data # Numeric array of shorts. self.vertex_indices # Numeric array of shorts. self.texture_indices frame_name # a numeric array of shorts, in range 0 - 255. self.texcoords = self._ConvertTexcoords(self.texcoords,self.texture_indices, header['skinHeight'], header['skinWidth'] ) # TODO: what is it? maybe need to convert cstrings to python strings. self.skins def _ConvertTexcoords(self, texcoords, texture_indices, w, h): """ Flips the v coordinate part, and makes a new array based on the texture indices. texcoords - texture_indices - """ texcoords = Numeric.reshape(texcoords, (len(texcoords) /2, 2)).astype('f') # flip the v coordinate. count = 0 for u,v in texcoords: texcoords[count] = [u/w, 1 - v/h] #texcoords[count] = [u/w, (v/h)] #print texcoords[count] count += 1 # allocate a new array with the length of the indices * 2. print len(texture_indices) new_texcoords= Numeric.zeros((len(texture_indices) * 3,2), 'f') max_xyz = 0 count = 0 for x,y,z in texture_indices: new_texcoords[count] = texcoords[x] new_texcoords[count+1] = texcoords[y] new_texcoords[count+2] = texcoords[z] print new_texcoords[count] print new_texcoords[count+1] print new_texcoords[count+2] count += 3 return new_texcoords def _ReadHeader(self, md2_file_name = None, md2_texture_file_name = None): """ """ if md2_file_name == None and md2_texture_file_name == None: # Use the opened file, if good. if hasattr(self, 'f'): f = self.f else: f = open(self.md2_file_name) else: # open the file name given. f = open(md2_file_name) f.seek(0) header_data = array.array('i', f.read(17 * 4) ) h = self.header h["magic"] = header_data[0] h["version"] = header_data[1] h["skinWidth"] = header_data[2] h["skinHeight"] = header_data[3] h["frameSize"] = header_data[4] h["numSkins"] = header_data[5] h["numVertices"] = header_data[6] h["numTexCoords"] = header_data[7] h["numTriangles"] = header_data[8] h["numGlCommands"] = header_data[9] h["numFrames"] = header_data[10] h["offsetSkins"] = header_data[11] h["offsetTexCoords"] = header_data[12] h["offsetTriangles"] = header_data[13] h["offsetFrames"] = header_data[14] h["offsetGlCommands"] = header_data[15] h["offsetEnd"] = header_data[16] return h new_rdpyg/build/lib/urdpyg/converters/middle_obj.py0000644000175100017510000002457207743744517023031 0ustar renerene00000000000000""" Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ """ A scene graph which will contain all sorts of information about 3d scenes. Advantages this method will give you. - Allow importers and exporters to be written independantly. Just write an importer and you can take advantage of all the exporters. - Able to choose a disk based, or memory based conversion. - Don't have to support all of a 3d format, can support only parts of a format. This is necessary as development nearly always happens incrementally with 3d format converters. This means importers and exporters will have to specify which elements that they support. - Extensibility: the system is designed to be extensible. So that if new 3d formats are added they will not affect the old ones. This is done by having all importers and exporters contain a list of features which they support. Here is an example of how it would all work: First the importer and exporter(s) will tell the middle object which features that they support(or are interested in). The importer will read in what of the 3d format it understands, then pass the 3d data onto the middle object. Also passing on the features which the importer has imported. - Support multiple exporters being used at once. But only one importer being used at once. Multiple exporters will be useful to save having to do the import step multiple times when exporting to lots of formats. - Each exporter will be responsible for setting which features that it wants to export. That way it is possible to - A feature can be any sort of 3D data. We want to support as much different data as possible. Here is a list of 3d data that I can think of: = mesh data, = vertex, face lists. = vertex shading information. = per vertex, pre face UV information. = Scene graph information( this will be hard ). - It could be a graph of indicies to other objects. Maybe a tuple of (feature_name, index into list) - Not sure how inheritance will be handled. = bezier lines, and patches. = nurb lines and patches. = Texture mapping info. = cameras = lights (point, spot, omni, ambient). = image maps for terrain. = Material information. - color maps. - animations. - bump maps. - alpha maps. - smoothing. - specularity. - May provide a heap of helper functions, to help make converting the data easier. Providing different views of the intermediate data. eg. converting a mesh made up of 4, and 3 sided polygons into a mesh made up of only 3 side polygons. Here is a list of helpers: = ngons to triangles. = curve patches to triangles. = per face, to per vertex uv mapping conversions. = scaling. = rotation. = converting which coordinates are up, sideways and depth. - May need to implement a disk based dictionary, and a disk based list. As the shelf object which uses a database as a backend is pretty lame. It can only store objects of a certain size. Also they are only dicts, not lists. - Perhaps to save on memory, we could write certain features to disk(using pickle) whilst the other data is being converted. - Importers, and exporters don't necessarily need to read or write to files. eg. They may comunicate directly with a 3d editor, or a game engine. They could use a COM, CORBA, or xml rpc interface. - Should try and make use of other converter libraries, eg lib3ds. - importers and exporters should be able to do things like eg. only export frame 34 of the animation. Probably have to expand on the feature passing idea for this. Diagram of how feature information moves around: user --wanted exporters--> middle_obj user --wanted features for exporters--> middle_obj user --wanted features--> middle_obj importer --supported features--> middle_obj middle_obj --features to export--> exporters - Reduce the number of unnessesary calculations. One way to do this is to have the importers and exporters know which way certain things are defined. Eg. the coordinate systems: in one format x may be depth, and in another format x may be depth but comming into the screen. ei. if two formats both use z+ as depth then there is no need to transform the coordinates when putting them into the middle object. NOTE: supplying all different types of stores in the middle object should not be mandatory. There will be a default for the middle object which all importers should support. NOTE: This information would be stored with each feature. Eg, Meshes.Triangles.PointOrder.Supported.Value = ["clockwise", "anticlockwize"] Meshes.Triangles.PointOrder.Default.Value = "clockwise" - If Conversions have to be done on data, make sure that the conversions also change other data which is dependant on it. The only example of this that I can think of at the moment is Indexes to things. eg. face list index to a heap of points. Maybe we should keep some dependancy information somewhere. Think about this some more. Maybe too much effort. - Keep documentation of all the features. Documentation of every feature will be kept in a master feature list. The master feature list will be generated from the importers,exporters, and the middle object. The middle object will be updated sporadically when new features come around. The documentation of the features will also be taken from - Keep a central repository of all the different features. Supply a report of which importers/exporters support what. These need to be automated. The feature objects of a importer/exporter/middle_object are python objects which contain __doc__ strings. - With (importers/exporters) and the middle object, the feature objects are used differently. The middle object uses features to store not only the documentation on the various features, but also data itself. - Make some test importers, and exporters. A test importer will fill up the middle object with what ever data the exporter asks of it. A test exporter will ask the middle object for some data to export. If we can get an test exporter, and importer which supports _ALL_ the features, then testing will be easier, and there will be some base implementations for people to look at. - A validate format function for each format may be useful. One function could be used to validate the import and export plugins. It is optional to implement this. Quality plugins implement this ;). - A DoValidation() method for importers and exporters may be useful. This way an importer/exporter has the option of validating the data or not. Not validating the data may be a speed increase. Both in speeding up the conversion and speeding up the writing of the plugin. Validating data during the conversion may also be faster than doing the validation as a seperate pass. It is optional to implement this. Quality plugins implement this ;). """ class MiddleObject: def __init__(self): """ """ # A dictionary of features self.features = {} def AddImporter(self, importer): """ importer - an object used to import 3d data into the middle object. """ def AddExporter(self, exporter): """ exporter - an object used to export 3d data from the middle object. """ def SendFeatureRequestsToImporter(self): """ Goes through the exporters and gathers a set of features which need to be sent to the importer. """ class Importer: """ Used for importing 3d data into a MiddleObject. This is a base class, to be used for importers for various 3d formats. """ def __init__(self, supported_features, wanted_features = {}): """ supported_features - features which the wanted_features - defaults to all features if not specified. """ self.supported_features = supported_features self.wanted_features = wanted_features def GetSupportedFeatures(self): """ Returns the features that this importer supports.""" return self.supported_features def SetFeaturesWanted(self, features): """ Used to tell the importer what features the importer should pass onto the middle object. NOTE: this does not mean that the importer should not load all of the 3d format. If it has to load it all so be it. Just pass the features that are wanted. """ self.wanted_features = features def Start(self): """ Starts the importer doing its import thing.""" raise "This importer is missing an implementation of Start()" class Exporter: """ Used for exporting 3d data from the MiddleObject. This is a base class, to be used for exporters for various 3d formats. """ def __init__(self, supported_features, wanted_features = {}): """ supported_features - """ self.supported_features = supported_features self.wanted_features = wanted_features def GetSupportedFeatures(self): """ Returns the features that this exporter supports.""" return self.supported_features def SetFeaturesWanted(self, features): """ Used to tell the exporter what features the exporter should get from the middle object. """ self.wanted_features = features new_rdpyg/build/lib/urdpyg/converters/ms3d_ascii_importer.py0000644000175100017510000003544310051352003024642 0ustar renerene00000000000000""" Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ from middle_obj import * #from features import import string from string import split from string import join import re import os import md5 import cPickle # TODO: # *- read meshes. # - read materials. # - read bones. # - figure out how to send data back into the middle_object. # probably register with a callback function, with initialize. # - Add checking in to see what features are required. # """ Milkshape 3d ascii format notes: Basic outline of format: --- Start of file --- Frames: Frame: Meshes: Materials: Bones: --- End of file --- A material index of -1 means no material. rotations seem to be in radians """ def str_parse(string_to_parse, conversion_list, seperator = " "): """ returns a list of formated converted variables based on the string_to_parse - um.. conversion_list - list of functions, to convert parts of the string. Use str for strings, int for ints, floats for floats etc :) seperator - string to use to seperate the elements of the string. Will raise exceptions if string not correctly set up. Or if data fails to convert. """ #TODO: Allow the conversion list to contain sequences of functions. # This way you can return subsequences. eg. # line = "0 1.0 1.0 1.0 2.0 2.0 2.0" # (flags,pos,rot)=str_parse(line, [int, (float, float, float), # (float, float, float)] # flags - 0 # pos - (1.0, 1.0, 1.0) # rot - (2.0, 2.0, 2.0) # # hrmm maybe I could just use regular expressions... split_list = split(string_to_parse, seperator) if(len(conversion_list) != len(split_list)): raise "wrong number of converters, or string doesn't match." return_list = [] for x in range(len(conversion_list)): return_list.append( conversion_list[x](split_list[x]) ) return return_list def chomp(s): if s[-2:] == "\r\n": return s[:-2] elif s[-1:] == "\n": return s[:-1] else: return s class milk_mesh: def __init__(self): # (flags, triangle indicies(a,b,c), # normal indicies(a,b,c), smoothing group) self.triangles = [] # (x,y,z) self.normals = [] # (flags, x,y,z,u,v, bone index). self.verts = [] self.mat_index = -1 self.flags = -1 def __str__(self): return "triangles:%s:\nnormals:%s:\nverts:%s:" % (self.triangles, self.normals, self.verts) class milk_material: def __init__(self): self.material_name = "" self.ambient = [] self.diffuse = [] self.specular = [] self.emissive = [] self.shininess = -1 self.transparency = -1 self.diffuse_texture_name = "" self.alpha_texture_name = "" class milk_bones: def __init__(self): self.name = "" self.parent_name = "" self.flags = 0 # three floats. self.position = [0., 0., 0.] # three floats. self.rotation = [0., 0., 0.] # list of tupples(4 floats) self.position_keys = [] # list of tupples(4 floats) self.rotation_keys = [] def __str__(self): a = """name:%s:|parent_name:%s:|flags:%s:|position:%s:|rotation:%s:|position_keys:%s:|rotation_keys:%s:""" % (self.name, self.parent_name, self.flags, self.position, self.rotation, self.position_keys, self.rotation_keys) return "\n".join(a.split("|")) class MS3dImporter(Importer): """ """ def __init__(self, wanted_features = None): """ If wanted_features equals None then all features are given.""" #FIXME: add the supported features. supported_features = "" #FIXME: call superclasses init. #Importer.__init__(supported_features, wanted_features) def Initialize(self, file): # File to load milkshape data from. self.file = file self.total_frames = 0 self.meshes = [] self.materials = [] self.bones = [] def Start(self): """ """ b_error = 0 f = self.file raw_line = f.readline() line = chomp( raw_line ) print "line :%s:" % line print "raw_line :%s:" % raw_line while (raw_line != "" and not(b_error)): if(line[2:] == "//"): pass # read in the meshes. elif(line[:7] == "Meshes:"): self.ReadMeshes(f, num_meshes = string.atoi(line[7:])) # read in the materials. elif(line[:10] == "Materials:"): self.ReadMaterials(f, num_materials = string.atoi(line[10:])) # read in the bones. elif(line[:6] == "Bones:"): self.ReadBones(f, num_bones = string.atoi(line[6:])) raw_line = f.readline() line = chomp( raw_line ) print "line :%s:" % line print "raw_line :%s:" % raw_line def ReadMeshes(self, a_file, num_meshes): """ """ f = a_file self.meshes = [] for mesh_count in range(num_meshes): m = milk_mesh() line = chomp( f.readline() ) # Get the name, flags, and material index. # split by space, join the last two, and the first. split_parts = split(line, " ") (m.flags, m.mat_index) = str_parse(join(split_parts[-2:]), [int,int]) # join the first parts of the string then take off the " at the # start and at the end. There should be no new line. m.mesh_name = join(split_parts[:-2])[1:-1] # Read in the number of vertices. num_verts = string.atoi( chomp(f.readline()) ) # read the verts into a list. f_readline = f.readline v_a = m.verts.append for vert_count in range(num_verts): v_a( str_parse(chomp(f_readline()), [int, float, float, float, float, float, int]) ) # Read in the normals. num_normals = string.atoi( chomp(f.readline()) ) n_a = m.normals.append for norm_count in range(num_normals): n1, n2, n3 = split( chomp(f_readline()) ) n_a( [float(n1), float(n2), float(n3)] ) # Read in the triangles. num_triangles = string.atoi( chomp(f.readline()) ) t_a = m.triangles.append for norm_count in range(num_triangles): flags, i1,i2,i3, ni1,ni2,ni3, index = split( (f_readline()) ) #t_a( [int(flags), float(i1), float(i2), float(i3), # float(ni1), float(ni2), float(ni3), int(index)] ) t_a( [int(flags), int(i1), int(i2), int(i3), int(ni1), int(ni2), int(ni3), int(index)] ) self.meshes.append(m) def ReadMaterials(self, a_file, num_materials): """ a_file should be set to after the Materials line.""" # Structure of the materials section is as follows. # each part takes up one line. # material name. in "" # ambient, 4 floats. # diffuse, 4 floats. # specular, 4 floats. # emissive, 4 floats. # shininess, 1 float. # transparency, 1 float. # diffuse texture name. in "" # alpha texture name. in "" f = a_file self.materials = [] for x in range(num_materials): # read the name of the material. try: #line = f.readline() m = milk_material() m.mat_name = string.strip(chomp(f.readline()))[1:-1] #print mat_name # ambient, 4 floats. m.amb = str_parse(chomp(f.readline()), [float, float, float, float]) # diffuse, 4 floats. m.diffuse = str_parse(chomp(f.readline()), [float, float, float, float]) # specular, 4 floats. m.specular = str_parse(chomp(f.readline()), [float, float, float, float]) # emissive, 4 floats. m.emissive = str_parse(chomp(f.readline()), [float, float, float, float]) # shininess, 1 float. m.shininess = float(chomp(f.readline())) # transparency, 1 float. m.transparency = float(chomp(f.readline())) # diffuse texture name. in "" m.diffuse_texture_name = chomp(f.readline())[1:-1] # alpha texture name. in "" m.alpha_texture_name = chomp(f.readline())[1:-1] self.materials.append(m) except: # find the line number of error. error_pos = f.tell() f.seek(0) l = f.readline() cur_pos = f.tell() line_num = 1 while cur_pos < error_pos: cur_pos = f.tell() line_num += 1 l = f.readline() #print line_num raise "Error on line:%s:" % line_num def ReadBones(self, a_file, num_bones): """ a_file should be set to after the Bones line.""" # Structure of the Bones section is as follows. # bone name in "" # bone parent in "" # flags(1 int), position(3 floats), rotation(3 floats) # Position key count (int). # position key block(position key lines long). # # Rotation key count (int). # rotation key block(rotation key lines long). # # # NOTE: The comment in the ms3d acii importer code states that bone # parent is alpha_texture... this is obviously a bone parent. f = a_file for x in range(num_bones): # read the name of the bone. line = chomp(f.readline()) b = milk_bones() b.name = string.strip(line)[1:-1] #print ":%s:" % b.name #print "b.name-1:%s:" % b.name[-1] #print "b.name-2:%s:" % b.name[-2] #print ":%s:len%s" % (line, len(line)) #print ":%s:len%s" % (line[1:-2], len(line)) # read in the bones parent name. line = chomp(f.readline()) b.parent_name = string.strip(line)[1:-1] #print ":%s:" % b.parent_name #print ":%s:" % line # Read in the flags, the position, and rotation. p = b.position r = b.rotation stuff = str_parse(chomp(f.readline()), [int, float, float, float, float, float, float]) (b.flags,p[0],p[1],p[2],r[0],r[1],r[2]) = stuff # Read in the number of position keys. num_position_keys = str_parse(chomp(f.readline()), [int])[0] # Read in the position keys. for x in range(num_position_keys): b.position_keys.append( str_parse(chomp(f.readline()), [float]*4) ) # Read in the number of rotation keys. num_rotation_keys = str_parse(chomp(f.readline()), [int])[0] print num_rotation_keys # Read in the rotation keys. for x in range(num_rotation_keys): b.rotation_keys.append( str_parse(chomp(f.readline()), [float]*4) ) self.bones.append(b) import operator import time operator_add = operator.add def convert_array_shape2(verts): return reduce(operator_add, [x[1:-1] for x in verts]) def convert_array_shape3(verts): """ Converts a [[1,1,1,1], [1,1,1,1]] into [1,1,1,1,1,1]""" out_verts = []; map(out_verts.extend, map(lambda x: x[1:4], verts)) return out_verts convert_array_shape = convert_array_shape3 def convert_milkshape(a_file): """ Returns a list of [points, indices, texcoords] Only converts one mesh. """ # DO_PICKLE = 1 from types import FileType if type(a_file) == type(""): a_file = open(a_file, "r") # see if a_file.name +".old_md5" exists. # if it does compare the md5 of the current file, with that of the old one. #TODO: what if it is a StringIO file? need to see if .name attrib exists. if os.path.exists(a_file.name + ".old_md5") and DO_PICKLE: #print "getting old digest" old_md5 = open(a_file.name + ".old_md5").read() # NOTE: may want to use mmap here. #print "getting new digest" new_md5 = md5.md5( a_file.read() ).digest() #print "done: getting new digest" if old_md5 == new_md5: # return the pickle if it exists. if os.path.exists( a_file.name + ".pickle" ): #print "loading pickle" print a_file.name try: pickle_file = open(a_file.name + ".pickle", "rb") return cPickle.load(pickle_file) except: pass a_file.seek(0) imp = MS3dImporter() imp.Initialize(a_file) imp.Start() mesh_data = [] for mesh in imp.meshes: verts = mesh.verts triangles = mesh.triangles normals = mesh.normals points = [] indices = [] texcoords = [] bone_indices = [] normal_list = [] # convert the verts to a list of points( one dimention ). map(points.extend, map(lambda x: x[1:4], verts)) map(normal_list.extend, map(lambda x: x[1:4], normals)) # get a list of texcoords, one dimention. map(texcoords.extend, map(lambda x: [x[4],1.0-x[5]], verts)) #texcoords = map(lambda x: 1.0 -x, texcoords) # Get the indices. map(indices.extend, map(lambda x: x[1:4], triangles)) # get the bone indices. bone_indices = map(lambda x: x[-1], verts) """ print verts[-1] print points[-3], points[-2], points[-1] print points """ #print len(points), len(texcoords), len(indices) assert(len(points) /3 == len(texcoords) /2) #assert(len(points) /3 == len(indices)) mesh_data.append( {"points": points, "normals": normal_list, "indices": indices, "texcoords":texcoords, "material_index":mesh.mat_index, "bone_indices":bone_indices} ) #for md in mesh_data: # if md[3] != -1: # md[3] = imp.materials[md[3]] milk_scene = {} milk_scene["materials"] = imp.materials # make a couple of dicts from the bones. # A parent dict, keyed by bone name, valued by parent name. # A #for b in imp.bones: milk_scene["bones"] = imp.bones milk_scene["mesh_data"] = mesh_data if DO_PICKLE: # make the pickle, and md5 file. if not locals().has_key("new_md5"): a_file.seek(0) new_md5 = md5.md5( a_file.read() ).digest() open(a_file.name + ".old_md5", "w").write(new_md5) an_f = open(a_file.name + ".pickle", "w") cPickle.dump(milk_scene, an_f, 1) return milk_scene def test_MS3dImporter(file_name): #points,indices,texcoords = convert_milkshape(file_name) meshes = convert_milkshape(file_name) if(__name__ == "__main__"): import sys if(len(sys.argv) != 2): print "" sys.exit(0) test_MS3dImporter(sys.argv[1]) new_rdpyg/build/lib/urdpyg/converters/test_cal3d_exporter.py0000644000175100017510000000142407743744517024705 0ustar renerene00000000000000""" unit tests for the cal3d exporter. """ import unittest import cal3d_exporter class Cal3dExporter(unittest.TestCase): pass def test_Cal3dBone__to_xml(self): """ does converting a Cal3dBone to xml work? """ b = cal3d_exporter.Cal3dBone() print b.to_xml() def test_Cal3dSkeleton__to_xml(self): """ does converting a Cal3dSkeleton to xml work? """ s = cal3d_exporter.Cal3dSkeleton() s.bones.append(cal3d_exporter.Cal3dBone()) s.bones.append(cal3d_exporter.Cal3dBone()) s.bones.append(cal3d_exporter.Cal3dBone()) s.bones.append(cal3d_exporter.Cal3dBone()) print s.to_xml() if __name__ == "__main__": unittest.main() new_rdpyg/build/lib/urdpyg/converters/test_md2_importer.py0000644000175100017510000000101007743744517024361 0ustar renerene00000000000000""" unit tests for the md2 importer. """ import unittest import md2_importer import os import pprint class TestMd2Importer(unittest.TestCase): pass def testReadHeader(self): """ """ md2_file_name = os.path.join("..", "models", "tris.md2") md2_texture_file_name = os.path.join("..", "models", "hobgoblin.bmp") md2 = md2_importer.Md2Model(md2_file_name, md2_texture_file_name) md2._ReadHeader() pprint.pprint (md2.header) md2.Load() if __name__ == "__main__": unittest.main() new_rdpyg/build/lib/urdpyg/converters/test_middle_obj.py0000644000175100017510000000023507743744517024056 0ustar renerene00000000000000""" unit tests for the md2 importer. """ import unittest class fsdf(unittest.TestCase): pass if __name__ == "__main__": unittest.main() new_rdpyg/build/lib/urdpyg/map/0000755000175100017510000000000010076374157016730 5ustar renerene00000000000000new_rdpyg/build/lib/urdpyg/map/__init__.py0000644000175100017510000000000010074105345021014 0ustar renerene00000000000000new_rdpyg/build/lib/urdpyg/map/map.py0000644000175100017510000001241210074245107020045 0ustar renerene00000000000000""" = Features wanted = * When not moving it can take only update parts of the screen. * update(dirty_rects) can be used to speed up drawing. * by only updating areas which are dirty. * if the map is not moving we can make it lots speedier. * Offscreen buffer. Blit all smaller tiles to an offscreen buffer then blit one big image to the screen. This can be faster on some screens/computers. * Different tile sizes. * different sizes on the same map. * Join maps together easily. * Different drawable sizes. Ie different camera views. * Be able to be used with pygame or pyopengl. * Different camera modes: * jump scrolling, * jump the map in blocks. Like ten pixels at a time. * smooth scrolling, * every pixel the camera moves the tiles move. * smooth-jump scrolling. * Mostly the screen stays still. When the character nears the edge everything stops moving while the maps scrolls over a little way. * centered camera. * Can center the camera on * Looping Map Edges * Paralax scrolling. * Moving layers at different speeds. * Multiple views of the map. * miniview of the map. Perhaps using a scaled version or one pixel per tile. * minimize overdraw. * using dirty rectangles. * for alpha images precalculate 'full rects'. * That is like a bounding box in the middle where the area is full. * think about using a coverage buffer. * animated tiles will probably always need to be redrawn(unless it's the same frame). * Overlapping tiles. * As well as overlapping whole maps. For joining maps together. * Layers/Z ordering. * draw characters by descending y value on same layer. * for certain types of games: see for explanation: * http://www.gamedev.net/reference/programming/features/gpgenesis9/page7.asp * line of sight tests between tiles and pixels/rects. * collision detection between tiles and pixels/rects. * some tiles may be pass through. * tiles on different layers may be collidable, others not. * fog of war. * darkening/lightening of areas. * Rotatable tiles. * scalable tiles? Other transforms needed? * Easy layer toggling. * So eg when you go inside a building the roof comes off and you can see inside. = Implementation ideas = * Use pygame sprites and sprite groups. * could then reuse lots of code... optimize in one place. Speed development. * think of camera movement as simply moving a sprite group in a certain way. * Use a quad tree for the collision detection. * Could use it for moving, and non moving. * Left to right, or top to bottom scrollers can be optimized in different ways. = Some map editors = The tile combie(or engine if you want) should have most of the features that these map editors contain. http://tilestudio.sourceforge.net/ http://www.tilemap.co.uk/ = A discussion about features = background tiling, layers, collision detection between layers and stuff (rect and pixel) paralax scrolling animation of background/sprites line of sight tests between tiles and pixels based on layer compositions and such eek, that's a lot of stuff good stuff :) separate environmental and UI layer systems what do you mean? so you can draw your UI without worrying how height your environments layers are the UI layers are alwayrs on top ah, cool basically, just 2 lists for heights auto-shadowing for sprites is good indeed, that'd be cool doing like angled skews on the images, and drawing them on the ground layer so you dont have to have separate shadow images for them nice or just auto positioning the same image, but based on heigth of the sprite so like a flying ship has its shadow in the real place, and its in its height-adjusted place, like zaxxon which basically just means you have a transformation for height built in, and use a sort of worrld coords and translated drawing coords aah which makes sense so you should have parameters to what your viewing perspective is, so they can adjust it based on how their art is rendered like: 1.5:1.0 or something you could also have layer toggling like i did in VT, where if you go into a building, it switches what the background tiles are. and if you change floors, it also does that ah, that sounds nice too but that may be a bit specific. though, you could make the design so its possible to rotate through BG tile maps specifically, like theyre layered and do a fall through if the current selected one doesnt exist to the default background map, which has all its spaces mapped sorta an "optional current level background" good for things where people take stairs, and you still want the ground of things outside buildings and such im running out of stuff ive thought about for tiling engines hehe. that's all stuff I didn't think about :) i want to retire im pretty happy doing fuck all all the time now heh having layers greyed out would be good hehe. mostly I'm happy doing fuck all too :) optional layers? or you mean something else? """ new_rdpyg/build/lib/urdpyg/milk_skeleton.py0000644000175100017510000005570510075765524021402 0ustar renerene00000000000000""" Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ import string, sys, os import time import UserDict import Numeric N = Numeric from urdpyg.converters import ms3d_ascii_importer import bisect """ Data flow: -------------- milkshape converter -> MilkshapeModelLoader In the MilkshapeModelLoader it converts the data into its internal representation. """ class MilkshapeModelLoader: """ responsible for loading a milkshape model. """ def __init__(self, file_name = ""): self._debug_level = 0 self._is_tex = 0 if file_name: self.Load(file_name) def _debug(self, x, debug_level = 1): """ """ if self._debug_level > debug_level: print x def IsTextured(self): if self._is_tex: return 1 else: return 0 def Load(self, file_name): """ """ t1 = time.time() self.data = ms3d_ascii_importer.convert_milkshape( file_name ) t2 = time.time() self._debug("load time of milk:%s:" % (t2 - t1), 2) d = self.data["mesh_data"][0] material_index = d["material_index"] self._debug("material_index:%s" % material_index, 2) self.texcoords= Numeric.asarray(d["texcoords"], 'f') self.points = Numeric.asarray(d["points"], 'f') self.normals = Numeric.asarray(d["normals"], 'f') self.indices = Numeric.asarray(d["indices"], 'i') if material_index != -1: m = self.data["materials"][material_index] self._debug("m.material_name:%s" % m.material_name, 2) self._debug("m.diffuse_texture_name:%s" %m.diffuse_texture_name, 2) self._debug("m.alpha_texture_name :%s" %m.alpha_texture_name, 2) self.image_name = apply(os.path.join, os.path.split(m.diffuse_texture_name[2:])) #NOTE: FIXME: materials don't need textures. #NOTE: FIXME: there are different textures too. self._is_tex = 1 #time.sleep(2) else: self._is_tex = 0 self.skeleton = MilkSkeleton(self.data) class BoneHeirarchy: """ Which bones are parents/children of which other bones. - has bone names, and bone indices into AbsoluteBones/RelativeBones. - GetChildren_names/indices - returns a list of names/indices. BoneName2BoneNumber_Map - mapping of bone names to a number in the bone index. """ def __init__(self, milk_bones): """Takes a milk_bones variable from the milkshape converter. """ # given the parents name get back a list of children. self.bone_parents_dict= {} # given the childs name get back a parent. self.bone_children_dict= {} # given a bone name you can get the idx of that bone in the bone list. self.bone_name_to_idx = {} self.Update(milk_bones) def Update(self, milk_bones): """ Takes a milk_bones variable from the milkshape converter. """ #NOTE: if we want to use 1000's bones it may be more efficient to use # ints as the keys. and possibly lists to store them. # # This is an efficient storage for 1000's of skeletons with 1000's of # bones. 1000 * 1000 * 20 == 20 megabytes. # 1000 * 1000 * 4 == 4 megabytes for a list implementation. self.bone_parents_dict= {} self.bone_children_dict= {} self.bone_name_to_idx = {} # keyed by bone name, valued by milk_bones instances. self.bone_dict = {} for b in milk_bones: if not self.bone_parents_dict.has_key(b.parent_name): self.bone_parents_dict[b.parent_name] = [b.name] else: self.bone_parents_dict[b.parent_name].append(b.name) if not self.bone_children_dict.has_key(b.name): self.bone_children_dict[b.name] = [b.parent_name] else: self.bone_children_dict[b.name].append(b.parent_name) #assert( not self.bone_dict.has_key(b.name) ) self.bone_dict[b.name] = b self.bone_name_to_idx = self._make__bone_name_to_idx(milk_bones) def _make__bone_name_to_idx(self, milk_bones): """ returns a dict mapping bone name -> its idx within the list. """ bone_name_to_idx = {} for idx, milk_bone in zip(range(len(milk_bones)), milk_bones): if bone_name_to_idx.has_key(milk_bone.name): raise ValueError("bone allready exists with name, %s" % milk_bone.name) bone_name_to_idx[milk_bone.name] = idx return bone_name_to_idx def GetChildren_idx(self, bone_name): """ returns a list of idx for the children of given bone name. """ children = self.GetChildren(bone_name) idx_list = [] for child in children: idx_list.append(self.bone_name_to_idx[child.name]) return idx_list def GetChildren(self, bone_name): """ Returns a list of children milk_bone instances.""" if not self.bone_parents_dict.has_key( bone_name ): return [] return map(self.bone_dict.get, self.bone_parents_dict[ bone_name ]) #return self.bone_dict[ self.bone_parents[ bone_name ] ] def GetParents(self, bone_name): """ Returns a list of parents milk_bone instances.""" if not self.bone_children_dict.has_key( bone_name ): return [] return map(self.bone_dict.get, self.bone_children_dict[ bone_name ]) #return self.bone_children[ bone_name ] def GetRootName(self): """ Returns the root bones name. """ return self.bone_parents_dict[""][0] def __str__(self): return self.PrintTree(details = 1) def PrintTree(self, a_bone = "ROOT", indent_level = 0, details = 0): """ Returns a string representation of bones tree. a_bone - a milk_bone instance, or "ROOT". if "ROOT" then we return from the root of the tree. """ if a_bone == "ROOT": a_bone = self.bone_dict[self.GetRootName()] return_text_list = [] indent_text = indent_level * " " if details: bone_text = str(a_bone) bone_text.split("\n") a = "".join(map(lambda x,y = indent_text: "".join((y,x,"\n")), bone_text.split("\n"))) return_text_list.append( a ) else: return_text_list.append( indent_text + a_bone.name ) children = self.GetChildren(a_bone.name) for bone in children: child_text = self.PrintTree(bone, indent_level+2, details) return_text_list.append(child_text) return string.join( return_text_list, "\n") class BoneName2BoneNumber_Map(UserDict.UserDict): """ mapping of bone names to a number in the bone index. """ def __init__(self, milk_bones): UserDict.UserDict.__init__(self) self.Update(milk_bones) def Update(self, milk_bones): for b in zip( milk_bones, range(len(milk_bones)) ) : self.data[b[0].name] = b[1] class Bone2Vert_Map(UserDict.UserDict): """ a list of indices for the verts that each bone should transform. Should probably be a Numeric 3d array. where self.data[0] == list of vert indices for the first bone. Each index could be 4 bytes for four bones. - this would be harder to access. - would limit the total number of bones. For now keep it simple. """ def __init__(self, milk_data): self.Update(self, milk_data) def Update(self, milk_data): """ """ # note: milkshape can only have one bone per vert. data = milk_data["mesh_data"]["bone_indices"] #self.data = Numeric.reshape(data, (len(data), 1)) bone2vert_map = {} for bone_idx, vert_idx in zip(data, len(data)): # if not bone2vert_map.has_key(bone_idx): bone2vert_map[bone_idx] = [vert_idx] else: bone2vert_map[bone_idx].append(vert_idx) # class Vert2Bone_Map: def __init__(self, ): self.Update(self, milk_data) def Update(self, milk_data): """ """ # note: milkshape can only have one bone per vert. data = Numeric.array(milk_data["mesh_data"]["bone_indices"], 'i') self.data = Numeric.reshape(data, (len(data), 1)) class Time2Keyframe_Map: """ Each bone should be able to have it's own key frames. time2keyframe_maps[bone_name] -> time2keyframe_map time2keyframe_map[seconds_since_start_of_animation] -> keyframe index's. Depending on whether we want the animation to loop or stop at the start or the end, we return a keyframe on either side of the time specified. TODO: we can loop at the start of the keyframes as well as at the end. """ def __init__(self, loop = 0): """ loop - should we loop the animation back to the start once the last keyframe has been reached? """ self.loop = loop def UpdateFromBones(self, milk_bone): """ milk_bone - used to get the different times for the keyframes. """ times = [] map(lambda x, t = times: t.append(x[0]), milk_bone.positions) self.times = times self.Update(times) def Update(self, times): """ times - a sequence of floats representing keyframes. """ self.times = times # Should the internal format be a dict and a list? # yes, as we need to find the next, and previous, as well as by a number. # should we have seperate keyframes for rotations, translations, # and scaling? # Why not? We do not have support for it in any editor. # not immediately useful. # For now we will just use the times for rotations. #TODO: incomplete. #raise NotImplementedError # the times should be sorted. self.time_index = {} # make an index of times. for t, i in zip(times, range(len(times))): self.time_index[t] = i def GetIndicesEitherSideOfTime(self, time): """ time - a float Returns the two keyframe indices either side of the time given. """ # no looping. # Find the smallest time which is greater than the time given. # TODO: need to do better than a linear search. # the code below is incomplete, needs fixing. raise "incomplete" largest_num = len(self.times) - 1 if time == self.times[smaller_index]: greater_index = 0 smaller_index = bisect.bisect_left(self.times, time) # if the position is greater than or equal to the largest index, # then we return the largest num as both of them. if smaller_index >= largest_num: smaller_index = largest_num greater_index = largest_num else: greater_index = smaller + 1 if greater_index > largest_num: greater_index = largest_num class AbsoluteBones: """ Stores the absolute transforms. There is a seperate one of these for each keyframe. - Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of 'four elements' ). - translation quats(array of 'four elements' ). Maybe only need matrix version for absolute? - No, need to slerp between two absolute bones. Don't need a matrix representation? - maybe not, if the these are only used to slerp up an intermediate set of bones. NOTE: for transforming the verts, it will be faster to transform them with a 3x3 rotation matrix if there is no translation/scaling happening. """ class RelativeBones: """ Stores transforms relative to it's parent. There is a seperate set of these for each of the keyframes. - Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of 'four elements' ). - translation quats(array of 'four elements' ). TODO: find if a quatRotation * quatTranslation is equal to a matrixRotation * matrixTranslation. """ def Update(self, milk_bone): """ From the milkshape data transform it into an internal representation. milk_bone - a bone from the converter. - Convert the Euler angle milkshape rotations into quaternions. - Convert the milkshape positions into quaternions. Q(Px, Py, Pz, w =0.0) - rotation, position quaternions multiplied and stored. """ # mb = milk_bone mb.position mb.position_keys mb.rotation mb.rotation_keys class MilkSkeleton: """ ---------------------------------------------------------------------- Data structures. - '=' denotes data belongs to this parent. Skeleton - this is where everything is put together. - we may want to share some data between skeletons, so we may need a higher level system. - this higher level system would share the different parts of memory. - Maybe it could even transform all of the data at once. = BoneHeirachy DONE. = Keyframes = Bone2Vert_Map DONE. = Time2Keyframe_Map = KeyframeNumber2Time_Map Keyframes - collects the different keyframe data for a skeleton. = AbsoluteBones = RelativeBones = Time2Keyframe_Map = KeyframeNumber2Time_Map AbsoluteBones - bones represented in their absolute form. - Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of 'four elements' ). - translation quats(array of 'four elements' ). - transform matrices(array of '16 elements' ie 4x4 matrices). RelativeBones - these bones will have all relative data. Eg each bone will only be relative to the others. Time2Keyframe_Map. - gets two keyframes on either side of a given time. - this would be per bone? Not at the moment(it should be per skeleton). KeyframeNumber2Time_Map. - given a keyframe number, give the time for it. - this would be per bone? Not at the moment(it should be per skeleton). DONE. BoneHeirachy - which bones are parents/children of which other bones. - has bone names, and bone indices into AbsoluteBones/RelativeBones. - GetChildren_names/indices - returns a list of names/indices. BoneName2BoneNumber_Map - mapping of bone names to a number in the bone index. DONE. Bone2Vert_Map - a list of indices for the verts that each bone should transform. Vert2Bone_Map - vert to list of bones which effect them. MilkBones - this is the data from the milk format. This contains the positions, and rotations in euler format, and the keyframe times. local2world_transform - a transform specifying where in the world the skeleton is. - This will likely change occasionally. - from every frame to once every minute. - is this specified by the root node? - Could we add this as the new root node? - would simplify the code if we did. - Can be added as an after thought if needed. Pretty easy. - Not really, as it possible this would change all the time. - We may want to add this, as it will solve having to re-transform them. - On the other hand this could be done in hardware with gf+ cards. ---------------------------------------------------------------------- --------------------------------------------------------------------- Order of the operations. - Things that need to be done in order to get the model transformed. Set up stuff. - things to do around load time. From the milk bones set up: - BoneHeirachy - Set up the relative bones. - Convert the Euler angle milkshape rotations into quaternions. - Convert the milkshape positions into quaternions. Q(Px, Py, Pz, w =0.0) - rotation, position quaternions multiplied and stored. - Time2Keyframe_Map - KeyframeNumber2Time_Map AbsoluteBones are made from RelativeBones. For each keyframe. Multiply the bones down the heirarchy. child.absolute = parent.absolute * child.relative Per frame stuff. Get current time in animation. From Time2Keyframe_Map grab two keyframes on either side of current time. For every absolute quat: Interpolate between two keyframes: t1 = current_time_in_animation - kf_a.time t2 = kf_b.time -kf_a.time slerp = t1/t2 frame_now = quat_slerp(kf_a.absolute, kf_b.absolute, slerp) Generate the matrices for each absolute quat. Transform each absolute matrix by the local2world_transform. Transform verts of the mesh: For vertex which is affected by one bone: For each absolute matrix transform its verts. If the vert is only affected by one bone: Multiply the vert by the absolute matrix. else: somehow interpolate the different bones. - TODO: ^ - maybe this could be done in the slerp? - storing some extra absolute quats for the verts affected by multiple ones. - this is where bone weights can fit in. For now we will only support one bone per vertex. Alternate way to transform the skin: For each vertex: look at the weight structure. ulong32 boneIndices - 4 indices to bones. ulong32 weights - 4 weights. --------------------------------------------------------------------- Optimizations. --------------------------------------------------------------------- When a key frame does not have any translations the transform of the vertices can be optimized to only use a 3x3 rot, instead of a 4x4. - There may be other optimizations depending on the bones state. - Maybe we could store a BONE_STATE int which will allow us to quickly identify a type of bone? This would allow us to quickly see if the bone has no translation. - We could group bones of similar nature together to make the transforms quicker. Eg all bones with no translation part could be stuck together. - Remember that we need to apply a local2world transform to all of the different absolute matrices. We may be able to cache certain different transforms. - I'm pretty sure there will be many repeated transforms. A cheap way to interpolate between keyframes would be linear using the mesh's verts. This would involve calculating the mesh for each key frame, and then interpolating between each vertex in meshes a, and b. Perhaps this could be an optional thing. To be used for slow computers, when a character is far away, or when the difference in time or movement of the character is really small. A downside to this is that you need to keep at least three sets of the mesh around at any time. An upside to this is that interpolation can be done on lighting values too. --------------------------------------------------------------------- --------------------------------------------------------------------- TODOS: Future todos: - have keyframe data for seperate parts of the skeleton. - eg make the hand have it's own keyframes. - This would complicate how to construct the absolute quats. - You would recalculate down from the animation for that part. - so if the arm was using some extra ones we'd go from there. - Probably not so useful until the animation tool supports it. - Incorporate bone weights into it. - Milkshape doesn't support these, however others(characterfx) do. - Look at the different ways to accelerate these with hardware. - ati, and nvidia have things to do this from geforce up. --------------------------------------------------------------------- --------------------------------------------------------------------- Dependencies - a list of different dependencies that need to be considered. - helps with caching different things. --------------------------------------------------------------------- --------------------------------------------------------------------- OLD Order of the operations. X Convert the axis angle milkshape rotations into quaternions. X The translations should also be converted into quaternions, X and multiplied by the rotation part. Q(Px, Py, Pz, w =0.0) X Have an absolute quaternion, and a relative one for each bone. X Quats should be seperate for the current frame that is to be rendered. X - that is the final bones for the current frame should be in a single X array. X - this is so that they may be easily converted to matrices. X Absolute matrices for the current frame should be made. X - these matrices include For each keyframe. Multiply the bones down the heirarchy. child.absolute = parent.absolute * child.relative To interpolate between two keyframes we do: t1 = current_time_in_animation - keyframe_a.time t2 = keyframe_b.time -keyframe_a.time slerp = t1/t2 frame_now = quat_slerp(keyframe_a.absolute, keyframe_b.absolute, slerp) Any time a bones rotation changes we need to recalculate all of its children. To transform verts of the mesh: We need the absolute matricies for each bone. Do we support multiple bones per vertex? If so will we use weighting? Apply a local2world transform to all of the different absolute matrices. - this should be added as a new root node. """ def __init__(self, milk_data): """ the data attribute from the milkshape converter. """ milk_bones = milk_data['bones'] self.milk_bones = milk_bones self.bone_heirarchy = BoneHeirarchy(milk_bones) self.bone_name2bone_number_map = BoneName2BoneNumber_Map(milk_bones) # for each bone we need: # - rotations. # - positions. # - scales. # - keyframe number -> time map. # - Way to get the two keyframes on either side of a given time. # these are 4 element quats. #self.rotations = N.array() # these are 3 element positions. #self.positions = N.array() def _convert_angles_to_quats(self): """ This converts the different rotations of the bones into quaternions. """ new_rdpyg/build/lib/urdpyg/__init__.py0000644000175100017510000000027210075756270020264 0ustar renerene00000000000000""" The unstable part of rdpyg. Contains modules that are not very well designed, tested, or commented, and which are not planned to be have the same api stick around for ages. """ new_rdpyg/build/lib/urdpyg/gl_images.py0000644000175100017510000000623107752432402020451 0ustar renerene00000000000000#file: images.py #purpose: everything to do with image loading. import pygame import os import time from OpenGL.GL import * try: from mygl import * except: pass def load_gl_textureRGB(name, flip = 1, internal_format = GL_RGB): """ returns a texid for the loaded image. """ if type(name) == type(""): im_surf = pygame.image.load(os.path.join("..", "data", "images", name)) else: im_surf = name image = pygame.image.tostring(im_surf, "RGB", flip) image_width = im_surf.get_width() image_height = im_surf.get_height() #TODO: add check for pow2 size. tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, tex) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glEnable(GL_TEXTURE_GEN_S) #glEnable(GL_TEXTURE_GEN_T) glTexImage2D(GL_TEXTURE_2D, 0, internal_format, image_width, image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image) return tex def load_gl_textureRGBA(name, flip = 1, internal_format = GL_RGBA): if type(name) == type(""): im_surf = pygame.image.load(os.path.join("..", "data", "images", name)) else: im_surf = name image = pygame.image.tostring(im_surf, "RGBA", flip) #print t2 - t1 image_width = im_surf.get_width() image_height = im_surf.get_height() #TODO: add check for pow2 size. tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, tex) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glEnable(GL_TEXTURE_GEN_S) #glEnable(GL_TEXTURE_GEN_T) #glTexImage2D(GL_TEXTURE_2D, 0, 3, image_width, image_height, glTexImage2D(GL_TEXTURE_2D, 0, internal_format, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) return tex new_rdpyg/build/lib/urdpyg/milkviewer4.py0000644000175100017510000000422310076013353020754 0ustar renerene00000000000000 import pygame from OpenGL.GL import * from numeric_gl import * from urdpyg.converters import ms3d_ascii_importer from urdpyg.milk_skeleton import * from urdpyg import gl_images class MilkshapeModel(MilkshapeModelLoader): """ Loads and displays a milk shape 3d model. """ def Load(self, file_name): MilkshapeModelLoader.Load(self, file_name) if self.IsTextured(): self.LoadImage(self.image_name) def LoadImage(self, filename): im_surf = pygame.image.load(filename) self.tex = gl_images.load_gl_textureRGB(im_surf) def ReloadTextures(self): """ reloads any textures. Useful when a context change happens. """ # NOTE: Shouldn't delete the texture... I think. if self.IsTextured(): self.LoadImage(self.image_name) def Display(self): """ Call this to draw. """ # set up the correct model matrix. self._StartDisplay() self._MiddleDisplay() self._FinishDisplay() def _MiddleDisplay(self): glDrawElementsui(GL_TRIANGLES, self.indices) def _StartDisplay(self): """ This is all the stuff you call before drawing. """ # bind the correct texture/s # enable the arrays for drawing. # draw the arrays. #print "points", self.points #print "texcoords", self.texcoords #print "indices", self.indices if self.IsTextured(): glEnable(GL_TEXTURE_2D) # Enables depth testing. glEnable(GL_DEPTH_TEST) # Enables smooth shading. glShadeModel(GL_SMOOTH) if self.IsTextured(): glBindTexture(GL_TEXTURE_2D, self.tex) glEnableClientState(GL_VERTEX_ARRAY) if self.IsTextured(): self._debug("is tex",4) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glVertexPointer(3, GL_FLOAT, 0, self.points) if self.IsTextured(): glTexCoordPointer(2, GL_FLOAT, 0, self.texcoords) def _FinishDisplay(self): """ Call after drawing. """ glDisableClientState(GL_VERTEX_ARRAY) if self.IsTextured(): glDisableClientState(GL_TEXTURE_COORD_ARRAY) glDisable(GL_DEPTH_TEST) if self.IsTextured(): glDisable(GL_TEXTURE_2D) new_rdpyg/build/lib/urdpyg/music.py0000644000175100017510000001255210076374352017647 0ustar renerene00000000000000# file: music.py # purpose: responsible for loading and playing music. """ """ music_events = ["game over happy", "game over sad", "game start", "using special", "close to end of game", ] # Different conditions for happy/sad music. # # 2 player, single computer. # - game over happy. # 2 player, networked, local loses. # - game over sad. # 2 player, networked, local wins. # - game over happy. # 1 player, human wins. # - game over happy # 1 player, human loses. # - game over sad. # import os, glob import pygame.mixer import pygame.mixer_music from rdpyg.util import cyclic_list import config import sound_config from rdpyg.util import vtimer class Music: """ Useage: m = Music() m.Play("intro") m.Play("bla") Need a directory ../data/music/intro.ogg """ def __init__(self): """ """ # for playing a track in 0.3 sec. self.play_timer= vtimer.vtimer(0.2, self.music_play_callback) self.fade_in_timer = vtimer.vtimer(0.2) self.fade_out_timer = vtimer.vtimer(0.2) # don't let it do a callback until finished. self.play_timer.set_finished_no_callback() self.fade_in_timer.set_finished_no_callback() self.fade_out_timer.set_finished_no_callback() self.fade_in = 0 self.fade_out = 0 self.GetFileNames() vol = config.max_music_volume self.SetMaxVol(vol) pygame.mixer.music.set_volume(vol) self.SetLoudVol(vol + 0.2) def SetLoudVol(self, vol): """ louder than max volume. this is for special occasions. """ if vol >= 1.0: self.max_loud_volume = 1.0 else: self.max_loud_volume = vol def SetMaxVol(self, vol): """ sets the maximum volume for the music. """ if vol >= 1.0: self.max_volume = 1.0 else: self.max_volume = vol def Load(self, music_type): """ music_type - one of the music types from the sound_config. """ if music_type == "intro": snd = sound_config._get_random(sound_config.music_types[music_type]) else: snd = sound_config._get_cyclic(sound_config.music_types[music_type]) pygame.mixer.music.load(self.sound_dict[snd]) def music_play_callback(self): self.Load(self.music_type) pygame.mixer.music.play(self.loop) def GetFileNames(self, path = os.path.join("..", "data", "music")): """ returns a dict of file names to be used as music. keyed by the file name without path, and .ogg. path - to the file names. """ #self.sound_list = map(lambda x:x[7:-4], glob.glob(os.path.join(path,"*.ogg")) ) self.sound_list = glob.glob(os.path.join(path,"*.ogg")) #print self.sound_list, "sound list" self.sound_dict = {} for sound in self.sound_list: file_name = os.path.split(sound)[-1] file_start = os.path.splitext(file_name)[0] self.sound_dict[file_start] = sound return self.sound_dict def Play(self, music_type, loop = -1): """ Starts playing the music. """ self.music_type = music_type self.loop = loop if pygame.mixer.music.get_busy(): # fade out the playing track, then play ours. #pygame.mixer.music.fadeout(1000) self.fade_out_timer.reset() self.fade_out = 1 # get ready to play the next song :) self.play_timer.reset() else: self.Load(music_type) pygame.mixer.music.play(self.loop) def Update(self, elapsed_time): """ To be called frequently. """ self.play_timer.Update(elapsed_time) self.fade_out_timer.Update(elapsed_time) self.fade_in_timer.Update(elapsed_time) if self.fade_out: vol = self.fade_out_timer.left_normalised() vol *= self.max_volume pygame.mixer.music.set_volume(vol) if self.fade_out_timer: # we have faded out. self.fade_out = 0 self.fade_in_timer.reset() self.fade_in = 1 if self.fade_in: vol = (1. - self.fade_in_timer.left_normalised()) vol *= self.max_volume pygame.mixer.music.set_volume(vol) if self.fade_in_timer: # we have faded in. self.fade_in = 0 if 0: if not (self.play_timer_100.just_finished or self.play_timer_1000.just_finished): if self.play_timer_1000 or self.play_timer_100: # check to see if there is any music playing if not, play it. if not pygame.mixer.music.get_busy(): self.Load(self.music_type) pygame.mixer.music.play(2) #if not pygame.mixer.music.get_busy(): # pygame.mixer.music.load(self.current) # self.Play() def Pause(self): """ pauses the music. """ pygame.mixer.music.pause() def UnPause(self): pygame.mixer.music.unpause() def Stop(self): """ """ #pygame.mixer.music.stop() pygame.mixer.music.fadeout(100) new_rdpyg/build/lib/urdpyg/some_sound.py0000644000175100017510000000633207713675013020703 0ustar renerene00000000000000""" file: some_sound.py purpose: to load all the sounds, and manage the playing of them. Probably have different sets of sounds in here somehow. """ import pygame import os import glob from pygame.locals import * def get_sound_list(): """ """ # load a list of sounds without sound/ at the beginning and .wav at the end. sound_list = map(lambda x:x[7:-4], glob.glob(os.path.join("sounds","*.wav")) ) ogg_sound_list = map(lambda x:x[7:-4], glob.glob(os.path.join("sounds","*.ogg")) ) sound_list.extend(ogg_sound_list) return sound_list class SoundManager: """ Controls loading, mixing, and playing the sounds. Having seperate classes allows different groups of sounds to be loaded, and unloaded from memory easily. """ def __init__(self): """ """ self.mixer = None self.music = None self.sounds = {} self.chans = {} self.initialized = 0 self._debug_level = 1 def _debug(self, x, debug_level = 0): """ """ if self._debug_level > debug_level: print x def Initialize(self): """ Initializes the mixer. """ global mixer, music try: import pygame.mixer pygame.mixer.init(44000, 8, 0) mixer = pygame.mixer music = pygame.mixer.music self.initialized = 1 return 1 except (ImportError, pygame.error): self.initialized= 0 self._debug("Error initializing sound.") return 0 def Load(self, names = sound_list): """Loads sounds.""" sounds = self.sounds if not mixer: for name in names: sounds[name] = None return for name in names: if not sounds.has_key(name): fullname = os.path.join('sounds', name+'.wav') try: sound = mixer.Sound(fullname) except: sound = None self._debug("Error loading sound") sounds[name] = sound def GetSound(self, name): """ Returns a Sound object for the given name. """ if not self.sounds.has_key(name): self.Load([name]) return self.sounds[name] def Play(self, name, volume=[1.0, 1.0], wait = 1): """ Plays the sound with the given name. name - of the sound. volume - left and right. Ranges 0.0 - 1.0 wait - if there is a sound of this type playing wait for it. """ vol_l, vol_r = volume sound = self.GetSound(name) if sound: if self.chans.has_key(name): c = 0 while self.chans[name].get_busy(): time.sleep(0.001) c += 1 if c > 40: break self.chans[name] = sound.play() if not self.chans[name]: self.chans[name] = pygame.mixer.find_channel(1) self.chans[name].play(sound) if self.chans[name]: self.chans[name].set_volume(vol_l, vol_r) del self.chans[name] def PlayMusic(self, musicname): """ Plays a music track. Only one can be played at a time. So if there is one playing, it will be stopped and the new one started. """ music = self.music if not music: return if music.get_busy(): #we really should fade out nicely and #wait for the end music event, for now, CUT music.stop() fullname = os.path.join('sounds', musicname) music.load(fullname) music.play(-1) music.set_volume(1.0) new_rdpyg/build/lib/urdpyg/some_sprites.py0000644000175100017510000003266607643510703021251 0ustar renerene00000000000000""" file: some_sprites.py purpose: animation, sprite playing. """ import os, os.path, glob, sys, bisect import time import pygame #import pygame.transform from pygame.locals import * DEBUG = 0 SCREENRECT = Rect(0, 0, 640, 480) try: import use_gl USE_GL = use_gl.USE_GL print "ahasjdhasjkhkjhsfd" except: USE_GL = 0 print USE_GL if USE_GL: from spritegl import SpriteGL, GroupGL pygame.sprite.Sprite = SpriteGL pygame.sprite.Group = GroupGL pygame.sprite.RenderPlain = GroupGL pygame.sprite.RenderUpdates = GroupGL #layer_order = ["walk_forwards", # "walk_left", # "walk_right", # "red background", # "transparent background"] """ layer_order = ["bam", "yellow", "red", "orange" ] """ # animations are made out of different frames from the character anim. # they have a list of frames, and a length of time for each frame. #animations = {} #a = animations #a['walk'] = [("walk_forwards", 1.0 ), # ("walk_right", 1.0), # ("walk_forwards", 1.0), # ("walk_left", 1.0), # ("walk_forwards", 1.0), # ] """ a['bam'] = [ ("orange", 0.01 ), ("red", 0.01), ("yellow", 0.01), ("orange", 0.01 ), ("red", 0.01), ("yellow", 0.01), ("orange", 0.01 ), ("red", 0.01), ("yellow", 0.01), ("bam", 0.4), ] """ def get_background_names(base_dir): """ TODO: needs fixing/testing. """ background_names = map(lambda x:x[len("background")+1:-4], glob.glob(os.path.join(base_dir, "background", "*.png")) ) background_names.extend( map(lambda x:x[len("background")+1:-4], glob.glob(os.path.join(base_dir, "background", "*.jpg")) ) ) return background_names class Timer: def __init__(self, length): """ a = Timer(10) # if the timer is finished. if a: print "asdf" """ self.Start(length) def Start(self, length): """ length is the amount of time that this timer should go for. """ self.end_time = time.time() + length def __nonzero__(self): if time.time() > self.end_time: return 1 else: return 0 def animation_factory(anim_data, loop = 1): """ Returns a dict keyed by anim_name valued by Animation instances. anim_data - keyed by anim name, valued by a list of tuples(frame_name, length). loop - passed through to Animation class. """ anims = {} for anim_name in anim_data.keys(): anims[anim_name] = Animation(anim_data[anim_name], anim_name, loop) return anims class Animation: """ For telling which of the frames should be drawn. Howto use: a = Animation(...) a.Start() if a.StillGoing(): new_frame_to_draw = a.NewFrame() if new_frame_to_draw: draw(new_frame_to_draw) else: # old frame to be rendered. pass else: # figure out what to do at end of anim. pass """ def __init__(self, animation_data, name, loop = 1): """ animation_data - a list of tuples (frame_name, time). The time part says for how long in the animation that the frame should be shown. Must have at least one element. loop - should the animation loop. If 0 the animation will return the last frame when it gets to the end. If -1 the animation will loop for ever. If non zero the animation will loop that many times. """ assert(len(animation_data) > 0) self.animation_data = animation_data self.loop = loop self.name = name self.Start() self.SetUpAnimationData(animation_data) self.last_frame = "" def Start(self, loop = 1): """ Starts the animation at the beginning. """ self.loop = loop self.start_time = time.time() self.last_frame = "" def GetName(self): return self.name def NewFrame(self): """ Returns the frame name if there is a new frame needed for the animation. Otherwise returns 0. """ frame_name = self.StillGoing() if frame_name == self.last_frame: return 0 else: return frame_name def StillGoing(self): """ returns the frame name if still going else, returns 0 if finished. """ # Add up the total length of the anim. cur_time = time.time() since_beginning = cur_time - self.start_time # do the infinity loop. if self.loop == -1: time_in_anim = since_beginning % self.GetLengthOfAnim() # no looping of anim. elif self.loop == 0: if since_beginning > self.GetLengthOfAnim(): # we are finished, so we return 0. return 0 else: time_in_anim = since_beginning # we are set to play a specific number of times. else: if since_beginning > self.loop * self.GetLengthOfAnim(): # we are finished, so we return 0. return 0 # find out where we are in the animation. time_in_anim = since_beginning % self.GetLengthOfAnim() # figure out which frame we are at. frame_name = self._GetFrameGivenTimeInAnim(time_in_anim) return frame_name def SetUpAnimationData(self, animation_data): """ Sets up the animation data ready for processing. """ self.anim_length_once = reduce(lambda x,y: x+y, map(lambda x:x[1],self.animation_data )) # set up the animation data for easy bisecting. # make a list of the animation data that holds the time that the frame starts. self.absolute_anim_data = [] total_time = 0. for frame_name, frame_length in self.animation_data: total_time += frame_length self.absolute_anim_data.append( total_time ) def _GetFrameGivenTimeInAnim(self, time_in_anim): """ Returns the frame name we should be rendering given a time in the anim. """ where_in = bisect.bisect(self.absolute_anim_data, time_in_anim) if where_in < 0: return self.animation_data[0][0] return self.animation_data[where_in][0] def GetLengthOfAnim(self): return self.anim_length_once def GetNumTimesPlayed(self): """ Returns the number of times the animation has been played. """ cur_time = time.time() return int( divmod(cur_time - self.start_time, self.anim_length_once)[0] ) def A__nonzero__(self): """ Used to see if the animation is still going. """ raise "Not implemented" def get_character_frame_names(the_layer_order, base_dir = ".."): """ returns a dict keyed by character name, valued by a dict(keyed by meaningful name, valued by image path name). """ global DEBUG character_names = filter(lambda x: os.path.isdir(os.path.join(base_dir, "characters",x)) , os.listdir(os.path.join(base_dir, 'characters'))) #print character_names character_frame_names = {} for character_name in character_names: t = glob.glob(os.path.join(base_dir, "characters", character_name, "*.gif")) t.extend( glob.glob(os.path.join(base_dir, "characters", character_name, "*.png")) ) # sort them so that they are in numerical order. # the naming scheme of gimp allows this with the normal sort func. t.sort() t.reverse() # now map the gimp file names with the meaningful names. if len(t) != len(the_layer_order): if DEBUG: print "don't have the correct number of frames for character:%s" % (character_name) print t print the_layer_order r = {} for meaning, img_path in zip(the_layer_order, t): r[meaning] = img_path character_frame_names[character_name] = r return character_frame_names def read_anim_data(character_name, base_dir = ".."): """ Reads the animation data from the characters anim.py file. """ d = {} e = {} file_name = os.path.join(base_dir, "characters",character_name , "anim.py") contents = open(file_name).read() a = compile(contents, file_name, "exec") eval(a, e, e) return [e['animations'], e['layer_order']] image_cache = {} def load_image(name, colorkey=None, convert_alpha = 0): global image_cache if image_cache.has_key(name): return [image_cache[name][0], pygame.Rect(image_cache[name][1])] try: image = pygame.image.load(name) except pygame.error, message: print 'Cannot load image:', name raise SystemExit, message if convert_alpha: image = image.convert_alpha() else: image = image.convert() if colorkey is not None: if colorkey is -1: colorkey = image.get_at((0,0)) image.set_colorkey(colorkey, RLEACCEL) image_cache[name] = (image, image.get_rect()) return image_cache[name] class A(pygame.sprite.Sprite): def __init__(self, im_name): pygame.sprite.Sprite.__init__(self) #call Sprite initializer self.image, self.rect = load_image(im_name, -1) class ImageAnimation(pygame.sprite.Sprite): def __init__(self, animation_set_name, initial_animation): """ animation_name - name of the animation set to use. """ pygame.sprite.Sprite.__init__(self) #call Sprite initializer self.animation_set_name = animation_set_name self.current_animation = initial_animation self.position = (0,0) # make self.layer_order, and self.animations self.LoadAnimationData() #character_image_dict - this is a dict keyed by # meaningful name, valued by image path name. self.character_image_dict = get_character_frame_names(self.layer_order)[animation_set_name] # load the images. self.images = {} self.LoadImages() # Make a whole heap of animation classes. self.anims = animation_factory(self.animations, loop = -1) self.StartAnim(self.current_animation) # modified_images is a dict keyed by modified type valued by # a dict of images of the frames. self.modified_images = {} self.modified_images['originals'] = self.images def StartAnim(self, anim_name, loop = 1): self.current_animation = anim_name self.anims[self.current_animation].Start(loop) new_frame_to_draw = self.anims[self.current_animation].NewFrame() if not new_frame_to_draw: raise "should be a frame here" self.image, self.rect = self.images[new_frame_to_draw] self.rect[0] = self.position[0] self.rect[1] = self.position[1] self.current_frame_name = new_frame_to_draw def SetPosition(self, position): self.position = position self.rect[0] = position[0] self.rect[1] = position[1] #print self.rect def MakeScaledVersion(self, key_name, size): """ keyname - what the scaled version should be called. eg ('really small', (0,0)) size - x,y tuple. """ self.modified_images[key_name] = {} mi = self.modified_images[key_name] for frame_name, image_rect in self.modified_images['originals'].items(): image = pygame.transform.scale(image_rect[0], size) #TODO: probably need to change the size of the rect here. r = (image_rect[1][0], image_rect[1][1], size[0], size[1]) new_rect = pygame.Rect(r) mi[frame_name] = [image, new_rect] def LoadImages(self, image_dict = {}): """ image_dict - should be a dictionary which is keyed by the frame name, and valued by an image for that frame. If the dict is {} then the images are loaded from disk. """ if image_dict == {}: for x in self.character_image_dict.keys(): self.images[x] = load_image(self.character_image_dict[x], -1, 1) else: self.images = image_dict def LoadAnimationData(self): """ """ #get_animations, get_layer_order = read_anim_data(self.animation_name) animations, layer_order = read_anim_data(self.animation_set_name) self.animations = animations self.layer_order = layer_order def move(self, direction): self.position += direction self.rect.move_ip(direction, 0) #self.rect = self.rect.clamp(SCREENRECT) def ResetImageRect(self): """ After changing the self.images dict this should be called. """ self.image, self.rect = self.images[self.current_frame_name] self.rect[0] = self.position[0] self.rect[1] = self.position[1] def SetLogicalImages(self, x_y): """ Sets the appropriate images for the place on the logical grid. """ self.images = self.modified_images[("scaled", x_y)] self.ResetImageRect() def update(self, frame_name =None, percent_trans = None): #def update(self ): """ frame_name - this is the name of the frame to draw. percent_trans - is the alpha value for which to draw If frame_name, and percent_trans are None then they are worked out for themselves. """ if frame_name != None and percent_trans != None: pass if self.anims[self.current_animation].StillGoing(): new_frame_to_draw = self.anims[self.current_animation].NewFrame() if new_frame_to_draw: self.current_frame_name = new_frame_to_draw self.image, self.rect = self.images[new_frame_to_draw] self.rect[0] = self.position[0] self.rect[1] = self.position[1] self.anims[self.current_animation].last_frame = new_frame_to_draw else: # old frame to be rendered. pass else: # figure out what to do at end of anim. pass new_rdpyg/build/lib/urdpyg/sounds.py0000644000175100017510000001257110075765413020044 0ustar renerene00000000000000""" file: sounds.py purpose: to load all the sounds, and manage the playing of them. Probably have different sets of sounds in here somehow. NOTE: not using pygames channel queueing as it only allows one sound to be queued. Also the sound can only be queued on a certain channel. """ import pygame import os import glob import time from pygame.locals import * SOUND_PATH = os.path.join("..", "data", "sounds") def get_sound_list(path = SOUND_PATH): """ gets a list of sound names without thier path, or extension. """ # load a list of sounds without path at the beginning and .ogg at the end. sound_list = map(lambda x:x[len(path)+1:-4], glob.glob(os.path.join(path,"*.ogg")) ) return sound_list SOUND_LIST = get_sound_list() class SoundManager: """ Controls loading, mixing, and playing the sounds. Having seperate classes allows different groups of sounds to be loaded, and unloaded from memory easily. Useage: sm = SoundManager() sm.Load() """ def __init__(self, sound_list = SOUND_LIST, sound_path = SOUND_PATH): """ """ self.mixer = None self.music = None self.sounds = {} self.chans = {} self._debug_level = 0 self.sound_list = sound_list self.sound_path = sound_path # sounds which are queued to play. self.queued_sounds = [] def _debug(self, x, debug_level = 0): """ """ if self._debug_level > debug_level: print x def Load(self, sound_list = [], sound_path = "."): """Loads sounds.""" sounds = self.sounds if not pygame.mixer: for name in sound_list: sounds[name] = None return for name in sound_list: if not sounds.has_key(name): fullname = os.path.join(sound_path, name+'.ogg') try: sound = pygame.mixer.Sound(fullname) except: sound = None self._debug("Error loading sound", fullname) sounds[name] = sound def GetSound(self, name): """ Returns a Sound object for the given name. """ if not self.sounds.has_key(name): self.Load([name]) return self.sounds[name] def Stop(self, name): if self.chans.has_key(name): if self.chans[name]: if self.chans[name].get_busy(): self.chans[name].stop() def StopAll(self): """ stops all sounds. """ for name in self.chans.keys(): self.Stop(name) def Play(self, name, volume=[1.0, 1.0], wait = 0, loop = 0): """ Plays the sound with the given name. name - of the sound. volume - left and right. Ranges 0.0 - 1.0 wait - used to control what happens if sound is allready playing: 0 - will not wait if sound playing. play anyway. 1 - if there is a sound of this type playing wait for it. 2 - if there is a sound of this type playing do not play again. loop - number of times to loop. -1 means forever. """ vol_l, vol_r = volume sound = self.GetSound(name) if sound: if wait in [1,2]: if self.chans.has_key(name) and self.chans[name].get_busy(): if wait == 1: # sound is allready playing we wait for it to finish. self.queued_sounds.append((name, volume, wait)) return elif wait == 2: # not going to play sound if playing. return self.chans[name] = sound.play(loop) if not self.chans[name]: if loop == 1: # forces a channel to return. we fade that out, # and enqueue our one. self.chans[name] = pygame.mixer.find_channel(1) #TODO: does this fadeout block? self.chans[name].fadeout(100) self.chans[name].queue(sound) else: # the pygame api doesn't allow you to queue a sound and # tell it to loop. So we hope for the best, and queue # the sound. self.queued_sounds.append((name, volume, wait)) # delete the None channel here. del self.chans[name] elif self.chans[name]: self.chans[name].set_volume(vol_l, vol_r) def Update(self, elapsed_time): """ """ for name in self.chans.keys(): if not self.chans[name]: # it may be a NoneType I think. del self.chans[name] elif not self.chans[name].get_busy(): del self.chans[name] old_queued = self.queued_sounds self.queued_sounds = [] for snd_info in old_queued: self.Play(*snd_info) def PlayMusic(self, musicname): """ Plays a music track. Only one can be played at a time. So if there is one playing, it will be stopped and the new one started. """ music = self.music if not music: return if music.get_busy(): #we really should fade out nicely and #wait for the end music event, for now, CUT music.stop() fullname = os.path.join('sounds', musicname) music.load(fullname) music.play(-1) music.set_volume(1.0) new_rdpyg/docs/0000755000175100017510000000000010160167715013716 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/0000755000175100017510000000000010160166530015035 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/0000755000175100017510000000000010160167334016165 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/app/0000755000175100017510000000000010160166530016742 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/app/the_app/0000755000175100017510000000000010160166530020362 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/app/the_app/TheApp.html0000644000175100017510000004017510160167714022445 0ustar renerene00000000000000 Class: TheApp

Table of Contents

Class: TheApp rdpyg/app/the_app.py

An application class to handle lots of common things within games, and game like applications, using pygame.

A lot of the methods are meant to be overrided. However they all come with sane default implementations.

Useage: a = TheApp()

  1. Start() a.Loop() a.Stop()

Methods   
Display
DoAfterFlip
DoBeforeDisplay
DoBeforeHandlingEvents
GetFps
HandleEvents
InitDisplay
Load
Loop
LoopInit
OneTic
SetupTiming
Start
Stop
TicTiming
Update
__init__
_debug
  Display 
Display ( self )

This is called before the display is flipped(or updated). Your drawing code should go in here.

  DoAfterFlip 
DoAfterFlip ( self )

Called after flip is done.

  DoBeforeDisplay 
DoBeforeDisplay ( self )

Stuff done before Display() is called.

  DoBeforeHandlingEvents 
DoBeforeHandlingEvents ( self )

Stuff done before we handle the events. Should return 0 to quit.

  GetFps 
GetFps ( self )

Returns the frames per second since the timing has begun.

  HandleEvents 
HandleEvents ( self,  event_list )

should handle the events every game tic.

  InitDisplay 
InitDisplay (
        self,
        width,
        height,
        first_time=0,
        )

A default InitDisplay. first_time - useful for working around some buggy systems. make it true if this is the first time calling it.

Exceptions   
ValueError( "error initializing display, can not get mode" )
  Load 
Load ( self )

For loading stuff.

  Loop 
Loop ( self )

Starts the game looping. Will eventually return.

  LoopInit 
LoopInit ( self )

Should put use loop initialisation stuff here.

  OneTic 
OneTic ( self )

Does one game tic worth of stuff. Should return 1 if not wanting to quit. If wanting to quit return 0.

  SetupTiming 
SetupTiming ( self )

Sets up some timing code.

  Start 
Start ( self )

Do the game loading.

  Stop 
Stop ( self )

Called when we want to stop.

  TicTiming 
TicTiming ( self )

Call this once per tic to update the timing.

  Update 
Update ( self,  elapsed_time )

update any game state.

  __init__ 
__init__ ( self,  debug_level=0 )

  _debug 
_debug (
        self,
        x,
        debug_level=0,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/app/the_app_gl/0000755000175100017510000000000010160166530021044 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/app/the_app_gl/TheAppGL.html0000644000175100017510000001607610160167714023355 0ustar renerene00000000000000 Class: TheAppGL

Table of Contents

Class: TheAppGL rdpyg/app/the_app_gl.py
Base Classes   
the_app.TheApp
Methods   
Display
GetWorldCoords
InitDisplay
SetupProjection
Start
  Display 
Display ( self )

A default display. Which clears the color buffer and depth buffer.

  GetWorldCoords 
GetWorldCoords (
        self,
        x,
        y,
        camera_z,
        )

returns (x,y,z) given x,y pygame screen coords. NOTE: try and get the model view matrix back to the camera position when using.

  InitDisplay 
InitDisplay (
        self,
        width,
        height,
        first_time=0,
        )

A default InitDisplay.

Exceptions   
ValueError( "error initializing display, can not get mode" )
  SetupProjection 
SetupProjection (
        self,
        width=640,
        height=480,
        zNear=5.,
        zFar=300.,
        )

Sets up the projection matrix for opengl.

  Start 
Start ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/app/__init__.html0000644000175100017510000000244610160167714021402 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/app/__init__.py

Common functionality for applications.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/app/index.html0000644000175100017510000000471710160167714020755 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.app

Table of Contents

HappyDoc Generated Documentation: rdpyg.app  

Common functionality for applications.

Modules and Packages   

rdpyg/app/

app

Common functionality for applications.

the_app

TheApp is a class for making a game like application, implementing

the_app_gl


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/app/the_app.html0000644000175100017510000001135510160167714021262 0ustar renerene00000000000000 Module: the_app

Table of Contents

Module: the_app rdpyg/app/the_app.py

TheApp is a class for making a game like application, implementing functionality common in many games. The idea is to make constructing games and demos quick, with minimal code.

TODO: a way to chose between display flip and update. without overriding the whole method.

There are a number of different methods with default implementations to save work. Most of these can be overridden if you need to specialise any parts.

= How the main loop works. =

TheApp class has a couple of different ways which it handles the main loop internally. It can use a while loop or the twisted reactor.

However by using the methods provided you should not have to modify this.

It can be instructional to have at a look at the source for different methods, so that overriding them can be easy.

This is the 2d pygame version of the class. There is an opengl version named rdpyg.app.the_app_gl.TheAppGL

= Commonly overridden methods =

  • Display Your drawing code. Update Updating your game logic, game play, and game ai. HandleEvents Code to handle user input, operating system interaction, and other events. Load * Code to load your game data. Like images, sounds etc.

= Order of operation =

The order in which the different methods get called is to update your game objects, handle user input, do your display changes.

Start() InitDislpay() Load()

Loop() Before loops starts looping: LoopInit() SetupTiming() Every tic or frame of loop: Update() HandleEvents() DoBeforeDisplay() Display() DoAfterFlip()

Imported modules   
import pygame
from pygame.locals import DOUBLEBUF, OPENGL, FULLSCREEN, QUIT, KEYDOWN, K_ESCAPE
import sys
import time
import traceback
Classes   

TheApp

An application class to handle lots of common things within games, and


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/app/the_app_gl.html0000644000175100017510000000611410160167714021741 0ustar renerene00000000000000 Module: the_app_gl

Table of Contents

Module: the_app_gl rdpyg/app/the_app_gl.py
Imported modules   
from OpenGL.GL import glMatrixMode, GL_PROJECTION, glLoadIdentity, glClearColor, glClear, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, glGetFloatv, GL_PROJECTION_MATRIX, GL_MODELVIEW, glViewport, glGetDoublev, GL_MODELVIEW_MATRIX
from OpenGL.GLU import gluPerspective, gluUnProject
import pygame
from pygame.locals import DOUBLEBUF, OPENGL, FULLSCREEN, QUIT, KEYDOWN, K_ESCAPE
import the_app
Classes   

TheAppGL


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/0000755000175100017510000000000010160166530017117 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/draw/pygame/0000755000175100017510000000000010160166530020401 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/draw/pygame/__init__.html0000644000175100017510000000240510160167714023034 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/draw/pygame/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pygame/index.html0000644000175100017510000000411110160167714022400 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.draw.pygame

Table of Contents

HappyDoc Generated Documentation: rdpyg.draw.pygame  
Modules and Packages   

rdpyg/draw/pygame/

pygame


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/0000755000175100017510000000000010160166530020754 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/particles/0000755000175100017510000000000010160166530022742 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/particles/cached_random.html0000644000175100017510000000770710160167714026417 0ustar renerene00000000000000 Class: cached_random

Table of Contents

Class: cached_random rdpyg/draw/pyopengl/particles.py

def __init__(self, size_of_cache = 500): self.size_of_cache = size_of_cache

Methods   
GetRandom100
GetRandom30
GetRandom60
  GetRandom100 
GetRandom100 ( self )

  GetRandom30 
GetRandom30 ( self )

  GetRandom60 
GetRandom60 ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/particles/Particle.html0000644000175100017510000000476410160167714025413 0ustar renerene00000000000000 Class: Particle

Table of Contents

Class: Particle rdpyg/draw/pyopengl/particles.py
Methods   
__init__
  __init__ 
__init__ ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/particles/Particles.html0000644000175100017510000002203210160167714025562 0ustar renerene00000000000000 Class: Particles

Table of Contents

Class: Particles rdpyg/draw/pyopengl/particles.py

This is a set of particles baby.

Methods   
Display
DisplayStateBegin
DisplayStateEnd
InitParticles
Load
LoadImagePng
MakeTexture
Update
__init__
_debug
  Display 
Display ( self )

A default display. Which clears the color buffer and depth buffer.

  DisplayStateBegin 
DisplayStateBegin ( self )

  DisplayStateEnd 
DisplayStateEnd ( self )

  InitParticles 
InitParticles ( self )

  Load 
Load (
        self,
        with_tex=None,
        file_name=None,
        )

with_tex can be an opengl texture.

  LoadImagePng 
LoadImagePng ( self,  filename )

  MakeTexture 
MakeTexture ( self )

return

  Update 
Update ( self,  elapsed_time )

TODO:

  __init__ 
__init__ ( self,  num_particles )

  _debug 
_debug (
        self,
        s,
        x,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/__init__.html0000644000175100017510000000240710160167714023411 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/draw/pyopengl/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/index.html0000644000175100017510000000450310160167714022760 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.draw.pyopengl

Table of Contents

HappyDoc Generated Documentation: rdpyg.draw.pyopengl  
Modules and Packages   

rdpyg/draw/pyopengl/

pyopengl

particles

paths


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/particles.html0000644000175100017510000000661510160167714023645 0ustar renerene00000000000000 Module: particles

Table of Contents

Module: particles rdpyg/draw/pyopengl/particles.py
Imported modules   
from OpenGL.GL import *
import os
import pygame
import pygame.image
import random
from random import randint
Classes   

Particle

Particles

This is a set of particles baby.

cached_random

def __init__(self, size_of_cache = 500):


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/pyopengl/paths.html0000644000175100017510000001023610160167714022770 0ustar renerene00000000000000 Module: paths

Table of Contents

Module: paths rdpyg/draw/pyopengl/paths.py
Imported modules   
from OpenGL.GL import glBegin, GL_LINES, glVertex3f, glEnd, glPushAttrib, GL_ALL_ATTRIB_BITS, glMatrixMode, GL_MODELVIEW, glLoadIdentity, glScale, glTranslatef, glPopAttrib
from OpenGL.GLUT import glutSolidTeapot
Functions   
draw_path
draw_path_with_traveler
  draw_path 
draw_path ( a_path )

draws a path with opengl lines.

  draw_path_with_traveler 
draw_path_with_traveler ( a_path )

draws a box where the position of the traveler is on the path.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/__init__.html0000644000175100017510000000237010160167714021553 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/draw/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/draw/index.html0000644000175100017510000000465210160167714021130 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.draw

Table of Contents

HappyDoc Generated Documentation: rdpyg.draw  
Modules and Packages   

rdpyg/draw/

draw

pygame

HappyDoc Generated Documentation: rdpyg.draw.pygame

pyopengl

HappyDoc Generated Documentation: rdpyg.draw.pyopengl


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/ifconfig_networking/0000755000175100017510000000000010160166531022216 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/ifconfig_networking/IfConfigFreeBSD.html0000644000175100017510000000754310160167034025733 0ustar renerene00000000000000 Class: IfConfigFreeBSD

Table of Contents

Class: IfConfigFreeBSD rdpyg/net/ifconfig_networking.py
Methods   
_read_ifconfig
get_info
  _read_ifconfig 
_read_ifconfig ( self )

  get_info 
get_info ( self )

Exceptions   
NotImplementedError

Table of Contents

This document was automatically generated on Thu Dec 16 13:08:26 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/ifconfig_networking/IfConfigLinux.html0000644000175100017510000000755710160167034025625 0ustar renerene00000000000000 Class: IfConfigLinux

Table of Contents

Class: IfConfigLinux rdpyg/net/ifconfig_networking.py
Methods   
_read_ipconfig
get_info
get_ips
  _read_ipconfig 
_read_ipconfig ( self )

  get_info 
get_info ( self,  the_output=None )

  get_ips 
get_ips ( self,  the_output=None )


Table of Contents

This document was automatically generated on Thu Dec 16 13:08:26 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/ifconfig_networking/IfConfigWindows.html0000644000175100017510000001247310160167034026151 0ustar renerene00000000000000 Class: IfConfigWindows

Table of Contents

Class: IfConfigWindows rdpyg/net/ifconfig_networking.py
Methods   
_read_ipconfig
get_default_gateways
get_info
get_ips
get_subnet_masks
  _read_ipconfig 
_read_ipconfig ( self )

  get_default_gateways 
get_default_gateways ( self,  the_output=None )

  get_info 
get_info ( self,  the_output=None )

  get_ips 
get_ips ( self,  the_output=None )

  get_subnet_masks 
get_subnet_masks ( self,  the_output=None )


Table of Contents

This document was automatically generated on Thu Dec 16 13:08:26 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/map/0000755000175100017510000000000010160166530016737 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/map/__init__.html0000644000175100017510000000236710160167334021377 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/map/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:11:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/map/index.html0000644000175100017510000000427310160167334020745 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.map

Table of Contents

HappyDoc Generated Documentation: rdpyg.map  
Modules and Packages   

rdpyg/map/

map

map

= Features wanted =


Table of Contents

This document was automatically generated on Thu Dec 16 13:11:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/map/map.html0000644000175100017510000001605710160167334020416 0ustar renerene00000000000000 Module: map

Table of Contents

Module: map rdpyg/map/map.py

= Features wanted = When not moving it can take only update parts of the screen. update(dirty_rects) can be used to speed up drawing. by only updating areas which are dirty. if the map is not moving we can make it lots speedier.

  • Offscreen buffer. Blit all smaller tiles to an offscreen buffer then blit one big image to the screen. This can be faster on some screens/computers. Different tile sizes. different sizes on the same map. Join maps together easily. Different drawable sizes. Ie different camera views. Be able to be used with pygame or pyopengl. Different camera modes: jump scrolling, jump the map in blocks. Like ten pixels at a time. smooth scrolling, every pixel the camera moves the tiles move. smooth-jump scrolling. Mostly the screen stays still. When the character nears the edge everything stops moving while the maps scrolls over a little way. centered camera. Can center the camera on Looping Map Edges Paralax scrolling. Moving layers at different speeds. Multiple views of the map. * miniview of the map. Perhaps using a scaled version or one pixel per tile.

  • minimize overdraw. using dirty rectangles. for alpha images precalculate full rects. That is like a bounding box in the middle where the area is full. think about using a coverage buffer. * animated tiles will probably always need to be redrawn(unless it's the same frame).

  • Overlapping tiles. As well as overlapping whole maps. For joining maps together. Layers/Z ordering. draw characters by descending y value on same layer. for certain types of games: see for explanation: * http://www.gamedev.net/reference/programming/features/gpgenesis9/page7.asp

  • line of sight tests between tiles and pixels/rects. collision detection between tiles and pixels/rects. some tiles may be pass through. * tiles on different layers may be collidable, others not.

  • fog of war. * darkening/lightening of areas.

  • Rotatable tiles. * scalable tiles? Other transforms needed?

  • Easy layer toggling. * So eg when you go inside a building the roof comes off and you can see inside.

= Implementation ideas =

  • Use pygame sprites and sprite groups. could then reuse lots of code... optimize in one place. Speed development. think of camera movement as simply moving a sprite group in a certain way.

  • Use a quad tree for the collision detection. * Could use it for moving, and non moving.

  • Left to right, or top to bottom scrollers can be optimized in different ways.

= Some map editors =

The tile combie(or engine if you want) should have most of the features that these map editors contain.

http://tilestudio.sourceforge.net/

http://www.tilemap.co.uk/

= A discussion about features =

<geoffh> background tiling, layers, collision detection between layers and stuff (rect and pixel) <geoffh> paralax scrolling <geoffh> animation of background/sprites <geoffh> line of sight tests between tiles and pixels <geoffh> based on layer compositions and such <illumeh> eek, that's a lot of stuff <illumeh> good stuff :) <geoffh> separate environmental and UI layer systems <illumeh> what do you mean? <geoffh> so you can draw your UI without worrying how height your environments layers are <geoffh> the UI layers are alwayrs on top <illumeh> ah, cool <geoffh> basically, just 2 lists for heights <geoffh> auto-shadowing for sprites is good <illumeh> indeed, that'd be cool <geoffh> doing like angled skews on the images, and drawing them on the ground layer <geoffh> so you dont have to have separate shadow images for them <illumeh> nice <geoffh> or just auto positioning the same image, but based on heigth of the sprite

<geoffh> so like a flying ship has its shadow in the real place, and its in its height-adjusted place, like zaxxon <geoffh> which basically just means you have a transformation for height built in, and use a sort of worrld coords and translated drawing coords <illumeh> aah <geoffh> which makes sense <geoffh> so you should have parameters to what your viewing perspective is, so they can adjust it based on how their art is rendered <geoffh> like: 1.5:1.0 or something

<geoffh> you could also have layer toggling like i did in VT, where if you go into a building, it switches what the background tiles are. and if you change floors, it also does that <illumeh> ah, that sounds nice too <geoffh> but that may be a bit specific. though, you could make the design so its possible to rotate through BG tile maps specifically, like theyre layered and do a fall through if the current selected one doesnt exist <geoffh> to the default background map, which has all its spaces mapped <geoffh> sorta an "optional current level background" <geoffh> good for things where people take stairs, and you still want the ground of things outside buildings and such <geoffh> im running out of stuff ive thought about for tiling engines <illumeh> hehe. that's all stuff I didn't think about :) <geoffh> i want to retire <geoffh> im pretty happy doing fuck all all the time now <geoffh> heh <illumeh> having layers greyed out would be good <illumeh> hehe. mostly I'm happy doing fuck all too :) <geoffh> optional layers? or you mean something else?


Table of Contents

This document was automatically generated on Thu Dec 16 13:11:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/net/0000755000175100017510000000000010160167334016753 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/net/ifconfig_networking/0000755000175100017510000000000010160167334023006 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/net/ifconfig_networking/IfConfigFreeBSD.html0000644000175100017510000000755110160167714026525 0ustar renerene00000000000000 Class: IfConfigFreeBSD

Table of Contents

Class: IfConfigFreeBSD rdpyg/net/ifconfig_networking.py
Methods   
_read_ifconfig
get_info
  _read_ifconfig 
_read_ifconfig ( self )

  get_info 
get_info ( self )

Exceptions   
NotImplementedError

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/net/ifconfig_networking/IfConfigLinux.html0000644000175100017510000000756510160167714026417 0ustar renerene00000000000000 Class: IfConfigLinux

Table of Contents

Class: IfConfigLinux rdpyg/net/ifconfig_networking.py
Methods   
_read_ipconfig
get_info
get_ips
  _read_ipconfig 
_read_ipconfig ( self )

  get_info 
get_info ( self,  the_output=None )

  get_ips 
get_ips ( self,  the_output=None )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/net/ifconfig_networking/IfConfigWindows.html0000644000175100017510000001250110160167714026734 0ustar renerene00000000000000 Class: IfConfigWindows

Table of Contents

Class: IfConfigWindows rdpyg/net/ifconfig_networking.py
Methods   
_read_ipconfig
get_default_gateways
get_info
get_ips
get_subnet_masks
  _read_ipconfig 
_read_ipconfig ( self )

  get_default_gateways 
get_default_gateways ( self,  the_output=None )

  get_info 
get_info ( self,  the_output=None )

  get_ips 
get_ips ( self,  the_output=None )

  get_subnet_masks 
get_subnet_masks ( self,  the_output=None )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/net/ifconfig_networking.html0000644000175100017510000001103410160167714023675 0ustar renerene00000000000000 Module: ifconfig_networking

Table of Contents

Module: ifconfig_networking rdpyg/net/ifconfig_networking.py
Imported modules   
import os
import platform
import re
import sys
Functions   
IfConfig
  IfConfig 
IfConfig ()

Classes   

IfConfigFreeBSD

IfConfigLinux

IfConfigWindows


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/net/__init__.html0000644000175100017510000000243110160167714021402 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/net/__init__.py

networking related stuff.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/net/index.html0000644000175100017510000000440310160167714020753 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.net

Table of Contents

HappyDoc Generated Documentation: rdpyg.net  

networking related stuff.

Modules and Packages   

rdpyg/net/

net

networking related stuff.

ifconfig_networking


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/sprites/0000755000175100017510000000000010160166530017653 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/sprites/spritegl/0000755000175100017510000000000010160166530021504 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/sprites/spritegl/ScreenGL.html0000644000175100017510000001723410160167715024051 0ustar renerene00000000000000 Class: ScreenGL

Table of Contents

Class: ScreenGL rdpyg/sprites/spritegl.py

TODO: - Fill in missing functions. - Work correctly when screen size changes. - only update the texture when blitting. - An optimization might be to not update the texture until the screen has been flipped, or updated. - This could work quite nicely with RenderUpdates :)

Methods   
__init__
blit
fill
get_clip
get_flags
get_rect
get_size
set_clip
  __init__ 
__init__ ( self,  screen )

  blit 
blit ( self,  *args )

meant as a replacement for screen.blit You really should consider making your background a seperate Sprite, and Group. useage: gl_screen_blit

  fill 
fill ( self,  *args )

  get_clip 
get_clip ( self,  *args )

  get_flags 
get_flags ( self,  *args )

  get_rect 
get_rect ( self,  *args )

  get_size 
get_size ( self,  *args )

  set_clip 
set_clip ( self,  *args )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/sprites/spritegl/GroupGL.html0000644000175100017510000002100310160167714023712 0ustar renerene00000000000000 Class: GroupGL

Table of Contents

Class: GroupGL rdpyg/sprites/spritegl.py
Base Classes   
pygame.sprite.Group
Methods   
FitSpritesOnTextures
MakeTextures
draw
draw_gl
load_2d_projection
set_up_2d_projection
setup_draw_texture
un_setup_draw_texture
  FitSpritesOnTextures 
FitSpritesOnTextures ( self )

  MakeTextures 
MakeTextures ( self )

For all of the sprites in this group we will make textures for them.

  draw 
draw ( self,  surface )

supposed to draw to the given surface. Problem is it is an opengl screen. so we get the size of it, and draw to the screen.

  draw_gl 
draw_gl ( self,  spr )

Assumes glMatrixMode( GL_MODELVIEW )

  load_2d_projection 
load_2d_projection ( self )

  set_up_2d_projection 
set_up_2d_projection ( self,  a_rect )

a_rect - the area to set up the projection for.

  setup_draw_texture 
setup_draw_texture ( self,  screen_rect )

Sets up opengl for drawing the textures.

  un_setup_draw_texture 
un_setup_draw_texture ( self )

resets the opengl state to what it was before drawing.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/sprites/spritegl/SpriteGL.html0000644000175100017510000001516510160167715024101 0ustar renerene00000000000000 Class: SpriteGL

Table of Contents

Class: SpriteGL rdpyg/sprites/spritegl.py

A sprite class which uses opengl. Should be able to use it in the place of the pygame sprite class.

Base Classes   
pygame.sprite.Sprite
Methods   
DeleteTexture
LoadImage
MakeTexture
load_del_make
update
  DeleteTexture 
DeleteTexture ( self )

  LoadImage 
LoadImage ( self )

Exceptions   
"problem here"
  MakeTexture 
MakeTexture ( self )

  load_del_make 
load_del_make ( self )

  update 
update ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/sprites/spritegl/SurfaceGL.html0000644000175100017510000001524210160167715024217 0ustar renerene00000000000000 Class: SurfaceGL

Table of Contents

Class: SurfaceGL rdpyg/sprites/spritegl.py

This is useful for tracking changes in a surface. It takes a surface as a keyword initializer: eg s = SurfaceGL(initialize_with_this = a_surf) Or you can initialize it like a normal surface.

Once the pixel data is changed, either is_dirty will be true, or changed_rects will not be empty. If is_dirty is true: then the whole image needs to be updated. Else: if changed_rects is not empty: update the rects which have been changed.

class SurfaceGL(pygame.old_Surface):

Methods   
__getattr__
__init__
__setattr__
blit
fill
  __getattr__ 
__getattr__ ( self,  name )

Exceptions   
AttributeError( name )
  __init__ 
__init__ (
        self,
        *args,
        *kwargs,
        )

  __setattr__ 
__setattr__ (
        self,
        name,
        value,
        )

  blit 
blit ( self,  *args )

TODO: needs to keep track of which parts have been changed. For now marking the whole image as dirty.

  fill 
fill ( self,  *args )

like a normal surface fill, but marks the thing as dirty.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/sprites/__init__.html0000644000175100017510000000237310160167714022312 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/sprites/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/sprites/index.html0000644000175100017510000000441510160167715021662 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.sprites

Table of Contents

HappyDoc Generated Documentation: rdpyg.sprites  
Modules and Packages   

rdpyg/sprites/

sprites

spritegl

Opengl drawing of pygame.sprite objects. With hopefully minimal/no changes


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/sprites/spritegl.html0000644000175100017510000002763510160167715022415 0ustar renerene00000000000000 Module: spritegl

Table of Contents

Module: spritegl rdpyg/sprites/spritegl.py

Opengl drawing of pygame.sprite objects. With hopefully minimal/no changes to programs, and big speed increases.

Rene Dudfield. illumen@yahoo.com

TODO:

First compatibilty, optimization, then next gen.

NOTE: there are some more TODO's sprinkled througout the code

Compatibilty. - need to implement all of screens methods.

  • test on more games. - chimp(works).

    • pyddr(doesn't work). - I think it has to do with the different format images. - I think a conversion may not be working properly.

    • bleten(works). - works, but is kinda slow when lots of images change. - need to work on a scaling method which uses opengl. - need to not use tostring() for making textures(slow). - work on caching some more, so that there is a texture cache as well. - so that images don't need to be uploaded to the card all the time.

    • yass(don't know).

  • a better way to detect when an images contents have changed. - probably a wrapper around surface, and surfarray which marks the image as dirty. - split sprites larger than 256x256 into multiple smaller textures. - for some older 3d cards. - should figure out how to detect max texture size.

  • support 8 and 16 bit and color keyed textures. - Make sure textures are cleaned up correctly in all cases. - Beta test on a wide number of machines.

  • Make it work correctly when the screen size changes.

Optimization.

  • Put multiple sprites onto the same texture, and use uv coords for drawing particular sprites. This is a big optimization. - especially for animation.

  • move all texture management into the group, so as to optimize texture drawing more easily.

  • Have a set max number of textures to use in a texture cache. - Cache textures

  • optimize the screen.blit function, and some others: - with blit, only update a certain part of the texture which was actually blitted. - screen.fill

  • Group drawing by the same texture(less texture binds). - Try display lists to see if better performing. - try vertex buffers for better performance. - Make 1000+ sprite test case, and optimize for this case. - Update texture instead of replacing it when: - some pixels change in an image. - when the image changes and the old one isn't to be used anymore. - How to know this?

Next gen. - Add scaling, rotation, other effects to a sprite class. - use caching of images for sdl, and straight opengl calls(eg glRotate etc). - shadows from sprites onto the background. - Make classes/optimize existing classes for drawing: - scrollers, tile maps, height maps, - 3d animated characters (http://www.py3d.org/py3d_zwiki/milkshape3d_animation) - doomIII clone ;)

Imported modules   
from OpenGL.GL import *
from OpenGL.GLU import *
import os
import pygame
from pygame.locals import *
from rdpyg.util import pack_textures
import time
Functions   
gl_display_get_surface
gl_display_set_mode
gl_display_update
gl_draw_line
gl_transform_scale
nextPower
printw
  gl_display_get_surface 
gl_display_get_surface ()

  gl_display_set_mode 
gl_display_set_mode ( *args )

TODO: Add check to see if a GL screen is infact being requested.

  gl_display_update 
gl_display_update ( *args )

  gl_draw_line 
gl_draw_line ( *args )

  gl_transform_scale 
gl_transform_scale ( *args,  *kwargs )

  nextPower 
nextPower ( x )

  printw 
printw ( *args )

Classes   

GroupGL

ScreenGL

TODO:

SpriteGL

A sprite class which uses opengl.

SurfaceGL

This is useful for tracking changes in a surface.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/0000755000175100017510000000000010160166531017140 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/util/cyclic_list/0000755000175100017510000000000010160166530021440 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/util/cyclic_list/cyclic_list.html0000644000175100017510000001376010160167715024644 0ustar renerene00000000000000 Class: cyclic_list

Table of Contents

Class: cyclic_list rdpyg/util/cyclic_list.py
Base Classes   
UserList.UserList
Methods   
__init__
cur
next
prev
set_cur
  __init__ 
__init__ (
        self,
        *args,
        *kwargs,
        )

  cur 
cur ( self )

returns the element at the current cursor.

  next 
next ( self )

increments the cursor, and returns the new current idx.

  prev 
prev ( self )

decrements the cursor, and returns the new current idx.

  set_cur 
set_cur ( self,  idx )

Sets the current cursor to the given idx.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/pack_textures/0000755000175100017510000000000010160166531022021 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/util/pack_textures/Texture.html0000644000175100017510000002351210160167715024357 0ustar renerene00000000000000 Class: Texture

Table of Contents

Class: Texture rdpyg/util/pack_textures.py

One texture which holds multiple smaller ones packed in.

x,y bottom left is 0,0. Which is like opengl, and not like sdl.

Methods   
__init__
__repr__
_bottom_left_first
_brute_force
clear
collide
could_fit
search_for_fit
try_fit
try_fit_batch
  __init__ 
__init__ (
        self,
        x,
        y,
        height,
        width,
        )

  __repr__ 
__repr__ ( self )

  _bottom_left_first 
_bottom_left_first ( self,  o )

do a search from bottom left. Return True if successful, else false. o - other texture.

  _brute_force 
_brute_force ( self,  o )

do a brute force search from bottom left to top right. Return True if successful, else false. o - other texture.

  clear 
clear ( self )

clears all the textures in this one.

  collide 
collide ( self,  other_texture )

checks this texture only to see if it collides. Returns True if it does collide.

  could_fit 
could_fit ( self,  other_texture )

checks this texture only to see if it fits. Does not care about any textures inside.

  search_for_fit 
search_for_fit ( self,  o )

do a search for a place to put the texture, and place it. Return True if successful, else false. o - other texture.

  try_fit 
try_fit ( self,  other_texture )

Tries to fit the texture into itself. Returns true if successful.

  try_fit_batch 
try_fit_batch ( self,  other_textures )

Tries to fit the textures into itself. Returns true if successful???. Or returns the unfitted ones?


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/paths/0000755000175100017510000000000010160166531020257 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/util/paths/Path.html0000644000175100017510000003646610160167715022065 0ustar renerene00000000000000 Class: Path

Table of Contents

Class: Path rdpyg/util/paths.py

Used for storing the path from one point to another. For working out where an object following that path at a certain speed would be.

p = Path() p.SetPoints([[0., 0., 0.], [0., 1., 0.], [1., 1., 0.], [2., 2., 0.], [3., 3., 0.]])

This creates a path of straight lines.

Now whatever is traveling along the path can use:

point_along_path = p.Travel(speed=0.5, elapsed_time=5)

Which will travel along the path 0.5 * 5 units, and give you the point where it is up to.

Methods   
GetBackwardsPoint
GetHeadingToPoint
GotoNextLine
SetLoopType
SetNewPoint
SetPoints
ShouldStop
Travel
Where
__eq__
__init__
__ne__
__str__
length
  GetBackwardsPoint 
GetBackwardsPoint ( self,  distance )

GetBackwardsPoint(distance) -> position Returns a point backwards from the current direction along the path. distance - backwards along the path.

  GetHeadingToPoint 
GetHeadingToPoint ( self )

GetHeadingToPoint() -> position Returns the point which the traveler is heading to.

  GotoNextLine 
GotoNextLine ( self )

GotoNextLine() -> None Starts heading to the next line in path.

  SetLoopType 
SetLoopType ( self,  loop_type )

SetLoopType("stop") -> None

Can be set to one of LOOP_TYPES, ["stop", "loop", "backwards"]

Exceptions   
NotImplementedError, loop_type
  SetNewPoint 
SetNewPoint ( self,  point )

SetNewPoint([x,y,z]) -> None Sets the current point that the traveller is on.

  SetPoints 
SetPoints ( self,  point_list )

SetPoints(point_list) -> None

Sets the points along the path. point_list - eg [[1., 1., 1.], [2., 2., 2.]] With each sublist being a point (x,y,z) in 3d space.

  ShouldStop 
ShouldStop ( self )

ShouldStop() -> Bool Are we at the end and is the loop_type "stop"

  Travel 
Travel (
        self,
        speed,
        elapsed_time,
        )

Travel(float, float) -> position Returns the point along the path that the traveler is at. speed - units per second. Average since the last call to this. elapsed_time - since the last call to this.

Exceptions   
RuntimeError( "too many iterations trying to find new place on path" )
  Where 
Where ( self )

Where() -> position. Returns the current position of the traveler.

  __eq__ 
__eq__ ( self,  other )

print self.points == other.points print self.elapsed_time == other.elapsed_time print self.loop_type == other.loop_type print self.current_point == other.current_point print self.current_heading_to_idx == other.current_heading_to_idx print self.current_idx == other.current_idx

  __init__ 
__init__ (
        self,
        points=[],
        loop_type="stop",
        )

points - defaults to []. should be like [[0.,0.,0.],[0.,1.,0.]]

  __ne__ 
__ne__ ( self,  other )

  __str__ 
__str__ ( self )

  length 
length ( self )

length() -> length of the path. TODO: why isn't this __len__() ?


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/quaternion/0000755000175100017510000000000010160166531021325 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/util/quaternion/Quaternion.html0000644000175100017510000002435210160167715024353 0ustar renerene00000000000000 Class: Quaternion

Table of Contents

Class: Quaternion rdpyg/util/quaternion.py

Quaternion object implementing those methods required to be useful for OpenGL rendering (and not many others)

Methods   
AXYZ
XYZR
__getitem__
__init__
__len__
__mul__
__neg__
__repr__
delta
matrix
  AXYZ 
AXYZ ( self )

returns the angle, and x,y,z as a vector. as used by glRotate.

  XYZR 
XYZR ( self )

Get a VRML-style axis plus rotation form of the rotation. Note that this is in radians, not degrees, and that the angle is the last, not the first item... (x,y,z,radians)

  __getitem__ 
__getitem__ ( self,  x )

  __init__ 
__init__ ( self,  elements=[ 1, 0, 0, 0 ] )

The initializer is a four-element array,

w, x,y,z
all elements should be doubles/floats the default values are those for a unit multiplication quaternion.
  __len__ 
__len__ ( self )

  __mul__ 
__mul__ ( self,  other )

Multiply this quaternion by another quaternion, generating a new quaternion which is the combination of the rotations represented by the two source quaternions.

Other is interpreted as taking place within the coordinate space defined by this quaternion.

Alternately, if "other" is a matrix, return the dot-product of that matrix with our matrix (i.e. rotate the coordinate)

  __neg__ 
__neg__ ( self )

  __repr__ 
__repr__ ( self )

Return a human-friendly representation of the quaternion

Currently this representation is as an axis plus rotation (in radians)

  delta 
delta ( self,  other )

Return the angle in radians between this quaternion and another.

Return value is a positive angle in the range 0-pi representing the minimum angle between the two quaternion rotations.

From code by Halldor Fannar on the 3D game development algos list

  matrix 
matrix ( self )

Get a rotation matrix representing this rotation


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/vtimer/0000755000175100017510000000000010160166531020446 5ustar renerene00000000000000new_rdpyg/docs/rdpyg/rdpyg/util/vtimer/vtimer.html0000644000175100017510000002454610160167715022662 0ustar renerene00000000000000 Class: vtimer

Table of Contents

Class: vtimer rdpyg/util/vtimer.py

times something. when it is done it is equal to 1, else equal to 0.

Useage: v = VirtTimer(5.) if v: dosomething() v.Update(elapsed_time)

OR with a callback.

v = VirtTimer(5., dosomething) v.Update(elapsed_time)

Call Update on each game tick. Passing in elapsed time in seconds allows you to have timers running on different time. So pausing, and things like bullet time are easy.

Also has some other features. You can be notified on the "edge" of time. That is when a timer is just_started or just_finished.

if v.just_finished: do_some_other_thing()

You can find how much time is left. As well as get a normalised amount of time left(between 0. and 1.).

eg. time_before_powerup_runs_out = powerup_timer.left()

Methods   
Update
__eq__
__init__
__ne__
__nonzero__
left
left_normalised
not_used
reset
set_finished_no_callback
  Update 
Update ( self,  elapsed_time )

Update(1.0) -> None To be called on every game tic. elapsed_time - since last update.

  __eq__ 
__eq__ ( self,  other )

  __init__ 
__init__ (
        self,
        length,
        callback=None,
        )

length - of time to run for. callback - optional callback function to call.

  __ne__ 
__ne__ ( self,  other )

  __nonzero__ 
__nonzero__ ( self )

  left 
left ( self )

left() -> time left until finished.

  left_normalised 
left_normalised ( self )

left_normalised() -> the time left normalized to 0. - 1.

  not_used 
not_used ( self )

not_used -> None

For if the timer is not being used. This is useful for one time, timers.

  reset 
reset ( self )

reset() -> None Resets the timer to the beginning.

  set_finished_no_callback 
set_finished_no_callback ( self )

set_finished_no_callback() -> None

Sets it to finished, without calling callback. not just finished.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/pack_textures.html0000644000175100017510000001561110160167715022720 0ustar renerene00000000000000 Module: pack_textures

Table of Contents

Module: pack_textures rdpyg/util/pack_textures.py

TODO: need to return UV coordinates and pixel coordinates for the packing/cutting functions for where the images are located on the textures.

Code to pack multiple textures into larger ones. As well as to cut up bigger textures into smaller ones.

This is useful for eg opengl where there are textures size limits. Also it can speed up rendering as you need to do less texture binding calls, and you can reduce geometry calls too.

Power of 2 textures can be a waste of memory if you have non power of 2 sized images. The more video memory saved the faster a game can go.

To make this code more useful it will work with rectangles. So that it can be used to update texture memory as well as to update images.

There will also need to be possibly multiple big output textures. So that you can specify a maximum size output texture.

Functions   
pack_images_into_multiple
split_big_image
  pack_images_into_multiple 
pack_images_into_multiple (
        small_list,
        max_size,
        use_pow2=1,
        )

returns a list of Texture objects with the textures from the small_list packed into them. small_list - list of Texture objects max_size - of the output Textures. use_pow2 - if 0 then we do not have to limit ourselves to power of 2.

Exceptions   
NotImplementedError
  split_big_image 
split_big_image (
        big_image,
        max_size,
        use_pow2=1,
        )

returns a list of Textures which the big_image is split into. big_image - a Texture object.

TODO: how to determine where the small bits are placed?

Exceptions   
NotImplementedError
Classes   

Texture

One texture which holds multiple smaller ones packed in.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/__init__.html0000644000175100017510000000237010160167715021574 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/util/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/cyclic_list.html0000644000175100017510000000531710160167715022342 0ustar renerene00000000000000 Module: cyclic_list

Table of Contents

Module: cyclic_list rdpyg/util/cyclic_list.py
Imported modules   
import UserList
Classes   

cyclic_list


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/index.html0000644000175100017510000000550310160167715021145 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg.util

Table of Contents

HappyDoc Generated Documentation: rdpyg.util  
Modules and Packages   

rdpyg/util/

util

cyclic_list

pack_textures

TODO: need to return UV coordinates and pixel coordinates for the

paths

quaternion

Simple module providing a quaternion class for manipulating rotations easily.

vtimer


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/quaternion.html0000644000175100017510000004301410160167715022222 0ustar renerene00000000000000 Module: quaternion

Table of Contents

Module: quaternion rdpyg/util/quaternion.py

Simple module providing a quaternion class for manipulating rotations easily.

NOTE: unittest in quaternion_test.py

NOTE: a lot of this code is taken from various places, including OpenglContext.

Note: all angles are assumed to be specified in radians. Note: this is an entirely separate implementation from the PyOpenGL quaternion class. This implementation assumes that Numeric python will be available, and provides only those methods and helpers commonly needed for manipulating rotations.

TODO:

Make all functions use an array instead of a quat class. Make a quat class which uses the functions. Make a c version of for the python functions. - based off amd lib, gamasutra article, and CS quats.

Imported modules   
import Matrix
import Numeric
import math
Functions   
angle_to_radians
euler_to_quats
fromAXYZ
fromEuler
fromEuler_angle
fromMatrix
fromXYZR
from_euler_list
get_angles_from_two_points
length_quat
magnitude_vectors
normalise_vector
normalise_vectors
radians_to_angle
slerp_quat
  angle_to_radians 
angle_to_radians ( angle )

  euler_to_quats 
euler_to_quats ( rotations )

Returns a sequence of quats. It is an array where each quat is four floats. w,x,y,z is the order. rotations- an array of rotations. where each rotation is three floats.

  fromAXYZ 
fromAXYZ (
        a,
        x,
        y,
        z,
        )

  fromEuler 
fromEuler (
        x=0,
        y=0,
        z=0,
        )

Create a new quaternion from a 3-element euler-angle rotation about x, then y, then z

  fromEuler_angle 
fromEuler_angle (
        x=0,
        y=0,
        z=0,
        )

From x,y,z angles in degrees create a quat.

  fromMatrix 
fromMatrix ( matrix )

from a 4x4 matrix return a quaternion.

These are the orders of the matrix: [00,01,02,03] [10,11,12,13] [20,21,22,23] [30,31,32,33]

[0 , 1, 2, 3] [4 , 5, 6, 7] [8 , 9,10,11] [12,13,14,15]

Which is the opengl order.

  fromXYZR 
fromXYZR (
        x,
        y,
        z,
        r,
        )

Create a new quaternion from a VRML-style rotation x,y,z are the axis of rotation r is the rotation in radians.

  from_euler_list 
from_euler_list ( l )

  get_angles_from_two_points 
get_angles_from_two_points ( a,  b )

returns the angles along the x,y,z axis. this is direction of the two points.

Exceptions   
ValueError("shouldn't get here x:%s: y :%s: " %( x, y ) )
  length_quat 
length_quat ( quat )

  magnitude_vectors 
magnitude_vectors ( vectors )

Calculate the magnitudes of the given vectors

vectors
sequence object with 1 or more 3-item vector values.

returns a double array with x elements, where x is the number of 3-element vectors

  normalise_vector 
normalise_vector ( vector )

Given a 3 or 4-item vector, return a 3-item unit vector

  normalise_vectors 
normalise_vectors ( vectors )

Get normalised versions of the vectors.

vectors
sequence object with 1 or more 3-item vector values.

returns a double array with x 3-element vectors, where x is the number of 3-element vectors in "vectors"

Will raise ZeroDivisionError if there are 0-magnitude vectors in the set.

  radians_to_angle 
radians_to_angle ( radians )

  slerp_quat 
slerp_quat (
        quat_a,
        quat_b,
        slerp,
        )

Returns a quaternion spherically interpolated between quat_a, quat_b. quat_a, quat_b - quaternions to interpolate between. slerp - interp factor (0.0 = quat_a, 1.0 = quat_b)

Classes   

Quaternion

Quaternion object implementing those methods required


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/paths.html0000644000175100017510000003042510160167715021156 0ustar renerene00000000000000 Module: paths

Table of Contents

Module: paths rdpyg/util/paths.py
Imported modules   
import math
Functions   
backwards
distance_between_points
forwards
forwards_from_next
interpolate_line
length_line
point_within
travel_line
within
  backwards 
backwards (
        cur_point,
        next_point,
        distance,
        )

backwards(point, point, num) -> point Returns the point backwards along the given line.

  distance_between_points 
distance_between_points ( p1,  p2 )

distance_between_points(point, point) -> num Returns the distance between two points.

Exceptions   
NotImplementedError
  forwards 
forwards (
        cur_point,
        next_point,
        distance,
        )

forwards(point, point, num) -> point Returns the point forwards the distance along the given line. From the current point!

  forwards_from_next 
forwards_from_next (
        cur_point,
        next_point,
        distance,
        )

forwards(point, point, num) -> point Returns the point forwards the distance along the given line. From the next point!

  interpolate_line 
interpolate_line (
        start_point,
        end_point,
        t,
        )

interpolate_line(point, point, num) -> point returns the new point along the line given. start_point - of the line. end_point - of the line. t - ratio between 0. - 1. along the line.

Exceptions   
NotImplementedError
  length_line 
length_line ( points )

length([point]) -> num returns the length of the line represented by the points.

  point_within 
point_within ( point,  a_rect )

point_within([x,y], rectstyle) -> true if a point is within the rect.

  travel_line 
travel_line (
        start_point,
        end_point,
        speed,
        elapsed_time,
        )

travel_lines(point, point, num, num) -> (time_left, new_point) Travels along the line given at a given speed, for a given time.

  within 
within (
        a,
        b,
        error_range,
        )

within(num, num, num) -> bool check if a is with error_range of b.

Classes   

Path

Used for storing the path from one point to another.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/util/vtimer.html0000644000175100017510000000410010160167715021334 0ustar renerene00000000000000 Module: vtimer

Table of Contents

Module: vtimer rdpyg/util/vtimer.py
Classes   

vtimer

times something. when it is done it is equal to 1, else equal to 0.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/ifconfig_networking.html0000644000175100017510000001102610160167034023103 0ustar renerene00000000000000 Module: ifconfig_networking

Table of Contents

Module: ifconfig_networking rdpyg/net/ifconfig_networking.py
Imported modules   
import os
import platform
import re
import sys
Functions   
IfConfig
  IfConfig 
IfConfig ()

Classes   

IfConfigFreeBSD

IfConfigLinux

IfConfigWindows


Table of Contents

This document was automatically generated on Thu Dec 16 13:08:26 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/__init__.html0000644000175100017510000000235510160167715020622 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ rdpyg/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/rdpyg/index.html0000644000175100017510000000556610160167715020201 0ustar renerene00000000000000 HappyDoc Generated Documentation: rdpyg

Table of Contents

HappyDoc Generated Documentation: rdpyg  
Modules and Packages   

rdpyg/

rdpyg

app

Common functionality for applications.

draw

HappyDoc Generated Documentation: rdpyg.draw

net

networking related stuff.

sprites

HappyDoc Generated Documentation: rdpyg.sprites

util

HappyDoc Generated Documentation: rdpyg.util


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/rdpyg/index.html0000644000175100017510000000407010160167715017041 0ustar renerene00000000000000 HappyDoc Generated Documentation

Table of Contents

HappyDoc Generated Documentation  
Modules and Packages   

rdpyg

HappyDoc Generated Documentation: rdpyg


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:39 2004 by HappyDoc version 2.1 new_rdpyg/docs/tests/0000755000175100017510000000000010160166524015055 5ustar renerene00000000000000new_rdpyg/docs/tests/run_all_tests.py.html0000644000175100017510000000447410160167712021261 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py
"""Regression testing framework

This module will search for scripts in the same directory named
test*.py.  Each such script should be a test suite that tests a
module through PyUnit.  (As of Python 2.1, PyUnit is included in
the standard library as "unittest".)  This script will aggregate all
found test suites into one big test suite and run them all at once.
"""

import sys, os, re, unittest, glob


def regressionTest():
    files = glob.glob("test*.py")
    if not files:
        os.chdir("tests")
        files = glob.glob("test*.py")
        

    filenameToModuleName = lambda f: os.path.splitext(f)[0]
    moduleNames = map(filenameToModuleName, files)         
    modules = map(__import__, moduleNames)                 
    load = unittest.defaultTestLoader.loadTestsFromModule  
    return unittest.TestSuite(map(load, modules))          

if __name__ == "__main__":                   
    unittest.main(defaultTest="regressionTest")
new_rdpyg/docs/tests/chimpgl.py.html0000644000175100017510000002720610160167712020024 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py
#/usr/bin/env python
"""
This simple example is used for the line-by-line tutorial
that comes with pygame. It is based on a 'popular' web banner.
Note there are comments here, but for the full explanation, 
follow along in the tutorial.
"""


#Import Modules
import os, pygame
from pygame.locals import *

if not pygame.font: print 'Warning, fonts disabled'
if not pygame.mixer: print 'Warning, sound disabled'

USE_GL = 1

if USE_GL:

    from rdpyg.sprites.spritegl import SpriteGL, GroupGL, gl_display_get_surface, gl_display_set_mode

    pygame.sprite.Sprite = SpriteGL
    pygame.sprite.Group = GroupGL
    pygame.sprite.RenderPlain = GroupGL


    pygame.display.old_get_surface = pygame.display.get_surface
    pygame.display.get_surface = gl_display_get_surface

    pygame.display.old_set_mode = pygame.display.set_mode
    pygame.display.set_mode = gl_display_set_mode



#functions to create our resources
def load_image(name, colorkey=None):
    fullname = os.path.join('data', name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'Cannot load image:', fullname
        raise SystemExit, message
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image, image.get_rect()

def load_sound(name):
    class NoneSound:
        def play(self): pass
    if not pygame.mixer or not pygame.mixer.get_init():
        return NoneSound()
    fullname = os.path.join('data', name)
    try:
        sound = pygame.mixer.Sound(fullname)
    except pygame.error, message:
        print 'Cannot load sound:', fullname
        return NoneSound()
        raise SystemExit, message
    return sound
        

#classes for our game objects
class Fist(pygame.sprite.Sprite):
    """moves a clenched fist on the screen, following the mouse"""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite initializer
        self.image, self.rect = load_image('fist.bmp', -1)
        self.punching = 0

    def update(self):
        "move the fist based on the mouse position"
        pos = pygame.mouse.get_pos()
        self.rect.midtop = pos
        if self.punching:
            self.rect.move_ip(5, 10)

    def punch(self, target):
        "returns true if the fist collides with the target"
        if not self.punching:
            self.punching = 1
            hitbox = self.rect.inflate(-5, -5)
            return hitbox.colliderect(target.rect)

    def unpunch(self):
        "called to pull the fist back"
        self.punching = 0


class Chimp(pygame.sprite.Sprite):
    """moves a monkey critter across the screen. it can spin the
       monkey when it is punched."""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite intializer
        self.image, self.rect = load_image('chimp.bmp', -1)
        screen = pygame.display.get_surface()
        self.area = screen.get_rect()
        self.rect.topleft = 10, 10
        self.move = 9
        self.dizzy = 0

    def update(self):
        "walk or spin, depending on the monkeys state"
        if self.dizzy:
            self._spin()
        else:
            self._walk()

    def _walk(self):
        "move the monkey across the screen, and turn at the ends"
        newpos = self.rect.move((self.move, 0))
        if self.rect.left < self.area.left or \
            self.rect.right > self.area.right:
            self.move = -self.move
            newpos = self.rect.move((self.move, 0))
            self.image = pygame.transform.flip(self.image, 1, 0)
        self.rect = newpos

    def _spin(self):
        "spin the monkey image"
        center = self.rect.center
        self.dizzy = self.dizzy + 12
        if self.dizzy >= 360:
            self.dizzy = 0
            self.image = self.original
        else:
            rotate = pygame.transform.rotate
            self.image = rotate(self.original, self.dizzy)
        self.rect = self.image.get_rect()
        self.rect.center = center

    def punched(self):
        "this will cause the monkey to start spinning"
        if not self.dizzy:
            self.dizzy = 1
            self.original = self.image
        

def main():
    """this function is called when the program starts.
       it initializes everything it needs, then runs in
       a loop until the function returns."""
#Initialize Everything
    pygame.init()
    screen = pygame.display.set_mode((468, 60))
    pygame.display.set_caption('Monkey Fever')
    pygame.mouse.set_visible(0)

#Create The Backgound
    background = pygame.Surface(screen.get_size())
    background = background.convert()
    background.fill((250, 250, 250))
    
#Put Text On The Background, Centered
    if pygame.font:
        font = pygame.font.Font(None, 36)
        text = font.render("Pummel The Chimp, And Win $$$", 1, (10, 10, 10))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        background.blit(text, textpos)

#Display The Background
    screen.blit(background, (0, 0))
    pygame.display.flip()
    
#Prepare Game Objects
    clock = pygame.time.Clock()
    whiff_sound = load_sound('whiff.wav')
    punch_sound = load_sound('punch.wav')
    chimp = Chimp()
    fist = Fist()
    allsprites = pygame.sprite.RenderPlain((fist, chimp))
    
#Main Loop
    while 1:
        clock.tick(60)
        

    #Handle Input Events
        for event in pygame.event.get():
            if event.type == QUIT:
                return
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                return
            elif event.type == MOUSEBUTTONDOWN:
                if fist.punch(chimp):
                    punch_sound.play() #punch
                    chimp.punched()
                else:
                    whiff_sound.play() #miss
            elif event.type == MOUSEBUTTONUP:
                fist.unpunch()

        allsprites.update()

    #Draw Everything
        screen.blit(background, (0, 0))
        allsprites.draw(screen)
        pygame.display.flip()
        print clock.get_fps()

#Game Over


#this calls the 'main' function when this script is executed
if __name__ == '__main__': main()
new_rdpyg/docs/tests/test_milk_skeleton.py.html0000644000175100017510000001504210160167712022273 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py
"""
    Copyright (C) 2002 by Rene Dudfield.
  
    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
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
"""



import unittest
from urdpyg import milk_skeleton
import os



class TestCaseBase(unittest.TestCase):

    _debug_level = 1

    def _debug(self, d, debug_level = 1):
        if self._debug_level >= debug_level:
            #a = StringIO()
            #pprint.pprint(d, a)
            #a.seek(0)
            #sys.stderr.write(":::%s:::\n" % a.read() )

            sys.stderr.write(":::%s:::\n" % d)




class Time2Keyframe_Map_test(TestCaseBase):
    def test_no_loop(self):
        """ Do the end conditions work when there is loop is set to false.
	"""

    def test_zero_seconds(self):
        """ tests to see if the correct results are returned at zero seconds.
	"""
	t2kf = milk_skeleton.Time2Keyframe_Map()
	t2kf.Update([4.0, 15.3, 16.2, 16.7, 16.9, 17.3, 130.0, 140.0, 150.9])

	






class BoneHeirachy_test(TestCaseBase):
    

    def test_MilkBonesConversion(self):
        """ test the conversion from milk_bone class into 
	      BoneHeirarchy.
	"""

	# read from a file, and manually get the correct results from the 
	#  file.

        model_path = os.path.join("data", "models", "bend.txt")
	m = milk_skeleton.MilkshapeModelLoader(model_path)
	#m.Load("milkshape_char_fx/yagogood.txt")

	should_be = {'': ['joint1'],
		     'joint1': ['joint2'],
		     'joint2': ['joint3'],
		     'joint3': ['joint4'],
		     'joint4': ['joint5'],
		     'joint5': ['joint6'],
		     'joint6': ['joint7']}

	self.assertEqual(m.skeleton.bone_heirarchy.bone_parents_dict, should_be)

	should_be = {'joint1': [''],
		     'joint2': ['joint1'],
		     'joint3': ['joint2'],
		     'joint4': ['joint3'],
		     'joint5': ['joint4'],
		     'joint6': ['joint5'],
		     'joint7': ['joint6']}

	self.assertEqual(m.skeleton.bone_heirarchy.bone_children_dict,should_be)



    def test_bone_name2bone_number_map(self):
	# We see if the order is done correctly.

        model_path = os.path.join("data", "models", "bend.txt")
	m = milk_skeleton.MilkshapeModelLoader(model_path)
	should_be = {'joint5': 4, 
	             'joint4': 3, 
		     'joint7': 6, 
		     'joint6': 5, 
		     'joint1': 0, 
		     'joint3': 2, 
		     'joint2': 1}

	self.assertEqual(m.skeleton.bone_name2bone_number_map,  should_be)





if __name__ == "__main__":
    unittest.main()




new_rdpyg/docs/tests/sounds_test.py.html0000644000175100017510000001724410160167712020754 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py
"""

Tests out the features of the urdpyg.sounds module.

Try the keys: o i u y t
    o: will play a sound and queue it if it's allready playing.
    i: will play a sound and queue it if it's allready playing.
    y: will play a sound if playing will play it anyway.
    t: will play a sound if playing will not play it.
    u: should fade out tracks.

"""


from OpenGL.GL import *
from OpenGL.GLU import *

from pygame.locals import *
import pygame

import time

from rdpyg.app import the_app_gl



pygame.init()


from urdpyg import sounds
import os


# Data driven sound loading.  Get all the sounds listed in the sound path.
SOUND_PATH = os.path.join("data", "sounds")
SOUND_LIST = sounds.get_sound_list(SOUND_PATH)



class SoundsTestApp(the_app_gl.TheAppGL):
    def __init__(self):
        the_app_gl.TheAppGL.__init__(self)

    def Load(self):
        the_app_gl.TheAppGL.Load(self)
        self.sound_manager = sounds.SoundManager(sound_list = SOUND_LIST, sound_path = SOUND_PATH)

        # Turn debugging on for the sound manager.  So we can see extra problems.
        self.sound_manager._debug_level = 1

        # Load all the files into memory.  Without calling Load sounds are loaded on demand.
        self.sound_manager.Load(sound_list = SOUND_LIST, sound_path = SOUND_PATH)



    def HandleEvents(self, event_list):
        if the_app_gl.TheAppGL.HandleEvents(self, event_list) == 0:
            return 0


        for event in event_list:
            if event.type == KEYDOWN and event.key == K_o:
                self.sound_manager.Play("one_bump3", wait = 1)
            if event.type == KEYDOWN and event.key == K_i:
                # will play a sound and queue it if it's allready playing.
                self.sound_manager.Play("one_bump4", wait = 1)
            if event.type == KEYDOWN and event.key == K_y:
                # will play a sound if playing will play it anyway.
                self.sound_manager.Play("one_bump4")
            if event.type == KEYDOWN and event.key == K_t:
                # will play a sound if playing will not play it.
                self.sound_manager.Play("one_bump4", wait = 2)



            if event.type == KEYDOWN and event.key == K_u:
                # should fade out tracks.
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump4")
                self.sound_manager.Play("one_bump3")
                self.sound_manager.Play("one_bump3")
                self.sound_manager.Play("one_bump3")
                self.sound_manager.Play("one_bump3")

            if event.type == KEYDOWN and event.key == K_u:
                # file not there.
                self.sound_manager.Play("one_bump99999999")

        return 1
        

    def Update(self, elapsed_time):
        the_app_gl.TheAppGL.Update(self, elapsed_time)

        # we tell the sound manager how much time has elapsed, so it can update playback of sounds.
        self.sound_manager.Update(elapsed_time)


    def Display(self):
        """  Basic display function just clears the screen.
        """
	glClearColor(1.0, 1.0, 1.0, 0.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)





if __name__ == "__main__":
    
    print "Try the keys: o i u y t"
    print "o: will play a sound and queue it if it's allready playing."
    print "i: will play a sound and queue it if it's allready playing."
    print "y: will play a sound if playing will play it anyway."
    print "t: will play a sound if playing will not play it."
    print "u: should fade out tracks."

    a = SoundsTestApp()
    a.Start()
    a.Loop()







new_rdpyg/docs/tests/visual_test_milkviewer4.py.html0000644000175100017510000000644510160167712023267 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py

from OpenGL.GL import *
from OpenGL.GLU import *

from pygame.locals import *
import pygame

import time, os, sys

from rdpyg.app import the_app_gl
from urdpyg import milkviewer4


from numeric_gl import *

pygame.init()



class MilkViewerVisualTest(the_app_gl.TheAppGL):
    def __init__(self):
        the_app_gl.TheAppGL.__init__(self)



    def Load(self):
	old_cwd = os.path.realpath( os.curdir )


        model_path = os.path.join("../", "data", "models", "monkeyluvva")

        model_path = os.path.join("data", "models")

        os.chdir(model_path)


	self.models = []
        m = milkviewer4.MilkshapeModel()
	#m.Load(sys.argv[1])
	m.Load("bend.txt")
        self.models.append(m)

	os.chdir( old_cwd )



    def Display(self):
	glClearColor(1.0, 1.0, 1.0, 0.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glLoadIdentity()
        glTranslatef(0., 0., -100)

        #glColor3f(1., 1., 1.)

	for m in self.models:
            if not m.IsTextured():
                glColor3f(1., 0., 1.)
	    m.Display()




if __name__ == "__main__":
    

    a = MilkViewerVisualTest()
    a.Start()
    a.Loop()


new_rdpyg/docs/tests/test_pack_textures.py.html0000644000175100017510000001346710160167712022325 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py

import unittest

from rdpyg.util import pack_textures


class TestPackTextures(unittest.TestCase):
    """ 
    """

    def test_could_fit(self):
        """
	"""

        t1 = pack_textures.Texture(0,0,256,256)
        t2 = pack_textures.Texture(0,0,256,256)
        t3 = pack_textures.Texture(0,0,128,256)
        t4 = pack_textures.Texture(0,0,128,256)
        t5 = pack_textures.Texture(0,0,512,512)
        t6 = pack_textures.Texture(500,500,128,128)
        t7 = pack_textures.Texture(0,500,128,128)
        t8 = pack_textures.Texture(500,0,128,128)
        t9 = pack_textures.Texture(0,128,128,128)
        t10 = pack_textures.Texture(128,0,128,128)


        # should fit in easily.
        self.assertEqual(True, t1.could_fit(t2))
        t1.clear()

        # should fit in easily.
        self.assertEqual(True, t1.could_fit(t3))
        t1.clear()

        # this one is too big.
        self.assertEqual(False, t1.could_fit(t5))
        t1.clear()

        # the x,y make this outside of it.
        self.assertEqual(False, t1.could_fit(t6))
        t1.clear()

        self.assertEqual(False, t1.could_fit(t7))
        t1.clear()

        self.assertEqual(False, t1.could_fit(t8))
        t1.clear()

        # these are right on the edge, but should work.
        self.assertEqual(True, t1.could_fit(t9))
        t1.clear()

        self.assertEqual(True, t1.could_fit(t10))
        t1.clear()


       

    def test_try_fit(self):
        """
	"""

        t1 = pack_textures.Texture(0,0,256,256)
        t2 = pack_textures.Texture(0,0,256,256)
        t3 = pack_textures.Texture(0,0,128,256)
        t4 = pack_textures.Texture(0,0,128,256)
        t5 = pack_textures.Texture(0,0,512,512)
        t6 = pack_textures.Texture(500,500,128,128)
        t7 = pack_textures.Texture(0,500,128,128)
        t8 = pack_textures.Texture(500,0,128,128)
        t9 = pack_textures.Texture(0,128,128,128)
        t10 = pack_textures.Texture(128,0,128,128)



        # both of these should fit on top of each other.
        self.assertEqual(True, t5.try_fit(t1))
        self.assertEqual(True, t5.try_fit(t2))
        self.assertEqual(True, t5.try_fit(t3))
        self.assertEqual(True, t5.try_fit(t4))
        #print t5.sub_textures
        t5.clear()

        t11 = pack_textures.Texture(0,0,4096,4096)
        smalls = []
        #for x in range(130):
        for x in range(3030):
            smalls.append(pack_textures.Texture(0,0,32,32))

        r = t11.try_fit_batch(smalls)
        #print t11.sub_textures
        t11.clear()


        # try to fit more than we have.
        for x in range(20000):
            smalls.append(pack_textures.Texture(0,0,32,32))

        r = t11.try_fit_batch(smalls)
        print len(r)
        #print t11.sub_textures
        t11.clear()


    def test_collide(self):
        """ does collision work?
        """

        t1 = pack_textures.Texture(0,0,256,256)
        t2 = pack_textures.Texture(0,0,256,256)
        t3 = pack_textures.Texture(0,0,128,256)
        t4 = pack_textures.Texture(0,0,128,256)
        t5 = pack_textures.Texture(0,0,512,512)
        t6 = pack_textures.Texture(500,500,128,128)
        t7 = pack_textures.Texture(0,500,128,128)
        t8 = pack_textures.Texture(500,0,128,128)
        t9 = pack_textures.Texture(0,128,128,128)
        t10 = pack_textures.Texture(128,0,128,128)
        t11 = pack_textures.Texture(1,1,256,256)

        self.assertEqual(True, t1.collide(t3))
        self.assertEqual(True, t1.collide(t2))
        self.assertEqual(True, t1.collide(t4))
        self.assertEqual(True, t1.collide(t9))
        self.assertEqual(True, t1.collide(t11))

        self.assertEqual(False, t1.collide(t6))
        self.assertEqual(False, t9.collide(t10))



if __name__ == "__main__":
    unittest.main()


new_rdpyg/docs/tests/test_paths.py.html0000644000175100017510000000356610160167712020562 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py

import unittest

from rdpyg.util import paths


import pickle


class TestPaths(unittest.TestCase):
    """ 
    """

    def test_pickling(self):
        """
	"""
        p = paths.Path()
        p.SetPoints([[0., 0., 0.],
	             [0., 1., 0.],
	             [1., 1., 0.],
	             [2., 2., 0.],
	             [3., 3., 0.]])

        pickled_path = pickle.dumps(p)
        unpickled_path = pickle.loads(pickled_path)


        self.assertEqual(p, unpickled_path)



if __name__ == "__main__":
    unittest.main()



new_rdpyg/docs/tests/test_quaternion.py.html0000644000175100017510000002347410160167712021630 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py

import unittest
import pickle

from rdpyg.util.quaternion import *
import rdpyg.util.quaternion as quaternion

import time
#import psyco
#psyco.bind(fromEuler)
#psyco.bind(fromXYZR)
#psyco.bind(normalise_vector)
#psyco.bind(Quaternion)
#psyco.bind(array)
#psyco.bind(sin)
#psyco.bind(cos)



def within_accuracy(a,b, allowable_error = 0.000001):
    """ Is a equal to b within the allowable_error?
    """
    #return a <= b+ allowable_error and a > b- allowable_error
    return math.fabs(a -b) < allowable_error




class TestBla(unittest.TestCase):

    _debug_level = 1

    def _debug(self, d, debug_level = 1):
        if self._debug_level >= debug_level:
            #a = StringIO()
            #pprint.pprint(d, a)
            #a.seek(0)
            #sys.stderr.write(":::%s:::\n" % a.read() )

            sys.stderr.write(":::%s:::\n" % d)



class TestExtraFuncs(unittest.TestCase):
    """ tests the extra functions.
    """


    _debug_level = 1

    def _debug(self, d, debug_level = 1):
        if self._debug_level >= debug_level:
            #a = StringIO()
            #pprint.pprint(d, a)
            #a.seek(0)
            #sys.stderr.write(":::%s:::\n" % a.read() )

            sys.stderr.write(":::%s:::\n" % d)

    def test_get_angles_from_two_points(self):
        """ does the angle come out correctly for the given points.
	"""

	p1 = [0., 0., 0.]
	p2 = [2., 0., 0.]

	angles = quaternion.get_angles_from_two_points(p1, p2)
	print angles
	#should be (0, 90, 0)


	p1 = [0., 0., 0.]
	p2 = [2., 1., 0.]

	angles = quaternion.get_angles_from_two_points(p1, p2)
	print angles


class TestQuaternions(unittest.TestCase):
    """ The quaternion functions which I need for 
    """


    _debug_level = 1

    def _debug(self, d, debug_level = 1):
        if self._debug_level >= debug_level:
            #a = StringIO()
            #pprint.pprint(d, a)
            #a.seek(0)
            #sys.stderr.write(":::%s:::\n" % a.read() )

            sys.stderr.write(":::%s:::\n" % d)


    def test_length(self):
        """ Is the length equal to 1.0?
	"""
	
        w,x,y,z = fromEuler( y = pi/2 ).internal
	length = x**2 + y**2 + z**2 + w**2
	self.assertEqual(1.0, length)

        # check to see if two multiplications equals length 1.
	q1 = fromEuler( y = pi/2 )
	q2 = fromEuler( x = pi/2 )
	q3 = q1 * q2

        w,x,y,z = q3.internal
	length = x**2 + y**2 + z**2 + w**2
	self.assertEqual(1.0, length)
        
    def test_fromEuler(self):
        """
	"""
	#print fromEuler( y = pi/2 ).XYZR()


    def test_to_matrix_and_back(self):
        """ Does the conversion to matrix and from matrix work correctly?
	"""

        a = fromEuler( y = pi/2 )
	b = fromMatrix(a.matrix())

        w,x,y,z = b.internal
	length = x**2 + y**2 + z**2 + w**2
	self.assertEqual(1.0, length)
	self.assertEqual(a.matrix(), b.matrix())




    def test_speed_of_convert_to_matrix(self):
        """  Is the speed of the quaternion to matrix acceptable?
	"""
	# How fast does this need to be?
	#  We have 30 bones per character.
	#  We have 13 characters.
	#  one tenth of the time is devoted to animation.
	#  one tenth of that is devoted to quat-> mat transforms.
	#  60 frames per second.
	#  30 * 13 per 

	#  1. /60 /10 /10 /13 /30
	#  .000000427 per one.
	#  0.000166 for all of them (13 * 30 == 390).

	t1 = time.time()
	a = fromEuler( z = pi/2 )
	a_matrix = a.matrix

	for x in range(13 * 300):
            b = a_matrix()
	t2 = time.time()
	total_time = t2 -t1
	print total_time

	#self.Assert
	

    def test_slerp(self):
        """ Does the slerp work correctly?
	"""
	a = fromEuler( z = pi/2 )
	b = fromEuler( x = pi/2 )
	c = slerp_quat(a,b, 0.5)
	self.assertEqual( 1, within_accuracy(1.,length_quat(c)) )


    def test_euler_to_quats(self):
        """ 
	"""
	a = [[0.0, 0.0, 0.0], [1.2042771577835081, 0.0, 0.0], [0.89011788368225098, 0.0, 0.0]]

	quats_a = euler_to_quats(a)

	b = [[0.087266437709331512, 5.1804383005560339e-10, 0.113446407020092], [-0.13962611556053159, -2.62412314100402e-08, 0.1134487614035606], [0.078540049493312836, -2.7923498180371101e-08, 0.1134487614035606]]

	quats_b = euler_to_quats(b)

	print quats_a
	print quats_b


    def test_pickling(self):
        """ Can we pickle and unpickle the quaternions nicely?
        """
	a = [[0.0, 0.0, 0.0], 
             [1.2042771577835081, 0.0, 0.0], 
             [0.89011788368225098, 0.0, 0.0]]

	q = euler_to_quats(a)
        pickled_q = pickle.dumps(q)
        unpickled_q = pickle.loads(pickled_q)

        self.assertEqual(q, unpickled_q)

    def test_pickle(self):
        """ can we pickle/unpickle it properly.
        """
	q = fromEuler(1.2042771577835081, 0.0, 0.0)

        pickled_quat = pickle.dumps(q)
        unpickled_q = pickle.loads(pickled_quat)

        self.assertEqual(q.internal, unpickled_q.internal)
        #self.assertEqual(q, unpickled_q)

    def test_invert(self):
        """ tests the inverse is correct.  That is the opposite direction.
        """
        q = fromAXYZ(180,1.,0.,0.)
        q2 = -q
        self.assertEqual(q2.AXYZ(), [180.00000000000003, -1.0, -0.0, -0.0] )



if __name__ == "__main__":
    unittest.main()


new_rdpyg/docs/tests/visual_test_map.py.html0000644000175100017510000000252710160167712021577 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py

from rdpyg.app import the_app
from urdpyg.map import map

# We have to initialise pygame ourselves.
import pygame
pygame.init()


a = the_app.TheApp()

a.Start()
a.Loop()
print a.GetFps()
a.Stop()



new_rdpyg/docs/tests/visual_test_particles.py.html0000644000175100017510000001135610160167712023010 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py
"""


"""



import rdpyg.app.the_app_gl as the_app_gl
import rdpyg.draw.pyopengl.particles as particles




import traceback


import time
import sys


import pygame
from pygame.locals import *


from OpenGL.GL import *

import os


pygame.init()




class AApp(the_app_gl.TheAppGL):


    draw_mode = 0

    def Display(self):
        pass

	self._debug("running display", 4)
	glClearColor(0.0, 0.0, 0.3, 0.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glMatrixMode(GL_MODELVIEW)
	glLoadIdentity()
        glTranslate(0., 0., -20)

        self.particles.DisplayStateBegin()
	self.particles.Display()
        self.particles.DisplayStateEnd()




    def Load(self):
        """ Place to load stuff.  duh!
	"""

	self._debug("loading")


        self.particles = particles.Particles(44)
        self.particles.Load(file_name = os.path.join("data", "particle.png"))


    def HandleEvents(self, event_list):

        for event in event_list:

	    if event.type == QUIT or (event.type == KEYDOWN and 
	                              event.key == K_ESCAPE):
	        self.Stop()
		return 0

		break

	    if event.type == KEYDOWN and event.key == K_LEFT:
	        pass
    
	    if event.type == KEYDOWN and event.key == K_RIGHT:
	        pass



        return 1



    def Update(self, elapsed_time):
        self.particles.Update(elapsed_time)
	






def main():

    pygame.key.set_repeat(500, 30)


    a = AApp()
    t1 = time.time()
    a.Start()

    try:
	a.Loop()
    except:
        traceback.print_exc(sys.stderr)
	print "Cleaning up."
        a.Stop()

    total_time = time.time() - t1
    print "time:%s frames:%s frames/time:%s" % (total_time, a.frames, a.frames/total_time)





if(__name__ == "__main__"):


    if len(sys.argv) != 1:
	if sys.argv[1] == "profile":
	    import profile
	    profile.run('main()', '/tmp/prof')
    else:

	main()
 

new_rdpyg/docs/tests/visual_test_paths.py.html0000644000175100017510000001540010160167712022133 0ustar renerene00000000000000 /home/rene/mystuff/python/new_rdpyg/tests/chimpgl.py
"""


"""



import rdpyg.util.paths as paths
import rdpyg.util.cyclic_list as cyclic_list
import rdpyg.app.the_app_gl as the_app_gl
import rdpyg.draw.pyopengl.paths as draw_paths




import traceback


import time
import sys


import pygame
from pygame.locals import *


from OpenGL.GL import *



pygame.init()




class AApp(the_app_gl.TheAppGL):


    draw_mode = 0

    def Display(self):
        pass

	self._debug("running display", 4)
	glClearColor(0.0, 0.0, 0.3, 0.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glMatrixMode(GL_MODELVIEW)
	glLoadIdentity()
        glTranslate(0., 0., -10)

	self.DrawPath()


    def DrawPath(self):
        if self.draw_mode:
	    draw = draw_paths.draw_path
	else:
	    draw = draw_paths.draw_path_with_traveler

	for p in self.paths:
	    draw(p)




    def Load(self):
        """ Place to load stuff.  duh!
	"""

	self._debug("loading")


        self.paths = cyclic_list.cyclic_list()

	p = self.paths

        p.append(paths.Path() )

	p[0].SetPoints([[0., 0., 0.],
	                [0., 1., 0.],
	                [1., 1., 0.],
	                [2., 2., 0.],
	                [3., 3., 0.]])


    def HandleEvents(self, event_list):

        for event in event_list:

	    if event.type == QUIT or (event.type == KEYDOWN and 
	                              event.key == K_ESCAPE):
	        self.Stop()
		return 0

		break

	    if event.type == KEYDOWN and event.key == K_LEFT:
	        pass
    
	    if event.type == KEYDOWN and event.key == K_RIGHT:
	        pass

	    

	    if event.type == KEYDOWN:

                p = self.paths.cur()

	        if event.key == K_SPACE:
		    if pygame.key.get_mods() == KMOD_SHIFT:
			self.paths.prev()
		    else:
			self.paths.next()

	        if event.key == K_RETURN:
		    if pygame.key.get_mods() == KMOD_SHIFT:
			for path in self.paths:
			    print path.length()
		    else:
		        pass



	        if event.key == K_BACKSPACE:
		    if self.draw_mode:
		        self.draw_mode = 0
		    else:
		        self.draw_mode = 1


	        if event.key == K_a:
		    if pygame.key.get_mods() & KMOD_SHIFT:
			r = p.Travel(1., 1.)
		    else:
			r = p.Travel(0.1, 0.1)

		    print r

	        if event.key == K_b:

		    if pygame.key.get_mods() & KMOD_SHIFT:
		        pass
		    else:
		        pass



		#print self.points

        return 1



    def Update(self, elapsed_time):
        p = self.paths.cur()
        p.Travel(0.7, elapsed_time)
	






def main():

    pygame.key.set_repeat(500, 30)


    a = AApp()
    t1 = time.time()
    a.Start()

    try:
	a.Loop()
    except:
        traceback.print_exc(sys.stderr)
	print "Cleaning up."
        a.Stop()

    total_time = time.time() - t1
    print "time:%s frames:%s frames/time:%s" % (total_time, a.frames, a.frames/total_time)





if(__name__ == "__main__"):


    if len(sys.argv) != 1:
	if sys.argv[1] == "profile":
	    import profile
	    profile.run('main()', '/tmp/prof')
    else:

	main()
 

new_rdpyg/docs/urdpyg/0000755000175100017510000000000010160167717015232 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/0000755000175100017510000000000010160167720016536 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/0000755000175100017510000000000010160167720020730 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/cal3d_exporter/0000755000175100017510000000000010160167717023654 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/cal3d_exporter/Cal3dSkeleton.html0000644000175100017510000000633610160167717027205 0ustar renerene00000000000000 Class: Cal3dSkeleton

Table of Contents

Class: Cal3dSkeleton urdpyg/converters/cal3d_exporter.py
Methods   
__init__
to_xml
  __init__ 
__init__ ( self )

  to_xml 
to_xml ( self,  indentation=0 )

returns a string with the xml for the cal3d skeleton.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/cal3d_exporter/Cal3dBone.html0000644000175100017510000000637210160167717026304 0ustar renerene00000000000000 Class: Cal3dBone

Table of Contents

Class: Cal3dBone urdpyg/converters/cal3d_exporter.py

a class representing a cal3d bone.

Methods   
__init__
to_xml
  __init__ 
__init__ ( self )

  to_xml 
to_xml ( self,  indentation=4 )

returns a string of xml representing this bone.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/md2_importer/0000755000175100017510000000000010160167717023341 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/md2_importer/Md2Model.html0000644000175100017510000001470510160167717025641 0ustar renerene00000000000000 Class: Md2Model

Table of Contents

Class: Md2Model urdpyg/converters/md2_importer.py
Methods   
Load
_ConvertTexcoords
_ReadHeader
_ReadMd2Data
__init__
  Load 
Load (
        self,
        md2_file_name=None,
        md2_texture_file_name=None,
        )

Exceptions   
"Object has no file to load."
"file corrupt, version is not 8"
  _ConvertTexcoords 
_ConvertTexcoords (
        self,
        texcoords,
        texture_indices,
        w,
        h,
        )

Flips the v coordinate part, and makes a new array based on the texture indices.

texcoords - texture_indices -

  _ReadHeader 
_ReadHeader (
        self,
        md2_file_name=None,
        md2_texture_file_name=None,
        )

  _ReadMd2Data 
_ReadMd2Data (
        self,
        md2_file_name=None,
        md2_texture_file_name=None,
        )

  __init__ 
__init__ (
        self,
        md2_file_name=None,
        md2_texture_file_name=None,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/middle_obj/0000755000175100017510000000000010160167717023026 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/middle_obj/MiddleObject.html0000644000175100017510000001157410160167717026251 0ustar renerene00000000000000 Class: MiddleObject

Table of Contents

Class: MiddleObject urdpyg/converters/middle_obj.py
Methods   
AddExporter
AddImporter
SendFeatureRequestsToImporter
__init__
  AddExporter 
AddExporter ( self,  exporter )

exporter - an object used to export 3d data from the middle object.

  AddImporter 
AddImporter ( self,  importer )

importer - an object used to import 3d data into the middle object.

  SendFeatureRequestsToImporter 
SendFeatureRequestsToImporter ( self )

Goes through the exporters and gathers a set of features which need to be sent to the importer.

  __init__ 
__init__ ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/middle_obj/Exporter.html0000644000175100017510000001047210160167717025530 0ustar renerene00000000000000 Class: Exporter

Table of Contents

Class: Exporter urdpyg/converters/middle_obj.py

Used for exporting 3d data from the MiddleObject. This is a base class, to be used for exporters for various 3d formats.

Methods   
GetSupportedFeatures
SetFeaturesWanted
__init__
  GetSupportedFeatures 
GetSupportedFeatures ( self )

Returns the features that this exporter supports.

  SetFeaturesWanted 
SetFeaturesWanted ( self,  features )

Used to tell the exporter what features the exporter should get from the middle object.

  __init__ 
__init__ (
        self,
        supported_features,
        wanted_features={},
        )

supported_features -


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/middle_obj/Importer.html0000644000175100017510000001375710160167717025532 0ustar renerene00000000000000 Class: Importer

Table of Contents

Class: Importer urdpyg/converters/middle_obj.py

Used for importing 3d data into a MiddleObject. This is a base class, to be used for importers for various 3d formats.

Methods   
GetSupportedFeatures
SetFeaturesWanted
Start
__init__
  GetSupportedFeatures 
GetSupportedFeatures ( self )

Returns the features that this importer supports.

  SetFeaturesWanted 
SetFeaturesWanted ( self,  features )

Used to tell the importer what features the importer should pass onto the middle object. NOTE: this does not mean that the importer should not load all of the 3d format. If it has to load it all so be it. Just pass the features that are wanted.

  Start 
Start ( self )

Starts the importer doing its import thing.

Exceptions   
"This importer is missing an implementation of Start()"
  __init__ 
__init__ (
        self,
        supported_features,
        wanted_features={},
        )

supported_features - features which the wanted_features - defaults to all features if not specified.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/ms3d_ascii_importer/0000755000175100017510000000000010160167720024667 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/ms3d_ascii_importer/MS3dImporter.html0000644000175100017510000001702310160167720030050 0ustar renerene00000000000000 Class: MS3dImporter

Table of Contents

Class: MS3dImporter urdpyg/converters/ms3d_ascii_importer.py
Base Classes   
Importer
Methods   
Initialize
ReadBones
ReadMaterials
ReadMeshes
Start
__init__
  Initialize 
Initialize ( self,  file )

  ReadBones 
ReadBones (
        self,
        a_file,
        num_bones,
        )

a_file should be set to after the Bones line.

  ReadMaterials 
ReadMaterials (
        self,
        a_file,
        num_materials,
        )

a_file should be set to after the Materials line.

Exceptions   
"Error on line:%s:" % line_num
  ReadMeshes 
ReadMeshes (
        self,
        a_file,
        num_meshes,
        )

  Start 
Start ( self )

  __init__ 
__init__ ( self,  wanted_features=None )

If wanted_features equals None then all features are given.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/ms3d_ascii_importer/milk_bones.html0000644000175100017510000000622510160167720027704 0ustar renerene00000000000000 Class: milk_bones

Table of Contents

Class: milk_bones urdpyg/converters/ms3d_ascii_importer.py
Methods   
__init__
__str__
  __init__ 
__init__ ( self )

  __str__ 
__str__ ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/ms3d_ascii_importer/milk_material.html0000644000175100017510000000500010160167720030362 0ustar renerene00000000000000 Class: milk_material

Table of Contents

Class: milk_material urdpyg/converters/ms3d_ascii_importer.py
Methods   
__init__
  __init__ 
__init__ ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/ms3d_ascii_importer/milk_mesh.html0000644000175100017510000000622310160167720027530 0ustar renerene00000000000000 Class: milk_mesh

Table of Contents

Class: milk_mesh urdpyg/converters/ms3d_ascii_importer.py
Methods   
__init__
__str__
  __init__ 
__init__ ( self )

  __str__ 
__str__ ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/test_cal3d_exporter/0000755000175100017510000000000010160167720024705 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/test_cal3d_exporter/Cal3dExporter.html0000644000175100017510000001012510160167720030251 0ustar renerene00000000000000 Class: Cal3dExporter

Table of Contents

Class: Cal3dExporter urdpyg/converters/test_cal3d_exporter.py
Base Classes   
unittest.TestCase
Methods   
test_Cal3dBone__to_xml
test_Cal3dSkeleton__to_xml
  test_Cal3dBone__to_xml 
test_Cal3dBone__to_xml ( self )

does converting a Cal3dBone to xml work?

  test_Cal3dSkeleton__to_xml 
test_Cal3dSkeleton__to_xml ( self )

does converting a Cal3dSkeleton to xml work?


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/test_md2_importer/0000755000175100017510000000000010160167720024372 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/test_md2_importer/TestMd2Importer.html0000644000175100017510000000632110160167720030266 0ustar renerene00000000000000 Class: TestMd2Importer

Table of Contents

Class: TestMd2Importer urdpyg/converters/test_md2_importer.py
Base Classes   
unittest.TestCase
Methods   
testReadHeader
  testReadHeader 
testReadHeader ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/test_middle_obj/0000755000175100017510000000000010160167720024057 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/converters/test_middle_obj/fsdf.html0000644000175100017510000000366310160167720025677 0ustar renerene00000000000000 Class: fsdf

Table of Contents

Class: fsdf urdpyg/converters/test_middle_obj.py
Base Classes   
unittest.TestCase

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/cal3d_exporter.html0000644000175100017510000001533210160167717024546 0ustar renerene00000000000000 Module: cal3d_exporter

Table of Contents

Module: cal3d_exporter urdpyg/converters/cal3d_exporter.py
Imported modules   
from math import cos, sin
import os
import py3d.milk_skeleton
import quaternion
import sys
import time
Functions   
ms3d_euler__to__cal3d_quat
read_milk
strl
test_some_shit
  ms3d_euler__to__cal3d_quat 
ms3d_euler__to__cal3d_quat (
        x,
        y,
        z,
        )

returns a quat suitable for cal3d ie a list [x,y,z,w].

  read_milk 
read_milk ( file_name )

  strl 
strl ( a_list )

makes each element in a list a string.

  test_some_shit 
test_some_shit ()

Classes   

Cal3dBone

a class representing a cal3d bone.

Cal3dSkeleton


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/__init__.html0000644000175100017510000000237710160167717023374 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ urdpyg/converters/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/md2_importer.html0000644000175100017510000001201010160167717024221 0ustar renerene00000000000000 Module: md2_importer

Table of Contents

Module: md2_importer urdpyg/converters/md2_importer.py

Copyright (C) 2002, 2003 by Rene Dudfield.

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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Imported modules   
import Numeric
import array
import struct
Functions   
from_c_string
  from_c_string 
from_c_string ( c_string )

Returns a python string from a c string. Ie it looks for a null character in the string and returns everything before that.

Classes   

Md2Model


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/index.html0000644000175100017510000000665110160167720022735 0ustar renerene00000000000000 HappyDoc Generated Documentation: urdpyg.converters

Table of Contents

HappyDoc Generated Documentation: urdpyg.converters  
Modules and Packages   

urdpyg/converters/

converters

cal3d_exporter

md2_importer

Copyright (C) 2002, 2003 by Rene Dudfield.

middle_obj

Copyright (C) 2002 by Rene Dudfield.

ms3d_ascii_exporter

ms3d_ascii_importer

Copyright (C) 2002 by Rene Dudfield.

test_cal3d_exporter

unit tests for the cal3d exporter.

test_md2_importer

unit tests for the md2 importer.

test_middle_obj

unit tests for the md2 importer.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/ms3d_ascii_exporter.html0000644000175100017510000000713410160167717025577 0ustar renerene00000000000000 Module: ms3d_ascii_exporter

Table of Contents

Module: ms3d_ascii_exporter urdpyg/converters/ms3d_ascii_exporter.py
Imported modules   
from middle_obj import *
from monkey import *
import re
import string
from string import split, join
Functions   
export_milk
  export_milk 
export_milk (
        points,
        indices,
        normals,
        out_file,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/middle_obj.html0000644000175100017510000000625710160167717023726 0ustar renerene00000000000000 Module: middle_obj

Table of Contents

Module: middle_obj urdpyg/converters/middle_obj.py

Copyright (C) 2002 by Rene Dudfield.

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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Classes   

Exporter

Used for exporting 3d data from the MiddleObject.

Importer

Used for importing 3d data into a MiddleObject.

MiddleObject


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/ms3d_ascii_importer.html0000644000175100017510000002561210160167720025563 0ustar renerene00000000000000 Module: ms3d_ascii_importer

Table of Contents

Module: ms3d_ascii_importer urdpyg/converters/ms3d_ascii_importer.py

Copyright (C) 2002 by Rene Dudfield.

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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Imported modules   
import cPickle
import md5
from middle_obj import *
import operator
import os
import re
import string
from string import split, join
import time
Functions   
chomp
convert_array_shape2
convert_array_shape3
convert_milkshape
str_parse
test_MS3dImporter
  chomp 
chomp ( s )

  convert_array_shape2 
convert_array_shape2 ( verts )

  convert_array_shape3 
convert_array_shape3 ( verts )

Converts a [[1,1,1,1], [1,1,1,1]] into [1,1,1,1,1,1]

  convert_milkshape 
convert_milkshape ( a_file )

Returns a list of [points, indices, texcoords] Only converts one mesh.

  str_parse 
str_parse (
        string_to_parse,
        conversion_list,
        seperator=" ",
        )

returns a list of formated converted variables based on the string_to_parse - um.. conversion_list - list of functions, to convert parts of the string. Use str for strings, int for ints, floats for floats etc :) seperator - string to use to seperate the elements of the string.

Will raise exceptions if string not correctly set up. Or if data fails to convert.

Exceptions   
"wrong number of converters, or string doesn't match."
  test_MS3dImporter 
test_MS3dImporter ( file_name )

points,indices,texcoords = convert_milkshape(file_name)

Classes   

MS3dImporter

milk_bones

milk_material

milk_mesh


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/test_cal3d_exporter.html0000644000175100017510000000554710160167720025606 0ustar renerene00000000000000 Module: test_cal3d_exporter

Table of Contents

Module: test_cal3d_exporter urdpyg/converters/test_cal3d_exporter.py

unit tests for the cal3d exporter.

Imported modules   
import cal3d_exporter
import unittest
Classes   

Cal3dExporter


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/test_md2_importer.html0000644000175100017510000000602510160167720025263 0ustar renerene00000000000000 Module: test_md2_importer

Table of Contents

Module: test_md2_importer urdpyg/converters/test_md2_importer.py

unit tests for the md2 importer.

Imported modules   
import md2_importer
import os
import pprint
import unittest
Classes   

TestMd2Importer


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/converters/test_middle_obj.html0000644000175100017510000000540010160167720024744 0ustar renerene00000000000000 Module: test_middle_obj

Table of Contents

Module: test_middle_obj urdpyg/converters/test_middle_obj.py

unit tests for the md2 importer.

Imported modules   
import unittest
Classes   

fsdf


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/map/0000755000175100017510000000000010160167720017313 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/map/__init__.html0000644000175100017510000000237010160167720021742 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ urdpyg/map/__init__.py

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/map/index.html0000644000175100017510000000427610160167720021321 0ustar renerene00000000000000 HappyDoc Generated Documentation: urdpyg.map

Table of Contents

HappyDoc Generated Documentation: urdpyg.map  
Modules and Packages   

urdpyg/map/

map

map

= Features wanted =


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/map/map.html0000644000175100017510000001606010160167720020761 0ustar renerene00000000000000 Module: map

Table of Contents

Module: map urdpyg/map/map.py

= Features wanted = When not moving it can take only update parts of the screen. update(dirty_rects) can be used to speed up drawing. by only updating areas which are dirty. if the map is not moving we can make it lots speedier.

  • Offscreen buffer. Blit all smaller tiles to an offscreen buffer then blit one big image to the screen. This can be faster on some screens/computers. Different tile sizes. different sizes on the same map. Join maps together easily. Different drawable sizes. Ie different camera views. Be able to be used with pygame or pyopengl. Different camera modes: jump scrolling, jump the map in blocks. Like ten pixels at a time. smooth scrolling, every pixel the camera moves the tiles move. smooth-jump scrolling. Mostly the screen stays still. When the character nears the edge everything stops moving while the maps scrolls over a little way. centered camera. Can center the camera on Looping Map Edges Paralax scrolling. Moving layers at different speeds. Multiple views of the map. * miniview of the map. Perhaps using a scaled version or one pixel per tile.

  • minimize overdraw. using dirty rectangles. for alpha images precalculate full rects. That is like a bounding box in the middle where the area is full. think about using a coverage buffer. * animated tiles will probably always need to be redrawn(unless it's the same frame).

  • Overlapping tiles. As well as overlapping whole maps. For joining maps together. Layers/Z ordering. draw characters by descending y value on same layer. for certain types of games: see for explanation: * http://www.gamedev.net/reference/programming/features/gpgenesis9/page7.asp

  • line of sight tests between tiles and pixels/rects. collision detection between tiles and pixels/rects. some tiles may be pass through. * tiles on different layers may be collidable, others not.

  • fog of war. * darkening/lightening of areas.

  • Rotatable tiles. * scalable tiles? Other transforms needed?

  • Easy layer toggling. * So eg when you go inside a building the roof comes off and you can see inside.

= Implementation ideas =

  • Use pygame sprites and sprite groups. could then reuse lots of code... optimize in one place. Speed development. think of camera movement as simply moving a sprite group in a certain way.

  • Use a quad tree for the collision detection. * Could use it for moving, and non moving.

  • Left to right, or top to bottom scrollers can be optimized in different ways.

= Some map editors =

The tile combie(or engine if you want) should have most of the features that these map editors contain.

http://tilestudio.sourceforge.net/

http://www.tilemap.co.uk/

= A discussion about features =

<geoffh> background tiling, layers, collision detection between layers and stuff (rect and pixel) <geoffh> paralax scrolling <geoffh> animation of background/sprites <geoffh> line of sight tests between tiles and pixels <geoffh> based on layer compositions and such <illumeh> eek, that's a lot of stuff <illumeh> good stuff :) <geoffh> separate environmental and UI layer systems <illumeh> what do you mean? <geoffh> so you can draw your UI without worrying how height your environments layers are <geoffh> the UI layers are alwayrs on top <illumeh> ah, cool <geoffh> basically, just 2 lists for heights <geoffh> auto-shadowing for sprites is good <illumeh> indeed, that'd be cool <geoffh> doing like angled skews on the images, and drawing them on the ground layer <geoffh> so you dont have to have separate shadow images for them <illumeh> nice <geoffh> or just auto positioning the same image, but based on heigth of the sprite

<geoffh> so like a flying ship has its shadow in the real place, and its in its height-adjusted place, like zaxxon <geoffh> which basically just means you have a transformation for height built in, and use a sort of worrld coords and translated drawing coords <illumeh> aah <geoffh> which makes sense <geoffh> so you should have parameters to what your viewing perspective is, so they can adjust it based on how their art is rendered <geoffh> like: 1.5:1.0 or something

<geoffh> you could also have layer toggling like i did in VT, where if you go into a building, it switches what the background tiles are. and if you change floors, it also does that <illumeh> ah, that sounds nice too <geoffh> but that may be a bit specific. though, you could make the design so its possible to rotate through BG tile maps specifically, like theyre layered and do a fall through if the current selected one doesnt exist <geoffh> to the default background map, which has all its spaces mapped <geoffh> sorta an "optional current level background" <geoffh> good for things where people take stairs, and you still want the ground of things outside buildings and such <geoffh> im running out of stuff ive thought about for tiling engines <illumeh> hehe. that's all stuff I didn't think about :) <geoffh> i want to retire <geoffh> im pretty happy doing fuck all all the time now <geoffh> heh <illumeh> having layers greyed out would be good <illumeh> hehe. mostly I'm happy doing fuck all too :) <geoffh> optional layers? or you mean something else?


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:42 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/0000755000175100017510000000000010160167720021376 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/BoneName2BoneNumber_Map.html0000644000175100017510000000763210160167720026614 0ustar renerene00000000000000 Class: BoneName2BoneNumber_Map

Table of Contents

Class: BoneName2BoneNumber_Map urdpyg/milk_skeleton.py

mapping of bone names to a number in the bone index.

Base Classes   
UserDict.UserDict
Methods   
Update
__init__
  Update 
Update ( self,  milk_bones )

  __init__ 
__init__ ( self,  milk_bones )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/AbsoluteBones.html0000644000175100017510000000430310160167720025031 0ustar renerene00000000000000 Class: AbsoluteBones

Table of Contents

Class: AbsoluteBones urdpyg/milk_skeleton.py

Stores the absolute transforms. There is a seperate one of these for each keyframe.

  • Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of four elements ). - translation quats(array of four elements ).

Maybe only need matrix version for absolute? - No, need to slerp between two absolute bones.

Don't need a matrix representation? - maybe not, if the these are only used to slerp up an intermediate set of bones.

NOTE: for transforming the verts, it will be faster to transform them with a 3x3 rotation matrix if there is no translation/scaling happening.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/Bone2Vert_Map.html0000644000175100017510000001033510160167720024671 0ustar renerene00000000000000 Class: Bone2Vert_Map

Table of Contents

Class: Bone2Vert_Map urdpyg/milk_skeleton.py

a list of indices for the verts that each bone should transform. Should probably be a Numeric 3d array. where self.data[0] == list of vert indices for the first bone.

Each index could be 4 bytes for four bones. - this would be harder to access. - would limit the total number of bones.

For now keep it simple.

Base Classes   
UserDict.UserDict
Methods   
Update
__init__
  Update 
Update ( self,  milk_data )

  __init__ 
__init__ ( self,  milk_data )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/BoneHeirarchy.html0000644000175100017510000002326710160167720025020 0ustar renerene00000000000000 Class: BoneHeirarchy

Table of Contents

Class: BoneHeirarchy urdpyg/milk_skeleton.py

Which bones are parents/children of which other bones. - has bone names, and bone indices into AbsoluteBones/RelativeBones. - GetChildren_names/indices - returns a list of names/indices.

BoneName2BoneNumber_Map - mapping of bone names to a number in the bone index.

Methods   
GetChildren
GetChildren_idx
GetParents
GetRootName
PrintTree
Update
__init__
__str__
_make__bone_name_to_idx
  GetChildren 
GetChildren ( self,  bone_name )

Returns a list of children milk_bone instances.

  GetChildren_idx 
GetChildren_idx ( self,  bone_name )

returns a list of idx for the children of given bone name.

  GetParents 
GetParents ( self,  bone_name )

Returns a list of parents milk_bone instances.

  GetRootName 
GetRootName ( self )

Returns the root bones name.

  PrintTree 
PrintTree (
        self,
        a_bone="ROOT",
        indent_level=0,
        details=0,
        )

Returns a string representation of bones tree. a_bone - a milk_bone instance, or "ROOT". if "ROOT" then we return from the root of the tree.

  Update 
Update ( self,  milk_bones )

Takes a milk_bones variable from the milkshape converter.

  __init__ 
__init__ ( self,  milk_bones )

Takes a milk_bones variable from the milkshape converter.

  __str__ 
__str__ ( self )

  _make__bone_name_to_idx 
_make__bone_name_to_idx ( self,  milk_bones )

returns a dict mapping bone name -> its idx within the list.

Exceptions   
ValueError( "bone allready exists with name, %s" % milk_bone.name )

Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/MilkshapeModelLoader.html0000644000175100017510000001111510160167720026310 0ustar renerene00000000000000 Class: MilkshapeModelLoader

Table of Contents

Class: MilkshapeModelLoader urdpyg/milk_skeleton.py

responsible for loading a milkshape model.

Methods   
IsTextured
Load
__init__
_debug
  IsTextured 
IsTextured ( self )

  Load 
Load ( self,  file_name )

  __init__ 
__init__ ( self,  file_name="" )

  _debug 
_debug (
        self,
        x,
        debug_level=1,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/MilkSkeleton.html0000644000175100017510000003235010160167720024670 0ustar renerene00000000000000 Class: MilkSkeleton

Table of Contents

Class: MilkSkeleton urdpyg/milk_skeleton.py

---------------------------------------------------------------------- Data structures. - = denotes data belongs to this parent.

Skeleton - this is where everything is put together. - we may want to share some data between skeletons, so we may need a higher level system. - this higher level system would share the different parts of memory. - Maybe it could even transform all of the data at once.

= BoneHeirachy DONE. = Keyframes = Bone2Vert_Map DONE. = Time2Keyframe_Map = KeyframeNumber2Time_Map

Keyframes - collects the different keyframe data for a skeleton. = AbsoluteBones = RelativeBones = Time2Keyframe_Map = KeyframeNumber2Time_Map

AbsoluteBones - bones represented in their absolute form. - Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of four elements ). - translation quats(array of four elements ). - transform matrices(array of 16 elements ie 4x4 matrices).

RelativeBones - these bones will have all relative data. Eg each bone will only be relative to the others.

Time2Keyframe_Map. - gets two keyframes on either side of a given time. - this would be per bone? Not at the moment(it should be per skeleton).

KeyframeNumber2Time_Map. - given a keyframe number, give the time for it. - this would be per bone? Not at the moment(it should be per skeleton).

DONE. BoneHeirachy - which bones are parents/children of which other bones. - has bone names, and bone indices into AbsoluteBones/RelativeBones. - GetChildren_names/indices - returns a list of names/indices.

BoneName2BoneNumber_Map - mapping of bone names to a number in the bone index.

DONE. Bone2Vert_Map - a list of indices for the verts that each bone should transform. Vert2Bone_Map - vert to list of bones which effect them.

MilkBones - this is the data from the milk format. This contains the positions, and rotations in euler format, and the keyframe times.

local2world_transform - a transform specifying where in the world the skeleton is. - This will likely change occasionally. - from every frame to once every minute. - is this specified by the root node? - Could we add this as the new root node? - would simplify the code if we did. - Can be added as an after thought if needed. Pretty easy. - Not really, as it possible this would change all the time. - We may want to add this, as it will solve having to re-transform them. - On the other hand this could be done in hardware with gf+ cards.

----------------------------------------------------------------------

--------------------------------------------------------------------- Order of the operations. - Things that need to be done in order to get the model transformed.

Set up stuff. - things to do around load time.

From the milk bones set up: - BoneHeirachy - Set up the relative bones. - Convert the Euler angle milkshape rotations into quaternions. - Convert the milkshape positions into quaternions. Q(Px, Py, Pz, w =0.0) - rotation, position quaternions multiplied and stored.

  • Time2Keyframe_Map - KeyframeNumber2Time_Map

AbsoluteBones are made from RelativeBones. For each keyframe. Multiply the bones down the heirarchy. child.absolute = parent.absolute * child.relative

Per frame stuff.

Get current time in animation.

From Time2Keyframe_Map grab two keyframes on either side of current time.

For every absolute quat: Interpolate between two keyframes: t1 = current_time_in_animation - kf_a.time t2 = kf_b.time -kf_a.time slerp = t1/t2 frame_now = quat_slerp(kf_a.absolute, kf_b.absolute, slerp)

Generate the matrices for each absolute quat.

Transform each absolute matrix by the local2world_transform.

Transform verts of the mesh: For vertex which is affected by one bone:

For each absolute matrix transform its verts. If the vert is only affected by one bone: Multiply the vert by the absolute matrix. else: somehow interpolate the different bones. - TODO: ^ - maybe this could be done in the slerp? - storing some extra absolute quats for the verts affected by multiple ones. - this is where bone weights can fit in. For now we will only support one bone per vertex.

Alternate way to transform the skin: For each vertex: look at the weight structure. ulong32 boneIndices - 4 indices to bones. ulong32 weights - 4 weights.

---------------------------------------------------------------------

Optimizations. --------------------------------------------------------------------- When a key frame does not have any translations the transform of the vertices can be optimized to only use a 3x3 rot, instead of a 4x4. - There may be other optimizations depending on the bones state. - Maybe we could store a BONE_STATE int which will allow us to quickly identify a type of bone? This would allow us to quickly see if the bone has no translation. - We could group bones of similar nature together to make the transforms quicker. Eg all bones with no translation part could be stuck together. - Remember that we need to apply a local2world transform to all of the different absolute matrices.

We may be able to cache certain different transforms. - I'm pretty sure there will be many repeated transforms.

A cheap way to interpolate between keyframes would be linear using the mesh's verts. This would involve calculating the mesh for each key frame, and then interpolating between each vertex in meshes a, and b.

Perhaps this could be an optional thing. To be used for slow computers, when a character is far away, or when the difference in time or movement of the character is really small.

A downside to this is that you need to keep at least three sets of the mesh around at any time.

An upside to this is that interpolation can be done on lighting values too.

---------------------------------------------------------------------

--------------------------------------------------------------------- TODOS:

Future todos: - have keyframe data for seperate parts of the skeleton. - eg make the hand have it's own keyframes. - This would complicate how to construct the absolute quats. - You would recalculate down from the animation for that part. - so if the arm was using some extra ones we'd go from there.

  • Probably not so useful until the animation tool supports it.

  • Incorporate bone weights into it. - Milkshape doesn't support these, however others(characterfx) do.

  • Look at the different ways to accelerate these with hardware. - ati, and nvidia have things to do this from geforce up.

---------------------------------------------------------------------

--------------------------------------------------------------------- Dependencies - a list of different dependencies that need to be considered. - helps with caching different things.

---------------------------------------------------------------------

--------------------------------------------------------------------- OLD Order of the operations.

X Convert the axis angle milkshape rotations into quaternions.

X The translations should also be converted into quaternions, X and multiplied by the rotation part. Q(Px, Py, Pz, w =0.0)

X Have an absolute quaternion, and a relative one for each bone.

X Quats should be seperate for the current frame that is to be rendered. X - that is the final bones for the current frame should be in a single X array. X - this is so that they may be easily converted to matrices.

X Absolute matrices for the current frame should be made. X - these matrices include

For each keyframe. Multiply the bones down the heirarchy. child.absolute = parent.absolute * child.relative

To interpolate between two keyframes we do: t1 = current_time_in_animation - keyframe_a.time t2 = keyframe_b.time -keyframe_a.time slerp = t1/t2 frame_now = quat_slerp(keyframe_a.absolute, keyframe_b.absolute, slerp)

Any time a bones rotation changes we need to recalculate all of its children.

To transform verts of the mesh: We need the absolute matricies for each bone.

Do we support multiple bones per vertex? If so will we use weighting?

Apply a local2world transform to all of the different absolute matrices. - this should be added as a new root node.

Methods   
__init__
_convert_angles_to_quats
  __init__ 
__init__ ( self,  milk_data )

the data attribute from the milkshape converter.

  _convert_angles_to_quats 
_convert_angles_to_quats ( self )

This converts the different rotations of the bones into quaternions.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/Time2Keyframe_Map.html0000644000175100017510000001411010160167720025522 0ustar renerene00000000000000 Class: Time2Keyframe_Map

Table of Contents

Class: Time2Keyframe_Map urdpyg/milk_skeleton.py

Each bone should be able to have it's own key frames.

time2keyframe_maps[bone_name] -> time2keyframe_map time2keyframe_map[seconds_since_start_of_animation] -> keyframe index's.

Depending on whether we want the animation to loop or stop at the start or the end, we return a keyframe on either side of the time specified.

TODO: we can loop at the start of the keyframes as well as at the end.

Methods   
GetIndicesEitherSideOfTime
Update
UpdateFromBones
__init__
  GetIndicesEitherSideOfTime 
GetIndicesEitherSideOfTime ( self,  time )

time - a float Returns the two keyframe indices either side of the time given.

Exceptions   
"incomplete"
  Update 
Update ( self,  times )

times - a sequence of floats representing keyframes.

  UpdateFromBones 
UpdateFromBones ( self,  milk_bone )

milk_bone - used to get the different times for the keyframes.

  __init__ 
__init__ ( self,  loop=0 )

loop - should we loop the animation back to the start once the last keyframe has been reached?


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/RelativeBones.html0000644000175100017510000000705710160167720025037 0ustar renerene00000000000000 Class: RelativeBones

Table of Contents

Class: RelativeBones urdpyg/milk_skeleton.py

Stores transforms relative to it's parent. There is a seperate set of these for each of the keyframes.

  • Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of four elements ). - translation quats(array of four elements ).

TODO: find if a quatRotation quatTranslation is equal to a matrixRotation matrixTranslation.

Methods   
Update
  Update 
Update ( self,  milk_bone )

From the milkshape data transform it into an internal representation.

milk_bone - a bone from the converter.

  • Convert the Euler angle milkshape rotations into quaternions. - Convert the milkshape positions into quaternions. Q(Px, Py, Pz, w =0.0) - rotation, position quaternions multiplied and stored.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton/Vert2Bone_Map.html0000644000175100017510000000621310160167720024671 0ustar renerene00000000000000 Class: Vert2Bone_Map

Table of Contents

Class: Vert2Bone_Map urdpyg/milk_skeleton.py
Methods   
Update
__init__
  Update 
Update ( self,  milk_data )

  __init__ 
__init__ ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milkviewer4/0000755000175100017510000000000010160167720021000 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/milkviewer4/MilkshapeModel.html0000644000175100017510000001666310160167720024600 0ustar renerene00000000000000 Class: MilkshapeModel

Table of Contents

Class: MilkshapeModel urdpyg/milkviewer4.py

Loads and displays a milk shape 3d model.

Base Classes   
MilkshapeModelLoader
Methods   
Display
Load
LoadImage
ReloadTextures
_FinishDisplay
_MiddleDisplay
_StartDisplay
  Display 
Display ( self )

Call this to draw.

  Load 
Load ( self,  file_name )

  LoadImage 
LoadImage ( self,  filename )

  ReloadTextures 
ReloadTextures ( self )

reloads any textures. Useful when a context change happens.

  _FinishDisplay 
_FinishDisplay ( self )

Call after drawing.

  _MiddleDisplay 
_MiddleDisplay ( self )

  _StartDisplay 
_StartDisplay ( self )

This is all the stuff you call before drawing.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/music/0000755000175100017510000000000010160167720017656 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/music/Music.html0000644000175100017510000002375210160167720021635 0ustar renerene00000000000000 Class: Music

Table of Contents

Class: Music urdpyg/music.py

Useage:

m = Music() m.Play("intro") m.Play("bla")

Need a directory ../data/music/intro.ogg

Methods   
GetFileNames
Load
Pause
Play
SetLoudVol
SetMaxVol
Stop
UnPause
Update
__init__
music_play_callback
  GetFileNames 
GetFileNames ( self,  path=os.path.join( "..", "data", "music" ) )

returns a dict of file names to be used as music. keyed by the file name without path, and .ogg. path - to the file names.

  Load 
Load ( self,  music_type )

music_type - one of the music types from the sound_config.

  Pause 
Pause ( self )

pauses the music.

  Play 
Play (
        self,
        music_type,
        loop=-1,
        )

Starts playing the music.

  SetLoudVol 
SetLoudVol ( self,  vol )

louder than max volume. this is for special occasions.

  SetMaxVol 
SetMaxVol ( self,  vol )

sets the maximum volume for the music.

  Stop 
Stop ( self )

  UnPause 
UnPause ( self )

  Update 
Update ( self,  elapsed_time )

To be called frequently.

  __init__ 
__init__ ( self )

  music_play_callback 
music_play_callback ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/some_sound/0000755000175100017510000000000010160167720020711 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/some_sound/SoundManager.html0000644000175100017510000001624010160167720024165 0ustar renerene00000000000000 Class: SoundManager

Table of Contents

Class: SoundManager urdpyg/some_sound.py

Controls loading, mixing, and playing the sounds. Having seperate classes allows different groups of sounds to be loaded, and unloaded from memory easily.

Methods   
GetSound
Initialize
Load
Play
PlayMusic
__init__
_debug
  GetSound 
GetSound ( self,  name )

Returns a Sound object for the given name.

  Initialize 
Initialize ( self )

Initializes the mixer.

  Load 
Load ( self,  names=sound_list )

Loads sounds.

  Play 
Play (
        self,
        name,
        volume=[ 1.0, 1.0 ],
        wait=1,
        )

Plays the sound with the given name. name - of the sound. volume - left and right. Ranges 0.0 - 1.0 wait - if there is a sound of this type playing wait for it.

  PlayMusic 
PlayMusic ( self,  musicname )

Plays a music track. Only one can be played at a time. So if there is one playing, it will be stopped and the new one started.

  __init__ 
__init__ ( self )

  _debug 
_debug (
        self,
        x,
        debug_level=0,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/some_sprites/0000755000175100017510000000000010160167720021252 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/some_sprites/Animation.html0000644000175100017510000002602210160167720024061 0ustar renerene00000000000000 Class: Animation

Table of Contents

Class: Animation urdpyg/some_sprites.py

For telling which of the frames should be drawn.

Howto use:

a = Animation(...) a.Start()

if a.StillGoing(): new_frame_to_draw = a.NewFrame() if new_frame_to_draw: draw(new_frame_to_draw) else: # old frame to be rendered. pass else: # figure out what to do at end of anim. pass

Methods   
A__nonzero__
GetLengthOfAnim
GetName
GetNumTimesPlayed
NewFrame
SetUpAnimationData
Start
StillGoing
_GetFrameGivenTimeInAnim
__init__
  A__nonzero__ 
A__nonzero__ ( self )

Used to see if the animation is still going.

Exceptions   
"Not implemented"
  GetLengthOfAnim 
GetLengthOfAnim ( self )

  GetName 
GetName ( self )

  GetNumTimesPlayed 
GetNumTimesPlayed ( self )

Returns the number of times the animation has been played.

  NewFrame 
NewFrame ( self )

Returns the frame name if there is a new frame needed for the animation. Otherwise returns 0.

  SetUpAnimationData 
SetUpAnimationData ( self,  animation_data )

Sets up the animation data ready for processing.

  Start 
Start ( self,  loop=1 )

Starts the animation at the beginning.

  StillGoing 
StillGoing ( self )

returns the frame name if still going else, returns 0 if finished.

  _GetFrameGivenTimeInAnim 
_GetFrameGivenTimeInAnim ( self,  time_in_anim )

Returns the frame name we should be rendering given a time in the anim.

  __init__ 
__init__ (
        self,
        animation_data,
        name,
        loop=1,
        )

animation_data - a list of tuples (frame_name, time). The time part says for how long in the animation that the frame should be shown. Must have at least one element.

loop - should the animation loop. If 0 the animation will return the last frame when it gets to the end. If -1 the animation will loop for ever. If non zero the animation will loop that many times.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/some_sprites/A.html0000644000175100017510000000621610160167720022325 0ustar renerene00000000000000 Class: A

Table of Contents

Class: A urdpyg/some_sprites.py
Base Classes   
pygame.sprite.Sprite
Methods   
__init__
  __init__ 
__init__ ( self,  im_name )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/some_sprites/ImageAnimation.html0000644000175100017510000002627310160167720025034 0ustar renerene00000000000000 Class: ImageAnimation

Table of Contents

Class: ImageAnimation urdpyg/some_sprites.py
Base Classes   
pygame.sprite.Sprite
Methods   
LoadAnimationData
LoadImages
MakeScaledVersion
ResetImageRect
SetLogicalImages
SetPosition
StartAnim
__init__
move
update
  LoadAnimationData 
LoadAnimationData ( self )

  LoadImages 
LoadImages ( self,  image_dict={} )

image_dict - should be a dictionary which is keyed by the frame name, and valued by an image for that frame. If the dict is {} then the images are loaded from disk.

  MakeScaledVersion 
MakeScaledVersion (
        self,
        key_name,
        size,
        )

keyname - what the scaled version should be called. eg (really small, (0,0)) size - x,y tuple.

  ResetImageRect 
ResetImageRect ( self )

After changing the self.images dict this should be called.

  SetLogicalImages 
SetLogicalImages ( self,  x_y )

Sets the appropriate images for the place on the logical grid.

  SetPosition 
SetPosition ( self,  position )

  StartAnim 
StartAnim (
        self,
        anim_name,
        loop=1,
        )

Exceptions   
"should be a frame here"
  __init__ 
__init__ (
        self,
        animation_set_name,
        initial_animation,
        )

animation_name - name of the animation set to use.

  move 
move ( self,  direction )

  update 
update (
        self,
        frame_name=None,
        percent_trans=None,
        )

frame_name - this is the name of the frame to draw. percent_trans - is the alpha value for which to draw

If frame_name, and percent_trans are None then they are worked out for themselves.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/some_sprites/Timer.html0000644000175100017510000000774310160167720023233 0ustar renerene00000000000000 Class: Timer

Table of Contents

Class: Timer urdpyg/some_sprites.py
Methods   
Start
__init__
__nonzero__
  Start 
Start ( self,  length )

length is the amount of time that this timer should go for.

  __init__ 
__init__ ( self,  length )

a = Timer(10) # if the timer is finished. if a: print "asdf"

  __nonzero__ 
__nonzero__ ( self )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/sounds/0000755000175100017510000000000010160167720020051 5ustar renerene00000000000000new_rdpyg/docs/urdpyg/urdpyg/sounds/SoundManager.html0000644000175100017510000002172010160167721023325 0ustar renerene00000000000000 Class: SoundManager

Table of Contents

Class: SoundManager urdpyg/sounds.py

Controls loading, mixing, and playing the sounds. Having seperate classes allows different groups of sounds to be loaded, and unloaded from memory easily.

Useage: sm = SoundManager() sm.Load()

Methods   
GetSound
Load
Play
PlayMusic
Stop
StopAll
Update
__init__
_debug
  GetSound 
GetSound ( self,  name )

Returns a Sound object for the given name.

  Load 
Load (
        self,
        sound_list=[],
        sound_path=".",
        )

Loads sounds.

  Play 
Play (
        self,
        name,
        volume=[ 1.0, 1.0 ],
        wait=0,
        loop=0,
        )

Plays the sound with the given name. name - of the sound. volume - left and right. Ranges 0.0 - 1.0 wait - used to control what happens if sound is allready playing: 0 - will not wait if sound playing. play anyway. 1 - if there is a sound of this type playing wait for it. 2 - if there is a sound of this type playing do not play again. loop - number of times to loop. -1 means forever.

  PlayMusic 
PlayMusic ( self,  musicname )

Plays a music track. Only one can be played at a time. So if there is one playing, it will be stopped and the new one started.

  Stop 
Stop ( self,  name )

  StopAll 
StopAll ( self )

stops all sounds.

  Update 
Update ( self,  elapsed_time )

  __init__ 
__init__ (
        self,
        sound_list=SOUND_LIST,
        sound_path=SOUND_PATH,
        )

  _debug 
_debug (
        self,
        x,
        debug_level=0,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milk_skeleton.html0000644000175100017510000001336310160167720022272 0ustar renerene00000000000000 Module: milk_skeleton

Table of Contents

Module: milk_skeleton urdpyg/milk_skeleton.py

Copyright (C) 2002 by Rene Dudfield.

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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Imported modules   
import Numeric
import UserDict
import bisect
import os
import string
import sys
import time
from urdpyg.converters import ms3d_ascii_importer
Classes   

AbsoluteBones

Stores the absolute transforms. There is a seperate one of these

Bone2Vert_Map

a list of indices for the verts that each bone should transform.

BoneHeirarchy

Which bones are parents/children of which other bones.

BoneName2BoneNumber_Map

mapping of bone names to a number in the bone index.

MilkSkeleton

----------------------------------------------------------------------

MilkshapeModelLoader

responsible for loading a milkshape model.

RelativeBones

Stores transforms relative to it's parent. There is a seperate set

Time2Keyframe_Map

Each bone should be able to have it's own key frames.

Vert2Bone_Map


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/__init__.html0000644000175100017510000000265210160167720021170 0ustar renerene00000000000000 Module: __init__

Table of Contents

Module: __init__ urdpyg/__init__.py

The unstable part of rdpyg.

Contains modules that are not very well designed, tested, or commented, and which are not planned to be have the same api stick around for ages.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/gl_images.html0000644000175100017510000001034710160167720021360 0ustar renerene00000000000000 Module: gl_images

Table of Contents

Module: gl_images urdpyg/gl_images.py
Imported modules   
from OpenGL.GL import *
import os
import pygame
import time
Functions   
load_gl_textureRGB
load_gl_textureRGBA
  load_gl_textureRGB 
load_gl_textureRGB (
        name,
        flip=1,
        internal_format=GL_RGB,
        )

returns a texid for the loaded image.

  load_gl_textureRGBA 
load_gl_textureRGBA (
        name,
        flip=1,
        internal_format=GL_RGBA,
        )


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/index.html0000644000175100017510000000714610160167721020544 0ustar renerene00000000000000 HappyDoc Generated Documentation: urdpyg

Table of Contents

HappyDoc Generated Documentation: urdpyg  

The unstable part of rdpyg.

Contains modules that are not very well designed, tested, or commented, and which are not planned to be have the same api stick around for ages.

Modules and Packages   

urdpyg/

urdpyg

The unstable part of rdpyg.

converters

HappyDoc Generated Documentation: urdpyg.converters

gl_images

map

HappyDoc Generated Documentation: urdpyg.map

milk_skeleton

Copyright (C) 2002 by Rene Dudfield.

milkviewer4

music

some_sound

file: some_sound.py

some_sprites

file: some_sprites.py

sounds

file: sounds.py


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/some_sprites.html0000644000175100017510000002175310160167720022150 0ustar renerene00000000000000 Module: some_sprites

Table of Contents

Module: some_sprites urdpyg/some_sprites.py

file: some_sprites.py purpose: animation, sprite playing.

Imported modules   
import bisect
import glob
import os
import os.path
import pygame
from pygame.locals import *
import sys
import time
Functions   
animation_factory
get_background_names
get_character_frame_names
load_image
read_anim_data
  animation_factory 
animation_factory ( anim_data,  loop=1 )

Returns a dict keyed by anim_name valued by Animation instances. anim_data - keyed by anim name, valued by a list of tuples(frame_name, length). loop - passed through to Animation class.

  get_background_names 
get_background_names ( base_dir )

TODO: needs fixing/testing.

  get_character_frame_names 
get_character_frame_names ( the_layer_order,  base_dir=".." )

returns a dict keyed by character name, valued by a dict(keyed by meaningful name, valued by image path name).

  load_image 
load_image (
        name,
        colorkey=None,
        convert_alpha=0,
        )

Exceptions   
SystemExit, message
  read_anim_data 
read_anim_data ( character_name,  base_dir=".." )

Reads the animation data from the characters anim.py file.

Classes   

A

Animation

For telling which of the frames should be drawn.

ImageAnimation

Timer


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/milkviewer4.html0000644000175100017510000000574510160167720021701 0ustar renerene00000000000000 Module: milkviewer4

Table of Contents

Module: milkviewer4 urdpyg/milkviewer4.py
Imported modules   
from OpenGL.GL import *
from numeric_gl import *
import pygame
from urdpyg import gl_images
from urdpyg.converters import ms3d_ascii_importer
from urdpyg.milk_skeleton import *
Classes   

MilkshapeModel

Loads and displays a milk shape 3d model.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/music.html0000644000175100017510000000567210160167720020556 0ustar renerene00000000000000 Module: music

Table of Contents

Module: music urdpyg/music.py
Imported modules   
import config
import glob
import os
import pygame.mixer
import pygame.mixer_music
from rdpyg.util import cyclic_list, vtimer
import sound_config
Classes   

Music

Useage:


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/some_sound.html0000644000175100017510000001046310160167720021603 0ustar renerene00000000000000 Module: some_sound

Table of Contents

Module: some_sound urdpyg/some_sound.py

file: some_sound.py purpose: to load all the sounds, and manage the playing of them.

Probably have different sets of sounds in here somehow.

Imported modules   
import glob
import os
import pygame
from pygame.locals import *
Functions   
get_sound_list
  get_sound_list 
get_sound_list ()

Classes   

SoundManager

Controls loading, mixing, and playing the sounds.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/urdpyg/sounds.html0000644000175100017510000001114610160167721020743 0ustar renerene00000000000000 Module: sounds

Table of Contents

Module: sounds urdpyg/sounds.py

file: sounds.py purpose: to load all the sounds, and manage the playing of them.

Probably have different sets of sounds in here somehow.

NOTE: not using pygames channel queueing as it only allows one sound to be queued. Also the sound can only be queued on a certain channel.

Imported modules   
import glob
import os
import pygame
from pygame.locals import *
import time
Functions   
get_sound_list
  get_sound_list 
get_sound_list ( path=SOUND_PATH )

gets a list of sound names without thier path, or extension.

Classes   

SoundManager

Controls loading, mixing, and playing the sounds.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/docs/urdpyg/index.html0000644000175100017510000000405610160167721017227 0ustar renerene00000000000000 HappyDoc Generated Documentation

Table of Contents

HappyDoc Generated Documentation  
Modules and Packages   

urdpyg

The unstable part of rdpyg.


Table of Contents

This document was automatically generated on Thu Dec 16 13:15:41 2004 by HappyDoc version 2.1 new_rdpyg/examples/0000755000175100017510000000000010156245512014601 5ustar renerene00000000000000new_rdpyg/examples/.minimal_gl.py.swp0000644000175100017510000003000010156245516020146 0ustar renerene00000000000000b0VIM 6.3gbÝ@7*Crenegrace/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/examples/minimal_gl.py3210#"! UtpÿadMßÞ´¦˜—–|{qhWNMLa.Stop()print a.GetFps()a.Loop()a.Start()a = the_app_gl.TheAppGL()pygame.init()import pygame# We have to initialise pygame ourselves.from rdpyg.app import the_app_glnew_rdpyg/examples/minimal.py0000644000175100017510000000023210067257511016601 0ustar renerene00000000000000from rdpyg.app import the_app # We have to initialise pygame ourselves. import pygame pygame.init() a = the_app.TheApp() a.Start() a.Loop() a.Stop() new_rdpyg/examples/minimal_gl.py0000644000175100017510000000026310067261147017267 0ustar renerene00000000000000from rdpyg.app import the_app_gl # We have to initialise pygame ourselves. import pygame pygame.init() a = the_app_gl.TheAppGL() a.Start() a.Loop() print a.GetFps() a.Stop() new_rdpyg/rdpyg/0000755000175100017510000000000010160170501014076 5ustar renerene00000000000000new_rdpyg/rdpyg/app/0000755000175100017510000000000010160420572014664 5ustar renerene00000000000000new_rdpyg/rdpyg/app/the_app_gl.py0000755000175100017510000001045310065303172017346 0ustar renerene00000000000000import the_app import pygame from pygame.locals import DOUBLEBUF, OPENGL, FULLSCREEN, QUIT, KEYDOWN, K_ESCAPE from OpenGL.GL import glMatrixMode, GL_PROJECTION, glLoadIdentity, glClearColor, glClear, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, glGetFloatv, GL_PROJECTION_MATRIX, GL_MODELVIEW, glViewport, glGetDoublev, GL_MODELVIEW_MATRIX from OpenGL.GLU import gluPerspective, gluUnProject class TheAppGL(the_app.TheApp): def Display(self): """ A default display. Which clears the color buffer and depth buffer. """ self._debug("running display", 4) glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) def InitDisplay(self, width, height, first_time = 0): """ A default InitDisplay. """ self._debug("initializing display", 4) if first_time: full_display_flags = DOUBLEBUF | OPENGL | FULLSCREEN display_flags = DOUBLEBUF | OPENGL if self.full_screen: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") if pygame.display.mode_ok((width, height), full_display_flags ): self.screen = pygame.display.set_mode((width, height), full_display_flags) else: raise ValueError("error initializing display, can not get mode") else: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") else: if self.full_screen: display_flags = DOUBLEBUF | OPENGL | FULLSCREEN else: display_flags = DOUBLEBUF | OPENGL if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") def Start(self): """ """ self._debug("starting", 4) width, height = 640, 480 #width, height = 1024, 768 self.width, self.height = width, height self.InitDisplay(width, height, first_time = 1) glViewport(0,0, width, height) # sets up the projection matrix. self.SetupProjection(width, height) self.Load() def SetupProjection(self, width = 640, height = 480, zNear = 5., zFar = 300.): """ Sets up the projection matrix for opengl. """ # set the projection transformation glMatrixMode(GL_PROJECTION) glLoadIdentity() #TODO: replace the glu call with something else. #gluPerspective(45.0, float(width) / height, scale * 50.0, scale * 1000.0) #gluPerspective(45.0, float(self.width) / float(self.height), 5.0, 1000.0) self.zNear = zNear self.zFar = zFar self.buffer_calc_a = self.zFar / ( self.zFar - self.zNear ) self.buffer_calc_b = self.zFar * self.zNear / ( self.zNear - self.zFar ) gluPerspective(45.0, float(width) / float(height), self.zNear, self.zFar) self.gl_projection_matrix = glGetFloatv(GL_PROJECTION_MATRIX) # set the model transformation glMatrixMode(GL_MODELVIEW) def GetWorldCoords(self, x,y, camera_z): """ returns (x,y,z) given x,y pygame screen coords. NOTE: try and get the model view matrix back to the camera position when using. """ y = self.height - y mod = glGetDoublev(GL_MODELVIEW_MATRIX) proj = glGetDoublev(GL_PROJECTION_MATRIX) #view = glGetIntegerv(GL_VIEWPORT) view = (0, 0, self.width, self.height) z = abs(camera_z) z_buffer_value = self.buffer_calc_a +self.buffer_calc_b / z objx, objy, objz = gluUnProject(x,y,z_buffer_value, mod, proj,view) return (objx, objy, objz) new_rdpyg/rdpyg/app/__init__.py0000644000175100017510000000005710160167023016776 0ustar renerene00000000000000""" Common functionality for applications. """ new_rdpyg/rdpyg/app/__init__.pyc0000644000175100017510000000024610160170543017142 0ustar renerene00000000000000;ò îÀAc@s dZdS(s( Common functionality for applications. N(s__doc__(((s./rdpyg/app/__init__.pys?snew_rdpyg/rdpyg/app/the_app.py0000755000175100017510000002062210160167011016657 0ustar renerene00000000000000#file: the_app.py #purpose: a base class for making applications from. """ TheApp is a class for making a game like application, implementing functionality common in many games. The idea is to make constructing games and demos quick, with minimal code. TODO: a way to chose between display flip and update. without overriding the whole method. There are a number of different methods with default implementations to save work. Most of these can be overridden if you need to specialise any parts. = How the main loop works. = TheApp class has a couple of different ways which it handles the main loop internally. It can use a while loop or the twisted reactor. However by using the methods provided you should not have to modify this. It can be instructional to have at a look at the source for different methods, so that overriding them can be easy. This is the 2d pygame version of the class. There is an opengl version named rdpyg.app.the_app_gl.TheAppGL = Commonly overridden methods = * Display * Your drawing code. * Update * Updating your game logic, game play, and game ai. * HandleEvents * Code to handle user input, operating system interaction, and other events. * Load * Code to load your game data. Like images, sounds etc. = Order of operation = The order in which the different methods get called is to update your game objects, handle user input, do your display changes. Start() InitDislpay() Load() Loop() Before loops starts looping: LoopInit() SetupTiming() Every 'tic' or frame of loop: Update() HandleEvents() DoBeforeDisplay() Display() DoAfterFlip() """ try: import config except: class blablablabla: USE_TWISTED = 0 full_screen = 0 config = blablablabla() import time import pygame from pygame.locals import DOUBLEBUF, OPENGL, FULLSCREEN, QUIT, KEYDOWN, K_ESCAPE # TODO: speed up loading time. this takes 0.2959 to load. if config.USE_TWISTED: import twisted.internet.reactor import traceback import sys class TheApp: """ An application class to handle lots of common things within games, and game like applications, using pygame. A lot of the methods are meant to be overrided. However they all come with sane default implementations. Useage: a = TheApp() a.Start() a.Loop() a.Stop() """ def __init__(self, debug_level = 0): self._debug_level = debug_level self.frames = 0 self.full_screen = config.full_screen def _debug(self, x, debug_level = 0): """ """ if self._debug_level > debug_level: print x def Display(self): """ This is called before the display is flipped(or updated). Your drawing code should go in here. """ self._debug("running display", 4) def InitDisplay(self, width, height, first_time = 0): """ A default InitDisplay. first_time - useful for working around some buggy systems. make it true if this is the first time calling it. """ self._debug("initializing display", 4) if first_time: full_display_flags = DOUBLEBUF | FULLSCREEN display_flags = DOUBLEBUF if self.full_screen: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") if pygame.display.mode_ok((width, height), full_display_flags ): self.screen = pygame.display.set_mode((width, height), full_display_flags) else: raise ValueError("error initializing display, can not get mode") else: if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") else: if self.full_screen: display_flags = DOUBLEBUF | FULLSCREEN else: display_flags = DOUBLEBUF if pygame.display.mode_ok((width, height), display_flags ): self.screen = pygame.display.set_mode((width, height), display_flags) else: raise ValueError("error initializing display, can not get mode") def Stop(self): """ Called when we want to stop. """ pygame.quit() def Start(self): """ Do the game loading. """ self._debug("starting", 4) width, height = 640, 480 #width, height = 1024, 768 self.width, self.height = width, height self.InitDisplay(width, height, first_time = 1) self.Load() def Load(self): """ For loading stuff. """ def HandleEvents(self, event_list): """ should handle the events every game tic. """ for event in event_list: if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): self.Stop() return 0 return 1 def Update(self, elapsed_time): """ update any game state. """ def OneTic(self): """ Does one game 'tic' worth of stuff. Should return 1 if not wanting to quit. If wanting to quit return 0. """ try: self.current_time, self.elapsed_time = self.TicTiming() if not self.DoBeforeHandlingEvents(): if config.USE_TWISTED: twisted.internet.reactor.stop() #self.Stop() return 0 else: return 0 self.Update(self.elapsed_time) event_list = pygame.event.get() if not self.HandleEvents(event_list): if config.USE_TWISTED: twisted.internet.reactor.stop() #self.Stop() return 0 else: return 0 self.DoBeforeDisplay() self.Display() #flip_time1 = time.time() pygame.display.flip() #flip_time2 = time.time() #flip_time = flip_time2 - flip_time1 #print "flip_time:", flip_time self.DoAfterFlip() self.frames += 1 self.last_time = self.current_time if config.USE_TWISTED: # run as fast as it can. twisted.internet.reactor.callLater(0.0, self.OneTic) else: return 1 except: traceback.print_exc(sys.stderr) # we have an error, quit instead. if config.USE_TWISTED: twisted.internet.reactor.stop() return 0 def DoAfterFlip(self): """ Called after flip is done. """ def DoBeforeDisplay(self): """ Stuff done before Display() is called. """ def DoBeforeHandlingEvents(self): """ Stuff done before we handle the events. Should return 0 to quit. """ return 1 def TicTiming(self): """ Call this once per tic to update the timing. """ current_time = time.time() elapsed_time = current_time - self.last_time self.total_elapsed_time += elapsed_time return (current_time, elapsed_time) def GetFps(self): """ Returns the frames per second since the timing has begun. """ if self.total_elapsed_time == 0: return 0. return self.frames/self.total_elapsed_time def LoopInit(self): """ Should put use loop initialisation stuff here. """ def SetupTiming(self): """ Sets up some timing code. """ self.last_time = time.time() self.total_elapsed_time = 0. def Loop(self): """ Starts the game looping. Will eventually return. """ self.LoopInit() self.SetupTiming() if config.USE_TWISTED: twisted.internet.reactor.callLater(0.0, self.OneTic) twisted.internet.reactor.run() else: while 1: if not self.OneTic(): break new_rdpyg/rdpyg/app/the_app.pyc0000644000175100017510000002310310160170546017023 0ustar renerene00000000000000;ò îÀAc@s¶dZy dkZWn#dfd„ƒYZeƒZnXdkZdkZdklZlZlZl Z l Z l Z ei o dk ZndkZdkZdfd„ƒYZdS(s4 TheApp is a class for making a game like application, implementing functionality common in many games. The idea is to make constructing games and demos quick, with minimal code. TODO: a way to chose between display flip and update. without overriding the whole method. There are a number of different methods with default implementations to save work. Most of these can be overridden if you need to specialise any parts. = How the main loop works. = TheApp class has a couple of different ways which it handles the main loop internally. It can use a while loop or the twisted reactor. However by using the methods provided you should not have to modify this. It can be instructional to have at a look at the source for different methods, so that overriding them can be easy. This is the 2d pygame version of the class. There is an opengl version named rdpyg.app.the_app_gl.TheAppGL = Commonly overridden methods = * Display * Your drawing code. * Update * Updating your game logic, game play, and game ai. * HandleEvents * Code to handle user input, operating system interaction, and other events. * Load * Code to load your game data. Like images, sounds etc. = Order of operation = The order in which the different methods get called is to update your game objects, handle user input, do your display changes. Start() InitDislpay() Load() Loop() Before loops starts looping: LoopInit() SetupTiming() Every 'tic' or frame of loop: Update() HandleEvents() DoBeforeDisplay() Display() DoAfterFlip() Ns blablablablacBstZdZdZRS(Ni(s__name__s __module__s USE_TWISTEDs full_screen(((s./rdpyg/app/the_app.pys blablablablaDs(s DOUBLEBUFsOPENGLs FULLSCREENsQUITsKEYDOWNsK_ESCAPEsTheAppcBs¹tZdZdd„Zdd„Zd„Zdd„Zd„Zd„Zd„Z d „Z d „Z d „Z d „Z d „Zd„Zd„Zd„Zd„Zd„Zd„ZRS(sN An application class to handle lots of common things within games, and game like applications, using pygame. A lot of the methods are meant to be overrided. However they all come with sane default implementations. Useage: a = TheApp() a.Start() a.Loop() a.Stop() icCs"||_d|_ti|_dS(Ni(s debug_levelsselfs _debug_levelsframessconfigs full_screen(sselfs debug_level((s./rdpyg/app/the_app.pys__init__ls  cCs|i|jo |GHndS(s N(sselfs _debug_levels debug_levelsx(sselfsxs debug_level((s./rdpyg/app/the_app.pys_debugsscCs|iddƒdS(st This is called before the display is flipped(or updated). Your drawing code should go in here. srunning displayiN(sselfs_debug(sself((s./rdpyg/app/the_app.pysDisplay{scCsƒ|iddƒ|ottB}t}|io˜ti i ||f|ƒo"ti i ||f|ƒ|_n tdƒ‚ti i ||f|ƒo"ti i ||f|ƒ|_qtdƒ‚qti i ||f|ƒo"ti i ||f|ƒ|_qtdƒ‚ni|iottB}nt}ti i ||f|ƒo"ti i ||f|ƒ|_n tdƒ‚dS(s³ A default InitDisplay. first_time - useful for working around some buggy systems. make it true if this is the first time calling it. sinitializing displayis,error initializing display, can not get modeN(sselfs_debugs first_times DOUBLEBUFs FULLSCREENsfull_display_flagss display_flagss full_screenspygamesdisplaysmode_okswidthsheightsset_modesscreens ValueError(sselfswidthsheights first_timesfull_display_flagss display_flags((s./rdpyg/app/the_app.pys InitDisplay…s*  " "" "cCstiƒdS(s Called when we want to stop. N(spygamesquit(sself((s./rdpyg/app/the_app.pysStop½scCs^|iddƒddf\}}||f\|_|_|i||ddƒ|iƒdS(s Do the game loading. sstartingii€iàs first_timeiN(sselfs_debugswidthsheights InitDisplaysLoad(sselfswidthsheight((s./rdpyg/app/the_app.pysStartÅs cCsdS(s For loading stuff. N((sself((s./rdpyg/app/the_app.pysLoadÕscCs[xP|D]H}|itjp|itjo |itjo|iƒdSqqWdSdS(s2 should handle the events every game tic. iiN( s event_listseventstypesQUITsKEYDOWNskeysK_ESCAPEsselfsStop(sselfs event_listsevent((s./rdpyg/app/the_app.pys HandleEventsÚs0  cCsdS(s update any game state. N((sselfs elapsed_time((s./rdpyg/app/the_app.pysUpdateåscCs_y|iƒ\|_|_|iƒ o*tiotii i ƒdSqSdSn|i |iƒt i iƒ}|i|ƒ o*tiotii i ƒdSq­dSn|iƒ|iƒt iiƒ|iƒ|id7_|i|_tiotii id|iƒndSWn9titiƒtiotii i ƒndSnXdS(sŽ Does one game 'tic' worth of stuff. Should return 1 if not wanting to quit. If wanting to quit return 0. iif0.0N(sselfs TicTimings current_times elapsed_timesDoBeforeHandlingEventssconfigs USE_TWISTEDstwistedsinternetsreactorsstopsUpdatespygameseventsgets event_lists HandleEventssDoBeforeDisplaysDisplaysdisplaysflips DoAfterFlipsframess last_times callLatersOneTics tracebacks print_excssyssstderr(sselfs event_list((s./rdpyg/app/the_app.pysOneTicës:         cCsdS(s$ Called after flip is done. N((sself((s./rdpyg/app/the_app.pys DoAfterFlip(scCsdS(s0 Stuff done before Display() is called. N((sself((s./rdpyg/app/the_app.pysDoBeforeDisplay-scCsdSdS(sV Stuff done before we handle the events. Should return 0 to quit. iN((sself((s./rdpyg/app/the_app.pysDoBeforeHandlingEvents1scCs6tiƒ}||i}|i|7_||fSdS(s6 Call this once per tic to update the timing. N(stimes current_timesselfs last_times elapsed_timestotal_elapsed_time(sselfs elapsed_times current_time((s./rdpyg/app/the_app.pys TicTiming9s   cCs*|idjodSn|i|iSdS(sC Returns the frames per second since the timing has begun. if0.0N(sselfstotal_elapsed_timesframes(sself((s./rdpyg/app/the_app.pysGetFpsDscCsdS(s8 Should put use loop initialisation stuff here. N((sself((s./rdpyg/app/the_app.pysLoopInitNscCstiƒ|_d|_dS(s# Sets up some timing code. f0.0N(stimesselfs last_timestotal_elapsed_time(sself((s./rdpyg/app/the_app.pys SetupTimingSscCsq|iƒ|iƒtio-tiiid|i ƒtiii ƒn#xno|i ƒ oPqNqUWdS(s; Starts the game looping. Will eventually return. f0.0iN( sselfsLoopInits SetupTimingsconfigs USE_TWISTEDstwistedsinternetsreactors callLatersOneTicsrun(sself((s./rdpyg/app/the_app.pysLoopZs   (s__name__s __module__s__doc__s__init__s_debugsDisplays InitDisplaysStopsStartsLoads HandleEventssUpdatesOneTics DoAfterFlipsDoBeforeDisplaysDoBeforeHandlingEventss TicTimingsGetFpssLoopInits SetupTimingsLoop(((s./rdpyg/app/the_app.pysTheApp[s&    8     =     (s__doc__sconfigs blablablablastimespygames pygame.localss DOUBLEBUFsOPENGLs FULLSCREENsQUITsKEYDOWNsK_ESCAPEs USE_TWISTEDstwisted.internet.reactorstwisteds tracebackssyssTheApp(s FULLSCREENs tracebacks DOUBLEBUFsTheAppsOPENGLstwistedsKEYDOWNsQUITs blablablablassysspygamestimesconfigsK_ESCAPE((s./rdpyg/app/the_app.pys?>s    +    new_rdpyg/rdpyg/draw/0000755000175100017510000000000010160170505015037 5ustar renerene00000000000000new_rdpyg/rdpyg/draw/pygame/0000755000175100017510000000000010065304046016324 5ustar renerene00000000000000new_rdpyg/rdpyg/draw/pygame/__init__.py0000644000175100017510000000000010065304046020423 0ustar renerene00000000000000new_rdpyg/rdpyg/draw/pyopengl/0000755000175100017510000000000010160170512016672 5ustar renerene00000000000000new_rdpyg/rdpyg/draw/pyopengl/__init__.py0000644000175100017510000000000010065304046020776 0ustar renerene00000000000000new_rdpyg/rdpyg/draw/pyopengl/__init__.pyc0000644000175100017510000000016110160170510021142 0ustar renerene00000000000000;ò &ˆÕ@c@sdS(N((((s!./rdpyg/draw/pyopengl/__init__.pys?snew_rdpyg/rdpyg/draw/pyopengl/particles.py0000755000175100017510000002221410072755676021264 0ustar renerene00000000000000# purpose: particles. from OpenGL.GL import * #from OpenGL.GLU import gluPerspective import random from random import randint import os import pygame import pygame.image class Particle: def __init__(self): self.active = 0 self.life = 0. # fade speed. self.ifade = 0. # Red, green, blue values. self.r = 0. self.g = 0. self.b = 0. # x,y,z position. self.x = 0. self.y = 0. self.z = 0. # x,y,z direction. self.xi = 0. self.yi = 0. self.zi = 0. # x,y,z gravity. self.xg = 0. self.yg = 0. self.zg = 0. class cached_random: #def __init__(self, size_of_cache = 500): # self.size_of_cache = size_of_cache size_of_cache = 5000 rands100 = [] for x in range(size_of_cache): rands100.append(float(random.randint(1,100))) rands60 = [] for x in range(size_of_cache): rands60.append(float(random.randint(1,60))) rands30 = [] for x in range(size_of_cache): rands30.append(float(random.randint(1,30))) cursor30 = 0 cursor60 = 0 cursor100 = 0 def GetRandom100(self): self.cursor100 += 1 if(self.cursor100 >= self.size_of_cache): self.cursor100 = 0 return self.rands100[self.cursor100] def GetRandom60(self): #print self.cursor60 self.cursor60 += 1 if(self.cursor60 >= self.size_of_cache): self.cursor60 = 0 #print self.rands60[self.cursor60] return self.rands60[self.cursor60] def GetRandom30(self): self.cursor30 += 1 if(self.cursor30 >= self.size_of_cache): self.cursor30 = 0 return self.rands30[self.cursor30] class Particles: """ This is a set of particles baby. """ def __init__(self, num_particles): self.num_particles = num_particles if self.num_particles < 11: self.num_particles = 11 self.window = 0 self.zoom = -10 self.slowdown=2.0 self.xspeed = 5. self.yspeed = 2. self.col = 0 self.cube = None self.top = None self.rainbow = 1 self.delay = 0 self.particles = [] for x in range(self.num_particles): self.particles.append(Particle()) self.rand = cached_random() self.rand100 = self.rand.GetRandom100 self.rand60 = self.rand.GetRandom60 self.rand30 = self.rand.GetRandom30 self.colors = [ [1.0,0.5,0.5],[1.0,0.75,0.5],[1.0,1.0,0.5],[0.75,1.0,0.5], [0.5,1.0,0.5],[0.5,1.0,0.75],[0.5,1.0,1.0],[0.5,0.75,1.0], [0.5,0.5,1.0],[0.75,0.5,1.0],[1.0,0.5,1.0],[1.0,0.5,0.75] ] def _debug(self, s, x): pass def DisplayStateBegin(self): glEnable(GL_TEXTURE_2D) glDisable(GL_DEPTH_TEST) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA,GL_ONE) glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST) glHint(GL_POINT_SMOOTH_HINT,GL_NICEST) glBindTexture(GL_TEXTURE_2D, self.tex) def DisplayStateEnd(self): glDisable(GL_BLEND) glEnable(GL_DEPTH_TEST) glDisable(GL_TEXTURE_2D) def Update(self, elapsed_time): """ TODO: """ pass def Display(self): """ A default display. Which clears the color buffer and depth buffer. """ # Disables depth testing. #self.DisplayStateBegin() #TODO translate/rotate for position. self._debug("running display", 4) col0 = self.colors[self.col][0] col1 = self.colors[self.col][1] col2 = self.colors[self.col][2] rand100 = self.rand100 rand60 = self.rand60 slowdown1000 = self.slowdown * 1000 #particle = self.particles #for loop in range(len(self.particles)): for particle in self.particles: #if (particle.active): # Get our x,y,z x = particle.x y = particle.y #z = particle.z + self.zoom z = particle.z # Color it using our particles colors. glColor4f(particle.r,particle.g,particle.b,particle.life) glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex3f(x+0.5,y+0.5,z); glTexCoord2d(0,1); glVertex3f(x-0.5,y+0.5,z); glTexCoord2d(1,0); glVertex3f(x+0.5,y-0.5,z); glTexCoord2d(0,0); glVertex3f(x-0.5,y-0.5,z); glEnd() particle.x+=particle.xi/(slowdown1000) particle.y+=particle.yi/(slowdown1000) #particle.z+=particle.zi/(slowdown1000) particle.xi+=particle.xg particle.yi+=particle.yg particle.zi+=particle.zg particle.life-=particle.fade if (particle.life<0.0): particle.life=1.0 particle.fade=(rand100())/1000.0+0.003 particle.x=0.0 particle.y=0.0 particle.z=0.0 particle.xi=self.xspeed+(rand60())-32.0 particle.yi=self.yspeed+(rand60())-30.0 particle.zi=(rand60())-30.0 particle.r=self.colors[self.col][0] particle.g=self.colors[self.col][1] particle.b=self.colors[self.col][2] particle.r=col0 particle.g=col1 particle.b=col2 self.delay += 1 if self.rainbow and self.delay > 25: self.delay = 0 self.col += 1 if self.col >= len(self.colors): self.col = 0 #self.col += 1 #if(self.col == 11): # self.col = 0 ##glTranslatef(0., 0., self.ztranslate) ##glRotatef(self.xrot, 1.0, 0.0, 0.0) ##glRotatef(self.yrot, 0.0, 1.0, 0.0) #glColor3fv(boxcol[yloop-1]) ##glCallList(self.cube); #glColor3fv(topcol[yloop-1]); ##glCallList(self.top); ##self.xrot+=1.0 ##if(self.xrot >= 360): ## self.xrot = 0. ##self.yrot+=1.0 ##if(self.yrot >= 360): ## self.yrot = 0. ##self.zrot+=1.0 ##if(self.zrot >= 360): ## self.zrot = 0. #self.DisplayStateEnd() def Load(self, with_tex = None, file_name = None): """ with_tex can be an opengl texture. """ if with_tex == None: if file_name == None: self.LoadImagePng(os.path.join("data", "images", "particle.png")) else: self.LoadImagePng(file_name) self.MakeTexture() else: self.tex = with_tex self.InitParticles() def InitParticles(self): particle = self.particles for loop in range(len(self.particles)): particle[loop].active=1 particle[loop].life=1.0 particle[loop].fade= (random.random() * 100) /1000.0+0.003 particle[loop].r=self.colors[loop/(self.num_particles/11)][0] particle[loop].g=self.colors[loop/(self.num_particles/11)][1] particle[loop].b=self.colors[loop/(self.num_particles/11)][2] particle[loop].xi=float( (random.random()*50)-26.0 )*10.0 particle[loop].yi=float( (random.random()*50)-26.0 )*10.0 particle[loop].zi=float( (random.random()*50)-26.0 )*10.0 particle[loop].xg=0.0 particle[loop].yg=-0.8 particle[loop].zg=0.0 def LoadImagePng(self, filename): im_surf = pygame.image.load(filename) self.imageWidth, self.imageHeight = im_surf.get_size() print "image size is:", im_surf.get_size() self.image = pygame.image.tostring(im_surf, "RGBX", 1) #self.image = pygame.image.tostring(im_surf, "RGBA", 1) def MakeTexture(self): #return self.tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.tex) #scale linearly when image bigger than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) #scale linearly when image smalled than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) # 2d texture, level of detail 0 (normal), # 3 components (red, green, blue), # x size from image, # y size from image, # border 0 (normal), # rgb color data, # unsigned byte data, # and finally the data itself. glTexImage2D(GL_TEXTURE_2D, 0, 3, self.imageWidth, self.imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, self.image) #glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.imageWidth, self.imageHeight, 0, # GL_RGBA, GL_UNSIGNED_BYTE, self.image) new_rdpyg/rdpyg/draw/pyopengl/paths.py0000644000175100017510000000207410067262621020377 0ustar renerene00000000000000 from OpenGL.GL import glBegin, GL_LINES, glVertex3f, glEnd, glPushAttrib, GL_ALL_ATTRIB_BITS, glMatrixMode, GL_MODELVIEW, glLoadIdentity, glScale, glTranslatef, glPopAttrib from OpenGL.GLUT import glutSolidTeapot def draw_path(a_path): """ draws a path with opengl lines. """ glBegin(GL_LINES) try: last = 0 for x,y,z in a_path.points: if last: glVertex3f(lx,ly,lz) glVertex3f(x,y,z) lx, ly, lz = x,y,z else: last = 1 lx, ly, lz = x,y,z finally: glEnd() def draw_path_with_traveler(a_path): """ draws a box where the position of the traveler is on the path. """ #TODO: speed this up. take out the scale as well. draw_path(a_path) # Get where the traveler is, and draw something there. x,y,z = a_path.Where() ##glPushAttrib(GL_ALL_ATTRIB_BITS) ##glMatrixMode(GL_MODELVIEW) ##glLoadIdentity() ##glScale(0.2, 0.2, 0.2) glTranslatef(x,y,z) # now draw a teapot there. glutSolidTeapot(0.1) glTranslatef(-x,-y,-z) ##glPopAttrib() new_rdpyg/rdpyg/draw/pyopengl/paths.pyc0000644000175100017510000000360510160170512020532 0ustar renerene00000000000000;ò ‘eÝ@c@srdklZlZlZlZlZlZlZlZl Z l Z l Z l Z dk lZd„Zd„ZdS(( sglBeginsGL_LINESs glVertex3fsglEnds glPushAttribsGL_ALL_ATTRIB_BITSs glMatrixModes GL_MODELVIEWsglLoadIdentitysglScales glTranslatefs glPopAttrib(sglutSolidTeapotcCs¡ttƒzˆd}x{|iD]p\}}}|o<t|||ƒt|||ƒ|||f\}}}qd}|||f\}}}qWWdt ƒXdS(s% draws a path with opengl lines. iiN( sglBeginsGL_LINESslastsa_pathspointssxsyszs glVertex3fslxslyslzsglEnd(sa_pathslastsysxszslzslxsly((s./rdpyg/draw/pyopengl/paths.pys draw_path s   cCsPt|ƒ|iƒ\}}}t|||ƒtdƒt| | | ƒdS(sD draws a box where the position of the traveler is on the path. f0.10000000000000001N(s draw_pathsa_pathsWheresxsyszs glTranslatefsglutSolidTeapot(sa_pathsysxsz((s./rdpyg/draw/pyopengl/paths.pysdraw_path_with_traveler s    N(s OpenGL.GLsglBeginsGL_LINESs glVertex3fsglEnds glPushAttribsGL_ALL_ATTRIB_BITSs glMatrixModes GL_MODELVIEWsglLoadIdentitysglScales glTranslatefs glPopAttribs OpenGL.GLUTsglutSolidTeapots draw_pathsdraw_path_with_traveler(s GL_MODELVIEWs glTranslatefsdraw_path_with_travelersGL_ALL_ATTRIB_BITSs glVertex3fs draw_pathsglScales glMatrixModesglEndsglBegins glPopAttribsglLoadIdentitysglutSolidTeapots glPushAttribsGL_LINES((s./rdpyg/draw/pyopengl/paths.pys?sO  new_rdpyg/rdpyg/draw/__init__.py0000644000175100017510000000000010065305160017137 0ustar renerene00000000000000new_rdpyg/rdpyg/draw/__init__.pyc0000644000175100017510000000015010160170505017307 0ustar renerene00000000000000;ò pŠÕ@c@sdS(N((((s./rdpyg/draw/__init__.pys?snew_rdpyg/rdpyg/effects/0000755000175100017510000000000007773743671015553 5ustar renerene00000000000000new_rdpyg/rdpyg/effects/pygame/0000755000175100017510000000000007773743665017040 5ustar renerene00000000000000new_rdpyg/rdpyg/effects/pyopengl/0000755000175100017510000000000007773743671017410 5ustar renerene00000000000000new_rdpyg/rdpyg/font_effects/0000755000175100017510000000000007773743570016577 5ustar renerene00000000000000new_rdpyg/rdpyg/gui/0000755000175100017510000000000007773743706014717 5ustar renerene00000000000000new_rdpyg/rdpyg/net/0000755000175100017510000000000010160167110014666 5ustar renerene00000000000000new_rdpyg/rdpyg/net/__init__.py0000644000175100017510000000004210160167110016773 0ustar renerene00000000000000""" networking related stuff. """ new_rdpyg/rdpyg/net/ifconfig_networking.py0000755000175100017510000001666310065303107021314 0ustar renerene00000000000000#import array, fcntl, struct, socket import os,sys,re,platform windows_output1 = """ Windows IP Configuration Ethernet adapter Network Bridge (Network Bridge): Connection-specific DNS Suffix . : IP Address. . . . . . . . . . . . : 192.168.0.10 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 192.168.0.1 """ class IfConfigWindows: """ """ def _read_ipconfig(self): p = os.popen("ipconfig") address = p.read() p.close() return address def get_info(self, the_output = None): if the_output == None: output = self._read_ipconfig() else: output = the_output lines = output.split("\n") ip_addresses = [] subnet_masks = [] default_gateway = [] for l in lines: if "IP Address" in l: parts = l.split(":") ip_addr = parts[1].strip() ip_addresses.append(ip_addr) elif "Subnet Mask" in l: parts = l.split(":") ip_addr = parts[1].strip() subnet_masks.append(ip_addr) elif "Default Gateway" in l: parts = l.split(":") ip_addr = parts[1].strip() default_gateway.append(ip_addr) return [ip_addresses, subnet_masks, default_gateway] def get_ips(self, the_output = None): return self.get_info(the_output)[0] def get_subnet_masks(self, the_output = None): return self.get_info(the_output)[1] def get_default_gateways(self, the_output = None): return self.get_info(the_output)[2] linux_output2 = """eth0 Link encap:Ethernet HWaddr 00:0C:76:41:D5:E1 inet addr:64.251.25.208 Bcast:64.251.25.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:24222107 errors:0 dropped:0 overruns:0 frame:0 TX packets:1693415 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:2578326033 (2.4 GiB) TX bytes:287660600 (274.3 MiB) Interrupt:23 Base address:0xe400 eth0:1 Link encap:Ethernet HWaddr 00:0C:76:41:D5:E1 inet addr:64.251.25.209 Bcast:64.255.255.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 Interrupt:23 Base address:0xe400 eth0:2 Link encap:Ethernet HWaddr 00:0C:76:41:D5:E1 inet addr:64.251.25.210 Bcast:64.255.255.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 Interrupt:23 Base address:0xe400 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:407668 errors:0 dropped:0 overruns:0 frame:0 TX packets:407668 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:35240368 (33.6 MiB) TX bytes:35240368 (33.6 MiB) """ linux_output1 = """eth0 Link encap:Ethernet HWaddr 00:E0:81:23:7D:3A UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:92494052 errors:0 dropped:0 overruns:0 frame:0 TX packets:106532110 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1940058549 (1850.1 Mb) TX bytes:657317003 (626.8 Mb) Interrupt:11 eth0:py3d Link encap:Ethernet HWaddr 00:E0:81:23:7D:3A inet addr:209.135.140.56 Bcast:209.135.140.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 Interrupt:11 lo Link encap:Local Loopback UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:9500783 errors:0 dropped:0 overruns:0 frame:0 TX packets:9500783 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3537945659 (3374.0 Mb) TX bytes:3537945659 (3374.0 Mb) """ class IfConfigLinux: def get_ips(self): output = p.read() print output p.close() def _read_ipconfig(self): p = os.popen("/sbin/ifconfig") output = p.read() p.close() return output def get_info(self, the_output = None): if the_output == None: output = self._read_ipconfig() else: output = the_output inet_regex = re.compile(r".*addr:(.*?)\s*[Bcast|Mask].*") lines = output.split("\n") ip_addresses = [] subnet_masks = [] default_gateway = [] info = {} info['ip_addresses'] = [] for l in lines: if "inet" in l: print l info['ip_addresses'].append(inet_regex.match(l).groups()[0]) return info def get_ips(self, the_output = None): return self.get_info(the_output)['ip_addresses'] # freebsd ifconfig output. """fxp0: flags=8843 mtu 1500 inet 207.142.132.145 netmask 0xffffff00 broadcast 207.142.132.255 inet 207.142.132.146 netmask 0xffffffff broadcast 207.142.132.146 inet 207.142.132.147 netmask 0xffffffff broadcast 207.142.132.147 inet 207.142.132.148 netmask 0xffffffff broadcast 207.142.132.148 inet 207.142.132.149 netmask 0xffffffff broadcast 207.142.132.149 ether 00:07:e9:08:d7:7c media: Ethernet autoselect (100baseTX ) status: active lp0: flags=8810 mtu 1500 lo0: flags=8049 mtu 16384 inet 127.0.0.1 netmask 0xff000000 """ class IfConfigFreeBSD: def get_info(self): raise NotImplementedError output = self._read_ipconfig() lines = output.split("\n") # keyed by interface name, valued by dicts containing various. interfaces = {} ip_addresses = [] subnet_masks = [] default_gateway = [] for l in lines: if "inet" in l: parts = l.split(":") ip_addr = parts[1].strip() ip_addresses.append(ip_addr) elif "Subnet Mask" in l: parts = l.split(":") ip_addr = parts[1].strip() subnet_masks.append(ip_addr) elif "Default Gateway" in l: parts = l.split(":") ip_addr = parts[1].strip() default_gateway.append(ip_addr) def _read_ifconfig(self): p = os.popen("/sbin/ifconfig") output = p.read() p.close() return output def IfConfig(): """ """ the_plat = platform.platform() if ('Microsoft' in the_plat or 'CYGWIN' in the_plat): return IfConfigWindows() elif('FreeBSD' in the_plat): return ifConfigFreeBSD() elif('Linux' in the_plat): return ifConfigFreeBsd() if __name__ == "__main__": i = IfConfigWindows() print i.get_ips(windows_output1) i = IfConfigLinux() print i.get_ips(linux_output1) print i.get_ips(linux_output2) i = IfConfig() print i.get_ips() new_rdpyg/rdpyg/path_finding/0000755000175100017510000000000007773743603016561 5ustar renerene00000000000000new_rdpyg/rdpyg/sprites/0000755000175100017510000000000010160170533015574 5ustar renerene00000000000000new_rdpyg/rdpyg/sprites/__init__.py0000644000175100017510000000000010065312357017701 0ustar renerene00000000000000new_rdpyg/rdpyg/sprites/__init__.pyc0000644000175100017510000000015310160170533020047 0ustar renerene00000000000000;ò ï”Õ@c@sdS(N((((s./rdpyg/sprites/__init__.pys?snew_rdpyg/rdpyg/sprites/spritegl.py0000644000175100017510000005470510073743546020027 0ustar renerene00000000000000""" Opengl drawing of pygame.sprite objects. With hopefully minimal/no changes to programs, and big speed increases. Rene Dudfield. illumen@yahoo.com TODO: First compatibilty, optimization, then next gen. NOTE: there are some more TODO's sprinkled througout the code Compatibilty. - need to implement all of screens methods. - test on more games. - chimp(works). - pyddr(doesn't work). - I think it has to do with the different format images. - I think a conversion may not be working properly. - bleten(works). - works, but is kinda slow when lots of images change. - need to work on a scaling method which uses opengl. - need to not use tostring() for making textures(slow). - work on caching some more, so that there is a texture cache as well. - so that images don't need to be uploaded to the card all the time. - yass(don't know). - a better way to detect when an images contents have changed. - probably a wrapper around surface, and surfarray which marks the image as dirty. - split sprites larger than 256x256 into multiple smaller textures. - for some older 3d cards. - should figure out how to detect max texture size. - support 8 and 16 bit and color keyed textures. - Make sure textures are cleaned up correctly in all cases. - Beta test on a wide number of machines. - Make it work correctly when the screen size changes. Optimization. - Put multiple sprites onto the same texture, and use uv coords for drawing particular sprites. This is a *big* optimization. - especially for animation. - move all texture management into the group, so as to optimize texture drawing more easily. - Have a set max number of textures to use in a texture cache. - Cache textures - optimize the screen.blit function, and some others: - with blit, only update a certain part of the texture which was actually blitted. - screen.fill - Group drawing by the same texture(less texture binds). - Try display lists to see if better performing. - try vertex buffers for better performance. - Make 1000+ sprite test case, and optimize for this case. - Update texture instead of replacing it when: - some pixels change in an image. - when the image changes and the old one isn't to be used anymore. - How to know this? Next gen. - Add scaling, rotation, other effects to a sprite class. - use caching of images for sdl, and straight opengl calls(eg glRotate etc). - shadows from sprites onto the background. - Make classes/optimize existing classes for drawing: - scrollers, tile maps, height maps, - 3d animated characters (http://www.py3d.org/py3d_zwiki/milkshape3d_animation) - doomIII clone ;) """ # search and replace this for __debug__ for a bit of a speed increase in -O _debug__ = 0 #Import Modules import os, pygame from pygame.locals import * from OpenGL.GL import * #from OpenGL.GLUT import * from OpenGL.GLU import * import time """ old_glMatrixMode = glMatrixMode def glMatrixMode(*args): modes = {GL_PROJECTION: "GL_PROJECTION", GL_MODELVIEW: "GL_MODELVIEW"} if _debug__: printw( glMatrixMode, modes[args[0]]) return apply(old_glMatrixMode, args) old_glTexSubImage2D = glTexSubImage2D def glTexSubImage2D(*args): if _debug__: printw( "glTexSubImage2D"+ str(args[:-1])) apply(old_glTexSubImage2D, args) """ #from _opengl2 import glVertexPointer, glColorPointer, glNormalPointer, glTexCoordPointer #from _opengl2 import glVertexPointer, glColorPointer, glNormalPointer#, glTexCoordPointer #from _opengl2 import glTexCoordPointer """ In order of easyness. make a draw method for the group. replace screen.blit with one which will work. make an update method. """ POWERS = (32, 64, 128, 256, 512, 1024, 2048, 4096) def nextPower(x): for y in POWERS: if y >= x: return y def printw(*args): print args from rdpyg.util import pack_textures #NOTE: TODO: maybe we shouldn't be using a subclass of Surface... pygame.old_Surface = pygame.Surface #class SurfaceGL(pygame.old_Surface): class SurfaceGL: """ This is useful for tracking changes in a surface. It takes a surface as a keyword initializer: eg s = SurfaceGL(initialize_with_this = a_surf) Or you can initialize it like a normal surface. Once the pixel data is changed, either is_dirty will be true, or changed_rects will not be empty. If is_dirty is true: then the whole image needs to be updated. Else: if changed_rects is not empty: update the rects which have been changed. """ def __init__(self, *args, **kwargs): if kwargs.has_key("initialize_with_this"): self.__dict__["realone"] = kwargs["initialize_with_this"] else: self.__dict__["realone"] = pygame.old_Surface(*args, **kwargs) # If this is dirty(ie has changed) then the whole image should # be reuploaded. Otherwise the rects from self.changed_rects will # be used for updating the image. self.__dict__["is_dirty"] = 0 # this is a list of rects to use when you only want to update a small # part of the image. self.__dict__["changed_areas"] = [] def __getattr__(self, name): if name == "realone": if self.__dict__.has_key("realone"): return self.__dict__["realone"] else: raise AttributeError(name) elif self.__dict__.has_key("realone"): if hasattr(self.__dict__["realone"], name): return getattr(self.__dict__["realone"], name) else: raise AttributeError(name) elif self.__dict__.has_key(name): return self.__dict__[name] else: print self.__dict__ raise AttributeError(name) def __setattr__(self, name, value): #print "ASDDFFAFDF", name, value if name in ["realone", "is_dirty", "changed_rects"]: self.__dict__[name] = value else: setattr(self.__dict__["realone"],name, value) def blit(self, *args): """ TODO: needs to keep track of which parts have been changed. For now marking the whole image as dirty. """ self.__dict__["is_dirty"] = 1 print type(args[0]) print dir(args[0]) # we need a real surface type for blit. if hasattr(args[0], "realone"): new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) if hasattr(args[0], "screen_gl"): new_args = list(args) new_args[0] = args[0].screen_gl.image args = tuple(new_args) return self.__dict__["realone"].blit(*args) def fill(self, *args): """ like a normal surface fill, but marks the thing as dirty. """ self.__dict__["is_dirty"] = 1 return self.__dict__["realone"].fill(*args) #pygame.sprite.Group_orig = pygame.sprite.Group #pygame.sprite.Sprite_orig = pygame.sprite.Sprite class GroupGL(pygame.sprite.Group) : def setup_draw_texture(self, screen_rect): """ Sets up opengl for drawing the textures. """ self.old_matrix_mode = glGetIntegerv(GL_MATRIX_MODE); if _debug__: printw( type(self.old_matrix_mode), self.old_matrix_mode) self.old_projection_matrix = glGetDoublev( GL_PROJECTION_MATRIX ) self.old_modelview_matrix = glGetDoublev( GL_MODELVIEW_MATRIX ) self.set_up_2d_projection(screen_rect) glEnable(GL_TEXTURE_2D) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) if _debug__: printw( "setup_draw_texture") glMatrixMode( GL_MODELVIEW ) self.has_setup = 1 def un_setup_draw_texture(self): """ resets the opengl state to what it was before drawing. """ if _debug__: printw( type(self.old_matrix_mode), self.old_matrix_mode) if self.old_matrix_mode: glMatrixMode( self.old_matrix_mode ) glDisable(GL_BLEND) glDisable(GL_TEXTURE_2D) if _debug__: printw( "un_setup_draw_texture1") glMatrixMode( GL_PROJECTION ) glLoadMatrixd(self.old_projection_matrix ) if _debug__: printw( "un_setup_draw_texture2") glMatrixMode( GL_MODELVIEW ) glLoadMatrixd( self.old_modelview_matrix ) self.has_setup = 0 def draw_gl(self, spr ): """ Assumes glMatrixMode( GL_MODELVIEW ) """ #glLoadIdentity() glBindTexture(GL_TEXTURE_2D, spr.tex) x = spr.rect[0] y = spr.rect[1] glTranslatef(x, y, 0) wv, hv = float(spr.rect.width)/float(spr.pow2_image_width), float(spr.rect.height)/float(spr.pow2_image_height) glBegin(GL_QUADS) glTexCoord2f(0.0, 0.0) glVertex2f(0.0, 0.0) glTexCoord2f(0.0, hv) glVertex2f(0, spr.rect.height) glTexCoord2f(wv, hv) glVertex2f(spr.rect.width, spr.rect.height) glTexCoord2f(wv, 0.0) glVertex2f(spr.rect.width, 0) glEnd() glTranslatef(-x, -y, 0) #(x, y), texid, (owidth, oheight), (width, height), #(xres, yres)): def set_up_2d_projection(self, a_rect): """ a_rect - the area to set up the projection for. """ if _debug__: printw( "set_up_2d_projection") glMatrixMode( GL_PROJECTION ) glLoadIdentity() gluOrtho2D( a_rect[0], a_rect.width, a_rect.height, a_rect[1]) def load_2d_projection(self): if _debug__: printw( "load_2d_projection") glMatrixMode( GL_PROJECTION ) glLoadMatrixd(self.projection_matrix_2d) def draw(self, surface ): """ supposed to draw to the given surface. Problem is it is an opengl screen. so we get the size of it, and draw to the screen. """ # TODO: OPTIMIZATION: order the sprites into ones which share the same textures. # TODO: OPTIMIZATION: make sure the texture is only loaded once for each image. if not hasattr(self, 'has_setup'): self.setup_draw_texture(surface.get_rect()) #damn, if not hasattr(self, 'has_setup') or not self.has_setup: # doesn't work. if not self.has_setup: self.setup_draw_texture(surface.get_rect()) glLoadIdentity() for spr,k in self.spritedict.items(): # see if the texture has been made for the things, if not # make them. if not hasattr(spr, 'image_string'): spr.LoadImage() if not hasattr(spr, 'tex'): spr.MakeTexture() if not hasattr(spr, 'old_rect'): spr.old_rect = pygame.Rect( spr.rect ) if not hasattr(spr, 'old_image_id'): spr.old_image_id = id( spr.image ) reload_the_texture = 0 # TODO: BUG: if the if spr.old_rect[2:] != spr.rect[2:] or spr.old_image_id != id( spr.image ): reload_the_texture = 1 if reload_the_texture: # TODO: FIXME: should probably check if the screen changes too. spr.DeleteTexture() spr.LoadImage() spr.MakeTexture() spr.old_rect = pygame.Rect( spr.rect ) spr.old_image_id = id( spr.image ) spr.pow2_image_width, spr.pow2_image_height = tuple(map( nextPower,(spr.rect.width, spr.rect.height) )) self.set_up_2d_projection(surface.get_rect()) glMatrixMode( GL_MODELVIEW ) self.draw_gl(spr) # this is here for compatibility with RenderUpdates return [] #self.un_setup_draw_texture() def MakeTextures(self): """ For all of the sprites in this group we will make textures for them. """ # TODO: make list of pack_textures.Textures for all the surfaces. # Figure out how big a texture we want to make. # Find the maximum texture size we can make. # find the smallest sized textures we can fit all the little # ones inside. # TODO: to draw we need to: # Bind the gl texture for each main texture. # Draw a bunch of quads using the x/y in the sub textures as # the uv coordinates. # def FitSpritesOnTextures(self): """ """ # get the max texture size. self.max_texture_size = (256, 256) class SpriteGL(pygame.sprite.Sprite): """ A sprite class which uses opengl. Should be able to use it in the place of the pygame sprite class. """ # a shared image cache. image_cache = {} max_image = 30 def update(self): pass def LoadImage(self): # The image should allready be loaded, and rect allready there. #self.image = pygame.image.load(filename) if _debug__: printw( "SpriteGL.LoadImage start") if not hasattr(self, 'rect'): self.rect = self.image.get_rect() # check if it is an alpha image. self.masks = self.image.get_masks() alpha_mask = self.masks[3] if _debug__: printw( self.masks, id(self)) #TODO: FIXME: better detection, and manipulation of different image # types. if _debug__: printw( "byte_size") printw( self.image.get_bytesize()) printw( self.masks) # DEPENDENCY - self.image # See if the image has changed. # If it has we need to update the texture. # # if self.image_cache.has_key((id(self.image),tuple(self.rect[2:])) ): if _debug__: printw( "SpriteGL.LoadImage: image_cache") self.image_string, rect, self.cache_tex = self.image_cache[(id(self.image),tuple(self.rect[2:]))] self.cache_hit = 1 elif not alpha_mask: if _debug__: printw( "SpriteGL.LoadImage: not alpha_mask") ##raise "ummmmm... not implemented, sorry" ##self.image_string = pygame.image.tostring(self.image, "RGB", 0) ##self.image_cache[(id(self.image),tuple(self.rect[2:]))] = [self.image_string, self.image.get_rect(), -1] ##self.cache_hit = 0 #TODO: OPTIMIZATION: need to have this handle non alpha images. # for now we convert it to an alpha one. #TODO: I don't think this works with 8 bit images. # need to test with different images. self.image = self.image.convert_alpha() if _debug__: printw( "self.image", self.image) self.masks = self.image.get_masks() alpha_mask = self.masks[3] if _debug__: if not alpha_mask: raise "problem here" self.image_string = pygame.image.tostring(self.image, "RGBA", 0) self.image_cache[(id(self.image),tuple(self.rect[2:]))] = [self.image_string, self.image.get_rect(), -1] self.cache_hit = 0 else: if _debug__: printw( "SpriteGL.LoadImage: else") self.image_string = pygame.image.tostring(self.image, "RGBA", 0) self.image_cache[(id(self.image),tuple(self.rect[2:]))] = [self.image_string, self.image.get_rect(), -1] self.cache_hit = 0 if hasattr(self, 'pow2_image_width') and hasattr(self, 'pow2_image_height'): self.old_pow2_image_width, self.old_pow2_image_height = self.pow2_image_width, self.pow2_image_height self.pow2_image_width, self.pow2_image_height = tuple(map(nextPower,self.image.get_size())) if self.old_pow2_image_width > self.pow2_image_width: self.pow2_image_width = self.old_pow2_image_width if self.old_pow2_image_height> self.pow2_image_height: self.pow2_image_height= self.old_pow2_image_height else: self.pow2_image_width, self.pow2_image_height = tuple(map(nextPower,self.image.get_size())) #TODO: make glTexImage2D version which can take surfaces directly. def DeleteTexture(self): if hasattr(self, 'tex'): if _debug__: printw( self.tex) glDeleteTextures([self.tex]) def load_del_make(self): """ """ def MakeTexture(self): #return if _debug__: printw( "SpriteGL.MakeTexture start") #if self.cache_tex != -1: # TODO: probably need to move texture making into the group. # need to keep a dict of cached textures. # delete those which are not needed etc. # For grouping textures, need to discover a list of texids, with images. # pass #self._debug("making texture") self.tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.tex) #glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) #scale linearly when image bigger than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) #scale linearly when image smalled than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) # 2d texture, level of detail 0 (normal), # 3 components (red, green, blue), # x size from image, # y size from image, # border 0 (normal), # rgb color data, # unsigned byte data, # and finally the data itself. #TODO: check to see what type of image was loaded, and make # and appropriate glTexImage2D call. #TODO: use the rect for the image size, width etc. #TODO: need to take power of 2 into account here. """ if _debug__: printw( self.rect.width) printw( self.rect.height) printw( self.image.get_width()) printw( self.image.get_height()) printw( len(self.image_string)) printw( type(self.image_string)) printw( GL_RGB) printw( GL_RGBA) """ self.pow2_image_width, self.pow2_image_height = tuple(map(nextPower,self.image.get_size())) if _debug__: printw( self.pow2_image_width, self.pow2_image_height) if not self.masks[3]: if _debug__: printw( "glTexImage2D RGB") glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.pow2_image_width, self.pow2_image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, None) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, self.rect.width, self.rect.height, GL_RGB, GL_UNSIGNED_BYTE, self.image_string) else: if _debug__: printw( "glTexImage2D RGBA") glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.pow2_image_width, self.pow2_image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, self.rect.width, self.rect.height, GL_RGBA, GL_UNSIGNED_BYTE, self.image_string) #glTexImage2D(GL_TEXTURE_2D, 0, 4, self.image_width, self.image_height, 0, # GL_RGBA, GL_UNSIGNED_BYTE, self.image_string) # GL_RGBA, GL_UNSIGNED_BYTE, self.image) """ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, owidth, oheight, GL_RGBA, GL_UNSIGNED_BYTE, imgstring) """ #self._debug("finished making texture") class ScreenGL: """ TODO: - Fill in missing functions. - Work correctly when screen size changes. - only update the texture when blitting. - An optimization might be to not update the texture until the screen has been flipped, or updated. - This could work quite nicely with RenderUpdates :) """ def __init__(self, screen): self.screen = screen self.screen_gl = SpriteGL() self.screen_gl.image = pygame.Surface(screen.get_size()) self.screen_gl.image.convert_alpha() self.screen_gl.rect = self.screen_gl.image.get_rect() self.screen_sprites= GroupGL((self.screen_gl)) #TODO: automatically add all the methods of surface # What's a nice way to do this in python? # def get_size(self, *args): return apply(self.screen_gl.image.get_size, args) def get_rect(self, *args): return apply(self.screen_gl.image.get_rect, args) def set_clip(self, *args): return apply(self.screen_gl.image.set_clip, args) def get_clip(self, *args): return apply(self.screen_gl.image.get_clip, args) def get_flags(self, *args): return apply(self.screen_gl.image.get_flags, args) def fill(self, *args): apply(self.screen_gl.image.fill, args) self.blit(None) def blit(self, *args): """ meant as a replacement for screen.blit You really should consider making your background a seperate Sprite, and Group. useage: gl_screen_blit """ ##print "blit" #print "args", args[0:1], args # blit to the internal software image here. if (None,) != args[0:1]: if hasattr(args[0], "realone"): new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) self.screen_gl.image.blit(*args) if _debug__: printw( "blitting to ScreenGL, with args :%s:" % (args,)) #screen_sprites.update() # write the internal image to disk. """ pygame.image.save(self.screen_gl.image, "/tmp/screen.tga") printw("sleeping for 2") time.sleep(20) printw("finished sleeping") """ self.screen_gl.DeleteTexture() self.screen_gl.LoadImage() self.screen_gl.MakeTexture() #self.screen_sprites.setup_draw_texture(self.screen_gl.image.get_rect()) self.screen_sprites.update() self.screen_sprites.draw(self.screen) ##print "done draw" #self.screen_sprites.un_setup_draw_texture() #screen_gl.DeleteTexture() def gl_display_get_surface(): return pygame.display.old_get_surface() def gl_display_set_mode(*args): # TODO: Add check to see if a GL screen is infact being requested. return ScreenGL( pygame.display.old_set_mode(args[0], OPENGL|DOUBLEBUF) ) #return ScreenGL( apply(pygame.display.old_set_mode, args) ) def gl_display_update(*args): pygame.display.flip() def gl_draw_line(*args): if hasattr(args[0], "realone"): args[0].is_dirty = 1 new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) return pygame.draw.old_line(*args) def gl_transform_scale(*args, **kwargs): print "len args", len(args) if hasattr(args[0], "realone"): new_args = list(args) new_args[0] = args[0].realone args = tuple(new_args) elif hasattr(args[0], "screen_gl"): new_args = list(args) new_args[0] = args[0].screen_gl.image args = tuple(new_args) #print kwargs, args if len(args) > 2: new_surface = pygame.transform.old_scale(*args[1:], **kwargs) else: new_surface = pygame.transform.old_scale(*args, **kwargs) return pygame.Surface(initialize_with_this = new_surface) #pygame.display.get_surface() and pygame.display.set_mode((height,width), OPENGL|DOUBLEBUF) new_rdpyg/rdpyg/util/0000755000175100017510000000000010220112575015057 5ustar renerene00000000000000new_rdpyg/rdpyg/util/quaternion.py0000644000175100017510000002671310065303034017626 0ustar renerene00000000000000"""Simple module providing a quaternion class for manipulating rotations easily. NOTE: unittest in quaternion_test.py NOTE: a lot of this code is taken from various places, including OpenglContext. Note: all angles are assumed to be specified in radians. Note: this is an entirely separate implementation from the PyOpenGL quaternion class. This implementation assumes that Numeric python will be available, and provides only those methods and helpers commonly needed for manipulating rotations. TODO: Make all functions use an array instead of a quat class. Make a quat class which uses the functions. Make a c version of for the python functions. - based off amd lib, gamasutra article, and CS quats. """ import Numeric, Matrix import math N = Numeric # some common math ones. pi = math.pi cos = math.cos acos = math.acos sin= math.sin atan= math.atan sqrt= math.sqrt def magnitude_vectors( vectors ): """Calculate the magnitudes of the given vectors vectors -- sequence object with 1 or more 3-item vector values. returns a double array with x elements, where x is the number of 3-element vectors """ vectors = N.asarray( vectors,'d', savespace = 1) vectors = N.reshape( vectors, (-1,3)) vectors = vectors*vectors result = vectors[:,0] N.add( result, vectors[:,1], result ) N.add( result, vectors[:,2], result ) N.sqrt( result, result ) return result def normalise_vectors( vectors ): """Get normalised versions of the vectors. vectors -- sequence object with 1 or more 3-item vector values. returns a double array with x 3-element vectors, where x is the number of 3-element vectors in "vectors" Will raise ZeroDivisionError if there are 0-magnitude vectors in the set. """ vectors = N.asarray( vectors, 'd', savespace = 1) vectors = N.reshape( vectors, (-1,3)) mags = N.reshape( magnitude_vectors( vectors ), (-1, 1)) return N.divide_safe( vectors, mags) def normalise_vector( vector ): """Given a 3 or 4-item vector, return a 3-item unit vector""" """ x,y,z = vector sqlen = x * x + y * y + z * z if (sqlen < SMALL_EPSILON): return vector invlen = sqrt (sqlen) return vector * invlen """ return normalise_vectors( vector[:3] )[0] def length_quat(quat): """ """ #w,x,y,z = quat.internal #length = x**2 + y**2 + z**2 + w**2 #return length return N.sum(quat.internal ** 2) def slerp_quat(quat_a, quat_b, slerp): """ Returns a quaternion spherically interpolated between quat_a, quat_b. quat_a, quat_b - quaternions to interpolate between. slerp - interp factor (0.0 = quat_a, 1.0 = quat_b) """ # TODO: FIXME: This is wrong! #raise NotImplementedError("broken implementation") # Difference at which to lerp instead of slerp DELTA = 0.0001 HALF_PI = math.pi /2 # DOT the quats to get the cosine of the angle between them cosom = N.sum(quat_a.internal * quat_b.internal) result = [0., 0., 0.,0.] # Two special cases: # Quats are exactly opposite, within DELTA? if (cosom > DELTA - 1.0): # make sure they are different enough to avoid a divide by 0 if (cosom < 1.0 - DELTA): # SLERP away omega = math.acos(cosom); isinom = 1.0 / math.sin(omega); scale0 = math.sin( (1.0 - slerp)*omega ) * isinom; scale1 = math.sin(slerp * omega) * isinom; else: # LERP is good enough at this distance scale0 = 1.0 - slerp; scale1 = slerp; result[0] = scale0 * quat_a.internal[0] + scale1 * quat_b.internal[0]; result[1] = scale0 * quat_a.internal[1] + scale1 * quat_b.internal[1]; result[2] = scale0 * quat_a.internal[2] + scale1 * quat_b.internal[2]; result[3] = scale0 * quat_a.internal[3] + scale1 * quat_b.internal[3]; else: # SLERP towards a perpendicular quat # Set slerp parameters #scale0 = math.sin ((1.0 - slerp) * HALF_PI); #scale1 = math.sin (slerp * HALF_PI); #q2w, q2x, q2y, q2z = quat_b.internal * N.array([-0.5,0.5,-0.5,0.5]) #result[0] = -quat_b.internal[1]; #result[1] = quat_b.internal[0]; #result[2] = -quat_b.internal[3]; #result[3] = quat_b.internal[2]; scale0 = sin((1.0 - slerp) * HALF_PI); scale1 = sin(slerp * HALF_PI); result[0] = scale0 * quat_a.internal[0] + scale1 * quat_b.internal[0]; result[1] = scale0 * quat_a.internal[1] + scale1 * quat_b.internal[1]; result[2] = scale0 * quat_a.internal[2] + scale1 * quat_b.internal[2]; result[3] = scale0 * quat_a.internal[3] + scale1 * quat_b.internal[3]; # Compute the result return Quaternion( result ) def get_angles_from_two_points(a,b): """ returns the angles along the x,y,z axis. this is direction of the two points. """ p1,p2 = N.array(a), N.array(b) origin = N.array([0.,0.,0.]) p2 = (origin - p1) + p2 p1 = origin v = N.absolute(p2 - p1) x,y,z = p2 if x >=0 and y >= 0: to_add = -180 elif x >= 0 and y < 0: to_add = 0 elif x < 0 and y >= 0: to_add = 180 elif x < 0 and y < 0: to_add = -360 else: # shouldn't get here. raise ValueError("shouldn't get here x:%s: y :%s: " % (x,y) ) #v = p2 - p1 # atan(Vy/Vx) if v[0] == 0: x_angle = 0. else: x_angle = atan(v[1] / v[0]) # atan(Vx/Vz) if v[1] == 0: y_angle = 0. else: y_angle = atan(v[0] / v[1]) # atan(Vy/Vx) if v[2] == 0: z_angle = 0. else: z_angle = atan(v[0] / v[2]) angles = map(radians_to_angle, (x_angle, y_angle, z_angle) ) new_angles = map(lambda x, y=to_add: x + y, angles) return map(abs, new_angles) #return (x_angle, y_angle, z_angle) def euler_to_quats(rotations): """ Returns a sequence of quats. It is an array where each quat is four floats. w,x,y,z is the order. rotations- an array of rotations. where each rotation is three floats. """ tmp = map(from_euler_list, rotations) return map(lambda x:x.internal, tmp) def fromMatrix(matrix): """ from a 4x4 matrix return a quaternion. These are the orders of the matrix: [00,01,02,03] [10,11,12,13] [20,21,22,23] [30,31,32,33] [0 , 1, 2, 3] [4 , 5, 6, 7] [8 , 9,10,11] [12,13,14,15] Which is the opengl order. """ m = matrix trace = matrix[0][0]+matrix[1][1]+matrix[2][2] s = sqrt (trace + 1.0); quat_s = (s * 0.5); s = 0.5 / s; q = Quaternion( [quat_s, (m[1][2]-m[2][1])*s, (m[2][0]-m[0][2])*s, (m[0][1]-m[1][0])*s ] ) return q def angle_to_radians(angle): pi_div_180 = pi / 180. return pi_div_180 * (angle % 360.) def radians_to_angle(radians): if radians == 0: return 0. return (180. / (pi / radians)) % 360. def fromAXYZ(a,x,y,z): return fromXYZR(x,y,z,angle_to_radians(a)) def fromXYZR( x,y,z, r ): """Create a new quaternion from a VRML-style rotation x,y,z are the axis of rotation r is the rotation in radians.""" x,y,z = normalise_vector( (x,y,z) ) return Quaternion ( N.array( [ cos(r/2.0), x*(sin(r/2.0)), y*(sin(r/2.0)), z*(sin(r/2.0)), ]) ) def from_euler_list( l ): return apply(fromEuler, l) def fromEuler_angle(x=0, y=0, z=0): """ From x,y,z angles in degrees create a quat. """ radians = map(angle_to_radians, (x,y,z)) return fromEuler(*radians) def fromEuler( x=0,y=0,z=0 ): """Create a new quaternion from a 3-element euler-angle rotation about x, then y, then z """ if x: base = fromXYZR( 1,0,0,x) if y: base = base * fromXYZR( 0,1,0,y) if z: base = base * fromXYZR( 0,0,1,z) return base elif y: base = fromXYZR( 0,1,0,y) if z: base = base * fromXYZR( 0,0,1,z) return base else: return fromXYZR( 0,0,1,z) class Quaternion: """Quaternion object implementing those methods required to be useful for OpenGL rendering (and not many others)""" def __init__ (self, elements = [1,0,0,0] ): """The initializer is a four-element array, w, x,y,z -- all elements should be doubles/floats the default values are those for a unit multiplication quaternion. """ elements = N.asarray( elements, 'd') length = sqrt( N.sum( elements * elements)) if length != 1: # print 'fixing quaternion length', repr(length) elements = elements/length self.internal = elements self.cache = {} def __mul__( self, other ): """Multiply this quaternion by another quaternion, generating a new quaternion which is the combination of the rotations represented by the two source quaternions. Other is interpreted as taking place within the coordinate space defined by this quaternion. Alternately, if "other" is a matrix, return the dot-product of that matrix with our matrix (i.e. rotate the coordinate) """ if hasattr( other, 'internal' ): w1,x1,y1,z1 = self.internal w2,x2,y2,z2 = other.internal w = w1*w2 - x1*x2 - y1*y2 - z1*z2 x = w1*x2 + x1*w2 + y1*z2 - z1*y2 y = w1*y2 + y1*w2 + z1*x2 - x1*z2 z = w1*z2 + z1*w2 + x1*y2 - y1*x2 return Quaternion( N.array([w,x,y,z],'d')) else: return N.dot( self.matrix (), other ) def AXYZ(self): """ returns the angle, and x,y,z as a vector. as used by glRotate. """ x,y,z,r = self.XYZR() return [radians_to_angle(r), x,y,z] def XYZR( self ): """Get a VRML-style axis plus rotation form of the rotation. Note that this is in radians, not degrees, and that the angle is the last, not the first item... (x,y,z,radians) """ w,x,y,z = self.internal try: aw = acos(w) except ValueError: # catches errors where w == 1.00000000002 aw = 0 scale = sin(aw) if not scale: return (0,1,0,0) return (x / scale, y / scale, z / scale, 2 * aw ) def matrix( self ): """Get a rotation matrix representing this rotation""" # TODO: should cache this. w,x,y,z = self.internal return Numeric.array([ [ 1-2*y*y-2*z*z, 2*x*y+2*w*z, 2*x*z-2*w*y, 0], [ 2*x*y-2*w*z, 1-2*x*x-2*z*z, 2*y*z+2*w*x, 0], [ 2*x*z+2*w*y, 2*y*z-2*w*x, 1-2*x*x-2*y*y, 0], [ 0,0,0,1], ]) def __getitem__( self, x ): return self.internal[x] def __len__( self ): return len( self.internal) def __repr__( self ): """Return a human-friendly representation of the quaternion Currently this representation is as an axis plus rotation (in radians) """ return """<%s XYZR=%s>"""%( self.__class__.__name__, list(self.XYZR())) def delta( self, other ): """Return the angle in radians between this quaternion and another. Return value is a positive angle in the range 0-pi representing the minimum angle between the two quaternion rotations. From code by Halldor Fannar on the 3D game development algos list """ #first get the dot-product of the two vectors cosValue = N.sum(self.internal + other.internal) # now get the positive angle in range 0-pi return acos( cosValue ) def __neg__(self): #return Quaternion(-self.a, -self.b, -self.c, -self.d) return Quaternion(-self.internal) #try: # import config # # if config.USE_TWISTED: # from twisted.spread import pb # # class CopyQuaternion(Quaternion, pb.Copyable, pb.RemoteCopy): # pass # # pb.setUnjellyableForClass('quaternion.CopyQuaternion', CopyQuaternion) #except: # pass #D3DRMQUATERNION is four floats x, y, z, s if __name__== "__main__": pass new_rdpyg/rdpyg/util/paths.py0000644000175100017510000003224210065305521016555 0ustar renerene00000000000000#file: paths.py #purpose: for 3d objects to follow paths. # NOTE: follows the opengl coordinate system. # distance units are in meters # time units are in seconds. import math # these are the types of loop the path can follow. LOOP_TYPES = ["stop", "loop", "backwards"] class Path: """ Used for storing the path from one point to another. For working out where an object following that path at a certain speed would be. p = Path() p.SetPoints([[0., 0., 0.], [0., 1., 0.], [1., 1., 0.], [2., 2., 0.], [3., 3., 0.]]) This creates a path of straight lines. Now whatever is traveling along the path can use: point_along_path = p.Travel(speed=0.5, elapsed_time=5) Which will travel along the path 0.5 * 5 units, and give you the point where it is up to. """ def __init__(self, points = [], loop_type = "stop"): """ points - defaults to []. should be like [[0.,0.,0.],[0.,1.,0.]] """ self.elapsed_time = 0. self.SetPoints(points) self.SetLoopType(loop_type) def SetLoopType(self, loop_type): """ SetLoopType("stop") -> None Can be set to one of LOOP_TYPES, ["stop", "loop", "backwards"] """ if loop_type in LOOP_TYPES: self.loop_type = loop_type else: raise NotImplementedError, loop_type def length(self): """ length() -> length of the path. TODO: why isn't this __len__() ? """ return length_line(self.points) def SetPoints(self, point_list): """ SetPoints(point_list) -> None Sets the points along the path. point_list - eg [[1., 1., 1.], [2., 2., 2.]] With each sublist being a point (x,y,z) in 3d space. """ #TODO: should we make the points a tuple? # this would allow the path to be used as a hash value. if len(point_list) == 0: point_list = [[0.,0.,0.], [0.,0.,0.]] if len(point_list) == 1: point_list = [point_list[0], point_list[0]] self.points = point_list if len(self.points) > 1: # we start at the beginning. self.current_point = self.points[0] # Where we are going to. self.current_heading_to_idx = 1 self.current_idx = 0 def SetNewPoint(self, point): """ SetNewPoint([x,y,z]) -> None Sets the current point that the traveller is on. """ self.current_point = point def GotoNextLine(self): """ GotoNextLine() -> None Starts heading to the next line in path. """ # what happens if we get to the end? self.current_heading_to_idx += 1 self.current_idx = self.current_heading_to_idx - 1 if len(self.points) == self.current_heading_to_idx: if self.loop_type == "stop": pass elif self.loop_type == "loop": self.current_heading_to_idx = 0 elif self.loop_type == "backwards": self.points.reverse() self.current_heading_to_idx = 1 self.current_idx = 0 def ShouldStop(self): """ ShouldStop() -> Bool Are we at the end and is the loop_type "stop" """ if self.loop_type == "stop": if self.current_idx >= len(self.points) -1: return 1 else: return 0 else: return 0 def Where(self): """ Where() -> position. Returns the current position of the traveler. """ return self.current_point[:] def GetHeadingToPoint(self): """ GetHeadingToPoint() -> position Returns the point which the traveler is heading to. """ return self.points[self.current_heading_to_idx] def __str__(self): return str(self.points) def __eq__(self, other): #print self.points == other.points #print self.elapsed_time == other.elapsed_time #print self.loop_type == other.loop_type #print self.current_point == other.current_point #print self.current_heading_to_idx == other.current_heading_to_idx #print self.current_idx == other.current_idx if not other.__class__ == self.__class__: return 0 if ((self.points == other.points) and (self.elapsed_time == other.elapsed_time) and (self.loop_type == other.loop_type) and (self.current_point == other.current_point) and (self.current_heading_to_idx == other.current_heading_to_idx) and (self.current_idx == other.current_idx)): return 1 else: return 0 def __ne__(self, other): return not self.__eq__(other) def GetBackwardsPoint(self, distance): """ GetBackwardsPoint(distance) -> position Returns a point backwards from the current direction along the path. distance - backwards along the path. """ #FIXME: I think this may be broken for the case where the traveler # is not moving. cur_point = self.Where() if self.ShouldStop(): #print self.current_heading_to_idx, "current_heading_to_idx" next_point = cur_point cur_point= self.points[0] else: next_point = self.points[self.current_heading_to_idx] backwards_point = backwards(cur_point, next_point, distance) return backwards_point def Travel(self, speed, elapsed_time): """ Travel(float, float) -> position Returns the point along the path that the traveler is at. speed - units per second. Average since the last call to this. elapsed_time - since the last call to this. """ if self.ShouldStop(): return self.Where() end_point = self.points[self.current_heading_to_idx] start_point = self.Where() time_left, new_point = travel_line(start_point, end_point, speed, elapsed_time) self.SetNewPoint(new_point) # to prevent an infinite loop incase this code is buggy. MAXIMUM_ITERATIONS = 100 c = 0 while not within(time_left, 0.0, 0.00001): # there is some time left. elapsed_time = time_left self.GotoNextLine() if self.ShouldStop(): break start_point = self.Where() end_point = self.points[self.current_heading_to_idx] time_left, new_point = travel_line(start_point, end_point, speed, elapsed_time) self.SetNewPoint(new_point) c += 1 # a sanity check to avoid maybe possible infinite loops. if c >= MAXIMUM_ITERATIONS: raise RuntimeError("too many iterations trying to find new place on path") return new_point # Some support for paths which can be copied with twisted. # TODO: remove this?? try: import config if config.USE_TWISTED: from twisted.spread import pb class CopyPath(Path, pb.Copyable, pb.RemoteCopy): pass pb.setUnjellyableForClass('paths.CopyPath', CopyPath) except: pass # Some helper functions. def within(a,b, error_range): """ within(num, num, num) -> bool check if a is with error_range of b. """ return abs(a - b) < error_range def travel_line(start_point, end_point, speed, elapsed_time): """ travel_lines(point, point, num, num) -> (time_left, new_point) Travels along the line given at a given speed, for a given time. """ distance = speed * elapsed_time distance_to_end = distance_between_points(start_point, end_point) reached_end = 0 if within(distance, distance_to_end, 0.00000001): # right on the end. return (0.0, end_point) elif within(distance_to_end, 0.0, 0.00000001): return (elapsed_time, end_point) elif distance > distance_to_end: reached_end = 1 if reached_end: # we have reached the end, so we figure out how much time we have left. # The new_point is the end_point ##t=elapsed_time-(elapsed_time-((distance - distance_to_end) / speed)) #time_left = elapsed_time - (elapsed_time / distance) t = elapsed_time-(elapsed_time-((distance - distance_to_end) / speed)) time_left = t return (time_left, end_point) else: # need to figure out where we are on the line between start and end. ratio = distance / distance_to_end if within(ratio, 1.0, 0.00000001): return (0.0, end_point) else: time_left = 0.0 new_point = interpolate_line(start_point, end_point, ratio) return (time_left, new_point) def interpolate_line(start_point, end_point, t): """ interpolate_line(point, point, num) -> point returns the new point along the line given. start_point - of the line. end_point - of the line. t - ratio between 0. - 1. along the line. """ # numeric: # (e - s) * t # other formula. probably faster if I make a line class, # or cache results in some other way. # # sx,sy = start # ex,ey = end # stepx = (ex-sx) / total_length # stepy = (ey-sy) / total_length # midx = sx + stepx * length # midy = sy + stepy * length # # another formular: # # (1 - t)*s + t * e #assert( t <= 1.0 ) if len(start_point) == 3: one_minus_t = 1 -t x = (start_point[0] * one_minus_t) + (end_point[0] * t) y = (start_point[1] * one_minus_t) + (end_point[1] * t) z = (start_point[2] * one_minus_t) + (end_point[2] * t) return [x,y,z] elif len(start_point) == 2: one_minus_t = 1 -t x = (start_point[0] * one_minus_t) + (end_point[0] * t) y = (start_point[1] * one_minus_t) + (end_point[1] * t) return [x,y] else: raise NotImplementedError def length_line(points): """ length([point]) -> num returns the length of the line represented by the points. """ len_points = len(points) if len_points < 1: return 0. elif len_points == 2: return distance_between_points(points[0], points[1]) else: total_length = 0 last_point = points[0] # go through all but the first point. for point in points[1:]: total_length += distance_between_points(last_point, point) last_point = point return total_length def distance_between_points(p1, p2): """ distance_between_points(point, point) -> num Returns the distance between two points. """ if len(p1) == 3: return math.sqrt( (p1[0] - p2[0])**2 + (p1[1] - p2[1])**2 + (p1[2] - p2[2])**2 ) elif len(p1) == 2: return math.sqrt( (p1[0] - p2[0])**2 + (p1[1] - p2[1])**2 ) else: raise NotImplementedError def backwards(cur_point, next_point, distance): """ backwards(point, point, num) -> point Returns the point backwards along the given line. """ # Find the distance between the current and next point. distance_to_next = distance_between_points(cur_point, next_point) # normalise that value to 1.0 normalised_distance = 1. / distance_to_next # multiply the distance wanted to travel by the normalised value. interpolated_num = distance * normalised_distance backwards_point = interpolate_line(cur_point, next_point, -interpolated_num) return backwards_point def forwards(cur_point, next_point, distance): """ forwards(point, point, num) -> point Returns the point forwards the distance along the given line. From the current point! """ # Find the distance between the current and next point. distance_to_next = distance_between_points(cur_point, next_point) # normalise that value to 1.0 normalised_distance = 1. / distance_to_next # multiply the distance wanted to travel by the normalised value. interpolated_num = distance * normalised_distance forwards_point = interpolate_line(cur_point, next_point, interpolated_num) return forwards_point def forwards_from_next(cur_point, next_point, distance): """ forwards(point, point, num) -> point Returns the point forwards the distance along the given line. From the next point! """ forwards_point = interpolate_line(cur_point, next_point, 1.2) cur_point = next_point next_point = forwards_point # Find the distance between the current and next point. distance_to_next = distance_between_points(cur_point, next_point) # normalise that value to 1.0 normalised_distance = 1. / distance_to_next # multiply the distance wanted to travel by the normalised value. interpolated_num = distance * normalised_distance forwards_point = interpolate_line(cur_point, next_point, interpolated_num) return forwards_point def point_within(point, a_rect): """ point_within([x,y], rectstyle) -> true if a point is within the rect. """ x,y,w,h = a_rect px, py = point[:2] if px < x: return 0 if px > x + w: return 0 if py < y: return 0 if py > y + h: return 0 return 1 new_rdpyg/rdpyg/util/.pack_textures.py.swp0000644000175100017510000004000010220112601021160 0ustar renerene00000000000000b0VIM 6.3§_æ@7;renegrace/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/rdpyg/util/pack_textures.py3210#"! Utpÿwÿÿÿÿ—x@adwüûµdcb.óò¦Z/.ä ™ ˜ I    · „ ƒ ‚ ~ } o a ` _ ^ O  Ä ¼ ‘ ~ k N 3    û ° ¯ ‰ : . - ÿ æ å ˜ s ? ' & % øÆÅÄÖa ÞÝÇÆÅ©rq&Ù¿¾y]\FEÈ¡h-Û²ŠcM%üÌ­€];:,籃‚Q! if not r: r = self.try_fit(other_texture) for other_texture in other_textures: # try fitting them one at a time. # could be able to be fairly fast then. # TODO: sort the textures into batches of the same size. else: x_pos = 0 y_pos += 1 if(x_pos > number_on_x): x_pos += 1 self.sub_textures.append(o) o.y = y_pos * height o.x = x_pos * width else: unfitted.append(o) # not anymore room. if(y_pos > number_on_y): for o in other_textures: y_pos = 0 x_pos = 0 number_on_y = int(round(self.height / height)) number_on_x = int(round(self.width / width)) # then raise along the y. # See how many in a row we could fit along the x. if same_size and self.sub_textures == []: unfitted = [] # can optimize it. # If they are all the same size, and the texture is empty we same_size = 1 if len(r) == len(other_textures): other_textures) r = filter(lambda oo:(oo.height == height and oo.width == width), x,y,height,width = o.x, o.y, o.height, o.width o=other_textures[0] same_size = 0 # see if they are the same size. """ Returns true if successful???. Or returns the unfitted ones? """ Tries to fit the textures into itself. def try_fit_batch(self, other_textures): return self.search_for_fit(other_texture) # Do a search for a place to put it. return True self.sub_textures.append(other_texture) if(self.sub_textures == []): # an early in. if there are no other textures, then just put it in. return False if not self.could_fit(other_texture): """ """ Tries to fit the texture into itself. Returns true if successful. def try_fit(self, other_texture): return "<%s,%s,%s,%s>" % (self.x, self.y, self.height, self.width) def __repr__(self): self.sub_textures= [] self.width = width self.height = height self.y = y self.x = x def __init__(self, x,y, height,width): """ x,y bottom left is 0,0. Which is like opengl, and not like sdl. """ One texture which holds multiple smaller ones packed in.class Texture:#psyco.full()#import psyco""" you can specify a maximum size output texture. There will also need to be possibly multiple big output textures. So that be used to update texture memory as well as to update images. To make this code more useful it will work with rectangles. So that it can 2 sized images. The more video memory saved the faster a game can go. Power of 2 textures can be a waste of memory if you have non power of and you can reduce geometry calls too. it can speed up rendering as you need to do less texture binding calls, This is useful for eg opengl where there are textures size limits. Also As well as to cut up bigger textures into smaller ones. Code to pack multiple textures into larger ones. packing/cutting functions for where the images are located on the textures. TODO: need to return UV coordinates and pixel coordinates for the """adoƒ @ÐϾ˜‚e:" ñÈR+ Î   ‚ e K J 3 2    í Å ­ Ÿ † … „ ƒ n = 1      Ì | a 4 » ³ • ” “ ’ Z  î í ­ ¥ ‡ † … „ ƒ ‚ raise NotImplementedError """ TODO: how to determine where the small bits are placed? big_image - a Texture object. """ returns a list of Textures which the big_image is split into.def split_big_image(big_image, max_size, use_pow2 = 1): raise NotImplementedError """ use_pow2 - if 0 then we do not have to limit ourselves to power of 2. max_size - of the output Textures. small_list - list of Texture objects packed into them. """ returns a list of Texture objects with the textures from the small_listdef pack_images_into_multiple(small_list, max_size, use_pow2 = 1): self.sub_textures= [] """ """ clears all the textures in this one. def clear(self): return False else: return True self.sub_textures.append(o) if not hits: break if not hits: x += 1 break if not hits: break x = sub.x + sub.width # move accross to the x of the sub. hits = 1 if sub.collide(o): # then we need to keep looking. # if we can fit inside a sub texture, for sub in self.sub_textures: hits = 0 o.y = y o.x = x #for x in range(x_try, x_end): while x < x_end: x = x_try for y in range(y_try, y_end): hits = 0 # then increment y_try and go again.new_rdpyg/rdpyg/util/__init__.py0000644000175100017510000000000010065303761017164 0ustar renerene00000000000000new_rdpyg/rdpyg/util/cyclic_list.py0000644000175100017510000000225510076400066017742 0ustar renerene00000000000000# file: cycling list. # purpose: a pointer to the current item is needed. # A goto_next method is needed. Which cycles over the next idx. import UserList class cyclic_list(UserList.UserList): def __init__(self, *args, **kwargs): UserList.UserList.__init__(self, *args, **kwargs) self.idx = 0 def next(self): """ increments the cursor, and returns the new current idx. """ self.idx += 1 if self.idx >= len(self.data): self.idx = 0 return self.idx def prev(self): """ decrements the cursor, and returns the new current idx. """ self.idx -= 1 if self.idx < 0: self.idx = len(self.data) -1 return self.idx def cur(self): """ returns the element at the current cursor. """ return self.data[self.idx] def set_cur(self, idx): """ Sets the current cursor to the given idx. """ self.idx = idx if __name__ == "__main__": c = cyclic_list([1,2,3,4]) print c.idx c.next() print c.idx c.next() print c.idx c.next() print c.idx c.next() print c.idx for x in range(5): c.prev() print c.idx new_rdpyg/rdpyg/util/pack_textures.py0000644000175100017510000002074010071457647020335 0ustar renerene00000000000000""" TODO: need to return UV coordinates and pixel coordinates for the packing/cutting functions for where the images are located on the textures. Code to pack multiple textures into larger ones. As well as to cut up bigger textures into smaller ones. This is useful for eg opengl where there are textures size limits. Also it can speed up rendering as you need to do less texture binding calls, and you can reduce geometry calls too. Power of 2 textures can be a waste of memory if you have non power of 2 sized images. The more video memory saved the faster a game can go. To make this code more useful it will work with rectangles. So that it can be used to update texture memory as well as to update images. There will also need to be possibly multiple big output textures. So that you can specify a maximum size output texture. """ #import psyco #psyco.full() class Texture: """ One texture which holds multiple smaller ones packed in. x,y bottom left is 0,0. Which is like opengl, and not like sdl. """ def __init__(self, x,y, height,width): self.x = x self.y = y self.height = height self.width = width self.sub_textures= [] def __repr__(self): return "<%s,%s,%s,%s>" % (self.x, self.y, self.height, self.width) def try_fit(self, other_texture): """ Tries to fit the texture into itself. Returns true if successful. """ if not self.could_fit(other_texture): return False # an early in. if there are no other textures, then just put it in. if(self.sub_textures == []): self.sub_textures.append(other_texture) return True # Do a search for a place to put it. return self.search_for_fit(other_texture) def try_fit_batch(self, other_textures): """ Tries to fit the textures into itself. Returns true if successful???. Or returns the unfitted ones? """ # see if they are the same size. same_size = 0 o=other_textures[0] x,y,height,width = o.x, o.y, o.height, o.width r = filter(lambda oo:(oo.height == height and oo.width == width), other_textures) if len(r) == len(other_textures): same_size = 1 # If they are all the same size, and the texture is empty we # can optimize it. unfitted = [] if same_size and self.sub_textures == []: # See how many in a row we could fit along the x. # then raise along the y. number_on_x = int(round(self.width / width)) number_on_y = int(round(self.height / height)) x_pos = 0 y_pos = 0 for o in other_textures: if(y_pos > number_on_y): # not anymore room. unfitted.append(o) else: o.x = x_pos * width o.y = y_pos * height self.sub_textures.append(o) x_pos += 1 if(x_pos > number_on_x): y_pos += 1 x_pos = 0 else: # TODO: sort the textures into batches of the same size. # could be able to be fairly fast then. # try fitting them one at a time. for other_texture in other_textures: r = self.try_fit(other_texture) if not r: unfitted.append(other_texture) return unfitted def collide(self, other_texture): """ checks this texture only to see if it collides. Returns True if it does collide. """ sx = self.x sy = self.y ox = other_texture.x oy = other_texture.y s_right = sx + self.width s_top = sy + self.height o_right = ox + other_texture.width o_top = oy + other_texture.height # check that it is not within the x or y. if(ox >= s_right): return False if(o_right < sx): return False if(o_top <= sy): return False if(oy > s_top): return False return True def could_fit(self, other_texture): """ checks this texture only to see if it fits. Does not care about any textures inside. """ # some early outs. if(other_texture.height > self.height): return False if(other_texture.width > self.width): return False if(other_texture.x != 0 or other_texture.y != 0 or self.x != 0 or self.y != 0): # if the x,y is not zero then need to adjust for that. s_right = self.x + self.width s_top = self.y + self.height o_right = other_texture.x + other_texture.width o_top = other_texture.y + other_texture.height if(o_top > s_top or o_right > s_right or other_texture.x < self.x or other_texture.y < self.y): return False return True def search_for_fit(self, o): """ do a search for a place to put the texture, and place it. Return True if successful, else false. o - other texture. """ #TODO: try and optimize this. #return self._brute_force(o) return self._bottom_left_first(o) def _brute_force(self, o): """ do a brute force search from bottom left to top right. Return True if successful, else false. o - other texture. """ x_try = self.x y_try = self.y x_end = self.x + self.width y_end = self.y + self.height # go from x_try -> x_end seeing if it fits, # then increment y_try and go again. hits = 0 for y in range(y_try, y_end): for x in range(x_try, x_end): o.x = x o.y = y hits = 0 for sub in self.sub_textures: # if we can fit inside a sub texture, # then we need to keep looking. if sub.collide(o): hits = 1 break if not hits: break if not hits: break if not hits: self.sub_textures.append(o) return True else: return False def _bottom_left_first(self, o): """ do a search from bottom left. Return True if successful, else false. o - other texture. """ x_try = self.x y_try = self.y x_end = self.x + self.width y_end = self.y + self.height # go from x_try -> x_end seeing if it fits, # then increment y_try and go again. hits = 0 for y in range(y_try, y_end): x = x_try while x < x_end: #for x in range(x_try, x_end): o.x = x o.y = y hits = 0 for sub in self.sub_textures: # if we can fit inside a sub texture, # then we need to keep looking. if sub.collide(o): hits = 1 # move accross to the x of the sub. x = sub.x + sub.width break if not hits: break x += 1 if not hits: break if not hits: self.sub_textures.append(o) return True else: return False def clear(self): """ clears all the textures in this one. """ self.sub_textures= [] def pack_images_into_multiple(small_list, max_size, use_pow2 = 1): """ returns a list of Texture objects with the textures from the small_list packed into them. small_list - list of Texture objects max_size - of the output Textures. use_pow2 - if 0 then we do not have to limit ourselves to power of 2. """ raise NotImplementedError def split_big_image(big_image, max_size, use_pow2 = 1): """ returns a list of Textures which the big_image is split into. big_image - a Texture object. TODO: how to determine where the small bits are placed? """ raise NotImplementedError new_rdpyg/rdpyg/util/vtimer.py0000644000175100017510000000711107774203450016754 0ustar renerene00000000000000# file: virtual_timer.py # purpose: to be able to do things once a time is up. # or to keep track of something which lasts a given time. class vtimer: """ times something. when it is done it is equal to 1, else equal to 0. Useage: v = VirtTimer(5.) if v: dosomething() v.Update(elapsed_time) OR with a callback. v = VirtTimer(5., dosomething) v.Update(elapsed_time) Call Update on each game tick. Passing in elapsed time in seconds allows you to have timers running on different time. So pausing, and things like bullet time are easy. Also has some other features. You can be notified on the "edge" of time. That is when a timer is just_started or just_finished. if v.just_finished: do_some_other_thing() You can find how much time is left. As well as get a normalised amount of time left(between 0. and 1.). eg. time_before_powerup_runs_out = powerup_timer.left() """ def __init__(self, length, callback = None): """ length - of time to run for. callback - optional callback function to call. """ self.length = length self.callback = callback self.reset() self.update = self.Update self.is_not_used = 0 def Update(self, elapsed_time): """Update(1.0) -> None To be called on every game tic. elapsed_time - since last update. """ if self.just_started: self.just_started = 0 if self.just_finished: self.just_finished = 0 self.total_elapsed_time += elapsed_time if self.total_elapsed_time >= self.length: if self.done == 0: self.just_finished = 1 self.done = 1 if self.callback != None: if not self.called_callback: self.callback() self.called_callback = 1 def reset(self): """ reset() -> None Resets the timer to the beginning. """ self.total_elapsed_time = 0. self.done = 0 self.called_callback = 0 self.just_started = 1 self.just_finished = 0 self.is_not_used = 0 def set_finished_no_callback(self): """ set_finished_no_callback() -> None Sets it to finished, without calling callback. not just finished. """ self.total_elapsed_time = 10000000000000L self.done = 1 self.called_callback = 1 self.just_started = 0 self.just_finished = 0 self.is_not_used = 1 def not_used(self): """ not_used -> None For if the timer is not being used. This is useful for one time, timers. """ self.is_not_used = 1 # equality methods used for testing the timer. def __eq__(self, other): return self.done == other def __ne__(self, other): return not self.__eq__(other) def __nonzero__(self): return self.done def left(self): """ left() -> time left until finished. """ left = self.length - self.total_elapsed_time if left < 0.: return 0. else: return left def left_normalised(self): """ left_normalised() -> the time left normalized to 0. - 1. """ left = self.left() if left == 0.: return 0. else: return (1. / self.length) * left new_rdpyg/rdpyg/__init__.py0000644000175100017510000000000010065303761016207 0ustar renerene00000000000000new_rdpyg/rdpyg/__init__.pyc0000644000175100017510000000014310160170501016350 0ustar renerene00000000000000;ò ñ‡Õ@c@sdS(N((((s./rdpyg/__init__.pys?snew_rdpyg/tests/0000755000175100017510000000000010250740305014120 5ustar renerene00000000000000new_rdpyg/tests/data/0000755000175100017510000000000010076013570015034 5ustar renerene00000000000000new_rdpyg/tests/data/models/0000755000175100017510000000000010076013776016327 5ustar renerene00000000000000new_rdpyg/tests/data/models/bend.txt.old_md50000644000175100017510000000002010076013776021312 0ustar renerene00000000000000‚’ÝÖªïý‰"¶ ¬µnew_rdpyg/tests/data/models/bend.txt0000644000175100017510000002335610076013574020005 0ustar renerene00000000000000// MilkShape 3D ASCII Frames: 30 Frame: 1 Meshes: 1 "Cylinder01" 0 -1 91 0 4.500000 -33.250000 0.000000 0.000000 1.000000 6 0 4.500000 -23.666668 0.000000 0.000000 0.833333 5 0 3.897114 -23.666668 2.250000 0.083333 0.833333 5 0 3.897114 -33.250000 2.250000 0.083333 1.000000 6 0 4.500000 -14.083334 0.000000 0.000000 0.666667 4 0 3.897114 -14.083334 2.250000 0.083333 0.666667 4 0 4.500000 -4.500000 0.000000 0.000000 0.500000 3 0 3.897114 -4.500000 2.250000 0.083333 0.500000 3 0 4.500000 5.083332 0.000000 0.000000 0.333333 2 0 3.897114 5.083332 2.250000 0.083333 0.333333 2 0 4.500000 14.666668 0.000000 0.000000 0.166667 1 0 3.897114 14.666668 2.250000 0.083333 0.166667 1 0 4.500000 24.250000 0.000000 0.000000 0.000000 0 0 3.897114 24.250000 2.250000 0.083333 0.000000 0 0 2.250000 -33.250000 3.897114 0.166667 1.000000 6 0 2.250000 -23.666668 3.897114 0.166667 0.833333 5 0 2.250000 -14.083334 3.897114 0.166667 0.666667 4 0 2.250000 -4.500000 3.897114 0.166667 0.500000 3 0 2.250000 5.083332 3.897114 0.166667 0.333333 2 0 2.250000 14.666668 3.897114 0.166667 0.166667 1 0 2.250000 24.250000 3.897114 0.166667 0.000000 0 0 0.000000 -23.666668 4.500000 0.250000 0.833333 5 0 0.000000 -33.250000 4.500000 0.250000 1.000000 6 0 0.000000 -14.083334 4.500000 0.250000 0.666667 4 0 0.000000 -4.500000 4.500000 0.250000 0.500000 3 0 0.000000 5.083332 4.500000 0.250000 0.333333 2 0 0.000000 14.666668 4.500000 0.250000 0.166667 1 0 0.000000 24.250000 4.500000 0.250000 0.000000 0 0 -2.250000 -33.250000 3.897114 0.333333 1.000000 6 0 -2.250000 -23.666668 3.897114 0.333333 0.833333 5 0 -2.250000 -14.083334 3.897114 0.333333 0.666667 4 0 -2.250000 -4.500000 3.897114 0.333333 0.500000 3 0 -2.250000 5.083332 3.897114 0.333333 0.333333 2 0 -2.250000 14.666668 3.897114 0.333333 0.166667 1 0 -2.250000 24.250000 3.897114 0.333333 0.000000 0 0 -3.897114 -23.666668 2.250000 0.416667 0.833333 5 0 -3.897114 -33.250000 2.250000 0.416667 1.000000 6 0 -3.897114 -14.083334 2.250000 0.416667 0.666667 4 0 -3.897114 -4.500000 2.250000 0.416667 0.500000 3 0 -3.897114 5.083332 2.250000 0.416667 0.333333 2 0 -3.897114 14.666668 2.250000 0.416667 0.166667 1 0 -3.897114 24.250000 2.250000 0.416667 0.000000 0 0 -4.500000 -33.250000 0.000000 0.500000 1.000000 6 0 -4.500000 -23.666668 0.000000 0.500000 0.833333 5 0 -4.500000 -14.083334 0.000000 0.500000 0.666667 4 0 -4.500000 -4.500000 0.000000 0.500000 0.500000 3 0 -4.500000 5.083332 0.000000 0.500000 0.333333 2 0 -4.500000 14.666668 0.000000 0.500000 0.166667 1 0 -4.500000 24.250000 0.000000 0.500000 0.000000 0 0 -3.897114 -23.666668 -2.250000 0.583333 0.833333 5 0 -3.897114 -33.250000 -2.250000 0.583333 1.000000 6 0 -3.897114 -14.083334 -2.250000 0.583333 0.666667 4 0 -3.897114 -4.500000 -2.250000 0.583333 0.500000 3 0 -3.897114 5.083332 -2.250000 0.583333 0.333333 2 0 -3.897114 14.666668 -2.250000 0.583333 0.166667 1 0 -3.897114 24.250000 -2.250000 0.583333 0.000000 0 0 -2.250000 -33.250000 -3.897114 0.666667 1.000000 6 0 -2.250000 -23.666668 -3.897114 0.666667 0.833333 5 0 -2.250000 -14.083334 -3.897114 0.666667 0.666667 4 0 -2.250000 -4.500000 -3.897114 0.666667 0.500000 3 0 -2.250000 5.083332 -3.897114 0.666667 0.333333 2 0 -2.250000 14.666668 -3.897114 0.666667 0.166667 1 0 -2.250000 24.250000 -3.897114 0.666667 0.000000 0 0 -0.000000 -23.666668 -4.500000 0.750000 0.833333 5 0 -0.000000 -33.250000 -4.500000 0.750000 1.000000 6 0 -0.000000 -14.083334 -4.500000 0.750000 0.666667 4 0 -0.000000 -4.500000 -4.500000 0.750000 0.500000 3 0 -0.000000 5.083332 -4.500000 0.750000 0.333333 2 0 -0.000000 14.666668 -4.500000 0.750000 0.166667 1 0 -0.000000 24.250000 -4.500000 0.750000 0.000000 0 0 2.250000 -33.250000 -3.897114 0.833333 1.000000 6 0 2.250000 -23.666668 -3.897114 0.833333 0.833333 5 0 2.250000 -14.083334 -3.897114 0.833333 0.666667 4 0 2.250000 -4.500000 -3.897114 0.833333 0.500000 3 0 2.250000 5.083332 -3.897114 0.833333 0.333333 2 0 2.250000 14.666668 -3.897114 0.833333 0.166667 1 0 2.250000 24.250000 -3.897114 0.833333 0.000000 0 0 3.897114 -23.666668 -2.250000 0.916667 0.833333 5 0 3.897114 -33.250000 -2.250000 0.916667 1.000000 6 0 3.897114 -14.083334 -2.250000 0.916667 0.666667 4 0 3.897114 -4.500000 -2.250000 0.916667 0.500000 3 0 3.897114 5.083332 -2.250000 0.916667 0.333333 2 0 3.897114 14.666668 -2.250000 0.916667 0.166667 1 0 3.897114 24.250000 -2.250000 0.916667 0.000000 0 0 4.500000 -33.250000 0.000000 1.000000 1.000000 6 0 4.500000 -23.666668 0.000000 1.000000 0.833333 5 0 4.500000 -14.083334 0.000000 1.000000 0.666667 4 0 4.500000 -4.500000 0.000000 1.000000 0.500000 3 0 4.500000 5.083332 0.000000 1.000000 0.333333 2 0 4.500000 14.666668 0.000000 1.000000 0.166667 1 0 4.500000 24.250000 0.000000 1.000000 0.000000 0 12 1.000000 0.000000 0.000000 0.866025 0.000000 0.500000 0.500000 0.000000 0.866025 0.000000 0.000000 1.000000 -0.500000 0.000000 0.866025 -0.866025 0.000000 0.500000 -1.000000 0.000000 0.000000 -0.866025 0.000000 -0.500000 -0.500000 0.000000 -0.866025 0.000000 0.000000 -1.000000 0.500000 0.000000 -0.866025 0.866025 0.000000 -0.500000 144 0 0 1 2 0 0 1 1 0 0 2 3 0 1 1 1 0 1 4 2 0 0 1 1 0 4 5 2 0 1 1 1 0 4 6 7 0 0 1 1 0 4 7 5 0 1 1 1 0 6 8 7 0 0 1 1 0 8 9 7 0 1 1 1 0 8 10 11 0 0 1 1 0 8 11 9 0 1 1 1 0 10 12 11 0 0 1 1 0 12 13 11 0 1 1 1 0 3 2 14 1 1 2 1 0 2 15 14 1 2 2 1 0 2 5 16 1 1 2 1 0 2 16 15 1 2 2 1 0 5 7 16 1 1 2 1 0 7 17 16 1 2 2 1 0 7 9 18 1 1 2 1 0 7 18 17 1 2 2 1 0 9 11 18 1 1 2 1 0 11 19 18 1 2 2 1 0 11 13 20 1 1 2 1 0 11 20 19 1 2 2 1 0 14 15 21 2 2 3 1 0 14 21 22 2 3 3 1 0 15 16 21 2 2 3 1 0 16 23 21 2 3 3 1 0 16 17 24 2 2 3 1 0 16 24 23 2 3 3 1 0 17 18 24 2 2 3 1 0 18 25 24 2 3 3 1 0 18 19 26 2 2 3 1 0 18 26 25 2 3 3 1 0 19 20 26 2 2 3 1 0 20 27 26 2 3 3 1 0 22 21 28 3 3 4 1 0 21 29 28 3 4 4 1 0 21 23 30 3 3 4 1 0 21 30 29 3 4 4 1 0 23 24 30 3 3 4 1 0 24 31 30 3 4 4 1 0 24 25 32 3 3 4 1 0 24 32 31 3 4 4 1 0 25 26 32 3 3 4 1 0 26 33 32 3 4 4 1 0 26 27 34 3 3 4 1 0 26 34 33 3 4 4 1 0 28 29 35 4 4 5 1 0 28 35 36 4 5 5 1 0 29 30 35 4 4 5 1 0 30 37 35 4 5 5 1 0 30 31 38 4 4 5 1 0 30 38 37 4 5 5 1 0 31 32 38 4 4 5 1 0 32 39 38 4 5 5 1 0 32 33 40 4 4 5 1 0 32 40 39 4 5 5 1 0 33 34 40 4 4 5 1 0 34 41 40 4 5 5 1 0 36 35 42 5 5 6 1 0 35 43 42 5 6 6 1 0 35 37 44 5 5 6 1 0 35 44 43 5 6 6 1 0 37 38 44 5 5 6 1 0 38 45 44 5 6 6 1 0 38 39 46 5 5 6 1 0 38 46 45 5 6 6 1 0 39 40 46 5 5 6 1 0 40 47 46 5 6 6 1 0 40 41 48 5 5 6 1 0 40 48 47 5 6 6 1 0 42 43 49 6 6 7 1 0 42 49 50 6 7 7 1 0 43 44 49 6 6 7 1 0 44 51 49 6 7 7 1 0 44 45 52 6 6 7 1 0 44 52 51 6 7 7 1 0 45 46 52 6 6 7 1 0 46 53 52 6 7 7 1 0 46 47 54 6 6 7 1 0 46 54 53 6 7 7 1 0 47 48 54 6 6 7 1 0 48 55 54 6 7 7 1 0 50 49 56 7 7 8 1 0 49 57 56 7 8 8 1 0 49 51 58 7 7 8 1 0 49 58 57 7 8 8 1 0 51 52 58 7 7 8 1 0 52 59 58 7 8 8 1 0 52 53 60 7 7 8 1 0 52 60 59 7 8 8 1 0 53 54 60 7 7 8 1 0 54 61 60 7 8 8 1 0 54 55 62 7 7 8 1 0 54 62 61 7 8 8 1 0 56 57 63 8 8 9 1 0 56 63 64 8 9 9 1 0 57 58 63 8 8 9 1 0 58 65 63 8 9 9 1 0 58 59 66 8 8 9 1 0 58 66 65 8 9 9 1 0 59 60 66 8 8 9 1 0 60 67 66 8 9 9 1 0 60 61 68 8 8 9 1 0 60 68 67 8 9 9 1 0 61 62 68 8 8 9 1 0 62 69 68 8 9 9 1 0 64 63 70 9 9 10 1 0 63 71 70 9 10 10 1 0 63 65 72 9 9 10 1 0 63 72 71 9 10 10 1 0 65 66 72 9 9 10 1 0 66 73 72 9 10 10 1 0 66 67 74 9 9 10 1 0 66 74 73 9 10 10 1 0 67 68 74 9 9 10 1 0 68 75 74 9 10 10 1 0 68 69 76 9 9 10 1 0 68 76 75 9 10 10 1 0 70 71 77 10 10 11 1 0 70 77 78 10 11 11 1 0 71 72 77 10 10 11 1 0 72 79 77 10 11 11 1 0 72 73 80 10 10 11 1 0 72 80 79 10 11 11 1 0 73 74 80 10 10 11 1 0 74 81 80 10 11 11 1 0 74 75 82 10 10 11 1 0 74 82 81 10 11 11 1 0 75 76 82 10 10 11 1 0 76 83 82 10 11 11 1 0 78 77 84 11 11 0 1 0 77 85 84 11 0 0 1 0 77 79 86 11 11 0 1 0 77 86 85 11 0 0 1 0 79 80 86 11 11 0 1 0 80 87 86 11 0 0 1 0 80 81 88 11 11 0 1 0 80 88 87 11 0 0 1 0 81 82 88 11 11 0 1 0 82 89 88 11 0 0 1 0 82 83 90 11 11 0 1 0 82 90 89 11 0 0 1 Materials: 0 Bones: 7 "joint1" "" 0 0.000000 24.250000 0.000000 1.545162 1.570796 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.000000 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.000000 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 "joint2" "joint1" 0 0.000000 0.000000 9.753204 0.106538 0.000000 0.000000 3 1.000000 0.000000 -0.000000 -0.000000 15.000000 0.000000 0.000000 -0.000000 30.000000 0.000000 0.000000 -0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 -0.401426 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 "joint3" "joint2" 0 0.000000 0.000000 9.280355 0.134906 -0.000000 3.141593 3 1.000000 -0.000000 -0.000000 0.000000 15.000000 -0.000000 -0.000000 0.000000 30.000000 -0.000000 -0.000000 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.366519 0.000000 -0.000000 30.000000 0.000000 0.000000 0.000000 "joint4" "joint3" 0 0.000000 0.000000 9.263503 -0.054002 0.000000 0.000000 3 1.000000 0.000000 -0.000000 0.000000 15.000000 0.000000 -0.000000 0.000000 30.000000 0.000000 -0.000000 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.523599 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 "joint5" "joint4" 0 0.000000 0.000000 10.000000 0.000000 0.000000 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.000000 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.401426 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 "joint6" "joint5" 0 0.000000 0.000000 10.000000 0.026310 0.000259 0.000000 3 1.000000 0.000000 -0.000000 -0.000000 15.000000 0.000000 0.000000 -0.000000 30.000000 0.000000 0.000000 -0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.383972 -0.000016 0.000097 30.000000 0.000000 0.000000 0.000000 "joint7" "joint6" 5 0.000000 0.000000 9.503289 0.000000 0.000000 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.000000 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 3 1.000000 0.000000 0.000000 0.000000 15.000000 0.174533 0.000000 0.000000 30.000000 0.000000 0.000000 0.000000 new_rdpyg/tests/data/models/bend.txt.pickle0000644000175100017510000002003210076013776021243 0ustar renerene00000000000000}q(Ubonesq]q((curdpyg.converters.ms3d_ascii_importer milk_bones qoq}q(U parent_nameqUUnameqUjoint1q U rotation_keysq ]q (]q (G?ðGGGe]q (G@.GGGe]q(G@>GGGeeUflagsqKUpositionq]q(GG@8@GeUrotationq]q(G?ø¸ûÊYêG?ù!úü‹zGeU position_keysq]q(]q(G?ðGGGe]q(G@.GGGe]q(G@>GGGeeub(hoq}q(hUjoint1qhUjoint2qh ]q(]q(G?ðGGGe]q(G@.G¿Ù°ö­pæóGGe]q (G@>GGGeehKh]q!(GGG@#£ôfnÊeh]q"(G?»F ÇÿÞGGeh]q#(]q$(G?ðGGGe]q%(G@.GGGe]q&(G@>GGGeeub(hoq'}q((hUjoint2q)hUjoint3q*h ]q+(]q,(G?ðGGGe]q-(G@.G?×u —5;GGe]q.(G@>GGGeehKh]q/(GGG@"Š°ÈŠHeh]q0(G?ÁD™_áGG@ !û‚½eh]q1(]q2(G?ðGGGe]q3(G@.GGGe]q4(G@>GGGeeub(hoq5}q6(hUjoint3q7hUjoint4q8h ]q9(]q:(G?ðGGGe]q;(G@.G?àÁR°¦üYGGe]q<(G@>GGGeehKh]q=(GGG@"†éÝ~˸eh]q>(G¿«¦&oÖQ±GGeh]q?(]q@(G?ðGGGe]qA(G@.GGGe]qB(G@>GGGeeub(hoqC}qD(hUjoint4qEhUjoint5qFh ]qG(]qH(G?ðGGGe]qI(G@.G?Ù°ö­pæóGGe]qJ(G@>GGGeehKh]qK(GGG@$eh]qL(GGGeh]qM(]qN(G?ðGGGe]qO(G@.GGGe]qP(G@>GGGeeub(hoqQ}qR(hUjoint5qShUjoint6qTh ]qU(]qV(G?ðGGGe]qW(G@.G?Ø’ÿK¥G¾ðÆ÷ µíG?mO“¼ e]qX(G@>GGGeehKh]qY(GGG@$eh]qZ(G?šñ6;%pG?0ùL‡˜VGeh]q[(]q\(G?ðGGGe]q](G@.GGGe]q^(G@>GGGeeub(hoq_}q`(hUjoint6qahUjoint7qbh ]qc(]qd(G?ðGGGe]qe(G@.G?ÆWë‰PvGGe]qf(G@>GGGeehKh]qg(GGG@#¯†ßƒeh]qh(GGGeh]qi(]qj(G?ðGGGe]qk(G@.GGGe]ql(G@>GGGeeubeU materialsqm]qnU mesh_dataqo]qp}qq(U texcoordsqr]qs(GGGG?ÅUX!)EtG?µUO½­uG?ÅUX!)EtG?µUO½­uGGG?ÕUSïk]FG?µUO½­uG?ÕUSïk]FGG?àG?µUO½­uG?àGG?åUVJQ]G?µUO½­uG?åUVJQ]GG?ꪩ÷µ®£G?µUO½­uG?ꪩ÷µ®£GG?ðG?µUO½­uG?ðG?ÅUX!)EtGG?ÅUX!)EtG?ÅUX!)EtG?ÅUX!)EtG?ÕUSïk]FG?ÅUX!)EtG?àG?ÅUX!)EtG?åUVJQ]G?ÅUX!)EtG?ꪩ÷µ®£G?ÅUX!)EtG?ðG?ÐG?ÅUX!)EtG?ÐGG?ÐG?ÕUSïk]FG?ÐG?àG?ÐG?åUVJQ]G?ÐG?ꪩ÷µ®£G?ÐG?ðG?ÕUSïk]FGG?ÕUSïk]FG?ÅUX!)EtG?ÕUSïk]FG?ÕUSïk]FG?ÕUSïk]FG?àG?ÕUSïk]FG?åUVJQ]G?ÕUSïk]FG?ꪩ÷µ®£G?ÕUSïk]FG?ðG?Úª¬”¢ºG?ÅUX!)EtG?Úª¬”¢ºGG?Úª¬”¢ºG?ÕUSïk]FG?Úª¬”¢ºG?àG?Úª¬”¢ºG?åUVJQ]G?Úª¬”¢ºG?ꪩ÷µ®£G?Úª¬”¢ºG?ðG?àGG?àG?ÅUX!)EtG?àG?ÕUSïk]FG?àG?àG?àG?åUVJQ]G?àG?ꪩ÷µ®£G?àG?ðG?⪩÷µ®£G?ÅUX!)EtG?⪩÷µ®£GG?⪩÷µ®£G?ÕUSïk]FG?⪩÷µ®£G?àG?⪩÷µ®£G?åUVJQ]G?⪩÷µ®£G?ꪩ÷µ®£G?⪩÷µ®£G?ðG?åUVJQ]GG?åUVJQ]G?ÅUX!)EtG?åUVJQ]G?ÕUSïk]FG?åUVJQ]G?àG?åUVJQ]G?åUVJQ]G?åUVJQ]G?ꪩ÷µ®£G?åUVJQ]G?ðG?èG?ÅUX!)EtG?èGG?èG?ÕUSïk]FG?èG?àG?èG?åUVJQ]G?èG?ꪩ÷µ®£G?èG?ðG?ꪩ÷µ®£GG?ꪩ÷µ®£G?ÅUX!)EtG?ꪩ÷µ®£G?ÕUSïk]FG?ꪩ÷µ®£G?àG?ꪩ÷µ®£G?åUVJQ]G?ꪩ÷µ®£G?ꪩ÷µ®£G?ꪩ÷µ®£G?ðG?íUVJQ]G?ÅUX!)EtG?íUVJQ]GG?íUVJQ]G?ÕUSïk]FG?íUVJQ]G?àG?íUVJQ]G?åUVJQ]G?íUVJQ]G?ꪩ÷µ®£G?íUVJQ]G?ðG?ðGG?ðG?ÅUX!)EtG?ðG?ÕUSïk]FG?ðG?àG?ðG?åUVJQ]G?ðG?ꪩ÷µ®£G?ðG?ðeUmaterial_indexqtJÿÿÿÿUpointsqu]qv(G@GÀ@ GG@GÀ7ªªÁ J,GG@-JÖEGÀ7ªªÁ J,G@G@-JÖEGÀ@ G@G@GÀ,*ªÁ J,GG@-JÖEGÀ,*ªÁ J,G@G@GÀGG@-JÖEGÀG@G@G@UTûÚ×RGG@-JÖEG@UTûÚ×RG@G@G@-UU‚”WGG@-JÖEG@-UU‚”WG@G@G@8@GG@-JÖEG@8@G@G@GÀ@ G@-JÖEG@GÀ7ªªÁ J,G@-JÖEG@GÀ,*ªÁ J,G@-JÖEG@GÀG@-JÖEG@G@UTûÚ×RG@-JÖEG@G@-UU‚”WG@-JÖEG@G@8@G@-JÖEGGÀ7ªªÁ J,G@GGÀ@ G@GGÀ,*ªÁ J,G@GGÀG@GG@UTûÚ×RG@GG@-UU‚”WG@GG@8@G@GÀGÀ@ G@-JÖEGÀGÀ7ªªÁ J,G@-JÖEGÀGÀ,*ªÁ J,G@-JÖEGÀGÀG@-JÖEGÀG@UTûÚ×RG@-JÖEGÀG@-UU‚”WG@-JÖEGÀG@8@G@-JÖEGÀ-JÖEGÀ7ªªÁ J,G@GÀ-JÖEGÀ@ G@GÀ-JÖEGÀ,*ªÁ J,G@GÀ-JÖEGÀG@GÀ-JÖEG@UTûÚ×RG@GÀ-JÖEG@-UU‚”WG@GÀ-JÖEG@8@G@GÀGÀ@ GGÀGÀ7ªªÁ J,GGÀGÀ,*ªÁ J,GGÀGÀGGÀG@UTûÚ×RGGÀG@-UU‚”WGGÀG@8@GGÀ-JÖEGÀ7ªªÁ J,GÀGÀ-JÖEGÀ@ GÀGÀ-JÖEGÀ,*ªÁ J,GÀGÀ-JÖEGÀGÀGÀ-JÖEG@UTûÚ×RGÀGÀ-JÖEG@-UU‚”WGÀGÀ-JÖEG@8@GÀGÀGÀ@ GÀ-JÖEGÀGÀ7ªªÁ J,GÀ-JÖEGÀGÀ,*ªÁ J,GÀ-JÖEGÀGÀGÀ-JÖEGÀG@UTûÚ×RGÀ-JÖEGÀG@-UU‚”WGÀ-JÖEGÀG@8@GÀ-JÖEGGÀ7ªªÁ J,GÀGGÀ@ GÀGGÀ,*ªÁ J,GÀGGÀGÀGG@UTûÚ×RGÀGG@-UU‚”WGÀGG@8@GÀG@GÀ@ GÀ-JÖEG@GÀ7ªªÁ J,GÀ-JÖEG@GÀ,*ªÁ J,GÀ-JÖEG@GÀGÀ-JÖEG@G@UTûÚ×RGÀ-JÖEG@G@-UU‚”WGÀ-JÖEG@G@8@GÀ-JÖEG@-JÖEGÀ7ªªÁ J,GÀG@-JÖEGÀ@ GÀG@-JÖEGÀ,*ªÁ J,GÀG@-JÖEGÀGÀG@-JÖEG@UTûÚ×RGÀG@-JÖEG@-UU‚”WGÀG@-JÖEG@8@GÀG@GÀ@ GG@GÀ7ªªÁ J,GG@GÀ,*ªÁ J,GG@GÀGG@G@UTûÚ×RGG@G@-UU‚”WGG@G@8@GeUnormalsqw]qx(GGGG?àGG?ë¶z–¼GG?ðGG?ë¶z–¼GG?àGGGG¿àGG¿ë¶z–¼GG¿ðGG¿ë¶z–¼GG¿àeUindicesqy]qz(KKKKKKKKKKKKKKKKKKKKKKK KKK K KK K K K K K K K KKKKKKKKKKKKKKKKKKKK KKKKK K KK KKK K KK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KK KKKK KK!K KKK"KK"K!KKK#KK#K$KKK#KK%K#KKK&KK&K%KK K&K K'K&K K!K(K K(K'K!K"K(K"K)K(K$K#K*K#K+K*K#K%K,K#K,K+K%K&K,K&K-K,K&K'K.K&K.K-K'K(K.K(K/K.K(K)K0K(K0K/K*K+K1K*K1K2K+K,K1K,K3K1K,K-K4K,K4K3K-K.K4K.K5K4K.K/K6K.K6K5K/K0K6K0K7K6K2K1K8K1K9K8K1K3K:K1K:K9K3K4K:K4K;K:K4K5KK6K>K=K8K9K?K8K?K@K9K:K?K:KAK?K:K;KBK:KBKAK;KKDK>KEKDK@K?KFK?KGKFK?KAKHK?KHKGKAKBKHKBKIKHKBKCKJKBKJKIKCKDKJKDKKKJKDKEKLKDKLKKKFKGKMKFKMKNKGKHKMKHKOKMKHKIKPKHKPKOKIKJKPKJKQKPKJKKKRKJKRKQKKKLKRKLKSKRKNKMKTKMKUKTKMKOKVKMKVKUKOKPKVKPKWKVKPKQKXKPKXKWKQKRKXKRKYKXKRKSKZKRKZKYeU bone_indicesq{]q|(KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKeuau.new_rdpyg/tests/data/sounds/0000755000175100017510000000000010075762547016365 5ustar renerene00000000000000new_rdpyg/tests/data/sounds/one_bump3.ogg0000644000175100017510000001636707713714564020770 0ustar renerene00000000000000OggS ,–8 vorbisD¬€8¸OggS ,–OúÙU-ÿÿÿÿÿÿÿÿÿÿÿÿnvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2f©sØ{ïB’ãBÐ{ï™AL¢BÌkì!c’àBŠcªÐU@g½—Ú{˽÷Þ{F¹gÔ{i½÷Þ{Ƚ‡Ö{ʽ÷Þ{ï½÷Þ{ï½÷Þ{%±g’{H½÷Þ{ã°GŽ{¹÷Þ{e½W’{(µ÷Þ{í½·Ú{î½÷Þ{©G{¹÷Þ{Á¨'ŠzĬ÷Þ{µ7 {å°÷Þ{ª½—^{ê½÷Þ{†½‡˜{н÷Þ{$µW’{(½÷Þ{†½WÒ{h½÷Þ{ê½—Þ{ì½÷Þ{ 4d ¢(Š¢( ² È@QÅqÉ‘ɱ  Y HФXŽåXŽ%Y’%Y’%I’¥y¦ëº®ëº®ëº.² HPQÅp Yd HŠ¥hЧˆŠ©¨Ž „†¬€\CTLÇ•\Ë5]Õu]×u]UUUUUUUUUUUU Y@Ði†©ˆ0#™BCVÈ0Å€ÐU@€IN’(9)¥”à YL’J9)¥”G1yT“ŒA)¥”RJ)¥”RJ)¥” YŽ’J9)¥”Ä(YŒ’*5)¥”G9yR“Œ=)¥”RJ)¥”RJ)¥”)yÒ’®A)¥”ä(iÐ’M=)¥”(E‰’“íI)¥”RJ)¥”RJ)¥”Jù ”RJ)¥”«=¹Ö“RJ)¥”1J Ÿ”RJ)¥”RJ)¥”RJ)¥Œ 4dgr(:‰Îg(gš‚¤BiB÷&9Jž“ÜJËÍé&œsº9åœOÎ9' Y@!…RH!…RH!…bˆ!‡œr *¨ ’J*ª¨¢Ê*Ë,³Ì2Ë,³Ì2Ë,³Î:ꨳB()´ÐZ±Æ[íÍI[s”ÒI)¥”RJéœsÎ BCV BdQF!…bÊ)§œ‚J*©€ÐU €Q2ÓQÑÑÑñÏñ$Q-Ï5Ó3EÓ4]UveY—mÙvuY·uÙ·}[·mÛ×Ýøã8Žã8Žã8Žã8Žã8† 4d „BH!…RH)¦s:!” YPGqÉ‘$I²$ËÒ,MÓ4MóDOôLOõ\QmÑö\ÏmÏõTOõTQ5UÓ5]Õu]×U]UVe×¶mÛ¶mÛ¶mÛ¶mÛ¶m[BCV:’#)’")’ã8’#I@hÈ*@@Š¢(ŽãHŽ%Y’&‰’i©–«Éžîé¢.ê@hÈ*@†hˆ†èˆ–¨‰¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢èyžçyžçyž„†¬$t$Gr,ÅR$ER,Çr€ÐU€ €Ã1$Er,˲4Mó<ÏóDOEQ4MÕTÐU €E±Ë‘$Íñ$Ñ%Q-Q5QEQEQEQEQEQEQEQEQEQEQEQEQE Y !„¾÷–bj)÷Ð8Ä ÷Z)­÷Ô@bœ÷VIb˜÷VQBŒõža„BCVQ€1È1ÄrÎQê$EÎ9*¥Æ9G©£ÔQJ±¦X3J%¦k㜣ÔQê(¥ZK«¥Tcª±€€ ¡Ð@b R )…”RÎ)æRÊ1åRJ9¦œSÎ9„Ê1ƒ)¥œSÎ)ç„ÌA圃ÐA' À ÀB(4dE'àpÏ“4M%MEÏ]×Mו4Í45QTUÍMÕTM[MU–%M3MMôTSEUMSvMS•mÏ4mÙTU]UÕ–e[vW–…Û3MÛUÕÖMÕµ}W–ma–m[˜4Í45QTUMUÕTUÝ6UU·5Qt]QUeYTUYV]W·U×Õ}M]ÕSMÙUÕ•UWõmÕ•ußt]aW]Ù×U×õ}]×}_¶u¨ªºnºª¯«®« ³.ûº¬ÛŒIÓLSEWÕDQUMUµmSUm]EWUUv=SU]Õu}]U]ÙÖDÑuEU•eQUeYu]_w]W×EUvÕu…ßT]]—mÝfÙÖuÑuu[•]ßW]W×eÝÆÖmßøLS×M×õmSU}_÷}ã—u[8FUõuÕ•…a•e_×}ß8n_7†QU}ß”]ßW]×÷mßÚºnü®mcë>¶®# ?ºo UÛ6ººÌ˜uÛ¨û:c7†Ægšºnºª®›ª«ë²­ mÝŠªªëªë »éʾ.ëºqì¾p£«ú¾*˾¯Ê²±Ûºnô}¡ðʲq̶-³­Ãpß7~®.ÇlëÆ1û¶pìÂÏ p0¡ ²"ˆ`”‚P1¡R B(¡¥Jjc2ƤTŒA)¥´BI­b BƘ„Œ1)¡„–J)­…RZ+¥ÄJi­µVkk-ÖPJk¡”ÖJ)-¦Öjl­ÕZ1&!sLJƘ”RJk¥”Ö2ç¤tÎIÉœ“RJJ±”ÔbŘ”Ì1)sRJ*1•RZ+¥ÄVJi±”[K±ÕÖb­¡”C)­•’Zl-ÕÖZ¬µb BƘ”Œ9)¥”ÖJ)­UŒI霓’1'¥”ÒZ))ÅÌ9)™sR:礔RZ+©ÄJ‰­¤[(¥Å[­-µVK)-–’Z,¥´Öb«µµT[(¡µRJŒ¡”[Œ¹¶k ¥ÄXJi±”[l±æc®¡”ØJ)±•RZl±Õ[«µµ–kK­Ö[­µÕÖk­½§ÖjM-åØZ«9ÖÖc­¹÷PJk¡”ØB)1¶Öjm1ÖJ‰­¤[)¥Å[­­ÅšC)1–RZ,¥ÄØb¬9ÆVkj­Ö[®)µšk­½×Vco­ÕÜZ¬¹µTk­µ÷Z[o 8˜P Y DÆ(Å„¦œƒÐ£˜s*¦œƒPJ¥˜sJ霃PJJsJI)„PJJ­…PJI©µ lДX Ð•@*`ŒRÎA))ÖF!ç ”’R­ RÎA(%¥Z3ç ”’Rk9gÎA(%¥Öjî ”’Rk±õÞA(%¥ÖZ뽤’Rk1Æ|I)¥ÖZ‹1•Zk1ÆZkª¥Öb¬µÖ$l­=÷ÞƒNÙœsν!œ2<Á¨À†ÕNŠÆ Y dÆ dRÈ „RH)„”RL(…†¬¢c „B!„BH „B!„B!„B!„B!„B!tÎ9çœsÎ9çœsÎ9þþ6hJ,PhÈJ 0F!Æ “’R‹ SŒA(%¥klcB)­Åc圄”Z‹±Ö\+ç ¤ÔZ­5çÜAH%¶ZkÍ=çBJ­ÕškÎ5ˆRb«5×tî9¤Ôb­9瞃ªµZsí½ç|O-Öœsν჋1לsî½!d«5çœ{:ájí9øàƒBkîA„ðÁÀÝà‘`ã +Ig…£Á…†¬B„”bÌ9ç „B¤cŒ9ç„Bˆ”bŒ9眃BcŒ9ç „B(¡bŒ1眃B!dÎ9ç„B¥”Ì9眃B¥”Ò9!„B(¥”R:ç „B¥”RJ!„B¡”RJ !„B!”RJ)!„B(¡”RJ)%„B¥”RJ)¥„B(¥”RJ)¥”B)¥”RJ)¥”B)¡„RJ)¥”RB %”RJ)¥”RJFÐIF•EØhÂ… Ð•F5ÖÖZ+ƒRpˆB r­cÌið3ˆqÌCHiécÈ@i¹öRAB ̃„ÏAÐ m‚™! ÁáA%@DL‰ ¹Paq‘vq]¸ ‹»„„ ±8€pp O¼á 78A§¨ÔAÀÀqDD4‡‘¡±ÁÑáñ4ðpˆÍadhlptx|€„€OggSN ,–v[x¨&'&'1/չǺ¾¼É´Á´ÃÂÁ»Ç¹½¸»ªÌHT`@›@´ZÖAàÜÚ¼¦Ys|+âk„LÓÿgö:6ÜHd"þˆ@{ ÿÿß½zã7oùͯÖíÁ+)„a +á~{£Ö;¨³'WîgÂn=í··Y¦„ùzn£?>¿ž+Øëa5Úv¡HzûmµGœõ/-CYZÊÚwd€Ý]cvZ êtÕ±&óýá<ÓC…ñLÏß½Ù¬w}êïçÖù|Üš£Í"ÂM\=­5ŠñȮ՛‹ÁÂ!á5ͳÐ^¹¬çùW—ßFH›Ž•ü¨Psv­ÿvü‹À¸X–îåôôäiwwÑ/cÁÜÈ/–ç`+Ùá©8c|©E®Ón‘»¿\-}ß§§}//nhRKï|P ~|[C?ÓŠƒW{9¥7QðÊíÚ—5Ѳœ¬Ièór0çÄÁ"z)ŒtJ1œÙ2åEëA޳YØ¡§‚«” sY= ëH-„$½õEÍ–ÏÉXëèýþƧªMç6J|¤þÚ¡@6(õ¯€#„^0J ®Ø6AqXx{²h”€~íÓŠÏêÁ4~Dó*ÓþŸgZf¯ìyôkgËÎIMEâbÜݺmÕ+ñtMÍiMk!z"q ý, ŠÄ¼ç´6X)ìN x"ÑÙeß‹Wx1pìU¶ë+6„̘ec[¯O©ÊÚÁÌRvä|öÄV«lk•Êf[dàÎlaŽCÕ{䶦ëµéÐlÀÈ–ðRkiˆO­«|lcÈCŒš'À\x˜N2d߀~gP]-> ]Ò@Oý™˜?±ð¾ïß-èŽSÓwæ,¸€ÈöXÀ#‰Zª³ »î füÝŽ4†Õ_˜ˆ¤ÐœçeO&ïØíêª/åA'cQHЫ%°èkJ¢8'õ7…ZúC“Y‡$©Õ]/Ð|ß* Š*2H Ë‚I`‚{Öß5º£u} &õ±PêÛ$A(@”†qïSQ êH ˜/àXE§dÁ¨‚Rfà(¦r—F|)¾ÇøY}  ÝòHÍûQLg• ÎûyÞÏœ³I`$Zí½GõâÍœÓlr³%¾÷û’x´3¸j÷»^~×ðbhµg®%”쾦©å¤kHô; N þ!ƒ+¯Š:ý»¨‚ ;¾îkàdC«)=IÁ0ççÆKZ’ä™>µþ|± y(ôð ¥Hó+êîà ¨Eº;«`A¥š12òV+Zå4f©k‚îüùʈ'ðB¦pàÕn?­‹Oz( @ 'qÒ?*ªzÙ{¢üh¥\Ü*Ñ‹z:Ò®fýPÐG Ý“ŽÃ^ªI·UvZ'ÁÑà¸Çn»¤ã¤§Ò˜õœ±CϪ»?ŒwÑ¥±u‰ðAô~'L¹eç°ØRÑõ¾k ‘Dah¯¢÷Œð&˜A²ba¸QHŒ»w0NÕòÝa8¬ñDmcÂK¤‰‚g—rPð*FY¹®Œ8¥‚r]$,¥ð™bŒ"<&-û– Àþ uÇÎêØMaY¨aEޱDÝ‹Mž5ûˆñ͹+öv͘é}ýTý©4îv¹Çƒ½Ê#¾uÁyD}  ¾"âxxFÀâ-^›#ôoo[0äѺÙɸ„RíÛÚ|õê;. !x#®ÒÈ«­Ã¼Äûß+kQA(–CÙ=«˜•[ŸË[_!”Àp™‘þ˜BA@Ò:¯ta)D¥½Ò~j¡±áä¹Wîáyþ*=Ê)ÓÇ à»ÅÎ3¿ž»¦–;ws×fÀÎ æÌÄ.zá8ŠÒô7I¾g²üï™FIÒõ<ÛjCu_ÛAè”xlnBiô¢ZT©^ñ‡³Â<òt»â[Ä08™»MËžUž*"8vDZÏM5«ï §)­4Èùº¶²à¥»Ò ^oI ‚(©&¥"P”®Úpædˆ˜ódF–íw’ºê;ð¯ |:±‡Þd¯ßU¡ä‘,P4?W@”ƒP_€Þ=ž{ýlC›o!ˆhiÃÓïQç:`Œ=}?‡N@ÖØ¶ XF"Òù}¼ŽŽ%[´j±f$G%Hìå1i1 ¥ªÛxüz¬xS£‘~ ÔEá·GŒ2Kï]hþ—ˆ„½ñš£Ó¦-6bÇ g¢N›i`½êÌlaoޝ érù)Z•G{M¹yªW]øV¤Ë$^I S_ih0@í*ã°ôfXåpÝ ‡ÚK v—Š¡2B¿D ªg¶©ž Î<ˆ©yõàþ ½ÎD½xÏ-Çô sŽÔ4σDgwíΓ`u§ü#ŸfôeÙå=zOn[´Ü€[ó8ЦH²±‹Nw„åš­+·õ»°(KÕ£µ¦“ʵ~n(ϸ¿ÕáEÐÒ`l±œÀCž›ùg›èÄßg{_ø- \B¯³/Z¸¼…5Ÿt“s6†Îx¶—6Ùn ‡Tãgs ³’ó“¬â˜Ê–ˈÊë$¨œgÐéçvƒc9§ÚZ1ÝnÇ èu^ ½Ä?-‚jï…©r³ÑË šÝl’¨ôSõùk¯ìßø–O²ôþ§uŽ”AyJ^Öa^é;u8ÓGÙ8±³¼v¡má]‰gÕ`¾äCÂŽK’]D–¼»ÖÜÄ[®Œ—ú0†ÞRcÃßåi¹ýÖeŸ/ßøqµ]bF\çf6ÔÅÕ1Óñý¢dӌǰy¢b±OŠ¢5ÈÙo/ÔW£|v*7‹k£—rÃ¥ÿ›°½þÝBì³ ;½ç9© š]8ÝÅçõË–ÑÖØsØ3 8¨`k@wwIIe I"z×å ­­¾÷Q-ÙÊ·Úó_Ó›€ß´@JD7ò¨Ð× £Ï¸~ôΤi=•zã€ÄE¢¸ צ÷CkcôdiDSòÇ`áâ‹èÎ@V‰hIMrÖ•‡Šž´Ëkúqf^iEÓZ4ohèÑÔ´`„F#À)‡+M˜igÖ>Ûªä˼¯ZX°Îù‚K…õËYHFÔ–zD„‰1†•Y¸‡Âþ=†’œúÀNl‹Þ5ž7/Ç®deÐ] 9ªn¶V\Ã\’—?³n¨ÒP]€_÷«¿ç÷Í‘Ö^*æZÐI¡ÄO®uù•+ ¨ä™o/mºMÖaūYUU묌Ò1´E,¬—ä¯öùÈÌ„ÿ°kº¨y=._©1ô™MŸrfÙ»ƒ³Ñy¦à­…‘«²[Äåíº*˜[À`ñPÿ "$Dì@0¹/Š(0:(³Y]hÚ“~ }¨ ¼·ÏKga‚Z³ ¨[wì€yD¡¦;,¹ýèT­3y‹Rÿ#ÕæX7е!âhµ*Œ´ŽÃZÕ¨? œÃŒÌöæÖ5-w§dz \·Ký`eƒÃ6úgyý|Ûý† !’ô,¿§ MgÓb „žðŒ©¢ç¬% (¨¸Âxw‚y9x>©æ!k¨Ÿ±Å7ðèÅ["¥6j(p^+^ª¥ÇèÓèGöiQˆpŽn;Aà/ß/÷™,â~ ý:¹‡@$yº¿y­z{-ëï°¬îpH5Ñ´™˜ï/.“¼Š=bU˜Òe­9€¸àÝæâAʧ.” ²k¬r·¾À‘åò­[[Ü@sEµÌ]Öâ[úba¯Ò§Ž{ƒ‚й©äÏ÷*Ž Kn䳦 ° „+trë ± Ø †v¡@.Kèj2Æ¢Ê2´:ä – ±4BËB¨È–y“F¡•¡ž¸žÏ­$‚Ù{[ ½Ï) Ìßkza$¬®ß¨ P»vèH5ëé˃‘˜@%- ÛNZ¾oÉž½AÜ–`Eýúëõ÷œ“sÑÄ“éš ¯[ÅU^A×PÝÊNp”Le&±çÄÈ®lˆÊo÷ò4åJK:ˆßŸŽBÁO½×µXí±b±õ²ÆC”j$+^à¹å"?`Ξ›G}!:‚_‰±]ówiç7¨Ùê^ƒw÷ƒl¯žÈ ÙOJ\wCÀf—>'ýu®`ÃwnŒ=:cO}ÿ9Ýc]º‘ªç2<îþäjÏ?Ûwåsîe­æÚ’÷Ü—l>~djxüm$< ¡¶öwñ9õ¦ÏÄ­•®[º–šT°0«ëý‡AG+ìø;þΨ©ùìy·ÿ9½‡ö!Åóc¼ÚóÈšìM½ùŽÑK`úÌJ×γóì8”{¼‡®sV~àРðxnew_rdpyg/tests/data/sounds/one_bump4.ogg0000644000175100017510000001115407713714567020761 0ustar renerene00000000000000OggSD•h΋b vorbisD¬€8¸OggSD•h˜6úk-ÿÿÿÿÿÿÿÿÿÿÿÿnvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2f©sØ{ïB’ãBÐ{ï™AL¢BÌkì!c’àBŠcªÐU@g½—Ú{˽÷Þ{F¹gÔ{i½÷Þ{Ƚ‡Ö{ʽ÷Þ{ï½÷Þ{ï½÷Þ{%±g’{H½÷Þ{ã°GŽ{¹÷Þ{e½W’{(µ÷Þ{í½·Ú{î½÷Þ{©G{¹÷Þ{Á¨'ŠzĬ÷Þ{µ7 {å°÷Þ{ª½—^{ê½÷Þ{†½‡˜{н÷Þ{$µW’{(½÷Þ{†½WÒ{h½÷Þ{ê½—Þ{ì½÷Þ{ 4d ¢(Š¢( ² È@QÅqÉ‘ɱ  Y HФXŽåXŽ%Y’%Y’%I’¥y¦ëº®ëº®ëº.² HPQÅp Yd HŠ¥hЧˆŠ©¨Ž „†¬€\CTLÇ•\Ë5]Õu]×u]UUUUUUUUUUUU Y@Ði†©ˆ0#™BCVÈ0Å€ÐU@€IN’(9)¥”à YL’J9)¥”G1yT“ŒA)¥”RJ)¥”RJ)¥” YŽ’J9)¥”Ä(YŒ’*5)¥”G9yR“Œ=)¥”RJ)¥”RJ)¥”)yÒ’®A)¥”ä(iÐ’M=)¥”(E‰’“íI)¥”RJ)¥”RJ)¥”Jù ”RJ)¥”«=¹Ö“RJ)¥”1J Ÿ”RJ)¥”RJ)¥”RJ)¥Œ 4dgr(:‰Îg(gš‚¤BiB÷&9Jž“ÜJËÍé&œsº9åœOÎ9' Y@!…RH!…RH!…bˆ!‡œr *¨ ’J*ª¨¢Ê*Ë,³Ì2Ë,³Ì2Ë,³Î:ꨳB()´ÐZ±Æ[íÍI[s”ÒI)¥”RJéœsÎ BCV BdQF!…bÊ)§œ‚J*©€ÐU €Q2ÓQÑÑÑñÏñ$Q-Ï5Ó3EÓ4]UveY—mÙvuY·uÙ·}[·mÛ×Ýøã8Žã8Žã8Žã8Žã8† 4d „BH!…RH)¦s:!” YPGqÉ‘$I²$ËÒ,MÓ4MóDOôLOõ\QmÑö\ÏmÏõTOõTQ5UÓ5]Õu]×U]UVe×¶mÛ¶mÛ¶mÛ¶mÛ¶m[BCV:’#)’")’ã8’#I@hÈ*@@Š¢(ŽãHŽ%Y’&‰’i©–«Éžîé¢.ê@hÈ*@†hˆ†èˆ–¨‰¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢(Š¢èyžçyžçyž„†¬$t$Gr,ÅR$ER,Çr€ÐU€ €Ã1$Er,˲4Mó<ÏóDOEQ4MÕTÐU €E±Ë‘$Íñ$Ñ%Q-Q5QEQEQEQEQEQEQEQEQEQEQEQEQE Y !„¾÷–bj)÷Ð8Ä ÷Z)­÷Ô@bœ÷VIb˜÷VQBŒõža„BCVQ€1È1ÄrÎQê$EÎ9*¥Æ9G©£ÔQJ±¦X3J%¦k㜣ÔQê(¥ZK«¥Tcª±€€ ¡Ð@b R )…”RÎ)æRÊ1åRJ9¦œSÎ9„Ê1ƒ)¥œSÎ)ç„ÌA圃ÐA' À ÀB(4dE'àpÏ“4M%MEÏ]×Mו4Í45QTUÍMÕTM[MU–%M3MMôTSEUMSvMS•mÏ4mÙTU]UÕ–e[vW–…Û3MÛUÕÖMÕµ}W–ma–m[˜4Í45QTUMUÕTUÝ6UU·5Qt]QUeYTUYV]W·U×Õ}M]ÕSMÙUÕ•UWõmÕ•ußt]aW]Ù×U×õ}]×}_¶u¨ªºnºª¯«®« ³.ûº¬ÛŒIÓLSEWÕDQUMUµmSUm]EWUUv=SU]Õu}]U]ÙÖDÑuEU•eQUeYu]_w]W×EUvÕu…ßT]]—mÝfÙÖuÑuu[•]ßW]W×eÝÆÖmßøLS×M×õmSU}_÷}ã—u[8FUõuÕ•…a•e_×}ß8n_7†QU}ß”]ßW]×÷mßÚºnü®mcë>¶®# ?ºo UÛ6ººÌ˜uÛ¨û:c7†Ægšºnºª®›ª«ë²­ mÝŠªªëªë »éʾ.ëºqì¾p£«ú¾*˾¯Ê²±Ûºnô}¡ðʲq̶-³­Ãpß7~®.ÇlëÆ1û¶pìÂÏ p0¡ ²"ˆ`”‚P1¡R B(¡¥Jjc2ƤTŒA)¥´BI­b BƘ„Œ1)¡„–J)­…RZ+¥ÄJi­µVkk-ÖPJk¡”ÖJ)-¦Öjl­ÕZ1&!sLJƘ”RJk¥”Ö2ç¤tÎIÉœ“RJJ±”ÔbŘ”Ì1)sRJ*1•RZ+¥ÄVJi±”[K±ÕÖb­¡”C)­•’Zl-ÕÖZ¬µb BƘ”Œ9)¥”ÖJ)­UŒI霓’1'¥”ÒZ))ÅÌ9)™sR:礔RZ+©ÄJ‰­¤[(¥Å[­-µVK)-–’Z,¥´Öb«µµT[(¡µRJŒ¡”[Œ¹¶k ¥ÄXJi±”[l±æc®¡”ØJ)±•RZl±Õ[«µµ–kK­Ö[­µÕÖk­½§ÖjM-åØZ«9ÖÖc­¹÷PJk¡”ØB)1¶Öjm1ÖJ‰­¤[)¥Å[­­ÅšC)1–RZ,¥ÄØb¬9ÆVkj­Ö[®)µšk­½×Vco­ÕÜZ¬¹µTk­µ÷Z[o 8˜P Y DÆ(Å„¦œƒÐ£˜s*¦œƒPJ¥˜sJ霃PJJsJI)„PJJ­…PJI©µ lДX Ð•@*`ŒRÎA))ÖF!ç ”’R­ RÎA(%¥Z3ç ”’Rk9gÎA(%¥Öjî ”’Rk±õÞA(%¥ÖZ뽤’Rk1Æ|I)¥ÖZ‹1•Zk1ÆZkª¥Öb¬µÖ$l­=÷ÞƒNÙœsν!œ2<Á¨À†ÕNŠÆ Y dÆ dRÈ „RH)„”RL(…†¬¢c „B!„BH „B!„B!„B!„B!„B!tÎ9çœsÎ9çœsÎ9þþ6hJ,PhÈJ 0F!Æ “’R‹ SŒA(%¥klcB)­Åc圄”Z‹±Ö\+ç ¤ÔZ­5çÜAH%¶ZkÍ=çBJ­ÕškÎ5ˆRb«5×tî9¤Ôb­9瞃ªµZsí½ç|O-Öœsν჋1לsî½!d«5çœ{:ájí9øàƒBkîA„ðÁÀÝà‘`ã +Ig…£Á…†¬B„”bÌ9ç „B¤cŒ9ç„Bˆ”bŒ9眃BcŒ9ç „B(¡bŒ1眃B!dÎ9ç„B¥”Ì9眃B¥”Ò9!„B(¥”R:ç „B¥”RJ!„B¡”RJ !„B!”RJ)!„B(¡”RJ)%„B¥”RJ)¥„B(¥”RJ)¥”B)¥”RJ)¥”B)¡„RJ)¥”RB %”RJ)¥”RJFÐIF•EØhÂ… Ð•F5ÖÖZ+ƒRpˆB r­cÌið3ˆqÌCHiécÈ@i¹öRAB ̃„ÏAÐ m‚™! ÁáA%@DL‰ ¹Paq‘vq]¸ ‹»„„ ±8€pp O¼á 78A§¨ÔAÀÀqDD4‡‘¡±ÁÑáñ4ðpˆÍadhlptx|€„€OggSD•hv Äà %&)./.ŵ³»²º¬Nõ`Y[äéh8÷”×Ô,Q|ô5½…¾7ä§7¶A©0¬Ì˜ˆÐž¬%ˆ@çß!x;¡Ð:K=W*yÌöÎ3lœ:¬LªÃú[3 TbÂê ë„2×ÜãÇãÆÐÏãÁýT'‰W6ÌDð·´ÎØ`ÝnÕh›€îm– µüsªyßË„o™ÿ3Åþ¶ž1rÿ—XφŠkÍ,Uæ$tSs"˜@M¯Ñ=ëöùúðß!‘íï{¶ñ05ë…¥|ƒÚ>Ÿª Þ$[ïr“öUß;ˆ²h2CŽçgÛ²¬n©:òò5~”]DÜ æƒu`€ØWzøÄ8×ÓÌäq™`÷¢O´t7¸ÄZª© &ÁÿVÉÒšÕàÞ‹ïO]XÐsù¥óèNùÚ¾[ɶŠ?ìY'™yñ<ÛÅhšñãýŠX<òe‘ó+‰h"féÔÕàc¹TÀT+ˆº¡Š. )Íùm›™T½lK %ì„ôjÇõ€7ü7,ñ ó½ŒdÜ^ÚChXç¼pA*…:½ÔV=`qÙ# hã’j€D†¥Wâ°´îX÷Ø ,t^¥p,fB(J\q^fÈìÈéñE.€•ï˜ïªÞ¶Yýø­5é5mÉ—,Y³J™z_\ig©0·«MÐAÎöÄLG Uö¡ÿ"aQÐS^ù´">ºàȬOFlÅœüS2ó|î¥/*œ!#\UÅ>¢ö‡Ч†}ù‚òÃG!ØUˉª:h°/aÒ¿Ö?¨ <êz¯dµ™Êæ (g3/Q›UUÌ ÇØJ^ø”f.NB¬Ìó»P ëfô€¸3¡@ §{¬¶óÿ[5Imë¿$i;ß zE‘X_®Ø¦uxªûôYóÅ}ŸîìIÕ+Ê©Àˆ+ [ ^àcÕ‚g“–AáJ7Á‡µIÜO‘6²ÐDüì.ý 8v= 4¾óú$¿ÕÈ÷T€¼¨#å45€›ÔŠ;¸ËÖâ·®¦ºB9Óʆ– ·íÎ˜Ž½¾ÙÔ …ÃI¡ÀPE½jÁeÖTê¬DGHø8LÆcäâx.( Ÿ¢TS¸IªºzLРû“Î:|„»ÝIwüK#Ž5€ ’G-<6Ðvg?k*÷@×P#Wl/#€ŠôTC%ÌKQ¯KªpA”³ê=Z)4€ŠA«¦ò·Š×·q÷¤xݳKt¯ƒÉðbÀîR´”ùœ^™ t—f%Dë°_NbÚm4£Ï퓘+»ugXÙ0‰(Ÿý?[PˆáÕ¦9p;!„+Åw•6Óà:E›¼v{{Ó0›!”*z;PõK."Û`9ôÂA3x_‘œL}Ö×$C9Ö/‚ÄZB øQjœ­v£—!«e`y3µæ” ûÕ ˆ‚ôw )/†é†½#Q ('-ñ(áì($)ÐJ üœs81ƆáÄØŒVífV&¥rc¨º¸UÃ-ž2š\ü¸ new_rdpyg/tests/data/chimp.bmp0000644000175100017510000001257207504130274016646 0ustar renerene00000000000000BMz2(6OH  ÿÿ~}óNPO¢¥£),*ÐÓÑxzyþçë麽»cfdŽ‘<>=›ñ¿Áßfd©„‡…Y[Z¯²°ô÷õÜßÝÅÈÆ™œšnqo465!#!EHF`\ù ÍÑ谳ʳ·ÍÿÕÔᦥÉ×Ù÷xvˆ»»È™™¼ª­«’¨A@úIGfÀÄÚ$'D³³¿~ƒƒ”—•BC[/10SVThkiãæäúýû^a_ÆÆÒ–•¡Š‹ACAµ¸¶ØÛÙÀÃÁÌÏÍàßì<@?ñõóvywLOM àãûtuæéç¡ ­êîë')(ÊËê@>N}€~¼¿½•˜–·º¸’ûÿüÒÕÓy|z`caORP¤§¥jmk586‹ŽŒÎÑÏ"$#¸¸ÄÇÊÈ«®¬€ƒUWV=@>…ˆ†Z][±´²uxvÞáß&('egf åèæÂÅÃðóñ¨«©»¾¼›žœGIH031_b`ËÊ×¹¼Óöù÷ÆÉÇ BECKNL­°®éìêÝàÞilj""""""""""""""""""’’Ë’x’0Y""""""""""""""""""""""""""""""""""""""""""""šì::s:˜ºˆýl""""""""""""""""""""""""""""""""""""""""""™«Ëõ:õ::::l""""""""""""""""""""""""""""""""""""""""""š:x˜ì|™{õŸ:x"""""""""""""""""""""""""""""""""""""A=’Ú˜:š:˜{{õ:h""""""""""""""""ý""""""""""""""""""""R5v·—::z:::{::š""""""""""’bwš’"""""""""""""""""""â–yDz :::ì:™›³˜†"","hŸbˆwš:|)í"""""""""""""""""""5y–+©©ˆ::õÄx’wBÖb’Vxî›’®’:xx@@:w""""""""""""""""""©o+©©©–F:˜˜ÚÌû:üo9¿² Ç@µõ왟:˜B3¸"""""""""""""""æv+©©©©©©µ:@Žwššy©ƒZ’=u::s8æB’’"""""""""""""""b©©©©©©éŒ›z:::‚Ìa:j–vD"""æšd:>™:ÄA""""""""""""""Yio©©©©©y Ð:::Ýš:šPx"""""q˜™{ìêšL""""""""""""""c©©©©©©u0–88šš„:õ¿,"""""™$':::BxÚ›A""""""""""""+©©©©©©"™…˜¯u›|ì:AÛK"""""'š’{šæV š°u"""""""""""œ©©©©©© ""’ƒýš3::¦J¥#""""Ä{ºxvÌ’€""""""""""""™Û©©©©©©©©ê""¿bjàwxìžt"""":::YhàÇ—w""""""""""""d©©©©©©à""Ý镜yÊðOË""""ݘì{::ê¼;’""""""""""""b©©©©©©©]K""xéw|x·ð¤£©‘""""a™ìY:{xŠÞë""""""""""""©©©©©©©Ì""Ä胎MÚw„˜Á©©ƒ™""""’ûz{ÄAw ›""""""""""""¤©©©©©©©©Ü""'¤¤™šš w©©©ë"""š)3:{{x b """""""""""†Ø©©©©©©©x""¥–wÊŠ3lÚm©©©©–ð""""xs˜::æ™M"""""""""""wé©©©©©©©©N"%\O…mœ°w–©©©©©©Œ"""ÚÒBüµÄ^ŸŠ""""""""""~©©©©©©©©˜N¥…—àðyœÀ¹©©©©©9""""u›xšxÝ€C""""""""Å£©©©©©©©©b—bˆ °²° ©©©©©+ê"""®VÚVö3wb‡"""""""È ©©©©©©XT–è@M–ƒ©©©©©Œ""""’Ÿ’’së‚"""""""" –©©©©©©©©Û¹JŽ’ uœ•—– –©©©©©©K"""—ŠA‚ÚA š¡""""""=ƒ©©©©©©©à’lµm¼ò9ƒ’©©©¹’"""èðu’’ûèu""""""”©©©©©©©©•‚ÊvÎ’v”¿yèž©©©©©9ð5¼"""u w@ˆ]—¤x""""""E©©©©©©©–”]V^Û•²uÏ©©©©ƒ£”•"""ˆy°›š)¯^"""""œ©©©©©©¥Šu蕜ÇÁá©©©©©©–wÝŸ)‚"""›Ç Ö^’bê"""",©©©©©©–£’Úwm—uà·¿ ·©©©©©©¹5x½Ä’"""u©5 Ú^‘Z""""0©©©©© ÚwRààç–©©©©©©©žsì{u""Ж xVbb…bs"""©©©©éàu¬¼°°¤”—5Û©©©©©©çò:u""Lé¿ðµY„•Ü""""Þ©©©©©–žb3  ðI]èéàày©©©©©©Û–’™³""¶—ƒƒvÌÇ’""""b©©©©èÊu—M èw¿²u¹©©©©©©Jð lqw"""ý/y¯”–mÊuY"""8–©©©©]² ¼Ÿ;?àè5©©©©©©•Ymuæ"""x éðmè;^àŠÃ(™"""™ñ©©©y·R·•¹£ð £”J©©©©©–5ûx""""š”çàžub—B"""™–©©©©Áé5Çèð° £ÁÁ©©©©©5›""""Úð£u‘ x˜u=""Ú#+©©©©ðu jà–•wu5©©©©©–•@ """"""y¹uw™ì)¢""ÚŒ·©©©©©•¼DzDžç©©©©©©£¼€@]ý"""""m¹¼ lÖ ³—Ÿ""†¾i©©©–JO𣤣ð°á©©©©©œ°mÝ"""""æ°–Jv ›)™°š""’©©©©¿1–¤èð°u–¤£©©©©©©+y·0""""""#¥”+5¤ ’ý|u™#""ñ©©©–£5œà—ð̤9·+©©©©©©ÏŽ""""""""Ž©¥¯qÎüÄu?m"""©©©J—Çò¥òwwJ5²©©©©©©+&"""""""""\©è·Ÿüš’wvu""""+©Rc5锹ޛléð+©©©©©©©²ó""""""""G–£¹èšìíkê""""–©éÇ—’xunw©©©©©©©©ow™"""""">y²w„€ µZ""""""9£y5൵û]s©©©©©©©©©©è""""""ð–ž š˜Y u="""""æ•©£•–ÏÇÊb±ˆèè>–©©©©©©©©©©© """""祠bm? Ë""""""·ƒ©ƒJBu’vœ’i©©©©©©©©©©W""""h–3 M1 †""""""4+œ –vx’›ûð9©©©©©©©©©©©w"""˜£àµxxM]>]"""""""^©©•?œ yy5Û3 ÌY°±+©©©©©©©©©©Ç"""5¼ ’Ðv ±a""""""Å©¼¼ÊJ÷ð‘BŸy©©©©©©©©©©©©B""v©ð±us5¼ """""""'©–—°žà59à¹x@xµ¤¹©©©©©©©©©©É""°©Ju°——~é"""""""©©¹ðœ]œJ¤j ’¯¤+©––©©©©©©'¤©•wðù•""""""""²©Ûç¤ˆŽ )â ¿©–£ °5©©©©©©·¦©¼M è¤9-˜""""""""@–©œ•àÊŸÇuxM¤+©©ìì˜:Am©©©©©©©©»Ç…£–r""""""""""5œ–èî‘]Mb»˜:::ê˜:©©©©©©©©£¤èǹ'""""""""""< ·vm·ƒ™Ú@¬›²©¤õ«Š’Y:§©©©©©5y?œJ—ý"""""""""""¥Š—ƒ¼V °3©bß›Ÿw)ûšh¤©©©©©–ƒ–Ç—œ·"""""""""""")5 w?5w9𔕕wæ::ÄõYš:b©©©©Jàyà ç5§""""""""""""JŸwy¤^ƒ–ƒ ½::˜ì{{õ)Τ©©©J—à ·—ô"""""""""""""à¼Ú^s^³ë¿¹{˜Ä|Æz{:w^ ˆ–©©©ÛÇà^œœ•°‡"""""""""""""’–¤]) ý{:wÇé›::™õ:{::Ž]¬Ç©²y°]â5€vÝ""""""""""""""¿°°>›ü{:x•°1: AMx::›¼âÖ ç–©éž›?u‘ê"""""""""""""" u]œê::^–•’|™::ì:˜˜’sÞ¤ƒ5uÚ uÐ…"""""""""""""""ÄuvM˜õ  ?@|„™8˜™›))ìõ¤u·ym—â B""""""""""""""""Ÿð—?3)ËBuxx€š:®¬YõÚ:)êh–Ç•èR¥‡"""""""""""""""""è?Šx™¥°Çx¬Ú˜)›ˆìš|šì’ )w¿¹–©žw‚A""""""""""""""""""—] VR–uÚw°ðuîŸ5ƒ–ž5’@v’˜|:‚ƒðÕ<"""""""""""""""""""9·m¼àJè@’¤—b °‘Mü’›q˜ öœ–£“"""""""""""""""""""""›—·5›¥âxÚì:õšY:ì: 3@Ÿ¯b—B e¹ö"""""""""""""""""""""""¬à–•RbÚÚ„„dîÚëÎb5^Ì1°õx’""""""""""""""""""""""""""­s•à9—@Î’ ::’bÚ 9ž¤—?КÄ""""""""""""""""""""""""""""Uð° |xûŸ:˜ˆÝ™Vuॹ¥A""""""""""""""""""""""""""""""šð” |mb®B)wΘ‚ƒuˆ'Ä""""""""""""""""""""""""""""""""¬å’R u¤wèb¤b;y•º""""""""""""""""""""""""""""""""""""œ°mu^Ú¤Ø""""""""""""""""""""""""""""""""""""""™êè uvuUvub’uÕ"""""""""""""""""""""""""""""""""""""""""""#Äý8=3ˆŠ¨ý""""""""""""""""""""new_rdpyg/tests/data/fist.bmp0000644000175100017510000001043207300416501016476 0ustar renerene00000000000000BM6(*K*'3-*3.-82,54.98/950;92<?8>52B;5C=8E76I:5H<9K69R<:QA9EC;KH>MB=QI?PE=ZKAFD@OH@OD@TKBSACZEAYFDYAC]CD]EE]KDZNHZRFUPHWPGZTK]YMZ_QW[S]KFaFI`LKcKKhMNhSLcXNaQNhUPe[QeTRkZTk\XnSOrUTpXWqV[v[YsVZx\\{cVbeZdcZls_eb\si^sc^|^a}l`hpbkxci|inda}jb{tht{lttfxthqv}px‡v~c^€^b€\c„ccƒje‚eh‡mi†cgˆejŒlj‹qh€{o„rlŒupˆ{sgk‘lm’tn‘jqštq•{s“rs›zvœtv¢xv¡ux¤{y¢}z¨{~©Š{ƒ‘†€u”€z•ˆ~—„}œŠ›€w ‚|¤‚~©~€ª‹€†‚Š’…‹”‡’“‰‘Ÿ”¤—›¥˜ž„€£Œ‚¥ƒ‚¬‹„«‡ˆ­‰®‘…¥•‹¬›’¦„„²Š†³ƒˆ³‹ŠµŒŒº“¶š¶‘»™¾”“·›’·–’¼™’¼š¼¢•¡«¡¡—¼¡™¾±¦®¶¨¬¶ª°¸¬±½°´»±¸Á´¶Ãµ¸Åº¿‘À”‘Áš“ž˜Ä—–ȗșʠ—Å¢šÃ¢Ë¢ŸÐ› È¦¤Â¨ Ç¢ Ì«¢Í¬©É³§Ç°§Í°¬Ê¹±Ã¿¸Î¥£Óª¥Õ¬ªÕ§¦Ø¬§Ú¦©Ú¬«Û±­Û¸±Ò»¶Ö´°Þ¸°Þ¸¸Û­®à±¯à³²ã¹´äº¹ã·¶è»¹ëÄ¿ÍþäÀ½îÁ¿ðÍÃÅÍÅÈÓÉÌÉÄÛÍÌÞÒÌÒÑÆÛÚÖØàÛÚÆÅåÏÌäÊÉéÑÎâÚÙæÓÑíÚ×êÞÚéÆÄñÏÎóÓÔôÚ×òרõÜÜôáÞëàßöåàãëæçêåêíéìñîîëêòìëøðîöðïøôóôøööööøø÷ùüüüüüûÆpkfcV=. €úüüüüüüüüüüüüüûÆpkfcV=. €úüüüüüüüüüüüüüü܉lgdU<2!!  üüüüüüüüüüüüüüüí–ni]U:.!! Øüüüüüüüüüüüüüüüö´pidW;/  ÞüüüüüüüüüüüüüüüüÚˆidYF9,, òüüüüüüüüüüüüüüüüÚˆidYF9,, òüüüüüüüüüüüüüüüüã–jgdW;-- )øüüüüüüüüüüüüüüüüôšnid[>55 Hüüüüüüüüüüüüüüüüüü»†lidU::, NüüüüüüüüüüüüüüüüüüâondW<<- QüüüüüüüüüüüüüüüüüüâondW<<- Qüüüüüüüüüüüüüüüüüüö˜†ndU::- Rüüüüüüüüüüüüüüüüüüú¸miW<<- RüüüüüüüüüüüüüüüüüüüÙ‘ogY>>5  |üüüüüüüüüüüüüüüüüüüæ˜{i]KK:+  ~üüüüüüüüüüüüüüüüüüüæ˜{i]KK:+  ~üüüüüüüüüüüüüüüüüüüö¶{j]]E/  GùüüüüüüüüüüüüüüüüüüüÇ‘†nggW9+  ¡üüüüüüüüüüüüüüüüüüüíªŽzii]>0  (ðüüüüüüüüüüüüüüüüüüø¶‘nndW6" qüüüüüüüüüüüüüüüüüüø¶‘nndW6" qüüüüüüüüüüüüüüüüüüüÀ¨ŽzzgY:+  ×üüüüüüüüüüüüüüüüüüÊ¨Ž††xeF-  *òüüüüüüüüüüüüüüüüüà¨zjY9!  ~üüüüüüüüüüüüüüüüüå©ŽŽŽ†ygE5  ïüüüüüüüüüüüüüüüüå©ŽŽŽ†ygE5  ïüüüüüüüüüüüüüüüüô³¨ŽŽŽn]<0   ¦üüüüüüüüüüüüüüüü÷¿¬¨¨¨‘†jW<3"  ƒüüüüüüüüüüüüüüüüûž®®­©”†gX<4'"  ~üüüüüüüüüüüüüüüüüÏò²²­«‘n]KC6- |üüüüüüüüüüüüüüüüüÏò²²­«‘n]KC6- |üüüüüüüüüüüüüüüüüßÁ¾¾²¶®«ŽjZLC60   ~üüüüüüüüüüüüüüüüüáÃÃþ¾²­”yeZL740  œüüüüüüüüüüüüüüüüüäÄÁÁ¾¿¾­”†g]XC73&& ÛüüüüüüüüüüüüüüüüüêÌÁÁ¿Ä¿±™‰n`ZLC600" ?øüüüüüüüüüüüüüüüüüêÌÁÁ¿Ä¿±™‰n`ZLC600" ?øüüüüüüüüüüüüüüüüüìÍÄÄÄË¿±ªzj`ZLC33# }üüüüüüüüüüüüüüüüüüîÍËËËË¿±ª‘Žyh`XC33# (ÛùüüüüüüüüüüüüüüüîÍËËÄËÁ±ª”zjg]E66#  MÝüüüüüüüüüüüüüüìÐÍÍ˾±¬©”‡yj]K77#  @øüüüüüüüüüüüüüìÐÍÍ˾±¬©”‡yj]K77#  @øüüüüüüüüüüüüüëÑÐÐÍÄ¿²­ª”zj]K77- ÖüüüüüüüüüüüüüéÑÎÎ̾²®ª©”zx`K77- ‚üüüüüüüüüüüüüèÑÍÍËÅ¿²®©•”†x`K770 $ qüüüüüüüüüüüüüëÑÍÍËž±ª©”ŽneKCC3"BùüüüüüüüüüüüüëÑÍÍËž±ª©”ŽneKCC3"BùüüüüüüüüüüüüêÑÎÎÍÄ¿²±­ªªngY>>3 BùüüüüüüüüüüüüèÔÑÑÎÈ¿²­­ªª”†jdEE2  ¢üüüüüüüüüüüüüèÔÑÑÑÎþ±±®ª•ngXX:" qùüüüüüüüüüüüüüçÑÑÑÑÎľ±¶¶®ª”†nee>0 üüüüüüüüüüüüüüçÑÑÑÑÎľ±¶¶®ª”†nee>0 üüüüüüüüüüüüüûÕÑÏÏÑ̾«˜«¶±¬”ŽzjjW5 rüüüüüüüüüüüüüúÔÎÈÈÉÀ±˜‡‹ž±®ª”‡xx]9 IùüüüüüüüüüüüüõÑÈÀÀ·µ˜‡hhŠž±¯¨Žyy]9 Jüüüüüüüüüüüüü÷ÑÌÀÀ¶«–„eK^w°•nnY5"%¥üüüüüüüüüüüüü÷ÑÌÀÀ¶«–„eK^w°•nnY5"%¥üüüüüüüüüüüüü÷ÎÈÅÅÀºµ’vZDCs—’‡jjX5"%NøüüüüüüüüüüüüüüÓÅ¿¿ª‡eK<-4Ls‰yhhX6'&$?¤üüüüüüüüüüüüüüôÀªªŽvh`L+"^h„…ssXC71&(§üüüüüüüüüüüüüüí··°™‡‡j9 a„‡„„hXD71"Hðüüüüüüüüüüüüüí··°™‡‡j9 a„‡„„hXD71"Hðüüüüüüüüüüüüüüææª‡–¶z832wŽˆˆˆvbLCA'(£üüüüüüüüüüüüüüüüñ¹º¶dTse>‹¾³††ZtaLA4#œüüüüüüüüüüüüüüüüüúâªy“™nTб\\2Db^DA1#£üüüüüüüüüüüüüüüüüüüÚ™ª˜yYs˜nFF-quPLC1%$SóüüüüüüüüüüüüüüüüüüüÚ™ª˜yYs˜nFF-quPLC1%$SóüüüüüüüüüüüüüüüüüüüüÙ™–†dX‰g<<&$Øö¼bLD›Øùüüüüüüüüüüüüüüüüüüüüüüæ°‡jEv]00$?óüüñÛïüüüüüüüüüüüüüüüüüüüüüüüüüüø½Š`aK''$¢üüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüôÒŒ_OOŸùüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüôÒŒ_OOŸùüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüøøøüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüünew_rdpyg/tests/data/particle.png0000644000175100017510000000271010072755176017360 0ustar renerene00000000000000‰PNG  IHDR szzô pHYs  šœtIMEÔ)ø?Y®tEXtCommentCreated with The GIMPïd%n>IDATxÚuWÛnÛH =s•%9u÷%‚¾öÿ¿§(P´ARõ%²+i®û%K¹»V¤Ñ<<<¤€jŒA­Æh­QkXk¡”B)J)€Ö´ho­u±çúšö@­9g”RÊZ[k­PJÑZóƘ÷JA)ÅÏh£ßZ+RJì¤R 9gäœù^)9gÔZaedµVXkÙSc ;FˆÐ3rŽ¢§ÿéš Ñ’Ï(SdròÜÃi)¥°Òi‚˜VΙÜdö/&جµ øÉ°t‚"¦è@)Lb)%>—ÞaˆXt¨„Þk-;!£ÔÈh•RH)ÁƒyžŽK¤J)ÐZÃJHÉ9¢µfãô뽑–Þ£ÃcŒ0Æ ÆˆišÐ4 bŒ\Jéû yŠž #Zk8çÆÛ¶ed¼÷Ìp2î½g#Þ{„Ð4 RJˆ1.8cŒAÎù )š¦iyïa­…÷ëõ«Õ Æ8ç˜tµVLÓÇ‘+cµZ-òMé–¤´²^ÉCï=š¦aÃ«Õ MÓ ï{l6Nµ–!žç!”R˜p¥\.”R ÅŽöh­a%óå/xïÑ÷=¼÷Øl6躷··èºÎ98çRÂ4Mˆ1ât:!ƈ¦i0 N§¬µŒE.õÃJvSd×Lÿðánnn°Ýnqww‡ûû{(¥¸tcŒ8ŒÞ~¿Ç0 ÌŸœ3œsÐZ#ÆÈðžé€,AÊ¿µëõ?~Äýý=v»¶Û-ú¾GJ ÇãJ)8çðåË(¥˜°”’b)t\2b:È9·È¿µ···Øn·øüù3>}úçJ)x~~F­_¿~Åv»EJi!>Ò° ¸ÖúÎÙ ¯ÿ¼÷躛ÍmÛb·Ûáññ]×ñ¡8NøõëÎç3^__¹eÝKÝ`âËŽEÄH)qË”€¾ïѶ-ärÎa½^/xDé#4ÿ+8­5´,C©é²4sèº777\†rŠ­ ƈãB]k³”dk-š¦1!ÌóŒoß¾áååeÑlŽÇ#~üøóùŒiš8ÒÁÿ»þk„¤m[´m˃Ç0 èû1F<==áû÷ïǯ¯¯†ooo\rR[¤q¥,©EœsFs9Ž#†aàNGÿüù“º\.8xyyÁ8ŽÇóHLNLs˜‡£´ÄÊ¥ÀÅ›’𠑦µ»¾Âϲ¥§…„xu…„’ª´ÀºÐޝžœŸž —~|€soŽ~„ƒˆ‡‹Œ£¢’®ªh]_>4 " D:,EJ())61^JO}jw›XªYqx_FwKA~8Jv]‘¨©Æ¤Ç·¾­³±¨Å¼ÐÏÆØÛùŬ°¼´¨¨˜‘›¥µÉ«ª»ÐÈ“µ—’žª“‰•›€`€\y”`ˆŸ˜¤ŠkÂÀˆ“a]U¸`cnQ'QNBt†Ra†]G`¡âv£Üt\žÌ§k_dfÆo*•Š–0‹ËATë~,ITF¦ªKÛž$yÜ¥c¢†s/‰½{ª1q&B†!Wؽy¤—]ËuO\Á³ŠH•ä•tÂèD­€kw™§‹Êª‹µnµ°p‚ÅÄ­šÒ«žš”´«®Ÿ±Ï‚X¶Äx¦ÏªB’©º<›Úq`GÃpUpThtf vxm*i`€:™ƒ6MªH“gešOo^< q`60sO:¢q]TwmB]dn‹ulM¨’X£žvå{{oƒ“¨kgØŠzj¦u=b}_¦v¡z‚½­Z§“mSƒ¿|\áœ]p‘‹¥›i”½Ë‰G”ÑAz³ªvƒ¬Ò¥yÑ„`êƒbÂj•®W—¡8´Zs„G®€Š>h:Pk5r¥E-c“cb¶]WŸ‹ƒqv‰‰C¨wXHu¡–a{Í”wWÎd~›†W«¨‰?´/lžV4 ¥'z¹S«s0lµM‡‰½[`v²WS\¸o…Ž‚‚p\ºx“C]¾(d©Èqi{Ÿdi¨ÛËix¼‹…n–»ä¯·‚{°z;‘®S>°¸8kÝ…GŠ~¢”\s¨³`’~‚‹{”{‡”“a]~IS¨v ]¤vXšdr…¦JY¥l‚sm‡†ªb}›š¨+s®@‹˜g8u€IV£™°ypt¿Š,xÖt[œµ†Ä¦€g†ÉS‰wZ‡x¹e3v¦€p„3|Šjmx™ªRp—uozÇ„Xœi{¥]t©Žš|j=m†Oo¦pd|ŠSeLG_–„@Jsk•^x{‰>}³}A\˜´{ˆx­ư‚ôš´ÔŒš]ÔâWx”®À€™–Ìqƒ„v±‡ƒžµr†³žyfz‰q€§wÉ~O“³W=…©l{}s=z`%§lI@xvRPQ[wpeB~`Xw‚PRmq1M–‡krn‰Qpƒ—`V•t•g€¾‹s‹v÷‚s´êoŒ¨–^¢°¡„˜“ojšnkp}x~”oz‹wa‹d^…gTk¤wQ|j\Œwš’‰Š”v²‘|Лޅ¢‚ Ÿr„­¥²˜Œ±lu•ªž§Œ}¿‚a³–e~©€RŒ‹y^‘¦_Gh‚sm…`ssd„OR{ŒyKRr…E7‘yO}lJhZ`aHhau”‰gky;^°prs«‰{Xƒ|ZŒœ’‡rŒ‡ƒ¯i—Çn¡Œ–tª­yn—µpi¯«^‡¾·}Œ›«’Á•y‹ÀÓyž„–f¢‚—¬…Wf´‰Rp´Jn¼ƒ8{­™›•‘yly‡Q‰¤_‘xR‘‚\wxeqœoYyŒ;\…3„š3C€eM¤Z"tq?Gy‡GQm`kFpzOdyHNbl\c£Y¥uaž‹­…­|~ÖÂwu”߇h–™ŠÅÀ¨¹§šÆò‰†ë¾¶¹¥‘¾» ´u˜·µ¤zsœ¥j¤œz–Šž‘c‹v˜Bxž[Zz`Th‚l;PŠC\tH@?pIHaOY9”KJ‹Œ:Z‘{a‰`I„†{Blˆ…ŠdxvvPQ£^¶Œg™«rM¼²fpÒb¬œp¢§ ••’¥‘u¤˜e¥}{\§h—œ}y†ƒq¬šŠ¦–‘•¤Šˆ†¹^v‰Vi–B~@dŽ‚\b¦£n‚Œ†›fdœ†iz˜va”gu‰“N‚˜‡˜ez}qum¤•b}ˆ€Žtq€op€r_‡vko{_…sqVO…p‚db‰vLX‚rfŒud”{]‰n“{u|ŽŠ‚…‡„‹nx  nš©~}Á˜XÊ|k—À¤Žp£Œ{u› k§©~{˜·‚q¸Œwx‹„|ˆnfhކf{Šzwbu—fXf|iH‚ql«pGŠm`jƒxZŠ£bfyhœ“_€š}Kl»sQ~€•tMmž“orŽ{vb„‡‚š‰mtІs¤‚xŽœ——n®ˆrˆ€¤{£ ‰|€¯€k˜ ‚lynŒ~ež¯{[^‰Œ{h|R|Š`sd€hpbƒz~z~f•”oˆŒp„€|{Œ‹ˆ‚‰„|x‰”†zu“Œmx‡‡‡uxƒ‹ŠepŸ”sln~{wdt‚‚}…qsŒ{^]ˆnl~axvejnxzˆ}rˆ„ŠВމŒ“‹’‚‰„—•‡Š–š‹£¥§š˜x‰›”wm˜p‚«‡|~sy„nW†—uw—ldlƒ›ndtˆŠjhyyvƒtei^|tuuk†qekujp•†b†‰k…œ€~Žƒ‰}u†‹p’‡„uv{Žhy†Œ‚rv‹|uƒ„Š{t…’‡t“…ˆˆ—ˆwŠ˜€ƒ•„€““ƒ€…‡‹ˆ‘}‚‘wv„‚v„|}‘ˆstj’…tƒt|Šjq…rz€yp|sozvxxvy†}m}ƒŠ‹|†„†z€‡|†ƒu{zx‡}n‚‹uy„x€‘}„ƒ€…x‰z~w‹“oˆux“…ru……ƒ{tŽxŒeŒxƒ~zxwˆzi‡Š{x‚u’‚Œ|„||‡’ˆƒŽ‡ƒo‰‰u~ˆz‡‹|u}‹|q†ƒ…zp{‰|q}‹Žs{€ƒ‚y‚„…u€ˆwu‡{ƒy…„}‡Šw}†|‚Š{…{ƒŠˆƒ‚‰}‡€ƒ‚xr}si}‚yzmuw€}nw†xtx{€{t€y{„„nx‡€v…€|‡}zŒxxƒ‹€~‰‡€„Œ‡‚ŠŠ{‰Ž~}€„‹‡ƒ…„€„‚|y‰Š€y~|x‚|‚|‚‚€r‚‰}y|…p…Œ€w{ƒŒww†{ƒ€}ƒz|‡}t~Šu€ˆzy†~‰€…ƒ|€’xˆ‰„Š}y‚Œˆ‚v…‰‚}‡}€‚†|~ƒ‚|}€„‡zx‡y{„†u~€‚xy|xzƒzk€ˆzz€€‚}}‚}}ƒ…~~…€‚}‡€}|€‡}}„|ƒ€y‚…~{‚ƒ}~‚ƒ~}„…{„…ƒ‚€‡ƒ}…„}ƒ…‡€†ƒ…‡ˆ…€~†ƒy„‰„……ƒ‚€ƒ‚}~…y€‚y|‚~w}}x|ƒ|x|€{}‚|z}}|{}}~}~€‚€|~~}}‚|}~€ƒzw…zƒ~|‚‚ƒ}ˆ‚€‚„ƒ‚€€ƒ~„‚„ƒ‚‚…‚…‚ƒ„„‡‚~…€ƒ‚„‚‚‚†€~„ƒ|ƒ‚€‚‡€}ƒ€€‚ƒ~~~ƒ|€~€‚z€~{|||~~{||€~z}}}~}~}}~x€‡€y‚|‚}~ƒƒ€ƒ€‚€‚ƒ€„ƒ~€…ƒƒƒƒ~€ƒƒ‚‚„‚~„‚€‚‚€€‚„€€ƒ‚}}‚~~ƒ}€‚‚}~…€}}‚‚€€ƒ€€€~‚€}€€}}}€~€~€~€€~€€}€ƒ}~€€‚€€€~ƒ~€€€€‚€€€€€~€‚€~€€€€€€‚€€€€‚€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€LISTDINFOICRD 1994-01-07INAM Punch FaceISFTSound Forge 2.0new_rdpyg/tests/data/whiff.wav0000644000175100017510000001333207216105640016662 0ustar renerene00000000000000RIFFÒWAVEfmt ++factŸdataŸ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€~~€}}~~~}~}~~}}~}~}}}~}}}}}~~~}~}~~}~~}}}~~~}}}{{{}}}}}{}}}}}}}}}}}~~~}}}~~}}}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}}~~~~~~~~}}}}}}}~~~~~~~~}}}}}}~~~~~}~}}}}}}}~}}~}~}~~~~~~}~~}~~~~~€€‚‚‚‚ƒƒƒƒƒƒƒƒ…………†††††‡‡‡ˆˆˆˆˆ‡ˆˆˆˆŠŠ‹ŒŒŒ‹ŠŒŒŠŒŒ‘‘‘‘‘’”””””’‘‘‘‘””•–––”’’‘‘‘’••–—––•••”••––———–—––•••””•”•••––•––••••••–––––—–—————™šššš›™š›šœœœœœœœšššš—ššš›››œšœš›š›ššš›š™š™™—––—•–—••”—•——™——––””””’’””’•”””‘’‘‘”‘–•–”••’’‘‘’”’•”’‘‘‘‘‘‘”””’’‘‘‘”‘’’’’”‘””–•–—••’•’”‘’”•’’’‘’••–••’‹‹‡ˆ‹Š‘”••І†‡Š…ˆŠ‹‡Š†…††‡‡‡†ƒ€‚‡ƒ…ƒ‚}}{~ƒ‚…‚†zyxuvy}~~~{uvstpxu{yzyusspquvz}{{sqlnntv~}~xuqkonu{}‚ƒ~{xpqnuu…‡†ƒ‚~}}~…Š‹‹‡†€}ŠˆŠŒŠ‡…ƒ€ƒ‚‡‹‹‹Œƒ…€~€‚‡‡…†…~}†††ˆ†…€zz{yzƒƒ‚€…yuststy€‚‡€uunloqp}y}yxqvlopstxy{{x{yuq{xqzyyyyy~{‚…‹‡ˆ†‡ƒ‡’•’‹ƒˆ‡ƒ’—–¤ Ÿž™œ’•™•›¡¡ š©š›™›™–›£¡£¥¤¦›Ÿ ”š™ž™¥ž¡™œ‘—””™–›Ÿ›ž¤ž›™ššš› ¤££¡ ™—••–™š  ¨¦Ÿ¤ž’ž™— £®ª°°© –™ˆ—™Ÿ®¨«¨¤¡™™–— ž ¨¡žœ•…†—ŒŒŒŒ‘•Œ‡}zz}†ƒ…ˆ†vusn{€ˆ––•–}jqtu€‚Šƒ…{yjtlux€…‹Šˆ†}{tt‚tvzxy{{~~€~ˆ†ˆ”™ Ÿ¡››‹Šˆ‚ˆ‘œ¤¥«œ™‹ƒ†Œ¥¥´¼¹¯°£ŸŸž£¦³®®«©’’‹‹…”£ž¥¡¡—  ž ©Ÿ™¦œ¡œ£ž™”‡~y}…‹†•—£•‡t}…~‡†…€}}kolszz‚•‹ˆ…p}}ttsqujsxqjly_gpxqx{uklniggtpfklVXXUXWeiggqkjnfjjidja]d\XSUHHNKN_W]``_e[`_ZbbbWk\\de[`ZLUUNRbgdqp]bVfRdboaxt{luleiexoˆƒ‘Œ‹‚†gpttkƒ”‡š–‹”…‹…Š™›ž°«©©²¦ž£”—› Ÿ­Ÿ¥——’Œ”™—¤©¨®°¯°£º¨Ÿ¦©•—‘•ŠŒŒƒŒˆ…•‘’£œ™™–Š‹ˆ‚…‚ƒy€vvnojq{}x}s\isvlt€iijibgN_WZPfb`bnfpglkgW`Z_bksspkiNUQNPdffdyfnd`\eaaiqiolptjj]WZ[gpu€zvspi]]dtv}‡”‡Œ‚p`lksœš¡¥ Ÿžž›–𦤩­®°¸Ã½®©™ªª¹×ÎËͺ¿²« ³²°ÚÍ¿·¾°¥ª¼ž¹¥¸³µÄþ®³©–œ ›°³¼´­©”{~†‚”š–”›ƒ†uvdq`xvzpt{`dfWPPf][jjXX_``_RUUV]X]`SLIPCNLMKUV]bRQIFDPRfaWRMMPSakf_aPX`tˆ†ƒƒjadlbv€qv{v™Œ‘†…†–ž²¿º²™‚ˆqƒ ’š’…‡†ŒšŸœŒ¤³¦¥¯©‹–•‘£š­’‘‘—x‹‹†•–šš’”ty{]kvoavngR[\NSkbX}€l€d]dX]efg_ZjiSSeZLQ_S_xybi[B=\SKNA.BCBB`=&/5)<]UIRG8:CNIF&-&&?QL>C?/=GVNNMPW_okdingjks…Œš”Œ•¡¤ª¤£—‹‚š™…vb`€xzdP[gelb\UKSki}‚np”xp}‚qvž —’𕆕™‘™œ¯¥º¿²ž”‚†‹––°º«­³´• ¥Œt…œ‡Š›~zkeeP`i_b{yp‚tŠ}}~pxt‹u‡‡{—‚t’Œ{—¨š”¤£¿­°³¤¸Ãº³³«º½½®¦¨¥´¿¼Ä¼ÈǾ¦°Â¹ÄÓн¾ÌÎìçÒÇÍðæîÿêÓäêÝôïØáÎÝÖßëÚáÓÜåîÌÍåÖéàËÃÈÕÓ×àÖ¿ÃÚÃåß©Ãà˯Ç´ÈÒß²¥Ä½¼Ò³£©¦¹Íµ­¸­®¹·« ¯´¹­¦©·¸µ´°™–¸°š © µ³¦°­š«¼¤¤¥~¤¹Ÿž—£¡”šŠŠ¾‹‘®š¤º´ …Ÿ}{¦©œ€’ª–{Š{•Œn†‘‹€©‘egt‡`bblžƒgi…}UkUiNIsyxqjzZNqXCVtgtl`Sao]MPIQt{PVsIXu`.Hda_]Vf]WV_?Ng[RX[[lg][CqbLS>fos`V]gUigXKjkfvapn[]Wp[Xt{anjpjz[gƒk\}€z€‚_jƒuppggŸ{†~ƒpupqy}”~‚…{€e{‡l’Š‘†}vp€€}}ˆ{}‚vu†‘v…†~€xtƒtq~ˆ’}‚~{qku’ys™€†o{ƒlyldz†aex~pb‹ˆuztuylnpb}‡qssuupsnsd†l\}~ul[€op]eebjtp_y{`X†xjdZ€Wps`ogzsg_l‹Vv]zxUuy_x…b]uujqpuVggi\fƒxyy€xuuu}j`isj~qv€sppi{p\usxo‡{o}xngnd\usiezxdtqlfk\qgkyo~apo\nMixndf‚p]t{`]qgtaukilqekt]Vk…i~{k{i}`nvbp{oo‚axy~gWŒ€ik…‚tz{‡ptz”‚poŠƒg‚†W‚”—~p–Š•v~ˆƒ‹tŠ™€‚~¦‘}t–’{’†š€ƒŠŠ…Šz‹y–tv…•‚~Šy”†yxz…qu€›vu…t~pˆv}uy”‚ƒ{x…psnpzf‚ty…uqquqŠujƒkl}tf…tzŠvp‹v‘ˆu€—Œ€kƒ‚†yv†’€’…Š~ŠŒ~}—ŠŒ‡~…z‘}‚‡‹’—Œ†‡‹€‡•”†Œ‹x‡~‡‡ˆŒ~†}‹ˆx~Šˆvˆtvˆ‚l~ƒŠvxz‚ix}yqƒtŠxs}{ui}uvpƒ€kizo€‚uƒxzs}ikvo~v~€€ƒp€y{ysq}}…{{€†{zjjn{†n‡ˆ{ss{lvlk‡…‹uuxxbbuƒknˆ~‚~xvznuxqpŒ†}~€qyxikt}†s}ulv~qg}yzx€~usqsnqq}€vxzyyk`exiXuzupxznuf`fqo`sxptsygqidkeod}snt{tlonjokkntqtdtigidjkskqnssog\ija\kjosfnnnjb][dbjijfzze]XfWfXVeoopubos_[`]_knjttnopfb]obennxu€unslpbgvvlv€puysjjglpuz†…}{tuuyxl€~Œƒ‡ƒzyxys‚†Œˆ‹‹Šy{zq{~}‚ŠŠ†zt€y{{ƒ‹…ˆ……}x~vvtz€z{€…z~tqx{zq~€€€€sz{uzqvxy€}{~~}vuy}vx{yz€€}{‡{x~ypu{x}z}ƒ{yyy~pvzxvy}{{zp{unlttplvtvvsvupfsukoktpveopqliqolfnsnjoqninskfltiionlnokiokgnongqoppjongkjklojnknolkglgiieojfqikkijdidgfbbekfedggdjgifjinofgjnkgenolkntptuxsnyvutxz}zy}}}z{~~€…ˆƒ…€ƒ€}}‚ƒ‚ƒ…ƒ…ƒ~ƒƒ‚ƒ€‚}{€xyy{y{z{{{zzzxyuz}z}z€~~{~€‚‡‡…‡‹‹ŠŠ‹•”––•”–š•–—”™ž™——›™–‘‹‹ˆ‡…‡Š†€ƒ~yyzxuzzvvvzuvuvqpkssonpnnqtllolplifljjkjlnlonlknpnplnpnllkfiead`]\_ZSQPNFB<9950--)%((      $(&)--/032320-.)$     %(+024478599:<<==?CCHIILNSVWWWVWWWWW\`dfgilpuyy{~€†…‡ŠŒ’–•–š›ŸŸœŸŸ ¡ Ÿœœž œ›š›œŸ £¤¤¦ªªª©©««­ª«ª©­¯¯­ª­°¯®«­««­ªª¥¤¤¤£ œžž     ££¤¡¡ž   Ÿ››ššššš—™šœžœš›žœŸžœœžžŸ ŸŸ¡¥¤¥¡¡¤¦¦¦¨¦¦ª®««ª­­®²­¯°²µ¹¹·¼¿¿ÄÇÇÆÉÉËËÄÆÄÇÆÄ¼½Á½ºº´³µµ´°­­®°°®««­¯°®ª««­°¯­«®²´·´´µ¸¹½º¸¹¼¾Á¿¾¾ÂÃÄÈÆÃÈÉÍÍÍÍÌÍÑÑÐÍÌÎÎÑÎÍÎÍÐÎÐÎÍÍÎÒÐÒÐÍÎÕÑÓÒÑÓÕÕ×ÖÓÓØ××ÛØÖÖÜØÜ×Ú××ÛÛÜÚØÛØÝÝÚØÚÛÛÚÝØÛÛÚÚßÜÚ×ÝÜÜÝÝÛÚÛÛÛÜÛØØÚ×ÚØ×ØÖ×ÕÓÖÕÒÓÓÑÐÒÎÍÑÍËÍÎÐÍÌËÍÌÉÉËÄÇÈÈÄËÇÇÄÄÄÄÆÄÇÃÁÄÃÃÿÁ¿¿Á¿¾¼½½½½ºº¹¸¼ºº¸·¹·¸¹µ·µ³³´³²´²°²³°²°°®°®°°­­­®­­«­­«ª®««ªªª©ª©¨ª©¨©¨¨¨¨¦©¦¤¥¡¤©¨¤¤¥¦ ¦¥£¤¥¥ ¡¦£¤¤£¤¥¡¥£¥¤¥¡¡££ ¥£ Ÿ    ŸŸŸ›œ œœž™šœœ›šš™™›œ———–™–š–”•–—––™•‘––•––””’•’’‘”‘’‹ˆ‹‹Œ†Šˆ‡‹ˆŠ†‡Šˆ‡Œƒƒ‚‡‡‚ˆˆ‚…ƒ€‚‚‚‚€‚€‚~}~€€~~€€~€‚ƒ~ƒ‚€…‚…~ˆ…ƒ†…€……‡ƒƒƒ…Š‚ˆƒ‚†ƒ…ƒ‚…‚………‚‚‡……‹‡ƒˆˆ†‡†‡ˆŒ‹ˆŒŠ‹Œ‘‹‘Œ‘‘’‘‘‘’•”•’‘’•’”•–’•—•””•™’—–•™•—–”™”——––•—’——•™š—’›———š–––™—–™™—–•—’𙕖’––”–”’••’’’”’’‘’‘’‘‘‘‘‹”‘‘‘‘‘‘‘‘‘Œ‹‹Œ‹Œ‹‹‹‡ŠŠŠ‡††‡ˆ†‚†…ƒ…†ƒ…‚ƒ€€€€~{}~}~{zy{yx{xyxvvuvtstspsppnlnknjnleijgieiddedba`a__Z\\\[[[ZX[ZZZZXWZ[Z[ZW\X[\X\WXZ\[W[ZZ[XZ[ZZ\Z[[][]_\]]]_aa_ababbebddefefgefggfiegfiifkgejiliijijjjlijkjkkklkllkkkllnolklkklolkkjonlllllnlollnnlonnoopnoonlnonnqpjlnoppnlnnlknonknlkllnlkkknkkljlkljkljllkjjikkkjjkkkkiillikljjkkillkjllkkljlkjllklnkknnknqnnlolpppqqqostssqsuttuvuuuuxvvvvvxyxvvvyyvyxvxyxyzvvzyzyzyx{zyzzzzz{{}{y{z}}}{z{{}z{}y{}}z{}z}~{}}{}}~~}~~~~}~€~~~~€~~~€€~~‚‚€~‚‚‚€‚ƒ€€‚…‚€‚‚ƒƒ‚€‚ƒƒƒ‚‚‚‚ƒƒƒ‚‚‚ƒƒƒƒƒ…………ƒ……†††………†‡††…††††……††††ƒ††‡†…†‡……†‡‡†‡‡†ˆ‡††ˆˆ†‡ˆ†‡ˆˆˆˆˆ†‡ˆŠ‡ˆ‡ˆˆˆ‡‡ˆˆŠ‡ˆ‡ˆŠ‡ˆ‡ˆ‡ˆŠˆˆŠŠˆˆˆˆ‡Š‹Š‡ˆ‡ˆŠ‹ˆˆˆŠŠŠŠ‡ˆŠŠŠŠˆ‡ˆŠŠŠŠŠˆŠˆŠ‹‹Š‹Š‹‹ŠŒŠ‹‹Œ‹‹‹ŠŠŒ‹ˆ‹‹‹‹‹ŠˆŒŒŠ‹‹‹‹‹ŒŒ‹ŒŒŒŒŒŒ‹ŒŒŒŒŒŒŒŠŒŒ‹ŒŒŒŒŒŒŒŒŒ‹Œ‹ŒŒŒŒŒŒŒŒŒŒ‹ŒŒŒŒŒŒŒŒŒ‹‹‹ŒŒŒŒ‹‹Œ‹ŒŒŒŒŒ‹Œ‹ŒŒŒŒ‹ŒŒŒŒŒŒŒŒŒŒŒnew_rdpyg/tests/.test_pack_textures.py.swp0000644000175100017510000004000010220112721021262 0ustar renerene00000000000000b0VIM 6.3E^æ@ôórenegrace/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_pack_textures.py3210#"! Utpÿ{ |ad%%{ÿïîÉÈÇœ“‹Šl`[Z*úÊšj6Ò   m l k K    æ µ ¢ ¡ ‚ P = <  ß Ì Ë ™ † … S @ ?  Ö Ã Â } | { s r V J E D  ä ´ „ T WVUT콎_@-,ùåÇ©mlF&èÉŒfQ1ÿÞÒÑ¡qAá­{Iä³²ƒT%$ self.assertEqual(True, t1.collide(t4)) self.assertEqual(True, t1.collide(t2)) self.assertEqual(True, t1.collide(t3)) t11 = pack_textures.Texture(1,1,256,256) t10 = pack_textures.Texture(128,0,128,128) t9 = pack_textures.Texture(0,128,128,128) t8 = pack_textures.Texture(500,0,128,128) t7 = pack_textures.Texture(0,500,128,128) t6 = pack_textures.Texture(500,500,128,128) t5 = pack_textures.Texture(0,0,512,512) t4 = pack_textures.Texture(0,0,128,256) t3 = pack_textures.Texture(0,0,128,256) t2 = pack_textures.Texture(0,0,256,256) t1 = pack_textures.Texture(0,0,256,256) """ """ does collision work? def test_collide(self): t11.clear() #print t11.sub_textures print len(r) r = t11.try_fit_batch(smalls) smalls.append(pack_textures.Texture(0,0,32,32)) for x in range(20000): # try to fit more than we have. t11.clear() #print t11.sub_textures r = t11.try_fit_batch(smalls) smalls.append(pack_textures.Texture(0,0,32,32)) for x in range(3030): #for x in range(130): smalls = [] t11 = pack_textures.Texture(0,0,4096,4096) t5.clear() #print t5.sub_textures self.assertEqual(True, t5.try_fit(t4)) self.assertEqual(True, t5.try_fit(t3)) self.assertEqual(True, t5.try_fit(t2)) self.assertEqual(True, t5.try_fit(t1)) # both of these should fit on top of each other. t10 = pack_textures.Texture(128,0,128,128) t9 = pack_textures.Texture(0,128,128,128) t8 = pack_textures.Texture(500,0,128,128) t7 = pack_textures.Texture(0,500,128,128) t6 = pack_textures.Texture(500,500,128,128) t5 = pack_textures.Texture(0,0,512,512) t4 = pack_textures.Texture(0,0,128,256) t3 = pack_textures.Texture(0,0,128,256) t2 = pack_textures.Texture(0,0,256,256) t1 = pack_textures.Texture(0,0,256,256) """ """ def test_try_fit(self): t1.clear() self.assertEqual(True, t1.could_fit(t10)) t1.clear() self.assertEqual(True, t1.could_fit(t9)) # these are right on the edge, but should work. t1.clear() self.assertEqual(False, t1.could_fit(t8)) t1.clear() self.assertEqual(False, t1.could_fit(t7)) t1.clear() self.assertEqual(False, t1.could_fit(t6)) # the x,y make this outside of it. t1.clear() self.assertEqual(False, t1.could_fit(t5)) # this one is too big. t1.clear() self.assertEqual(True, t1.could_fit(t3)) # should fit in easily. t1.clear() self.assertEqual(True, t1.could_fit(t2)) # should fit in easily. t10 = pack_textures.Texture(128,0,128,128) t9 = pack_textures.Texture(0,128,128,128) t8 = pack_textures.Texture(500,0,128,128) t7 = pack_textures.Texture(0,500,128,128) t6 = pack_textures.Texture(500,500,128,128) t5 = pack_textures.Texture(0,0,512,512) t4 = pack_textures.Texture(0,0,128,256) t3 = pack_textures.Texture(0,0,128,256) t2 = pack_textures.Texture(0,0,256,256) t1 = pack_textures.Texture(0,0,256,256) """ """ def test_could_fit(self): """ """ class TestPackTextures(unittest.TestCase):from rdpyg.util import pack_texturesimport unittestadÇ  Ñ¡ p?>=<!     unittest.main()if __name__ == "__main__": self.assertEqual(False, t9.collide(t10)) self.assertEqual(False, t1.collide(t6)) self.assertEqual(True, t1.collide(t11)) self.assertEqual(True, t1.collide(t9))new_rdpyg/tests/chimpgl.py0000644000175100017510000001420010067276060016122 0ustar renerene00000000000000#/usr/bin/env python """ This simple example is used for the line-by-line tutorial that comes with pygame. It is based on a 'popular' web banner. Note there are comments here, but for the full explanation, follow along in the tutorial. """ #Import Modules import os, pygame from pygame.locals import * if not pygame.font: print 'Warning, fonts disabled' if not pygame.mixer: print 'Warning, sound disabled' USE_GL = 1 if USE_GL: from rdpyg.sprites.spritegl import SpriteGL, GroupGL, gl_display_get_surface, gl_display_set_mode pygame.sprite.Sprite = SpriteGL pygame.sprite.Group = GroupGL pygame.sprite.RenderPlain = GroupGL pygame.display.old_get_surface = pygame.display.get_surface pygame.display.get_surface = gl_display_get_surface pygame.display.old_set_mode = pygame.display.set_mode pygame.display.set_mode = gl_display_set_mode #functions to create our resources def load_image(name, colorkey=None): fullname = os.path.join('data', name) try: image = pygame.image.load(fullname) except pygame.error, message: print 'Cannot load image:', fullname raise SystemExit, message image = image.convert() if colorkey is not None: if colorkey is -1: colorkey = image.get_at((0,0)) image.set_colorkey(colorkey, RLEACCEL) return image, image.get_rect() def load_sound(name): class NoneSound: def play(self): pass if not pygame.mixer or not pygame.mixer.get_init(): return NoneSound() fullname = os.path.join('data', name) try: sound = pygame.mixer.Sound(fullname) except pygame.error, message: print 'Cannot load sound:', fullname return NoneSound() raise SystemExit, message return sound #classes for our game objects class Fist(pygame.sprite.Sprite): """moves a clenched fist on the screen, following the mouse""" def __init__(self): pygame.sprite.Sprite.__init__(self) #call Sprite initializer self.image, self.rect = load_image('fist.bmp', -1) self.punching = 0 def update(self): "move the fist based on the mouse position" pos = pygame.mouse.get_pos() self.rect.midtop = pos if self.punching: self.rect.move_ip(5, 10) def punch(self, target): "returns true if the fist collides with the target" if not self.punching: self.punching = 1 hitbox = self.rect.inflate(-5, -5) return hitbox.colliderect(target.rect) def unpunch(self): "called to pull the fist back" self.punching = 0 class Chimp(pygame.sprite.Sprite): """moves a monkey critter across the screen. it can spin the monkey when it is punched.""" def __init__(self): pygame.sprite.Sprite.__init__(self) #call Sprite intializer self.image, self.rect = load_image('chimp.bmp', -1) screen = pygame.display.get_surface() self.area = screen.get_rect() self.rect.topleft = 10, 10 self.move = 9 self.dizzy = 0 def update(self): "walk or spin, depending on the monkeys state" if self.dizzy: self._spin() else: self._walk() def _walk(self): "move the monkey across the screen, and turn at the ends" newpos = self.rect.move((self.move, 0)) if self.rect.left < self.area.left or \ self.rect.right > self.area.right: self.move = -self.move newpos = self.rect.move((self.move, 0)) self.image = pygame.transform.flip(self.image, 1, 0) self.rect = newpos def _spin(self): "spin the monkey image" center = self.rect.center self.dizzy = self.dizzy + 12 if self.dizzy >= 360: self.dizzy = 0 self.image = self.original else: rotate = pygame.transform.rotate self.image = rotate(self.original, self.dizzy) self.rect = self.image.get_rect() self.rect.center = center def punched(self): "this will cause the monkey to start spinning" if not self.dizzy: self.dizzy = 1 self.original = self.image def main(): """this function is called when the program starts. it initializes everything it needs, then runs in a loop until the function returns.""" #Initialize Everything pygame.init() screen = pygame.display.set_mode((468, 60)) pygame.display.set_caption('Monkey Fever') pygame.mouse.set_visible(0) #Create The Backgound background = pygame.Surface(screen.get_size()) background = background.convert() background.fill((250, 250, 250)) #Put Text On The Background, Centered if pygame.font: font = pygame.font.Font(None, 36) text = font.render("Pummel The Chimp, And Win $$$", 1, (10, 10, 10)) textpos = text.get_rect() textpos.centerx = background.get_rect().centerx background.blit(text, textpos) #Display The Background screen.blit(background, (0, 0)) pygame.display.flip() #Prepare Game Objects clock = pygame.time.Clock() whiff_sound = load_sound('whiff.wav') punch_sound = load_sound('punch.wav') chimp = Chimp() fist = Fist() allsprites = pygame.sprite.RenderPlain((fist, chimp)) #Main Loop while 1: clock.tick(60) #Handle Input Events for event in pygame.event.get(): if event.type == QUIT: return elif event.type == KEYDOWN and event.key == K_ESCAPE: return elif event.type == MOUSEBUTTONDOWN: if fist.punch(chimp): punch_sound.play() #punch chimp.punched() else: whiff_sound.play() #miss elif event.type == MOUSEBUTTONUP: fist.unpunch() allsprites.update() #Draw Everything screen.blit(background, (0, 0)) allsprites.draw(screen) pygame.display.flip() print clock.get_fps() #Game Over #this calls the 'main' function when this script is executed if __name__ == '__main__': main() new_rdpyg/tests/run_all_tests.py0000644000175100017510000000160510160213520017344 0ustar renerene00000000000000"""Regression testing framework short:Runs all the tests. long:This module will search for scripts in the same directory named test*.py. Each such script should be a test suite that tests a module through PyUnit. This script will aggregate all found test suites into one big test suite and run them all at once. """ import sys, os, re, unittest, glob def regressionTest(): files = glob.glob("test*.py") if not files: os.chdir("tests") files = glob.glob("test*.py") filenameToModuleName = lambda f: os.path.splitext(f)[0] moduleNames = map(filenameToModuleName, files) modules = map(__import__, moduleNames) load = unittest.defaultTestLoader.loadTestsFromModule return unittest.TestSuite(map(load, modules)) if __name__ == "__main__": unittest.main(defaultTest="regressionTest") new_rdpyg/tests/sounds_test.py0000644000175100017510000000762510157476702017073 0ustar renerene00000000000000""" Tests out the features of the urdpyg.sounds module. Try the keys: o i u y t o: will play a sound and queue it if it's allready playing. i: will play a sound and queue it if it's allready playing. y: will play a sound if playing will play it anyway. t: will play a sound if playing will not play it. u: should fade out tracks. """ from OpenGL.GL import * from OpenGL.GLU import * from pygame.locals import * import pygame import time from rdpyg.app import the_app_gl pygame.init() from urdpyg import sounds import os # Data driven sound loading. Get all the sounds listed in the sound path. SOUND_PATH = os.path.join("data", "sounds") SOUND_LIST = sounds.get_sound_list(SOUND_PATH) class SoundsTestApp(the_app_gl.TheAppGL): def __init__(self): the_app_gl.TheAppGL.__init__(self) def Load(self): the_app_gl.TheAppGL.Load(self) self.sound_manager = sounds.SoundManager(sound_list = SOUND_LIST, sound_path = SOUND_PATH) # Turn debugging on for the sound manager. So we can see extra problems. self.sound_manager._debug_level = 1 # Load all the files into memory. Without calling Load sounds are loaded on demand. self.sound_manager.Load(sound_list = SOUND_LIST, sound_path = SOUND_PATH) def HandleEvents(self, event_list): if the_app_gl.TheAppGL.HandleEvents(self, event_list) == 0: return 0 for event in event_list: if event.type == KEYDOWN and event.key == K_o: self.sound_manager.Play("one_bump3", wait = 1) if event.type == KEYDOWN and event.key == K_i: # will play a sound and queue it if it's allready playing. self.sound_manager.Play("one_bump4", wait = 1) if event.type == KEYDOWN and event.key == K_y: # will play a sound if playing will play it anyway. self.sound_manager.Play("one_bump4") if event.type == KEYDOWN and event.key == K_t: # will play a sound if playing will not play it. self.sound_manager.Play("one_bump4", wait = 2) if event.type == KEYDOWN and event.key == K_u: # should fade out tracks. self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump4") self.sound_manager.Play("one_bump3") self.sound_manager.Play("one_bump3") self.sound_manager.Play("one_bump3") self.sound_manager.Play("one_bump3") if event.type == KEYDOWN and event.key == K_u: # file not there. self.sound_manager.Play("one_bump99999999") return 1 def Update(self, elapsed_time): the_app_gl.TheAppGL.Update(self, elapsed_time) # we tell the sound manager how much time has elapsed, so it can update playback of sounds. self.sound_manager.Update(elapsed_time) def Display(self): """ Basic display function just clears the screen. """ glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) if __name__ == "__main__": print "Try the keys: o i u y t" print "o: will play a sound and queue it if it's allready playing." print "i: will play a sound and queue it if it's allready playing." print "y: will play a sound if playing will play it anyway." print "t: will play a sound if playing will not play it." print "u: should fade out tracks." a = SoundsTestApp() a.Start() a.Loop() new_rdpyg/tests/test_milk_skeleton.py0000644000175100017510000000574410076014255020407 0ustar renerene00000000000000""" Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ import unittest from urdpyg import milk_skeleton import os class TestCaseBase(unittest.TestCase): _debug_level = 1 def _debug(self, d, debug_level = 1): if self._debug_level >= debug_level: #a = StringIO() #pprint.pprint(d, a) #a.seek(0) #sys.stderr.write(":::%s:::\n" % a.read() ) sys.stderr.write(":::%s:::\n" % d) class Time2Keyframe_Map_test(TestCaseBase): def test_no_loop(self): """ Do the end conditions work when there is loop is set to false. """ def test_zero_seconds(self): """ tests to see if the correct results are returned at zero seconds. """ t2kf = milk_skeleton.Time2Keyframe_Map() t2kf.Update([4.0, 15.3, 16.2, 16.7, 16.9, 17.3, 130.0, 140.0, 150.9]) class BoneHeirachy_test(TestCaseBase): def test_MilkBonesConversion(self): """ test the conversion from milk_bone class into BoneHeirarchy. """ # read from a file, and manually get the correct results from the # file. model_path = os.path.join("data", "models", "bend.txt") m = milk_skeleton.MilkshapeModelLoader(model_path) #m.Load("milkshape_char_fx/yagogood.txt") should_be = {'': ['joint1'], 'joint1': ['joint2'], 'joint2': ['joint3'], 'joint3': ['joint4'], 'joint4': ['joint5'], 'joint5': ['joint6'], 'joint6': ['joint7']} self.assertEqual(m.skeleton.bone_heirarchy.bone_parents_dict, should_be) should_be = {'joint1': [''], 'joint2': ['joint1'], 'joint3': ['joint2'], 'joint4': ['joint3'], 'joint5': ['joint4'], 'joint6': ['joint5'], 'joint7': ['joint6']} self.assertEqual(m.skeleton.bone_heirarchy.bone_children_dict,should_be) def test_bone_name2bone_number_map(self): # We see if the order is done correctly. model_path = os.path.join("data", "models", "bend.txt") m = milk_skeleton.MilkshapeModelLoader(model_path) should_be = {'joint5': 4, 'joint4': 3, 'joint7': 6, 'joint6': 5, 'joint1': 0, 'joint3': 2, 'joint2': 1} self.assertEqual(m.skeleton.bone_name2bone_number_map, should_be) if __name__ == "__main__": unittest.main() new_rdpyg/tests/test_milk_skeleton.pyc0000644000175100017510000001142510157500102020532 0ustar renerene00000000000000;ò ­ø@c@s‰dZdkZdklZdkZdeifd„ƒYZdefd„ƒYZdefd„ƒYZe d joei ƒndS( s  Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. N(s milk_skeletons TestCaseBasecBstZdZdd„ZRS(NicCs,|i|jotiid|ƒndS(Ns :::%s::: (sselfs _debug_levels debug_levelssyssstderrswritesd(sselfsds debug_level((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pys_debugs(s__name__s __module__s _debug_levels_debug(((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pys TestCaseBasessTime2Keyframe_Map_testcBstZd„Zd„ZRS(NcCsdS(sA Do the end conditions work when there is loop is set to false. N((sself((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pys test_no_loop,sc Cs8tiƒ}|iddddddddd g ƒd S( sD tests to see if the correct results are returned at zero seconds. f4.0f15.300000000000001f16.199999999999999f16.699999999999999f16.899999999999999f17.300000000000001f130.0f140.0f150.90000000000001N(s milk_skeletonsTime2Keyframe_Mapst2kfsUpdate(sselfst2kf((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pystest_zero_seconds0s (s__name__s __module__s test_no_loopstest_zero_seconds(((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pysTime2Keyframe_Map_test+s sBoneHeirachy_testcBstZd„Zd„ZRS(NcCstiidddƒ}ti|ƒ}hddg<ddg<ddg<ddg<dd g<d d g<d d g<}|i |i i i |ƒhddg<ddg<ddg<ddg<d dg<d d g<d d g<}|i |i i i |ƒd S( sG test the conversion from milk_bone class into BoneHeirarchy. sdatasmodelssbend.txtssjoint1sjoint2sjoint3sjoint4sjoint5sjoint6sjoint7N(sosspathsjoins model_paths milk_skeletonsMilkshapeModelLoadersms should_besselfs assertEqualsskeletonsbone_heirarchysbone_parents_dictsbone_children_dict(sselfs should_besms model_path((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pystest_MilkBonesConversion@sZZcCs†tiidddƒ}ti|ƒ}hdd<dd<dd <d d <d d <dd<dd<}|i |i i |ƒdS(Nsdatasmodelssbend.txtsjoint5isjoint4isjoint7isjoint6isjoint1isjoint3isjoint2i( sosspathsjoins model_paths milk_skeletonsMilkshapeModelLoadersms should_besselfs assertEqualsskeletonsbone_name2bone_number_map(sselfs should_besms model_path((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pystest_bone_name2bone_number_mapbsE(s__name__s __module__stest_MilkBonesConversionstest_bone_name2bone_number_map(((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pysBoneHeirachy_test=s "s__main__( s__doc__sunittestsurdpygs milk_skeletonsossTestCases TestCaseBasesTime2Keyframe_Map_testsBoneHeirachy_tests__name__smain(sTime2Keyframe_Map_tests TestCaseBasesunittests milk_skeletonsBoneHeirachy_testsos((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_milk_skeleton.pys?s   8 new_rdpyg/tests/test_pack_textures.py0000644000175100017510000000732010071457105020420 0ustar renerene00000000000000 import unittest from rdpyg.util import pack_textures class TestPackTextures(unittest.TestCase): """ """ def test_could_fit(self): """ """ t1 = pack_textures.Texture(0,0,256,256) t2 = pack_textures.Texture(0,0,256,256) t3 = pack_textures.Texture(0,0,128,256) t4 = pack_textures.Texture(0,0,128,256) t5 = pack_textures.Texture(0,0,512,512) t6 = pack_textures.Texture(500,500,128,128) t7 = pack_textures.Texture(0,500,128,128) t8 = pack_textures.Texture(500,0,128,128) t9 = pack_textures.Texture(0,128,128,128) t10 = pack_textures.Texture(128,0,128,128) # should fit in easily. self.assertEqual(True, t1.could_fit(t2)) t1.clear() # should fit in easily. self.assertEqual(True, t1.could_fit(t3)) t1.clear() # this one is too big. self.assertEqual(False, t1.could_fit(t5)) t1.clear() # the x,y make this outside of it. self.assertEqual(False, t1.could_fit(t6)) t1.clear() self.assertEqual(False, t1.could_fit(t7)) t1.clear() self.assertEqual(False, t1.could_fit(t8)) t1.clear() # these are right on the edge, but should work. self.assertEqual(True, t1.could_fit(t9)) t1.clear() self.assertEqual(True, t1.could_fit(t10)) t1.clear() def test_try_fit(self): """ """ t1 = pack_textures.Texture(0,0,256,256) t2 = pack_textures.Texture(0,0,256,256) t3 = pack_textures.Texture(0,0,128,256) t4 = pack_textures.Texture(0,0,128,256) t5 = pack_textures.Texture(0,0,512,512) t6 = pack_textures.Texture(500,500,128,128) t7 = pack_textures.Texture(0,500,128,128) t8 = pack_textures.Texture(500,0,128,128) t9 = pack_textures.Texture(0,128,128,128) t10 = pack_textures.Texture(128,0,128,128) # both of these should fit on top of each other. self.assertEqual(True, t5.try_fit(t1)) self.assertEqual(True, t5.try_fit(t2)) self.assertEqual(True, t5.try_fit(t3)) self.assertEqual(True, t5.try_fit(t4)) #print t5.sub_textures t5.clear() t11 = pack_textures.Texture(0,0,4096,4096) smalls = [] #for x in range(130): for x in range(3030): smalls.append(pack_textures.Texture(0,0,32,32)) r = t11.try_fit_batch(smalls) #print t11.sub_textures t11.clear() # try to fit more than we have. for x in range(20000): smalls.append(pack_textures.Texture(0,0,32,32)) r = t11.try_fit_batch(smalls) print len(r) #print t11.sub_textures t11.clear() def test_collide(self): """ does collision work? """ t1 = pack_textures.Texture(0,0,256,256) t2 = pack_textures.Texture(0,0,256,256) t3 = pack_textures.Texture(0,0,128,256) t4 = pack_textures.Texture(0,0,128,256) t5 = pack_textures.Texture(0,0,512,512) t6 = pack_textures.Texture(500,500,128,128) t7 = pack_textures.Texture(0,500,128,128) t8 = pack_textures.Texture(500,0,128,128) t9 = pack_textures.Texture(0,128,128,128) t10 = pack_textures.Texture(128,0,128,128) t11 = pack_textures.Texture(1,1,256,256) self.assertEqual(True, t1.collide(t3)) self.assertEqual(True, t1.collide(t2)) self.assertEqual(True, t1.collide(t4)) self.assertEqual(True, t1.collide(t9)) self.assertEqual(True, t1.collide(t11)) self.assertEqual(False, t1.collide(t6)) self.assertEqual(False, t9.collide(t10)) if __name__ == "__main__": unittest.main() new_rdpyg/tests/test_pack_textures.pyc0000644000175100017510000000746610157500102020565 0ustar renerene00000000000000;ò E^æ@c@sNdkZdklZdeifd„ƒYZedjoeiƒndS(N(s pack_texturessTestPackTexturescBs)tZdZd„Zd„Zd„ZRS(s c Cs tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ} tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ} |i t|i|ƒƒ|iƒ|i t|i|ƒƒ|iƒ|i t|i|ƒƒ|iƒ|i t|i|ƒƒ|iƒ|i t|i|ƒƒ|iƒ|i t|i|ƒƒ|iƒ|i t|i|ƒƒ|iƒ|i t|i| ƒƒ|iƒdS(s iii€iiôN(s pack_texturessTexturest1st2st3st4st5st6st7st8st9st10sselfs assertEqualsTrues could_fitsclearsFalse( sselfst8st9st6st7st5st2st3st1st10st4((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_pack_textures.pystest_could_fit s6       cCs)tiddddƒ} tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ} |i t|i| ƒƒ|i t|i|ƒƒ|i t|i|ƒƒ|i t|i|ƒƒ|iƒtiddddƒ} g}x3tdƒD]%} |itiddddƒƒq‰W| i|ƒ} | iƒx3td ƒD]%} |itiddddƒƒqØW| i|ƒ} t| ƒGH| iƒd S( s iii€iiôiiÖ i i NN(s pack_texturessTexturest1st2st3st4st5st6st7st8st9st10sselfs assertEqualsTruestry_fitsclearst11ssmallssrangesxsappends try_fit_batchsrslen(sselfssmallsst8st9st6st7st5st2st3st1srst10st11sxst4((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_pack_textures.pys test_try_fit;s:  #  # c Cs»tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ} tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ}tiddddƒ} tiddddƒ} |it|i|ƒƒ|it|i|ƒƒ|it|i| ƒƒ|it|i|ƒƒ|it|i| ƒƒ|it|i|ƒƒ|it|i| ƒƒdS(s does collision work? iii€iiôiN(s pack_texturessTexturest1st2st3st4st5st6st7st8st9st10st11sselfs assertEqualsTruescollidesFalse( sselfst8st9st6st7st5st2st3st1st10st11st4((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_pack_textures.pys test_collideis&(s__name__s __module__s__doc__stest_could_fits test_try_fits test_collide(((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_pack_textures.pysTestPackTexturess  0 .s__main__(sunittests rdpyg.utils pack_texturessTestCasesTestPackTexturess__name__smain(sunittests pack_texturessTestPackTextures((sL/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_pack_textures.pys?s  } new_rdpyg/tests/test_paths.py0000644000175100017510000000102110067435744016660 0ustar renerene00000000000000 import unittest from rdpyg.util import paths import pickle class TestPaths(unittest.TestCase): """ """ def test_pickling(self): """ """ p = paths.Path() p.SetPoints([[0., 0., 0.], [0., 1., 0.], [1., 1., 0.], [2., 2., 0.], [3., 3., 0.]]) pickled_path = pickle.dumps(p) unpickled_path = pickle.loads(pickled_path) self.assertEqual(p, unpickled_path) if __name__ == "__main__": unittest.main() new_rdpyg/tests/test_paths.pyc0000644000175100017510000000175710157500025017024 0ustar renerene00000000000000;ò ä;Þ@c@sWdkZdklZdkZdeifd„ƒYZedjoeiƒndS(N(spathss TestPathscBstZdZd„ZRS(s cCs‡tiƒ}|idddgdddgdddgdddgdddggƒti|ƒ}ti|ƒ}|i ||ƒdS(s f0.0f1.0f2.0f3.0N( spathssPathsps SetPointsspicklesdumpss pickled_pathsloadssunpickled_pathsselfs assertEqual(sselfs pickled_pathspsunpickled_path((s test_paths.pys test_picklings  I(s__name__s __module__s__doc__s test_pickling(((s test_paths.pys TestPaths s s__main__(sunittests rdpyg.utilspathsspicklesTestCases TestPathss__name__smain(spathssunittestspickles TestPaths((s test_paths.pys?s    new_rdpyg/tests/test_quaternion.py0000644000175100017510000001204510157467506017737 0ustar renerene00000000000000 import unittest import pickle from rdpyg.util.quaternion import * import rdpyg.util.quaternion as quaternion import time #import psyco #psyco.bind(fromEuler) #psyco.bind(fromXYZR) #psyco.bind(normalise_vector) #psyco.bind(Quaternion) #psyco.bind(array) #psyco.bind(sin) #psyco.bind(cos) def within_accuracy(a,b, allowable_error = 0.000001): """ Is a equal to b within the allowable_error? """ #return a <= b+ allowable_error and a > b- allowable_error return math.fabs(a -b) < allowable_error class TestBla(unittest.TestCase): _debug_level = 1 def _debug(self, d, debug_level = 1): if self._debug_level >= debug_level: #a = StringIO() #pprint.pprint(d, a) #a.seek(0) #sys.stderr.write(":::%s:::\n" % a.read() ) sys.stderr.write(":::%s:::\n" % d) class TestExtraFuncs(unittest.TestCase): """ tests the extra functions. """ _debug_level = 1 def _debug(self, d, debug_level = 1): if self._debug_level >= debug_level: #a = StringIO() #pprint.pprint(d, a) #a.seek(0) #sys.stderr.write(":::%s:::\n" % a.read() ) sys.stderr.write(":::%s:::\n" % d) def test_get_angles_from_two_points(self): """ does the angle come out correctly for the given points. """ p1 = [0., 0., 0.] p2 = [2., 0., 0.] angles = quaternion.get_angles_from_two_points(p1, p2) print angles #should be (0, 90, 0) p1 = [0., 0., 0.] p2 = [2., 1., 0.] angles = quaternion.get_angles_from_two_points(p1, p2) print angles class TestQuaternions(unittest.TestCase): """ The quaternion functions which I need for """ _debug_level = 1 def _debug(self, d, debug_level = 1): if self._debug_level >= debug_level: #a = StringIO() #pprint.pprint(d, a) #a.seek(0) #sys.stderr.write(":::%s:::\n" % a.read() ) sys.stderr.write(":::%s:::\n" % d) def test_length(self): """ Is the length equal to 1.0? """ w,x,y,z = fromEuler( y = pi/2 ).internal length = x**2 + y**2 + z**2 + w**2 self.assertEqual(1.0, length) # check to see if two multiplications equals length 1. q1 = fromEuler( y = pi/2 ) q2 = fromEuler( x = pi/2 ) q3 = q1 * q2 w,x,y,z = q3.internal length = x**2 + y**2 + z**2 + w**2 self.assertEqual(1.0, length) def test_fromEuler(self): """ """ #print fromEuler( y = pi/2 ).XYZR() def test_to_matrix_and_back(self): """ Does the conversion to matrix and from matrix work correctly? """ a = fromEuler( y = pi/2 ) b = fromMatrix(a.matrix()) w,x,y,z = b.internal length = x**2 + y**2 + z**2 + w**2 self.assertEqual(1.0, length) self.assertEqual(a.matrix(), b.matrix()) def test_speed_of_convert_to_matrix(self): """ Is the speed of the quaternion to matrix acceptable? """ # How fast does this need to be? # We have 30 bones per character. # We have 13 characters. # one tenth of the time is devoted to animation. # one tenth of that is devoted to quat-> mat transforms. # 60 frames per second. # 30 * 13 per # 1. /60 /10 /10 /13 /30 # .000000427 per one. # 0.000166 for all of them (13 * 30 == 390). t1 = time.time() a = fromEuler( z = pi/2 ) a_matrix = a.matrix for x in range(13 * 300): b = a_matrix() t2 = time.time() total_time = t2 -t1 print total_time #self.Assert def test_slerp(self): """ Does the slerp work correctly? """ a = fromEuler( z = pi/2 ) b = fromEuler( x = pi/2 ) c = slerp_quat(a,b, 0.5) self.assertEqual( 1, within_accuracy(1.,length_quat(c)) ) def test_euler_to_quats(self): """ """ a = [[0.0, 0.0, 0.0], [1.2042771577835081, 0.0, 0.0], [0.89011788368225098, 0.0, 0.0]] quats_a = euler_to_quats(a) b = [[0.087266437709331512, 5.1804383005560339e-10, 0.113446407020092], [-0.13962611556053159, -2.62412314100402e-08, 0.1134487614035606], [0.078540049493312836, -2.7923498180371101e-08, 0.1134487614035606]] quats_b = euler_to_quats(b) print quats_a print quats_b def test_pickling(self): """ Can we pickle and unpickle the quaternions nicely? """ a = [[0.0, 0.0, 0.0], [1.2042771577835081, 0.0, 0.0], [0.89011788368225098, 0.0, 0.0]] q = euler_to_quats(a) pickled_q = pickle.dumps(q) unpickled_q = pickle.loads(pickled_q) self.assertEqual(q, unpickled_q) def test_pickle(self): """ can we pickle/unpickle it properly. """ q = fromEuler(1.2042771577835081, 0.0, 0.0) pickled_quat = pickle.dumps(q) unpickled_q = pickle.loads(pickled_quat) self.assertEqual(q.internal, unpickled_q.internal) #self.assertEqual(q, unpickled_q) def test_invert(self): """ tests the inverse is correct. That is the opposite direction. """ q = fromAXYZ(180,1.,0.,0.) q2 = -q self.assertEqual(q2.AXYZ(), [180.00000000000003, -1.0, -0.0, -0.0] ) if __name__ == "__main__": unittest.main() new_rdpyg/tests/test_quaternion.pyc0000644000175100017510000001775310157500102020071 0ustar renerene00000000000000;ò Fo¾Ac@s§dkZdkZdkTdkiiZdkZdd„Zdeifd„ƒYZdeifd„ƒYZ deifd „ƒYZ e d joei ƒndS( N(s*f9.9999999999999995e-07cCsti||ƒ|jSdS(s1 Is a equal to b within the allowable_error? N(smathsfabssasbsallowable_error(sasbsallowable_error((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pyswithin_accuracyssTestBlacBstZdZdd„ZRS(NicCs,|i|jotiid|ƒndS(Ns :::%s::: (sselfs _debug_levels debug_levelssyssstderrswritesd(sselfsds debug_level((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys_debug!s(s__name__s __module__s _debug_levels_debug(((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pysTestBlassTestExtraFuncscBs)tZdZdZdd„Zd„ZRS(s tests the extra functions. icCs,|i|jotiid|ƒndS(Ns :::%s::: (sselfs _debug_levels debug_levelssyssstderrswritesd(sselfsds debug_level((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys_debug3scCsndddg}dddg}ti||ƒ}|GHdddg}dddg}ti||ƒ}|GHdS(s: does the angle come out correctly for the given points. f0.0f2.0f1.0N(sp1sp2s quaternionsget_angles_from_two_pointssangles(sselfsp2sp1sangles((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pystest_get_angles_from_two_points<s(s__name__s __module__s__doc__s _debug_levels_debugstest_get_angles_from_two_points(((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pysTestExtraFuncs,s  sTestQuaternionscBsqtZdZdZdd„Zd„Zd„Zd„Zd„Zd„Z d„Z d „Z d „Z d „Z RS( s0 The quaternion functions which I need for icCs,|i|jotiid|ƒndS(Ns :::%s::: (sselfs _debug_levels debug_levelssyssstderrswritesd(sselfsds debug_level((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys_debugVsc CsÏtdtdƒi\}}}}|d|d|d|d}|i d|ƒtdtdƒ}tdtdƒ}||}|i\}}}}|d|d|d|d}|i d|ƒdS(s Is the length equal to 1.0? syif1.0sxN( s fromEulerspisinternalswsxsyszslengthsselfs assertEqualsq1sq2sq3( sselfsq1sq3slengthsq2swsysxsz((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys test_length`s"" "cCsdS(s N((sself((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pystest_fromEulerqscCsŒtdtdƒ}t|iƒƒ}|i\}}}}|d|d|d|d}|i d|ƒ|i |iƒ|iƒƒdS(s@ Does the conversion to matrix and from matrix work correctly? syif1.0N(s fromEulerspisas fromMatrixsmatrixsbsinternalswsxsyszslengthsselfs assertEqual(sselfsasbszslengthswsysx((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pystest_to_matrix_and_backws"cCsktiƒ}tdtdƒ}|i}x!tddƒD]}|ƒ}q9Wtiƒ}||}|GHdS(s8 Is the speed of the quaternion to matrix acceptable? szii i,N( stimest1s fromEulerspisasmatrixsa_matrixsrangesxsbst2s total_time(sselfsas total_timesbsa_matrixst2st1sx((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pystest_speed_of_convert_to_matrix†s     cCs[tdtdƒ}tdtdƒ}t||dƒ}|idtdt |ƒƒƒdS(s! Does the slerp work correctly? szisxf0.5if1.0N( s fromEulerspisasbs slerp_quatscsselfs assertEqualswithin_accuracys length_quat(sselfsascsb((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys test_slerp¢s cCs{dddgdddgdddgg}t|ƒ}dddgd dd gd d d gg}t|ƒ}|GH|GHd S( s f0.0f1.2042771577835081f0.89011788368225098f0.087266437709331512f5.1804383005560339e-10f0.113446407020092f0.13962611556053159f-2.62412314100402e-08f0.1134487614035606f0.078540049493312836f-2.7923498180371101e-08N(saseuler_to_quatssquats_asbsquats_b(sselfsasbsquats_bsquats_a((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pystest_euler_to_quats«s* + cCshdddgdddgdddgg}t|ƒ}ti|ƒ}ti|ƒ}|i ||ƒdS(s< Can we pickle and unpickle the quaternions nicely? f0.0f1.2042771577835081f0.89011788368225098N( saseuler_to_quatssqspicklesdumpss pickled_qsloadss unpickled_qsselfs assertEqual(sselfsasqs pickled_qs unpickled_q((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys test_picklingºs * cCsJtdddƒ}ti|ƒ}ti|ƒ}|i|i |i ƒdS(s- can we pickle/unpickle it properly. f1.2042771577835081f0.0N( s fromEulersqspicklesdumpss pickled_quatsloadss unpickled_qsselfs assertEqualsinternal(sselfs pickled_quatsqs unpickled_q((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys test_pickleÇs cCsDtddddƒ}| }|i|iƒddd d gƒdS(sH tests the inverse is correct. That is the opposite direction. i´f1.0f0.0f180.00000000000003f-1.0N(sfromAXYZsqsq2sselfs assertEqualsAXYZ(sselfsqsq2((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys test_invertÒs(s__name__s __module__s__doc__s _debug_levels_debugs test_lengthstest_fromEulerstest_to_matrix_and_backstest_speed_of_convert_to_matrixs test_slerpstest_euler_to_quatss test_picklings test_pickles test_invert(((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pysTestQuaternionsOs       s__main__( sunittestspicklesrdpyg.util.quaternionsutils quaternionstimeswithin_accuracysTestCasesTestBlasTestExtraFuncssTestQuaternionss__name__smain(sTestQuaternionssTestExtraFuncssunittestsTestBlaswithin_accuracys quaternionstimespickle((sI/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tests/test_quaternion.pys?s   #Œ new_rdpyg/tests/visual_test_map.py0000644000175100017510000000031110076212647017675 0ustar renerene00000000000000 from rdpyg.app import the_app from urdpyg.map import map # We have to initialise pygame ourselves. import pygame pygame.init() a = the_app.TheApp() a.Start() a.Loop() print a.GetFps() a.Stop() new_rdpyg/tests/visual_test_milkviewer4.py0000644000175100017510000000216010076014060021353 0ustar renerene00000000000000 from OpenGL.GL import * from OpenGL.GLU import * from pygame.locals import * import pygame import time, os, sys from rdpyg.app import the_app_gl from urdpyg import milkviewer4 from numeric_gl import * pygame.init() class MilkViewerVisualTest(the_app_gl.TheAppGL): def __init__(self): the_app_gl.TheAppGL.__init__(self) def Load(self): old_cwd = os.path.realpath( os.curdir ) model_path = os.path.join("../", "data", "models", "monkeyluvva") model_path = os.path.join("data", "models") os.chdir(model_path) self.models = [] m = milkviewer4.MilkshapeModel() #m.Load(sys.argv[1]) m.Load("bend.txt") self.models.append(m) os.chdir( old_cwd ) def Display(self): glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glTranslatef(0., 0., -100) #glColor3f(1., 1., 1.) for m in self.models: if not m.IsTextured(): glColor3f(1., 0., 1.) m.Display() if __name__ == "__main__": a = MilkViewerVisualTest() a.Start() a.Loop() new_rdpyg/tests/visual_test_particles.py0000644000175100017510000000353310072756117021120 0ustar renerene00000000000000""" """ import rdpyg.app.the_app_gl as the_app_gl import rdpyg.draw.pyopengl.particles as particles import traceback import time import sys import pygame from pygame.locals import * from OpenGL.GL import * import os pygame.init() class AApp(the_app_gl.TheAppGL): draw_mode = 0 def Display(self): pass self._debug("running display", 4) glClearColor(0.0, 0.0, 0.3, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslate(0., 0., -20) self.particles.DisplayStateBegin() self.particles.Display() self.particles.DisplayStateEnd() def Load(self): """ Place to load stuff. duh! """ self._debug("loading") self.particles = particles.Particles(44) self.particles.Load(file_name = os.path.join("data", "particle.png")) def HandleEvents(self, event_list): for event in event_list: if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): self.Stop() return 0 break if event.type == KEYDOWN and event.key == K_LEFT: pass if event.type == KEYDOWN and event.key == K_RIGHT: pass return 1 def Update(self, elapsed_time): self.particles.Update(elapsed_time) def main(): pygame.key.set_repeat(500, 30) a = AApp() t1 = time.time() a.Start() try: a.Loop() except: traceback.print_exc(sys.stderr) print "Cleaning up." a.Stop() total_time = time.time() - t1 print "time:%s frames:%s frames/time:%s" % (total_time, a.frames, a.frames/total_time) if(__name__ == "__main__"): if len(sys.argv) != 1: if sys.argv[1] == "profile": import profile profile.run('main()', '/tmp/prof') else: main() new_rdpyg/tests/visual_test_paths.py0000644000175100017510000000565110067264052020250 0ustar renerene00000000000000""" """ import rdpyg.util.paths as paths import rdpyg.util.cyclic_list as cyclic_list import rdpyg.app.the_app_gl as the_app_gl import rdpyg.draw.pyopengl.paths as draw_paths import traceback import time import sys import pygame from pygame.locals import * from OpenGL.GL import * pygame.init() class AApp(the_app_gl.TheAppGL): draw_mode = 0 def Display(self): pass self._debug("running display", 4) glClearColor(0.0, 0.0, 0.3, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslate(0., 0., -10) self.DrawPath() def DrawPath(self): if self.draw_mode: draw = draw_paths.draw_path else: draw = draw_paths.draw_path_with_traveler for p in self.paths: draw(p) def Load(self): """ Place to load stuff. duh! """ self._debug("loading") self.paths = cyclic_list.cyclic_list() p = self.paths p.append(paths.Path() ) p[0].SetPoints([[0., 0., 0.], [0., 1., 0.], [1., 1., 0.], [2., 2., 0.], [3., 3., 0.]]) def HandleEvents(self, event_list): for event in event_list: if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): self.Stop() return 0 break if event.type == KEYDOWN and event.key == K_LEFT: pass if event.type == KEYDOWN and event.key == K_RIGHT: pass if event.type == KEYDOWN: p = self.paths.cur() if event.key == K_SPACE: if pygame.key.get_mods() == KMOD_SHIFT: self.paths.prev() else: self.paths.next() if event.key == K_RETURN: if pygame.key.get_mods() == KMOD_SHIFT: for path in self.paths: print path.length() else: pass if event.key == K_BACKSPACE: if self.draw_mode: self.draw_mode = 0 else: self.draw_mode = 1 if event.key == K_a: if pygame.key.get_mods() & KMOD_SHIFT: r = p.Travel(1., 1.) else: r = p.Travel(0.1, 0.1) print r if event.key == K_b: if pygame.key.get_mods() & KMOD_SHIFT: pass else: pass #print self.points return 1 def Update(self, elapsed_time): p = self.paths.cur() p.Travel(0.7, elapsed_time) def main(): pygame.key.set_repeat(500, 30) a = AApp() t1 = time.time() a.Start() try: a.Loop() except: traceback.print_exc(sys.stderr) print "Cleaning up." a.Stop() total_time = time.time() - t1 print "time:%s frames:%s frames/time:%s" % (total_time, a.frames, a.frames/total_time) if(__name__ == "__main__"): if len(sys.argv) != 1: if sys.argv[1] == "profile": import profile profile.run('main()', '/tmp/prof') else: main() new_rdpyg/tools/0000755000175100017510000000000010160166523014122 5ustar renerene00000000000000new_rdpyg/tools/PyFontify.pyc0000644000175100017510000001017510160166523016572 0ustar renerene00000000000000;ò |êÀAc@sœdZdZdkZdkZdkZd„Zdddddd d d d d ddddddddddddddddgZdZdZeed d!ƒd"eed d#ƒZd$Zei ei eƒd%ƒZeed d!ƒd"eed d#ƒZ d&Z e d'Z xeD]Ze ed"Z qWe d( d)e Z e d"ed"e d"eZeieƒZd*ZeieƒZd+ed,„Zd-„ZdS(.s]Module to analyze Python source code; for syntax coloring tools. Interface: tags = fontify(pytext, searchfrom, searchto) The 'pytext' argument is a string containing Python source code. The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext. The returned value is a lists of tuples, formatted like this: [('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ] The tuple contents are always like this: (tag, startindex, endindex, sublist) tag is one of 'keyword', 'string', 'comment' or 'identifier' sublist is not used, hence always None. s0.3.1NcCs titi||ƒ|ƒSdS(N(sstringsjoinssplitswhereswhatswith(swhereswhatswith((sC/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tools/PyFontify.pysreplace"ssdelsfromslambdasreturnsandselifsglobalsnotstrysbreakselsesifsorswhilesclasssexceptsimportspassscontinuesfinallysinsprintsdefsforsissraises#.*sq[^\q ]*\(\\[-ÿ][^\q ]*\)*qsqs's\|s"s‰ qqq [^\q]* \( \( \\[-ÿ] \| q \( \\[-ÿ] \| [^\q] \| q \( \\[-ÿ] \| [^\q] \) \) \) [^\q]* \)* qqq ss\(^\|[^a-zA-Z0-9_."']\)s\(iþÿÿÿs\)s[ ]*[A-Za-z_][A-Za-z_0-9.]*icCsè|tjot|ƒ}nti}ti}ti}ti}g}|i }d} d}d}d} d} |} xinoa||| ƒ} | djp | |joPn|dƒ}| t|ƒ} |d} | djo¿| |jo|dd!}| d} n |d }| d} ||| | tfƒ|d d gjoV||| ƒ} | | jo6|dƒ}| t|ƒ} || | | tfƒqšqÛqw| d jo|| | | tfƒqw||| | tfƒq~W|SdS( Nscommentsstringskeywords identifieriis#'"iÿÿÿÿsdefsclasss#(ssearchtosNoneslenspytextsmatchREssearchsgroupsidREsidSearchsidGroupstagssappends tags_appends commentTags stringTags keywordTags identifierTagsstarts searchfromsendsmatchsc(spytexts searchfromssearchtos keywordTagssearchsidSearchsgroupstagss stringTagsendsstarts identifierTagscs commentTags tags_appendsidGroupsmatch((sC/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tools/PyFontify.pysfontify_sN               " cCs`t|ƒ}|iƒ}|iƒt|ƒ}x+|D]#\}}}}|G|||! GHq5WdS(N( sopenspathsfsreadstextsclosesfontifystagsstagsstartsendssublist(spathsendstagsstextsfssublistsstartstag((sC/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tools/PyFontify.pystest“s    (s__doc__s __version__sstringsregexsreplaces keywordsLists commentPatspatsquotePatsjoinssplitstripleQuotePats nonKeyPatskeyPatskeywordsmatchPatscompilesmatchREsidKeyPatsidREsNonesfontifystest(sregexsfontifysmatchREspatsstringskeywordsquotePatsidREsreplaces nonKeyPats commentPatskeyPatsidKeyPatstests keywordsListsmatchPats __version__stripleQuotePat((sC/mnt/hdc3/home/rene/dev/mystuff/python/new_rdpyg/tools/PyFontify.pys?s.  T && 4new_rdpyg/tools/PyFontify.py0000644000175100017510000001033210160165174016423 0ustar renerene00000000000000"""Module to analyze Python source code; for syntax coloring tools. Interface: tags = fontify(pytext, searchfrom, searchto) The 'pytext' argument is a string containing Python source code. The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext. The returned value is a lists of tuples, formatted like this: [('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ] The tuple contents are always like this: (tag, startindex, endindex, sublist) tag is one of 'keyword', 'string', 'comment' or 'identifier' sublist is not used, hence always None. """ # Based on FontText.py by Mitchell S. Chapman, # which was modified by Zachary Roadhouse, # then un-Tk'd by Just van Rossum. # Many thanks for regular expression debugging & authoring are due to: # Tim (the-incredib-ly y'rs) Peters and Cristian Tismer # So, who owns the copyright? ;-) How about this: # Copyright 1996-1997: # Mitchell S. Chapman, # Zachary Roadhouse, # Tim Peters, # Just van Rossum __version__ = "0.3.1" import string, regex # First a little helper, since I don't like to repeat things. (Tismer speaking) import string def replace(where, what, with): return string.join(string.split(where, what), with) # This list of keywords is taken from ref/node13.html of the # Python 1.3 HTML documentation. ("access" is intentionally omitted.) keywordsList = [ "del", "from", "lambda", "return", "and", "elif", "global", "not", "try", "break", "else", "if", "or", "while", "class", "except", "import", "pass", "continue", "finally", "in", "print", "def", "for", "is", "raise"] # Build up a regular expression which will match anything # interesting, including multi-line triple-quoted strings. commentPat = "#.*" pat = "q[^\q\n]*\(\\\\[\000-\377][^\q\n]*\)*q" quotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"') # Way to go, Tim! pat = """ qqq [^\\q]* \( \( \\\\[\000-\377] \| q \( \\\\[\000-\377] \| [^\\q] \| q \( \\\\[\000-\377] \| [^\\q] \) \) \) [^\\q]* \)* qqq """ pat = string.join(string.split(pat), '') # get rid of whitespace tripleQuotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"') # Build up a regular expression which matches all and only # Python keywords. This will let us skip the uninteresting # identifier references. # nonKeyPat identifies characters which may legally precede # a keyword pattern. nonKeyPat = "\(^\|[^a-zA-Z0-9_.\"']\)" keyPat = nonKeyPat + "\(" for keyword in keywordsList: keyPat = keyPat + keyword + "\|" keyPat = keyPat[:-2] + "\)" + nonKeyPat matchPat = keyPat + "\|" + commentPat + "\|" + tripleQuotePat + "\|" + quotePat matchRE = regex.compile(matchPat) idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*" # Ident w. leading whitespace. idRE = regex.compile(idKeyPat) def fontify(pytext, searchfrom = 0, searchto = None): if searchto is None: searchto = len(pytext) # Cache a few attributes for quicker reference. search = matchRE.search group = matchRE.group idSearch = idRE.search idGroup = idRE.group tags = [] tags_append = tags.append commentTag = 'comment' stringTag = 'string' keywordTag = 'keyword' identifierTag = 'identifier' start = 0 end = searchfrom while 1: start = search(pytext, end) if start < 0 or start >= searchto: break # EXIT LOOP match = group(0) end = start + len(match) c = match[0] if c not in "#'\"": # Must have matched a keyword. if start <> searchfrom: # there's still a redundant char before and after it, strip! match = match[1:-1] start = start + 1 else: # this is the first keyword in the text. # Only a space at the end. match = match[:-1] end = end - 1 tags_append((keywordTag, start, end, None)) # If this was a defining keyword, look ahead to the # following identifier. if match in ["def", "class"]: start = idSearch(pytext, end) if start == end: match = idGroup(0) end = start + len(match) tags_append((identifierTag, start, end, None)) elif c == "#": tags_append((commentTag, start, end, None)) else: tags_append((stringTag, start, end, None)) return tags def test(path): f = open(path) text = f.read() f.close() tags = fontify(text) for tag, start, end, sublist in tags: print tag, `text[start:end]` new_rdpyg/tools/py2html.py0000755000175100017510000004114010160165163016075 0ustar renerene00000000000000#!/usr/bin/python -u """ Python Highlighter Version: 0.8 py2html.py [options] files... options: -h print help - read from stdin, write to stdout -stdout read from files, write to stdout -files read from files, write to filename+'.html' (default) -format: html output XHTML page (default) rawhtml output pure XHTML (without headers, titles, etc.) -mode: color output in color (default) mono output b/w (for printing) -title:Title use 'Title' as title of the generated page -bgcolor:color use color as background-color for page -header:file use contents of file as header -footer:file use contents of file as footer -URL replace all occurances of 'URL: link' with 'link'; this is always enabled in CGI mode -v verbose Takes the input, assuming it is Python code and formats it into colored XHTML. When called without parameters the script tries to work in CGI mode. It looks for a field 'script=URL' and tries to use that URL as input file. If it can't find this field, the path info (the part of the URL following the CGI script name) is tried. In case no host is given, the host where the CGI script lives and HTTP are used. * Uses Just van Rossum's PyFontify version 0.3 to tag Python scripts. You can get it via his homepage on starship: URL: http://starship.python.net/crew/just """ __comments__ = """ The following snippet is a small shell script I use for viewing Python scripts via less on Unix: pyless: #!/bin/sh # Browse pretty printed Python code using ANSI codes for highlighting py2html -stdout -format:ansi -mode:color $* | less -r History: 0.8: Added patch by Patrick Lynch to have py2html.py use style sheets for markup 0.7: Added patch by Ville Skyttä to make py2html.py output valid XHTML. 0.6: Fixed a bug in .escape_html(); thanks to Vespe Savikko for finding this one. 0.5: Added a few suggestions by Kevin Ng to make the CGI version a little more robust. """ __copyright__ = """\ Copyright (c) 1998-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com Copyright (c) 2000-2002, eGenix.com Software GmbH; mailto:info@egenix.com Distributed under the terms and conditions of the eGenix.com Public License. See http://www.egenix.com/files/python/mxLicense.html for details, or contact the author. All Rights Reserved.\ """ __version__ = '0.8' __cgifooter__ = ('\n
# code highlighted using py2html.py '
                 'version %s
\n' % __version__) import sys,string,re # Adjust path so that PyFontify is found... sys.path.append('.') ### Constants # URL of the input form the user is redirected to in case no script=xxx # form field is given. The URL *must* be absolute. Leave blank to # have the script issue an error instead. INPUT_FORM = 'http://www.lemburg.com/files/python/SoftwareDescriptions.html#py2html.py' # HTML DOCTYPE and XML namespace HTML_DOCTYPE = '' HTML_XMLNS = ' xmlns="http://www.w3.org/1999/xhtml"' ### Helpers def fileio(file, mode='rb', data=None, close=0): if type(file) == type(''): f = open(file,mode) close = 1 else: f = file if data: f.write(data) else: data = f.read() if close: f.close() return data ### Converter class class PrettyPrint: """ generic Pretty Printer class * supports tagging Python scripts in the following ways: # format/mode | color mono # -------------------------- # rawhtml | x x (HTML without headers, etc.) # html | x x (a HTML page with HEAD&BODY:) # ansi | x x (with Ansi-escape sequences) * interfaces: file_filter -- takes two files: input & output (may be stdin/stdout) filter -- takes a string and returns the highlighted version * to create an instance use: c = PrettyPrint(tagfct,format,mode) where format and mode must be strings according to the above table if you plan to use PyFontify.fontify as tagfct * the tagfct has to take one argument, text, and return a taglist (format: [(id,left,right,sublist),...], where id is the "name" given to the slice left:right in text and sublist is a taglist for tags inside the slice or None) """ # misc settings title = '' bgcolor = '#FFFFFF' css = '' header = '' footer = '' replace_URLs = 0 # formats to be used formats = {} def __init__(self,tagfct=None,format='html',mode='color'): self.tag = tagfct self.set_mode = getattr(self,'set_mode_%s_%s' % (format, mode)) self.filter = getattr(self,'filter_%s' % format) def file_filter(self,infile,outfile): self.set_mode() text = fileio(infile,'r') if type(infile) == type('') and self.title == '': self.title = infile fileio(outfile,'w',self.filter(text)) ### Set pre- and postfixes for formats & modes # # These methods must set self.formats to a dictionary having # an entry for every tag returned by the tagging function. # # The format used is simple: # tag:(prefix,postfix) # where prefix and postfix are either strings or callable objects, # that return a string (they are called with the matching tag text # as only parameter). prefix is inserted in front of the tag, postfix # is inserted right after the tag. def set_mode_html_color(self): self.css = """ """ % self.bgcolor self.formats = { 'all':('
','
'), 'comment':('',''), 'keyword':('',''), 'parameter':('',''), 'identifier':( lambda x,strip=string.strip: '' % (strip(x)), ''), 'string':('','') } set_mode_rawhtml_color = set_mode_html_color def set_mode_html_mono(self): self.css = """ """ % self.bgcolor self.formats = { 'all':('
','
'), 'comment':('',''), 'keyword':( '',''), 'parameter':('',''), 'identifier':( lambda x,strip=string.strip: '' % (strip(x)), ''), 'string':('','') } set_mode_rawhtml_mono = set_mode_html_mono def set_mode_ansi_mono(self): self.formats = { 'all':('',''), 'comment':('\033[2m','\033[m'), 'keyword':('\033[4m','\033[m'), 'parameter':('',''), 'identifier':('\033[1m','\033[m'), 'string':('','') } def set_mode_ansi_color(self): self.formats = { 'all':('',''), 'comment':('\033[34;2m','\033[m'), 'keyword':('\033[1;34m','\033[m'), 'parameter':('',''), 'identifier':('\033[1;31m','\033[m'), 'string':('\033[32;2m','\033[m') } ### Filters for Python scripts given as string def escape_html(self,text): t = (('&','&'),('<','<'),('>','>')) for x,y in t: text = string.join(string.split(text,x),y) return text def filter_html(self,text): output = self.fontify(self.escape_html(text)) if self.replace_URLs: output = re.sub('URL:([ \t]+)([^ \n\r<]+)', 'URL:\\1\\2',output) html = """%s %s %s %s %s %s \n"""%(HTML_DOCTYPE, HTML_XMLNS, self.title, self.css, self.header, output, self.footer) return html def filter_rawhtml(self,text): output = self.fontify(self.escape_html(text)) if self.replace_URLs: output = re.sub('URL:([ \t]+)([^ \n\r<]+)', 'URL:\\1\\2',output) return self.header + output + self.footer def filter_ansi(self,text): output = self.fontify(text) return self.header + output + self.footer ### Fontify engine def fontify(self,pytext): # parse taglist = self.tag(pytext) # prepend special 'all' tag: taglist[:0] = [('all',0,len(pytext),None)] # prepare splitting splits = [] addsplits(splits,pytext,self.formats,taglist) # do splitting & inserting splits.sort() l = [] li = 0 for ri,dummy,insert in splits: if ri > li: l.append(pytext[li:ri]) l.append(insert) li = ri if li < len(pytext): l.append(pytext[li:]) return string.join(l,'') def addsplits(splits,text,formats,taglist): """ Helper for .fontify() """ for id,left,right,sublist in taglist: try: pre,post = formats[id] except KeyError: # sys.stderr.write('Warning: no format for %s specified\n'%repr(id)) pre,post = '','' if type(pre) != type(''): pre = pre(text[left:right]) if type(post) != type(''): post = post(text[left:right]) # len(splits) is a dummy used to make sorting stable splits.append((left,len(splits),pre)) if sublist: addsplits(splits,text,formats,sublist) splits.append((right,len(splits),post)) def write_html_error(titel,text): print """\ %s%s

%s

%s """ % (HTML_DOCTYPE,HTML_XMLNS,titel,titel,text) def redirect_to(url): sys.stdout.write('Content-Type: text/html\r\n') sys.stdout.write('Status: 302\r\n') sys.stdout.write('Location: %s\r\n\r\n' % url) print """ %s 302 Moved Temporarily

302 Moved Temporarily

The document has moved to %s.

""" % (HTML_DOCTYPE,HTML_XMLNS,url,url) def main(cmdline): """ main(cmdline) -- process cmdline as if it were sys.argv """ # parse options/files options = [] optvalues = {} for o in cmdline[1:]: if o[0] == '-': if ':' in o: k,v = tuple(string.split(o,':')) optvalues[k] = v options.append(k) else: options.append(o) else: break files = cmdline[len(options)+1:] ### create converting object # load fontifier if '-marcs' in options: # use mxTextTool's tagging engine as fontifier from mx.TextTools import tag from mx.TextTools.Examples.Python import python_script tagfct = lambda text,tag=tag,pytable=python_script: \ tag(text,pytable)[1] print "Py2HTML: using Marc's tagging engine" else: # load Just's fontifier try: import PyFontify if PyFontify.__version__ < '0.3': raise ValueError tagfct = PyFontify.fontify except: print """ Sorry, but this script needs the PyFontify.py module version 0.3; You can download it from Just's homepage at URL: http://starship.python.net/crew/just """ sys.exit() if '-format' in options: format = optvalues['-format'] else: # use default format = 'html' if '-mode' in options: mode = optvalues['-mode'] else: # use default mode = 'color' c = PrettyPrint(tagfct,format,mode) convert = c.file_filter ### start working if '-title' in options: c.title = optvalues['-title'] if '-bgcolor' in options: c.bgcolor = optvalues['-bgcolor'] if '-header' in options: try: f = open(optvalues['-header']) c.header = f.read() f.close() except IOError: if verbose: print 'IOError: header file not found' if '-footer' in options: try: f = open(optvalues['-footer']) c.footer = f.read() f.close() except IOError: if verbose: print 'IOError: footer file not found' if '-URL' in options: c.replace_URLs = 1 if '-' in options: convert(sys.stdin,sys.stdout) sys.exit() if '-h' in options: print __doc__ sys.exit() if len(files) == 0: # Turn URL processing on c.replace_URLs = 1 # Try CGI processing... import cgi,urllib,urlparse,os form = cgi.FieldStorage() if not form.has_key('script'): # Ok, then try pathinfo if not os.environ.has_key('PATH_INFO'): if INPUT_FORM: redirect_to(INPUT_FORM) else: sys.stdout.write('Content-Type: text/html\r\n\r\n') write_html_error('Missing Parameter', 'Missing script=URL field in request') sys.exit(1) url = os.environ['PATH_INFO'][1:] # skip the leading slash else: url = form['script'].value sys.stdout.write('Content-Type: text/html\r\n\r\n') scheme, host, path, params, query, frag = urlparse.urlparse(url) if not host: scheme = 'http' if os.environ.has_key('HTTP_HOST'): host = os.environ['HTTP_HOST'] else: host = 'localhost' url = urlparse.urlunparse((scheme, host, path, params, query, frag)) #print url; sys.exit() network = urllib.URLopener() try: tempfile,headers = network.retrieve(url) except IOError,reason: write_html_error('Error opening "%s"' % url, 'The given URL could not be opened. Reason: %s' %\ str(reason)) sys.exit(1) f = open(tempfile,'rb') c.title = url c.footer = __cgifooter__ convert(f,sys.stdout) f.close() network.close() sys.exit() if '-stdout' in options: filebreak = '-'*72 for f in files: try: if len(files) > 1: print filebreak print 'File:',f print filebreak convert(f,sys.stdout) except IOError: pass else: verbose = ('-v' in options) if verbose: print 'Py2HTML: working on', for f in files: try: if verbose: print f, convert(f,f+'.html') except IOError: if verbose: print '(IOError!)', if verbose: print print 'Done.' if __name__=='__main__': main(sys.argv) new_rdpyg/urdpyg/0000755000175100017510000000000010160165014014266 5ustar renerene00000000000000new_rdpyg/urdpyg/converters/0002755000175100017510000000000010076016113016463 5ustar renerene00000000000000new_rdpyg/urdpyg/converters/cal3d_exporter.py0000644000175100017510000001236507743744517022007 0ustar renerene00000000000000 from math import cos, sin import os, sys, time import quaternion import py3d.milk_skeleton def strl(a_list): """ makes each element in a list a string. """ return map(str, a_list) def ms3d_euler__to__cal3d_quat(x,y,z): """ returns a quat suitable for cal3d ie a list [x,y,z,w]. """ r_quaternion = [0,0,0,0] cosx = cos(x * 0.5) cosy = cos(y * 0.5) cosz = cos(z * 0.5) sinx = sin(x * 0.5) siny = sin(y * 0.5) sinz = sin(z * 0.5) cosc = cosx * cosz; coss = cosx * sinz; sinc = sinx * cosz; sins = sinx * sinz; r_quaternion[0] = (cosy * sinc) - (siny * coss) r_quaternion[1] = (cosy * sins) + (siny * cosc) r_quaternion[2] = (cosy * coss) - (siny * sinc) # why do we have to negate this??? # hmmm ... "milkshape style"... well it works this way =) r_quaternion[3] = -((cosy * cosc) + (siny * sins)) return r_quaternion def test_some_shit(): a_milk_rotation = [-0.00014899999999999999, -0.046429999999999999, -0.017059000000000001] q = ms3d_euler__to__cal3d_quat(*a_milk_rotation) print "w,x,y,z",q q2 = quaternion.fromEuler(*a_milk_rotation) print "x,y,z,w", q2.internal milk_as_angles = map(quaternion.radians_to_angle, a_milk_rotation) q3 = ms3d_euler__to__cal3d_quat(*milk_as_angles) print "x,y,z,w",q3 q_forquat = [q[1], q[2], q[3], q[0]] q3_forquat = [q3[1], q3[2], q3[3], q3[0]] q4 = quaternion.Quaternion(q_forquat) q5 = quaternion.Quaternion(q3_forquat) print q4.internal print "q2", q2.AXYZ() print "q4", q4.AXYZ() print "q5", q5.AXYZ() # Conclusion. What the fuck!?!?? weirdro quaternions. # Going to need to test somewhat. class Cal3dBone: """ a class representing a cal3d bone. """ def __init__(self): """ """ self.bone_id = 0 self.name = "initial_bone_name" self.translation = [-14440., -14440., -14440.] # rotation is a quaternion. self.rotation = [-24440., -24440.,-24440., -24441.] self.local_translation = [-34440., -34440., -34440.] # local rotation is a quaternion. self.local_rotation = [-44440., -44440.,-44440., -44441.] # an index into which bone is the parent. # -1 means there is no parent to this self.parent_id = -54441 # a list of child ids for this bone. They are ints. self.child_ids = [] def to_xml(self, indentation=4): """ returns a string of xml representing this bone. """ indent_text = indentation * " " start_bone = """"""%(self.bone_id, self.name, len(self.child_ids)) start_bone = indent_text + start_bone trans = "%s" % (" ".join( strl(self.translation) )) rot = "%s" % (" ".join( strl(self.rotation) )) local_trans = "%s" % (" ".join( strl(self.local_translation) )) local_rot = "%s" % (" ".join( strl(self.local_rotation) )) parent_id = "%s" % (self.parent_id) child_ids = map(lambda x:"%s" %x, self.child_ids) bits = [trans, rot, local_trans, local_rot, parent_id] bits.extend(child_ids) print bits bits_text = "\n".join(map(lambda x: indent_text*2 + x, bits)) end_bone = indent_text + "" return "\n".join([start_bone, bits_text, end_bone]) class Cal3dSkeleton: def __init__(self): self.bones = [] def to_xml(self, indentation=0): """ returns a string with the xml for the cal3d skeleton. """ indent = indentation * " " start_skeleton = indent + """""" % len(self.bones) bones = "\n".join( map(lambda x: x.to_xml(), self.bones) ) end_skeleton = indent + "" return "\n".join([start_skeleton, bones, end_skeleton]) def read_milk( file_name ): import ms3d_ascii_importer data = ms3d_ascii_importer.convert_milkshape( file_name ) #print dir(data['bones'][0]) cal3d_skeleton = Cal3dSkeleton() bone_heirarchy = py3d.milk_skeleton.BoneHeirarchy(data['bones']) for milk_bone in data['bones']: cb = Cal3dBone() cb.name = milk_bone.name cb.bone_id = bone_heirarchy.bone_name_to_idx[milk_bone.name] cb.child_ids = bone_heirarchy.GetChildren_idx(milk_bone.name) if not bone_heirarchy.bone_name_to_idx.has_key( milk_bone.parent_name ): print "milk_bone.parent_name :%s:" % milk_bone.parent_name if milk_bone.parent_name == "": # has no parent. cb.parent_id = -1 else: cb.parent_id = bone_heirarchy.bone_name_to_idx[milk_bone.parent_name] cal3d_skeleton.bones.append(cb) print cal3d_skeleton.to_xml() if __name__ == "__main__": read_milk(sys.argv[1]) #test_some_shit() new_rdpyg/urdpyg/converters/__init__.py0000644000175100017510000000000007743744517020607 0ustar renerene00000000000000new_rdpyg/urdpyg/converters/ms3d_ascii_exporter.py0000644000175100017510000000214207743744517023027 0ustar renerene00000000000000from middle_obj import * #from features import import string from string import split from string import join import re from monkey import * """ Milkshape 3d ascii format notes: Basic outline of format: --- Start of file --- Frames: Frame: Meshes: Materials: Bones: --- End of file --- A material index of -1 means no material. """ def export_milk( points, indices, normals, out_file ): """ """ fw = out_file.write fw("// MilkShape 3D ASCII\n\n") fw("Frames: 30\n") fw("Frame: 1\n\n") fw("Meshes: 1\n") fw('"Bla" 0 -1\n') # num verts fw("%s\n" % len(points) ) for p in points: fw("0 %s %s %s 1.0 1.0 0\n" % (p[0], p[1], p[2]) ) # num normals fw("%s\n" % len(normals) ) for n in normals: fw("%s %s %s\n" % (n[0], n[1], n[2]) ) # num faces fw("%s\n" % len(indices) ) for i in indices: fw("0 %s %s %s 0 0 0\n" % (i[0], i[1], i[2]) ) fw("\nMaterials: 0\n\nBones: 0\n") f = open("bla2", "w") export_milk( points, indices, normals, f ) f.close() new_rdpyg/urdpyg/converters/md2_importer.py0000644000175100017510000002556007743744517021475 0ustar renerene00000000000000""" Copyright (C) 2002, 2003 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ """ For reading md2 files. A description of the MD2 file format can be found here: http://www.ugrad.cs.jhu.edu/~dansch/md2/ """ import array import struct import Numeric N = Numeric # some maximums for the md2 format. MD2_MAX_TRIANGLES = 4096 MD2_MAX_VERTICES = 2048 MD2_MAX_TEXCOORDS = 2048 MD2_MAX_FRAMES = 512 MD2_MAX_SKINS = 32 MD2_MAX_FRAMESIZE = (MD2_MAX_VERTICES * 4 + 128) tMd2Header = { "magic":0, # Used to identify the file. "version":0, # Version number of the file (Must be 8). "skinWidth":0, # Skin width in pixels. "skinHeight":0, # Skin height in pixels. "frameSize":0, # Size in bytes the frames are. "numSkins":0, # Number of skins associated with the model. "numVertices":0, # Number of vertices (constant for each frame). "numTexCoords":0, # Number of texture coordinates. "numTriangles":0, # Number of faces (polygons). "numGlCommands":0, # Number of gl commands. "numFrames":0, # Number of animation frames. "offsetSkins":0, # Offset in the file for the skin data. "offsetTexCoords":0, # Offset in the file for the texture data. "offsetTriangles":0, # Offset in the file for the face data. "offsetFrames":0, # Offset in the file for the frames data. "offsetGlCommands":0, # Offset in the file for the gl commands data. "offsetEnd":0} # End of the file offset. def from_c_string(c_string): """ Returns a python string from a c string. Ie it looks for a null character in the string and returns everything before that. """ to_return = [] for x in c_string: if ord(x) == 0: return "".join(to_return) else: to_return.append(x) return "".join(to_return) class Md2Model: def __init__(self, md2_file_name = None, md2_texture_file_name = None): """ """ if md2_file_name == None and md2_texture_file_name == None: # Don't open anything! pass else: # open the file name given. self.f = open(md2_file_name) self.md2_file_name = md2_file_name self.md2_texture_file_name = md2_texture_file_name self.image_name = md2_texture_file_name #tMd2Header m_Header; // The header data #tMd2Skin *m_pSkins; // The skin data #tMd2TexCoord *m_pTexCoords; // The texture coordinates #tMd2Face *m_pTriangles; // Face index information #tMd2Frame *m_pFrames; // The frames of animation (vertices) # List of skin strings. self.skins = [] # The texture coordinates. string of shorts, u,v self.tex_coords = "" # Face index information. # [[vertexIndices,textureIndices], ...] # [[[0,0,0], [0,0,0]], ...] self.triangles = [] #vertex_indices = [] #texture_indices = [] # The frames of animation (vertices) # [[frame_name, vertices, normals], ...] self.frames = [] self.header = {} # copy the header as 0. self.header.update(tMd2Header) def Load(self, md2_file_name = None, md2_texture_file_name = None): if md2_file_name == None and md2_texture_file_name == None: # Use the internal names. if self.md2_file_name == None: raise "Object has no file to load." pass else: # Set self.md2_file_name = md2_file_name self.md2_texture_file_name = md2_texture_file_name self.f = open(self.md2_file_name) self._ReadHeader() if self.header["version"] != 8: raise "file corrupt, version is not 8" self._ReadMd2Data() def _ReadMd2Data(self, md2_file_name = None, md2_texture_file_name = None): """ """ if md2_file_name == None and md2_texture_file_name == None: # Use the opened file. f = self.f else: # open the file name given. f = open(md2_file_name) header = self.header # Next, we start reading in the data by seeking to our skin names offset. f.seek(header['offsetSkins']) # Depending on the skin count, we read in each skin for this model. s = f.read(64 * header['numSkins']) self.skins = [s[x:x+64] for x in range(0,len(s),64)] # Seek to the texture coordinates. f.seek(header['offsetTexCoords']) # Read in all the texture coordinates in one fell swoop self.texcoords = f.read(2* 2 * header['numTexCoords']) tcoords = struct.unpack('%sh' % (header['numTexCoords'] *2), self.texcoords) self.texcoords= Numeric.array(tcoords, 's') del tcoords # Move the file pointer to the triangles/face data offset f.seek(header['offsetTriangles']) # Read in the face data for each triangle (vertex and texCoord indices) self.triangles = f.read(12 * header['numTriangles']) tris = struct.unpack('%sh' % (header['numTriangles'] * 2 * 3), self.triangles) # vertex_indices 3 shorts, texture_indices 3 shorts. triangle_data = Numeric.array(tris, 's') del tris triangle_data = Numeric.reshape(triangle_data, (len(triangle_data) /3, 3)).astype('s') # make two seperate arrays. One for vertex_indices, other for texture_indices. # every second set of three. self.vertex_indices = triangle_data[::2] self.texture_indices= triangle_data[1::2] # Move the file pointer to the vertices (frames) f.seek(header['offsetFrames']) # Read in the first frame of animation self.frames = f.read(header['frameSize']) # I think the first part of this is: # 12 bytes, 0 - 11, float scale[3] # 12 bytes, 12 - 23, float translate[3] # 16 bytes, 24 - 39, char name[16] scale = Numeric.array(struct.unpack('fff', self.frames[0:12]), 'f') translate = Numeric.array(struct.unpack('fff', self.frames[12:24]), 'f') print scale print translate frame_name = from_c_string(self.frames[24:39]) # Make an array of the bytes. byte vertex[3]; byte lightNormalIndex; # vertex_light_data = Numeric.array(self.frames[40:], 'b') print vertex_light_data[0], "vertex_light_data" print vertex_light_data[1], "vertex_light_data" print vertex_light_data[2], "vertex_light_data" print vertex_light_data[3], "vertex_light_data" vertex_light_data = Numeric.reshape(vertex_light_data, (len(vertex_light_data)/4, 4)).astype('b') # Need to seperate the lightNormalIndex from the rest of the shite. # that is get rid of every 4th element. # We won't use the lightNormalIndex, as that requires a 1.7MB quake2 specific normals file. # Make a new array with 3 elements instead of 4. vertex_data = Numeric.zeros((len(vertex_light_data),3), 'f') # loop over vertex_data, and put the first 3 elems in there. #TODO: there has to be a faster way to do this... # Maybe the code I'm copying from is wrong. count = 0 print vertex_light_data[0], "vertex_light_data" for vert_light in vertex_light_data: # we swap the second, and third elem to match opengls coord system. vertex_data[count] = Numeric.array([vert_light[0] * scale[0] + translate[0], vert_light[2] * scale[2] + + translate[2], -1 * (vert_light[1] * scale[1] + translate[1])], 'f') count += 1 # Multiply the array by the scale, then add the translate to the array. # This will transform it into an array of floats. #vertex_floats = vertex_data * scale #vertex_floats = vertex_data + translate #print vertex_floats[0] print vertex_data[0] print len(vertex_data) print vertex_data[156] print vertex_data[476] # We have at the end. #TODO: read in the rest of the frames. # Numeric array of floats, there will be one array for each frame. self.vertex_data = vertex_data # Numeric array of shorts. self.vertex_indices # Numeric array of shorts. self.texture_indices frame_name # a numeric array of shorts, in range 0 - 255. self.texcoords = self._ConvertTexcoords(self.texcoords,self.texture_indices, header['skinHeight'], header['skinWidth'] ) # TODO: what is it? maybe need to convert cstrings to python strings. self.skins def _ConvertTexcoords(self, texcoords, texture_indices, w, h): """ Flips the v coordinate part, and makes a new array based on the texture indices. texcoords - texture_indices - """ texcoords = Numeric.reshape(texcoords, (len(texcoords) /2, 2)).astype('f') # flip the v coordinate. count = 0 for u,v in texcoords: texcoords[count] = [u/w, 1 - v/h] #texcoords[count] = [u/w, (v/h)] #print texcoords[count] count += 1 # allocate a new array with the length of the indices * 2. print len(texture_indices) new_texcoords= Numeric.zeros((len(texture_indices) * 3,2), 'f') max_xyz = 0 count = 0 for x,y,z in texture_indices: new_texcoords[count] = texcoords[x] new_texcoords[count+1] = texcoords[y] new_texcoords[count+2] = texcoords[z] print new_texcoords[count] print new_texcoords[count+1] print new_texcoords[count+2] count += 3 return new_texcoords def _ReadHeader(self, md2_file_name = None, md2_texture_file_name = None): """ """ if md2_file_name == None and md2_texture_file_name == None: # Use the opened file, if good. if hasattr(self, 'f'): f = self.f else: f = open(self.md2_file_name) else: # open the file name given. f = open(md2_file_name) f.seek(0) header_data = array.array('i', f.read(17 * 4) ) h = self.header h["magic"] = header_data[0] h["version"] = header_data[1] h["skinWidth"] = header_data[2] h["skinHeight"] = header_data[3] h["frameSize"] = header_data[4] h["numSkins"] = header_data[5] h["numVertices"] = header_data[6] h["numTexCoords"] = header_data[7] h["numTriangles"] = header_data[8] h["numGlCommands"] = header_data[9] h["numFrames"] = header_data[10] h["offsetSkins"] = header_data[11] h["offsetTexCoords"] = header_data[12] h["offsetTriangles"] = header_data[13] h["offsetFrames"] = header_data[14] h["offsetGlCommands"] = header_data[15] h["offsetEnd"] = header_data[16] return h new_rdpyg/urdpyg/converters/middle_obj.py0000644000175100017510000002457207743744517021164 0ustar renerene00000000000000""" Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ """ A scene graph which will contain all sorts of information about 3d scenes. Advantages this method will give you. - Allow importers and exporters to be written independantly. Just write an importer and you can take advantage of all the exporters. - Able to choose a disk based, or memory based conversion. - Don't have to support all of a 3d format, can support only parts of a format. This is necessary as development nearly always happens incrementally with 3d format converters. This means importers and exporters will have to specify which elements that they support. - Extensibility: the system is designed to be extensible. So that if new 3d formats are added they will not affect the old ones. This is done by having all importers and exporters contain a list of features which they support. Here is an example of how it would all work: First the importer and exporter(s) will tell the middle object which features that they support(or are interested in). The importer will read in what of the 3d format it understands, then pass the 3d data onto the middle object. Also passing on the features which the importer has imported. - Support multiple exporters being used at once. But only one importer being used at once. Multiple exporters will be useful to save having to do the import step multiple times when exporting to lots of formats. - Each exporter will be responsible for setting which features that it wants to export. That way it is possible to - A feature can be any sort of 3D data. We want to support as much different data as possible. Here is a list of 3d data that I can think of: = mesh data, = vertex, face lists. = vertex shading information. = per vertex, pre face UV information. = Scene graph information( this will be hard ). - It could be a graph of indicies to other objects. Maybe a tuple of (feature_name, index into list) - Not sure how inheritance will be handled. = bezier lines, and patches. = nurb lines and patches. = Texture mapping info. = cameras = lights (point, spot, omni, ambient). = image maps for terrain. = Material information. - color maps. - animations. - bump maps. - alpha maps. - smoothing. - specularity. - May provide a heap of helper functions, to help make converting the data easier. Providing different views of the intermediate data. eg. converting a mesh made up of 4, and 3 sided polygons into a mesh made up of only 3 side polygons. Here is a list of helpers: = ngons to triangles. = curve patches to triangles. = per face, to per vertex uv mapping conversions. = scaling. = rotation. = converting which coordinates are up, sideways and depth. - May need to implement a disk based dictionary, and a disk based list. As the shelf object which uses a database as a backend is pretty lame. It can only store objects of a certain size. Also they are only dicts, not lists. - Perhaps to save on memory, we could write certain features to disk(using pickle) whilst the other data is being converted. - Importers, and exporters don't necessarily need to read or write to files. eg. They may comunicate directly with a 3d editor, or a game engine. They could use a COM, CORBA, or xml rpc interface. - Should try and make use of other converter libraries, eg lib3ds. - importers and exporters should be able to do things like eg. only export frame 34 of the animation. Probably have to expand on the feature passing idea for this. Diagram of how feature information moves around: user --wanted exporters--> middle_obj user --wanted features for exporters--> middle_obj user --wanted features--> middle_obj importer --supported features--> middle_obj middle_obj --features to export--> exporters - Reduce the number of unnessesary calculations. One way to do this is to have the importers and exporters know which way certain things are defined. Eg. the coordinate systems: in one format x may be depth, and in another format x may be depth but comming into the screen. ei. if two formats both use z+ as depth then there is no need to transform the coordinates when putting them into the middle object. NOTE: supplying all different types of stores in the middle object should not be mandatory. There will be a default for the middle object which all importers should support. NOTE: This information would be stored with each feature. Eg, Meshes.Triangles.PointOrder.Supported.Value = ["clockwise", "anticlockwize"] Meshes.Triangles.PointOrder.Default.Value = "clockwise" - If Conversions have to be done on data, make sure that the conversions also change other data which is dependant on it. The only example of this that I can think of at the moment is Indexes to things. eg. face list index to a heap of points. Maybe we should keep some dependancy information somewhere. Think about this some more. Maybe too much effort. - Keep documentation of all the features. Documentation of every feature will be kept in a master feature list. The master feature list will be generated from the importers,exporters, and the middle object. The middle object will be updated sporadically when new features come around. The documentation of the features will also be taken from - Keep a central repository of all the different features. Supply a report of which importers/exporters support what. These need to be automated. The feature objects of a importer/exporter/middle_object are python objects which contain __doc__ strings. - With (importers/exporters) and the middle object, the feature objects are used differently. The middle object uses features to store not only the documentation on the various features, but also data itself. - Make some test importers, and exporters. A test importer will fill up the middle object with what ever data the exporter asks of it. A test exporter will ask the middle object for some data to export. If we can get an test exporter, and importer which supports _ALL_ the features, then testing will be easier, and there will be some base implementations for people to look at. - A validate format function for each format may be useful. One function could be used to validate the import and export plugins. It is optional to implement this. Quality plugins implement this ;). - A DoValidation() method for importers and exporters may be useful. This way an importer/exporter has the option of validating the data or not. Not validating the data may be a speed increase. Both in speeding up the conversion and speeding up the writing of the plugin. Validating data during the conversion may also be faster than doing the validation as a seperate pass. It is optional to implement this. Quality plugins implement this ;). """ class MiddleObject: def __init__(self): """ """ # A dictionary of features self.features = {} def AddImporter(self, importer): """ importer - an object used to import 3d data into the middle object. """ def AddExporter(self, exporter): """ exporter - an object used to export 3d data from the middle object. """ def SendFeatureRequestsToImporter(self): """ Goes through the exporters and gathers a set of features which need to be sent to the importer. """ class Importer: """ Used for importing 3d data into a MiddleObject. This is a base class, to be used for importers for various 3d formats. """ def __init__(self, supported_features, wanted_features = {}): """ supported_features - features which the wanted_features - defaults to all features if not specified. """ self.supported_features = supported_features self.wanted_features = wanted_features def GetSupportedFeatures(self): """ Returns the features that this importer supports.""" return self.supported_features def SetFeaturesWanted(self, features): """ Used to tell the importer what features the importer should pass onto the middle object. NOTE: this does not mean that the importer should not load all of the 3d format. If it has to load it all so be it. Just pass the features that are wanted. """ self.wanted_features = features def Start(self): """ Starts the importer doing its import thing.""" raise "This importer is missing an implementation of Start()" class Exporter: """ Used for exporting 3d data from the MiddleObject. This is a base class, to be used for exporters for various 3d formats. """ def __init__(self, supported_features, wanted_features = {}): """ supported_features - """ self.supported_features = supported_features self.wanted_features = wanted_features def GetSupportedFeatures(self): """ Returns the features that this exporter supports.""" return self.supported_features def SetFeaturesWanted(self, features): """ Used to tell the exporter what features the exporter should get from the middle object. """ self.wanted_features = features new_rdpyg/urdpyg/converters/ms3d_ascii_importer.py0000644000175100017510000003544310051352003022775 0ustar renerene00000000000000""" Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ from middle_obj import * #from features import import string from string import split from string import join import re import os import md5 import cPickle # TODO: # *- read meshes. # - read materials. # - read bones. # - figure out how to send data back into the middle_object. # probably register with a callback function, with initialize. # - Add checking in to see what features are required. # """ Milkshape 3d ascii format notes: Basic outline of format: --- Start of file --- Frames: Frame: Meshes: Materials: Bones: --- End of file --- A material index of -1 means no material. rotations seem to be in radians """ def str_parse(string_to_parse, conversion_list, seperator = " "): """ returns a list of formated converted variables based on the string_to_parse - um.. conversion_list - list of functions, to convert parts of the string. Use str for strings, int for ints, floats for floats etc :) seperator - string to use to seperate the elements of the string. Will raise exceptions if string not correctly set up. Or if data fails to convert. """ #TODO: Allow the conversion list to contain sequences of functions. # This way you can return subsequences. eg. # line = "0 1.0 1.0 1.0 2.0 2.0 2.0" # (flags,pos,rot)=str_parse(line, [int, (float, float, float), # (float, float, float)] # flags - 0 # pos - (1.0, 1.0, 1.0) # rot - (2.0, 2.0, 2.0) # # hrmm maybe I could just use regular expressions... split_list = split(string_to_parse, seperator) if(len(conversion_list) != len(split_list)): raise "wrong number of converters, or string doesn't match." return_list = [] for x in range(len(conversion_list)): return_list.append( conversion_list[x](split_list[x]) ) return return_list def chomp(s): if s[-2:] == "\r\n": return s[:-2] elif s[-1:] == "\n": return s[:-1] else: return s class milk_mesh: def __init__(self): # (flags, triangle indicies(a,b,c), # normal indicies(a,b,c), smoothing group) self.triangles = [] # (x,y,z) self.normals = [] # (flags, x,y,z,u,v, bone index). self.verts = [] self.mat_index = -1 self.flags = -1 def __str__(self): return "triangles:%s:\nnormals:%s:\nverts:%s:" % (self.triangles, self.normals, self.verts) class milk_material: def __init__(self): self.material_name = "" self.ambient = [] self.diffuse = [] self.specular = [] self.emissive = [] self.shininess = -1 self.transparency = -1 self.diffuse_texture_name = "" self.alpha_texture_name = "" class milk_bones: def __init__(self): self.name = "" self.parent_name = "" self.flags = 0 # three floats. self.position = [0., 0., 0.] # three floats. self.rotation = [0., 0., 0.] # list of tupples(4 floats) self.position_keys = [] # list of tupples(4 floats) self.rotation_keys = [] def __str__(self): a = """name:%s:|parent_name:%s:|flags:%s:|position:%s:|rotation:%s:|position_keys:%s:|rotation_keys:%s:""" % (self.name, self.parent_name, self.flags, self.position, self.rotation, self.position_keys, self.rotation_keys) return "\n".join(a.split("|")) class MS3dImporter(Importer): """ """ def __init__(self, wanted_features = None): """ If wanted_features equals None then all features are given.""" #FIXME: add the supported features. supported_features = "" #FIXME: call superclasses init. #Importer.__init__(supported_features, wanted_features) def Initialize(self, file): # File to load milkshape data from. self.file = file self.total_frames = 0 self.meshes = [] self.materials = [] self.bones = [] def Start(self): """ """ b_error = 0 f = self.file raw_line = f.readline() line = chomp( raw_line ) print "line :%s:" % line print "raw_line :%s:" % raw_line while (raw_line != "" and not(b_error)): if(line[2:] == "//"): pass # read in the meshes. elif(line[:7] == "Meshes:"): self.ReadMeshes(f, num_meshes = string.atoi(line[7:])) # read in the materials. elif(line[:10] == "Materials:"): self.ReadMaterials(f, num_materials = string.atoi(line[10:])) # read in the bones. elif(line[:6] == "Bones:"): self.ReadBones(f, num_bones = string.atoi(line[6:])) raw_line = f.readline() line = chomp( raw_line ) print "line :%s:" % line print "raw_line :%s:" % raw_line def ReadMeshes(self, a_file, num_meshes): """ """ f = a_file self.meshes = [] for mesh_count in range(num_meshes): m = milk_mesh() line = chomp( f.readline() ) # Get the name, flags, and material index. # split by space, join the last two, and the first. split_parts = split(line, " ") (m.flags, m.mat_index) = str_parse(join(split_parts[-2:]), [int,int]) # join the first parts of the string then take off the " at the # start and at the end. There should be no new line. m.mesh_name = join(split_parts[:-2])[1:-1] # Read in the number of vertices. num_verts = string.atoi( chomp(f.readline()) ) # read the verts into a list. f_readline = f.readline v_a = m.verts.append for vert_count in range(num_verts): v_a( str_parse(chomp(f_readline()), [int, float, float, float, float, float, int]) ) # Read in the normals. num_normals = string.atoi( chomp(f.readline()) ) n_a = m.normals.append for norm_count in range(num_normals): n1, n2, n3 = split( chomp(f_readline()) ) n_a( [float(n1), float(n2), float(n3)] ) # Read in the triangles. num_triangles = string.atoi( chomp(f.readline()) ) t_a = m.triangles.append for norm_count in range(num_triangles): flags, i1,i2,i3, ni1,ni2,ni3, index = split( (f_readline()) ) #t_a( [int(flags), float(i1), float(i2), float(i3), # float(ni1), float(ni2), float(ni3), int(index)] ) t_a( [int(flags), int(i1), int(i2), int(i3), int(ni1), int(ni2), int(ni3), int(index)] ) self.meshes.append(m) def ReadMaterials(self, a_file, num_materials): """ a_file should be set to after the Materials line.""" # Structure of the materials section is as follows. # each part takes up one line. # material name. in "" # ambient, 4 floats. # diffuse, 4 floats. # specular, 4 floats. # emissive, 4 floats. # shininess, 1 float. # transparency, 1 float. # diffuse texture name. in "" # alpha texture name. in "" f = a_file self.materials = [] for x in range(num_materials): # read the name of the material. try: #line = f.readline() m = milk_material() m.mat_name = string.strip(chomp(f.readline()))[1:-1] #print mat_name # ambient, 4 floats. m.amb = str_parse(chomp(f.readline()), [float, float, float, float]) # diffuse, 4 floats. m.diffuse = str_parse(chomp(f.readline()), [float, float, float, float]) # specular, 4 floats. m.specular = str_parse(chomp(f.readline()), [float, float, float, float]) # emissive, 4 floats. m.emissive = str_parse(chomp(f.readline()), [float, float, float, float]) # shininess, 1 float. m.shininess = float(chomp(f.readline())) # transparency, 1 float. m.transparency = float(chomp(f.readline())) # diffuse texture name. in "" m.diffuse_texture_name = chomp(f.readline())[1:-1] # alpha texture name. in "" m.alpha_texture_name = chomp(f.readline())[1:-1] self.materials.append(m) except: # find the line number of error. error_pos = f.tell() f.seek(0) l = f.readline() cur_pos = f.tell() line_num = 1 while cur_pos < error_pos: cur_pos = f.tell() line_num += 1 l = f.readline() #print line_num raise "Error on line:%s:" % line_num def ReadBones(self, a_file, num_bones): """ a_file should be set to after the Bones line.""" # Structure of the Bones section is as follows. # bone name in "" # bone parent in "" # flags(1 int), position(3 floats), rotation(3 floats) # Position key count (int). # position key block(position key lines long). # # Rotation key count (int). # rotation key block(rotation key lines long). # # # NOTE: The comment in the ms3d acii importer code states that bone # parent is alpha_texture... this is obviously a bone parent. f = a_file for x in range(num_bones): # read the name of the bone. line = chomp(f.readline()) b = milk_bones() b.name = string.strip(line)[1:-1] #print ":%s:" % b.name #print "b.name-1:%s:" % b.name[-1] #print "b.name-2:%s:" % b.name[-2] #print ":%s:len%s" % (line, len(line)) #print ":%s:len%s" % (line[1:-2], len(line)) # read in the bones parent name. line = chomp(f.readline()) b.parent_name = string.strip(line)[1:-1] #print ":%s:" % b.parent_name #print ":%s:" % line # Read in the flags, the position, and rotation. p = b.position r = b.rotation stuff = str_parse(chomp(f.readline()), [int, float, float, float, float, float, float]) (b.flags,p[0],p[1],p[2],r[0],r[1],r[2]) = stuff # Read in the number of position keys. num_position_keys = str_parse(chomp(f.readline()), [int])[0] # Read in the position keys. for x in range(num_position_keys): b.position_keys.append( str_parse(chomp(f.readline()), [float]*4) ) # Read in the number of rotation keys. num_rotation_keys = str_parse(chomp(f.readline()), [int])[0] print num_rotation_keys # Read in the rotation keys. for x in range(num_rotation_keys): b.rotation_keys.append( str_parse(chomp(f.readline()), [float]*4) ) self.bones.append(b) import operator import time operator_add = operator.add def convert_array_shape2(verts): return reduce(operator_add, [x[1:-1] for x in verts]) def convert_array_shape3(verts): """ Converts a [[1,1,1,1], [1,1,1,1]] into [1,1,1,1,1,1]""" out_verts = []; map(out_verts.extend, map(lambda x: x[1:4], verts)) return out_verts convert_array_shape = convert_array_shape3 def convert_milkshape(a_file): """ Returns a list of [points, indices, texcoords] Only converts one mesh. """ # DO_PICKLE = 1 from types import FileType if type(a_file) == type(""): a_file = open(a_file, "r") # see if a_file.name +".old_md5" exists. # if it does compare the md5 of the current file, with that of the old one. #TODO: what if it is a StringIO file? need to see if .name attrib exists. if os.path.exists(a_file.name + ".old_md5") and DO_PICKLE: #print "getting old digest" old_md5 = open(a_file.name + ".old_md5").read() # NOTE: may want to use mmap here. #print "getting new digest" new_md5 = md5.md5( a_file.read() ).digest() #print "done: getting new digest" if old_md5 == new_md5: # return the pickle if it exists. if os.path.exists( a_file.name + ".pickle" ): #print "loading pickle" print a_file.name try: pickle_file = open(a_file.name + ".pickle", "rb") return cPickle.load(pickle_file) except: pass a_file.seek(0) imp = MS3dImporter() imp.Initialize(a_file) imp.Start() mesh_data = [] for mesh in imp.meshes: verts = mesh.verts triangles = mesh.triangles normals = mesh.normals points = [] indices = [] texcoords = [] bone_indices = [] normal_list = [] # convert the verts to a list of points( one dimention ). map(points.extend, map(lambda x: x[1:4], verts)) map(normal_list.extend, map(lambda x: x[1:4], normals)) # get a list of texcoords, one dimention. map(texcoords.extend, map(lambda x: [x[4],1.0-x[5]], verts)) #texcoords = map(lambda x: 1.0 -x, texcoords) # Get the indices. map(indices.extend, map(lambda x: x[1:4], triangles)) # get the bone indices. bone_indices = map(lambda x: x[-1], verts) """ print verts[-1] print points[-3], points[-2], points[-1] print points """ #print len(points), len(texcoords), len(indices) assert(len(points) /3 == len(texcoords) /2) #assert(len(points) /3 == len(indices)) mesh_data.append( {"points": points, "normals": normal_list, "indices": indices, "texcoords":texcoords, "material_index":mesh.mat_index, "bone_indices":bone_indices} ) #for md in mesh_data: # if md[3] != -1: # md[3] = imp.materials[md[3]] milk_scene = {} milk_scene["materials"] = imp.materials # make a couple of dicts from the bones. # A parent dict, keyed by bone name, valued by parent name. # A #for b in imp.bones: milk_scene["bones"] = imp.bones milk_scene["mesh_data"] = mesh_data if DO_PICKLE: # make the pickle, and md5 file. if not locals().has_key("new_md5"): a_file.seek(0) new_md5 = md5.md5( a_file.read() ).digest() open(a_file.name + ".old_md5", "w").write(new_md5) an_f = open(a_file.name + ".pickle", "w") cPickle.dump(milk_scene, an_f, 1) return milk_scene def test_MS3dImporter(file_name): #points,indices,texcoords = convert_milkshape(file_name) meshes = convert_milkshape(file_name) if(__name__ == "__main__"): import sys if(len(sys.argv) != 2): print "" sys.exit(0) test_MS3dImporter(sys.argv[1]) new_rdpyg/urdpyg/converters/test_cal3d_exporter.py0000644000175100017510000000142407743744517023040 0ustar renerene00000000000000""" unit tests for the cal3d exporter. """ import unittest import cal3d_exporter class Cal3dExporter(unittest.TestCase): pass def test_Cal3dBone__to_xml(self): """ does converting a Cal3dBone to xml work? """ b = cal3d_exporter.Cal3dBone() print b.to_xml() def test_Cal3dSkeleton__to_xml(self): """ does converting a Cal3dSkeleton to xml work? """ s = cal3d_exporter.Cal3dSkeleton() s.bones.append(cal3d_exporter.Cal3dBone()) s.bones.append(cal3d_exporter.Cal3dBone()) s.bones.append(cal3d_exporter.Cal3dBone()) s.bones.append(cal3d_exporter.Cal3dBone()) print s.to_xml() if __name__ == "__main__": unittest.main() new_rdpyg/urdpyg/converters/test_md2_importer.py0000644000175100017510000000101007743744517022514 0ustar renerene00000000000000""" unit tests for the md2 importer. """ import unittest import md2_importer import os import pprint class TestMd2Importer(unittest.TestCase): pass def testReadHeader(self): """ """ md2_file_name = os.path.join("..", "models", "tris.md2") md2_texture_file_name = os.path.join("..", "models", "hobgoblin.bmp") md2 = md2_importer.Md2Model(md2_file_name, md2_texture_file_name) md2._ReadHeader() pprint.pprint (md2.header) md2.Load() if __name__ == "__main__": unittest.main() new_rdpyg/urdpyg/converters/test_middle_obj.py0000644000175100017510000000023507743744517022211 0ustar renerene00000000000000""" unit tests for the md2 importer. """ import unittest class fsdf(unittest.TestCase): pass if __name__ == "__main__": unittest.main() new_rdpyg/urdpyg/map/0000755000175100017510000000000010076376710015060 5ustar renerene00000000000000new_rdpyg/urdpyg/map/__init__.py0000644000175100017510000000000010074105345017147 0ustar renerene00000000000000new_rdpyg/urdpyg/map/map.py0000644000175100017510000001241210074245107016200 0ustar renerene00000000000000""" = Features wanted = * When not moving it can take only update parts of the screen. * update(dirty_rects) can be used to speed up drawing. * by only updating areas which are dirty. * if the map is not moving we can make it lots speedier. * Offscreen buffer. Blit all smaller tiles to an offscreen buffer then blit one big image to the screen. This can be faster on some screens/computers. * Different tile sizes. * different sizes on the same map. * Join maps together easily. * Different drawable sizes. Ie different camera views. * Be able to be used with pygame or pyopengl. * Different camera modes: * jump scrolling, * jump the map in blocks. Like ten pixels at a time. * smooth scrolling, * every pixel the camera moves the tiles move. * smooth-jump scrolling. * Mostly the screen stays still. When the character nears the edge everything stops moving while the maps scrolls over a little way. * centered camera. * Can center the camera on * Looping Map Edges * Paralax scrolling. * Moving layers at different speeds. * Multiple views of the map. * miniview of the map. Perhaps using a scaled version or one pixel per tile. * minimize overdraw. * using dirty rectangles. * for alpha images precalculate 'full rects'. * That is like a bounding box in the middle where the area is full. * think about using a coverage buffer. * animated tiles will probably always need to be redrawn(unless it's the same frame). * Overlapping tiles. * As well as overlapping whole maps. For joining maps together. * Layers/Z ordering. * draw characters by descending y value on same layer. * for certain types of games: see for explanation: * http://www.gamedev.net/reference/programming/features/gpgenesis9/page7.asp * line of sight tests between tiles and pixels/rects. * collision detection between tiles and pixels/rects. * some tiles may be pass through. * tiles on different layers may be collidable, others not. * fog of war. * darkening/lightening of areas. * Rotatable tiles. * scalable tiles? Other transforms needed? * Easy layer toggling. * So eg when you go inside a building the roof comes off and you can see inside. = Implementation ideas = * Use pygame sprites and sprite groups. * could then reuse lots of code... optimize in one place. Speed development. * think of camera movement as simply moving a sprite group in a certain way. * Use a quad tree for the collision detection. * Could use it for moving, and non moving. * Left to right, or top to bottom scrollers can be optimized in different ways. = Some map editors = The tile combie(or engine if you want) should have most of the features that these map editors contain. http://tilestudio.sourceforge.net/ http://www.tilemap.co.uk/ = A discussion about features = background tiling, layers, collision detection between layers and stuff (rect and pixel) paralax scrolling animation of background/sprites line of sight tests between tiles and pixels based on layer compositions and such eek, that's a lot of stuff good stuff :) separate environmental and UI layer systems what do you mean? so you can draw your UI without worrying how height your environments layers are the UI layers are alwayrs on top ah, cool basically, just 2 lists for heights auto-shadowing for sprites is good indeed, that'd be cool doing like angled skews on the images, and drawing them on the ground layer so you dont have to have separate shadow images for them nice or just auto positioning the same image, but based on heigth of the sprite so like a flying ship has its shadow in the real place, and its in its height-adjusted place, like zaxxon which basically just means you have a transformation for height built in, and use a sort of worrld coords and translated drawing coords aah which makes sense so you should have parameters to what your viewing perspective is, so they can adjust it based on how their art is rendered like: 1.5:1.0 or something you could also have layer toggling like i did in VT, where if you go into a building, it switches what the background tiles are. and if you change floors, it also does that ah, that sounds nice too but that may be a bit specific. though, you could make the design so its possible to rotate through BG tile maps specifically, like theyre layered and do a fall through if the current selected one doesnt exist to the default background map, which has all its spaces mapped sorta an "optional current level background" good for things where people take stairs, and you still want the ground of things outside buildings and such im running out of stuff ive thought about for tiling engines hehe. that's all stuff I didn't think about :) i want to retire im pretty happy doing fuck all all the time now heh having layers greyed out would be good hehe. mostly I'm happy doing fuck all too :) optional layers? or you mean something else? """ new_rdpyg/urdpyg/milk_skeleton.py0000644000175100017510000005570510075765524017535 0ustar renerene00000000000000""" Copyright (C) 2002 by Rene Dudfield. 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 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ import string, sys, os import time import UserDict import Numeric N = Numeric from urdpyg.converters import ms3d_ascii_importer import bisect """ Data flow: -------------- milkshape converter -> MilkshapeModelLoader In the MilkshapeModelLoader it converts the data into its internal representation. """ class MilkshapeModelLoader: """ responsible for loading a milkshape model. """ def __init__(self, file_name = ""): self._debug_level = 0 self._is_tex = 0 if file_name: self.Load(file_name) def _debug(self, x, debug_level = 1): """ """ if self._debug_level > debug_level: print x def IsTextured(self): if self._is_tex: return 1 else: return 0 def Load(self, file_name): """ """ t1 = time.time() self.data = ms3d_ascii_importer.convert_milkshape( file_name ) t2 = time.time() self._debug("load time of milk:%s:" % (t2 - t1), 2) d = self.data["mesh_data"][0] material_index = d["material_index"] self._debug("material_index:%s" % material_index, 2) self.texcoords= Numeric.asarray(d["texcoords"], 'f') self.points = Numeric.asarray(d["points"], 'f') self.normals = Numeric.asarray(d["normals"], 'f') self.indices = Numeric.asarray(d["indices"], 'i') if material_index != -1: m = self.data["materials"][material_index] self._debug("m.material_name:%s" % m.material_name, 2) self._debug("m.diffuse_texture_name:%s" %m.diffuse_texture_name, 2) self._debug("m.alpha_texture_name :%s" %m.alpha_texture_name, 2) self.image_name = apply(os.path.join, os.path.split(m.diffuse_texture_name[2:])) #NOTE: FIXME: materials don't need textures. #NOTE: FIXME: there are different textures too. self._is_tex = 1 #time.sleep(2) else: self._is_tex = 0 self.skeleton = MilkSkeleton(self.data) class BoneHeirarchy: """ Which bones are parents/children of which other bones. - has bone names, and bone indices into AbsoluteBones/RelativeBones. - GetChildren_names/indices - returns a list of names/indices. BoneName2BoneNumber_Map - mapping of bone names to a number in the bone index. """ def __init__(self, milk_bones): """Takes a milk_bones variable from the milkshape converter. """ # given the parents name get back a list of children. self.bone_parents_dict= {} # given the childs name get back a parent. self.bone_children_dict= {} # given a bone name you can get the idx of that bone in the bone list. self.bone_name_to_idx = {} self.Update(milk_bones) def Update(self, milk_bones): """ Takes a milk_bones variable from the milkshape converter. """ #NOTE: if we want to use 1000's bones it may be more efficient to use # ints as the keys. and possibly lists to store them. # # This is an efficient storage for 1000's of skeletons with 1000's of # bones. 1000 * 1000 * 20 == 20 megabytes. # 1000 * 1000 * 4 == 4 megabytes for a list implementation. self.bone_parents_dict= {} self.bone_children_dict= {} self.bone_name_to_idx = {} # keyed by bone name, valued by milk_bones instances. self.bone_dict = {} for b in milk_bones: if not self.bone_parents_dict.has_key(b.parent_name): self.bone_parents_dict[b.parent_name] = [b.name] else: self.bone_parents_dict[b.parent_name].append(b.name) if not self.bone_children_dict.has_key(b.name): self.bone_children_dict[b.name] = [b.parent_name] else: self.bone_children_dict[b.name].append(b.parent_name) #assert( not self.bone_dict.has_key(b.name) ) self.bone_dict[b.name] = b self.bone_name_to_idx = self._make__bone_name_to_idx(milk_bones) def _make__bone_name_to_idx(self, milk_bones): """ returns a dict mapping bone name -> its idx within the list. """ bone_name_to_idx = {} for idx, milk_bone in zip(range(len(milk_bones)), milk_bones): if bone_name_to_idx.has_key(milk_bone.name): raise ValueError("bone allready exists with name, %s" % milk_bone.name) bone_name_to_idx[milk_bone.name] = idx return bone_name_to_idx def GetChildren_idx(self, bone_name): """ returns a list of idx for the children of given bone name. """ children = self.GetChildren(bone_name) idx_list = [] for child in children: idx_list.append(self.bone_name_to_idx[child.name]) return idx_list def GetChildren(self, bone_name): """ Returns a list of children milk_bone instances.""" if not self.bone_parents_dict.has_key( bone_name ): return [] return map(self.bone_dict.get, self.bone_parents_dict[ bone_name ]) #return self.bone_dict[ self.bone_parents[ bone_name ] ] def GetParents(self, bone_name): """ Returns a list of parents milk_bone instances.""" if not self.bone_children_dict.has_key( bone_name ): return [] return map(self.bone_dict.get, self.bone_children_dict[ bone_name ]) #return self.bone_children[ bone_name ] def GetRootName(self): """ Returns the root bones name. """ return self.bone_parents_dict[""][0] def __str__(self): return self.PrintTree(details = 1) def PrintTree(self, a_bone = "ROOT", indent_level = 0, details = 0): """ Returns a string representation of bones tree. a_bone - a milk_bone instance, or "ROOT". if "ROOT" then we return from the root of the tree. """ if a_bone == "ROOT": a_bone = self.bone_dict[self.GetRootName()] return_text_list = [] indent_text = indent_level * " " if details: bone_text = str(a_bone) bone_text.split("\n") a = "".join(map(lambda x,y = indent_text: "".join((y,x,"\n")), bone_text.split("\n"))) return_text_list.append( a ) else: return_text_list.append( indent_text + a_bone.name ) children = self.GetChildren(a_bone.name) for bone in children: child_text = self.PrintTree(bone, indent_level+2, details) return_text_list.append(child_text) return string.join( return_text_list, "\n") class BoneName2BoneNumber_Map(UserDict.UserDict): """ mapping of bone names to a number in the bone index. """ def __init__(self, milk_bones): UserDict.UserDict.__init__(self) self.Update(milk_bones) def Update(self, milk_bones): for b in zip( milk_bones, range(len(milk_bones)) ) : self.data[b[0].name] = b[1] class Bone2Vert_Map(UserDict.UserDict): """ a list of indices for the verts that each bone should transform. Should probably be a Numeric 3d array. where self.data[0] == list of vert indices for the first bone. Each index could be 4 bytes for four bones. - this would be harder to access. - would limit the total number of bones. For now keep it simple. """ def __init__(self, milk_data): self.Update(self, milk_data) def Update(self, milk_data): """ """ # note: milkshape can only have one bone per vert. data = milk_data["mesh_data"]["bone_indices"] #self.data = Numeric.reshape(data, (len(data), 1)) bone2vert_map = {} for bone_idx, vert_idx in zip(data, len(data)): # if not bone2vert_map.has_key(bone_idx): bone2vert_map[bone_idx] = [vert_idx] else: bone2vert_map[bone_idx].append(vert_idx) # class Vert2Bone_Map: def __init__(self, ): self.Update(self, milk_data) def Update(self, milk_data): """ """ # note: milkshape can only have one bone per vert. data = Numeric.array(milk_data["mesh_data"]["bone_indices"], 'i') self.data = Numeric.reshape(data, (len(data), 1)) class Time2Keyframe_Map: """ Each bone should be able to have it's own key frames. time2keyframe_maps[bone_name] -> time2keyframe_map time2keyframe_map[seconds_since_start_of_animation] -> keyframe index's. Depending on whether we want the animation to loop or stop at the start or the end, we return a keyframe on either side of the time specified. TODO: we can loop at the start of the keyframes as well as at the end. """ def __init__(self, loop = 0): """ loop - should we loop the animation back to the start once the last keyframe has been reached? """ self.loop = loop def UpdateFromBones(self, milk_bone): """ milk_bone - used to get the different times for the keyframes. """ times = [] map(lambda x, t = times: t.append(x[0]), milk_bone.positions) self.times = times self.Update(times) def Update(self, times): """ times - a sequence of floats representing keyframes. """ self.times = times # Should the internal format be a dict and a list? # yes, as we need to find the next, and previous, as well as by a number. # should we have seperate keyframes for rotations, translations, # and scaling? # Why not? We do not have support for it in any editor. # not immediately useful. # For now we will just use the times for rotations. #TODO: incomplete. #raise NotImplementedError # the times should be sorted. self.time_index = {} # make an index of times. for t, i in zip(times, range(len(times))): self.time_index[t] = i def GetIndicesEitherSideOfTime(self, time): """ time - a float Returns the two keyframe indices either side of the time given. """ # no looping. # Find the smallest time which is greater than the time given. # TODO: need to do better than a linear search. # the code below is incomplete, needs fixing. raise "incomplete" largest_num = len(self.times) - 1 if time == self.times[smaller_index]: greater_index = 0 smaller_index = bisect.bisect_left(self.times, time) # if the position is greater than or equal to the largest index, # then we return the largest num as both of them. if smaller_index >= largest_num: smaller_index = largest_num greater_index = largest_num else: greater_index = smaller + 1 if greater_index > largest_num: greater_index = largest_num class AbsoluteBones: """ Stores the absolute transforms. There is a seperate one of these for each keyframe. - Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of 'four elements' ). - translation quats(array of 'four elements' ). Maybe only need matrix version for absolute? - No, need to slerp between two absolute bones. Don't need a matrix representation? - maybe not, if the these are only used to slerp up an intermediate set of bones. NOTE: for transforming the verts, it will be faster to transform them with a 3x3 rotation matrix if there is no translation/scaling happening. """ class RelativeBones: """ Stores transforms relative to it's parent. There is a seperate set of these for each of the keyframes. - Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of 'four elements' ). - translation quats(array of 'four elements' ). TODO: find if a quatRotation * quatTranslation is equal to a matrixRotation * matrixTranslation. """ def Update(self, milk_bone): """ From the milkshape data transform it into an internal representation. milk_bone - a bone from the converter. - Convert the Euler angle milkshape rotations into quaternions. - Convert the milkshape positions into quaternions. Q(Px, Py, Pz, w =0.0) - rotation, position quaternions multiplied and stored. """ # mb = milk_bone mb.position mb.position_keys mb.rotation mb.rotation_keys class MilkSkeleton: """ ---------------------------------------------------------------------- Data structures. - '=' denotes data belongs to this parent. Skeleton - this is where everything is put together. - we may want to share some data between skeletons, so we may need a higher level system. - this higher level system would share the different parts of memory. - Maybe it could even transform all of the data at once. = BoneHeirachy DONE. = Keyframes = Bone2Vert_Map DONE. = Time2Keyframe_Map = KeyframeNumber2Time_Map Keyframes - collects the different keyframe data for a skeleton. = AbsoluteBones = RelativeBones = Time2Keyframe_Map = KeyframeNumber2Time_Map AbsoluteBones - bones represented in their absolute form. - Need matrix, and quat+pos_vector versions - The matrix versions would be used to transform verts. - The quat_pos_vector versions will blend with other bones. - The conversion to matrices will need to be cached. - Use three arrays. - rotation quats( an array of 'four elements' ). - translation quats(array of 'four elements' ). - transform matrices(array of '16 elements' ie 4x4 matrices). RelativeBones - these bones will have all relative data. Eg each bone will only be relative to the others. Time2Keyframe_Map. - gets two keyframes on either side of a given time. - this would be per bone? Not at the moment(it should be per skeleton). KeyframeNumber2Time_Map. - given a keyframe number, give the time for it. - this would be per bone? Not at the moment(it should be per skeleton). DONE. BoneHeirachy - which bones are parents/children of which other bones. - has bone names, and bone indices into AbsoluteBones/RelativeBones. - GetChildren_names/indices - returns a list of names/indices. BoneName2BoneNumber_Map - mapping of bone names to a number in the bone index. DONE. Bone2Vert_Map - a list of indices for the verts that each bone should transform. Vert2Bone_Map - vert to list of bones which effect them. MilkBones - this is the data from the milk format. This contains the positions, and rotations in euler format, and the keyframe times. local2world_transform - a transform specifying where in the world the skeleton is. - This will likely change occasionally. - from every frame to once every minute. - is this specified by the root node? - Could we add this as the new root node? - would simplify the code if we did. - Can be added as an after thought if needed. Pretty easy. - Not really, as it possible this would change all the time. - We may want to add this, as it will solve having to re-transform them. - On the other hand this could be done in hardware with gf+ cards. ---------------------------------------------------------------------- --------------------------------------------------------------------- Order of the operations. - Things that need to be done in order to get the model transformed. Set up stuff. - things to do around load time. From the milk bones set up: - BoneHeirachy - Set up the relative bones. - Convert the Euler angle milkshape rotations into quaternions. - Convert the milkshape positions into quaternions. Q(Px, Py, Pz, w =0.0) - rotation, position quaternions multiplied and stored. - Time2Keyframe_Map - KeyframeNumber2Time_Map AbsoluteBones are made from RelativeBones. For each keyframe. Multiply the bones down the heirarchy. child.absolute = parent.absolute * child.relative Per frame stuff. Get current time in animation. From Time2Keyframe_Map grab two keyframes on either side of current time. For every absolute quat: Interpolate between two keyframes: t1 = current_time_in_animation - kf_a.time t2 = kf_b.time -kf_a.time slerp = t1/t2 frame_now = quat_slerp(kf_a.absolute, kf_b.absolute, slerp) Generate the matrices for each absolute quat. Transform each absolute matrix by the local2world_transform. Transform verts of the mesh: For vertex which is affected by one bone: For each absolute matrix transform its verts. If the vert is only affected by one bone: Multiply the vert by the absolute matrix. else: somehow interpolate the different bones. - TODO: ^ - maybe this could be done in the slerp? - storing some extra absolute quats for the verts affected by multiple ones. - this is where bone weights can fit in. For now we will only support one bone per vertex. Alternate way to transform the skin: For each vertex: look at the weight structure. ulong32 boneIndices - 4 indices to bones. ulong32 weights - 4 weights. --------------------------------------------------------------------- Optimizations. --------------------------------------------------------------------- When a key frame does not have any translations the transform of the vertices can be optimized to only use a 3x3 rot, instead of a 4x4. - There may be other optimizations depending on the bones state. - Maybe we could store a BONE_STATE int which will allow us to quickly identify a type of bone? This would allow us to quickly see if the bone has no translation. - We could group bones of similar nature together to make the transforms quicker. Eg all bones with no translation part could be stuck together. - Remember that we need to apply a local2world transform to all of the different absolute matrices. We may be able to cache certain different transforms. - I'm pretty sure there will be many repeated transforms. A cheap way to interpolate between keyframes would be linear using the mesh's verts. This would involve calculating the mesh for each key frame, and then interpolating between each vertex in meshes a, and b. Perhaps this could be an optional thing. To be used for slow computers, when a character is far away, or when the difference in time or movement of the character is really small. A downside to this is that you need to keep at least three sets of the mesh around at any time. An upside to this is that interpolation can be done on lighting values too. --------------------------------------------------------------------- --------------------------------------------------------------------- TODOS: Future todos: - have keyframe data for seperate parts of the skeleton. - eg make the hand have it's own keyframes. - This would complicate how to construct the absolute quats. - You would recalculate down from the animation for that part. - so if the arm was using some extra ones we'd go from there. - Probably not so useful until the animation tool supports it. - Incorporate bone weights into it. - Milkshape doesn't support these, however others(characterfx) do. - Look at the different ways to accelerate these with hardware. - ati, and nvidia have things to do this from geforce up. --------------------------------------------------------------------- --------------------------------------------------------------------- Dependencies - a list of different dependencies that need to be considered. - helps with caching different things. --------------------------------------------------------------------- --------------------------------------------------------------------- OLD Order of the operations. X Convert the axis angle milkshape rotations into quaternions. X The translations should also be converted into quaternions, X and multiplied by the rotation part. Q(Px, Py, Pz, w =0.0) X Have an absolute quaternion, and a relative one for each bone. X Quats should be seperate for the current frame that is to be rendered. X - that is the final bones for the current frame should be in a single X array. X - this is so that they may be easily converted to matrices. X Absolute matrices for the current frame should be made. X - these matrices include For each keyframe. Multiply the bones down the heirarchy. child.absolute = parent.absolute * child.relative To interpolate between two keyframes we do: t1 = current_time_in_animation - keyframe_a.time t2 = keyframe_b.time -keyframe_a.time slerp = t1/t2 frame_now = quat_slerp(keyframe_a.absolute, keyframe_b.absolute, slerp) Any time a bones rotation changes we need to recalculate all of its children. To transform verts of the mesh: We need the absolute matricies for each bone. Do we support multiple bones per vertex? If so will we use weighting? Apply a local2world transform to all of the different absolute matrices. - this should be added as a new root node. """ def __init__(self, milk_data): """ the data attribute from the milkshape converter. """ milk_bones = milk_data['bones'] self.milk_bones = milk_bones self.bone_heirarchy = BoneHeirarchy(milk_bones) self.bone_name2bone_number_map = BoneName2BoneNumber_Map(milk_bones) # for each bone we need: # - rotations. # - positions. # - scales. # - keyframe number -> time map. # - Way to get the two keyframes on either side of a given time. # these are 4 element quats. #self.rotations = N.array() # these are 3 element positions. #self.positions = N.array() def _convert_angles_to_quats(self): """ This converts the different rotations of the bones into quaternions. """ new_rdpyg/urdpyg/__init__.py0000644000175100017510000000027210075756270016417 0ustar renerene00000000000000""" The unstable part of rdpyg. Contains modules that are not very well designed, tested, or commented, and which are not planned to be have the same api stick around for ages. """ new_rdpyg/urdpyg/gl_images.py0000644000175100017510000000623107752432402016604 0ustar renerene00000000000000#file: images.py #purpose: everything to do with image loading. import pygame import os import time from OpenGL.GL import * try: from mygl import * except: pass def load_gl_textureRGB(name, flip = 1, internal_format = GL_RGB): """ returns a texid for the loaded image. """ if type(name) == type(""): im_surf = pygame.image.load(os.path.join("..", "data", "images", name)) else: im_surf = name image = pygame.image.tostring(im_surf, "RGB", flip) image_width = im_surf.get_width() image_height = im_surf.get_height() #TODO: add check for pow2 size. tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, tex) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glEnable(GL_TEXTURE_GEN_S) #glEnable(GL_TEXTURE_GEN_T) glTexImage2D(GL_TEXTURE_2D, 0, internal_format, image_width, image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image) return tex def load_gl_textureRGBA(name, flip = 1, internal_format = GL_RGBA): if type(name) == type(""): im_surf = pygame.image.load(os.path.join("..", "data", "images", name)) else: im_surf = name image = pygame.image.tostring(im_surf, "RGBA", flip) #print t2 - t1 image_width = im_surf.get_width() image_height = im_surf.get_height() #TODO: add check for pow2 size. tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, tex) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) ##glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST) #glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) #glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) #glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP) #glEnable(GL_TEXTURE_GEN_S) #glEnable(GL_TEXTURE_GEN_T) #glTexImage2D(GL_TEXTURE_2D, 0, 3, image_width, image_height, glTexImage2D(GL_TEXTURE_2D, 0, internal_format, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) return tex new_rdpyg/urdpyg/milkviewer4.py0000644000175100017510000000422310076013353017107 0ustar renerene00000000000000 import pygame from OpenGL.GL import * from numeric_gl import * from urdpyg.converters import ms3d_ascii_importer from urdpyg.milk_skeleton import * from urdpyg import gl_images class MilkshapeModel(MilkshapeModelLoader): """ Loads and displays a milk shape 3d model. """ def Load(self, file_name): MilkshapeModelLoader.Load(self, file_name) if self.IsTextured(): self.LoadImage(self.image_name) def LoadImage(self, filename): im_surf = pygame.image.load(filename) self.tex = gl_images.load_gl_textureRGB(im_surf) def ReloadTextures(self): """ reloads any textures. Useful when a context change happens. """ # NOTE: Shouldn't delete the texture... I think. if self.IsTextured(): self.LoadImage(self.image_name) def Display(self): """ Call this to draw. """ # set up the correct model matrix. self._StartDisplay() self._MiddleDisplay() self._FinishDisplay() def _MiddleDisplay(self): glDrawElementsui(GL_TRIANGLES, self.indices) def _StartDisplay(self): """ This is all the stuff you call before drawing. """ # bind the correct texture/s # enable the arrays for drawing. # draw the arrays. #print "points", self.points #print "texcoords", self.texcoords #print "indices", self.indices if self.IsTextured(): glEnable(GL_TEXTURE_2D) # Enables depth testing. glEnable(GL_DEPTH_TEST) # Enables smooth shading. glShadeModel(GL_SMOOTH) if self.IsTextured(): glBindTexture(GL_TEXTURE_2D, self.tex) glEnableClientState(GL_VERTEX_ARRAY) if self.IsTextured(): self._debug("is tex",4) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glVertexPointer(3, GL_FLOAT, 0, self.points) if self.IsTextured(): glTexCoordPointer(2, GL_FLOAT, 0, self.texcoords) def _FinishDisplay(self): """ Call after drawing. """ glDisableClientState(GL_VERTEX_ARRAY) if self.IsTextured(): glDisableClientState(GL_TEXTURE_COORD_ARRAY) glDisable(GL_DEPTH_TEST) if self.IsTextured(): glDisable(GL_TEXTURE_2D) new_rdpyg/urdpyg/music.py0000644000175100017510000001255210076374352016002 0ustar renerene00000000000000# file: music.py # purpose: responsible for loading and playing music. """ """ music_events = ["game over happy", "game over sad", "game start", "using special", "close to end of game", ] # Different conditions for happy/sad music. # # 2 player, single computer. # - game over happy. # 2 player, networked, local loses. # - game over sad. # 2 player, networked, local wins. # - game over happy. # 1 player, human wins. # - game over happy # 1 player, human loses. # - game over sad. # import os, glob import pygame.mixer import pygame.mixer_music from rdpyg.util import cyclic_list import config import sound_config from rdpyg.util import vtimer class Music: """ Useage: m = Music() m.Play("intro") m.Play("bla") Need a directory ../data/music/intro.ogg """ def __init__(self): """ """ # for playing a track in 0.3 sec. self.play_timer= vtimer.vtimer(0.2, self.music_play_callback) self.fade_in_timer = vtimer.vtimer(0.2) self.fade_out_timer = vtimer.vtimer(0.2) # don't let it do a callback until finished. self.play_timer.set_finished_no_callback() self.fade_in_timer.set_finished_no_callback() self.fade_out_timer.set_finished_no_callback() self.fade_in = 0 self.fade_out = 0 self.GetFileNames() vol = config.max_music_volume self.SetMaxVol(vol) pygame.mixer.music.set_volume(vol) self.SetLoudVol(vol + 0.2) def SetLoudVol(self, vol): """ louder than max volume. this is for special occasions. """ if vol >= 1.0: self.max_loud_volume = 1.0 else: self.max_loud_volume = vol def SetMaxVol(self, vol): """ sets the maximum volume for the music. """ if vol >= 1.0: self.max_volume = 1.0 else: self.max_volume = vol def Load(self, music_type): """ music_type - one of the music types from the sound_config. """ if music_type == "intro": snd = sound_config._get_random(sound_config.music_types[music_type]) else: snd = sound_config._get_cyclic(sound_config.music_types[music_type]) pygame.mixer.music.load(self.sound_dict[snd]) def music_play_callback(self): self.Load(self.music_type) pygame.mixer.music.play(self.loop) def GetFileNames(self, path = os.path.join("..", "data", "music")): """ returns a dict of file names to be used as music. keyed by the file name without path, and .ogg. path - to the file names. """ #self.sound_list = map(lambda x:x[7:-4], glob.glob(os.path.join(path,"*.ogg")) ) self.sound_list = glob.glob(os.path.join(path,"*.ogg")) #print self.sound_list, "sound list" self.sound_dict = {} for sound in self.sound_list: file_name = os.path.split(sound)[-1] file_start = os.path.splitext(file_name)[0] self.sound_dict[file_start] = sound return self.sound_dict def Play(self, music_type, loop = -1): """ Starts playing the music. """ self.music_type = music_type self.loop = loop if pygame.mixer.music.get_busy(): # fade out the playing track, then play ours. #pygame.mixer.music.fadeout(1000) self.fade_out_timer.reset() self.fade_out = 1 # get ready to play the next song :) self.play_timer.reset() else: self.Load(music_type) pygame.mixer.music.play(self.loop) def Update(self, elapsed_time): """ To be called frequently. """ self.play_timer.Update(elapsed_time) self.fade_out_timer.Update(elapsed_time) self.fade_in_timer.Update(elapsed_time) if self.fade_out: vol = self.fade_out_timer.left_normalised() vol *= self.max_volume pygame.mixer.music.set_volume(vol) if self.fade_out_timer: # we have faded out. self.fade_out = 0 self.fade_in_timer.reset() self.fade_in = 1 if self.fade_in: vol = (1. - self.fade_in_timer.left_normalised()) vol *= self.max_volume pygame.mixer.music.set_volume(vol) if self.fade_in_timer: # we have faded in. self.fade_in = 0 if 0: if not (self.play_timer_100.just_finished or self.play_timer_1000.just_finished): if self.play_timer_1000 or self.play_timer_100: # check to see if there is any music playing if not, play it. if not pygame.mixer.music.get_busy(): self.Load(self.music_type) pygame.mixer.music.play(2) #if not pygame.mixer.music.get_busy(): # pygame.mixer.music.load(self.current) # self.Play() def Pause(self): """ pauses the music. """ pygame.mixer.music.pause() def UnPause(self): pygame.mixer.music.unpause() def Stop(self): """ """ #pygame.mixer.music.stop() pygame.mixer.music.fadeout(100) new_rdpyg/urdpyg/some_sound.py0000644000175100017510000000633207713675013017036 0ustar renerene00000000000000""" file: some_sound.py purpose: to load all the sounds, and manage the playing of them. Probably have different sets of sounds in here somehow. """ import pygame import os import glob from pygame.locals import * def get_sound_list(): """ """ # load a list of sounds without sound/ at the beginning and .wav at the end. sound_list = map(lambda x:x[7:-4], glob.glob(os.path.join("sounds","*.wav")) ) ogg_sound_list = map(lambda x:x[7:-4], glob.glob(os.path.join("sounds","*.ogg")) ) sound_list.extend(ogg_sound_list) return sound_list class SoundManager: """ Controls loading, mixing, and playing the sounds. Having seperate classes allows different groups of sounds to be loaded, and unloaded from memory easily. """ def __init__(self): """ """ self.mixer = None self.music = None self.sounds = {} self.chans = {} self.initialized = 0 self._debug_level = 1 def _debug(self, x, debug_level = 0): """ """ if self._debug_level > debug_level: print x def Initialize(self): """ Initializes the mixer. """ global mixer, music try: import pygame.mixer pygame.mixer.init(44000, 8, 0) mixer = pygame.mixer music = pygame.mixer.music self.initialized = 1 return 1 except (ImportError, pygame.error): self.initialized= 0 self._debug("Error initializing sound.") return 0 def Load(self, names = sound_list): """Loads sounds.""" sounds = self.sounds if not mixer: for name in names: sounds[name] = None return for name in names: if not sounds.has_key(name): fullname = os.path.join('sounds', name+'.wav') try: sound = mixer.Sound(fullname) except: sound = None self._debug("Error loading sound") sounds[name] = sound def GetSound(self, name): """ Returns a Sound object for the given name. """ if not self.sounds.has_key(name): self.Load([name]) return self.sounds[name] def Play(self, name, volume=[1.0, 1.0], wait = 1): """ Plays the sound with the given name. name - of the sound. volume - left and right. Ranges 0.0 - 1.0 wait - if there is a sound of this type playing wait for it. """ vol_l, vol_r = volume sound = self.GetSound(name) if sound: if self.chans.has_key(name): c = 0 while self.chans[name].get_busy(): time.sleep(0.001) c += 1 if c > 40: break self.chans[name] = sound.play() if not self.chans[name]: self.chans[name] = pygame.mixer.find_channel(1) self.chans[name].play(sound) if self.chans[name]: self.chans[name].set_volume(vol_l, vol_r) del self.chans[name] def PlayMusic(self, musicname): """ Plays a music track. Only one can be played at a time. So if there is one playing, it will be stopped and the new one started. """ music = self.music if not music: return if music.get_busy(): #we really should fade out nicely and #wait for the end music event, for now, CUT music.stop() fullname = os.path.join('sounds', musicname) music.load(fullname) music.play(-1) music.set_volume(1.0) new_rdpyg/urdpyg/some_sprites.py0000644000175100017510000003266607643510703017404 0ustar renerene00000000000000""" file: some_sprites.py purpose: animation, sprite playing. """ import os, os.path, glob, sys, bisect import time import pygame #import pygame.transform from pygame.locals import * DEBUG = 0 SCREENRECT = Rect(0, 0, 640, 480) try: import use_gl USE_GL = use_gl.USE_GL print "ahasjdhasjkhkjhsfd" except: USE_GL = 0 print USE_GL if USE_GL: from spritegl import SpriteGL, GroupGL pygame.sprite.Sprite = SpriteGL pygame.sprite.Group = GroupGL pygame.sprite.RenderPlain = GroupGL pygame.sprite.RenderUpdates = GroupGL #layer_order = ["walk_forwards", # "walk_left", # "walk_right", # "red background", # "transparent background"] """ layer_order = ["bam", "yellow", "red", "orange" ] """ # animations are made out of different frames from the character anim. # they have a list of frames, and a length of time for each frame. #animations = {} #a = animations #a['walk'] = [("walk_forwards", 1.0 ), # ("walk_right", 1.0), # ("walk_forwards", 1.0), # ("walk_left", 1.0), # ("walk_forwards", 1.0), # ] """ a['bam'] = [ ("orange", 0.01 ), ("red", 0.01), ("yellow", 0.01), ("orange", 0.01 ), ("red", 0.01), ("yellow", 0.01), ("orange", 0.01 ), ("red", 0.01), ("yellow", 0.01), ("bam", 0.4), ] """ def get_background_names(base_dir): """ TODO: needs fixing/testing. """ background_names = map(lambda x:x[len("background")+1:-4], glob.glob(os.path.join(base_dir, "background", "*.png")) ) background_names.extend( map(lambda x:x[len("background")+1:-4], glob.glob(os.path.join(base_dir, "background", "*.jpg")) ) ) return background_names class Timer: def __init__(self, length): """ a = Timer(10) # if the timer is finished. if a: print "asdf" """ self.Start(length) def Start(self, length): """ length is the amount of time that this timer should go for. """ self.end_time = time.time() + length def __nonzero__(self): if time.time() > self.end_time: return 1 else: return 0 def animation_factory(anim_data, loop = 1): """ Returns a dict keyed by anim_name valued by Animation instances. anim_data - keyed by anim name, valued by a list of tuples(frame_name, length). loop - passed through to Animation class. """ anims = {} for anim_name in anim_data.keys(): anims[anim_name] = Animation(anim_data[anim_name], anim_name, loop) return anims class Animation: """ For telling which of the frames should be drawn. Howto use: a = Animation(...) a.Start() if a.StillGoing(): new_frame_to_draw = a.NewFrame() if new_frame_to_draw: draw(new_frame_to_draw) else: # old frame to be rendered. pass else: # figure out what to do at end of anim. pass """ def __init__(self, animation_data, name, loop = 1): """ animation_data - a list of tuples (frame_name, time). The time part says for how long in the animation that the frame should be shown. Must have at least one element. loop - should the animation loop. If 0 the animation will return the last frame when it gets to the end. If -1 the animation will loop for ever. If non zero the animation will loop that many times. """ assert(len(animation_data) > 0) self.animation_data = animation_data self.loop = loop self.name = name self.Start() self.SetUpAnimationData(animation_data) self.last_frame = "" def Start(self, loop = 1): """ Starts the animation at the beginning. """ self.loop = loop self.start_time = time.time() self.last_frame = "" def GetName(self): return self.name def NewFrame(self): """ Returns the frame name if there is a new frame needed for the animation. Otherwise returns 0. """ frame_name = self.StillGoing() if frame_name == self.last_frame: return 0 else: return frame_name def StillGoing(self): """ returns the frame name if still going else, returns 0 if finished. """ # Add up the total length of the anim. cur_time = time.time() since_beginning = cur_time - self.start_time # do the infinity loop. if self.loop == -1: time_in_anim = since_beginning % self.GetLengthOfAnim() # no looping of anim. elif self.loop == 0: if since_beginning > self.GetLengthOfAnim(): # we are finished, so we return 0. return 0 else: time_in_anim = since_beginning # we are set to play a specific number of times. else: if since_beginning > self.loop * self.GetLengthOfAnim(): # we are finished, so we return 0. return 0 # find out where we are in the animation. time_in_anim = since_beginning % self.GetLengthOfAnim() # figure out which frame we are at. frame_name = self._GetFrameGivenTimeInAnim(time_in_anim) return frame_name def SetUpAnimationData(self, animation_data): """ Sets up the animation data ready for processing. """ self.anim_length_once = reduce(lambda x,y: x+y, map(lambda x:x[1],self.animation_data )) # set up the animation data for easy bisecting. # make a list of the animation data that holds the time that the frame starts. self.absolute_anim_data = [] total_time = 0. for frame_name, frame_length in self.animation_data: total_time += frame_length self.absolute_anim_data.append( total_time ) def _GetFrameGivenTimeInAnim(self, time_in_anim): """ Returns the frame name we should be rendering given a time in the anim. """ where_in = bisect.bisect(self.absolute_anim_data, time_in_anim) if where_in < 0: return self.animation_data[0][0] return self.animation_data[where_in][0] def GetLengthOfAnim(self): return self.anim_length_once def GetNumTimesPlayed(self): """ Returns the number of times the animation has been played. """ cur_time = time.time() return int( divmod(cur_time - self.start_time, self.anim_length_once)[0] ) def A__nonzero__(self): """ Used to see if the animation is still going. """ raise "Not implemented" def get_character_frame_names(the_layer_order, base_dir = ".."): """ returns a dict keyed by character name, valued by a dict(keyed by meaningful name, valued by image path name). """ global DEBUG character_names = filter(lambda x: os.path.isdir(os.path.join(base_dir, "characters",x)) , os.listdir(os.path.join(base_dir, 'characters'))) #print character_names character_frame_names = {} for character_name in character_names: t = glob.glob(os.path.join(base_dir, "characters", character_name, "*.gif")) t.extend( glob.glob(os.path.join(base_dir, "characters", character_name, "*.png")) ) # sort them so that they are in numerical order. # the naming scheme of gimp allows this with the normal sort func. t.sort() t.reverse() # now map the gimp file names with the meaningful names. if len(t) != len(the_layer_order): if DEBUG: print "don't have the correct number of frames for character:%s" % (character_name) print t print the_layer_order r = {} for meaning, img_path in zip(the_layer_order, t): r[meaning] = img_path character_frame_names[character_name] = r return character_frame_names def read_anim_data(character_name, base_dir = ".."): """ Reads the animation data from the characters anim.py file. """ d = {} e = {} file_name = os.path.join(base_dir, "characters",character_name , "anim.py") contents = open(file_name).read() a = compile(contents, file_name, "exec") eval(a, e, e) return [e['animations'], e['layer_order']] image_cache = {} def load_image(name, colorkey=None, convert_alpha = 0): global image_cache if image_cache.has_key(name): return [image_cache[name][0], pygame.Rect(image_cache[name][1])] try: image = pygame.image.load(name) except pygame.error, message: print 'Cannot load image:', name raise SystemExit, message if convert_alpha: image = image.convert_alpha() else: image = image.convert() if colorkey is not None: if colorkey is -1: colorkey = image.get_at((0,0)) image.set_colorkey(colorkey, RLEACCEL) image_cache[name] = (image, image.get_rect()) return image_cache[name] class A(pygame.sprite.Sprite): def __init__(self, im_name): pygame.sprite.Sprite.__init__(self) #call Sprite initializer self.image, self.rect = load_image(im_name, -1) class ImageAnimation(pygame.sprite.Sprite): def __init__(self, animation_set_name, initial_animation): """ animation_name - name of the animation set to use. """ pygame.sprite.Sprite.__init__(self) #call Sprite initializer self.animation_set_name = animation_set_name self.current_animation = initial_animation self.position = (0,0) # make self.layer_order, and self.animations self.LoadAnimationData() #character_image_dict - this is a dict keyed by # meaningful name, valued by image path name. self.character_image_dict = get_character_frame_names(self.layer_order)[animation_set_name] # load the images. self.images = {} self.LoadImages() # Make a whole heap of animation classes. self.anims = animation_factory(self.animations, loop = -1) self.StartAnim(self.current_animation) # modified_images is a dict keyed by modified type valued by # a dict of images of the frames. self.modified_images = {} self.modified_images['originals'] = self.images def StartAnim(self, anim_name, loop = 1): self.current_animation = anim_name self.anims[self.current_animation].Start(loop) new_frame_to_draw = self.anims[self.current_animation].NewFrame() if not new_frame_to_draw: raise "should be a frame here" self.image, self.rect = self.images[new_frame_to_draw] self.rect[0] = self.position[0] self.rect[1] = self.position[1] self.current_frame_name = new_frame_to_draw def SetPosition(self, position): self.position = position self.rect[0] = position[0] self.rect[1] = position[1] #print self.rect def MakeScaledVersion(self, key_name, size): """ keyname - what the scaled version should be called. eg ('really small', (0,0)) size - x,y tuple. """ self.modified_images[key_name] = {} mi = self.modified_images[key_name] for frame_name, image_rect in self.modified_images['originals'].items(): image = pygame.transform.scale(image_rect[0], size) #TODO: probably need to change the size of the rect here. r = (image_rect[1][0], image_rect[1][1], size[0], size[1]) new_rect = pygame.Rect(r) mi[frame_name] = [image, new_rect] def LoadImages(self, image_dict = {}): """ image_dict - should be a dictionary which is keyed by the frame name, and valued by an image for that frame. If the dict is {} then the images are loaded from disk. """ if image_dict == {}: for x in self.character_image_dict.keys(): self.images[x] = load_image(self.character_image_dict[x], -1, 1) else: self.images = image_dict def LoadAnimationData(self): """ """ #get_animations, get_layer_order = read_anim_data(self.animation_name) animations, layer_order = read_anim_data(self.animation_set_name) self.animations = animations self.layer_order = layer_order def move(self, direction): self.position += direction self.rect.move_ip(direction, 0) #self.rect = self.rect.clamp(SCREENRECT) def ResetImageRect(self): """ After changing the self.images dict this should be called. """ self.image, self.rect = self.images[self.current_frame_name] self.rect[0] = self.position[0] self.rect[1] = self.position[1] def SetLogicalImages(self, x_y): """ Sets the appropriate images for the place on the logical grid. """ self.images = self.modified_images[("scaled", x_y)] self.ResetImageRect() def update(self, frame_name =None, percent_trans = None): #def update(self ): """ frame_name - this is the name of the frame to draw. percent_trans - is the alpha value for which to draw If frame_name, and percent_trans are None then they are worked out for themselves. """ if frame_name != None and percent_trans != None: pass if self.anims[self.current_animation].StillGoing(): new_frame_to_draw = self.anims[self.current_animation].NewFrame() if new_frame_to_draw: self.current_frame_name = new_frame_to_draw self.image, self.rect = self.images[new_frame_to_draw] self.rect[0] = self.position[0] self.rect[1] = self.position[1] self.anims[self.current_animation].last_frame = new_frame_to_draw else: # old frame to be rendered. pass else: # figure out what to do at end of anim. pass new_rdpyg/urdpyg/sounds.py0000644000175100017510000001257110075765413016177 0ustar renerene00000000000000""" file: sounds.py purpose: to load all the sounds, and manage the playing of them. Probably have different sets of sounds in here somehow. NOTE: not using pygames channel queueing as it only allows one sound to be queued. Also the sound can only be queued on a certain channel. """ import pygame import os import glob import time from pygame.locals import * SOUND_PATH = os.path.join("..", "data", "sounds") def get_sound_list(path = SOUND_PATH): """ gets a list of sound names without thier path, or extension. """ # load a list of sounds without path at the beginning and .ogg at the end. sound_list = map(lambda x:x[len(path)+1:-4], glob.glob(os.path.join(path,"*.ogg")) ) return sound_list SOUND_LIST = get_sound_list() class SoundManager: """ Controls loading, mixing, and playing the sounds. Having seperate classes allows different groups of sounds to be loaded, and unloaded from memory easily. Useage: sm = SoundManager() sm.Load() """ def __init__(self, sound_list = SOUND_LIST, sound_path = SOUND_PATH): """ """ self.mixer = None self.music = None self.sounds = {} self.chans = {} self._debug_level = 0 self.sound_list = sound_list self.sound_path = sound_path # sounds which are queued to play. self.queued_sounds = [] def _debug(self, x, debug_level = 0): """ """ if self._debug_level > debug_level: print x def Load(self, sound_list = [], sound_path = "."): """Loads sounds.""" sounds = self.sounds if not pygame.mixer: for name in sound_list: sounds[name] = None return for name in sound_list: if not sounds.has_key(name): fullname = os.path.join(sound_path, name+'.ogg') try: sound = pygame.mixer.Sound(fullname) except: sound = None self._debug("Error loading sound", fullname) sounds[name] = sound def GetSound(self, name): """ Returns a Sound object for the given name. """ if not self.sounds.has_key(name): self.Load([name]) return self.sounds[name] def Stop(self, name): if self.chans.has_key(name): if self.chans[name]: if self.chans[name].get_busy(): self.chans[name].stop() def StopAll(self): """ stops all sounds. """ for name in self.chans.keys(): self.Stop(name) def Play(self, name, volume=[1.0, 1.0], wait = 0, loop = 0): """ Plays the sound with the given name. name - of the sound. volume - left and right. Ranges 0.0 - 1.0 wait - used to control what happens if sound is allready playing: 0 - will not wait if sound playing. play anyway. 1 - if there is a sound of this type playing wait for it. 2 - if there is a sound of this type playing do not play again. loop - number of times to loop. -1 means forever. """ vol_l, vol_r = volume sound = self.GetSound(name) if sound: if wait in [1,2]: if self.chans.has_key(name) and self.chans[name].get_busy(): if wait == 1: # sound is allready playing we wait for it to finish. self.queued_sounds.append((name, volume, wait)) return elif wait == 2: # not going to play sound if playing. return self.chans[name] = sound.play(loop) if not self.chans[name]: if loop == 1: # forces a channel to return. we fade that out, # and enqueue our one. self.chans[name] = pygame.mixer.find_channel(1) #TODO: does this fadeout block? self.chans[name].fadeout(100) self.chans[name].queue(sound) else: # the pygame api doesn't allow you to queue a sound and # tell it to loop. So we hope for the best, and queue # the sound. self.queued_sounds.append((name, volume, wait)) # delete the None channel here. del self.chans[name] elif self.chans[name]: self.chans[name].set_volume(vol_l, vol_r) def Update(self, elapsed_time): """ """ for name in self.chans.keys(): if not self.chans[name]: # it may be a NoneType I think. del self.chans[name] elif not self.chans[name].get_busy(): del self.chans[name] old_queued = self.queued_sounds self.queued_sounds = [] for snd_info in old_queued: self.Play(*snd_info) def PlayMusic(self, musicname): """ Plays a music track. Only one can be played at a time. So if there is one playing, it will be stopped and the new one started. """ music = self.music if not music: return if music.get_busy(): #we really should fade out nicely and #wait for the end music event, for now, CUT music.stop() fullname = os.path.join('sounds', musicname) music.load(fullname) music.play(-1) music.set_volume(1.0) new_rdpyg/README.txt0000644000175100017510000000514510157502635014471 0ustar renerene00000000000000------------------------------------------------------ ALPHA BETA CRAP! Not finished yet. It is in its infant stages at the moment for what it wants to be. Please see the TODO.txt for things that need to be done. Please email rene AT py3d DOT org before starting on too much though. Eventually the website for this project will be http://rdpyg.sf.net/ So check there as well. Also check out this wiki page: http://www.py3d.org/mywiki/PygameExtras Status: at this stage, moving bits and pieces of code in from various projects of mine. Lots of cleaning up needed at this point. Again see TODO.txt ------------------------------------------------------ = INSTALL = You may want to remove any existing rdpyg and urdpyg packages before installing. python setup.py install Then run the tests: cd tests python run_all_tests.py Then run the interactive visual and sound tests. They are named sounds*.py visual*.py Check out the documentation in the docs/ directory. = Description = A collection of code for games using python. Mostly code for use with games made with pygame, and/or pyopengl. Allthough some of it can be used outside. == Stable and unstable parts == There are two main parts to this. The stable part(rdpyg), and the unstable one(urdpy). The unstable urdpyg part has some code which is either: - untested, - buggy, - undocumented, - incomplete, - without tests, - likely to have its api change. The rdpyg package should be none of those things. It should be code which is allready used in a few games, and works well. = Project goals = High quality. Well, I hope! * Good documentation. * Nice, html docs, doc strings, tutorials, and examples. * Tests for everything. * Consistent api. * Data driven api. * Simple api. Code which has been, and is being used in games only. 'Engine' code will not be put in. It must have actually been used in a game! Release early, release often. Only release a stable version 'when it is ready'. Other cliches! = Features = Only the features which currently exist and are usable are listed. ... hrmmm... This library does nothing! Please come again later. Check out the tests, and examples directories. They have a number of programs using the code. To run the tests you need to install first. = Make docs = There is a shell script which uses the py2html.py from http://www.lemburg.com/files/python/ to colourise the python scripts. ps. To the fucker who stole my bike in Amsterdam: Thank you! I was getting sick of riding it and finding places to lock it up. You showed me my folley in not using a chain thicker than my wrist. new_rdpyg/TODO.txt0000644000175100017510000000323210157511347014274 0ustar renerene00000000000000 Make a way to generate docs. - Make index pages for tests. link to py and html py versions. - Make docs for modules. Texture packing/cutting. - make it faster for lots of small images. - make a way to cut up bigger images into smaller ones. Fix up spritegl to be lots better... see todos in spritegl.py Make some spritegl test apps. Game performance diagnostics. - set it up to make profile reports easily(like a command line/config opt). - graphing fps over time. - showing how much time each main section takes. - eg Display, Update etc. Remove as many dependencies as possible. Try and keep pyopengl and pygame stuff seperate from stuff that can be used without either. Decide on a coding standard, and make all of the source conform to it. make a way to run all of the visual_test_* tests automatically. - each visual_test should do its thing and then exit. - run each visual_test in its own process? Think of a way to make the paths and vtimer apis similar. tests for the following things: util/quaternion.py util/vtimer.py draw/pyopengl/particles.py Examples: ------------------------------ May do these as part of a tutorial series. Full games should be kept out of here perhaps. Maybe convert some of the gamelets to use rdpyg. DONE ---------- == Tue Dec 14 18:12:34 EST 2004 == Make syntax highlighted versions of the tests. make a way to run all of the test_* tests automatically. == Sat Jun 26 23:09:00 EST 2004 == Document all the_app methods. == Sat Jun 26 22:41:37 EST 2004 == Fix up visual_test_paths.py clean it up as much as possible. == Sat Jun 26 21:37:55 EST 2004 == Make a minimal app test. new_rdpyg/make_docs.sh0000755000175100017510000000055610160167703015255 0ustar renerene00000000000000 # make the test documentation. ./tools/py2html.py ~/mystuff/python/new_rdpyg/tests/*.py mv tests/*.html docs/tests/ # create the module documentation. happydoc -d docs/rdpyg/ rdpyg --author="Rene Dudfield rene@py3d.org" -t "Random python game extras." happydoc -d docs/urdpyg/ urdpyg --author="Rene Dudfield rene@py3d.org" -t "Random python game extras." new_rdpyg/setup.py0000644000175100017510000000151510075765550014510 0ustar renerene00000000000000#!/usr/bin/env python # see http://www.python.org/doc/current/dist/setup-script.html # for distutil options. # import os, sys from distutils.core import setup packages = ['rdpyg', 'rdpyg.app', 'rdpyg.draw', 'rdpyg.draw.pygame', 'rdpyg.draw.pyopengl', # 'rdpyg.effects', # 'rdpyg.font_effects', # 'rdpyg.gui', 'rdpyg.sprites', 'rdpyg.util', 'urdpyg', 'urdpyg.map', 'urdpyg.converters', ] # Go force and multiply setup(name="rdpyg", version="0.4", description="Useful code for python games. RanDom Python Game extras", author="Many authors, Rene Dudfield", author_email="rene@py3d.org", url="http://www.py3d.org/rdpyg/", packages=packages, )