""" Version: 1.71 August 22, 2005 Developed in-house for an OSCON talk. Demonstrates suitability of Pygame for coding a programmatically controlled, scene-based presentation manager (not a new idea -- a reimplementation of an old idea). Fixed some typos after the show. -- Kirby (c) 2005, 4D Solutions, GNU Public License. """ import pygame pygame.font.init() pygame.display.init() pygame.mixer.init() from pygame.locals import * import threading import time import sys import random class Content(object): """ Used to pass media content """ step = 1,1 milliseconds = 100 fontsize = 20 scrolldirection = 1 scrollwidth = 600 fontcolor = 'black' font = 'verdana' def __getattr__(self, prop): return None class Resource( object ): """ Standard API for all Resource objects. Some don't respond to some keys, so the default method in every case is to do nothing """ def run(self): pass def stop(self): pass def pause(self): pass def unpause(self): pass def restart(self): pass def start(self): pass def next(self): pass def prev(self): pass def join(self): pass def isAlive(self): pass class Stillimage( Resource ): """ Place a still Image at params.topleft or autocenter) """ def __init__(self, params, scene): self.scene = scene self.screen = scene.screen self.theimage = pygame.image.load(params.filename).convert() self.topleft = params.topleft def start (self): w,h = self.theimage.get_size() if self.topleft: lc = self.topleft else: lc = 512 - w//2, 384 - h//2 self.rect = pygame.Rect(lc,(w,h)) self.screen.blit(self.theimage, self.rect) pygame.display.update() class Stilltext( Resource ): """ Place still text at params.topleft or autocenter) """ def __init__(self, params, scene): self.scene = scene self.screen = scene.screen self.filename = params.filename self.fontsize = params.fontsize self.font = pygame.font.SysFont('verdana',self.fontsize) self.topleft = params.topleft def start (self): lines = open(self.filename).readlines() numlines = len(lines) leading = self.fontsize//4 surfaces = [] for i in range(numlines): theline = lines[i][:-1] theline = theline.replace('\t',' ') surfaces.append ( self.font.render(theline,1, pygame.color.Color('black')) ) row = self.topleft[0], self.topleft[1] + ((self.fontsize + leading) * i) self.screen.fill(pygame.color.Color(self.scene.bg), pygame.Rect(row,(600,self.fontsize + leading)) ) self.screen.blit(surfaces[i], pygame.Rect(row,(600,self.fontsize + leading)), pygame.Rect(0,0,600, self.fontsize + leading) ) pygame.display.update() class Movingimage( threading.Thread, Resource ): """ Image moves around the screen """ moving = True looping = True def __init__(self, params, scene): self.scene = scene self.screen = scene.screen self.posrect = params.posrect self.theimage = pygame.image.load(params.filename).convert() self.step = params.step threading.Thread.__init__(self) def run (self): hstep, vstep = self.step while self.looping: if self.moving: if self.posrect.right>1040 or self.posrect.left<-10: hstep = -hstep if self.posrect.bottom>700 or self.posrect.top<60: vstep = -vstep self.screen.fill(pygame.color.Color(self.scene.bg), self.posrect) self.posrect = self.posrect.move(hstep,vstep) self.screen.blit(self.theimage, self.posrect) pygame.display.update() def restart(self): self.moving = True def pause (self): self.moving = False def stop (self): self.looping = False class Flipimage (Resource ): def __init__ (self, params, scene ): self.scene = scene self.screen = scene.screen self.imagelist = params.imagelist self.imagenum = 0 self.rect = None self.topleft = params.topleft def start(self): if self.rect: self.screen.fill(pygame.color.Color(self.scene.bg), self.rect) self.theimage = pygame.image.load(self.imagelist[self.imagenum]).convert() w,h = self.theimage.get_size() if self.topleft: lc = self.topleft else: lc = 512 - w//2, 384 - h//2 self.rect = pygame.Rect(lc,(w,h)) self.screen.blit(self.theimage, self.rect) pygame.display.update() def run(self): self.start() def next(self): self.imagenum += 1 if self.imagenum == len(self.imagelist): self.imagenum = 0 self.start() def prev(self): self.imagenum -= 1 if self.imagenum == -1: self.imagenum = len(self.imagelist)-1 self.start() class Autoflipimage ( threading.Thread, Resource ): def __init__ (self, params, scene ): self.scene = scene self.screen = scene.screen self.imagelist = params.imagelist self.usercenter = params.usercenter self.imagenum = 0 self.rect = None self.topleft = None self.milliseconds = params.milliseconds if not self.milliseconds: self.milliseconds = 100 self.topleft = params.topleft self.looping = True self.flipping = True threading.Thread.__init__(self) def run (self): while self.looping: if self.flipping: self.theimage = pygame.image.load(self.imagelist[self.imagenum]).convert() if self.rect: self.screen.fill(pygame.color.Color(self.scene.bg), self.rect) w,h = self.theimage.get_size() if self.topleft: lc = self.topleft elif self.usercenter: lc = self.usercenter[0] - w//2, self.usercenter[1] - h//2 else: lc = 512 - w//2, 384 - h//2 self.rect = pygame.Rect(lc,(w,h)) self.screen.blit(self.theimage, self.rect) pygame.display.update() self.imagenum += 1 if self.imagenum == len(self.imagelist): self.imagenum = 0 pygame.time.delay(self.milliseconds) def restart(self): self.imagenum = 0 self.flipping = True def pause (self): self.flipping = False def unpause (self): self.flipping = True def stop (self): self.looping = False class Scrolltextfile ( threading.Thread, Resource ): def __init__ (self, params, scene ): self.scene = scene self.screen = scene.screen self.filename = params.filename self.milliseconds = params.milliseconds self.displaylines = params.displaylines self.fontsize = params.fontsize self.rect = None self.looping = True self.scrolling = True self.font = params.font self.font = pygame.font.SysFont(self.font,self.fontsize) self.fontcolor = params.fontcolor self.topleft = params.topleft self.scrolldirection = params.scrolldirection self.scrollwidth = params.scrollwidth if not self.topleft: self.topleft = 100,100 threading.Thread.__init__(self) def run (self): lines = open(self.filename).readlines() lines.append("--------------------------------------") lines.append(" ") self.offset = 0 numlines = len(lines) leading = self.fontsize//4 if not self.displaylines: self.displaylines = 600//(self.fontsize + leading) if self.scrolldirection<>1: therange = list(reversed(range(self.displaylines))) else: therange = range(self.displaylines) while self.looping: if self.scrolling: surfaces = [] for i in therange: theline = lines[(i+self.offset) % numlines][:-1] theline = theline.replace('\t',' ') surfaces.append ( self.font.render(theline,1, pygame.color.Color(self.fontcolor)) ) for i in therange: row = self.topleft[0], self.topleft[1]+((self.fontsize + leading) * i) self.screen.fill(pygame.color.Color(self.scene.bg), pygame.Rect(row,(self.scrollwidth, self.fontsize + leading)) ) self.screen.blit(surfaces[i], pygame.Rect(row,(600,self.fontsize + leading)), pygame.Rect(0,0,self.scrollwidth, self.fontsize + leading) ) self.offset += 1 pygame.display.update() pygame.time.delay(self.milliseconds) def restart(self): self.offset = 0 self.scrolling = True def pause (self): self.scrolling = False def unpause (self): self.scrolling = True def stop (self): self.looping = False class Movieplayer( threading.Thread, Resource ): def __init__( self, params, scene): self.scene = scene self.screen = scene.screen self.filename = params.filename self.topleft = params.topleft self.themovie = None threading.Thread.__init__(self) def run ( self ): if not self.themovie: self.themovie = pygame.movie.Movie(self.filename) w,h = self.themovie.get_size() if not self.topleft: self.topleft = 512 - w//2, 384 - h//2 self.themovie.set_display(self.screen, pygame.Rect(self.topleft, (w,h))) self.themovie.play() def restart ( self ): if self.themovie.get_busy(): self.themovie.stop() self.themovie.rewind() self.themovie.play() def stop ( self ): if self.themovie.get_busy(): self.themovie.stop() def unpause(self): # resume play if not playing if self.themovie.get_busy(): self.themovie.play() pause = stop class Coderunner( threading.Thread, Resource ): """ Runs a generator with output rendered to a surface """ def __init__( self, params, scene): self.scene = scene self.screen = scene.screen self.usercenter = params.usercenter self.topleft = params.topleft self.milliseconds = params.milliseconds self.generator = params.generator self.fontsize = params.fontsize self.font = params.font self.font = pygame.font.SysFont(self.font,self.fontsize) threading.Thread.__init__(self) def run ( self ): self.f = self.generator() self.looping = True self.iterating = True self.rect = None while self.looping: if self.iterating == True: output = self.f.next() if not type(output)==type(''): output = str(output) surface = self.font.render(output,1,pygame.color.Color('black')) if self.rect: self.screen.fill(pygame.color.Color(self.scene.bg), self.rect) w,h = surface.get_size() if self.topleft: lc = self.topleft elif self.usercenter: lc = self.usercenter[0] - w//2, self.usercenter[1] - h//2 else: lc = 512 - w//2, 384 - h//2 self.screen.blit(surface, pygame.Rect(lc,(w,h)) ) self.rect = pygame.Rect(lc,(w,h)) pygame.display.update() pygame.time.delay(self.milliseconds) def restart ( self ): self.f = self.generator() self.iterating = True def stop ( self ): self.looping = False def unpause(self): self.iterating = True def pause ( self ): self.iterating = False class Scene ( object ): footerfont = pygame.font.SysFont('verdana',20) headerfont = pygame.font.SysFont('verdana',40) def __init__(self, screen, bg, name, num, hfcolor='black', contents=[]): self.screen = screen self.bg = bg self.name = name self.num = num self.hfcolor = hfcolor self.contents = contents self.resources = [] def display(self): s = self.screen s.fill(pygame.color.Color(self.bg)) today = time.ctime().split() today = "%s, %s %s, %s" % (today[0], today[1], today[2], today[4]) footer0 = self.footerfont.render(today,1,pygame.color.Color(self.hfcolor)) footer1 = self.footerfont.render('OSCON 2005',1,pygame.color.Color(self.hfcolor)) footer2 = self.footerfont.render(str(self.num),1,pygame.color.Color(self.hfcolor)) header = self.headerfont.render(self.name,1,pygame.color.Color(self.hfcolor)) w,h = header.get_size() s.blit(footer1, (450,730)) s.blit(footer0, (20,730)) s.blit(footer2, (950,730)) s.blit(header, (512 - w//2, 10)) self.resources = [] for o in self.contents: if o.content_type == 'movie': self.resources.append(Movieplayer( o, self)) elif o.content_type == 'movingimage': self.resources.append(Movingimage( o, self)) elif o.content_type == 'flipimage': self.resources.append(Flipimage( o, self )) elif o.content_type == 'autoflip': self.resources.append(Autoflipimage( o, self )) elif o.content_type == 'scrollfile': self.resources.append(Scrolltextfile( o, self )) elif o.content_type == 'stillimage': self.resources.append(Stillimage( o, self )) elif o.content_type == 'stilltext': self.resources.append(Stilltext( o, self )) elif o.content_type == 'coderunner': self.resources.append(Coderunner( o, self )) def run(self): for r in self.resources: if hasattr(r,"themovie"): pygame.mixer.quit() r.start() def end(self): for r in self.resources: r.stop() if r.isAlive(): r.join() if not pygame.mixer.get_init(): pygame.mixer.init() self.resources = [] # path options fpath = "c:/Documents and Settings/Kirby/My Documents/Projects/oscon2005/" # fpath = "C:/Documents and Settings/Kirby/Desktop/oscon2005/" """ Each slide or scene is set up inside a function, the purpose of which is to pass in some slide-level parameters, including a list of resources called 'contents', a list of surface objects to be displayed. Many of these surface objects invoke their own threads, so that the outer keyboard loop remains in effect (keystrokes get passed to internal content, e.g. to pause a video clip or whatever). """ def setscene_welcome(s, num=0): """ Scroll this source code with animated graphic """ mobj = Content() mobj.content_type = 'scrollfile' mobj.fontsize = 14 mobj.filename = fpath + "oscon2005.py" contents = [mobj] graphics = [] for pic in ['ch1.gif','ch2.gif','ch3.gif','ch4.gif', 'ch5.gif','ch6.gif','ch7.gif','ch8.gif','ch9.gif','ch10.gif']: graphics.append(fpath + pic) mobj = Content() mobj.content_type = 'autoflip' mobj.imagelist = graphics mobj.topleft = 680,450 contents.append(mobj) mobj = Content() mobj.content_type = 'stillimage' mobj.filename = fpath + 'osconbanner.gif' mobj.topleft = 780,100 contents.append(mobj) scene = Scene( s, 'white', 'Welcome to OSCON 2005', num, contents = contents) return scene def setscene_thankyou(s, num=0): """ Your willingness to participate in the free and open source revolution has given humanity a new vector, towards a more sustainable and happier career as crew of Spaceship Earth. """ contents = [] for r in range(5): mobj = Content() mobj.content_type = 'stillimage' mobj.filename = fpath + 'osconbanner.gif' mobj.topleft = 150 + r*150,100 contents.append(mobj) mobj = Content() mobj.content_type = 'stilltext' mobj.filename = fpath + "thankyou.txt" mobj.fontsize = 30 mobj.topleft = (280,400) contents.append(mobj) mobj = Content() mobj.content_type = 'stilltext' mobj.filename = fpath + "optional.txt" mobj.fontsize = 30 mobj.topleft = (330,550) contents.append(mobj) scene = Scene( s, 'white', 'Thank You!', num, contents = contents) return scene def setscene_rbf(s, num=0): """ RBF slide; intro to a series of collaborations """ graphics = [] for pic in ['rbfjitter.jpg','vesphere.jpg','domecar.gif', 'dymaxcar.gif','Mtl-biosphere.jpg','eye.gif','bfitm.png', 'bmc1.jpg', 'build.gif','buckyworks.gif','epball1.gif', 'edapple2.jpg','synbook.jpg','buckystampssm.png', 'ohman12192004.jpg','conf_06.gif', 'conf_02.gif', 'conf_03.gif']: graphics.append(fpath + pic) mobj = Content() mobj.content_type = 'flipimage' mobj.imagelist = graphics mobj.milliseconds = 500 scene = Scene( s, 'white', 'R. Buckminster Fuller (RBF)', num, contents = [mobj]) return scene def setscene_collab(s, num=0): """ A scrolling lists of collaborations and contributions that emerged to define the Fuller School (the list goes on, and gets longer). I've been in on a few of these, lots of times I'm just an onlooker from afar. """ mobj = Content() mobj.content_type = 'scrollfile' mobj.filename = fpath + "collablist.txt" mobj.fontsize = 20 mobj.milliseconds = 500 mobj.fontcolor = 'yellow' mobj.font = 'courier' mobj.scrollwidth = 820 contents = [mobj] scene = Scene( s, 'black', 'A Web of Collaborations', num, hfcolor='yellow', contents = [mobj]) return scene def setscene_rywalt(s, num=0): """ Chris unfolds the World Game "game board" creating a digital library video clip """ mobj = Content() mobj.content_type = 'movie' mobj.filename = fpath + "dymaxion_2003.animation.mpeg" mobj.topleft = (110,70) scene = Scene( s, 'white', 'Chris Rywalt Plays World Game', num, contents = [mobj]) return scene def setscene_metoo(s, num=0): """ One of my early animations, derived from a POV-Ray tutorial with some Fuller School twists """ mobj = Content() mobj.content_type = 'movie' mobj.filename = fpath + "ghostjit.mpeg" scene = Scene( s, 'black', 'Me Too!', num, hfcolor = "orange", contents = [mobj]) return scene def setscene_wanderers(s, num=0): """ A cultural phenomenon: the Math Wars = a breakdown in agreement over what and how to teach mathematics. My view is the open source community has plenty to offer, and would provide a valuable service by competing in the recruiting of faculty and students to a curriculum designed to pass on core skills and values. """ mobj = Content() mobj.content_type = 'flipimage' graphics = [] for i in range(2): graphics.append(fpath + ('wwwanderers.jpg','demowanderers.jpg')[i]) mobj.imagelist = graphics mobj.usercenter = (512,400) scene = Scene( s, 'black', 'Math Through Storytelling', num, hfcolor = 'yellow', contents = [mobj]) return scene def setscene_dome(s, num=0): """ Rick Bono started the ball rolling with DOME, an free software offering (GPL) built on Hugh Kenner's 'Geodesic Math and How to Use It' """ mobj = Content() mobj.content_type = 'scrollfile' mobj.filename = fpath + "Geodesic.cpp" mobj.fontcolor = 'black' mobj.fontsize = 14 contents = [mobj] mobj = Content() mobj.content_type = 'movingimage' mobj.step = 0,1 mobj.filename = fpath + 'rbono.gif' mobj.posrect = pygame.Rect(800,400,113,121) contents.append(mobj) scene = Scene( s, 'white', 'Dome by Rick Bono', num, hfcolor = 'orange', contents = contents) return scene def setscene_bonoballs(s, num=0): """ Illustrates the concept of 'frequency' """ contents=[] graphics = [] pix = ['freq1.png','freq2.png','freq3.png','freq4.png', 'freq5.png','freq6.png', 'freq7.png', 'freq8.png', 'freq9.png'] pix.extend( list(reversed(pix[:-1])) ) for i in pix: graphics.append(fpath + i) mobj = Content() mobj.content_type = 'autoflip' mobj.imagelist = graphics mobj.milliseconds = 100 contents.append(mobj) scene = Scene( s, 'white', 'Dome by Rick Bono', num, contents = contents) return scene def setscene_waterman1(s, num=0): """ Waterman Polyhedra include the maximum number of CCP vertices at a given radius or less, such that overall convexity is preserved. Larger radius polys become ever more spherical in appearance """ mobj = Content() mobj.filename = fpath + "w1000.gif" mobj.content_type='movingimage' mobj.posrect = pygame.Rect(200,200,490,467) scene = Scene( s, 'white', 'Waterman Polyhedra', num, contents = [mobj] ) return scene def setscene_waterman2(s, num=0): """ Figuring a convex hull has always been the hard part. Qhull was a godsend. More recently, QuickHull3D by has meant the whole computation may be done within a single Jython script. """ mobj = Content() mobj = Content() mobj.content_type = 'stillimage' mobj.filename = fpath + 'w500.png' scene = Scene( s, 'black', 'Waterman Polyhedra', num, hfcolor = 'yellow', contents = [mobj] ) return scene def setscene_snelson(s, num=0): """ Kenneth Snelson is an internationally recognized artist. He has also put a lot of skill into a visual atomic model. He had a stormy relationship with Fuller, after a happy start at Black Mountain College, owing to a tug-o-war for ownership/priority vis-a-vis tensegrity a.k.a. floating compression. Both took out patents. """ graphics = [] for pic in ['Ken_Snelsonsmall.gif','eqtower.jpg','29-AltComplexAtm.jpeg.jpg', '26-Neon.jpeg.jpg','ForestDevCross.jpg','WoodenXPiece.jpg']: graphics.append(fpath + pic) mobj = Content() mobj.content_type = 'flipimage' mobj.imagelist = graphics scene = Scene( s, 'white', 'Kenneth Snelson', num, contents = [mobj]) return scene def setscene_eig(s, num=0): """ Kenneth Snelson (and Fuller) inspired Gerald de Jong to create Elastic Interval Geometry (EIG), a simple concept with for exploring dynamic networks, where the edges resist being pushed or pulled from some ideal length. In Fluidiom, Gerald let EIG networks randomly emerge and had his program select those best able to cover distance, per some supplied algorithm. Karl Erickson and Russell Chu were adept EIG sculptors i.e. Struck power users and contributed to the specimens below (Struck provided animations in the form of a POV-Ray clock loop). SpringDance and Springie came later in the story (i.e. after Struck). """ contents = [] mobj = Content() mobj.content_type = 'movie' mobj.filename = fpath + "Dolphin.mpg" mobj.topleft = (10,90) contents.append(mobj) mobj = Content() mobj.content_type = 'movie' mobj.filename = fpath + "Golem.mpg" mobj.topleft = (355,90) contents.append(mobj) mobj = Content() mobj.content_type = 'movie' mobj.filename = fpath + "IcosaFlip.mpg" mobj.topleft = (700,90) contents.append(mobj) mobj = Content() mobj.content_type = 'movie' mobj.filename = fpath + "Fishy.mpg" mobj.topleft = (110,400) contents.append(mobj) mobj = Content() mobj.content_type = 'movie' mobj.filename = fpath + "Bird.mpg" mobj.topleft = (510,400) contents.append(mobj) scene = Scene( s, 'black', 'Elastic Interval Geometry (EIG)', num, hfcolor = 'yellow', contents = contents) return scene def setscene_bellivm(s, num=0): """ Alexander Graham Bell pioneer the development of a space frame known as the octet truss, which has a close relationship with the CCP sphere packing. Fuller found out about this later. """ graphics = [] contents = [] pics = [('belltower.jpg',(150,70)), ('smbellbigkite.jpg',(550,70)), ('truss.gif',(150,450)), ('archforum1.jpg',(550,320)) ] for pic in pics: mobj = Content() mobj.content_type = 'stillimage' mobj.filename = fpath + pic[0] mobj.topleft = pic[1] contents.append(mobj) scene = Scene( s, 'white', 'Octet Truss', num, contents = contents ) return scene def setscene_quadrays(s, num=0): """ Doing this kind of tetrahedron-focused geometry led David Chako and others to invent tetrays or quadray geometry, a way of doing vector arithmetic that gives easy integer coordinates to many of our concentric hierarchy vertices Programming around Quadrays is what led me to explore some new (to me) languages, always reimplementing a similar design. I went from FoxPro to Java, then to Python. What hooked me about Python was the interactive shell, plus operator overloading, which FoxPro didn't support. I continued to use Visual FoxPro though, in various professional programming jobs. This was also time when I looked fairly seriously at Haskell, Ocaml, Scheme and LISP -- and J. """ graphics = [] graphics.append(fpath + "quadray.png") graphics.append(fpath + "rhdodeca.jpg") graphics.append(fpath + "povlabels.gif") graphics.append(fpath + "quadraycode.jpg") graphics.append(fpath + "hoops.gif") graphics.append(fpath + "javasamp.jpg") graphics.append(fpath + "fox.gif") mobj = Content() mobj.content_type = 'flipimage' mobj.imagelist = graphics scene = Scene( s, 'white', 'Quadrays', num, contents = [mobj] ) return scene def setscene_cosmichierarchy(s, num=0): """ The concentric hierarchy is a way of presenting a sequence of polyhedra such that their many logical relationships are made clear and memorable """ graphics = [] for i in range(1,11): pic = 'ch'+str(i)+'.gif' graphics.append(fpath + pic) graphics += list(reversed(graphics[:-1])) mobj = Content() mobj.content_type = 'autoflip' mobj.milliseconds = 200 mobj.imagelist = graphics scene = Scene( s, 'white', 'Concentric Hierarchy', num, contents = [mobj] ) return scene def setscene_grunch(s, num=0): """ Towards the end of his life, Fuller contemplated the significance of swift globalization, and posited that corporations were in a transformative position, both dissolving national boundaries for selfish ends, and inadvertently creating the conditions for a new management philosophy based on letting intellectual goods cooperate to greater synergetic advantage (e.g. the free software development model, now recognized and embraced in many tech-savvy board rooms). """ graphics = [] for pic in ['obey1.gif','obey2.gif']: graphics.append(fpath + pic) mobj = Content() mobj.content_type = 'autoflip' mobj.imagelist = graphics mobj.milliseconds = 444 scene = Scene( s, 'white', 'Grunch of Giants', num, contents = [mobj]) return scene def setscene_eja(s, num=0): """ Ed was one of Fuller's primary collaborators. Ed's high level of discipline made it possible for Fuller to make deeper forays into philosophy and literature, plus Ed gave us the 'Synergetics Dictionary' (a four-volume compendium of Fuller's "pattern language"). Ed also worked on the Wichita House Project (a.k.a. the DDU, or Dymaxion Deployment Unit). """ contents = [] pics = [ ('cia.png',(600,100)), ('ejarbf2.jpg',(150,150)), ('eja.jpg',(150,450)) ] for pic in pics: mobj = Content() mobj.content_type = 'stillimage' mobj.filename = fpath + pic[0] mobj.topleft = pic[1] contents.append(mobj) mobj = Content() mobj.content_type = 'autoflip' mobj.imagelist = fpath + 'eja.gif', fpath + 'june.gif' mobj.topleft = (400,100) mobj.milliseconds = 2000 contents.append(mobj) mobj1 = Content() mobj1.content_type = 'stilltext' mobj1.filename = fpath + "edbio.txt" mobj1.fontsize = 20 mobj1.topleft = 250,450 contents.append(mobj1) scene = Scene( s, 'white', 'Ed Applewhite (EJA)', num, contents = contents) return scene def setscene_europix(s, num=0): """ The intellectual property theme was big at Europython. Coincidentally, the campus where we met features a mascot based on a Disney character, similar to University of Oregons's in my neck of the woods: http://www.goducks.com/ Tintin is another important cartoon character in Europe, part of a shared heritage. One of the lawyers present used some Tintin images in his slides, saying he knew the rules well enough to know that he was operating within them. """ mobj = Content() mobj.content_type = 'flipimage' graphics = [] for i in range(9): graphics.append(fpath + 'euro'+str(i) + '.jpg') graphics.append('prp.jpg') # People's Repub. of Perl (frm Larry's SOTO) mobj.imagelist = graphics mobj.usercenter = (512,400) scene = Scene( s, 'black', 'Scholarship & IP', num, hfcolor = 'yellow', contents = [mobj]) return scene def setscene_gst(s, num=0): """ GST might put a different spin on things than Econ, i.e. is reflective of a newer management philosophy that doesn't begin from all the same premises """ graphics = [] for pic in ['gst2.gif','gst3.gif','gst1.gif']: graphics.append(fpath + pic) mobj = Content() mobj.content_type = 'flipimage' mobj.imagelist = graphics scene = Scene( s, 'white', 'General Systems Theory (GST)', num, contents = [mobj]) return scene def setscene_eikclip(s, num=0): """ Fuller talking about what he's going to be talking about. """ mobj0 = Content() mobj0.content_type = 'movie' mobj0.filename = fpath + "04003_new.mpg" mobj0.topleft = 350,200 mobj1 = Content() mobj1.content_type = 'scrollfile' mobj1.filename = fpath + "04003_new.txt" mobj1.fontsize = 20 mobj1.milliseconds = 4000 mobj1.displaylines = 7 mobj1.fontcolor = 'orange' mobj1.topleft = 325,450 scene = Scene( s, 'black', '2 Minute EIK Archive Clip', num, hfcolor = 'orange', contents = [mobj0, mobj1]) return scene def setscene_ccp(s, num=0): """ Demonstrates closest packing of spheres. An easy place for kids to start learning Python, and 21st century math topics, is with sequences based on figurate and polyhedral numbers. Generators are good for this, and this slide features an object that renders generator output to screen. """ graphics = [] for i in range(1,12): filename = "cubanim"+str(i).zfill(2) graphics.append(fpath + filename + ".png" ) mobj0 = Content() mobj0.content_type = 'autoflip' mobj0.topleft = (400,100) mobj0.imagelist = graphics mobj0.milliseconds = 100 mobj1 = Content() mobj1.content_type = 'stilltext' mobj1.filename = fpath + "ccp.py" mobj1.fontsize = 20 mobj1.topleft = (60,200) mobj2 = Content() mobj2.content_type = 'coderunner' mobj2.usercenter = (515,350) def ccp(): shell, accum = 1,1 yield (shell, accum) f = 1 while True: shell = 10*f*f + 2 f += 1 accum += shell yield shell,accum mobj2.generator = ccp mobj2.milliseconds = 1000 mobj3 = Content() mobj3.content_type = 'autoflip' mobj3.topleft = (350,400) mobj3.imagelist = [fpath + 'smbellbigkite.jpg', fpath + 'vesphere.jpg', fpath + 'bellivm.jpg'] mobj3.milliseconds = 1000 mobj4 = Content() mobj4.content_type = 'stillimage' mobj4.topleft = (750,200) mobj4.filename = fpath + 'tetrapack.gif' scene = Scene( s, 'white', 'Closest Packing of Spheres', num, contents = [mobj2, mobj0, mobj1, mobj3, mobj4]) return scene def main(startslide, num=0): s = pygame.display.set_mode((1024,768), pygame.FULLSCREEN) pygame.mouse.set_visible(0) snd = pygame.mixer.Sound(fpath + "whoosh.wav") soundon = True # the code below serves as a sorter tray thescenes = enumerate([ setscene_welcome, setscene_rbf, setscene_collab, setscene_rywalt, setscene_metoo, setscene_wanderers, setscene_dome, setscene_bonoballs, setscene_snelson, setscene_eig, setscene_bellivm, setscene_ccp, setscene_waterman1, setscene_waterman2, setscene_quadrays, setscene_cosmichierarchy, setscene_grunch, setscene_eja, setscene_europix, setscene_gst, setscene_eikclip, setscene_thankyou ]) # slides have now been sorted... scenes = [] for i, f in thescenes: scenes.append(f(s,i)) snum = int(startslide) currscene = scenes[snum] currscene.display() if currscene.contents: currscene.run() pygame.display.update() newscene = False pygame.event.set_blocked(KEYUP) while 1: nextkey = pygame.event.wait() if not hasattr(nextkey, "key"): continue if nextkey.key == K_ESCAPE or pygame.event.peek(QUIT): print "Escape!" currscene.end() break if nextkey.key == K_r: # Rewind! if currscene.contents: for r in currscene.resources: r.restart() if nextkey.key == K_p: # Pause! if currscene.contents: for r in currscene.resources: r.pause() if nextkey.key == K_u: # Unpause! if currscene.contents: for r in currscene.resources: r.unpause() if nextkey.key == K_x: # neXt! # relevant to Flipimages if currscene.contents: for r in currscene.resources: r.next() if nextkey.key == K_v: # preVious! # relevant to Flipimages if currscene.contents: for r in currscene.resources: r.prev() if nextkey.key == K_RIGHT: # next scene snum += 1 if snum == len(scenes): snum = 0 newscene = True if nextkey.key == K_LEFT: # previous scene snum -= 1 if snum == -1: snum = len(scenes)-1 newscene = True if newscene: currscene.end() # newscene sound if soundon: if pygame.mixer.get_init(): snd.play() print snum currscene = scenes[snum] currscene.display() # initialize content (whether in its own thread or in this event loop) if currscene.contents: currscene.run() newscene = False pygame.display.update() pygame.quit() if __name__ == '__main__': if len(sys.argv)>1: startslide = sys.argv[1] else: startslide = 0 main(startslide)