+++ /dev/null
-'''\r
-Created on 15 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-from gui.constants import *\r
-import fluidsynth\r
-\r
-class Wiimote:\r
- '''\r
- Object representing a Wiimote\r
- \r
- number:\r
- The number of the Wiimote\r
- port:\r
- The pypm object representing the MIDI port on which the Wiimote emits\r
- instrument:\r
- The instrument associated with the Wiimote\r
- cursor:\r
- The cursor associated with the Wiimote\r
- '''\r
-\r
- def __init__(self, number, portNumber, port, instrument, cursor):\r
- '''\r
- Constructor\r
- \r
- number:\r
- The number of the Wiimote\r
- portNumber:\r
- The number of the port (as numbered by pypm) on which the wiimote emits\r
- port:\r
- The pypm object representing the MIDI port on which the Wiimote emits\r
- instrument:\r
- The instrument associated with the Wiimote\r
- cursor:\r
- The cursor associated with the Wiimote \r
- '''\r
- self.number = number\r
- self.portNumber = portNumber\r
- self.port = port\r
- self.instrument = instrument\r
- self.cursor = cursor\r
- self.numberPlayed = 0\r
- \r
- self.fs = fs = fluidsynth.Synth()\r
- fs.start()\r
- soundFont = r"C:\Documents and Settings\Administrator\My Documents\Telechargements\fluid-soundfont-3.1\FluidR3_GM.sf2"\r
- self.fsid = fsid = fs.sfload(soundFont)\r
- bank = 0\r
- preset = 0\r
- fs.program_select(0, fsid, bank, preset)\r
-\r
- def __del__(self) :\r
- self.fs.delete()\r
- \r
- def getNoteOnHexCode(self):\r
- return (0x90 + self.instrument.channel - 1)\r
- \r
- def getAftertouchHexCode(self):\r
- return (0xA0 + self.instrument.channel - 1)\r
- \r
- def getCCHexCode(self):\r
- return (0xB0 + self.instrument.channel - 1)\r
- \r
-# def playNote(self, note, velocity):\r
-# print 'playNote'\r
-# noteNumber = self.instrument.getNote(note)\r
-# \r
-# if noteNumber != None :\r
-# noteOnHexCode = self.getNoteOnHexCode()\r
-# CCHexCode = self.getCCHexCode()\r
-# else :\r
-# noteNumber = defaultInstrumentNote\r
-# noteOnHexCode = defaultNoteOnHexCode\r
-# CCHexCode = defaultCCHexCode\r
-# \r
-# self.port.write_short(noteOnHexCode, noteNumber , 127)\r
-# self.port.write_short(CCHexCode, 07, velocity)\r
-\r
- def playNoteByNoteNumber(self, midiNoteNumber, velocity):\r
- print 'playNoteByNumber'\r
- noteNumber = self.instrument.getNoteByNoteNumber(midiNoteNumber)\r
- fs = self.fs\r
- fs.noteon(0, noteNumber, velocity)\r
- \r
- return\r
- noteNumber = self.instrument.getNoteByNoteNumber(midiNoteNumber)\r
- \r
- if noteNumber != None :\r
- noteOnHexCode = self.getNoteOnHexCode()\r
- CCHexCode = self.getCCHexCode()\r
- else :\r
- noteNumber = defaultInstrumentNote\r
- noteOnHexCode = defaultNoteOnHexCode\r
- CCHexCode = defaultCCHexCode\r
- \r
- self.port.write_short(noteOnHexCode, noteNumber , 127)\r
- self.port.write_short(CCHexCode, 07, velocity)\r
- \r
- self.numberPlayed += 1\r
- \r
-# def stopNote(self, note):\r
-# print 'stopNote'\r
-# noteNumber = self.instrument.getNote(note)\r
-# if noteNumber != None :\r
-# noteOnHexCode = self.getNoteOnHexCode()\r
-# else :\r
-# noteNumber = defaultInstrumentNote\r
-# noteOnHexCode = defaultNoteOnHexCode\r
-# \r
-# self.port.write_short(noteOnHexCode, noteNumber, 0)\r
- \r
- def stopNoteByNoteNumber(self, midiNoteNumber):\r
- print 'stopNoteByNoteNumber'\r
- \r
- noteNumber = self.instrument.getNoteByNoteNumber(midiNoteNumber)\r
- fs = self.fs\r
- fs.noteoff(0, noteNumber)\r
- \r
- return\r
- noteNumber = self.instrument.getNoteByNoteNumber(midiNoteNumber)\r
- if noteNumber != None :\r
- noteOnHexCode = self.getNoteOnHexCode()\r
- else :\r
- noteNumber = defaultInstrumentNote\r
- noteOnHexCode = defaultNoteOnHexCode\r
- \r
- self.port.write_short(noteOnHexCode, noteNumber, 0)\r
- \r
-# def allNotesOff(self):\r
-# print 'allNoteOff'\r
-# CCHexCode = self.getCCHexCode()\r
-# self.port.write_short(CCHexCode,123,0)\r
+++ /dev/null
-'''\r
-Created on 29 mai 2009\r
-\r
-@author: samsam\r
-'''\r
-\r
-import os, sys, math\r
-\r
-import pygame\r
-from pygame.sprite import Sprite\r
-\r
-class WarpingCursor(Sprite):\r
- '''\r
- The class for animating the warping cursor\r
- \r
- screen:\r
- the screen on which the WarpingCursor is painted\r
- images:\r
- The images constituting the animation of the cursor\r
- durations:\r
- The duration of each image in the animation\r
- centerPosition:\r
- The Position of the center of the cursor\r
- _imagePointer:\r
- A pointer to the current image\r
- _animationOffset:\r
- The time elapsed since when the current image should have been displayed\r
- '''\r
- screen = None\r
- images = None\r
- durations = None\r
- centerPosition = None\r
- _imagePointer = None\r
- _animationOffset = None\r
- \r
-\r
- def __init__(self, scr, images, durations, initCenterPosition,flashImage):\r
- '''\r
- Constructor\r
- \r
- scr:\r
- the screen on which the WarpingCursor is painted\r
- images:\r
- The images constituting the animation of the cursor\r
- durations:\r
- The duration of each image in the animation\r
- initCenterPosition:\r
- The Position of the center of the cursor at the beginning \r
- '''\r
- self.screen = scr\r
- self.images = images\r
- self.flashImagePath = flashImage\r
- self.durations = durations\r
- self.centerPosition = initCenterPosition\r
- self.flashLength = 100\r
- self.flashing = False\r
- self.image = pygame.image.load(self.images[0]).convert_alpha()\r
- self._imagePointer = 0\r
- self._animationOffset = 0\r
- self._flashTimer = 0 \r
- \r
- def update(self, elapsedTime, centerPosition):\r
- '''\r
- Update the cursor's look and position\r
- \r
- elapsedTime:\r
- The time passed since the previous update\r
- centerPosition:\r
- the new position of the creep\r
- '''\r
- self._updateImage(elapsedTime)\r
- self.centerPosition = centerPosition\r
- if self.flashing :\r
- self._flashTimer += elapsedTime\r
- if self._flashTimer > self.flashLength:\r
- self.flashing = False\r
- \r
- def _updateImage(self, elapsedTime):\r
- '''\r
- Update the cursor's image\r
- \r
- elapsedTime:\r
- The time passed since the previous update\r
- '''\r
- self._animationOffset += elapsedTime\r
- \r
- if self._animationOffset > self.durations[self._imagePointer]:\r
- #New animation offset is computed first, before updating the pointer\r
- self._animationOffset -= self.durations[self._imagePointer]\r
- #point to the next image (restarts from the beginning when it reaches the end)\r
- self._imagePointer = (self._imagePointer + 1) % len(self.images)\r
- \r
- if self.flashing:\r
- self.image = pygame.image.load(self.flashImagePath).convert_alpha() \r
- else : \r
- self.image = pygame.image.load(self.images[self._imagePointer]).convert_alpha()\r
- \r
- def flash(self,flashLength = None):\r
- self._flashTimer = 0\r
- self.flashing = True\r
- if flashLength:\r
- self.flashlength = flashLength\r
- \r
- def blit(self,surface):\r
- '''\r
- Draw the circle on surface\r
- '''\r
- \r
- newPos = (self.centerPosition[0] - self.image.get_width() / 2, self.centerPosition[1] - self.image.get_height() / 2)\r
- surface.blit(self.image, newPos)\r
-\r
-def createImageListFromPath(path, imageCount):\r
- '''\r
- Create a list of images for a cursor (the concatenation of the original and reversed lists of images).\r
- Images must be stored as path/imageNumber.png\r
- \r
- path:\r
- The folder where the images for that cursor are stored\r
- imageCount:\r
- The number of images in the folder\r
- '''\r
- \r
- tempImages = [''.join([path, '/', str(i), '.png']) for i in range(imageCount)]\r
- #tempImagesReversed = tempImages[:]\r
- #tempImagesReversed.reverse()\r
- #return(tempImages+tempImagesReversed)\r
- return(tempImages) \r
-\r
-#testing\r
-if __name__ == "__main__" :\r
- window = pygame.display.set_mode((1680, 1050), pygame.FULLSCREEN)\r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock()\r
- \r
- images = createImageListFromPath('cursorImages/black',11)\r
- durations = [50 for i in range(22)]\r
- position = (400, 300)\r
- cursor = WarpingCursor(screen, images, durations, position)\r
- \r
- while True:\r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = clock.tick(50)\r
- \r
- for event in pygame.event.get():\r
- if event.type == pygame.QUIT:\r
- sys.exit()\r
- if event.type == pygame.MOUSEMOTION:\r
- position = event.pos\r
- \r
- cursor.update(timePassed, position)\r
- cursor.blit(screen)\r
- pygame.display.flip()\r
- \r
- \r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="48px"
- height="48px"
- id="svg2397"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="cursor.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor00.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs2399">
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 24 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="48 : 24 : 1"
- inkscape:persp3d-origin="24 : 16 : 1"
- id="perspective2405" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="7"
- inkscape:cx="-1.2857143"
- inkscape:cy="24.45"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1920"
- inkscape:window-height="1125"
- inkscape:window-x="1680"
- inkscape:window-y="25"
- showguides="true"
- inkscape:guide-bbox="true">
- <sodipodi:guide
- orientation="0,1"
- position="-4.4285714,24"
- id="guide3229" />
- <sodipodi:guide
- orientation="1,0"
- position="24,-18.571429"
- id="guide3231" />
- </sodipodi:namedview>
- <metadata
- id="metadata2402">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- id="path2413"
- sodipodi:cx="37.57143"
- sodipodi:cy="36.57143"
- sodipodi:rx="21.571428"
- sodipodi:ry="21.571428"
- d="M 59.142859,36.57143 A 21.571428,21.571428 0 1 1 16.000002,36.57143 A 21.571428,21.571428 0 1 1 59.142859,36.57143 z"
- transform="matrix(1.0873786,0,0,1.0873787,-16.782941,-15.838419)" />
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:0;stroke:#000000;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path3227"
- sodipodi:cx="10.928572"
- sodipodi:cy="13.928572"
- sodipodi:rx="13.785714"
- sodipodi:ry="13.785714"
- d="M 24.714286,13.928572 A 13.785714,13.785714 0 1 1 -2.8571424,13.928572 A 13.785714,13.785714 0 1 1 24.714286,13.928572 z"
- transform="matrix(1.5759606,0,0,1.567424,6.8484288,2.1217689)"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor100.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="48px"
- height="48px"
- id="svg2397"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="cursorBlue.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor00.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs2399">
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 24 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="48 : 24 : 1"
- inkscape:persp3d-origin="24 : 16 : 1"
- id="perspective2405" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="7"
- inkscape:cx="-31.071429"
- inkscape:cy="24.45"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1920"
- inkscape:window-height="1125"
- inkscape:window-x="1680"
- inkscape:window-y="25"
- showguides="true"
- inkscape:guide-bbox="true">
- <sodipodi:guide
- orientation="0,1"
- position="-4.4285714,24"
- id="guide3229" />
- <sodipodi:guide
- orientation="1,0"
- position="24,-18.571429"
- id="guide3231" />
- </sodipodi:namedview>
- <metadata
- id="metadata2402">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- id="path2413"
- sodipodi:cx="37.57143"
- sodipodi:cy="36.57143"
- sodipodi:rx="21.571428"
- sodipodi:ry="21.571428"
- d="M 59.142859,36.57143 A 21.571428,21.571428 0 1 1 16.000002,36.57143 A 21.571428,21.571428 0 1 1 59.142859,36.57143 z"
- transform="matrix(1.0873786,0,0,1.0873787,-16.782941,-15.838419)" />
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:0;stroke:#0000ff;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path3227"
- sodipodi:cx="10.928572"
- sodipodi:cy="13.928572"
- sodipodi:rx="13.785714"
- sodipodi:ry="13.785714"
- d="M 24.714286,13.928572 A 13.785714,13.785714 0 1 1 -2.8571424,13.928572 A 13.785714,13.785714 0 1 1 24.714286,13.928572 z"
- transform="matrix(1.5759606,0,0,1.567424,6.8484293,2.1217687)"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor100.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="48px"
- height="48px"
- id="svg2397"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="cursorGreen.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor00.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs2399">
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 24 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="48 : 24 : 1"
- inkscape:persp3d-origin="24 : 16 : 1"
- id="perspective2405" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="7"
- inkscape:cx="-31.071429"
- inkscape:cy="24.45"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1920"
- inkscape:window-height="1125"
- inkscape:window-x="1680"
- inkscape:window-y="25"
- showguides="true"
- inkscape:guide-bbox="true">
- <sodipodi:guide
- orientation="0,1"
- position="-4.4285714,24"
- id="guide3229" />
- <sodipodi:guide
- orientation="1,0"
- position="24,-18.571429"
- id="guide3231" />
- </sodipodi:namedview>
- <metadata
- id="metadata2402">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00ff00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- id="path2413"
- sodipodi:cx="37.57143"
- sodipodi:cy="36.57143"
- sodipodi:rx="21.571428"
- sodipodi:ry="21.571428"
- d="M 59.142859,36.57143 A 21.571428,21.571428 0 1 1 16.000002,36.57143 A 21.571428,21.571428 0 1 1 59.142859,36.57143 z"
- transform="matrix(1.0873786,0,0,1.0873787,-16.782941,-15.838419)" />
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:0;stroke:#00ff00;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path3227"
- sodipodi:cx="10.928572"
- sodipodi:cy="13.928572"
- sodipodi:rx="13.785714"
- sodipodi:ry="13.785714"
- d="M 24.714286,13.928572 A 13.785714,13.785714 0 1 1 -2.8571424,13.928572 A 13.785714,13.785714 0 1 1 24.714286,13.928572 z"
- transform="matrix(1.5759606,0,0,1.567424,6.8484285,2.1680224)"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor100.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="48px"
- height="48px"
- id="svg2397"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="cursorRed.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor00.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs2399">
- <inkscape:perspective
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 24 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="48 : 24 : 1"
- inkscape:persp3d-origin="24 : 16 : 1"
- id="perspective2405" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="7"
- inkscape:cx="-31.071429"
- inkscape:cy="22.307143"
- inkscape:current-layer="layer1"
- showgrid="true"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:window-width="1920"
- inkscape:window-height="1125"
- inkscape:window-x="1680"
- inkscape:window-y="25"
- showguides="true"
- inkscape:guide-bbox="true">
- <sodipodi:guide
- orientation="0,1"
- position="-4.4285714,24"
- id="guide3229" />
- <sodipodi:guide
- orientation="1,0"
- position="24,-18.571429"
- id="guide3231" />
- </sodipodi:namedview>
- <metadata
- id="metadata2402">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- id="path2413"
- sodipodi:cx="37.57143"
- sodipodi:cy="36.57143"
- sodipodi:rx="21.571428"
- sodipodi:ry="21.571428"
- d="M 59.142859,36.57143 A 21.571428,21.571428 0 1 1 16.000002,36.57143 A 21.571428,21.571428 0 1 1 59.142859,36.57143 z"
- transform="matrix(1.0873786,0,0,1.0873787,-16.782941,-15.838419)" />
- <path
- sodipodi:type="arc"
- style="fill:#ffffff;fill-opacity:0;stroke:#ff0000;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path3227"
- sodipodi:cx="10.928572"
- sodipodi:cy="13.928572"
- sodipodi:rx="13.785714"
- sodipodi:ry="13.785714"
- d="M 24.714286,13.928572 A 13.785714,13.785714 0 1 1 -2.8571424,13.928572 A 13.785714,13.785714 0 1 1 24.714286,13.928572 z"
- transform="matrix(1.5759606,0,0,1.567424,6.9912861,2.264626)"
- inkscape:export-filename="/home/sbenven/Desktop/cursorGifs/cursor100.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90" />
- </g>
-</svg>
+++ /dev/null
-desktop background desktop.png
-
-input font Vera.ttf 16
-input background input.normal.png
-input color #000000
-input:focus background input.focus.png
-input padding_left 6
-input padding_right 6
-input padding_top 3
-input padding_bottom 3
-
-link font Vera.ttf 24
-link color #0000FF
-link:hover color #FF0000
-link:down color #00FF00
-
-label font Vera.ttf 16
-label color #000000
-
-document font Vera.ttf 16
-document color #000000
-div font Vera.ttf 16
-div color #000000
-
-td font Vera.ttf 16
-td color #000000
-th font Vera.ttf 16
-th color #000000
-
-h1 font Vera.ttf 24
-h1 color #000000
-h2 font Vera.ttf 20
-h2 color #000000
-h3 font Vera.ttf 16
-h3 color #000000
-h4 font Vera.ttf 14
-h4 color #000000
-h5 font Vera.ttf 12
-h5 color #000000
-h6 font Vera.ttf 10
-h6 color #000000
-
-ul font Vera.ttf 16
-ul color #000000
-ol font Vera.ttf 16
-ol color #000000
-li font Vera.ttf 16
-li color #000000
-li padding_left 32
-
-pre font mono 16
-pre color #000000
-code font mono 16
-code color #000000
-
-checkbox off checkbox.off.normal.tga
-checkbox on checkbox.on.normal.tga
-checkbox:hover off checkbox.off.hover.tga
-checkbox:hover on checkbox.on.hover.tga
-checkbox:down off checkbox.off.hover.tga
-checkbox:down on checkbox.on.hover.tga
-
-switch off checkbox.off.normal.tga
-switch on checkbox.on.normal.tga
-switch:hover off checkbox.off.hover.tga
-switch:hover on checkbox.on.hover.tga
-switch:down off checkbox.off.hover.tga
-switch:down on checkbox.on.hover.tga
-
-radio off radio.off.normal.tga
-radio on radio.on.normal.tga
-radio:hover off radio.off.hover.tga
-radio:hover on radio.on.hover.tga
-radio:down off radio.off.hover.tga
-radio:down on radio.on.hover.tga
-
-button background button.normal.tga
-button:hover background button.hover.tga
-button:down background button.down.tga
-button padding_left 8
-button padding_right 8
-button padding_top 1
-button padding_bottom 1
-button.label font Vera.ttf 16
-button.label color #000000
-
-slider background slider.tga
-slider bar slider.bar.normal.tga
-slider:hover bar slider.bar.hover.tga
-slider width 16
-slider height 16
-
-hslider background hslider.tga
-hslider bar hslider.bar.normal.tga
-hslider:hover bar hslider.bar.hover.tga
-hslider:down bar hslider.bar.hover.tga
-hslider width 16
-hslider height 16
-
-vslider background vslider.tga
-vslider bar vslider.bar.normal.tga
-vslider:hover bar vslider.bar.hover.tga
-vslider:down bar vslider.bar.hover.tga
-vslider width 16
-vslider height 16
-
-xhscrollbar height 16
-xhscrollbar background scroller.slide.h.tga
-xhscrollbar bar scroller.slide.bar.normal.tga
-xhscrollbar:hover bar scroller.slide.bar.hover.tga
-
-xvscrollbar width 16
-xvscrollbar background scroller.slide.v.tga
-xvscrollbar bar scroller.slide.bar.normal.tga
-xvscrollbar:hover bar scroller.slide.bar.hover.tga
-
-hscrollbar.slider background hslider.tga
-hscrollbar.slider bar hslider.bar.normal.tga
-hscrollbar.slider:hover bar hslider.bar.hover.tga
-hscrollbar.slider:down bar hslider.bar.hover.tga
-hscrollbar.slider width 16
-hscrollbar.slider height 16
-hscrollbar minus hslider.left.tga
-hscrollbar plus hslider.right.tga
-
-vscrollbar.slider background vslider.tga
-vscrollbar.slider bar vslider.bar.normal.tga
-vscrollbar.slider:hover bar vslider.bar.hover.tga
-vscrollbar.slider:down bar vslider.bar.hover.tga
-vscrollbar.slider width 16
-vscrollbar.slider height 16
-vscrollbar minus vslider.up.tga
-vscrollbar plus vslider.down.tga
-
-
-select.selected background select.selected.normal.tga
-select.selected:hover background select.selected.hover.tga
-select.selected:down background select.selected.down.tga
-select.selected padding_left 4
-select.selected padding_right 4
-select.selected padding_top 1
-select.selected padding_bottom 1
-select.arrow background select.arrow.normal.tga
-select.arrow:hover background select.arrow.hover.tga
-select.arrow:down background select.arrow.down.tga
-select.arrow padding_left 1
-select.arrow padding_right 1
-
-select.options background select.options.png
-select.option background select.option.normal.png
-select.option:hover background select.option.hover.png
-select.option:down background select.option.hover.png
-select.option padding_left 4
-select.option padding_right 4
-select.option padding_top 1
-select.option padding_bottom 1
-#select.option border_top 1
-#select.option border_right 1
-#select.option border_bottom 1
-#select.option border_left 1
-
-select.option.label font Vera.ttf 16
-select.option.label color #000000
-select.options padding_left 1
-select.options padding_right 1
-select.options padding_top 1
-select.options padding_bottom 1
-select arrow select.arrow.png
-
-
-dialog background dialog.bar.png
-xdialog.bar background dialog.bar.png
-dialog.bar padding_left 8
-dialog.bar padding_right 8
-dialog.bar padding_top 2
-dialog.bar padding_bottom 1
-dialog.bar.close image dialog.close.normal.tga
-dialog.bar.close:hover image dialog.close.hover.tga
-dialog.bar.close:down image dialog.close.down.tga
-dialog.main background dialog.png
-dialog.main padding_left 8
-dialog.main padding_right 8
-dialog.main padding_top 4
-dialog.main padding_bottom 4
-
-keysym font Vera.ttf 16
-keysym background input.normal.png
-keysym color #000000
-keysym:focus background input.focus.png
-keysym padding_left 6
-keysym padding_right 6
-keysym padding_top 3
-keysym padding_bottom 3
-
-tool background tool.normal.tga
-tool:hover background tool.hover.tga
-tool:down background tool.down.tga
-tool padding_left 4
-tool padding_right 4
-tool padding_top 1
-tool padding_bottom 1
-tool.label font Vera.ttf 16
-tool.label color #000000
-
-menu background menu.normal.tga
-menu:hover background menu.hover.tga
-menu:down background menu.down.tga
-menu padding_left 6
-menu padding_right 6
-menu padding_top 3
-menu padding_bottom 3
-menu.label font Vera.ttf 16
-menu.label color #000000
-
-menu-open background menu.down.tga
-menu-open:hover background menu.down.tga
-menu-open:down background menu.down.tga
-menu-open padding_left 6
-menu-open padding_right 6
-menu-open padding_top 3
-menu-open padding_bottom 3
-
-menu.options background select.options.png
-menu.option background select.option.normal.png
-menu.option:hover background select.option.hover.png
-menu.option:down background select.option.hover.png
-menu.option padding_left 6
-menu.option padding_right 6
-menu.option padding_top 1
-menu.option padding_bottom 1
-menu.option.label font Vera.ttf 16
-menu.option.label color #000000
-menu.options padding_left 1
-menu.options padding_right 1
-menu.options padding_top 1
-menu.options padding_bottom 1
-menu arrow select.arrow.tga
-
-
-scrollarea.content background #ffffff
-scrollarea.content padding_left 1
-scrollarea.content padding_right 1
-scrollarea.content padding_top 1
-scrollarea.content padding_bottom 1
-
-
-list.item background list.item.normal.png
-list.item:hover background list.item.down.png
-list.item:down background list.item.down.png
-list.item padding_left 4
-list.item padding_right 4
-list.item padding_top 2
-list.item padding_bottom 2
-list.item margin_bottom 1
-list.item align -1
-list.item.label font Vera.ttf 14
-list.item.label color #000000
-
-list background list.png
-list padding_left 1
-list padding_right 1
-list padding_top 1
-list padding_bottom 1
-list.content background #eeeeee
-list.content padding_left 1
-list.content padding_right 1
-list.content padding_top 1
-list.content padding_bottom 1
-
-filedialog.folder image filebrowser.folder.png
-filedialog.label font Vera.ttf 14
-filedialog.label color #000000
-filedialog.title.label font Vera.ttf 16
-filedialog.title.label color #000000
-filedialog.input font Vera.ttf 14
-filedialog.input background input.normal.png
-filedialog.input color #000000
-filedialog.input:focus background input.focus.png
-filedialog.input padding_left 6
-filedialog.input padding_right 6
-filedialog.input padding_top 3
-filedialog.input padding_bottom 3
-
-dialog.title.label font Vera.ttf 16
-dialog.title.label color #000000
-
-
-progressbar background progressbar.tga
-progressbar bar progressbar.bar.tga
-progressbar width 16
-progressbar height 16
+++ /dev/null
-import pygame
-from pygame.locals import *
-pygame.display.init()
-pygame.display.set_mode((80,80),32)
-
-def prep(name):
- fname = name+".png"
- img = pygame.image.load(fname)
- w,h = img.get_width()/2,img.get_height()/2
-
- out = pygame.Surface((w*3,h*3),SWSURFACE|SRCALPHA,32)
- out.fill((0,0,0,0))
- out.blit(img.subsurface(0,0,w,h),(0,0))
- out.blit(img.subsurface(w,0,w,h),(w*2,0))
- out.blit(img.subsurface(0,h,w,h),(0,h*2))
- out.blit(img.subsurface(w,h,w,h),(w*2,h*2))
- for i in range(0,w):
- img = out.subsurface((w-1,0,1,h*3)).convert_alpha()
- out.blit(img,(w+i,0))
- for i in range(0,h):
- img = out.subsurface((0,h-1,w*3,1)).convert_alpha()
- out.blit(img,(0,h+i))
-
- return out,w,h
-
-todo = [
- ('button.normal','dot.normal',None,3,3,'789456123'),
- ('button.hover','dot.hover',None,3,3,'789456123'),
- ('button.down','dot.down',None,3,3,'789456123'),
-
- ('checkbox.off.normal','box.normal',None,2,2,'7913'),
- ('checkbox.on.normal','box.down','check',2,2,'7913'),
- ('checkbox.off.hover','box.hover',None,2,2,'7913'),
- ('checkbox.on.hover','box.hover','check',2,2,'7913'),
-
- ('radio.off.normal','dot.normal',None,2,2,'7913'),
- ('radio.on.normal','dot.down','radio',2,2,'7913'),
- ('radio.off.hover','dot.hover',None,2,2,'7913'),
- ('radio.on.hover','dot.hover','radio',2,2,'7913'),
-
- ('tool.normal','box.normal',None,3,3,'789456123'),
- ('tool.hover','box.hover',None,3,3,'789456123'),
- ('tool.down','box.down',None,3,3,'789456123'),
-
- ('hslider','idot.normal',None,3,3,'789456123'),
- ('hslider.bar.normal','dot.normal',None,3,3,'789456123'),
- ('hslider.bar.hover','dot.hover',None,3,3,'789456123'),
- ('hslider.left','sbox.normal','left',2,2,'7913'),
- ('hslider.right','sbox.normal','right',2,2,'7913'),
-
-
- ('vslider','idot.normal',None,3,3,'789456123'),
- ('vslider.bar.normal','vdot.normal',None,3,3,'789456123'),
- ('vslider.bar.hover','vdot.hover',None,3,3,'789456123'),
- ('vslider.up','vsbox.normal','up',2,2,'7913'),
- ('vslider.down','vsbox.normal','down',2,2,'7913'),
-
- ('dialog.close.normal','rdot.hover',None,2,2,'7913'),
- ('dialog.close.hover','rdot.hover','x',2,2,'7913'),
- ('dialog.close.down','rdot.down','x',2,2,'7913'),
-
- ('menu.normal','desktop',None,1,1,'7'),
- ('menu.hover','box.normal',None,3,3,'789456123'),
- ('menu.down','box.down',None,3,3,'789456123'),
-
- ('select.selected.normal','box.normal',None,3,3,'788455122'),
- ('select.selected.hover','box.hover',None,3,3,'788455122'),
- ('select.selected.down','box.down',None,3,3,'788455122'),
-
- ('select.arrow.normal','box.hover',None,3,3,'889556223'),
- ('select.arrow.hover','box.hover',None,3,3,'889556223'),
- ('select.arrow.down','box.down',None,3,3,'889556223'),
-
- ('progressbar','sbox.normal',None,3,3,'789456123'),
- ('progressbar.bar','box.hover',None,3,3,'789456123'),
- ]
-
-for fname,img,over,ww,hh,s in todo:
- print fname
- img,w,h = prep(img)
- out = pygame.Surface((ww*w,hh*h),SWSURFACE|SRCALPHA,32)
- out.fill((0,0,0,0))
- n = 0
- for y in range(0,hh):
- for x in range(0,ww):
- c = int(s[n])
- xx,yy = (c-1)%3,2-(c-1)/3
- out.blit(img.subsurface((xx*w,yy*h,w,h)),(x*w,y*h))
- n += 1
- if over != None:
- over = pygame.image.load(over+".png")
- out.blit(over,(0,0))
- pygame.image.save(out,fname+".tga")
-
-
-
-
-
+++ /dev/null
-dot and box.xcf:
-
-color -170
-
-.down
-.hover +64 brightness
-.normal, grayscale +127 brightness, +48 contrast
-
+++ /dev/null
-desktop background desktop.png
-
-input font Vera.ttf 16
-input background input.normal.png
-input color #000000
-input:focus background input.focus.png
-input padding_left 6
-input padding_right 6
-input padding_top 3
-input padding_bottom 3
-
-label font Vera.ttf 16
-label color #000000
-
-document font Vera.ttf 16
-document color #000000
-div font Vera.ttf 16
-div color #000000
-
-td font Vera.ttf 16
-td color #000000
-th font Vera.ttf 16
-th color #000000
-
-h1 font Vera.ttf 24
-h1 color #000000
-h2 font Vera.ttf 20
-h2 color #000000
-h3 font Vera.ttf 16
-h3 color #000000
-h4 font Vera.ttf 14
-h4 color #000000
-h5 font Vera.ttf 12
-h5 color #000000
-h6 font Vera.ttf 10
-h6 color #000000
-
-ul font Vera.ttf 16
-ul color #000000
-ol font Vera.ttf 16
-ol color #000000
-li font Vera.ttf 16
-li color #000000
-li padding_left 32
-
-pre font mono 16
-pre color #000000
-code font mono 16
-code color #000000
-
-checkbox off checkbox.off.normal.png
-checkbox on checkbox.on.normal.png
-checkbox:down off checkbox.off.down.png
-checkbox:down on checkbox.on.down.png
-
-switch off checkbox.off.normal.png
-switch on checkbox.on.normal.png
-switch:down off checkbox.off.down.png
-switch:down on checkbox.on.down.png
-
-radio off radio.off.normal.png
-radio on radio.on.normal.png
-radio:down off radio.off.down.png
-radio:down on radio.on.down.png
-
-button background button.normal.png
-button:down background button.down.png
-button padding_left 8
-button padding_right 8
-button padding_top 1
-button padding_bottom 1
-button.label font Vera.ttf 16
-button.label color #000000
-
-slider background slider.png
-slider bar slider.bar.normal.png
-slider:down bar slider.bar.down.png
-slider width 16
-slider height 16
-
-hslider background slider.png
-hslider bar slider.bar.normal.png
-hslider:down bar slider.bar.down.png
-hslider width 16
-hslider height 16
-
-vslider background slider.png
-vslider bar slider.bar.normal.png
-vslider:down bar slider.bar.down.png
-vslider width 16
-vslider height 16
-
-select.selected background select.selected.normal.png
-#select.selected:down background select.selected.down.png
-select.selected padding_left 4
-select.selected padding_right 4
-select.selected padding_top 1
-select.selected padding_bottom 1
-select.arrow background select.arrow.normal.png
-select.arrow:down background select.arrow.down.png
-select.arrow padding_left 1
-select.arrow padding_right 1
-
-select.options background select.options.png
-select.option background select.option.normal.png
-#select.option:hover background select.option.hover.png
-select.option padding_left 4
-select.option padding_right 4
-select.option padding_top 1
-select.option padding_bottom 1
-#select.option border_top 1
-#select.option border_right 1
-#select.option border_bottom 1
-#select.option border_left 1
-
-select.option.label font Vera.ttf 16
-select.option.label color #000000
-select.options padding_left 1
-select.options padding_right 1
-select.options padding_top 1
-select.options padding_bottom 1
-select arrow select.arrow.png
-
-
-dialog.bar background dialog.bar.png
-dialog.bar padding_left 8
-dialog.bar padding_right 8
-dialog.bar padding_top 2
-dialog.bar padding_bottom 1
-dialog.bar.close image dialog.close.normal.png
-dialog.bar.close:down image dialog.close.down.png
-dialog.main background dialog.png
-dialog.main padding_left 8
-dialog.main padding_right 8
-dialog.main padding_top 4
-dialog.main padding_bottom 4
-
-keysym font helvetica 16
-keysym background input.normal.png
-keysym color #000000
-keysym:focus background input.focus.png
-keysym padding_left 6
-keysym padding_right 6
-keysym padding_top 3
-keysym padding_bottom 3
-
-tool background tool.normal.png
-tool:down background tool.down.png
-tool padding_left 4
-tool padding_right 4
-tool padding_top 1
-tool padding_bottom 1
-tool.label font Vera.ttf 16
-tool.label color #000000
-
-menu background menu.normal.png
-menu:hover background menu.hover.png
-menu:down background menu.down.png
-menu padding_left 6
-menu padding_right 6
-menu padding_top 3
-menu padding_bottom 3
-menu.label font Vera.ttf 16
-menu.label color #000000
-
-menu-open background menu.down.png
-menu-open:down background menu.down.png
-menu-open padding_left 6
-menu-open padding_right 6
-menu-open padding_top 3
-menu-open padding_bottom 3
-
-menu.options background select.options.png
-menu.option background menu.option.normal.png
-menu.option:hover background menu.option.hover.png
-#menu.option.label color #FF0000
-menu.option padding_left 6
-menu.option padding_right 6
-menu.option padding_top 1
-menu.option padding_bottom 1
-menu.option.label font Vera.ttf 16
-menu.option.label color #000000
-menu.options padding_left 1
-menu.options padding_right 1
-menu.options padding_top 1
-menu.options padding_bottom 1
-menu arrow select.arrow.png
-
-
-scrollarea.content background #ffffff
-scrollarea.content padding_left 1
-scrollarea.content padding_right 1
-scrollarea.content padding_top 1
-scrollarea.content padding_bottom 1
-hscrollbar height 15
-##hscrollbar background scroller.slide.h.png
-hscrollbar background slider.png
-##hscrollbar bar scroller.slide.bar.normal.png
-hscrollbar bar slider.bar.normal.png
-##hscrollbar:down bar scroller.slide.bar.down.png
-vscrollbar width 15
-##vscrollbar background scroller.slide.v.png
-vscrollbar background slider.png
-##vscrollbar bar scroller.slide.bar.normal.png
-vscrollbar bar slider.bar.normal.png
-##vscrollbar:down bar scroller.slide.bar.down.png
-
-list.item background list.item.normal.png
-#list.item:down background list.item.down.png
-list.item padding_left 4
-list.item padding_right 4
-list.item padding_top 2
-list.item padding_bottom 2
-list.item margin_bottom 1
-list.item align -1
-list.item.label font Vera.ttf 14
-list.item.label color #000000
-
-list background list.png
-list padding_left 1
-list padding_right 1
-list padding_top 1
-list padding_bottom 1
-list.content background #eeeeee
-list.content padding_left 1
-list.content padding_right 1
-list.content padding_top 1
-list.content padding_bottom 1
-
-filedialog.folder image filebrowser.folder.png
-filedialog.label font Vera.ttf 14
-filedialog.label color #000000
-filedialog.title.label font Vera.ttf 16
-filedialog.title.label color #000000
-filedialog.input font Vera.ttf 14
-filedialog.input background input.normal.png
-filedialog.input color #000000
-filedialog.input:focus background input.focus.png
-filedialog.input padding_left 6
-filedialog.input padding_right 6
-filedialog.input padding_top 3
-filedialog.input padding_bottom 3
-
-
+++ /dev/null
-tool.draw image icons48.draw.tga
-tool.pixel image icons48.pixel.tga
-tool.line image icons48.line.tga
-tool.fill image icons48.fill.tga
-
-tool.select image icons48.select.tga
-tool.eraser image icons48.eraser.tga
-
-tool.tile image icons48.tile.tga
-tool.code image icons48.code.tga
-tool.bkgr image icons48.bkgr.tga
+++ /dev/null
-# odict.py
-# An Ordered Dictionary object
-# Copyright (C) 2005 Nicola Larosa, Michael Foord
-# E-mail: nico AT tekNico DOT net, fuzzyman AT voidspace DOT org DOT uk
-
-# This software is licensed under the terms of the BSD license.
-# http://www.voidspace.org.uk/python/license.shtml
-# Basically you're free to copy, modify, distribute and relicense it,
-# So long as you keep a copy of the license with it.
-
-# Documentation at http://www.voidspace.org.uk/python/odict.html
-# For information about bugfixes, updates and support, please join the
-# Pythonutils mailing list:
-# http://groups.google.com/group/pythonutils/
-# Comments, suggestions and bug reports welcome.
-
-"""A dict that keeps keys in insertion order"""
-from __future__ import generators
-
-__author__ = ('Nicola Larosa <nico-NoSp@m-tekNico.net>,'
- 'Michael Foord <fuzzyman AT voidspace DOT org DOT uk>')
-
-__docformat__ = "restructuredtext en"
-
-__revision__ = '$Id: odict.py 129 2005-09-12 18:15:28Z teknico $'
-
-__version__ = '0.2.2'
-
-__all__ = ['OrderedDict', 'SequenceOrderedDict']
-
-import sys
-INTP_VER = sys.version_info[:2]
-if INTP_VER < (2, 2):
- raise RuntimeError("Python v.2.2 or later required")
-
-import types, warnings
-
-class OrderedDict(dict):
- """
- A class of dictionary that keeps the insertion order of keys.
-
- All appropriate methods return keys, items, or values in an ordered way.
-
- All normal dictionary methods are available. Update and comparison is
- restricted to other OrderedDict objects.
-
- Various sequence methods are available, including the ability to explicitly
- mutate the key ordering.
-
- __contains__ tests:
-
- >>> d = OrderedDict(((1, 3),))
- >>> 1 in d
- 1
- >>> 4 in d
- 0
-
- __getitem__ tests:
-
- >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[2]
- 1
- >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[4]
- Traceback (most recent call last):
- KeyError: 4
-
- __len__ tests:
-
- >>> len(OrderedDict())
- 0
- >>> len(OrderedDict(((1, 3), (3, 2), (2, 1))))
- 3
-
- get tests:
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.get(1)
- 3
- >>> d.get(4) is None
- 1
- >>> d.get(4, 5)
- 5
- >>> d
- OrderedDict([(1, 3), (3, 2), (2, 1)])
-
- has_key tests:
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.has_key(1)
- 1
- >>> d.has_key(4)
- 0
- """
-
- def __init__(self, init_val=(), strict=False):
- """
- Create a new ordered dictionary. Cannot init from a normal dict,
- nor from kwargs, since items order is undefined in those cases.
-
- If the ``strict`` keyword argument is ``True`` (``False`` is the
- default) then when doing slice assignment - the ``OrderedDict`` you are
- assigning from *must not* contain any keys in the remaining dict.
-
- >>> OrderedDict()
- OrderedDict([])
- >>> OrderedDict({1: 1})
- Traceback (most recent call last):
- TypeError: undefined order, cannot get items from dict
- >>> OrderedDict({1: 1}.items())
- OrderedDict([(1, 1)])
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d
- OrderedDict([(1, 3), (3, 2), (2, 1)])
- >>> OrderedDict(d)
- OrderedDict([(1, 3), (3, 2), (2, 1)])
- """
- self.strict = strict
- dict.__init__(self)
- if isinstance(init_val, OrderedDict):
- self._sequence = init_val.keys()
- dict.update(self, init_val)
- elif isinstance(init_val, dict):
- # we lose compatibility with other ordered dict types this way
- raise TypeError('undefined order, cannot get items from dict')
- else:
- self._sequence = []
- self.update(init_val)
-
-### Special methods ###
-
- def __delitem__(self, key):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> del d[3]
- >>> d
- OrderedDict([(1, 3), (2, 1)])
- >>> del d[3]
- Traceback (most recent call last):
- KeyError: 3
- >>> d[3] = 2
- >>> d
- OrderedDict([(1, 3), (2, 1), (3, 2)])
- >>> del d[0:1]
- >>> d
- OrderedDict([(2, 1), (3, 2)])
- """
- if isinstance(key, types.SliceType):
- # FIXME: efficiency?
- keys = self._sequence[key]
- for entry in keys:
- dict.__delitem__(self, entry)
- del self._sequence[key]
- else:
- # do the dict.__delitem__ *first* as it raises
- # the more appropriate error
- dict.__delitem__(self, key)
- self._sequence.remove(key)
-
- def __eq__(self, other):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d == OrderedDict(d)
- True
- >>> d == OrderedDict(((1, 3), (2, 1), (3, 2)))
- False
- >>> d == OrderedDict(((1, 0), (3, 2), (2, 1)))
- False
- >>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
- False
- >>> d == dict(d)
- False
- >>> d == False
- False
- """
- if isinstance(other, OrderedDict):
- # FIXME: efficiency?
- # Generate both item lists for each compare
- return (self.items() == other.items())
- else:
- return False
-
- def __lt__(self, other):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
- >>> c < d
- True
- >>> d < c
- False
- >>> d < dict(c)
- Traceback (most recent call last):
- TypeError: Can only compare with other OrderedDicts
- """
- if not isinstance(other, OrderedDict):
- raise TypeError('Can only compare with other OrderedDicts')
- # FIXME: efficiency?
- # Generate both item lists for each compare
- return (self.items() < other.items())
-
- def __le__(self, other):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
- >>> e = OrderedDict(d)
- >>> c <= d
- True
- >>> d <= c
- False
- >>> d <= dict(c)
- Traceback (most recent call last):
- TypeError: Can only compare with other OrderedDicts
- >>> d <= e
- True
- """
- if not isinstance(other, OrderedDict):
- raise TypeError('Can only compare with other OrderedDicts')
- # FIXME: efficiency?
- # Generate both item lists for each compare
- return (self.items() <= other.items())
-
- def __ne__(self, other):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d != OrderedDict(d)
- False
- >>> d != OrderedDict(((1, 3), (2, 1), (3, 2)))
- True
- >>> d != OrderedDict(((1, 0), (3, 2), (2, 1)))
- True
- >>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
- False
- >>> d != dict(d)
- True
- >>> d != False
- True
- """
- if isinstance(other, OrderedDict):
- # FIXME: efficiency?
- # Generate both item lists for each compare
- return not (self.items() == other.items())
- else:
- return True
-
- def __gt__(self, other):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
- >>> d > c
- True
- >>> c > d
- False
- >>> d > dict(c)
- Traceback (most recent call last):
- TypeError: Can only compare with other OrderedDicts
- """
- if not isinstance(other, OrderedDict):
- raise TypeError('Can only compare with other OrderedDicts')
- # FIXME: efficiency?
- # Generate both item lists for each compare
- return (self.items() > other.items())
-
- def __ge__(self, other):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
- >>> e = OrderedDict(d)
- >>> c >= d
- False
- >>> d >= c
- True
- >>> d >= dict(c)
- Traceback (most recent call last):
- TypeError: Can only compare with other OrderedDicts
- >>> e >= d
- True
- """
- if not isinstance(other, OrderedDict):
- raise TypeError('Can only compare with other OrderedDicts')
- # FIXME: efficiency?
- # Generate both item lists for each compare
- return (self.items() >= other.items())
-
- def __repr__(self):
- """
- Used for __repr__ and __str__
-
- >>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
- >>> r1
- "OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])"
- >>> r2 = repr(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
- >>> r2
- "OrderedDict([('a', 'b'), ('e', 'f'), ('c', 'd')])"
- >>> r1 == str(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
- True
- >>> r2 == str(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
- True
- """
- return '%s([%s])' % (self.__class__.__name__, ', '.join(
- ['(%r, %r)' % (key, self[key]) for key in self._sequence]))
-
- def __setitem__(self, key, val):
- """
- Allows slice assignment, so long as the slice is an OrderedDict
- >>> d = OrderedDict()
- >>> d['a'] = 'b'
- >>> d['b'] = 'a'
- >>> d[3] = 12
- >>> d
- OrderedDict([('a', 'b'), ('b', 'a'), (3, 12)])
- >>> d[:] = OrderedDict(((1, 2), (2, 3), (3, 4)))
- >>> d
- OrderedDict([(1, 2), (2, 3), (3, 4)])
- >>> d[::2] = OrderedDict(((7, 8), (9, 10)))
- >>> d
- OrderedDict([(7, 8), (2, 3), (9, 10)])
- >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)))
- >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
- >>> d
- OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
- >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)), strict=True)
- >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
- >>> d
- OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
-
- >>> a = OrderedDict(((0, 1), (1, 2), (2, 3)), strict=True)
- >>> a[3] = 4
- >>> a
- OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a
- OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)])
- Traceback (most recent call last):
- ValueError: slice assignment must be from unique keys
- >>> a = OrderedDict(((0, 1), (1, 2), (2, 3)))
- >>> a[3] = 4
- >>> a
- OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a
- OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a
- OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a[::-1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> a
- OrderedDict([(3, 4), (2, 3), (1, 2), (0, 1)])
-
- >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> d[:1] = 3
- Traceback (most recent call last):
- TypeError: slice assignment requires an OrderedDict
-
- >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
- >>> d[:1] = OrderedDict([(9, 8)])
- >>> d
- OrderedDict([(9, 8), (1, 2), (2, 3), (3, 4)])
- """
- if isinstance(key, types.SliceType):
- if not isinstance(val, OrderedDict):
- # FIXME: allow a list of tuples?
- raise TypeError('slice assignment requires an OrderedDict')
- keys = self._sequence[key]
- # NOTE: Could use ``range(*key.indices(len(self._sequence)))``
- indexes = range(len(self._sequence))[key]
- if key.step is None:
- # NOTE: new slice may not be the same size as the one being
- # overwritten !
- # NOTE: What is the algorithm for an impossible slice?
- # e.g. d[5:3]
- pos = key.start or 0
- del self[key]
- newkeys = val.keys()
- for k in newkeys:
- if k in self:
- if self.strict:
- raise ValueError('slice assignment must be from '
- 'unique keys')
- else:
- # NOTE: This removes duplicate keys *first*
- # so start position might have changed?
- del self[k]
- self._sequence = (self._sequence[:pos] + newkeys +
- self._sequence[pos:])
- dict.update(self, val)
- else:
- # extended slice - length of new slice must be the same
- # as the one being replaced
- if len(keys) != len(val):
- raise ValueError('attempt to assign sequence of size %s '
- 'to extended slice of size %s' % (len(val), len(keys)))
- # FIXME: efficiency?
- del self[key]
- item_list = zip(indexes, val.items())
- # smallest indexes first - higher indexes not guaranteed to
- # exist
- item_list.sort()
- for pos, (newkey, newval) in item_list:
- if self.strict and newkey in self:
- raise ValueError('slice assignment must be from unique'
- ' keys')
- self.insert(pos, newkey, newval)
- else:
- if key not in self:
- self._sequence.append(key)
- dict.__setitem__(self, key, val)
-
- def __getitem__(self, key):
- """
- Allows slicing. Returns an OrderedDict if you slice.
- >>> b = OrderedDict([(7, 0), (6, 1), (5, 2), (4, 3), (3, 4), (2, 5), (1, 6)])
- >>> b[::-1]
- OrderedDict([(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1), (7, 0)])
- >>> b[2:5]
- OrderedDict([(5, 2), (4, 3), (3, 4)])
- >>> type(b[2:4])
- <class '__main__.OrderedDict'>
- """
- if isinstance(key, types.SliceType):
- # FIXME: does this raise the error we want?
- keys = self._sequence[key]
- # FIXME: efficiency?
- return OrderedDict([(entry, self[entry]) for entry in keys])
- else:
- return dict.__getitem__(self, key)
-
- __str__ = __repr__
-
- def __setattr__(self, name, value):
- """
- Implemented so that accesses to ``sequence`` raise a warning and are
- diverted to the new ``setkeys`` method.
- """
- if name == 'sequence':
- warnings.warn('Use of the sequence attribute is deprecated.'
- ' Use the keys method instead.', DeprecationWarning)
- # NOTE: doesn't return anything
- self.setkeys(value)
- else:
- # FIXME: do we want to allow arbitrary setting of attributes?
- # Or do we want to manage it?
- object.__setattr__(self, name, value)
-
- def __getattr__(self, name):
- """
- Implemented so that access to ``sequence`` raises a warning.
-
- >>> d = OrderedDict()
- >>> d.sequence
- []
- """
- if name == 'sequence':
- warnings.warn('Use of the sequence attribute is deprecated.'
- ' Use the keys method instead.', DeprecationWarning)
- # NOTE: Still (currently) returns a direct reference. Need to
- # because code that uses sequence will expect to be able to
- # mutate it in place.
- return self._sequence
- else:
- # raise the appropriate error
- raise AttributeError("OrderedDict has no '%s' attribute" % name)
-
- def __deepcopy__(self, memo):
- """
- To allow deepcopy to work with OrderedDict.
-
- >>> from copy import deepcopy
- >>> a = OrderedDict([(1, 1), (2, 2), (3, 3)])
- >>> a['test'] = {}
- >>> b = deepcopy(a)
- >>> b == a
- True
- >>> b is a
- False
- >>> a['test'] is b['test']
- False
- """
- from copy import deepcopy
- return self.__class__(deepcopy(self.items(), memo), self.strict)
-
-
-### Read-only methods ###
-
- def copy(self):
- """
- >>> OrderedDict(((1, 3), (3, 2), (2, 1))).copy()
- OrderedDict([(1, 3), (3, 2), (2, 1)])
- """
- return OrderedDict(self)
-
- def items(self):
- """
- ``items`` returns a list of tuples representing all the
- ``(key, value)`` pairs in the dictionary.
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.items()
- [(1, 3), (3, 2), (2, 1)]
- >>> d.clear()
- >>> d.items()
- []
- """
- return zip(self._sequence, self.values())
-
- def keys(self):
- """
- Return a list of keys in the ``OrderedDict``.
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.keys()
- [1, 3, 2]
- """
- return self._sequence[:]
-
- def values(self, values=None):
- """
- Return a list of all the values in the OrderedDict.
-
- Optionally you can pass in a list of values, which will replace the
- current list. The value list must be the same len as the OrderedDict.
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.values()
- [3, 2, 1]
- """
- return [self[key] for key in self._sequence]
-
- def iteritems(self):
- """
- >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iteritems()
- >>> ii.next()
- (1, 3)
- >>> ii.next()
- (3, 2)
- >>> ii.next()
- (2, 1)
- >>> ii.next()
- Traceback (most recent call last):
- StopIteration
- """
- def make_iter(self=self):
- keys = self.iterkeys()
- while True:
- key = keys.next()
- yield (key, self[key])
- return make_iter()
-
- def iterkeys(self):
- """
- >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys()
- >>> ii.next()
- 1
- >>> ii.next()
- 3
- >>> ii.next()
- 2
- >>> ii.next()
- Traceback (most recent call last):
- StopIteration
- """
- return iter(self._sequence)
-
- __iter__ = iterkeys
-
- def itervalues(self):
- """
- >>> iv = OrderedDict(((1, 3), (3, 2), (2, 1))).itervalues()
- >>> iv.next()
- 3
- >>> iv.next()
- 2
- >>> iv.next()
- 1
- >>> iv.next()
- Traceback (most recent call last):
- StopIteration
- """
- def make_iter(self=self):
- keys = self.iterkeys()
- while True:
- yield self[keys.next()]
- return make_iter()
-
-### Read-write methods ###
-
- def clear(self):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.clear()
- >>> d
- OrderedDict([])
- """
- dict.clear(self)
- self._sequence = []
-
- def pop(self, key, *args):
- """
- No dict.pop in Python 2.2, gotta reimplement it
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.pop(3)
- 2
- >>> d
- OrderedDict([(1, 3), (2, 1)])
- >>> d.pop(4)
- Traceback (most recent call last):
- KeyError: 4
- >>> d.pop(4, 0)
- 0
- >>> d.pop(4, 0, 1)
- Traceback (most recent call last):
- TypeError: pop expected at most 2 arguments, got 3
- """
- if len(args) > 1:
- raise TypeError, ('pop expected at most 2 arguments, got %s' %
- (len(args) + 1))
- if key in self:
- val = self[key]
- del self[key]
- else:
- try:
- val = args[0]
- except IndexError:
- raise KeyError(key)
- return val
-
- def popitem(self, i=-1):
- """
- Delete and return an item specified by index, not a random one as in
- dict. The index is -1 by default (the last item).
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.popitem()
- (2, 1)
- >>> d
- OrderedDict([(1, 3), (3, 2)])
- >>> d.popitem(0)
- (1, 3)
- >>> OrderedDict().popitem()
- Traceback (most recent call last):
- KeyError: 'popitem(): dictionary is empty'
- >>> d.popitem(2)
- Traceback (most recent call last):
- IndexError: popitem(): index 2 not valid
- """
- if not self._sequence:
- raise KeyError('popitem(): dictionary is empty')
- try:
- key = self._sequence[i]
- except IndexError:
- raise IndexError('popitem(): index %s not valid' % i)
- return (key, self.pop(key))
-
- def setdefault(self, key, defval = None):
- """
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.setdefault(1)
- 3
- >>> d.setdefault(4) is None
- True
- >>> d
- OrderedDict([(1, 3), (3, 2), (2, 1), (4, None)])
- >>> d.setdefault(5, 0)
- 0
- >>> d
- OrderedDict([(1, 3), (3, 2), (2, 1), (4, None), (5, 0)])
- """
- if key in self:
- return self[key]
- else:
- self[key] = defval
- return defval
-
- def update(self, from_od):
- """
- Update from another OrderedDict or sequence of (key, value) pairs
-
- >>> d = OrderedDict(((1, 0), (0, 1)))
- >>> d.update(OrderedDict(((1, 3), (3, 2), (2, 1))))
- >>> d
- OrderedDict([(1, 3), (0, 1), (3, 2), (2, 1)])
- >>> d.update({4: 4})
- Traceback (most recent call last):
- TypeError: undefined order, cannot get items from dict
- >>> d.update((4, 4))
- Traceback (most recent call last):
- TypeError: cannot convert dictionary update sequence element "4" to a 2-item sequence
- """
- if isinstance(from_od, OrderedDict):
- for key, val in from_od.items():
- self[key] = val
- elif isinstance(from_od, dict):
- # we lose compatibility with other ordered dict types this way
- raise TypeError('undefined order, cannot get items from dict')
- else:
- # FIXME: efficiency?
- # sequence of 2-item sequences, or error
- for item in from_od:
- try:
- key, val = item
- except TypeError:
- raise TypeError('cannot convert dictionary update'
- ' sequence element "%s" to a 2-item sequence' % item)
- self[key] = val
-
- def rename(self, old_key, new_key):
- """
- Rename the key for a given value, without modifying sequence order.
-
- For the case where new_key already exists this raise an exception,
- since if new_key exists, it is ambiguous as to what happens to the
- associated values, and the position of new_key in the sequence.
-
- >>> od = OrderedDict()
- >>> od['a'] = 1
- >>> od['b'] = 2
- >>> od.items()
- [('a', 1), ('b', 2)]
- >>> od.rename('b', 'c')
- >>> od.items()
- [('a', 1), ('c', 2)]
- >>> od.rename('c', 'a')
- Traceback (most recent call last):
- ValueError: New key already exists: 'a'
- >>> od.rename('d', 'b')
- Traceback (most recent call last):
- KeyError: 'd'
- """
- if new_key == old_key:
- # no-op
- return
- if new_key in self:
- raise ValueError("New key already exists: %r" % new_key)
- # rename sequence entry
- value = self[old_key]
- old_idx = self._sequence.index(old_key)
- self._sequence[old_idx] = new_key
- # rename internal dict entry
- dict.__delitem__(self, old_key)
- dict.__setitem__(self, new_key, value)
-
- def setitems(self, items):
- """
- This method allows you to set the items in the dict.
-
- It takes a list of tuples - of the same sort returned by the ``items``
- method.
-
- >>> d = OrderedDict()
- >>> d.setitems(((3, 1), (2, 3), (1, 2)))
- >>> d
- OrderedDict([(3, 1), (2, 3), (1, 2)])
- """
- self.clear()
- # FIXME: this allows you to pass in an OrderedDict as well :-)
- self.update(items)
-
- def setkeys(self, keys):
- """
- ``setkeys`` all ows you to pass in a new list of keys which will
- replace the current set. This must contain the same set of keys, but
- need not be in the same order.
-
- If you pass in new keys that don't match, a ``KeyError`` will be
- raised.
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.keys()
- [1, 3, 2]
- >>> d.setkeys((1, 2, 3))
- >>> d
- OrderedDict([(1, 3), (2, 1), (3, 2)])
- >>> d.setkeys(['a', 'b', 'c'])
- Traceback (most recent call last):
- KeyError: 'Keylist is not the same as current keylist.'
- """
- # FIXME: Efficiency? (use set for Python 2.4 :-)
- # NOTE: list(keys) rather than keys[:] because keys[:] returns
- # a tuple, if keys is a tuple.
- kcopy = list(keys)
- kcopy.sort()
- self._sequence.sort()
- if kcopy != self._sequence:
- raise KeyError('Keylist is not the same as current keylist.')
- # NOTE: This makes the _sequence attribute a new object, instead
- # of changing it in place.
- # FIXME: efficiency?
- self._sequence = list(keys)
-
- def setvalues(self, values):
- """
- You can pass in a list of values, which will replace the
- current list. The value list must be the same len as the OrderedDict.
-
- (Or a ``ValueError`` is raised.)
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.setvalues((1, 2, 3))
- >>> d
- OrderedDict([(1, 1), (3, 2), (2, 3)])
- >>> d.setvalues([6])
- Traceback (most recent call last):
- ValueError: Value list is not the same length as the OrderedDict.
- """
- if len(values) != len(self):
- # FIXME: correct error to raise?
- raise ValueError('Value list is not the same length as the '
- 'OrderedDict.')
- self.update(zip(self, values))
-
-### Sequence Methods ###
-
- def index(self, key):
- """
- Return the position of the specified key in the OrderedDict.
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.index(3)
- 1
- >>> d.index(4)
- Traceback (most recent call last):
- ValueError: list.index(x): x not in list
- """
- return self._sequence.index(key)
-
- def insert(self, index, key, value):
- """
- Takes ``index``, ``key``, and ``value`` as arguments.
-
- Sets ``key`` to ``value``, so that ``key`` is at position ``index`` in
- the OrderedDict.
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.insert(0, 4, 0)
- >>> d
- OrderedDict([(4, 0), (1, 3), (3, 2), (2, 1)])
- >>> d.insert(0, 2, 1)
- >>> d
- OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2)])
- >>> d.insert(8, 8, 1)
- >>> d
- OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2), (8, 1)])
- """
- if key in self:
- # FIXME: efficiency?
- del self[key]
- self._sequence.insert(index, key)
- dict.__setitem__(self, key, value)
-
- def reverse(self):
- """
- Reverse the order of the OrderedDict.
-
- >>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
- >>> d.reverse()
- >>> d
- OrderedDict([(2, 1), (3, 2), (1, 3)])
- """
- self._sequence.reverse()
-
- def sort(self, *args, **kwargs):
- """
- Sort the key order in the OrderedDict.
-
- This method takes the same arguments as the ``list.sort`` method on
- your version of Python.
-
- >>> d = OrderedDict(((4, 1), (2, 2), (3, 3), (1, 4)))
- >>> d.sort()
- >>> d
- OrderedDict([(1, 4), (2, 2), (3, 3), (4, 1)])
- """
- self._sequence.sort(*args, **kwargs)
-
-class Keys(object):
- # FIXME: should this object be a subclass of list?
- """
- Custom object for accessing the keys of an OrderedDict.
-
- Can be called like the normal ``OrderedDict.keys`` method, but also
- supports indexing and sequence methods.
- """
-
- def __init__(self, main):
- self._main = main
-
- def __call__(self):
- """Pretend to be the keys method."""
- return self._main._keys()
-
- def __getitem__(self, index):
- """Fetch the key at position i."""
- # NOTE: this automatically supports slicing :-)
- return self._main._sequence[index]
-
- def __setitem__(self, index, name):
- """
- You cannot assign to keys, but you can do slice assignment to re-order
- them.
-
- You can only do slice assignment if the new set of keys is a reordering
- of the original set.
- """
- if isinstance(index, types.SliceType):
- # FIXME: efficiency?
- # check length is the same
- indexes = range(len(self._main._sequence))[index]
- if len(indexes) != len(name):
- raise ValueError('attempt to assign sequence of size %s '
- 'to slice of size %s' % (len(name), len(indexes)))
- # check they are the same keys
- # FIXME: Use set
- old_keys = self._main._sequence[index]
- new_keys = list(name)
- old_keys.sort()
- new_keys.sort()
- if old_keys != new_keys:
- raise KeyError('Keylist is not the same as current keylist.')
- orig_vals = [self._main[k] for k in name]
- del self._main[index]
- vals = zip(indexes, name, orig_vals)
- vals.sort()
- for i, k, v in vals:
- if self._main.strict and k in self._main:
- raise ValueError('slice assignment must be from '
- 'unique keys')
- self._main.insert(i, k, v)
- else:
- raise ValueError('Cannot assign to keys')
-
- ### following methods pinched from UserList and adapted ###
- def __repr__(self): return repr(self._main._sequence)
-
- # FIXME: do we need to check if we are comparing with another ``Keys``
- # object? (like the __cast method of UserList)
- def __lt__(self, other): return self._main._sequence < other
- def __le__(self, other): return self._main._sequence <= other
- def __eq__(self, other): return self._main._sequence == other
- def __ne__(self, other): return self._main._sequence != other
- def __gt__(self, other): return self._main._sequence > other
- def __ge__(self, other): return self._main._sequence >= other
- # FIXME: do we need __cmp__ as well as rich comparisons?
- def __cmp__(self, other): return cmp(self._main._sequence, other)
-
- def __contains__(self, item): return item in self._main._sequence
- def __len__(self): return len(self._main._sequence)
- def __iter__(self): return self._main.iterkeys()
- def count(self, item): return self._main._sequence.count(item)
- def index(self, item, *args): return self._main._sequence.index(item, *args)
- def reverse(self): self._main._sequence.reverse()
- def sort(self, *args, **kwds): self._main._sequence.sort(*args, **kwds)
- def __mul__(self, n): return self._main._sequence*n
- __rmul__ = __mul__
- def __add__(self, other): return self._main._sequence + other
- def __radd__(self, other): return other + self._main._sequence
-
- ## following methods not implemented for keys ##
- def __delitem__(self, i): raise TypeError('Can\'t delete items from keys')
- def __iadd__(self, other): raise TypeError('Can\'t add in place to keys')
- def __imul__(self, n): raise TypeError('Can\'t multiply keys in place')
- def append(self, item): raise TypeError('Can\'t append items to keys')
- def insert(self, i, item): raise TypeError('Can\'t insert items into keys')
- def pop(self, i=-1): raise TypeError('Can\'t pop items from keys')
- def remove(self, item): raise TypeError('Can\'t remove items from keys')
- def extend(self, other): raise TypeError('Can\'t extend keys')
-
-class Items(object):
- """
- Custom object for accessing the items of an OrderedDict.
-
- Can be called like the normal ``OrderedDict.items`` method, but also
- supports indexing and sequence methods.
- """
-
- def __init__(self, main):
- self._main = main
-
- def __call__(self):
- """Pretend to be the items method."""
- return self._main._items()
-
- def __getitem__(self, index):
- """Fetch the item at position i."""
- if isinstance(index, types.SliceType):
- # fetching a slice returns an OrderedDict
- return self._main[index].items()
- key = self._main._sequence[index]
- return (key, self._main[key])
-
- def __setitem__(self, index, item):
- """Set item at position i to item."""
- if isinstance(index, types.SliceType):
- # NOTE: item must be an iterable (list of tuples)
- self._main[index] = OrderedDict(item)
- else:
- # FIXME: Does this raise a sensible error?
- orig = self._main.keys[index]
- key, value = item
- if self._main.strict and key in self and (key != orig):
- raise ValueError('slice assignment must be from '
- 'unique keys')
- # delete the current one
- del self._main[self._main._sequence[index]]
- self._main.insert(index, key, value)
-
- def __delitem__(self, i):
- """Delete the item at position i."""
- key = self._main._sequence[i]
- if isinstance(i, types.SliceType):
- for k in key:
- # FIXME: efficiency?
- del self._main[k]
- else:
- del self._main[key]
-
- ### following methods pinched from UserList and adapted ###
- def __repr__(self): return repr(self._main.items())
-
- # FIXME: do we need to check if we are comparing with another ``Items``
- # object? (like the __cast method of UserList)
- def __lt__(self, other): return self._main.items() < other
- def __le__(self, other): return self._main.items() <= other
- def __eq__(self, other): return self._main.items() == other
- def __ne__(self, other): return self._main.items() != other
- def __gt__(self, other): return self._main.items() > other
- def __ge__(self, other): return self._main.items() >= other
- def __cmp__(self, other): return cmp(self._main.items(), other)
-
- def __contains__(self, item): return item in self._main.items()
- def __len__(self): return len(self._main._sequence) # easier :-)
- def __iter__(self): return self._main.iteritems()
- def count(self, item): return self._main.items().count(item)
- def index(self, item, *args): return self._main.items().index(item, *args)
- def reverse(self): self._main.reverse()
- def sort(self, *args, **kwds): self._main.sort(*args, **kwds)
- def __mul__(self, n): return self._main.items()*n
- __rmul__ = __mul__
- def __add__(self, other): return self._main.items() + other
- def __radd__(self, other): return other + self._main.items()
-
- def append(self, item):
- """Add an item to the end."""
- # FIXME: this is only append if the key isn't already present
- key, value = item
- self._main[key] = value
-
- def insert(self, i, item):
- key, value = item
- self._main.insert(i, key, value)
-
- def pop(self, i=-1):
- key = self._main._sequence[i]
- return (key, self._main.pop(key))
-
- def remove(self, item):
- key, value = item
- try:
- assert value == self._main[key]
- except (KeyError, AssertionError):
- raise ValueError('ValueError: list.remove(x): x not in list')
- else:
- del self._main[key]
-
- def extend(self, other):
- # FIXME: is only a true extend if none of the keys already present
- for item in other:
- key, value = item
- self._main[key] = value
-
- def __iadd__(self, other):
- self.extend(other)
-
- ## following methods not implemented for items ##
-
- def __imul__(self, n): raise TypeError('Can\'t multiply items in place')
-
-class Values(object):
- """
- Custom object for accessing the values of an OrderedDict.
-
- Can be called like the normal ``OrderedDict.values`` method, but also
- supports indexing and sequence methods.
- """
-
- def __init__(self, main):
- self._main = main
-
- def __call__(self):
- """Pretend to be the values method."""
- return self._main._values()
-
- def __getitem__(self, index):
- """Fetch the value at position i."""
- if isinstance(index, types.SliceType):
- return [self._main[key] for key in self._main._sequence[index]]
- else:
- return self._main[self._main._sequence[index]]
-
- def __setitem__(self, index, value):
- """
- Set the value at position i to value.
-
- You can only do slice assignment to values if you supply a sequence of
- equal length to the slice you are replacing.
- """
- if isinstance(index, types.SliceType):
- keys = self._main._sequence[index]
- if len(keys) != len(value):
- raise ValueError('attempt to assign sequence of size %s '
- 'to slice of size %s' % (len(name), len(keys)))
- # FIXME: efficiency? Would be better to calculate the indexes
- # directly from the slice object
- # NOTE: the new keys can collide with existing keys (or even
- # contain duplicates) - these will overwrite
- for key, val in zip(keys, value):
- self._main[key] = val
- else:
- self._main[self._main._sequence[index]] = value
-
- ### following methods pinched from UserList and adapted ###
- def __repr__(self): return repr(self._main.values())
-
- # FIXME: do we need to check if we are comparing with another ``Values``
- # object? (like the __cast method of UserList)
- def __lt__(self, other): return self._main.values() < other
- def __le__(self, other): return self._main.values() <= other
- def __eq__(self, other): return self._main.values() == other
- def __ne__(self, other): return self._main.values() != other
- def __gt__(self, other): return self._main.values() > other
- def __ge__(self, other): return self._main.values() >= other
- def __cmp__(self, other): return cmp(self._main.values(), other)
-
- def __contains__(self, item): return item in self._main.values()
- def __len__(self): return len(self._main._sequence) # easier :-)
- def __iter__(self): return self._main.itervalues()
- def count(self, item): return self._main.values().count(item)
- def index(self, item, *args): return self._main.values().index(item, *args)
-
- def reverse(self):
- """Reverse the values"""
- vals = self._main.values()
- vals.reverse()
- # FIXME: efficiency
- self[:] = vals
-
- def sort(self, *args, **kwds):
- """Sort the values."""
- vals = self._main.values()
- vals.sort(*args, **kwds)
- self[:] = vals
-
- def __mul__(self, n): return self._main.values()*n
- __rmul__ = __mul__
- def __add__(self, other): return self._main.values() + other
- def __radd__(self, other): return other + self._main.values()
-
- ## following methods not implemented for values ##
- def __delitem__(self, i): raise TypeError('Can\'t delete items from values')
- def __iadd__(self, other): raise TypeError('Can\'t add in place to values')
- def __imul__(self, n): raise TypeError('Can\'t multiply values in place')
- def append(self, item): raise TypeError('Can\'t append items to values')
- def insert(self, i, item): raise TypeError('Can\'t insert items into values')
- def pop(self, i=-1): raise TypeError('Can\'t pop items from values')
- def remove(self, item): raise TypeError('Can\'t remove items from values')
- def extend(self, other): raise TypeError('Can\'t extend values')
-
-class SequenceOrderedDict(OrderedDict):
- """
- Experimental version of OrderedDict that has a custom object for ``keys``,
- ``values``, and ``items``.
-
- These are callable sequence objects that work as methods, or can be
- manipulated directly as sequences.
-
- Test for ``keys``, ``items`` and ``values``.
-
- >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4)))
- >>> d
- SequenceOrderedDict([(1, 2), (2, 3), (3, 4)])
- >>> d.keys
- [1, 2, 3]
- >>> d.keys()
- [1, 2, 3]
- >>> d.setkeys((3, 2, 1))
- >>> d
- SequenceOrderedDict([(3, 4), (2, 3), (1, 2)])
- >>> d.setkeys((1, 2, 3))
- >>> d.keys[0]
- 1
- >>> d.keys[:]
- [1, 2, 3]
- >>> d.keys[-1]
- 3
- >>> d.keys[-2]
- 2
- >>> d.keys[0:2] = [2, 1]
- >>> d
- SequenceOrderedDict([(2, 3), (1, 2), (3, 4)])
- >>> d.keys.reverse()
- >>> d.keys
- [3, 1, 2]
- >>> d.keys = [1, 2, 3]
- >>> d
- SequenceOrderedDict([(1, 2), (2, 3), (3, 4)])
- >>> d.keys = [3, 1, 2]
- >>> d
- SequenceOrderedDict([(3, 4), (1, 2), (2, 3)])
- >>> a = SequenceOrderedDict()
- >>> b = SequenceOrderedDict()
- >>> a.keys == b.keys
- 1
- >>> a['a'] = 3
- >>> a.keys == b.keys
- 0
- >>> b['a'] = 3
- >>> a.keys == b.keys
- 1
- >>> b['b'] = 3
- >>> a.keys == b.keys
- 0
- >>> a.keys > b.keys
- 0
- >>> a.keys < b.keys
- 1
- >>> 'a' in a.keys
- 1
- >>> len(b.keys)
- 2
- >>> 'c' in d.keys
- 0
- >>> 1 in d.keys
- 1
- >>> [v for v in d.keys]
- [3, 1, 2]
- >>> d.keys.sort()
- >>> d.keys
- [1, 2, 3]
- >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4)), strict=True)
- >>> d.keys[::-1] = [1, 2, 3]
- >>> d
- SequenceOrderedDict([(3, 4), (2, 3), (1, 2)])
- >>> d.keys[:2]
- [3, 2]
- >>> d.keys[:2] = [1, 3]
- Traceback (most recent call last):
- KeyError: 'Keylist is not the same as current keylist.'
-
- >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4)))
- >>> d
- SequenceOrderedDict([(1, 2), (2, 3), (3, 4)])
- >>> d.values
- [2, 3, 4]
- >>> d.values()
- [2, 3, 4]
- >>> d.setvalues((4, 3, 2))
- >>> d
- SequenceOrderedDict([(1, 4), (2, 3), (3, 2)])
- >>> d.values[::-1]
- [2, 3, 4]
- >>> d.values[0]
- 4
- >>> d.values[-2]
- 3
- >>> del d.values[0]
- Traceback (most recent call last):
- TypeError: Can't delete items from values
- >>> d.values[::2] = [2, 4]
- >>> d
- SequenceOrderedDict([(1, 2), (2, 3), (3, 4)])
- >>> 7 in d.values
- 0
- >>> len(d.values)
- 3
- >>> [val for val in d.values]
- [2, 3, 4]
- >>> d.values[-1] = 2
- >>> d.values.count(2)
- 2
- >>> d.values.index(2)
- 0
- >>> d.values[-1] = 7
- >>> d.values
- [2, 3, 7]
- >>> d.values.reverse()
- >>> d.values
- [7, 3, 2]
- >>> d.values.sort()
- >>> d.values
- [2, 3, 7]
- >>> d.values.append('anything')
- Traceback (most recent call last):
- TypeError: Can't append items to values
- >>> d.values = (1, 2, 3)
- >>> d
- SequenceOrderedDict([(1, 1), (2, 2), (3, 3)])
-
- >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4)))
- >>> d
- SequenceOrderedDict([(1, 2), (2, 3), (3, 4)])
- >>> d.items()
- [(1, 2), (2, 3), (3, 4)]
- >>> d.setitems([(3, 4), (2 ,3), (1, 2)])
- >>> d
- SequenceOrderedDict([(3, 4), (2, 3), (1, 2)])
- >>> d.items[0]
- (3, 4)
- >>> d.items[:-1]
- [(3, 4), (2, 3)]
- >>> d.items[1] = (6, 3)
- >>> d.items
- [(3, 4), (6, 3), (1, 2)]
- >>> d.items[1:2] = [(9, 9)]
- >>> d
- SequenceOrderedDict([(3, 4), (9, 9), (1, 2)])
- >>> del d.items[1:2]
- >>> d
- SequenceOrderedDict([(3, 4), (1, 2)])
- >>> (3, 4) in d.items
- 1
- >>> (4, 3) in d.items
- 0
- >>> len(d.items)
- 2
- >>> [v for v in d.items]
- [(3, 4), (1, 2)]
- >>> d.items.count((3, 4))
- 1
- >>> d.items.index((1, 2))
- 1
- >>> d.items.index((2, 1))
- Traceback (most recent call last):
- ValueError: list.index(x): x not in list
- >>> d.items.reverse()
- >>> d.items
- [(1, 2), (3, 4)]
- >>> d.items.reverse()
- >>> d.items.sort()
- >>> d.items
- [(1, 2), (3, 4)]
- >>> d.items.append((5, 6))
- >>> d.items
- [(1, 2), (3, 4), (5, 6)]
- >>> d.items.insert(0, (0, 0))
- >>> d.items
- [(0, 0), (1, 2), (3, 4), (5, 6)]
- >>> d.items.insert(-1, (7, 8))
- >>> d.items
- [(0, 0), (1, 2), (3, 4), (7, 8), (5, 6)]
- >>> d.items.pop()
- (5, 6)
- >>> d.items
- [(0, 0), (1, 2), (3, 4), (7, 8)]
- >>> d.items.remove((1, 2))
- >>> d.items
- [(0, 0), (3, 4), (7, 8)]
- >>> d.items.extend([(1, 2), (5, 6)])
- >>> d.items
- [(0, 0), (3, 4), (7, 8), (1, 2), (5, 6)]
- """
-
- def __init__(self, init_val=(), strict=True):
- OrderedDict.__init__(self, init_val, strict=strict)
- self._keys = self.keys
- self._values = self.values
- self._items = self.items
- self.keys = Keys(self)
- self.values = Values(self)
- self.items = Items(self)
- self._att_dict = {
- 'keys': self.setkeys,
- 'items': self.setitems,
- 'values': self.setvalues,
- }
-
- def __setattr__(self, name, value):
- """Protect keys, items, and values."""
- if not '_att_dict' in self.__dict__:
- object.__setattr__(self, name, value)
- else:
- try:
- fun = self._att_dict[name]
- except KeyError:
- OrderedDict.__setattr__(self, name, value)
- else:
- fun(value)
-
-if __name__ == '__main__':
- if INTP_VER < (2, 3):
- raise RuntimeError("Tests require Python v.2.3 or later")
- # turn off warnings for tests
- warnings.filterwarnings('ignore')
- # run the code tests in doctest format
- import doctest
- m = sys.modules.get('__main__')
- globs = m.__dict__.copy()
- globs.update({
- 'INTP_VER': INTP_VER,
- })
- doctest.testmod(m, globs=globs)
-
+++ /dev/null
-#Copyright 2006 DR0ID <dr0id@bluewin.ch> http://mypage.bluewin.ch/DR0ID
-#
-#
-#
-"""
-Allow to draw some gradients relatively easy.
-"""
-
-__author__ = "$Author: DR0ID $"
-__version__= "$Revision: 109 $"
-__date__ = "$Date: 2007-08-09 20:33:32 +0200 (Do, 09 Aug 2007) $"
-
-import pygame
-import math
-
-BLEND_MODES_AVAILABLE = False
-vernum = pygame.vernum
-if vernum[0]>=1 and vernum[1]>=8:
- BLEND_MODES_AVAILABLE = True
-
-
-class ColorInterpolator(object):
- '''
- ColorInterpolator(distance, color1, color2, rfunc, gfunc, bfunc, afunc)
-
- interpolates a color over the distance using different functions for r,g,b,a
- separately (a= alpha).
- '''
- def __init__(self, distance, color1, color2, rfunc, gfunc, bfunc, afunc):
- object.__init__(self)
-
- self.rInterpolator = FunctionInterpolator(color1[0], color2[0], distance, rfunc)
- self.gInterpolator = FunctionInterpolator(color1[1], color2[1], distance, gfunc)
- self.bInterpolator = FunctionInterpolator(color1[2], color2[2], distance, bfunc)
- if len(color1)==4 and len(color2)==4:
- self.aInterpolator = FunctionInterpolator(color1[3], color2[3], distance, afunc)
- else:
- self.aInterpolator = FunctionInterpolator(255, 255, distance, afunc)
-
- def eval(self, x):
- '''
- eval(x) -> color
-
- returns the color at the position 0<=x<=d (actually not bound to this interval).
- '''
-## print "colorInterp x", x, self.rInterpolator.eval(x), self.gInterpolator.eval(x), self.bInterpolator.eval(x)
- return [self.rInterpolator.eval(x),
- self.gInterpolator.eval(x),
- self.bInterpolator.eval(x),
- self.aInterpolator.eval(x)]
-
-
-
-class FunctionInterpolator(object):
- '''
- FunctionINterpolator(startvalue, endvalue, trange, func)
-
- interpolates a function y=f(x) in the range trange with
- startvalue = f(0)
- endvalue = f(trange)
- using the function func
- '''
- def __init__(self, startvalue, endvalue, trange, func):
- object.__init__(self)
- # function
- self.func = func
- # y-scaling
- self.a = endvalue-startvalue
- if self.a == 0:
- self.a = 1.
- # x-scaling
- if trange!=0:
- self.b = 1./abs(trange)
- else:
- self.b = 1.
- # x-displacement
- self.c = 0
- # y-displacement
- self.d = min(max(startvalue,0),255)
-
- def eval(self, x):
- '''
- eval(x)->float
-
- return value at position x
- '''
- # make sure that the returned value is in [0,255]
-## return int(round(min(max(self.a*self.func(self.b*(x+self.c))+self.d, 0), 255)))
- return int(min(max(self.a*self.func(self.b*(x+self.c))+self.d, 0), 255))
-
-
-
-##def gradient(surface,
-## startpoint,
-## endpoint,
-## startcolor,
-## endcolor,
-## Rfunc = (lambda x:x),
-## Gfunc = (lambda x:x),
-## Bfunc = (lambda x:x),
-## Afunc = (lambda x:1),
-## type = "line",
-## mode = None ):
-## '''
-## surface : surface to draw on
-## startpoint: (x,y) point on surface
-## endpoint : (x,y) point on surface
-## startcolor: (r,g,b,a) color at startpoint
-## endcolor : (r,g,b,a) color at endpoint
-## Rfunc : function y = f(x) with startcolor =f(0) and endcolor = f(1) where 0 is at startpoint and 1 at endpoint
-## Gfunc : --- " ---
-## Bfunc : --- " ---
-## Afunc : --- " ---
-## these functions are evaluated in the range 0 <= x <= 1 and 0<= y=f(x) <= 1
-## type : "line", "circle" or "rect"
-## mode : "+", "-", "*", None (how the pixels are drawen)
-##
-## returns : surface with the color characteristics w,h = (d, 256) and d = length of endpoint-startpoint
-##
-## '''
-## dx = endpoint[0]-startpoint[0]
-## dy = endpoint[1]-startpoint[1]
-## d = int(round(math.hypot(dx, dy)))
-## angle = math.degrees( math.atan2(dy, dx) )
-##
-## color = ColorInterpolator(d, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
-##
-## if type=="line":
-## h = int(2.*math.hypot(*surface.get_size()))
-### bigSurf = pygame.Surface((d, h)).convert_alpha()
-## bigSurf = pygame.Surface((d, h), pygame.SRCALPHA)#.convert_alpha()
-### bigSurf = pygame.Surface((d, 1), pygame.SRCALPHA)#.convert_alpha()
-## bigSurf.lock()
-## bigSurf.fill((0,0,0,0))
-## bigSurf.set_colorkey((0,0,0,0))
-## for x in range(d):
-## pygame.draw.line(bigSurf, color.eval(x), (x,0), (x,h), 1)
-### for x in range(d):
-### bigSurf.set_at((x, 0), color.eval(x))
-### bigSurf = pygame.transform.scale(bigSurf, (d, h))
-##
-## bigSurf = pygame.transform.rotate(bigSurf, -angle) #rotozoom(bigSurf, -angle, 1)
-## bigSurf.set_colorkey((0,0,0, 0))
-## rect = bigSurf.get_rect()
-## srect = pygame.Rect(rect)
-## dx = d/2. * math.cos(math.radians(angle))
-## dy = d/2. * math.sin(math.radians(angle))
-## rect.center = startpoint
-## rect.move_ip(dx, dy)
-## bigSurf.unlock()
-##
-## elif type=="circle":
-## bigSurf = pygame.Surface((2*d, 2*d)).convert_alpha()
-## bigSurf.fill((0,0,0,0))
-## bigSurf.lock()
-## for x in range(d, 0, -1):
-## pygame.draw.circle(bigSurf, color.eval(x), (d,d), x)
-## bigSurf.unlock()
-## rect = bigSurf.get_rect()
-## srect = pygame.Rect(rect)
-## rect.center = (startpoint[0], startpoint[1])
-##
-## elif type=="rect":
-## bigSurf = pygame.Surface((2*d, 2*d)).convert_alpha()
-## bigSurf.fill((0,0,0,0))
-## c = bigSurf.get_rect().center
-## bigSurf.lock()
-## for x in range(d,-1,-1):
-## r = pygame.Rect(0,0,2*x,2*x)
-## r.center = c
-## pygame.draw.rect(bigSurf, color.eval(x), r)
-## bigSurf.unlock()
-## bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1)
-## bigSurf.set_colorkey((0,0,0, 0))
-##
-## rect = bigSurf.get_rect()
-## srect = pygame.Rect(rect)
-## rect.center = startpoint
-## else:
-## raise NameError("type must be one of \"line\",\"circle\" or \"rect\"")
-##
-## if mode is None:
-## surface.blit(bigSurf, rect, srect)
-## else:
-## if mode=="+":
-## cf = pygame.color.add
-## elif mode=="*":
-## cf = pygame.color.multiply
-## elif mode=="-":
-## cf = pygame.color.subtract
-## else:
-## raise NameError("type must be one of \"+\", \"*\", \"-\" or None")
-## irect = surface.get_clip().clip(rect)
-## surface.lock()
-## for x in range(irect.left, irect.left+irect.width):
-## for y in range(irect.top, irect.top+irect.height):
-## surface.set_at((x,y), cf(surface.get_at((x,y)), bigSurf.get_at((x-rect.left, y-rect.top)) ) )
-## surface.unlock()
-##
-## del bigSurf
-## char = pygame.Surface((d+1, 257))
-### char.fill((0,0,0))
-### ox = 0
-### oldcol = color.eval(0)
-### for x in range(d):
-### col = color.eval(x)
-### pygame.draw.line(char, (255,0,0), (x, 256-col[0]), (ox, 256-oldcol[0]))
-### pygame.draw.line(char, (0,255,0), (x, 256-col[1]), (ox, 256-oldcol[1]))
-### pygame.draw.line(char, (0,0,255), (x, 256-col[2]), (ox, 256-oldcol[2]))
-### pygame.draw.line(char, (255,255,255), (x, 256-col[3]), (ox, 256-oldcol[3]))
-### ox = x
-### oldcol = col
-###
-## return char
-
-
-
-
-def vertical(size, startcolor, endcolor):
- """
- Draws a vertical linear gradient filling the entire surface. Returns a
- surface filled with the gradient (numeric is only 2-3 times faster).
- """
- height = size[1]
- bigSurf = pygame.Surface((1,height)).convert_alpha()
- dd = 1.0/height
- sr, sg, sb, sa = startcolor
- er, eg, eb, ea = endcolor
- rm = (er-sr)*dd
- gm = (eg-sg)*dd
- bm = (eb-sb)*dd
- am = (ea-sa)*dd
- for y in range(height):
- bigSurf.set_at((0,y),
- (int(sr + rm*y),
- int(sg + gm*y),
- int(sb + bm*y),
- int(sa + am*y))
- )
- return pygame.transform.scale(bigSurf, size)
-
-
-def horizontal(size, startcolor, endcolor):
- """
- Draws a horizontal linear gradient filling the entire surface. Returns a
- surface filled with the gradient (numeric is only 2-3 times faster).
- """
- width = size[0]
- bigSurf = pygame.Surface((width, 1)).convert_alpha()
- dd = 1.0/width
- sr, sg, sb, sa = startcolor
- er, eg, eb, ea = endcolor
- rm = (er-sr)*dd
- gm = (eg-sg)*dd
- bm = (eb-sb)*dd
- am = (ea-sa)*dd
- for y in range(width):
- bigSurf.set_at((y,0),
- (int(sr + rm*y),
- int(sg + gm*y),
- int(sb + bm*y),
- int(sa + am*y))
- )
- return pygame.transform.scale(bigSurf, size)
-
-
-def radial(radius, startcolor, endcolor):
- """
- Draws a linear raidal gradient on a square sized surface and returns
- that surface.
- """
- bigSurf = pygame.Surface((2*radius, 2*radius)).convert_alpha()
- bigSurf.fill((0,0,0,0))
- dd = -1.0/radius
- sr, sg, sb, sa = endcolor
- er, eg, eb, ea = startcolor
- rm = (er-sr)*dd
- gm = (eg-sg)*dd
- bm = (eb-sb)*dd
- am = (ea-sa)*dd
-
- draw_circle = pygame.draw.circle
- for rad in range(radius, 0, -1):
- draw_circle(bigSurf, (er + int(rm*rad),
- eg + int(gm*rad),
- eb + int(bm*rad),
- ea + int(am*rad)), (radius, radius), rad)
- return bigSurf
-
-def squared(width, startcolor, endcolor):
- """
- Draws a linear sqared gradient on a square sized surface and returns
- that surface.
- """
- bigSurf = pygame.Surface((width, width)).convert_alpha()
- bigSurf.fill((0,0,0,0))
- dd = -1.0/(width/2)
- sr, sg, sb, sa = endcolor
- er, eg, eb, ea = startcolor
- rm = (er-sr)*dd
- gm = (eg-sg)*dd
- bm = (eb-sb)*dd
- am = (ea-sa)*dd
-
- draw_rect = pygame.draw.rect
- for currentw in range((width/2), 0, -1):
- pos = (width/2)-currentw
- draw_rect(bigSurf, (er + int(rm*currentw),
- eg + int(gm*currentw),
- eb + int(bm*currentw),
- ea + int(am*currentw)), pygame.Rect(pos, pos, 2*currentw, 2*currentw ))
- return bigSurf
-
-
-def vertical_func(size, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1)):
- """
- Draws a vertical linear gradient filling the entire surface. Returns a
- surface filled with the gradient (numeric is only 2x faster).
- Rfunc, Gfunc, Bfunc and Afunc are function like y = f(x). They define
- how the color changes.
- """
- height = size[1]
- bigSurf = pygame.Surface((1,height)).convert_alpha()
- color = ColorInterpolator(height, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
- for y in range(0, height):
- bigSurf.set_at((0,y), color.eval(y+0.1))
- return pygame.transform.scale(bigSurf, size)
-
-
-def horizontal_func(size, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1)):
- """
- Draws a horizontal linear gradient filling the entire surface. Returns a
- surface filled with the gradient (numeric is only 2x faster).
- Rfunc, Gfunc, Bfunc and Afunc are function like y = f(x). They define
- how the color changes.
- """
- width = size[0]
- bigSurf = pygame.Surface((width, 1)).convert_alpha()
- color = ColorInterpolator(width, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
- for y in range(0, width):
- bigSurf.set_at((y, 0), color.eval(y+0.1))
- return pygame.transform.scale(bigSurf, size)
-
-def radial_func(radius, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), colorkey=(0,0,0,0)):
- """
- Draws a linear raidal gradient on a square sized surface and returns
- that surface.
- """
- bigSurf = pygame.Surface((2*radius, 2*radius)).convert_alpha()
- if len(colorkey)==3:
- colorkey += (0,)
- bigSurf.fill(colorkey)
- color = ColorInterpolator(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
- draw_circle = pygame.draw.circle
- for rad in range(radius, 0, -1):
- draw_circle(bigSurf, color.eval(rad), (radius, radius), rad)
- return bigSurf
-
-def radial_func_offset(radius, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), colorkey=(0,0,0,0), offset=(0,0)):
- """
- Draws a linear raidal gradient on a square sized surface and returns
- that surface.
- offset is the amount the center of the gradient is displaced of the center of the image.
- Unfotunately this function ignores alpha.
- """
- bigSurf = pygame.Surface((2*radius, 2*radius))#.convert_alpha()
-
- mask = pygame.Surface((2*radius, 2*radius), pygame.SRCALPHA)#.convert_alpha()
- mask.fill(colorkey)
- mask.set_colorkey((255,0,255))
- pygame.draw.circle(mask, (255,0,255), (radius, radius), radius)
-
- if len(colorkey)==3:
- colorkey += (0,)
- bigSurf.fill(colorkey)
-
- color = ColorInterpolator(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
- draw_circle = pygame.draw.circle
- radi = radius + int(math.hypot(offset[0], offset[1])+1)
- for rad in range(radi, 0, -1):
- draw_circle(bigSurf, color.eval(rad), (radius+offset[0], radius+offset[1]), rad)
-
- bigSurf.blit(mask, (0,0))
- bigSurf.set_colorkey(colorkey)
- return bigSurf
-
-
-def squared_func(width, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), offset=(0,0)):
- """
- Draws a linear sqared gradient on a square sized surface and returns
- that surface.
- """
- bigSurf = pygame.Surface((width, width)).convert_alpha()
- bigSurf.fill((0,0,0,0))
- color = ColorInterpolator(width/2, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
- draw_rect = pygame.draw.rect
- widthh = width+2*int(max(abs(offset[0]),abs(offset[1])))
- for currentw in range((widthh/2), 0, -1):
-## pos = (width/2)-currentw
- rect = pygame.Rect(0, 0, 2*currentw, 2*currentw )
- rect.center = (width/2+offset[0], width/2+offset[1])
- draw_rect(bigSurf, color.eval(currentw), rect)
- return bigSurf
-
-def draw_gradient(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0):
- """
- Instead of returning an Surface, this function draw it directy onto the
- given Surface and returns the rect.
- """
- dx = endpoint[0]-startpoint[0]
- dy = endpoint[1]-startpoint[1]
- d = int(round(math.hypot(dx, dy)))
- angle = math.degrees( math.atan2(dy, dx) )
-
- h = int(2.*math.hypot(*surface.get_size()))
-
- bigSurf = horizontal_func((d,h), startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
-
-## bigSurf = pygame.transform.rotate(bigSurf, -angle) #rotozoom(bigSurf, -angle, 1)
- bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1)
-## bigSurf.set_colorkey((0,0,0, 0))
- rect = bigSurf.get_rect()
- srect = pygame.Rect(rect)
- dx = d/2. * math.cos(math.radians(angle))
- dy = d/2. * math.sin(math.radians(angle))
- rect.center = startpoint
- rect.move_ip(dx, dy)
- if BLEND_MODES_AVAILABLE:
- return surface.blit(bigSurf, rect, None, mode)
- else:
- return surface.blit(bigSurf, rect)
-
-
-def draw_circle(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0):
- """
- Instead of returning an Surface, this function draw it directy onto the
- given Surface and returns the rect.
- """
- dx = endpoint[0]-startpoint[0]
- dy = endpoint[1]-startpoint[1]
- radius = int(round(math.hypot(dx, dy)))
- pos = (startpoint[0]-radius, startpoint[1]-radius)
- if BLEND_MODES_AVAILABLE:
- return surface.blit(radial_func(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc), pos, None, mode)
- else:
- return surface.blit(radial_func(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc), pos)
-
-def draw_squared(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0):
- """
- Instead of returning an Surface, this function draw it directy onto the
- given Surface and returns the rect.
- """
- dx = endpoint[0]-startpoint[0]
- dy = endpoint[1]-startpoint[1]
- angle = math.degrees( math.atan2(dy, dx) )
- width = 2*int(round(math.hypot(dx, dy)))
-
- bigSurf = squared_func(width, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
-
- bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1)
-## bigSurf.set_colorkey((0,0,0, 0))
- rect = bigSurf.get_rect()
- rect.center = startpoint
- if BLEND_MODES_AVAILABLE:
- return surface.blit(bigSurf, rect, None, mode)
- else:
- return surface.blit(bigSurf, rect)
-
-
-def chart(startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), scale=None):
- """
- This returns a Surface where the change of the colors over the distance
- (the width of the image) is showen as a line.
- scale: a float, 1 is not scaling
- """
- dx = endpoint[0]-startpoint[0]
- dy = endpoint[1]-startpoint[1]
- distance = int(round(math.hypot(dx, dy)))
- color = ColorInterpolator(distance, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
- bigSurf = pygame.Surface((distance, 256))
- bigSurf.fill((0,)*3)
- oldcol = color.eval(0)
- for x in range(distance):
- r, g, b, a = color.eval(x)
- pygame.draw.line(bigSurf, (255, 0, 0, 128), (x-1, oldcol[0]), (x, r))
- pygame.draw.line(bigSurf, (0, 255, 0, 128), (x-1, oldcol[1]), (x, g))
- pygame.draw.line(bigSurf, (0, 0, 255, 128), (x-1, oldcol[2]), (x, b))
- pygame.draw.line(bigSurf, (255, 255, 255, 128), (x-1, oldcol[3]), (x, a))
- oldcol = (r,g,b,a)
- if scale:
-## return pygame.transform.scale(bigSurf, size)
- return pygame.transform.rotozoom(bigSurf, 0, scale)
- return pygame.transform.flip(bigSurf, 0, 1)
-#------------------------------------------------------------------------------
-
-
-
-
-def genericFxyGradient(surf, clip, color1, color2, func, intx, yint, zint=None):
- """
- genericFxyGradient(size, color1, color2,func, intx, yint, zint=None)
-
- some sort of highfield drawer :-)
-
- surf : surface to draw
- clip : rect on surf to draw in
- color1 : start color
- color2 : end color
- func : function z = func(x,y)
- xint : interval in x direction where the function is evaluated
- yint : interval in y direction where the function is evaluated
- zint : if not none same as yint or xint, if None then the max and min value
- of func is taken as z-interval
-
- color = a*func(b*(x+c), d*(y+e))+f
- """
- # make shure that x1<x2 and y1<y2 and z1<z2
- w,h = clip.size
- x1 = min(intx)
- x2 = max(intx)
- y1 = min(yint)
- y2 = max(yint)
- if zint: # if user give us z intervall, then use it
- z1 = min(zint)
- z2 = max(zint)
- else: # look for extrema of function (not best algorithme)
- z1 = func(x1,y1)
- z2 = z1
- for i in range(w):
- for j in range(h):
- r = func(i,j)
- z1 = min(z1, r)
- z2 = max(z2, r)
-
- x1 = float(x1)
- x2 = float(x2)
- y1 = float(y1)
- y2 = float(y2)
- z1 = float(z1)
- z2 = float(z2)
- if len(color1)==3:
- color1 = list(color1)
- color1.append(255)
- if len(color2)==3:
- color2 = list(color2)
- color2.append(255)
-
- # calculate streching and displacement variables
- a = ((color2[0]-color1[0])/(z2-z1), \
- (color2[1]-color1[1])/(z2-z1), \
- (color2[2]-color1[2])/(z2-z1), \
- (color2[3]-color1[3])/(z2-z1) ) # streching in z direction
- b = (x2-x1)/float(w) # streching in x direction
- d = (y2-y1)/float(h) # streching in y direction
- f = ( color1[0]-a[0]*z1, \
- color1[1]-a[1]*z1, \
- color1[2]-a[2]*z1, \
- color1[3]-a[3]*z1 )# z displacement
- c = x1/b
- e = y1/d
-
- surff = pygame.surface.Surface((w,h)).convert_alpha()
- # generate values
- for i in range(h):
- for j in range(w):
- val = func(b*(j+c), d*(i+e))
- #clip color
- color = ( max(min(a[0]*val+f[0],255),0), \
- max(min(a[1]*val+f[1],255),0), \
- max(min(a[2]*val+f[2],255),0), \
- max(min(a[3]*val+f[3],255),0) )
- surff.set_at( (j,i), color )
- surf.blit(surff, clip)
-
-
-
+++ /dev/null
-'''\r
-Created on 21 janv. 2010\r
-\r
-@author: samsam\r
-'''\r
-import pygame\r
-\r
-from gui.FamiliarizerPGUConfiguration import FamiliarizerPGUConfiguration\r
-\r
-class DefaultFamiliarizer(FamiliarizerPGUConfiguration):\r
- '''\r
- classdocs\r
- '''\r
-\r
-\r
- def __init__(self,window):\r
- '''\r
- Constructor\r
- '''\r
- FamiliarizerPGUConfiguration.__init__(self, window,defaultParams = True)\r
-\r
-if __name__ == "__main__" :\r
- pygame.init()\r
- modeResolution = (1024,768)\r
- window = pygame.display.set_mode(modeResolution,pygame.FULLSCREEN)\r
- familiarizer = DefaultFamiliarizer(window)\r
- pygame.quit()
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 21 janv. 2010\r
-\r
-@author: samsam\r
-'''\r
-\r
-import pygame\r
-import pygame.midi\r
-import sys\r
-import time\r
-import pickle\r
-\r
-from numpy import array\r
-from numpy.linalg import norm\r
-\r
-from math import floor\r
-\r
-from gui.constants import *\r
-from PlayingScreen import PlayingScreen\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from logging.EventLog import EventLog\r
-from logging.PickleableEvent import PickleableEvent \r
-from InstrumentChoice import InstrumentChoice\r
-\r
-class DummyInstrumentChoice():\r
- '''\r
- classdocs\r
- '''\r
-\r
-\r
- def __init__(self,wiimotes, window, screen, clock, joys, portOffset, activeWiimotes, eventLog=None, replay = False, logFilePath = None, scaleFactor = 1):\r
- '''\r
- Constructor\r
- '''\r
- self.wiimotes =wiimotes\r
- self.activeWiimotes =activeWiimotes\r
- self.window = window\r
- self.screen = screen\r
- self.scaleFactor = scaleFactor\r
- self.width = int(floor(screen.get_width()*self.scaleFactor))\r
- self.height = int(floor(screen.get_height()*self.scaleFactor))\r
- self.blitOrigin = ((self.screen.get_width()-self.width)/2,(self.screen.get_height()-self.height)/2)\r
- self.clock = clock \r
- self.savedScreen = pygame.Surface(self.screen.get_size())\r
- self.savedScreen.fill((255, 255, 255))\r
- self.playerScreen = pygame.Surface(self.savedScreen.get_size())\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- self.cursorPositions = []\r
- for i in range(len(self.wiimotes)):\r
- self.wiimotes[i].cursor.screen = self.playerScreen\r
- self.cursorPositions.append(self.wiimotes[i].cursor.centerPosition)\r
- self.joys = joys\r
- self.portOffset = portOffset\r
- self.eventLog = eventLog\r
- self.replay = replay
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 15 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-import pygame\r
-import pygame.midi\r
-import sys\r
-import time\r
-import pickle\r
-import random\r
-\r
-from numpy import array\r
-from numpy.linalg import norm\r
-\r
-from math import floor\r
-\r
-from gui.constants import *\r
-from PlayingScreen import PlayingScreen\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from logging.EventLog import EventLog\r
-from logging.PickleableEvent import PickleableEvent \r
-\r
-joyNames = ["PPJoy Virtual joystick 1", "PPJoy Virtual joystick 2", "PPJoy Virtual joystick 3"]\r
-portNames = ["Out To MIDI Yoke: 1"]\r
-majorScale = [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72]\r
-minorScale = [55, 56, 58, 60, 62, 63, 65, 67, 68, 70, 72]\r
-myxolydianScale = [55, 57, 58, 60, 62, 64, 65, 67, 69, 70, 72]\r
-dorianScale = [55, 57, 58, 60, 62, 63, 65, 67, 69, 70, 72]\r
-instrumentImagePathList = ["piano", "guitare", "accordeon", "violon", "flute", "tuba", "orgue", "violoncelle", "celesta"]\r
-octaves = [0, -1, 0, 1, 1, -2, 0, -1, 0]\r
-\r
-class Familiarizer:\r
- '''\r
- The screen for choosing instruments\r
- \r
- instruments: \r
- The available instruments \r
- wiimotes: \r
- The wiimotes used in this session\r
- window:\r
- The main display window\r
- screen:\r
- The main display surface\r
- clock:\r
- The clock used to animate the screen\r
- savedScreen:\r
- The background that is painted every time\r
- playerScreen:\r
- The buffer for painting everything before bliting\r
- width:\r
- The width of the window in pixels\r
- height:\r
- The height of the window in pixels\r
- done:\r
- Goes to True when all instruments have been selected\r
- cursorPositions:\r
- The positions of the cursors on the screen, in pixels\r
- imageRects:\r
- The rectangles where the images of the instruments are located\r
- focus:\r
- The numbers of the instruments currently in focus\r
- '''\r
- \r
- def __init__(self, instruments, wiimotes, window, screen, clock, joys, portOffset, eventLog=None, replay = False, logFilePath = None, scaleFactor = 1, level = 1):\r
- '''\r
- Constructor\r
- \r
- instruments: \r
- The instruments for this session \r
- wiimotes: \r
- The wiimotes used in this session\r
- '''\r
- \r
- \r
- self.scaleFactor = scaleFactor\r
- \r
- self.instruments = instruments\r
- self.wiimotes = wiimotes\r
- self.window = window\r
- self.screen = screen\r
- self.clock = clock\r
- self.width = int(floor(screen.get_width()*self.scaleFactor))\r
- self.height = int(floor(screen.get_height()*self.scaleFactor))\r
- self.blitOrigin = ((self.screen.get_width()-self.width)/2,(self.screen.get_height()-self.height)/2) \r
- self.joys = joys\r
- self.portOffset = portOffset\r
- \r
- self.currentWiimote = 0\r
- self.done = False \r
- \r
- self.cursorPositions = []\r
- self.imageRects = []\r
- self.displayedInstruments = []\r
- self.savedImageRects = []\r
- self.focus = []\r
- self.level = level\r
- \r
- if eventLog == None:\r
- self.eventLog = EventLog()\r
- self.replay = False\r
- else:\r
- self.eventLog = eventLog\r
- self.replay = replay\r
- \r
- self.savedScreen = pygame.Surface(self.screen.get_size()) \r
- \r
- self.displayedInstruments.append(0)\r
- if level == 1 :\r
- self.displayedInstruments.append(2)\r
- \r
- self.savedScreen.fill((255, 255, 255))\r
- for i in range(len(self.displayedInstruments)):\r
- self.imageRects.append(self.drawInstrument(self.displayedInstruments[i]))\r
- \r
- self.savedImageRects = self.imageRects[:]\r
- \r
- #Draw the initial cursor on the buffer\r
- self.playerScreen = pygame.Surface(self.savedScreen.get_size())\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- for i in range(len(self.wiimotes)):\r
- #Create the list of instrument focus (one focus per wiimote)\r
- self.focus.append(None)\r
- #Set the screen for the cursors (it can't be set before)\r
- self.wiimotes[i].cursor.screen = self.playerScreen\r
- self.cursorPositions.append(self.wiimotes[i].cursor.centerPosition)\r
- \r
- self.wiimotes[self.currentWiimote].cursor.blit(self.playerScreen)\r
- \r
- #The main loop\r
- while self.done == False :\r
- \r
- #Clear the cursors from the screen\r
- self.drawBackground()\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = self.clock.tick(50)\r
- \r
- if self.replay:\r
- self.eventLog.update(timePassed)\r
- pickledEventsToPost = self.eventLog.getPickledEvents() \r
- for pickledEvent in pickledEventsToPost:\r
- pygame.event.post(pickledEvent.event)\r
- \r
- events = pygame.event.get()\r
- \r
- if not self.replay:\r
- pickledEvents = [PickleableEvent(event.type,event.dict) for event in events if self.eventFilter(event)]\r
- if pickledEvents != [] :\r
- self.eventLog.appendEventGroup(pickledEvents)\r
- \r
- for event in events:\r
- self.input(event)\r
- \r
- for i in range(len(self.wiimotes)):\r
- self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])\r
- \r
- self.wiimotes[self.currentWiimote].cursor.blit(self.playerScreen) \r
- \r
- self.focus[self.currentWiimote] = None\r
- \r
- for i in range(len(self.imageRects)) :\r
- if self.imageRects[i].collidepoint(self.cursorPositions[self.currentWiimote]):\r
- self.focus[self.currentWiimote] = i\r
- \r
- self.screen.blit(self.playerScreen, (0, 0))\r
- \r
- pygame.display.flip()\r
- \r
- def input(self, event):\r
- if event.type == pygame.QUIT:\r
- pygame.midi.quit()\r
- sys.exit()\r
- if event.type == pygame.JOYAXISMOTION:\r
- self.updateCursorPositionFromJoy(event)\r
- if event.type == pygame.JOYBUTTONDOWN :\r
- self.joyClicked(event)\r
- if event.type == pygame.MOUSEBUTTONDOWN:\r
- self.mouseClicked(event)\r
- if event.type == pygame.MOUSEMOTION:\r
- self.updateCursorPositionFromMouse(event)\r
- if event.type == pygame.KEYDOWN:\r
- if event.key == pygame.K_q:\r
- self.done = True \r
- \r
- def updateCursorPositionFromJoy(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = joyNames.index(joyName) \r
- if correctedJoyId < len(self.cursorPositions):\r
- if joyEvent.axis == 0 :\r
- self.cursorPositions[correctedJoyId] = (int((joyEvent.value + 1) / 2 * self.screen.get_width()), self.cursorPositions[correctedJoyId][1])\r
- if joyEvent.axis == 1 :\r
- self.cursorPositions[correctedJoyId] = (self.cursorPositions[correctedJoyId][0], int((joyEvent.value + 1) / 2 * self.screen.get_height())) \r
- \r
- def assignInstrumentToWiimote(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = joyNames.index(joyName)\r
- if self.zoomed[correctedJoyId] == self.focus[correctedJoyId]:\r
- self.wiimotes[correctedJoyId].instrument = self.instruments[self.focus[correctedJoyId]]\r
- self.zoomed[correctedJoyId] = None\r
- self.imageRects = self.savedImageRects[:]\r
- if self.currentWiimote<len(self.wiimotes)-1:\r
- self.currentWiimote = self.currentWiimote+1\r
- else:\r
- self.zoomed[correctedJoyId] = self.focus[correctedJoyId]\r
- if self.hasFinished():\r
- self.done = True\r
- \r
- def updateCursorPositionFromMouse(self, mouseEvent):\r
- self.cursorPositions[0] = mouseEvent.pos\r
- \r
- def assignInstrumentToMouse(self, mouseEvent):\r
- self.wiimotes[0].instrument = self.instruments[self.focus[0]]\r
- if self.hasFinished():\r
- self.done = True\r
- \r
- def hasFinished(self):\r
- finished = True\r
- for wiimote in self.wiimotes:\r
- if wiimote.instrument == None:\r
- finished = False\r
- return(finished)\r
- \r
- def eventFilter(self, event):\r
- c = event.type\r
- if c == 17:\r
- return False\r
- elif c == pygame.MOUSEMOTION or pygame.MOUSEBUTTONDOWN or pygame.MOUSEBUTTONUP or pygame.JOYAXISMOTION or pygame.JOYBUTTONDOWN or pygame.JOYBUTTONUP or pygame.KEYDOWN:\r
- return True\r
- else:\r
- return False\r
- \r
- def drawInstrument(self,instrumentNumber,drawPos = None):\r
- if not drawPos :\r
- drawPos = array([random.randint(0,self.width/2),random.randint(0,self.height/2)])\r
- curImage = pygame.image.load(self.instruments[instrumentNumber].image).convert_alpha()\r
- scaledImage = pygame.transform.smoothscale(curImage, (self.width / 2, self.height / 2))\r
- imageRect = self.savedScreen.blit(scaledImage, drawPos + self.blitOrigin)\r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 255), imageRect, 5)\r
- return imageRect \r
- \r
- def drawBackground(self):\r
- self.savedScreen.fill((255, 255, 255))\r
- for i in range(len(self.displayedInstruments)):\r
- self.drawInstrument(self.displayedInstruments[i], self.imageRects[i].topleft)\r
- if i in self.focus:\r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 255, 0, 255), self.imageRects[i], 10)\r
- \r
- def mouseClicked(self,mouseEvent):\r
- correctedJoyId = 0\r
- self.wiimotes[correctedJoyId].cursor.flash(400)\r
- if self.focus[correctedJoyId] != None :\r
- self.imageRects.pop(self.focus[correctedJoyId])\r
- instrumentNumber = self.displayedInstruments.pop(self.focus[correctedJoyId])\r
- self.drawBackground()\r
- self.imageRects.append(self.drawInstrument(instrumentNumber))\r
- self.displayedInstruments.append(instrumentNumber)\r
- self.wiimotes[correctedJoyId].instrument = self.instruments[instrumentNumber]\r
- octave = self.wiimotes[correctedJoyId].instrument.octave\r
- noteOnHexCode = self.wiimotes[correctedJoyId].getNoteOnHexCode()\r
- baseTime = pygame.midi.time()\r
- self.wiimotes[correctedJoyId].port.write([[[noteOnHexCode,60+12*octave,127],baseTime],[[noteOnHexCode,60+12*octave,0],baseTime+500],[[noteOnHexCode,65+12*octave,100],baseTime+510],[[noteOnHexCode,65+12*octave,0],baseTime+1000]])\r
- self.wiimotes[correctedJoyId].instrument = None\r
- \r
- def joyClicked(self,joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = joyNames.index(joyName)\r
- self.wiimotes[correctedJoyId].cursor.flash(400)\r
- if self.focus[correctedJoyId] != None :\r
- self.imageRects.pop(self.focus[correctedJoyId])\r
- instrumentNumber = self.displayedInstruments.pop(self.focus[correctedJoyId])\r
- self.drawBackground()\r
- self.imageRects.append(self.drawInstrument(instrumentNumber))\r
- self.displayedInstruments.append(instrumentNumber)\r
- self.wiimotes[correctedJoyId].instrument = self.instruments[instrumentNumber]\r
- octave = self.wiimotes[correctedJoyId].instrument.octave\r
- noteOnHexCode = self.wiimotes[correctedJoyId].getNoteOnHexCode()\r
- baseTime = pygame.midi.time()\r
- self.wiimotes[correctedJoyId].port.write([[[noteOnHexCode,60+12*octave,127],baseTime],[[noteOnHexCode,60+12*octave,0],baseTime+500],[[noteOnHexCode,65+12*octave,100],baseTime+510],[[noteOnHexCode,65+12*octave,0],baseTime+1000]])\r
- self.wiimotes[correctedJoyId].instrument = None\r
- \r
-\r
-def zoomRect(rect, ratio):\r
- zoomedRect = rect.inflate(int(floor((ratio - 1) * rect.width)), int(floor((ratio - 1) * rect.height)))\r
- return(zoomedRect) \r
-\r
-if __name__ == "__main__":\r
- pygame.init()\r
- #pygame.event.set_blocked([pygame.MOUSEBUTTONDOWN,pygame.MOUSEBUTTONUP,pygame.MOUSEMOTION])\r
- \r
- pygame.midi.init()\r
- instruments = [Instrument(majorScale, i + 1, "".join(["../instruments/instrumentImages/", instrumentImagePathList[i], ".jpg"]), octaves[i]) for i in range(9)]\r
- \r
- joys = [pygame.joystick.Joystick(id).get_name() for id in range(pygame.joystick.get_count())]\r
- joyOffset = joys.index(joyNames[0])\r
- pygame.joystick.Joystick(joyOffset).init()\r
- print(joyOffset) \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(portNames[0])\r
- print(portOffset)\r
- \r
- window = pygame.display.set_mode((1280, 1024),pygame.FULLSCREEN)\r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages = createImageListFromPath('../cursor/cursorImages/black', 11)\r
- durations = [75 for i in range(len(cursorImages))]\r
- \r
- extsc = False\r
- casc = False\r
- \r
- jadbt = [3, 4, 5, 3, 4, 4, 5, 6, 6, 5, 3, 3, 4, 5, 3, 4, 4, 5, 6, 7, 3]\r
- song = None\r
- \r
- cursors = [WarpingCursor(None, cursorImages, durations, (300 * i, 300 * i),'../cursor/cursorImages/black/flash.png') for i in range(1)]\r
- wiimotes = [Wiimote(i, i + portOffset, pygame.midi.Output(i+portOffset,latency = 20), None, cursors[i]) for i in range(1)]\r
- familiarize = Familiarizer(instruments, wiimotes, window, screen, clock, joyOffset, portOffset)\r
- for wiimote in wiimotes:\r
- del wiimote.port \r
- \r
- pygame.midi.quit()\r
- sys.exit()\r
+++ /dev/null
-'''\r
-Created on 12 nov. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-from logging.FamiliarizerLog import FamiliarizerLog\r
-\r
-import os\r
-import sys\r
-import subprocess\r
-\r
-import pygame\r
-import pygame.midi\r
-import pickle\r
-\r
-from pygame.locals import *\r
-\r
-from pgu import gui\r
-\r
-from StaticFamiliarizer import StaticFamiliarizer\r
-from SongFamiliarizer import SongFamiliarizer\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from logging.FamiliarizerLog import FamiliarizerLog\r
-from songs.Song import Song\r
-from constants import *\r
-from SongPlayingScreen import SongPlayingScreen\r
-from DummyInstrumentChoice import DummyInstrumentChoice\r
-\r
-class FamiliarizerPGUConfiguration(gui.Desktop):\r
- '''\r
- classdocs\r
- '''\r
-\r
-\r
- def __init__(self,window,defaultParams = False):\r
- '''\r
- Constructor\r
- '''\r
- gui.Desktop.__init__(self)\r
- self.done = False\r
- self.level = 0\r
- self.scale = scaleDict["majorScale"]\r
- self.fileName = fileName\r
- self.log = None\r
- self.activeWiimotes = [False for i in range(4)] \r
- \r
- pygame.font.init()\r
-\r
- self.titleFont = pygame.font.Font(None,100)\r
- self.font = pygame.font.Font(None,70)\r
- self.spaceSize = (100,100)\r
- \r
- self.goButton = gui.Button(self.createLabel("Go"))\r
- self.goButton.connect(gui.CLICK,self.goButtonClicked,None)\r
- \r
- self.quitButton = gui.Button(self.createLabel("Fin"))\r
- self.quitButton.connect(gui.CLICK,self.quitButtonClicked,None)\r
- \r
- self.levelSelect = gui.Select()\r
- for i in range(3) :\r
- self.levelSelect.add(self.createLabel(str(i+1)),i)\r
- self.levelSelect.connect(gui.CHANGE,self.levelSelectChanged,None)\r
- \r
- self.activeWiimoteSwitches = [gui.Switch(False) for i in range(4)]\r
- for i in range(len(self.activeWiimoteSwitches)) :\r
- self.activeWiimoteSwitches[i].connect(gui.CHANGE,self.activeWiimoteSwitchesChanged,i) \r
- \r
- self.connect(gui.QUIT,self.quit,None)\r
- \r
- self.window = window\r
- \r
- ##The table code is entered much like HTML.\r
- ##::\r
- mainContainer = gui.Table() \r
- \r
- c = gui.Table()\r
- \r
-# c.tr()\r
-# c.td(self.createLabel("MINWii",self.titleFont),colspan = 4)\r
- \r
- c.tr()\r
- c.td(gui.Spacer(*self.spaceSize))\r
- \r
- c.tr()\r
- c.td(self.createLabel("Niveau :"))\r
- c.td(self.levelSelect,colspan=3)\r
- \r
- c.tr()\r
- c.td(gui.Spacer(*self.spaceSize))\r
- \r
- c.tr()\r
- c.td(self.createLabel("Joueurs :", self.font))\r
- playerTable = gui.Table()\r
- for i in range(len(self.activeWiimoteSwitches)):\r
- playerTable.td(self.createLabel(" " + str(i+1)+" ", self.font))\r
- playerTable.td(self.activeWiimoteSwitches[i])\r
- c.td(playerTable,colspan = 3)\r
- \r
- c.tr()\r
- c.td(gui.Spacer(*self.spaceSize))\r
- \r
- c.tr()\r
- c.td(self.goButton)\r
- c.td(self.quitButton,colspan=3) \r
- \r
- c.tr()\r
- c.td(gui.Spacer(500,500))\r
- \r
- mainContainer.add(c,0,0)\r
- \r
- if defaultParams :\r
- self.goButtonClicked()\r
- else :\r
- self.run(mainContainer)\r
- \r
- def open_file_browser(self,data=None):\r
- d = gui.FileDialog()\r
- d.connect(gui.CHANGE, self.handle_file_browser_closed, d)\r
- d.open()\r
- \r
-\r
- def handle_file_browser_closed(self,dlg):\r
- if dlg.value:\r
- self.file = dlg.value\r
- \r
- def createLabel(self,text,font = None):\r
- if font == None :\r
- font = self.font\r
- w,h = self.font.size(text)\r
- label = gui.Label(text,width=w,height=h,font = font)\r
- return(label)\r
- \r
- def levelSelectChanged(self,data=None):\r
- self.level = self.levelSelect.value\r
- \r
- def quitButtonClicked(self,data = None):\r
- self.done = True\r
- self.quit()\r
- \r
- def activeWiimoteSwitchesChanged(self,data = None):\r
- if self.activeWiimoteSwitches[data].value :\r
- for i in range(len(self.activeWiimoteSwitches)) :\r
- if self.activeWiimoteSwitches[i].value and data != i :\r
- self.activeWiimoteSwitches[i].click() \r
- for i in range(len(self.activeWiimoteSwitches)) :\r
- self.activeWiimotes[i] = self.activeWiimoteSwitches[i].value\r
- \r
- def hasActiveWiimote(self):\r
- hasActive = False\r
- for active in self.activeWiimotes :\r
- if active :\r
- hasActive = True\r
- break\r
- return(hasActive)\r
- \r
-\r
- \r
- \r
- def goButtonClicked(self,data = None): \r
- \r
- pygame.midi.init()\r
- instruments = [Instrument(self.scale, i + 1, "".join(["../instruments/instrumentImages/", instrumentImagePathList[i], ".jpg"]), octaves[i]) for i in range(9)]\r
- \r
- joys = [[id,pygame.joystick.Joystick(id).get_name()] for id in range(pygame.joystick.get_count())]\r
- for joy in joys:\r
- if joy[1] in joyNames:\r
- pygame.joystick.Joystick(joy[0]).init() \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(portNames[0])\r
- print(portOffset)\r
- \r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages=[['../cursor/cursorImages/black/10.png'],['../cursor/cursorImages/red/10.png'],['../cursor/cursorImages/blue/10.png'],['../cursor/cursorImages/green/10.png']]\r
- durations = [75 for i in range(len(cursorImages))]\r
- \r
- extsc = True\r
- casc = False\r
- easyMode = True\r
- \r
- song = Song(scaleDict["majorScale"],[3,9,6,4,1,8,5,7,2,10],True)\r
-\r
- wiimoteCount = 4\r
- \r
- cursors = [WarpingCursor(None, cursorImages[i], durations, (300 * i, 300 * i),'../cursor/cursorImages/black/flash.png') for i in range(wiimoteCount)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, instruments[0], cursors[i]) for i in range(wiimoteCount)]\r
- dummyInstrumentChoice = DummyInstrumentChoice(wiimotes, self.window, screen, clock, joys, portOffset, self.activeWiimotes)\r
- if not self.hasActiveWiimote():\r
- self.activeWiimotes[0] = True\r
- if self.level < 2 :\r
- familiarize = StaticFamiliarizer(wiimotes, self.window, screen, clock, joys, portOffset,self.activeWiimotes,level = self.level)\r
- elif familiarize.nextLevel == 2 :\r
- familiarize = SongFamiliarizer(wiimotes, self.window, screen, clock, joys, portOffset,song,self.activeWiimotes,casc,extsc,easyMode)\r
- else :\r
- familiarize = SongPlayingScreen(dummyInstrumentChoice,songDict["clairdelalune"],easyMode = True)\r
- \r
- while familiarize.nextLevel != None :\r
- if familiarize.nextLevel < 2 :\r
- familiarize = StaticFamiliarizer(wiimotes, self.window, screen, clock, joys, portOffset,self.activeWiimotes,level = familiarize.nextLevel,eventLog = familiarize.eventLog)\r
- elif familiarize.nextLevel == 2 :\r
- familiarize = SongFamiliarizer(wiimotes, self.window, screen, clock, joys, portOffset,song,self.activeWiimotes,casc,extsc,easyMode,eventLog = familiarize.eventLog)\r
- else :\r
- familiarize = SongPlayingScreen(dummyInstrumentChoice,songDict["clairdelalune"],easyMode = True,eventLog = familiarize.eventLog)\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port \r
- \r
- pygame.midi.quit()\r
- \r
- i = 1 \r
- filePath = "".join([self.fileName,str(i),".fmwi"]) \r
- while os.path.exists(filePath):\r
- i += 1\r
- filePath = "".join([self.fileName,str(i),".fmwi"])\r
- \r
- f = file(filePath, 'w')\r
- self.log = FamiliarizerLog(familiarize.eventLog,self.level,self.activeWiimotes)\r
- pickler = pickle.Pickler(f)\r
- pickler.dump(self.log)\r
- \r
- f.close()\r
- \r
- self.repaint()\r
- \r
-if __name__ == "__main__" :\r
- pygame.init()\r
- modeResolution = (1024,768)\r
- window = pygame.display.set_mode(modeResolution,pygame.FULLSCREEN)\r
- familiarizer = FamiliarizerPGUConfiguration(window)\r
- pygame.quit() \r
- \r
- \r
- \r
-
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 15 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-import pygame\r
-import pygame.midi\r
-import sys\r
-import time\r
-import pickle\r
-\r
-from numpy import array\r
-from numpy.linalg import norm\r
-\r
-from math import floor\r
-\r
-from gui.constants import *\r
-from PlayingScreen import PlayingScreen\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from logging.EventLog import EventLog\r
-from logging.PickleableEvent import PickleableEvent \r
-\r
-class InstrumentChoice:\r
- '''\r
- The screen for choosing instruments\r
- \r
- instruments: \r
- The available instruments \r
- wiimotes: \r
- The wiimotes used in this session\r
- window:\r
- The main display window\r
- screen:\r
- The main display surface\r
- clock:\r
- The clock used to animate the screen\r
- savedScreen:\r
- The background that is painted every time\r
- playerScreen:\r
- The buffer for painting everything before bliting\r
- width:\r
- The width of the window in pixels\r
- height:\r
- The height of the window in pixels\r
- done:\r
- Goes to True when all instruments have been selected\r
- cursorPositions:\r
- The positions of the cursors on the screen, in pixels\r
- imageRects:\r
- The rectangles where the images of the instruments are located\r
- focus:\r
- The numbers of the instruments currently in focus\r
- '''\r
- \r
- def __init__(self, instruments, wiimotes, window, screen, clock, joys, portOffset, activeWiimotes, eventLog=None, replay = False, logFilePath = None, scaleFactor = 1):\r
- '''\r
- Constructor\r
- \r
- instruments: \r
- The instruments for this session \r
- wiimotes: \r
- The wiimotes used in this session\r
- '''\r
- self.scaleFactor = scaleFactor\r
- \r
- self.instruments = instruments\r
- self.wiimotes = wiimotes\r
- self.window = window\r
- self.screen = screen\r
- self.clock = clock\r
- self.width = int(floor(screen.get_width()*self.scaleFactor))\r
- self.height = int(floor(screen.get_height()*self.scaleFactor))\r
- self.blitOrigin = ((self.screen.get_width()-self.width)/2,(self.screen.get_height()-self.height)/2) \r
- self.joys = joys\r
- self.portOffset = portOffset\r
- \r
- self.activeWiimotes = activeWiimotes\r
- \r
- self.currentWiimote = 0\r
- while not self.activeWiimotes[self.currentWiimote] :\r
- self.currentWiimote += 1\r
- self.done = False \r
- \r
- self.cursorPositions = []\r
- self.imageRects = []\r
- self.savedImageRects = []\r
- self.focus = []\r
- self.zoomed = []\r
- \r
- if eventLog == None:\r
- self.eventLog = EventLog()\r
- self.replay = False\r
- else:\r
- self.eventLog = eventLog\r
- self.replay = replay\r
- print self.replay\r
- \r
- #There are 3 instruments per row, up to 9 instruments\r
- #Draw their images on the screen\r
- self.savedScreen = pygame.Surface(self.screen.get_size())\r
- self.savedScreen.fill((255, 255, 255))\r
- for i in range(len(self.instruments)) :\r
- drawPos = array([(self.width / 3) * (i % 3), (self.height / 3) * (i / 3)])\r
- curImage = pygame.image.load(self.instruments[i].image).convert_alpha()\r
- scaledImage = pygame.transform.smoothscale(curImage, (self.width / 3, self.height / 3))\r
- self.imageRects.append(self.savedScreen.blit(scaledImage, drawPos + self.blitOrigin))\r
- self.savedImageRects = self.imageRects[:]\r
- #Draw the initial cursor on the buffer\r
- self.playerScreen = pygame.Surface(self.savedScreen.get_size())\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- for i in range(len(self.wiimotes)):\r
- #Create the list of instrument focus (one focus per wiimote)\r
- self.focus.append(0)\r
- self.zoomed.append(None)\r
- #Set the screen for the cursors (it can't be set before)\r
- self.wiimotes[i].cursor.screen = self.playerScreen\r
- self.cursorPositions.append(self.wiimotes[i].cursor.centerPosition)\r
- \r
- self.wiimotes[self.currentWiimote].cursor.blit(self.playerScreen)\r
- \r
- #The main loop\r
- while self.done == False :\r
- \r
- #Clear the cursors from the screen\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = self.clock.tick(50)\r
- \r
- if self.replay:\r
- self.eventLog.update(timePassed)\r
- pickledEventsToPost = self.eventLog.getPickledEvents() \r
- for pickledEvent in pickledEventsToPost:\r
- pygame.event.post(pickledEvent.event)\r
- \r
- events = pygame.event.get()\r
- \r
- if not self.replay:\r
- pickledEvents = [PickleableEvent(event.type,event.dict) for event in events if self.eventFilter(event)]\r
- if pickledEvents != [] :\r
- self.eventLog.appendEventGroup(pickledEvents)\r
- \r
- for event in events:\r
- self.input(event)\r
- \r
- \r
- if self.zoomed[self.currentWiimote] != None :\r
- self.imageRects = self.savedImageRects[:]\r
- #inflate the chosen rect\r
- zoomedRectNumber = self.zoomed[self.currentWiimote]\r
- newRect = zoomRect(self.imageRects[zoomedRectNumber], 1.3)\r
- self.imageRects[zoomedRectNumber] = newRect\r
- curImage = pygame.image.load(self.instruments[zoomedRectNumber].image).convert_alpha()\r
- self.scaledImage = pygame.transform.smoothscale(curImage, newRect.size)\r
- self.playerScreen.blit(self.scaledImage, newRect.topleft)\r
- \r
- for i in range(len(self.wiimotes)):\r
- self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])\r
- \r
- self.wiimotes[self.currentWiimote].cursor.blit(self.playerScreen) \r
- \r
- if self.zoomed[self.currentWiimote] != None and self.imageRects[self.zoomed[self.currentWiimote]].collidepoint(self.cursorPositions[self.currentWiimote]):\r
- self.focus[self.currentWiimote] = self.zoomed[self.currentWiimote]\r
- pygame.draw.rect(self.playerScreen, pygame.Color(0, 255, 0, 255), self.imageRects[self.zoomed[self.currentWiimote]], 10)\r
- else:\r
- for i in range(len(self.imageRects)) :\r
- if self.imageRects[i].collidepoint(self.cursorPositions[self.currentWiimote]):\r
- self.focus[self.currentWiimote] = i\r
- pygame.draw.rect(self.playerScreen, pygame.Color(0, 255, 0, 255), self.imageRects[i], 10)\r
- if self.zoomed[self.currentWiimote] != None:\r
- self.playerScreen.blit(self.scaledImage, self.imageRects[self.zoomed[self.currentWiimote]].topleft)\r
- \r
- self.screen.blit(self.playerScreen, (0, 0))\r
- \r
- pygame.display.flip()\r
- \r
- def input(self, event):\r
- if event.type == pygame.QUIT:\r
- pygame.midi.quit()\r
- sys.exit()\r
- if event.type == pygame.JOYAXISMOTION:\r
- self.updateCursorPositionFromJoy(event)\r
- if event.type == pygame.JOYBUTTONDOWN :\r
- self.assignInstrumentToWiimote(event)\r
- if event.type == pygame.MOUSEBUTTONDOWN:\r
- if self.zoomed[self.currentWiimote] == self.focus[self.currentWiimote]:\r
- self.assignInstrumentToMouse(event)\r
- else:\r
- self.zoomed[self.currentWiimote] = self.focus[self.currentWiimote]\r
- if event.type == pygame.MOUSEMOTION:\r
- self.updateCursorPositionFromMouse(event) \r
- \r
- def updateCursorPositionFromJoy(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- print joyName\r
- correctedJoyId = joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]: \r
- if correctedJoyId < len(self.cursorPositions):\r
- if joyEvent.axis == 0 :\r
- self.cursorPositions[correctedJoyId] = (int((joyEvent.value + 1) / 2 * self.screen.get_width()), self.cursorPositions[correctedJoyId][1])\r
- if joyEvent.axis == 1 :\r
- self.cursorPositions[correctedJoyId] = (self.cursorPositions[correctedJoyId][0], int((joyEvent.value + 1) / 2 * self.screen.get_height())) \r
- \r
- def assignInstrumentToWiimote(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- if self.zoomed[correctedJoyId] == self.focus[correctedJoyId]:\r
- self.wiimotes[correctedJoyId].instrument = self.instruments[self.focus[correctedJoyId]]\r
- self.zoomed[correctedJoyId] = None\r
- self.imageRects = self.savedImageRects[:]\r
- if self.currentWiimote<len(self.wiimotes)-1:\r
- self.currentWiimote = self.currentWiimote+1\r
- else:\r
- self.zoomed[correctedJoyId] = self.focus[correctedJoyId]\r
- if self.hasFinished():\r
- self.done = True\r
- \r
- def updateCursorPositionFromMouse(self, mouseEvent):\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- self.cursorPositions[correctedJoyId] = mouseEvent.pos\r
- \r
- def assignInstrumentToMouse(self, mouseEvent):\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- self.wiimotes[correctedJoyId].instrument = self.instruments[self.focus[correctedJoyId]]\r
- if self.hasFinished():\r
- self.done = True\r
- \r
- def hasFinished(self):\r
- finished = True\r
- for i in range(len(self.wiimotes)):\r
- if self.wiimotes[i].instrument == None and self.activeWiimotes[i]:\r
- finished = False\r
- return(finished)\r
- \r
- def eventFilter(self, event):\r
- c = event.type\r
- if c == 17:\r
- return False\r
- elif c == pygame.MOUSEMOTION or pygame.MOUSEBUTTONDOWN or pygame.MOUSEBUTTONUP or pygame.JOYAXISMOTION or pygame.JOYBUTTONDOWN or pygame.JOYBUTTONUP or pygame.KEYDOWN:\r
- return True\r
- else:\r
- return False\r
-\r
-def zoomRect(rect, ratio):\r
- zoomedRect = rect.inflate(int(floor((ratio - 1) * rect.width)), int(floor((ratio - 1) * rect.height)))\r
- return(zoomedRect) \r
-\r
-if __name__ == "__main__":\r
- pygame.init()\r
- #pygame.event.set_blocked([pygame.MOUSEBUTTONDOWN,pygame.MOUSEBUTTONUP,pygame.MOUSEMOTION])\r
- \r
- pygame.midi.init()\r
- instruments = [Instrument(majorScale, i + 1, "".join(["../instruments/instrumentImages/", instrumentImagePathList[i], ".jpg"]), octaves[i]) for i in range(9)]\r
- \r
- joys = [pygame.joystick.Joystick(id).get_name() for id in range(pygame.joystick.get_count())]\r
- joyOffset = joys.index(joyNames[0])\r
- pygame.joystick.Joystick(joyOffset).init()\r
- print(joyOffset) \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(portNames[0])\r
- print(portOffset)\r
- \r
- window = pygame.display.set_mode((1280, 1024),pygame.FULLSCREEN)\r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages = createImageListFromPath('../cursor/cursorImages/black', 11)\r
- durations = [75 for i in range(len(cursorImages))]\r
- \r
- extsc = False\r
- casc = False\r
- \r
- jadbt = [3, 4, 5, 3, 4, 4, 5, 6, 6, 5, 3, 3, 4, 5, 3, 4, 4, 5, 6, 7, 3]\r
- song = None\r
- \r
- cursors = [WarpingCursor(None, cursorImages, durations, (300 * i, 300 * i)) for i in range(1)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(1)]\r
- choice = InstrumentChoice(instruments, wiimotes, window, screen, clock, joyOffset, portOffset)\r
- play = PlayingScreen(choice, song, casc, extsc)\r
- for wiimote in wiimotes:\r
- del wiimote.port \r
- \r
- f = file('temp.pkl', 'w')\r
- pickler = pickle.Pickler(f)\r
- pickler.dump(play.eventLog.eventGroups)\r
- pickler.dump(play.eventLog.times)\r
- f.close()\r
- \r
- f = file('temp.pkl', 'r')\r
- unpickler = pickle.Unpickler(f)\r
- eventGroups = unpickler.load()\r
- times = unpickler.load()\r
- f.close()\r
- eventLog = EventLog(eventGroups,times)\r
- \r
- cursors = [WarpingCursor(None, cursorImages, durations, (300 * i, 300 * i)) for i in range(1)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(1)]\r
- choice2 = InstrumentChoice(instruments, wiimotes, window, screen, clock, joyOffset, portOffset, eventLog)\r
- play = PlayingScreen(choice2, song, casc, extsc)\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port\r
- \r
- pygame.midi.quit()\r
- sys.exit()\r
+++ /dev/null
-# -*- coding: utf-8 -*-\r
-'''\r
-Created on 17 dec. 2009\r
-\r
-@author: samsam\r
-'''\r
-\r
-import pgu.gui as pguGui\r
-import os\r
-import constants\r
-\r
-class MINWiiDialog(pguGui.FileDialog):\r
- '''\r
- classdocs\r
- '''\r
- \r
- def __init__(self, font = None, width = 800, height = 600,path=None):\r
- pguGui.FileDialog.__init__(self,title_txt = "Choisir une chanson", customFont = font,customWidth = width, customHeight = height,folderText = "", fileText = "",path =path,showCurDir = False)\r
- \r
- def _list_dir_(self):\r
- self.input_dir.value = self.curdir\r
- self.input_dir.pos = len(self.curdir)\r
- self.input_dir.vpos = 0\r
- dirs = []\r
- files = []\r
- try:\r
- for i in os.listdir(self.curdir):\r
- if os.path.isdir(os.path.join(self.curdir, i)): dirs.append(i)\r
- else: files.append(i)\r
- except:\r
- self.input_file.value = "Opps! no access"\r
- #if '..' not in dirs: dirs.append('..')\r
- dirs.sort()\r
- dirs = ['..'] + dirs\r
- \r
- files.sort()\r
- for i in dirs:\r
- #item = ListItem(image=self.dir_img, text=i, value=i)\r
- if self.customFont == None :\r
- self.list.add(i,image=self.dir_img,value=i)\r
- else :\r
- if i == ".." or i[0] != ".":\r
- label = pguGui.basic.Label(i,font = self.customFont)\r
- self.list.add(label,image=self.dir_img,value=i)\r
- for i in files:\r
- #item = ListItem(image=None, text=i, value=i)\r
- if self.customFont == None :\r
- self.list.add(i,value=i)\r
- else:\r
- if i.endswith(".smwi"):\r
- key = i[:-5]\r
- if key in constants.reversedReadabilityDict : \r
- label = pguGui.basic.Label(constants.reversedReadabilityDict[key],font = self.customFont)\r
- else :\r
- label = pguGui.basic.Label(key,font = self.customFont)\r
- self.list.add(label,value=i)\r
- elif i.endswith(".xml") :\r
- # TODO : afficher le Titre de la chanson au lieu du nom\r
- # de fichier\r
- label = pguGui.basic.Label(i, font=self.customFont)\r
- self.list.add(label,value=i)\r
- #self.list.resize()\r
- self.list.set_vertical_scroll(0)\r
- #self.list.repaintall()\r
-
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 12 nov. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-import os\r
-import sys\r
-import subprocess\r
-\r
-import pygame\r
-import pygame.midi\r
-import pickle\r
-\r
-from pygame.locals import *\r
-\r
-from pgu import gui as pguGui\r
-\r
-from PlayingScreen import PlayingScreen\r
-from SongPlayingScreen import SongPlayingScreen\r
-from InstrumentChoice import InstrumentChoice\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from logging.Log import Log\r
-from songs.Song import Song,loadSong\r
-from songs.musicxmltosong import musicXml2Song\r
-from constants import *\r
-from MINWiiDialog import MINWiiDialog\r
-\r
-class PGUConfiguration(pguGui.Desktop):\r
- '''\r
- classdocs\r
- '''\r
-\r
-\r
- def __init__(self,window):\r
- '''\r
- Constructor\r
- '''\r
- pguGui.Desktop.__init__(self)\r
- self.extendedScale = False\r
- self.cascade = False\r
- self.song = None\r
- self.scale = scaleDict["majorScale"]\r
- self.log = None\r
- self.done = False\r
- self.easyMode = True\r
- self.mode = 0\r
- self.activeWiimotes = [False for i in range(4)]\r
- self.alwaysDown = False\r
- \r
- self.file = None\r
- #fileName is the path for the log file\r
- self.fileName = fileName\r
- self.titleFont = pygame.font.Font(None,100)\r
- self.font = pygame.font.Font(None,70)\r
- self.spaceSize = (100,100)\r
- \r
- self.browseButton = pguGui.Button(self.createLabel("Choisir..."))\r
- self.browseButton.connect(pguGui.CLICK, self.open_file_browser, None)\r
- \r
- self.songSwitch = pguGui.Switch(False)\r
- \r
- self.modeSelect = pguGui.Select()\r
- for key in modeDict.keys() :\r
- self.modeSelect.add(self.createLabel(reversedReadabilityDict[key]),key)\r
- self.modeSelect.connect(pguGui.CHANGE,self.modeSelectChanged,None)\r
- \r
- self.activeWiimoteSwitches = [pguGui.Switch(False) for i in range(4)]\r
- for i in range(len(self.activeWiimoteSwitches)) :\r
- self.activeWiimoteSwitches[i].connect(pguGui.CHANGE,self.activeWiimoteSwitchesChanged,i)\r
- \r
- self.goButton = pguGui.Button(self.createLabel("Go"))\r
- self.goButton.connect(pguGui.CLICK,self.goButtonClicked,None)\r
- \r
- self.quitButton = pguGui.Button(self.createLabel("Fin"))\r
- self.quitButton.connect(pguGui.CLICK,self.quitButtonClicked,None)\r
- \r
- self.connect(pguGui.QUIT,self.quit,None)\r
- \r
- self.window = window\r
- \r
- ##The table code is entered much like HTML.\r
- ##::\r
- \r
- self.mainTable = pguGui.Table()\r
- \r
- self.fillMainTable()\r
- \r
-# self.mainTable.tr()\r
-# self.mainTable.td(self.createLabel("MINWii",self.titleFont),colspan = 4)\r
- \r
- self.run(self.mainTable)\r
- \r
- def open_file_browser(self,data=None):\r
- d = MINWiiDialog(font = self.font,width = 800, height = 600,path = "../songs/smwis")\r
- d.connect(pguGui.CHANGE, self.handle_file_browser_closed, d)\r
- d.open()\r
- \r
-\r
- def handle_file_browser_closed(self,dlg):\r
- if dlg.value:\r
- if os.path.isfile(dlg.value):\r
- self.file = dlg.value\r
- if self.file.endswith('.smwi') :\r
- self.song = loadSong(self.file)\r
- key = os.path.basename(self.file)[:-5]\r
- if key in reversedReadabilityDict : \r
- label = self.createLabel(reversedReadabilityDict[key])\r
- else :\r
- label = self.createLabel(key)\r
- elif self.file.endswith('.xml') :\r
- self.song = musicXml2Song(self.file, printNotes=False)\r
- filename = os.path.basename(self.file)\r
- label = self.createLabel(filename) \r
- self.browseButton = pguGui.Button(label)\r
- self.browseButton.connect(pguGui.CLICK, self.open_file_browser, None)\r
- if not self.songSwitch.value :\r
- self.songSwitch.click()\r
- self.mainTable.clear()\r
- self.fillMainTable()\r
- \r
- \r
- def fillMainTable(self):\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(pguGui.Spacer(*self.spaceSize))\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(self.createLabel("Chanson :"))\r
- self.mainTable.td(self.browseButton,colspan=2)\r
- self.mainTable.td(self.songSwitch)\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(pguGui.Spacer(*self.spaceSize))\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(self.createLabel("Niveau :"))\r
- self.mainTable.td(self.modeSelect,colspan=3)\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(pguGui.Spacer(*self.spaceSize))\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(self.createLabel("Joueurs :", self.font))\r
- playerTable = pguGui.Table()\r
- for i in range(len(self.activeWiimoteSwitches)):\r
- playerTable.td(self.createLabel(" " + str(i+1)+" ", self.font))\r
- playerTable.td(self.activeWiimoteSwitches[i])\r
- self.mainTable.td(playerTable,colspan = 3)\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(pguGui.Spacer(*self.spaceSize))\r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(self.goButton)\r
- self.mainTable.td(self.quitButton,colspan=3) \r
- \r
- self.mainTable.tr()\r
- self.mainTable.td(pguGui.Spacer(500,500)) \r
- \r
- def createLabel(self,text,font = None):\r
- if font == None :\r
- font = self.font\r
- w,h = self.font.size(text)\r
- label = pguGui.Label(text,width=w,height=h,font = font)\r
- return(label)\r
- \r
- def songSelectChanged(self,data=None):\r
- self.song = songDict[self.songSelect.value]\r
- \r
- def activeWiimoteSwitchesChanged(self,data = None):\r
- if self.activeWiimoteSwitches[data].value :\r
- for i in range(len(self.activeWiimoteSwitches)) :\r
- if self.activeWiimoteSwitches[i].value and data != i :\r
- self.activeWiimoteSwitches[i].click() \r
- for i in range(len(self.activeWiimoteSwitches)) :\r
- self.activeWiimotes[i] = self.activeWiimoteSwitches[i].value\r
- \r
- def modeSelectChanged(self,data = None):\r
- self.mode = modeDict[self.modeSelect.value]\r
- \r
- def hasActiveWiimote(self):\r
- hasActive = False\r
- for i in self.activeWiimotes:\r
- if i :\r
- hasActive = True\r
- return(hasActive)\r
- \r
- def quitButtonClicked(self,data = None):\r
- self.done = True\r
- print 'puti'\r
- for isActive in self.activeWiimotes :\r
- print isActive\r
- self.quit()\r
- \r
- def goButtonClicked(self,data = None):\r
- pygame.font.init()\r
- \r
- if not self.hasActiveWiimote():\r
- self.activeWiimotes[0] = True\r
- pygame.midi.init()\r
- instruments = [Instrument(self.scale, i + 1, "".join(["../instruments/instrumentImages/", instrumentImagePathList[i], ".jpg"]), octaves[i]) for i in range(9)]\r
- \r
- joys = [[id,pygame.joystick.Joystick(id).get_name()] for id in range(pygame.joystick.get_count())]\r
- for joy in joys:\r
- print joy[1]\r
- if joy[1] in joyNames:\r
- print "On"\r
- pygame.joystick.Joystick(joy[0]).init()\r
- else :\r
- print "off" \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(portNames[0])\r
- print(portOffset)\r
- \r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages=[['../cursor/cursorImages/black/10.png'],['../cursor/cursorImages/red/10.png'],['../cursor/cursorImages/blue/10.png'],['../cursor/cursorImages/green/10.png']]\r
- durations = [75 for i in range(len(cursorImages[0]))]\r
- \r
- wiimoteCount = 4\r
- cursors = [WarpingCursor(None, cursorImages[i], durations, (300 * i, 300 * i),flashImage = '../cursor/cursorImages/black/flash.png' ) for i in range(wiimoteCount)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(wiimoteCount)]\r
- \r
- if self.song != None and self.songSwitch.value :\r
- \r
- if self.mode == 0 :\r
- self.extendedScale = self.song.requiresExtendedScale\r
- self.cascade = True\r
- self.easyMode = True\r
- self.alwaysDown = True\r
- elif self.mode == 1 :\r
- self.extendedScale = self.song.requiresExtendedScale\r
- self.cascade = True\r
- self.easyMode = True\r
- elif self.mode == 2:\r
- self.extendedScale = self.song.requiresExtendedScale\r
- self.cascade = False\r
- self.easyMode = True\r
- elif self.mode == 3:\r
- self.extendedScale = True\r
- self.cascade = False\r
- self.easyMode = False\r
- \r
- choice = InstrumentChoice(instruments, wiimotes, self.window, screen, clock, joys, portOffset,self.activeWiimotes, scaleFactor = songScaleFactor)\r
- play = SongPlayingScreen(choice, self)# self.song,self.cascade, self.extendedScale,self.easyMode,self.alwaysDown)\r
- \r
- else:\r
- \r
- if self.mode == 0 :\r
- self.extendedScale = False\r
- self.cascade = False\r
- elif self.mode == 1 :\r
- self.extendedScale = True\r
- self.cascade = False\r
- elif self.mode == 2:\r
- self.extendedScale = False\r
- self.cascade = True\r
- elif self.mode == 3:\r
- self.extendedScale = True\r
- self.cascade = True\r
- \r
- choice = InstrumentChoice(instruments, wiimotes, self.window, screen, clock, joys, portOffset,self.activeWiimotes)\r
- play = PlayingScreen(choice, self)#None,self.cascade, self.extendedScale) \r
- \r
- while play.backToInstrumentChoice == True :\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port\r
- \r
- wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(wiimoteCount)]\r
- previousEventLog = choice.eventLog\r
-\r
- if self.song != None :\r
- choice = InstrumentChoice(instruments, wiimotes, self.window, screen, clock, joys, portOffset, self.activeWiimotes,eventLog = previousEventLog, replay = False, scaleFactor = songScaleFactor)\r
- play = SongPlayingScreen(choice, self.song, False, self.extendedScale,self.easyMode)\r
- else:\r
- choice = InstrumentChoice(instruments, wiimotes, self.window, screen, clock, joys, portOffset,self.activeWiimotes, eventLog = previousEventLog, replay = False)\r
- play = PlayingScreen(choice, None, self.cascade, self.extendedScale)\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port\r
- \r
- i = 1 \r
- filePath = "".join([self.fileName,str(i),".mwi"]) \r
- while os.path.exists(filePath):\r
- i += 1\r
- filePath = "".join([self.fileName,str(i),".mwi"]) \r
- \r
- f = file(filePath, 'w')\r
- self.log = Log(play.eventLog,self.scale,self.extendedScale,self.cascade,self.song,self.mode,self.activeWiimotes)\r
- pickler = pickle.Pickler(f)\r
- pickler.dump(self.log)\r
- \r
- f.close()\r
- \r
- pygame.midi.quit()\r
- \r
- self.repaint()\r
- \r
-if __name__ == "__main__" :\r
- pygame.init()\r
- modeResolution = (1024,768)\r
- window = pygame.display.set_mode(modeResolution)#,pygame.FULLSCREEN)\r
- pgu = PGUConfiguration(window)\r
- pygame.quit() \r
- \r
- \r
- \r
-
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 23 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-from math import floor, ceil\r
-import pygame\r
-import sys\r
-import colorsys\r
-import constants\r
-from gradients import gradients\r
-from logging.PickleableEvent import PickleableEvent\r
-\r
-\r
-class PlayingScreen:\r
- '''\r
- The screen on which the game is played\r
- \r
- wiimotes: \r
- The wiimotes used in this session\r
- window:\r
- The main display window\r
- screen:\r
- The main display surface\r
- clock:\r
- The clock used to animate the screen\r
- savedScreen:\r
- The background that is painted every time\r
- playerScreen:\r
- The buffer for painting everything before bliting\r
- width:\r
- The width of the window in pixels\r
- height:\r
- The height of the window in pixels\r
- extendScale :\r
- True if the scale is G to C instead of C to C\r
- cascade:\r
- True if crossing from note to note with a button pressed triggers a new note\r
- scaleSize:\r
- The size of the scale used\r
- cursorPositions:\r
- The positions of the cursors on the screen, in pixels\r
- '''\r
- \r
- \r
- \r
- def __init__(self, instrumentChoice=None, song = None, cascade=False, extendedScale=False, defaultInstrumentChannel = 16, defaultNote = 60):\r
- '''\r
- Constructor\r
- ''' \r
- self.blinkLength = 200\r
- self.minimalVelocity = 64\r
- self.shortScaleSize = 8\r
- self.longScaleSize = 11\r
- if not extendedScale:\r
- self.offset = self.longScaleSize - self.shortScaleSize\r
- else:\r
- self.offset = 0\r
- self.borderSize = 5\r
- self.savedHighlightedNote = 0\r
- \r
- self.wiimotes = instrumentChoice.wiimotes\r
- self.activeWiimotes = instrumentChoice.activeWiimotes\r
- self.window = instrumentChoice.window\r
- self.screen = instrumentChoice.screen\r
- self.blitOrigin = instrumentChoice.blitOrigin\r
- self.clock = instrumentChoice.clock\r
- self.width = instrumentChoice.width\r
- self.height = instrumentChoice.height\r
- self.cursorPositions = instrumentChoice.cursorPositions\r
- self.savedScreen = instrumentChoice.savedScreen\r
- self.playerScreen = instrumentChoice.playerScreen\r
- self.extendedScale = extendedScale\r
- self.cascade = cascade\r
- self.joys = instrumentChoice.joys\r
- self.portOffset = instrumentChoice.portOffset\r
- self.eventLog = instrumentChoice.eventLog\r
- self.cursorPositions = instrumentChoice.cursorPositions\r
- self.song = song\r
- self.songIterator = self.moveToNextNote()\r
- self.replay = instrumentChoice.replay\r
- \r
- self.defaultInstrumentChannel = defaultInstrumentChannel\r
- self.defaultNote = defaultNote\r
- \r
- self.done = False\r
- self.backToInstrumentChoice = False\r
- self.easyMode = False\r
- \r
- self.highlightedNote = self.songIterator.next()\r
- \r
- self.blinkOn = False\r
- self.savedBlinkOn = False\r
- ##Will prevent the song to move on if two consecutive notes are identical and the buttons have not been released in between the two\r
- ##i.e. it guarantees that there will be an attack between two identical consecutive notes\r
- self.highlightIsFree = True\r
- \r
- self.noteRects = []\r
- self.boundingRect = None\r
- self.notes = []\r
- self.buttonDown = []\r
- self.velocityLock = []\r
- \r
- self._blinkOffset = 0\r
- \r
- self.font = pygame.font.Font(None,50)\r
- self.firstWiimote = 0\r
- while not self.activeWiimotes[self.firstWiimote] :\r
- self.firstWiimote += 1\r
- self.renderedNoteNames = [self.font.render(constants.noteNumberToName(note),False,(0,0,0)) for note in self.wiimotes[self.firstWiimote].instrument.notes[self.offset:]]\r
- \r
- self.drawBackground()\r
- self.initializeWiimotes()\r
- \r
- #The main loop\r
- while not self.done :\r
- \r
- #Clear the cursors from the screen\r
- if self.hasChanged():\r
- self.drawBackground()\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = self.clock.tick(50)\r
- \r
- self._blinkOffset += timePassed\r
- if self._blinkOffset > self.blinkLength:\r
- self._blinkOffset -= self.blinkLength\r
- self.blinkOn = not self.blinkOn\r
- \r
- if self.replay:\r
- self.eventLog.update(timePassed)\r
- pickledEventsToPost = self.eventLog.getPickledEvents() \r
- for pickledEvent in pickledEventsToPost:\r
- pygame.event.post(pickledEvent.event)\r
- \r
- events = pygame.event.get()\r
- \r
- if not self.replay:\r
- pickledEvents = [PickleableEvent(event.type,event.dict) for event in events]\r
- if pickledEvents != [] :\r
- self.eventLog.appendEventGroup(pickledEvents)\r
- \r
- for event in events:\r
- self.input(event)\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])\r
- if self.buttonDown[i] :\r
- self.wiimotes[i].cursor.flash()\r
- self.wiimotes[i].cursor.blit(self.playerScreen)\r
- \r
- self.screen.blit(self.playerScreen, (0,0))\r
- \r
- pygame.display.flip()\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].stopNote(self.notes[i]) \r
- \r
- def drawBackground(self):\r
- self.savedScreen.fill((255,255,255))\r
- \r
- if self.extendedScale :\r
- self.scaleSize = self.longScaleSize\r
- else:\r
- self.scaleSize = self.shortScaleSize\r
- \r
- self.noteRects = [pygame.Rect(i * self.width / self.scaleSize+self.blitOrigin[0], self.blitOrigin[1], self.width / self.scaleSize + 1, self.height+1) for i in range(self.scaleSize)]\r
- #inflate last noteRect to cover the far right pixels\r
- self.noteRects[-1].width = self.noteRects[-1].width + 1\r
- \r
- #create bounding rect\r
- self.boundingRect = self.noteRects[0].unionall(self.noteRects)\r
- \r
- #fill the rectangles with a color gradient\r
- #We start with blue\r
- startingHue = 0.66666666666666663\r
- \r
- for rectNumber in range(self.scaleSize):\r
- colorRatio = float(rectNumber) / (self.scaleSize - 1)\r
- #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up\r
- hue = startingHue * (1 - colorRatio)\r
- if self.song != None:\r
- if rectNumber + self.offset == self.highlightedNote:\r
- #The color of the bottom of the rectangle in hls coordinates\r
- bottomColorHls = (hue, 0.6, 1)\r
- #The color of the top of the rectangle in hls coordinates\r
- topColorHls = (hue, 0.9, 1)\r
- else:\r
- #The color of the bottom of the rectangle in hls coordinates\r
- bottomColorHls = (hue, 0.2, 1)\r
- #The color of the top of the rectangle in hls coordinates\r
- topColorHls = (hue, 0.4, 1)\r
- else:\r
- #The color of the bottom of the rectangle in hls coordinates\r
- bottomColorHls = (hue, 0.6, 1)\r
- #The color of the top of the rectangle in hls coordinates\r
- topColorHls = (hue, 0.9, 1)\r
- \r
- #convert to rgb ranging from 0 to 255\r
- bottomColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*bottomColorHls)]\r
- topColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*topColorHls)]\r
- #add transparency\r
- bottomColorRgb.append(255)\r
- topColorRgb.append(255)\r
- #convert to tuple\r
- bottomColorRgb = tuple(bottomColorRgb)\r
- topColorRgb = tuple(topColorRgb) \r
- \r
- self.savedScreen.blit(gradients.vertical(self.noteRects[rectNumber].size, topColorRgb, bottomColorRgb), self.noteRects[rectNumber])\r
- \r
- textBlitPoint = (self.noteRects[rectNumber].left+(self.noteRects[rectNumber].width-self.renderedNoteNames[rectNumber].get_width())/2,\r
- self.noteRects[rectNumber].bottom-self.renderedNoteNames[rectNumber].get_height())\r
- \r
- self.savedScreen.blit(self.renderedNoteNames[rectNumber], textBlitPoint)\r
- \r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 255), self.noteRects[rectNumber], 2)\r
- \r
- \r
- if self.song != None and self.blinkOn:\r
- borderSize = self.borderSize\r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 0), self.noteRects[self.highlightedNote-self.offset].inflate(borderSize/2,borderSize/2), borderSize)\r
- \r
- def initializeWiimotes(self):\r
- for loop in self.wiimotes:\r
- if loop.port == None :\r
- loop.port = pygame.midi.Output(loop.portNumber)\r
- self.notes.append(0)\r
- self.buttonDown.append(False)\r
- self.velocityLock.append(False)\r
- \r
- def updateCursorPositionFromJoy(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if correctedJoyId < len(self.cursorPositions):\r
- if joyEvent.axis == 0 :\r
- self.cursorPositions[correctedJoyId] = (int((joyEvent.value + 1) / 2 * self.screen.get_width()), self.cursorPositions[correctedJoyId][1])\r
- if joyEvent.axis == 1 :\r
- self.cursorPositions[correctedJoyId] = (self.cursorPositions[correctedJoyId][0], int((joyEvent.value + 1) / 2 * self.screen.get_height()))\r
- \r
- def heightToVelocity(self, pos, controllerNumber):\r
- if self.song != None:\r
- if self.boundingRect.collidepoint(pos) and (self.highlightedNote == self.notes[controllerNumber] or self.velocityLock[controllerNumber]):\r
- velocity = int(floor((1 - (float(pos[1])-self.blitOrigin[1]) / self.height) * (127-self.minimalVelocity))+self.minimalVelocity)\r
- else :\r
- if self.easyMode:\r
- velocity = None\r
- else:\r
- velocity = self.minimalVelocity/3\r
- else:\r
- if self.boundingRect.collidepoint(pos):\r
- velocity = int(floor((1 - (float(pos[1])-self.blitOrigin[1]) / self.height) * (127-self.minimalVelocity))+self.minimalVelocity)\r
- else :\r
- velocity = self.minimalVelocity\r
- return(velocity)\r
- \r
- def widthToNote(self, pos):\r
- nn = 0\r
- try :\r
- while self.noteRects[nn].collidepoint(pos) == False:\r
- nn = nn + 1\r
- return(nn + self.offset)\r
- except(IndexError):\r
- return(None)\r
- \r
- def input(self, event): \r
- \r
- if event.type == pygame.QUIT:\r
- for loop in self.wiimotes:\r
- del loop.port\r
- pygame.midi.quit()\r
- sys.exit(0) \r
- \r
- if event.type == pygame.KEYDOWN:\r
- if event.key == pygame.K_q:\r
- self.done = True\r
- \r
- if event.key == pygame.K_i:\r
- self.backToInstrumentChoice = True\r
- self.done = True \r
- \r
- if event.type == pygame.JOYAXISMOTION:\r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- self.updateCursorPositionFromJoy(event) \r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- \r
- if self.buttonDown[correctedJoyId]:\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity)\r
- if self.cascade:\r
- n = self.widthToNote(pos)\r
- if n != self.notes[correctedJoyId]:\r
- wiimote.stopNote(self.notes[correctedJoyId])\r
- self.notes[correctedJoyId] = n\r
- \r
- if self.song != None :\r
- if self.highlightedNote == self.notes[correctedJoyId]:\r
- self.highlightedNote = self.songIterator.next()\r
- self.velocityLock[correctedJoyId] = True\r
- else:\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- \r
- wiimote.playNote(self.notes[correctedJoyId],velocity)\r
- \r
- if event.type == pygame.JOYBUTTONDOWN :\r
- \r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- \r
- if not self.buttonDown[correctedJoyId]:\r
- savedNote = self.notes[correctedJoyId]\r
- self.notes[correctedJoyId] = self.widthToNote(pos)\r
- \r
- if self.song != None :\r
- if self.highlightedNote == self.notes[correctedJoyId]:\r
- self.highlightedNote = self.songIterator.next()\r
- self.velocityLock[correctedJoyId] = True\r
- \r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- \r
- if velocity != None : \r
- if self.easyMode :\r
- wiimote.stopNote(savedNote)\r
- wiimote.playNote(self.notes[correctedJoyId],velocity)\r
- self.buttonDown[correctedJoyId] = True\r
- \r
- if event.type == pygame.JOYBUTTONUP:\r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- self.buttonDown[correctedJoyId] = False\r
- wiimote = self.wiimotes[correctedJoyId]\r
- if not self.easyMode:\r
- wiimote.stopNote(self.notes[correctedJoyId])\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- if event.type == pygame.MOUSEMOTION:\r
- \r
- self.updateCursorPositionFromMouse(event)\r
-\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
-\r
- if self.buttonDown[correctedJoyId]:\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity)\r
- if self.cascade:\r
- n = self.widthToNote(pos)\r
- if n != self.notes[correctedJoyId]:\r
- wiimote.stopNote(self.notes[correctedJoyId])\r
- self.notes[correctedJoyId] = n\r
- \r
- if self.song != None :\r
- if self.highlightedNote == self.notes[correctedJoyId]:\r
- self.highlightedNote = self.songIterator.next()\r
- self.velocityLock[correctedJoyId] = True\r
- else:\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- \r
- wiimote.playNote(self.notes[correctedJoyId],velocity) \r
- \r
- if event.type == pygame.MOUSEBUTTONDOWN:\r
- \r
- if event.button == 1:\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- \r
- if not self.buttonDown[correctedJoyId]:\r
- self.notes[correctedJoyId] = self.widthToNote(pos)\r
- \r
- if self.song != None :\r
- if self.highlightedNote == self.notes[correctedJoyId]:\r
- self.highlightedNote = self.songIterator.next()\r
- self.velocityLock[correctedJoyId] = True\r
- \r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- \r
- wiimote.playNote(self.notes[correctedJoyId],velocity)\r
- self.buttonDown[correctedJoyId] = True\r
- \r
- if event.button == 2:\r
- \r
- self.done = True\r
- \r
- if event.type == pygame.MOUSEBUTTONUP:\r
- \r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- wiimote.stopNote(self.notes[correctedJoyId])\r
- self.buttonDown[correctedJoyId] = False\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- def hasChanged(self):\r
- changed = False\r
- if self.song != None:\r
- if self.blinkOn != self.savedBlinkOn or self.highlightedNote != self.savedHighlightedNote:\r
- self.savedBlinkOn = self.blinkOn\r
- self.savedHighlightedNote = self.highlightedNote\r
- changed = True\r
- return(changed)\r
- \r
- def updateCursorPositionFromMouse(self, mouseEvent):\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- self.cursorPositions[correctedJoyId] = mouseEvent.pos\r
- \r
- def moveToNextNote(self):\r
- while True:\r
- if self.song == None:\r
- yield(None)\r
- else:\r
- for note in self.song:\r
- yield note\r
+++ /dev/null
-'''\r
-Created on 23 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-from math import floor, ceil\r
-import pygame\r
-import sys\r
-import colorsys\r
-import constants\r
-from gradients import gradients\r
-from logging.PickleableEvent import PickleableEvent\r
-from logging.EventLog import EventLog\r
-\r
-\r
-class SongFamiliarizer:\r
- '''\r
- The screen on which the game is played\r
- \r
- wiimotes: \r
- The wiimotes used in this session\r
- window:\r
- The main display window\r
- screen:\r
- The main display surface\r
- clock:\r
- The clock used to animate the screen\r
- savedScreen:\r
- The background that is painted every time\r
- playerScreen:\r
- The buffer for painting everything before bliting\r
- width:\r
- The width of the window in pixels\r
- height:\r
- The height of the window in pixels\r
- extendScale :\r
- True if the scale is G to C instead of C to C\r
- cascade:\r
- True if crossing from note to note with a button pressed triggers a new note\r
- scaleSize:\r
- The size of the scale used\r
- cursorPositions:\r
- The positions of the cursors on the screen, in pixels\r
- '''\r
- \r
- \r
- \r
- def __init__(self, wiimotes, window, screen, clock, joys, portOffset, song, activeWiimotes, cascade=False, extendedScale=False, easyMode = False, replay = False, eventLog = None, defaultInstrumentChannel = 16, defaultNote = 60):\r
- '''\r
- Constructor\r
- ''' \r
- self.firstClickTime = None\r
- self.firstClickInTime = None\r
- self.duration = None\r
- self.clicks = 0\r
- self.clicksIn = 0\r
- \r
- pygame.font.init()\r
- self.font = pygame.font.Font(None,60)\r
- self.congratulations = ["Bien !","Tres Bien !","Bravo !","Excellent !","Felicitations !"]\r
- self.renderedCongratulations = [self.font.render(congratulation,False,(0,0,0)) for congratulation in self.congratulations]\r
- self.congratulationCount = None\r
- self.isCongratulating = False\r
- self.congratulationTimer = 0\r
- self.congratulationLength = 2000\r
- self.congratulationPos = None\r
- \r
- self.blinkLength = 200\r
- self.minimalVelocity = 90\r
- self.shortScaleSize = 8\r
- self.longScaleSize = 11\r
- if not extendedScale:\r
- self.offset = self.longScaleSize - self.shortScaleSize\r
- else:\r
- self.offset = 0\r
- self.borderSize = 5\r
- self.highlightedNote = 0\r
- self.highlightedNoteNumber = 0\r
- self.syllabus = None\r
- self.savedHighlightedNote = 0\r
- self.scaleFactor = 1\r
- self.level = 3\r
- \r
- self.wiimotes = wiimotes\r
- self.activeWiimotes = activeWiimotes\r
- self.window = window\r
- self.screen = screen\r
- self.width = int(floor(screen.get_width()*self.scaleFactor))\r
- self.height = int(floor(screen.get_height()*self.scaleFactor))\r
- self.blitOrigin = ((self.screen.get_width()-self.width)/2,(self.screen.get_height()-self.height)/2) \r
- self.joys = joys\r
- self.clock = clock\r
- self.cursorPositions = []\r
- self.savedScreen = pygame.Surface(self.screen.get_size())\r
- self.savedScreen.fill((255,255,255))\r
- self.playerScreen = pygame.Surface(self.savedScreen.get_size())\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- self.extendedScale = extendedScale\r
- self.cascade = cascade\r
- self.portOffset =portOffset\r
- self.eventLog = eventLog\r
- self.song = song\r
- self.songIterator = self.song.getSongIterator()\r
- self.midiNoteNumbers = self.song.scale\r
- self.replay = replay\r
- self.quarterNoteLength = 800\r
- self.cascadeLockLengthMultiplier = 1\r
- self.cascadeLockLength = self.quarterNoteLength * self.cascadeLockLengthMultiplier\r
- \r
- self.defaultInstrumentChannel = defaultInstrumentChannel\r
- self.defaultNote = defaultNote\r
- \r
- self.done = False\r
- self.backToInstrumentChoice = False\r
- self.easyMode = easyMode\r
- \r
- if eventLog == None:\r
- self.eventLog = EventLog()\r
- self.replay = False\r
- else:\r
- self.eventLog = eventLog\r
- self.replay = replay\r
- \r
- #Initializes the highlightedNote and highlightedNoteNumber etc...\r
- self.moveToNextNote()\r
- \r
- self.blinkOn = False\r
- self.savedBlinkOn = False\r
- ##Will prevent the song to move on if two consecutive notes are identical and the buttons have not been released in between the two\r
- ##i.e. it guarantees that there will be an attack between two identical consecutive notes\r
- self.highlightIsFree = True\r
- \r
- self.noteRects = []\r
- self.boundingRect = None\r
- self.notes = []\r
- \r
- self.buttonDown = []\r
- self.velocityLock = []\r
- \r
- self._blinkOffset = 0\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = True\r
- \r
- self.font = pygame.font.Font(None,50)\r
- self.renderedNoteNames = [self.font.render(constants.noteNumberToName(note),False,(0,0,0)) for note in self.midiNoteNumbers]\r
- \r
- self.drawBackground()\r
- self.initializeWiimotes()\r
- \r
- events = pygame.event.get()\r
- \r
- #The main loop\r
- while not self.done :\r
- \r
- #Clear the cursors from the screen\r
- if self.hasChanged():\r
- self.drawBackground()\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = self.clock.tick(10000)\r
- \r
- self._blinkOffset += timePassed\r
- if self.buttonDown and not self.cascadeIsFree :\r
- self._cascadeLockTimer += timePassed\r
- if self._cascadeLockTimer > self.cascadeLockLength :\r
- self.cascadeIsFree = True\r
- \r
- \r
- if self._blinkOffset > self.blinkLength:\r
- self._blinkOffset -= self.blinkLength\r
- self.blinkOn = not self.blinkOn\r
- \r
- if self.replay:\r
- self.eventLog.update(timePassed)\r
- pickledEventsToPost = self.eventLog.getPickledEvents() \r
- for pickledEvent in pickledEventsToPost:\r
- pygame.event.post(pickledEvent.event)\r
- \r
- events = pygame.event.get()\r
- \r
- if not self.replay:\r
- pickledEvents = [PickleableEvent(event.type,event.dict) for event in events]\r
- if pickledEvents != [] :\r
- self.eventLog.appendEventGroup(pickledEvents)\r
- \r
- for event in events:\r
- self.input(event)\r
- \r
- if self.isCongratulating :\r
- self.congratulationTimer += timePassed\r
- if self.congratulationTimer < self.congratulationLength :\r
- self.blitCongratulation()\r
- else :\r
- self.isCongratulating = False\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])\r
- if self.buttonDown[i] :\r
- self.wiimotes[i].cursor.flash()\r
- self.wiimotes[i].cursor.blit(self.playerScreen)\r
- \r
- self.screen.blit(self.playerScreen, (0,0))\r
- \r
- pygame.display.flip()\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].stopNoteByNoteNumber(self.midiNoteNumbers[self.notes[i]]) \r
- if self.replay :\r
- self.duration = self.eventLog.getCurrentTime()\r
- \r
- def drawBackground(self):\r
- self.savedScreen.fill((255,255,255))\r
- \r
- if self.extendedScale :\r
- self.scaleSize = self.longScaleSize\r
- else:\r
- self.scaleSize = self.shortScaleSize\r
- \r
- self.noteRects = [pygame.Rect(i * self.width / self.scaleSize+self.blitOrigin[0], self.blitOrigin[1], self.width / self.scaleSize + 1, self.height+1) for i in range(self.scaleSize)]\r
- #inflate last noteRect to cover the far right pixels\r
- self.noteRects[-1].width = self.noteRects[-1].width + 1\r
- \r
- self.noteRects[self.highlightedNote-self.offset].inflate_ip(self.noteRects[self.highlightedNote-self.offset].width*2,0)\r
- \r
- #create bounding rect\r
- self.boundingRect = self.noteRects[0].unionall(self.noteRects)\r
- \r
- self.renderedNoteNames = [self.font.render(constants.noteNumberToName(note),False,(0,0,0)) for note in self.midiNoteNumbers]\r
- \r
- #fill the rectangles with a color gradient\r
- #We start with blue\r
- startingHue = 0.66666666666666663\r
- \r
-# for rectNumber in range(self.scaleSize):\r
-# colorRatio = float(rectNumber) / (self.scaleSize - 1)\r
-# #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up\r
-# hue = startingHue * (1 - colorRatio)\r
-# if rectNumber + self.offset != self.highlightedNote:\r
-# #The color of the bottom of the rectangle in hls coordinates\r
-# bottomColorHls = (hue, 0.1, 1)\r
-# #The color of the top of the rectangle in hls coordinates\r
-# topColorHls = (hue, 0.1, 1)\r
-# \r
-# #convert to rgb ranging from 0 to 255\r
-# bottomColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*bottomColorHls)]\r
-# topColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*topColorHls)]\r
-# #add transparency\r
-# bottomColorRgb.append(255)\r
-# topColorRgb.append(255)\r
-# #convert to tuple\r
-# bottomColorRgb = tuple(bottomColorRgb)\r
-# topColorRgb = tuple(topColorRgb) \r
-# \r
-# self.savedScreen.blit(gradients.vertical(self.noteRects[rectNumber].size, topColorRgb, bottomColorRgb), self.noteRects[rectNumber])\r
-# \r
-# noteNameBlitPoint = (self.noteRects[rectNumber].left+(self.noteRects[rectNumber].width-self.renderedNoteNames[rectNumber].get_width())/2,\r
-# self.noteRects[rectNumber].bottom-self.renderedNoteNames[rectNumber].get_height())\r
-# \r
-# self.savedScreen.blit(self.renderedNoteNames[rectNumber], noteNameBlitPoint)\r
-# \r
-# pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 255), self.noteRects[rectNumber], 2)\r
- \r
- colorRatio = float(self.highlightedNote-self.offset) / (self.scaleSize - 1)\r
- #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up\r
- hue = startingHue * (1 - colorRatio)\r
- #The color of the bottom of the rectangle in hls coordinates\r
- bottomColorHls = (hue, 0.6, 1)\r
- #The color of the top of the rectangle in hls coordinates\r
- topColorHls = (hue, 0.9, 1)\r
- \r
- #convert to rgb ranging from 0 to 255\r
- bottomColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*bottomColorHls)]\r
- topColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*topColorHls)]\r
- #add transparency\r
- bottomColorRgb.append(255)\r
- topColorRgb.append(255)\r
- #convert to tuple\r
- bottomColorRgb = tuple(bottomColorRgb)\r
- topColorRgb = tuple(topColorRgb) \r
- \r
- self.savedScreen.blit(gradients.vertical(self.noteRects[self.highlightedNote-self.offset].size, topColorRgb, bottomColorRgb), self.noteRects[self.highlightedNote-self.offset])\r
- \r
-# noteNameBlitPoint = (self.noteRects[self.highlightedNote-self.offset].left+(self.noteRects[self.highlightedNote-self.offset].width-self.renderedNoteNames[self.highlightedNote-self.offset].get_width())/2,\r
-# self.noteRects[self.highlightedNote-self.offset].bottom-self.renderedNoteNames[self.highlightedNote-self.offset].get_height())\r
-# \r
-# self.savedScreen.blit(self.renderedNoteNames[self.highlightedNote-self.offset], noteNameBlitPoint)\r
-# \r
-# if self.syllabus :\r
-# renderedSyllabus = self.font.render(self.syllabus,False,(0,0,0))\r
-# \r
-# syllabusBlitPoint = (self.noteRects[self.highlightedNote-self.offset].left+(self.noteRects[self.highlightedNote-self.offset].width-renderedSyllabus.get_width())/2,\r
-# self.noteRects[self.highlightedNote-self.offset].centery-renderedSyllabus.get_height()/2)\r
-# \r
-# self.savedScreen.blit(renderedSyllabus, syllabusBlitPoint)\r
- \r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 255), self.noteRects[self.highlightedNote-self.offset], 2) \r
- \r
-# if self.song != None and self.blinkOn:\r
-# borderSize = self.borderSize\r
-# pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 0), self.noteRects[self.highlightedNote-self.offset].inflate(borderSize/2,borderSize/2), borderSize)\r
- \r
- def initializeWiimotes(self):\r
- for loop in self.wiimotes:\r
- if loop.port == None :\r
- loop.port = pygame.midi.Output(loop.portNumber)\r
- self.notes.append(0)\r
- self.cursorPositions.append(loop.cursor.centerPosition)\r
- self.buttonDown.append(False)\r
- self.velocityLock.append(False)\r
- \r
- def updateCursorPositionFromJoy(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if correctedJoyId < len(self.cursorPositions):\r
- if joyEvent.axis == 0 :\r
- self.cursorPositions[correctedJoyId] = (int((joyEvent.value + 1) / 2 * self.screen.get_width()), self.cursorPositions[correctedJoyId][1])\r
- if joyEvent.axis == 1 :\r
- self.cursorPositions[correctedJoyId] = (self.cursorPositions[correctedJoyId][0], int((joyEvent.value + 1) / 2 * self.screen.get_height()))\r
- \r
- def heightToVelocity(self, pos, controllerNumber):\r
- if self.song != None:\r
- if self.boundingRect.collidepoint(pos) and (self.highlightedNote == self.notes[controllerNumber] or self.velocityLock[controllerNumber]):\r
- velocity = int(floor((1 - (float(pos[1])-self.blitOrigin[1]) / self.height) * (127-self.minimalVelocity))+self.minimalVelocity)\r
- else :\r
- if self.easyMode:\r
- velocity = None\r
- else:\r
- velocity = 60\r
- else:\r
- if self.boundingRect.collidepoint(pos):\r
- velocity = int(floor((1 - (float(pos[1])-self.blitOrigin[1]) / self.height) * (127-self.minimalVelocity))+self.minimalVelocity)\r
- else :\r
- velocity = self.minimalVelocity\r
- return(velocity)\r
- \r
- def widthToNote(self, pos):\r
- nn = 0\r
- try :\r
- if self.noteRects[self.highlightedNote-self.offset].collidepoint(pos) :\r
- return self.highlightedNote\r
- else :\r
- while self.noteRects[nn].collidepoint(pos) == False:\r
- nn = nn + 1\r
- return(nn + self.offset)\r
- except(IndexError):\r
- return(None)\r
- \r
- def congratulate(self,targetRect,posy):\r
- if self.congratulationCount != None :\r
- if self.congratulationCount < len(self.congratulations)-1:\r
- self.congratulationCount += 1\r
- else :\r
- self.congratulationCount = 0\r
- self.congratulationTimer = 0\r
- self.congratulationPos = (targetRect.left+(targetRect.width-self.renderedCongratulations[self.congratulationCount].get_width())/2,posy)\r
- self.isCongratulating = True\r
- \r
- def resetCongratulation(self):\r
- self.congratulationCount = None\r
- self.congratulationPos = None\r
- self.isCongratulating = False\r
- \r
- def blitCongratulation(self):\r
- self.playerScreen.blit(self.renderedCongratulations[self.congratulationCount],self.congratulationPos)\r
- \r
- def input(self, event): \r
- \r
- if event.type == pygame.QUIT:\r
- for loop in self.wiimotes:\r
- del loop.port\r
- pygame.midi.quit()\r
- sys.exit(0) \r
- \r
- if event.type == pygame.KEYDOWN:\r
- if event.key == pygame.K_q:\r
- self.nextLevel = None\r
- self.done = True\r
- \r
- if event.key == pygame.K_w:\r
- self.nextLevel = 0\r
- self.done = True\r
- \r
- if event.key == pygame.K_e:\r
- self.nextLevel = 1\r
- self.done = True\r
- \r
- if event.key == pygame.K_r:\r
- self.nextLevel = 2\r
- self.done = True\r
- \r
- if event.key == pygame.K_t:\r
- self.nextLevel = 3\r
- self.done = True\r
- \r
- if event.type == pygame.JOYAXISMOTION:\r
- \r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- self.updateCursorPositionFromJoy(event)\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- \r
- if self.buttonDown[correctedJoyId]:\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- if velocity != None :\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity)\r
- if self.cascade and self.cascadeIsFree :\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- self.moveToNextNote()\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- \r
- if event.type == pygame.JOYBUTTONDOWN :\r
- \r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- self.wiimotes[correctedJoyId].cursor.flash()\r
- if self.replay:\r
- self.clicks += 1\r
- if self.firstClickTime == None :\r
- self.firstClickTime = self.eventLog.getCurrentTime()\r
- \r
- if not self.buttonDown[correctedJoyId]:\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- if self.easyMode:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- self.congratulate(self.noteRects[self.notes[correctedJoyId]],pos[1])\r
- if self.replay:\r
- self.clicksIn += 1\r
- if self.firstClickInTime == None :\r
- self.firstClickInTime = self.eventLog.getCurrentTime()\r
- \r
- self.moveToNextNote()\r
- else :\r
- self.resetCongratulation()\r
- if not self.easyMode :\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId) \r
- if velocity != None :\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity) \r
- self.buttonDown[correctedJoyId] = True\r
- \r
- if event.type == pygame.JOYBUTTONUP:\r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- self.buttonDown[correctedJoyId] = False\r
- wiimote = self.wiimotes[correctedJoyId]\r
- if not self.easyMode:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- if event.type == pygame.MOUSEMOTION:\r
- \r
- self.updateCursorPositionFromMouse(event)\r
- \r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
-\r
- if self.buttonDown[correctedJoyId]:\r
- self.wiimotes[correctedJoyId].cursor.flash()\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- if velocity != None :\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity)\r
- if self.cascade and self.cascadeIsFree :\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- self.moveToNextNote()\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False \r
- \r
- if event.type == pygame.MOUSEBUTTONDOWN:\r
- \r
- if event.button == 1:\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- self.wiimotes[correctedJoyId].cursor.flash()\r
- if self.replay:\r
- self.clicks += 1\r
- if self.firstClickTime == None :\r
- self.firstClickTime = self.eventLog.getCurrentTime()\r
- \r
- if not self.buttonDown[correctedJoyId]:\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- if self.easyMode:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- self.congratulate(self.noteRects[self.notes[correctedJoyId]],pos[1])\r
- if self.replay:\r
- self.clicksIn += 1\r
- if self.firstClickInTime == None :\r
- self.firstClickInTime = self.eventLog.getCurrentTime()\r
- \r
- self.moveToNextNote()\r
- else :\r
- self.resetCongratulation()\r
- if not self.easyMode :\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId) \r
- if velocity != None :\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity) \r
- self.buttonDown[correctedJoyId] = True \r
- \r
- if event.button == 2:\r
- \r
- self.done = True\r
- \r
- if event.type == pygame.MOUSEBUTTONUP:\r
- if event.button == 1 :\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- self.buttonDown[correctedJoyId] = False\r
- if not self.easyMode:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- def hasChanged(self):\r
- changed = False\r
- if self.song != None:\r
- if self.blinkOn != self.savedBlinkOn or self.highlightedNote != self.savedHighlightedNote:\r
- self.savedBlinkOn = self.blinkOn\r
- self.savedHighlightedNote = self.highlightedNote\r
- changed = True\r
- return(changed)\r
- \r
- def updateCursorPositionFromMouse(self, mouseEvent):\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- self.cursorPositions[correctedJoyId] = mouseEvent.pos\r
- \r
- def moveToNextNote(self):\r
- self.savedMidiNoteNumbers = self.midiNoteNumbers[:]\r
- self.highlightedNote, self.highlightedNoteNumber, self.syllabus, self.cascadeLockLengthMultiplier = self.songIterator.next()\r
- self.midiNoteNumbers[self.highlightedNote] = self.highlightedNoteNumber\r
+++ /dev/null
-'''\r
-Created on 23 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-from math import floor, ceil\r
-import pygame\r
-import sys\r
-import colorsys\r
-import constants\r
-from gradients import gradients\r
-from logging.PickleableEvent import PickleableEvent\r
-from songs.Song import Song\r
-from songs.musicxmltosong import Part\r
-\r
-\r
-class SongPlayingScreen:\r
- '''\r
- The screen on which the game is played\r
- \r
- wiimotes: \r
- The wiimotes used in this session\r
- window:\r
- The main display window\r
- screen:\r
- The main display surface\r
- clock:\r
- The clock used to animate the screen\r
- savedScreen:\r
- The background that is painted every time\r
- playerScreen:\r
- The buffer for painting everything before bliting\r
- width:\r
- The width of the window in pixels\r
- height:\r
- The height of the window in pixels\r
- extendScale :\r
- True if the scale is G to C instead of C to C\r
- cascade:\r
- True if crossing from note to note with a button pressed triggers a new note\r
- scaleSize:\r
- The size of the scale used\r
- cursorPositions:\r
- The positions of the cursors on the screen, in pixels\r
- '''\r
- \r
- \r
- \r
- def __init__(self, instrumentChoice, pguconf):# song, cascade=False, extendedScale=False, easyMode = False, alwaysDown = False, eventLog = None, replay = None, defaultInstrumentChannel = 16, defaultNote = 60):\r
- '''\r
- Constructor\r
- '''\r
- song = pguconf.song\r
- cascade = pguconf.cascade\r
- extendedScale = song.requiresExtendedScale\r
- easyMode = pguconf.easyMode\r
- alwaysDown = pguconf.alwaysDown\r
- eventLog = instrumentChoice.eventLog\r
- replay = instrumentChoice.replay\r
- defaultInstrumentChannel = 16\r
- defaultNote = 60\r
-\r
- if isinstance(song, Song) :\r
- self.songDurations = []\r
- self.totalDuration = None\r
- self.clicks = [0]\r
- self.clicksIn = [0]\r
- self.clicksPerMinute = [0]\r
- self.clicksInPerMinute = [0]\r
- self.meanTimeBetweenNotes = []\r
- self.firstClick = None\r
- self.firstClickIn = None\r
- \r
- self.blinkLength = 200\r
- self.minimalVelocity = 90\r
- self.shortScaleSize = 8\r
- self.longScaleSize = 11\r
- if not extendedScale:\r
- self.offset = self.longScaleSize - self.shortScaleSize\r
- else:\r
- self.offset = 0\r
- self.borderSize = 5\r
- self.highlightedNote = 0\r
- self.highlightedNoteNumber = 0\r
- self.syllabus = None\r
- self.savedHighlightedNote = 0\r
- self.alwaysDown = alwaysDown\r
- self.nextLevel = None\r
- \r
- self.wiimotes = instrumentChoice.wiimotes\r
- self.activeWiimotes = instrumentChoice.activeWiimotes\r
- self.window = instrumentChoice.window\r
- self.screen = instrumentChoice.screen\r
- self.blitOrigin = instrumentChoice.blitOrigin\r
- self.clock = instrumentChoice.clock\r
- self.width = instrumentChoice.width\r
- self.height = instrumentChoice.height\r
- self.cursorPositions = instrumentChoice.cursorPositions\r
- self.savedScreen = instrumentChoice.savedScreen\r
- self.playerScreen = instrumentChoice.playerScreen\r
- self.extendedScale = extendedScale\r
- self.cascade = cascade\r
- self.joys = instrumentChoice.joys\r
- self.portOffset = instrumentChoice.portOffset\r
- if eventLog == None :\r
- self.eventLog = instrumentChoice.eventLog\r
- else :\r
- self.eventLog = eventLog\r
- self.cursorPositions = instrumentChoice.cursorPositions\r
- self.song = song\r
- self.songIterator = self.song.getSongIterator()\r
- self.midiNoteNumbers = self.song.scale\r
- if replay == None :\r
- self.replay = instrumentChoice.replay\r
- else :\r
- self.replay = replay\r
- self.quarterNoteLength = song.quarterNoteLength\r
- self.cascadeLockLengthMultiplier = 1\r
- self.nextCascadeLockLengthMultiplier = 1\r
- self.cascadeLockLength = self.quarterNoteLength * self.cascadeLockLengthMultiplier\r
- \r
- self.defaultInstrumentChannel = defaultInstrumentChannel\r
- self.defaultNote = defaultNote\r
- \r
- self.done = False\r
- self.backToInstrumentChoice = False\r
- self.easyMode = easyMode\r
- \r
- #Initializes the highlightedNote and highlightedNoteNumber etc...\r
- self.moveToNextNote()\r
- self.cascadeLockLengthMultiplier = self.nextCascadeLockLengthMultiplier\r
- \r
- self.blinkOn = False\r
- self.savedBlinkOn = False\r
- ##Will prevent the song to move on if two consecutive notes are identical and the buttons have not been released in between the two\r
- ##i.e. it guarantees that there will be an attack between two identical consecutive notes\r
- self.highlightIsFree = True\r
- \r
- self.noteRects = []\r
- self.boundingRect = None\r
- self.notes = []\r
- \r
- self.buttonDown = []\r
- self.velocityLock = []\r
- \r
- self._blinkOffset = 0\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = True\r
- \r
- self.font = pygame.font.Font(None,80)\r
- self.renderedNoteNames = [self.font.render(constants.noteNumberToName(note),False,(0,0,0)) for note in self.midiNoteNumbers]\r
- \r
- self.drawBackground()\r
- self.initializeWiimotes()\r
- \r
- self.songStartTime = self.eventLog.getCurrentTime()\r
- \r
- #The main loop\r
- while not self.done :\r
- \r
- #Clear the cursors from the screen\r
- if self.hasChanged():\r
- self.drawBackground()\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = self.clock.tick(10000)\r
- \r
- self._blinkOffset += timePassed\r
- if (self.buttonDown or self.alwaysDown) and not self.cascadeIsFree :\r
- self._cascadeLockTimer += timePassed\r
- if self._cascadeLockTimer > self.cascadeLockLengthMultiplier*self.quarterNoteLength :\r
- self.cascadeIsFree = True\r
- self.cascadeLockLengthMultiplier = self.nextCascadeLockLengthMultiplier\r
- \r
- \r
- if self._blinkOffset > self.blinkLength:\r
- self._blinkOffset -= self.blinkLength\r
- self.blinkOn = not self.blinkOn\r
- \r
- if self.replay:\r
- self.eventLog.update(timePassed)\r
- pickledEventsToPost = self.eventLog.getPickledEvents() \r
- for pickledEvent in pickledEventsToPost:\r
- pygame.event.post(pickledEvent.event)\r
- \r
- events = pygame.event.get()\r
- \r
- if not self.replay:\r
- pickledEvents = [PickleableEvent(event.type,event.dict) for event in events]\r
- if pickledEvents != [] :\r
- self.eventLog.appendEventGroup(pickledEvents)\r
- \r
- for event in events:\r
- self.input(event)\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])\r
- if self.buttonDown[i] or self.alwaysDown:\r
- self.wiimotes[i].cursor.flash()\r
- self.wiimotes[i].cursor.blit(self.playerScreen)\r
- \r
- self.screen.blit(self.playerScreen, (0,0))\r
- \r
- pygame.display.flip()\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].stopNoteByNoteNumber(self.midiNoteNumbers[self.notes[i]])\r
- if self.replay : \r
- self.totalDuration = self.eventLog.getCurrentTime()\r
- \r
- elif isinstance(song, Part) :\r
- self.songDurations = []\r
- self.totalDuration = None\r
- self.clicks = [0]\r
- self.clicksIn = [0]\r
- self.clicksPerMinute = [0]\r
- self.clicksInPerMinute = [0]\r
- self.meanTimeBetweenNotes = []\r
- self.firstClick = None\r
- self.firstClickIn = None\r
- \r
- self.blinkLength = 200\r
- self.minimalVelocity = 90\r
- self.shortScaleSize = 8\r
- self.longScaleSize = 11\r
- if not extendedScale:\r
- self.offset = self.longScaleSize - self.shortScaleSize\r
- else:\r
- self.offset = 0\r
- self.borderSize = 5\r
- self.highlightedNote = 0\r
- self.highlightedNoteNumber = 0\r
- self.syllabus = None\r
- self.savedHighlightedNote = 0\r
- self.alwaysDown = alwaysDown\r
- self.nextLevel = None\r
- \r
- self.wiimotes = instrumentChoice.wiimotes\r
- self.activeWiimotes = instrumentChoice.activeWiimotes\r
- self.window = instrumentChoice.window\r
- self.screen = instrumentChoice.screen\r
- self.blitOrigin = instrumentChoice.blitOrigin\r
- self.clock = instrumentChoice.clock\r
- self.width = instrumentChoice.width\r
- self.height = instrumentChoice.height\r
- self.cursorPositions = instrumentChoice.cursorPositions\r
- self.savedScreen = instrumentChoice.savedScreen\r
- self.playerScreen = instrumentChoice.playerScreen\r
- self.extendedScale = extendedScale\r
- self.cascade = cascade\r
- self.joys = instrumentChoice.joys\r
- self.portOffset = instrumentChoice.portOffset\r
- if eventLog == None :\r
- self.eventLog = instrumentChoice.eventLog\r
- else :\r
- self.eventLog = eventLog\r
- self.cursorPositions = instrumentChoice.cursorPositions\r
- self.song = song\r
- self.songIterator = self.song.iterNotes()\r
- self.midiNoteNumbers = self.song.scale\r
- if replay == None :\r
- self.replay = instrumentChoice.replay\r
- else :\r
- self.replay = replay\r
- self.quarterNoteLength = song.quarterNoteLength\r
- self.cascadeLockLengthMultiplier = 1\r
- self.nextCascadeLockLengthMultiplier = 1\r
- self.cascadeLockLength = self.quarterNoteLength * self.cascadeLockLengthMultiplier\r
- \r
- self.defaultInstrumentChannel = defaultInstrumentChannel\r
- self.defaultNote = defaultNote\r
- \r
- self.done = False\r
- self.backToInstrumentChoice = False\r
- self.easyMode = easyMode\r
- \r
- #Initializes the highlightedNote and highlightedNoteNumber etc...\r
- self.moveToNextNote()\r
- self.cascadeLockLengthMultiplier = self.nextCascadeLockLengthMultiplier\r
- \r
- self.blinkOn = False\r
- self.savedBlinkOn = False\r
- ##Will prevent the song to move on if two consecutive notes are identical and the buttons have not been released in between the two\r
- ##i.e. it guarantees that there will be an attack between two identical consecutive notes\r
- self.highlightIsFree = True\r
- \r
- self.noteRects = []\r
- self.boundingRect = None\r
- self.notes = []\r
- \r
- self.buttonDown = []\r
- self.velocityLock = []\r
- \r
- self._blinkOffset = 0\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = True\r
- \r
- self.font = pygame.font.Font(None,80)\r
- self.renderedNoteNames = [self.font.render(constants.noteNumberToName(note),False,(0,0,0)) for note in self.midiNoteNumbers]\r
- \r
- self.drawBackground()\r
- self.initializeWiimotes()\r
- \r
- self.songStartTime = self.eventLog.getCurrentTime()\r
- \r
- #The main loop\r
- while not self.done :\r
- \r
- #Clear the cursors from the screen\r
- if self.hasChanged():\r
- self.drawBackground()\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = self.clock.tick(10000)\r
- \r
- self._blinkOffset += timePassed\r
- if (self.buttonDown or self.alwaysDown) and not self.cascadeIsFree :\r
- self._cascadeLockTimer += timePassed\r
- if self._cascadeLockTimer > self.cascadeLockLengthMultiplier*self.quarterNoteLength :\r
- self.cascadeIsFree = True\r
- self.cascadeLockLengthMultiplier = self.nextCascadeLockLengthMultiplier\r
- \r
- \r
- if self._blinkOffset > self.blinkLength:\r
- self._blinkOffset -= self.blinkLength\r
- self.blinkOn = not self.blinkOn\r
- \r
- if self.replay:\r
- self.eventLog.update(timePassed)\r
- pickledEventsToPost = self.eventLog.getPickledEvents() \r
- for pickledEvent in pickledEventsToPost:\r
- pygame.event.post(pickledEvent.event)\r
- \r
- events = pygame.event.get()\r
- \r
- if not self.replay:\r
- pickledEvents = [PickleableEvent(event.type,event.dict) for event in events]\r
- if pickledEvents != [] :\r
- self.eventLog.appendEventGroup(pickledEvents)\r
- \r
- for event in events:\r
- self.input(event)\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])\r
- if self.buttonDown[i] or self.alwaysDown:\r
- self.wiimotes[i].cursor.flash()\r
- self.wiimotes[i].cursor.blit(self.playerScreen)\r
- \r
- self.screen.blit(self.playerScreen, (0,0))\r
- \r
- pygame.display.flip()\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].stopNoteByNoteNumber(self.midiNoteNumbers[self.notes[i]])\r
- if self.replay : \r
- self.totalDuration = self.eventLog.getCurrentTime()\r
- \r
- def drawBackground(self):\r
- self.savedScreen.fill((255,255,255))\r
- \r
- if self.extendedScale :\r
- self.scaleSize = self.longScaleSize\r
- else:\r
- self.scaleSize = self.shortScaleSize\r
- \r
- self.noteRects = [pygame.Rect(i * self.width / self.scaleSize+self.blitOrigin[0], self.blitOrigin[1], self.width / self.scaleSize + 1, self.height+1) for i in range(self.scaleSize)]\r
- #inflate last noteRect to cover the far right pixels\r
- self.noteRects[-1].width = self.noteRects[-1].width + 1\r
- \r
- self.noteRects[self.highlightedNote-self.offset].inflate_ip(self.noteRects[self.highlightedNote-self.offset].width*2,0)\r
- \r
- #create bounding rect\r
- self.boundingRect = self.noteRects[0].unionall(self.noteRects)\r
- \r
- self.renderedNoteNames = [self.font.render(constants.noteNumberToName(note),False,(0,0,0)) for note in self.midiNoteNumbers]\r
- \r
- #fill the rectangles with a color gradient\r
- #We start with blue\r
- startingHue = 0.66666666666666663\r
- \r
- for rectNumber in range(self.scaleSize):\r
- colorRatio = float(rectNumber) / (self.scaleSize - 1)\r
- #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up\r
- hue = startingHue * (1 - colorRatio)\r
- if rectNumber + self.offset != self.highlightedNote:\r
- #The color of the bottom of the rectangle in hls coordinates\r
- bottomColorHls = (hue, 0.1, 1)\r
- #The color of the top of the rectangle in hls coordinates\r
- topColorHls = (hue, 0.1, 1)\r
- \r
- #convert to rgb ranging from 0 to 255\r
- bottomColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*bottomColorHls)]\r
- topColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*topColorHls)]\r
- #add transparency\r
- bottomColorRgb.append(255)\r
- topColorRgb.append(255)\r
- #convert to tuple\r
- bottomColorRgb = tuple(bottomColorRgb)\r
- topColorRgb = tuple(topColorRgb) \r
- \r
- self.savedScreen.blit(gradients.vertical(self.noteRects[rectNumber].size, topColorRgb, bottomColorRgb), self.noteRects[rectNumber])\r
- \r
- noteNameBlitPoint = (self.noteRects[rectNumber].left+(self.noteRects[rectNumber].width-self.renderedNoteNames[rectNumber+self.offset].get_width())/2,\r
- self.noteRects[rectNumber].bottom-self.renderedNoteNames[rectNumber+self.offset].get_height())\r
- \r
- self.savedScreen.blit(self.renderedNoteNames[rectNumber+self.offset], noteNameBlitPoint)\r
- \r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 255), self.noteRects[rectNumber], 2)\r
- \r
- colorRatio = float(self.highlightedNote-self.offset) / (self.scaleSize - 1)\r
- #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up\r
- hue = startingHue * (1 - colorRatio)\r
- #The color of the bottom of the rectangle in hls coordinates\r
- bottomColorHls = (hue, 0.6, 1)\r
- #The color of the top of the rectangle in hls coordinates\r
- topColorHls = (hue, 0.9, 1)\r
- \r
- #convert to rgb ranging from 0 to 255\r
- bottomColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*bottomColorHls)]\r
- topColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*topColorHls)]\r
- #add transparency\r
- bottomColorRgb.append(255)\r
- topColorRgb.append(255)\r
- #convert to tuple\r
- bottomColorRgb = tuple(bottomColorRgb)\r
- topColorRgb = tuple(topColorRgb) \r
- \r
- self.savedScreen.blit(gradients.vertical(self.noteRects[self.highlightedNote-self.offset].size, topColorRgb, bottomColorRgb), self.noteRects[self.highlightedNote-self.offset])\r
- \r
- noteNameBlitPoint = (self.noteRects[self.highlightedNote-self.offset].left+(self.noteRects[self.highlightedNote-self.offset].width-self.renderedNoteNames[self.highlightedNote].get_width())/2,\r
- self.noteRects[self.highlightedNote-self.offset].bottom-self.renderedNoteNames[self.highlightedNote].get_height())\r
- \r
- self.savedScreen.blit(self.renderedNoteNames[self.highlightedNote], noteNameBlitPoint)\r
- \r
- if self.syllabus :\r
- renderedSyllabus = self.font.render(self.syllabus,False,(0,0,0))\r
- \r
- syllabusBlitPoint = (self.noteRects[self.highlightedNote-self.offset].left+(self.noteRects[self.highlightedNote-self.offset].width-renderedSyllabus.get_width())/2,\r
- self.noteRects[self.highlightedNote-self.offset].centery-renderedSyllabus.get_height()/2)\r
- \r
- self.savedScreen.blit(renderedSyllabus, syllabusBlitPoint)\r
- \r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 255), self.noteRects[self.highlightedNote-self.offset], 2) \r
- \r
- if self.song != None and self.blinkOn:\r
- borderSize = self.borderSize\r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 0), self.noteRects[self.highlightedNote-self.offset].inflate(borderSize/2,borderSize/2), borderSize)\r
- \r
- def initializeWiimotes(self):\r
- for loop in self.wiimotes:\r
- if loop.port == None :\r
- loop.port = pygame.midi.Output(loop.portNumber)\r
- self.notes.append(0)\r
- self.buttonDown.append(False)\r
- self.velocityLock.append(False)\r
- \r
- def updateCursorPositionFromJoy(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if correctedJoyId < len(self.cursorPositions):\r
- if joyEvent.axis == 0 :\r
- self.cursorPositions[correctedJoyId] = (int((joyEvent.value + 1) / 2 * self.screen.get_width()), self.cursorPositions[correctedJoyId][1])\r
- if joyEvent.axis == 1 :\r
- self.cursorPositions[correctedJoyId] = (self.cursorPositions[correctedJoyId][0], int((joyEvent.value + 1) / 2 * self.screen.get_height()))\r
- \r
- def heightToVelocity(self, pos, controllerNumber):\r
- if self.song != None:\r
- if self.boundingRect.collidepoint(pos) and (self.highlightedNote == self.notes[controllerNumber] or self.velocityLock[controllerNumber]):\r
- velocity = int(floor((1 - (float(pos[1])-self.blitOrigin[1]) / self.height) * (127-self.minimalVelocity))+self.minimalVelocity)\r
- else :\r
- if self.easyMode:\r
- velocity = None\r
- else:\r
- velocity = 60\r
- else:\r
- if self.boundingRect.collidepoint(pos):\r
- velocity = int(floor((1 - (float(pos[1])-self.blitOrigin[1]) / self.height) * (127-self.minimalVelocity))+self.minimalVelocity)\r
- else :\r
- velocity = self.minimalVelocity\r
- return(velocity)\r
- \r
- def widthToNote(self, pos):\r
- nn = 0\r
- try :\r
- if self.noteRects[self.highlightedNote-self.offset].collidepoint(pos) :\r
- return self.highlightedNote\r
- else :\r
- while self.noteRects[nn].collidepoint(pos) == False:\r
- nn = nn + 1\r
- return(nn + self.offset)\r
- except(IndexError):\r
- return(None)\r
- \r
- def logClick(self):\r
- self.clicks[-1] += 1\r
- if self.firstClick == None :\r
- self.firstClick = self.eventLog.getCurrentTime()\r
- minute = int(floor((self.eventLog.getCurrentTime()-self.songStartTime)/60000))\r
- if minute > len(self.clicksPerMinute)-1:\r
- self.clicksPerMinute.append(0)\r
- self.clicksPerMinute[-1] += 1\r
- \r
- def logClickIn(self):\r
- self.clicksIn[-1] += 1\r
- if self.clicksIn[-1] > len(self.song.notes)-1 :\r
- self.clicksIn.append(0)\r
- self.clicks.append(0)\r
- self.songDurations.append(self.eventLog.getCurrentTime())\r
- if self.firstClickIn == None :\r
- self.firstClickIn = self.eventLog.getCurrentTime()\r
- minute = int(floor((self.eventLog.getCurrentTime()-self.songStartTime)/60000))\r
- if minute > len(self.clicksInPerMinute)-1:\r
- self.clicksInPerMinute.append(0)\r
- self.clicksInPerMinute[-1]+=1\r
- \r
- def input(self, event): \r
- \r
- if event.type == pygame.QUIT:\r
- for loop in self.wiimotes:\r
- del loop.port\r
- pygame.midi.quit()\r
- sys.exit(0) \r
- \r
- if event.type == pygame.KEYDOWN:\r
- if event.key == pygame.K_q:\r
- self.nextLevel = None\r
- self.done = True\r
- \r
- if event.key == pygame.K_i:\r
- self.backToInstrumentChoice = True\r
- self.done = True\r
- \r
- if event.key == pygame.K_w:\r
- self.nextLevel = 0\r
- self.done = True\r
- \r
- if event.key == pygame.K_e:\r
- self.nextLevel = 1\r
- self.done = True\r
- \r
- if event.key == pygame.K_r:\r
- self.nextLevel = 2\r
- self.done = True\r
- \r
- if event.key == pygame.K_t:\r
- self.nextLevel = 3\r
- self.done = True \r
- \r
- if event.type == pygame.JOYAXISMOTION:\r
- \r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- self.updateCursorPositionFromJoy(event)\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- \r
- if (self.buttonDown[correctedJoyId] or self.alwaysDown):\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- if velocity != None :\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity)\r
- if self.cascade and self.cascadeIsFree :\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- self.moveToNextNote()\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- \r
- if event.type == pygame.JOYBUTTONDOWN :\r
- \r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- self.wiimotes[correctedJoyId].cursor.flash()\r
- if self.replay:\r
- self.logClick()\r
- \r
- if not (self.buttonDown[correctedJoyId] or self.alwaysDown):\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- if self.easyMode:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- if self.replay :\r
- self.logClickIn()\r
- self.moveToNextNote()\r
- else :\r
- if not self.easyMode :\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId) \r
- if velocity != None and self.notes[correctedJoyId] != None :\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity) \r
- self.buttonDown[correctedJoyId] = True\r
- \r
- if event.type == pygame.JOYBUTTONUP:\r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- self.buttonDown[correctedJoyId] = False\r
- wiimote = self.wiimotes[correctedJoyId]\r
- if not self.easyMode:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- if event.type == pygame.MOUSEMOTION:\r
- \r
- self.updateCursorPositionFromMouse(event)\r
- \r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
-\r
- if (self.buttonDown[correctedJoyId] or self.alwaysDown):\r
- self.wiimotes[correctedJoyId].cursor.flash()\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- if velocity != None :\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity)\r
- if self.cascade and self.cascadeIsFree :\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- self.moveToNextNote()\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False \r
- \r
- if event.type == pygame.MOUSEBUTTONDOWN:\r
- \r
- if event.button == 1:\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- self.wiimotes[correctedJoyId].cursor.flash()\r
- if self.replay:\r
- self.logClick()\r
- \r
- if not (self.buttonDown[correctedJoyId] or self.alwaysDown):\r
- n = self.widthToNote(pos)\r
- if self.highlightedNote == n:\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- if self.easyMode:\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- self.velocityLock[correctedJoyId] = True\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity)\r
- if self.replay :\r
- self.logClickIn()\r
- self.moveToNextNote()\r
- else :\r
- if not self.easyMode :\r
- self._cascadeLockTimer = 0\r
- self.cascadeIsFree = False\r
- self.notes[correctedJoyId] = n\r
- velocity = self.heightToVelocity(pos, correctedJoyId) \r
- if velocity != None and self.notes[correctedJoyId] != None :\r
- wiimote.playNoteByNoteNumber(self.midiNoteNumbers[self.notes[correctedJoyId]],velocity) \r
- self.buttonDown[correctedJoyId] = True \r
- \r
- if event.button == 2:\r
- \r
- self.done = True\r
- \r
- if event.type == pygame.MOUSEBUTTONUP:\r
- if event.button == 1 :\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- self.buttonDown[correctedJoyId] = False\r
- if not self.easyMode:\r
- if self.notes[correctedJoyId] != None :\r
- wiimote.stopNoteByNoteNumber(self.savedMidiNoteNumbers[self.notes[correctedJoyId]])\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- def hasChanged(self):\r
- changed = False\r
- if self.song != None:\r
- if self.blinkOn != self.savedBlinkOn or self.highlightedNote != self.savedHighlightedNote:\r
- self.savedBlinkOn = self.blinkOn\r
- self.savedHighlightedNote = self.highlightedNote\r
- changed = True\r
- return(changed)\r
- \r
- def updateCursorPositionFromMouse(self, mouseEvent):\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- self.cursorPositions[correctedJoyId] = mouseEvent.pos\r
- \r
- def moveToNextNote(self):\r
- self.savedMidiNoteNumbers = self.midiNoteNumbers[:]\r
- note, lyricIndex = self.songIterator.next()\r
- self.highlightedNote = note.column\r
- self.highlightedNoteNumber = note.midi\r
- self.syllabus = note.lyrics[lyricIndex].syllabus('iso-8859-1')\r
- self.nextCascadeLockLengthMultiplier = note.duration\r
- self.midiNoteNumbers[self.highlightedNote] = self.highlightedNoteNumber\r
- \r
- #self.highlightedNote, self.highlightedNoteNumber, self.syllabus, self.nextCascadeLockLengthMultiplier = self.songIterator.next()\r
- #self.midiNoteNumbers[self.highlightedNote] = self.highlightedNoteNumber\r
+++ /dev/null
-'''\r
-Created on 23 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-from math import floor, ceil\r
-import pygame\r
-import pygame.midi\r
-import sys\r
-import colorsys\r
-import constants\r
-from gradients import gradients\r
-from logging.PickleableEvent import PickleableEvent\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from logging.EventLog import EventLog\r
-\r
-\r
-class StaticFamiliarizer:\r
- '''\r
- The screen on which the game is played\r
- \r
- wiimotes: \r
- The wiimotes used in this session\r
- window:\r
- The main display window\r
- screen:\r
- The main display surface\r
- clock:\r
- The clock used to animate the screen\r
- savedScreen:\r
- The background that is painted every time\r
- playerScreen:\r
- The buffer for painting everything before bliting\r
- width:\r
- The width of the window in pixels\r
- height:\r
- The height of the window in pixels\r
- extendScale :\r
- True if the scale is G to C instead of C to C\r
- cascade:\r
- True if crossing from note to note with a button pressed triggers a new note\r
- scaleSize:\r
- The size of the scale used\r
- cursorPositions:\r
- The positions of the cursors on the screen, in pixels\r
- '''\r
- \r
- \r
- \r
- def __init__(self, wiimotes, window, screen, clock, joys, portOffset,activeWiimotes,replay = False, level = 0, defaultInstrumentChannel = 16, defaultNote = 60, eventLog = None):\r
- '''\r
- Constructor\r
- '''\r
- self.firstClickTime = None\r
- self.firstClickInTime = None\r
- self.duration = None\r
- self.clicks = 0\r
- self.clicksIn = 0\r
- \r
- pygame.font.init()\r
- self.font = pygame.font.Font(None,60)\r
- self.congratulations = ["Bien !","Tres Bien !","Bravo !","Excellent !","Felicitations !"]\r
- self.renderedCongratulations = [self.font.render(congratulation,False,(0,0,0)) for congratulation in self.congratulations]\r
- self.congratulationCount = None\r
- self.isCongratulating = False\r
- self.congratulationTimer = 0\r
- self.congratulationLength = 2000\r
- self.congratulationPos = None\r
- \r
- self.blinkLength = 200\r
- self.minimalVelocity = 64\r
- self.shortScaleSize = 8\r
- self.longScaleSize = 11\r
- self.borderSize = 5\r
- self.savedHighlightedNote = 0\r
- self.scaleFactor = 1\r
- self.wiimotes = wiimotes\r
- self.window = window\r
- self.screen = screen\r
- self.clock = clock\r
- self.width = int(floor(screen.get_width()*self.scaleFactor))\r
- self.height = int(floor(screen.get_height()*self.scaleFactor))\r
- self.blitOrigin = ((self.screen.get_width()-self.width)/2,(self.screen.get_height()-self.height)/2) \r
- self.joys = joys\r
- self.portOffset = portOffset\r
- self.savedScreen = pygame.Surface(self.screen.get_size())\r
- self.savedScreen.fill((255,255,255))\r
- self.playerScreen = pygame.Surface(self.savedScreen.get_size())\r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- self.cursorPositions = []\r
- self.level = level\r
- self.nextLevel = None\r
- self.activeWiimotes = activeWiimotes\r
- \r
- for i in range(len(self.wiimotes)):\r
- #Set the screen for the cursors (it can't be set before)\r
- self.wiimotes[i].cursor.screen = self.playerScreen\r
- self.cursorPositions.append(self.wiimotes[i].cursor.centerPosition)\r
- \r
- if eventLog == None:\r
- self.eventLog = EventLog()\r
- self.replay = False\r
- else:\r
- self.eventLog = eventLog\r
- self.replay = replay\r
- \r
- self.defaultInstrumentChannel = defaultInstrumentChannel\r
- self.defaultNote = defaultNote\r
- \r
- self.done = False\r
- self.backToInstrumentChoice = False\r
- self.easyMode = False\r
-\r
- self.noteRects = []\r
- self.boundingRect = None\r
- self.notes = []\r
- self.buttonDown = []\r
- self.velocityLock = []\r
- \r
- self.drawBackground()\r
- self.initializeWiimotes()\r
- events = pygame.event.get()\r
- \r
- #The main loop\r
- while not self.done :\r
- \r
- self.playerScreen.blit(self.savedScreen, (0, 0))\r
- \r
- # Limit frame speed to 50 FPS\r
- #\r
- timePassed = self.clock.tick(10000)\r
- \r
- if self.replay:\r
- self.eventLog.update(timePassed)\r
- pickledEventsToPost = self.eventLog.getPickledEvents() \r
- for pickledEvent in pickledEventsToPost:\r
- pygame.event.post(pickledEvent.event)\r
- \r
- events = pygame.event.get()\r
- \r
- if not self.replay:\r
- pickledEvents = [PickleableEvent(event.type,event.dict) for event in events]\r
- if pickledEvents != [] :\r
- self.eventLog.appendEventGroup(pickledEvents)\r
- \r
- for event in events:\r
- self.input(event)\r
- \r
- if self.isCongratulating :\r
- self.congratulationTimer += timePassed\r
- if self.congratulationTimer < self.congratulationLength :\r
- self.blitCongratulation()\r
- else :\r
- self.isCongratulating = False\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- self.wiimotes[i].cursor.update(timePassed, self.cursorPositions[i])\r
- if self.buttonDown[i] :\r
- self.wiimotes[i].cursor.flash()\r
- self.wiimotes[i].cursor.blit(self.playerScreen)\r
- \r
- self.screen.blit(self.playerScreen, (0,0))\r
- \r
- pygame.display.flip()\r
- \r
- for i in range(len(self.wiimotes)):\r
- if self.activeWiimotes[i]:\r
- if self.notes[i] != None :\r
- self.wiimotes[i].stopNote(self.notes[i])\r
- if self.replay :\r
- self.duration = self.eventLog.getCurrentTime() \r
- \r
- def drawBackground(self):\r
- self.savedScreen.fill((255,255,255))\r
- if self.level == 0 :\r
- A = [4] \r
- else :\r
- A = [1,7]\r
- \r
- self.noteRects = [pygame.Rect(i * self.width / 11+self.blitOrigin[0], self.blitOrigin[1], (self.width / 11 + 1)*3, self.height+1) for i in A]\r
- \r
- #create bounding rect\r
- self.boundingRect = self.noteRects[0].unionall(self.noteRects)\r
- \r
- #fill the rectangles with a color gradient\r
- #We start with blue\r
- startingHue = 0.66666666666666663\r
- \r
- for rectNumber in range(len(self.noteRects)) :\r
- colorRatio = float(A[rectNumber]) / (11 - 1)\r
- #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up\r
- hue = startingHue * (1 - colorRatio)\r
- #The color of the bottom of the rectangle in hls coordinates\r
- bottomColorHls = (hue, 0.6, 1)\r
- #The color of the top of the rectangle in hls coordinates\r
- topColorHls = (hue, 0.9, 1)\r
- \r
- #convert to rgb ranging from 0 to 255\r
- bottomColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*bottomColorHls)]\r
- topColorRgb = [floor(255 * i) for i in colorsys.hls_to_rgb(*topColorHls)]\r
- #add transparency\r
- bottomColorRgb.append(255)\r
- topColorRgb.append(255)\r
- #convert to tuple\r
- bottomColorRgb = tuple(bottomColorRgb)\r
- topColorRgb = tuple(topColorRgb) \r
- \r
- self.savedScreen.blit(gradients.vertical(self.noteRects[rectNumber].size, topColorRgb, bottomColorRgb), self.noteRects[rectNumber])\r
- \r
- pygame.draw.rect(self.savedScreen, pygame.Color(0, 0, 0, 255), self.noteRects[rectNumber], 2)\r
- \r
- def initializeWiimotes(self):\r
- for loop in self.wiimotes:\r
- if loop.port == None :\r
- loop.port = pygame.midi.Output(loop.portNumber)\r
- self.notes.append(0)\r
- self.buttonDown.append(False)\r
- self.velocityLock.append(False)\r
- \r
- def updateCursorPositionFromJoy(self, joyEvent):\r
- joyName = pygame.joystick.Joystick(joyEvent.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if correctedJoyId < len(self.cursorPositions):\r
- if joyEvent.axis == 0 :\r
- self.cursorPositions[correctedJoyId] = (int((joyEvent.value + 1) / 2 * self.screen.get_width()), self.cursorPositions[correctedJoyId][1])\r
- if joyEvent.axis == 1 :\r
- self.cursorPositions[correctedJoyId] = (self.cursorPositions[correctedJoyId][0], int((joyEvent.value + 1) / 2 * self.screen.get_height()))\r
- \r
- def heightToVelocity(self, pos, controllerNumber):\r
- velocity = int(floor((1 - (float(pos[1])-self.blitOrigin[1]) / self.height) * (127-self.minimalVelocity))+self.minimalVelocity)\r
- return(velocity)\r
- \r
- def widthToNote(self, pos):\r
- nn = 0\r
- try :\r
- while self.noteRects[nn].collidepoint(pos) == False:\r
- nn = nn + 1\r
- return(nn)\r
- except(IndexError):\r
- return(None)\r
- \r
- def congratulate(self,targetRect,posy):\r
- if self.congratulationCount != None :\r
- if self.congratulationCount < len(self.congratulations)-1:\r
- self.congratulationCount += 1\r
- else :\r
- self.congratulationCount = 0\r
- self.congratulationTimer = 0\r
- self.congratulationPos = (targetRect.left+(targetRect.width-self.renderedCongratulations[self.congratulationCount].get_width())/2,posy)\r
- self.isCongratulating = True\r
- \r
- def resetCongratulation(self):\r
- self.congratulationCount = None\r
- self.congratulationPos = None\r
- self.isCongratulating = False\r
- \r
- def blitCongratulation(self):\r
- self.playerScreen.blit(self.renderedCongratulations[self.congratulationCount],self.congratulationPos) \r
- \r
- def input(self, event): \r
- \r
- print event\r
- \r
- if event.type == pygame.QUIT:\r
- for loop in self.wiimotes:\r
- del loop.port\r
- pygame.midi.quit()\r
- sys.exit(0) \r
- \r
- if event.type == pygame.KEYDOWN:\r
- if event.key == pygame.K_q:\r
- self.nextLevel = None\r
- self.done = True\r
- \r
- if event.key == pygame.K_w:\r
- self.nextLevel = 0\r
- self.done = True\r
- \r
- if event.key == pygame.K_e:\r
- self.nextLevel = 1\r
- self.done = True\r
- \r
- if event.key == pygame.K_r:\r
- self.nextLevel = 2\r
- self.done = True\r
- \r
- if event.key == pygame.K_t:\r
- self.nextLevel = 3\r
- self.done = True \r
- \r
- if event.type == pygame.JOYAXISMOTION:\r
- \r
- \r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- self.updateCursorPositionFromJoy(event)\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- \r
- if self.buttonDown[correctedJoyId]:\r
- wiimote.cursor.flash()\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity)\r
- \r
- if event.type == pygame.JOYBUTTONDOWN :\r
- \r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- wiimote.cursor.flash()\r
- if self.replay :\r
- self.clicks += 1\r
- if self.firstClickTime == None :\r
- self.firstClickTime = self.eventLog.getCurrentTime()\r
- \r
- if not self.buttonDown[correctedJoyId]:\r
- self.notes[correctedJoyId] = self.widthToNote(pos)\r
- \r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- \r
- if self.notes[correctedJoyId] != None : \r
- wiimote.playNote(self.notes[correctedJoyId],velocity)\r
- self.congratulate(self.noteRects[self.notes[correctedJoyId]],pos[1])\r
- if self.replay :\r
- self.clicksIn += 1\r
- if self.firstClickInTime == None :\r
- self.firstClickInTime = self.eventLog.getCurrentTime()\r
- else :\r
- self.resetCongratulation()\r
- \r
- self.buttonDown[correctedJoyId] = True\r
- \r
- if event.type == pygame.JOYBUTTONUP:\r
- joyName = pygame.joystick.Joystick(event.joy).get_name()\r
- correctedJoyId = constants.joyNames.index(joyName)\r
- if self.activeWiimotes[correctedJoyId]:\r
- wiimote = self.wiimotes[correctedJoyId]\r
- wiimote.stopNote(self.notes[correctedJoyId])\r
- self.buttonDown[correctedJoyId] = False\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- if event.type == pygame.MOUSEMOTION:\r
- \r
- self.updateCursorPositionFromMouse(event)\r
- \r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
-\r
- if self.buttonDown[correctedJoyId]:\r
- wiimote.cursor.flash()\r
- if self.notes[correctedJoyId] != None:\r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- CCHexCode = wiimote.getCCHexCode()\r
- wiimote.port.write_short(CCHexCode, 07, velocity) \r
- \r
- if event.type == pygame.MOUSEBUTTONDOWN:\r
- \r
- if event.button == 1:\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- pos = self.cursorPositions[correctedJoyId]\r
- wiimote.cursor.flash()\r
- if self.replay :\r
- self.clicks += 1\r
- if self.firstClickTime == None :\r
- self.firstClickTime = self.eventLog.getCurrentTime()\r
- \r
- if not self.buttonDown[correctedJoyId]:\r
- self.notes[correctedJoyId] = self.widthToNote(pos)\r
- \r
- velocity = self.heightToVelocity(pos, correctedJoyId)\r
- \r
- if self.notes[correctedJoyId] != None : \r
- wiimote.playNote(self.notes[correctedJoyId],velocity)\r
- self.congratulate(self.noteRects[self.notes[correctedJoyId]],pos[1])\r
- if self.replay :\r
- self.clicksIn += 1\r
- if self.firstClickInTime == None :\r
- self.firstClickInTime = self.eventLog.getCurrentTime()\r
- else :\r
- self.resetCongratulation()\r
- \r
- self.buttonDown[correctedJoyId] = True\r
- \r
- if event.button == 2:\r
- \r
- self.done = True\r
- \r
- if event.type == pygame.MOUSEBUTTONUP:\r
- \r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- wiimote = self.wiimotes[correctedJoyId]\r
- wiimote.stopNote(self.notes[correctedJoyId])\r
- self.buttonDown[correctedJoyId] = False\r
- self.velocityLock[correctedJoyId] = False\r
- \r
- def hasChanged(self):\r
- return(True)\r
- \r
- def updateCursorPositionFromMouse(self, mouseEvent):\r
- correctedJoyId = 0\r
- while not self.activeWiimotes[correctedJoyId] :\r
- correctedJoyId += 1\r
- self.cursorPositions[correctedJoyId] = mouseEvent.pos\r
- \r
-if __name__ == "__main__" :\r
- pygame.init()\r
- modeResolution = (1024,768)\r
- window = pygame.display.set_mode(modeResolution,pygame.FULLSCREEN)\r
- pygame.font.init()\r
- \r
- pygame.midi.init()\r
- instruments = [Instrument(constants.scaleDict["majorScale"], i + 1, "".join(["../instruments/instrumentImages/", constants.instrumentImagePathList[i], ".jpg"]), constants.octaves[i]) for i in range(9)]\r
- \r
- joys = [[id,pygame.joystick.Joystick(id).get_name()] for id in range(pygame.joystick.get_count())]\r
- for joy in joys:\r
- if joy[1] in constants.joyNames:\r
- pygame.joystick.Joystick(joy[0]).init() \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(constants.portNames[0])\r
- print(portOffset)\r
- \r
- events = pygame.event.get()\r
- \r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages = [createImageListFromPath('../cursor/cursorImages/black', 11),createImageListFromPath('../cursor/cursorImages/red', 11)]\r
- durations = [75 for i in range(len(cursorImages[0]))]\r
- \r
- wiimoteCount = 1\r
- cursors = [WarpingCursor(None, cursorImages[i], durations, (300 * i, 300 * i),flashImage = '../cursor/cursorImages/black/flash.png' ) for i in range(wiimoteCount)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, instruments[i], cursors[i]) for i in range(wiimoteCount)]\r
- \r
- fam = StaticFamiliarizer(instruments, wiimotes, window, screen, clock, joys, portOffset)\r
- \r
- for loop in fam.wiimotes:\r
- del loop.port\r
- \r
- pygame.midi.quit()\r
- \r
- pygame.quit() \r
+++ /dev/null
-from songs.Song import Song#,loadSongFromMidi\r
-from dataTools.odict import OrderedDict\r
-\r
-joyNames = ["PPJoy Virtual joystick 1", "PPJoy Virtual joystick 2", "PPJoy Virtual joystick 3", "PPJoy Virtual joystick 4"]\r
-portNames = ["Out To MIDI Yoke: 1","Out To MIDI Yoke: 2","Out To MIDI Yoke: 3","Out To MIDI Yoke: 4"]\r
-\r
-readabilityDict = OrderedDict([("majeure" , "majorScale"),\r
- ("mineure naturelle" , "minorScale"),\r
- ("majeure myxolydienne" , "myxolydianScale"),\r
- ("mineure dorienne" , "dorianScale"),\r
- ("phrygienne espagnole" , "spanishPhrygianScale"),\r
- ("lydienne" , "lydianScale"),\r
- ("phrygienne" , "phrygianScale"),\r
- ("J'ai du bon tabac" , "jadbt"),\r
- ("L'eau vive" , "eauvive"),\r
- ("Le penitencier" , "penitencier"),\r
- ("La foule" , "foule"),\r
- ("Petit papa noel" , "papanoel"),\r
- ("La marseillaise" , "marseillaise"),\r
- ("A la claire fontaine" , "clairefontaine"),\r
- ("Au clair de la lune" , "clairdelalune"),\r
- ("Frere jacques" , "frerejacques"),\r
- ("Le petit vin blanc" , "vinblanc"),\r
- ("La vie en rose","vierose"),\r
- ("Les feuilles mortes","feuillesmortes"),\r
- ("Il pleut bergere","bergere"),\r
- ("Le temps des cerises","cerises"),\r
- ("La boheme","boheme"),\r
- ("Chanson Test","test"),\r
- ("Improvisation" , "none"),\r
- ("Do/Do","C/C"),\r
- ("Sol/Do","G/C"),\r
- ("Oui","Yes"),\r
- ("Non","No"),\r
- ("Tres facile","veryEasy"),\r
- ("Facile","easy"),\r
- ("Normal","normal"),\r
- ("Expert","expert")])\r
-\r
-reversedReadabilityDict = dict(zip(readabilityDict.values(),readabilityDict.keys()))\r
-\r
-rangeDict = {"C/C":False,"G/C":True}\r
-\r
-cascadeDict = {"Yes":True,"No":False}\r
-\r
-modeDict = OrderedDict([("veryEasy",0),("easy",1),("normal",2),("expert",3)])\r
-print modeDict['veryEasy']\r
-\r
-scaleDict = OrderedDict ([("majorScale" , [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72]),\r
- ("minorScale" , [55, 56, 58, 60, 62, 63, 65, 67, 68, 70, 72]),\r
- ("myxolydianScale" , [55, 57, 58, 60, 62, 64, 65, 67, 69, 70, 72]),\r
- ("dorianScale" , [55, 57, 58, 60, 62, 63, 65, 67, 69, 70, 72]),\r
- ("spanishPhrygianScale" , [55,57,58,60,62,63,66,67,69,70,72]),\r
- ("lydianScale" , [55, 57, 59, 60, 62, 64, 66, 67, 69, 71, 72]),\r
- ("phrygianScale" , [55, 56, 58, 60, 61, 63, 65, 67, 68, 70, 72])])\r
-\r
-songDict = OrderedDict([("jadbt" , Song(scaleDict["majorScale"],[3, 4, 5, 3, 4, 4, 5, 6, 6, 5, 5, 3, 4, 5, 3, 4, 4, 5, 6, 7, 3,7,7,6,5,4,5,6,7,4,7,7,6,5,4,5,6,7,4],False,\r
- lyrics = ["J'ai","du","bon","ta-","-bac","dans","ma","ta-","-ba-","-tie-","-re","J'ai","du","bon","ta-","-bac","tu","n'en","au-","-ras","pas","j'en","ai","du","fin","et","du","bien","ra-","-pe","mais","ce","n'est","pas","pour","ton","vi-","-lain","nez"],\r
- noteLengths = [1,1,1,1,2,1,1,2,2,2,2,1,1,1,1,2,1,1,2,2,4,2,1,1,2,1,1,2,2,4,2,1,1,2,1,1,2,2,4],\r
- quarterNoteLength = 400)),\r
- ("eauvive" , Song(scaleDict["majorScale"],[5,3,5,3,5,3,4,4,5,6,4,5,3,4,5,3,5,3,5,3,4,4,5,6,4,5,3,4,7,8,7,6,6,4,6,5,3,5,4,3,4,5,6,5,4,3,4,3,2,3],\r
- True,\r
- lyrics = ["Ma","pe-","-tite","est","co-","-mme","l'eau","elle","est","co-","-mme","l'eau","vi-","-ve","e-","-lle","court","comme","un","rui-","-sseau","que","les","en-","-fants","pour-","-sui-","-vent","ve-","-nez","ve-","-nez","mes","a-","-gneaux","mes","a-","-gne-","-lets","ja-","-mais","ja-","-mais","vous","ne","la","ra-","-ttra-","-pe-","-rez"],\r
- noteLengths = [2,1,2,1,2,1,3,1,1,1,2,1,3,3,2,1,2,1,2,1,3,1,1,1,2,1,3,3,3,3,3,3,1,1,1,1,1,1,6,3,3,3,3,1,1,1,1,1,1,6],\r
- quarterNoteLength = 300)),\r
- ("penitencier" , \r
- Song(scaleDict["dorianScale"],[3,3,3,5,7,6,3,3,10,10,10,9,7,6,7,10,10,10,3,5,6,7,6,3,5,3,3,3,3,2,2,3],\r
- True,\r
- alterationIndexes = [-2,-3],\r
- alterations = [1,1],\r
- lyrics = ["Les","por-","-tes","du","pe-","-ni-","-ten-","-cier","bien-","-tot","vont","se","re-","-fer-","-mer","et","c'est","la","que","je","fi-","-ni-","-rai","ma","vie","comme","d'au-","-tres","gars","l'ont","fi-","-nie"],\r
- noteLengths =[1,5,1,5,1,1,6,4,1,5,1,4,1,1,10,1,1,5,1,4,1,1,5,1,5,1,1,1,4,5,1,12],\r
- quarterNoteLength = 250)),\r
- ("papanoel" , Song(scaleDict["myxolydianScale"],[3,6,6,6,7,6,6,7,8,8,8,9,8,7,6,6,6,6,5,4,3,3,3,6,6,6,7,7,6],False,\r
- lyrics = ["pe-","-ti","Pa-","-pa","No-","-el","quand","tu","de-","-scen-","-dras","du","ciel","a-","-vec","tes","jou-","-ets","par","mi-","-lliers","n'ou-","-blie","pas","mes","pe-","-tits","sou-","-liers"],\r
- noteLengths = [1,1,1,1,1,3,0.5,0.5,1,1,1,1,3,1,1.5,0.5,0.5,0.5,0.5,0.5,3,0.5,0.5,1,0.5,0.5,0.5,0.5,3],\r
- quarterNoteLength = 500)),\r
- ("foule" , Song(scaleDict["myxolydianScale"],[7,7,6,5,6,8,7,7,6,8,7,7,6,9,7,7,6,9,7,7,6,8,7,7,6,8,7,6,5,4,4,4,4,4,4,6,6,6,6,8,8,7,6,8,7,7,7,7,7,7,7,7,7,7,7,7,6,9,8,7,8,8,7,8,8,7,8,8,7,8,8,6,8,8,6,8,8,7],False,modulationIndexes = [28],modulationScales = [scaleDict["spanishPhrygianScale"]],\r
- lyrics = ["Em-","-por-","-tes","par","la","fou-","-le","qui","nous","trai-","-ne","nous","en-","-trai-","-ne","e-","-cra-","-ses","l'un","con-","-tre","l'au-","-tre","nous","ne","for-","-mons","qu'un","seul","corps","et","le","flot","sans","e-","-ffort","nous","pousse","en-","-chai-","-nes","l'un","et","l'au-","-tre","et","nous","lai-","-sse","tous","deux","e-","-pa-","-nouis-","en-","-i-","-vres","et","heu-","-reux","ta-","-dam","ta","ta-","-dam","ta","ta-","-dam","ta","ta-","-dam","ta","ta-","-dam","ta","ta-","-dam","ta"],\r
- noteLengths = [1,1.5,.5,.5,.5,1.5,.5,.5,.5,1.5,.5,.5,.5,1.5,.5,.5,.5,1.5,.5,.5,.5,1.5,.5,.5,.5,1.5,.5,.5,.5,3,.5,.5,.5,.5,.5,.5,.5,.5,.5,1,1,.5,.5,1.5,3,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,1,1,1.5,.5,1,1.5,.5,1,1.5,.5,1,1.5,.5,1,1.5,.5,1,1.5,.5,1,3],\r
- quarterNoteLength = 400)),\r
- ("clairefontaine" , Song(scaleDict["majorScale"],\r
- [3,3,5,5,4,5,4,3,3,5,5,4,5,5,5,4,3,5,7,5,7,7,5,3,5,4,3,3,5,5,5,4,5,5,5,5,3,5,4,3],\r
- False,\r
- lyrics = ["A","la","clai-","-re","fon-","-tai-","-ne","m'en","a-","-llant","pro-","-me-","-ner","j'ai","trou-","-ve","l'eau","si","be-","-lle","que","je","m'y","suis","bai-","-gne","il","y-a","long-","-temps","que","je","t'aime","ja-","-mais","je","ne","t'ou-","-blie-","-rai"],\r
- noteLengths = [2,1,1,1,1,1,1,2,1,1,1,1,2,2,1,1,1,1,1,1,2,1,1,1,1,2,2,1,1,1,0.5,0.5,2,2,1,0.5,0.5,1,1,4],\r
- quarterNoteLength = 400)),\r
- ("clairdelalune", Song(scaleDict["lydianScale"], [7,7,7,8,9,8,7,9,8,8,7,7,7,7,8,9,8,7,9,8,8,7,8,8,8,8,5,5,8,7,6,5,4,7,7,7,8,9,8,7,9,8,8,7],False,\r
- lyrics = ["Au","clair","de","la","lu-","-ne","mon","a-","-mi","Pie-","-rrot","pre-","-te","moi","ta","plu-","-me","pour","e-","-crire","un","mot","ma","chan-","-delle","est","mor-","-te","je","n'ai","plus","de","feu","ou-","-vre","moi","ta","po-","-rte","pour","l'a-","-mour","de","Dieu"],\r
- noteLengths = [1,1,1,1,2,2,1,1,1,1,4,1,1,1,1,2,2,1,1,1,1,4,1,1,1,1,2,2,1,1,1,1,4,1,1,1,1,2,2,1,1,1,1,4],\r
- quarterNoteLength = 500)),\r
- ("frerejacques" , \r
- Song(scaleDict["majorScale"],\r
- [3,4,5,3,3,4,5,3,5,6,7,5,6,7,7,8,7,6,5,3,7,8,7,6,5,3,3,0,3,3,0,3],\r
- True,\r
- lyrics = ["Fre-","-re","Ja-","-cques","fre-","-re","-Ja","-cques","dor-","-mez","vous","dor-","-mez","vous","so-","-nnez","les","ma-","-ti-","-nes","so-","-nnez","les","ma-","-ti-","-nes","ding","ding","dong","ding","ding","dong"],\r
- noteLengths = [1,1,1,1,1,1,1,1,1,1,2,1,1,2,1.5,0.5,1,1,2,2,1.5,0.5,1,1,2,2,1,1,2,1,1,2],\r
- quarterNoteLength = 600)),\r
- ("marseillaise" , Song(scaleDict["majorScale"],[0, 0, 0, 3, 3, 4, 4, 7, 5, 3, 3, 5, 3, 1, 6, 4, 2, 3, 3, 4, 5, 5, 5, 6, 5, 5, 4, 4, 5, 6, 6, 6, 7, 6, 5, 7, 7, 7, 5, 3, 7, 5, 3, 0, 0, 0, 2, 4, 6, 4, 2, 4, 3, 2, 1, 3, 3, 3, 2, 3, 4, 4, 5, 5, 5, 5, 6, 7, 4, 5, 4, 3, 3, 3, 5, 4, 3, 3,2,7,7,7,5,3,4,7,7,7,5,3,4,0,3,4,5,6,7,8,4,8,7,5,6,4,3], True, modulationIndexes = [53,54,61,77], modulationScales = [scaleDict["dorianScale"],scaleDict["majorScale"],scaleDict["dorianScale"],scaleDict["majorScale"]],\r
- lyrics = ["A-","-llons","en-","-fants","de","la","pa","tri-","-i-","-e","le","jour","de","gloire","est","a-","-rri-","-ve","con-","-tre","nous","de","la","ty-","-ra-","-nni-","-e","l'e-","-ten-","-dard","san-","-glant","est","le-","-ve","l'e-","-ten-","-dard","san-","-an-","-glant","est","le-","-ve","en-","-ten-","-dez","vous","dans","nos","cam-","-pa-","-gnes","mu-","-gir","ces","fe-","-ro-","-ces","sol-","-dats","qui","vie-","-nnent","ju-","-sque","dans","nos","bras","e-","-gor-","-ger","nos","fils","et","nos","com-","-pa-","-gnes","aux","ar-","-mes","ci-","-toy-","-yen","for-","-mez","vos","ba-","-ta-","-illons","mar-","-chons","mar-","-chons","qu'un","sang","im-","-pur","a-","-breu-","-ve","nos","si-","-illons","pon","pon","pon","pon"],\r
- noteLengths = [1,2,1,3,3,3,3,5,1,2,1,2,1,3,6,2,1,9,2,1,3,3,3,2,1,3,6,2,1,3,3,3,2,1,6,2,1,3,2,1,3,2,1,6,1,2,1,6,3,2,1,3,3,6,3,2,1,3,2,1,6,3,5,1,2,1,2,1,6,2,1,5,1,2,1,2,1,6,5,1,7,1,2,1,8,1,7,1,2,1,8,3,9,3,9,6,3,3,9,3,8,1,2,1,2,1,2,1,8],\r
- quarterNoteLength = 300)),\r
- ("vinblanc" , \r
- Song(scaleDict["phrygianScale"],[5, 5, 5, 3, 5, 6, 5, 5, 5, 3, 7, 6, 6, 6, 6, 4, 8, 7, 7, 7, 8, 9, 7, 5, 5, 5, 5, 3, 5, 6, 8, 9, 10, 9, 8, 10, 9, 8, 6, 6, 8, 7, 6, 8, 6, 5, 3, 5, 6, 3, 5, 6, 3, 5, 6, 3, 5, 6, 3, 5, 7, 6, 5, 7, 6, 5, 8],\r
- False,\r
- lyrics = ["Ah","le","pe-","-tit","vin","blanc","qu'on","boit","sous","les","to-","-nelles","quand","les","fi-","-lles","sont","belles","du","co-","-te","de","No-","-geant","et","puis","de","temps","en","temps","un","air","de","vie-","-lle","ro-","-man-","-ce","sem-","-ble","do-","-nner","la","ca-","-den-","-ce","pour","fau-","-ter","pour","fau-","-ter","dans","les","bois","dans","les","pres","du","co-","-te","du","co-","-te","de","No-","-geant"],\r
- noteLengths = [1,1,1,2,1,6,1,1,1,2,1,6,1,1,1,2,1,6,1,1,1,2,1,6,1,1,1,2,1,6,1,1,1,1,1,1,3,3,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6],\r
- quarterNoteLength = 300)),\r
- ("none" , None)])\r
-\r
-instrumentImagePathList = ["piano", "guitare", "accordeon", "violon", "flute", "tuba", "orgue", "violoncelle", "celesta"]\r
-octaves = [0, -1, 0, 1, 1, -2, 0, -1, 0]\r
-\r
-defaultInstrumentChannel = 16\r
-defaultInstrumentNote = 60\r
-defaultCCHexCode = 0xB0+defaultInstrumentChannel - 1\r
-defaultNoteOnHexCode = 0x90+defaultInstrumentChannel - 1\r
-\r
-songScaleFactor = 0.99\r
-\r
-fileName = "../../../saves/22-01-2009-coll1-v65-"\r
-\r
-def noteNumberToName(noteNumber):\r
- names = ["Do","Do#","R\xe9","Mib","Mi","Fa","Fa#","Sol","Sol#","La","Sib","Si"]\r
- return(names[noteNumber%12])\r
-\r
-if __name__ == "__main__":\r
- key = "papanoel"\r
- if songDict[key] != None :\r
- songDict[key].save("../songs/smwis/"+str(key)+".smwi")\r
+++ /dev/null
-'''\r
-Created on 15 juil. 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-class Instrument:\r
- '''\r
- Object representing an instrument.\r
- \r
- notes:\r
- The MIDI numbers of the notes played by this instrument (usually a scale)\r
- channel:\r
- The channel corresponding to the instrument in the synthesizer\r
- image:\r
- The image for the instrument\r
- '''\r
-\r
- def __init__(self, notes, channel, image, octave = 0):\r
- '''\r
- Constructor\r
- \r
- notes:\r
- The MIDI numbers of the notes played by this instrument (usually a scale)\r
- channel:\r
- The channel corresponding to the instrument in the synthesizer\r
- image:\r
- The image for the instrument\r
- '''\r
- \r
- self.notes = [loop+12*octave for loop in notes]\r
- self.octave = octave\r
- self.channel = channel\r
- self.image = image\r
- \r
- def getNote(self,noteNumber):\r
- if noteNumber == None :\r
- return(None)\r
- else :\r
- return(self.notes[noteNumber])\r
- \r
- def getNoteByNoteNumber(self,baseMidiNoteNumber):\r
- if baseMidiNoteNumber == None:\r
- return(None)\r
- else :\r
- return(baseMidiNoteNumber+self.octave*12)
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 21 aout 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-import time\r
-\r
-class EventLog:\r
- '''\r
- classdocs\r
- '''\r
- \r
- def __init__(self,eventGroups = [], times = []):\r
- '''\r
- Constructor\r
- '''\r
- self.eventGroups = eventGroups\r
- self.times = times\r
- self.rate = 1\r
- self.yielder = self.eventGroupYielder()\r
- self.yieldPointer = 0\r
- \r
- self._timeCounter = 0\r
- \r
- def __getstate__(self):\r
- d = []\r
- d.append(self.eventGroups)\r
- d.append(self.times)\r
- return d\r
- \r
- def __setstate__(self,d):\r
- self.eventGroups = d[0]\r
- self.times = d[1]\r
- self.yielder = self.eventGroupYielder()\r
- \r
- self._timeCounter = 0\r
- \r
- def appendEventGroup(self, eventGroup):\r
- t = time.clock()*1000\r
- self.times.append(t)\r
- self.eventGroups.append(eventGroup)\r
- \r
- def update(self,timePassed):\r
- self._timeCounter += timePassed\r
- \r
- def setReplayRate(self,rate):\r
- self.rate = rate\r
- self.yielder = self.eventGroupYielder()\r
- \r
- def getPickledEvents(self):\r
- return(self.yielder.next())\r
- \r
- def getCurrentTime(self):\r
- return(self.times[self.yieldPointer])\r
- \r
- def eventGroupYielder(self):\r
- '''\r
- Will return the next event to post if enough time has passed and [] otherwise\r
- '''\r
- i = 0\r
- while i in range(len(self.eventGroups)):\r
- print "rate is " + str(self.rate)\r
- if self._timeCounter*self.rate>self.times[i]:\r
- print str(self._timeCounter*self.rate)+" > "+ str(self.times[i])\r
- self.yieldPointer = i\r
- yield self.eventGroups[i]\r
- i += 1\r
- else:\r
- yield []\r
+++ /dev/null
-'''\r
-Created on 28 aout 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-import os\r
-import sys\r
-import subprocess\r
-import re\r
-\r
-import pygame\r
-import pygame.midi\r
-import pickle\r
-\r
-from gui.constants import *\r
-\r
-from gui.PlayingScreen import PlayingScreen\r
-from gui.InstrumentChoice import InstrumentChoice\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from songs.Song import Song\r
-from gui.StaticFamiliarizer import StaticFamiliarizer\r
-from gui.SongFamiliarizer import SongFamiliarizer\r
-from gui.SongPlayingScreen import SongPlayingScreen\r
-from gui.DummyInstrumentChoice import DummyInstrumentChoice\r
-\r
-class FamiliarizerLog():\r
- '''\r
- classdocs\r
- '''\r
-\r
- def __init__(self,eventLog,level,activeWiimotes):\r
- '''\r
- Constructor\r
- '''\r
- self.eventLog = eventLog\r
- self.level = level\r
- self.activeWiimotes = activeWiimotes\r
- self.scale = scaleDict["majorScale"] \r
- \r
-if __name__ == '__main__':\r
- \r
- f = file('../../../saves/19-01-2009-testcoll1-v65-1.fmwi', 'r')\r
- unpickler = pickle.Unpickler(f)\r
- log = unpickler.load()\r
- f.close()\r
- \r
- pygame.init()\r
- modeResolution = (1024,768)\r
- window = pygame.display.set_mode(modeResolution,pygame.FULLSCREEN)\r
- pygame.midi.init()\r
- instruments = [Instrument(log.scale, i + 1, "".join(["../instruments/instrumentImages/", instrumentImagePathList[i], ".jpg"]), octaves[i]) for i in range(9)]\r
- \r
- joys = [[id,pygame.joystick.Joystick(id).get_name()] for id in range(pygame.joystick.get_count())]\r
- for joy in joys:\r
- if joy[1] in joyNames:\r
- pygame.joystick.Joystick(joy[0]).init() \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(portNames[0])\r
- print(portOffset)\r
- \r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages=[['../cursor/cursorImages/black/10.png'],['../cursor/cursorImages/red/10.png'],['../cursor/cursorImages/blue/10.png'],['../cursor/cursorImages/green/10.png']]\r
- durations = [75 for i in range(len(cursorImages))]\r
- \r
- extsc = True\r
- casc = False\r
- easyMode = True\r
- \r
- song = Song(scaleDict["majorScale"],[3,9,6,4,1,8,5,7,2,10],True)\r
-\r
- wiimoteCount = 4\r
- \r
- cursors = [WarpingCursor(None, cursorImages[i], durations, (300 * i, 300 * i),'../cursor/cursorImages/black/flash.png') for i in range(wiimoteCount)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, instruments[0], cursors[i]) for i in range(wiimoteCount)]\r
- dummyInstrumentChoice = DummyInstrumentChoice(wiimotes, window, screen, clock, joys, portOffset, log.activeWiimotes)\r
- if log.level < 2 :\r
- familiarize = StaticFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,log.activeWiimotes,level = log.level,eventLog = log.eventLog,replay = True)\r
- elif log.level == 2 :\r
- familiarize = SongFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,song,log.activeWiimotes,casc,extsc,easyMode,eventLog = log.eventLog,replay = True)\r
- else :\r
- familiarize = SongPlayingScreen(dummyInstrumentChoice,songDict["clairdelalune"],easyMode = True,eventLog = log.eventLog,replay = True)\r
- \r
- while familiarize.nextLevel != None :\r
- if familiarize.nextLevel < 2 :\r
- familiarize = StaticFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,log.activeWiimotes,level = familiarize.nextLevel,eventLog = familiarize.eventLog,replay = True)\r
- elif familiarize.nextLevel == 2 :\r
- familiarize = SongFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,song,log.activeWiimotes,casc,extsc,easyMode,eventLog = familiarize.eventLog,replay = True)\r
- else :\r
- familiarize = SongPlayingScreen(dummyInstrumentChoice,songDict["clairdelalune"],easyMode = True,eventLog = familiarize.eventLog,replay = True)\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port \r
- \r
- pygame.midi.quit()\r
- pygame.quit()
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 28 aout 2009\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-import os\r
-import sys\r
-import subprocess\r
-import re\r
-\r
-import pygame\r
-import pygame.midi\r
-import pickle\r
-\r
-from gui.constants import *\r
-\r
-from gui.PlayingScreen import PlayingScreen\r
-from gui.SongPlayingScreen import SongPlayingScreen\r
-from gui.InstrumentChoice import InstrumentChoice\r
-from instruments.Instrument import Instrument\r
-from cursor.WarpingCursor import *\r
-from controllers.Wiimote import Wiimote\r
-from songs.Song import Song\r
-\r
-\r
-class Log:\r
- '''\r
- classdocs\r
- '''\r
-\r
-\r
- def __init__(self,eventLog,scale,extendedScale,cascade,song,mode,activeWiimotes,easyMode = True):\r
- '''\r
- Constructor\r
- '''\r
- self.eventLog = eventLog\r
- self.scale = scale\r
- self.extendedScale = extendedScale\r
- self.cascade = cascade\r
- self.song = song\r
- self.activeWiimotes = activeWiimotes\r
- self.mode = mode \r
- \r
-if __name__ == '__main__':\r
- \r
- f = file('../../saves/4-12-2009-B1-v50-1.mwi', 'r')\r
- unpickler = pickle.Unpickler(f)\r
- log = unpickler.load()\r
- f.close()\r
- \r
- pygame.init()\r
- pygame.midi.init()\r
- instruments = [Instrument(scaleDict["majorScale"], i + 1, "".join(["../instruments/instrumentImages/", instrumentImagePathList[i], ".jpg"]), octaves[i]) for i in range(9)]\r
- \r
- joys = [[id,pygame.joystick.Joystick(id).get_name()] for id in range(pygame.joystick.get_count())]\r
- for joy in joys:\r
- if joy[1] in joyNames:\r
- pygame.joystick.Joystick(joy[0]).init() \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(portNames[0])\r
- print(portOffset)\r
- \r
- modeResolution = (1024,768)\r
- window = pygame.display.set_mode(modeResolution,pygame.FULLSCREEN)\r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages=[['../cursor/cursorImages/black/10.png'],['../cursor/cursorImages/red/10.png'],['../cursor/cursorImages/blue/10.png'],['../cursor/cursorImages/green/10.png']]\r
- durations = [75 for i in range(len(cursorImages[0]))]\r
- \r
- wiimoteCount = 4\r
- cursors = [WarpingCursor(None, cursorImages[i], durations, (300 * i, 300 * i),flashImage = '../cursor/cursorImages/black/flash.png' ) for i in range(wiimoteCount)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(wiimoteCount)]\r
- \r
- if log.song != None :\r
- \r
- if log.mode == 0 :\r
- log.extendedScale = log.song.requiresExtendedScale\r
- log.cascade = True\r
- log.easyMode = True\r
- elif log.mode == 1 :\r
- log.extendedScale = log.song.requiresExtendedScale\r
- log.cascade = True\r
- log.easyMode = True\r
- elif log.mode == 2:\r
- log.extendedScale = log.song.requiresExtendedScale\r
- log.cascade = False\r
- log.easyMode = True\r
- elif log.mode == 3:\r
- log.extendedScale = True\r
- log.cascade = False\r
- log.easyMode = False\r
- \r
- choice = InstrumentChoice(instruments, wiimotes, window, screen, clock, joys, portOffset,log.activeWiimotes, eventLog = log.eventLog,scaleFactor = songScaleFactor,replay = True)\r
- play = SongPlayingScreen(choice, log.song,log.cascade, log.extendedScale,log.easyMode)\r
- \r
- else:\r
- \r
- if log.mode == 0 :\r
- log.extendedScale = False\r
- log.cascade = False\r
- elif log.mode == 1 :\r
- log.extendedScale = True\r
- log.cascade = False\r
- elif log.mode == 2:\r
- log.extendedScale = False\r
- log.cascade = True\r
- elif log.mode == 3:\r
- log.extendedScale = True\r
- log.cascade = True\r
- \r
- choice = InstrumentChoice(instruments, wiimotes, window, screen, clock, joys, portOffset,log.activeWiimotes,eventLog = log.eventLog,replay = True)\r
- play = PlayingScreen(choice, None,log.cascade, log.extendedScale) \r
- \r
- while play.backToInstrumentChoice == True :\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port\r
- \r
- wiimotes = [Wiimote(i, i + portOffset, None, None, cursors[i]) for i in range(wiimoteCount)]\r
- previousEventLog = play.eventLog\r
-\r
- if log.song != None :\r
- choice = InstrumentChoice(instruments, wiimotes,window, screen, clock, joys, portOffset, log.activeWiimotes,eventLog = previousEventLog, replay = True, scaleFactor = songScaleFactor)\r
- play = SongPlayingScreen(choice, log.song, False, log.extendedScale,log.easyMode)\r
- else:\r
- choice = InstrumentChoice(instruments, wiimotes, log.window, screen, clock, joys, portOffset,log.activeWiimotes, eventLog = previousEventLog, replay = True)\r
- play = PlayingScreen(choice, None, log.cascade, log.extendedScale)\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port\r
- \r
- pygame.midi.quit()\r
- pygame.quit()
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 25 janv. 2010\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-from LogPGUPlayer import LogPGUPlayer\r
-\r
-class LogPGUAnalyzer(LogPGUPlayer):\r
- '''\r
- classdocs\r
- '''\r
-\r
-\r
- def __init__(self):\r
- '''\r
- Constructor\r
- '''\r
- \r
- self.firstStepDurations = []\r
- self.firstStepClicks = []\r
- self.firstStepClicksIn = []\r
- \r
- self.secondStepDurations = []\r
- self.secondStepClicks = []\r
- self.secondStepClicksIn = []\r
- \r
- self.thirdStepDurations = []\r
- self.thirdStepClicks = []\r
- self.thirdStepClicksIn = []\r
- \r
- self.songDurations = []\r
- self.songClicks = []\r
- self.songClicksIn = []\r
- self.songClicksPerMinute = []\r
- self.songClicksInPerMinute = []\r
- self.songTotalDurations = []\r
- \r
- self.meanTimeBetweenNotes = []\r
- \r
- LogPGUPlayer.__init__(self,20)\r
-
\ No newline at end of file
+++ /dev/null
-'''\r
-Created on 25 janv. 2010\r
-\r
-@author: Samuel Benveniste\r
-'''\r
-\r
-import pygame\r
-import pickle\r
-\r
-from pgu import gui as pguGui\r
-\r
-from gui import constants\r
-\r
-from instruments.Instrument import Instrument\r
-from songs.Song import Song\r
-from cursor.WarpingCursor import *\r
-from gui.StaticFamiliarizer import StaticFamiliarizer\r
-from gui.SongFamiliarizer import SongFamiliarizer\r
-from gui.SongPlayingScreen import SongPlayingScreen\r
-from gui.DummyInstrumentChoice import DummyInstrumentChoice\r
-from controllers.Wiimote import Wiimote\r
-\r
-class LogPGUPlayer(pguGui.Desktop):\r
- '''\r
- classdocs\r
- '''\r
-\r
-\r
- def __init__(self,rate):\r
- '''\r
- Constructor\r
- '''\r
- self.firstStepDurations = []\r
- self.firstStepClicks = []\r
- self.firstStepClicksIn = []\r
- \r
- self.secondStepDurations = []\r
- self.secondStepClicks = []\r
- self.secondStepClicksIn = []\r
- \r
- self.thirdStepDurations = []\r
- self.thirdStepClicks = []\r
- self.thirdStepClicksIn = []\r
- \r
- self.songDurations = []\r
- self.songClicks = []\r
- self.songClicksIn = []\r
- self.songClicksPerMinute = []\r
- self.songClicksInPerMinute = []\r
- self.songTotalDurations = []\r
- \r
- self.meanTimeBetweenNotes = []\r
- \r
- pguGui.Desktop.__init__(self)\r
- \r
- self.replayRate = rate\r
- #pguGui.theme.load('../data/themes/default')\r
- \r
- self.connect(pguGui.QUIT,self.quit,None)\r
- \r
- main = pguGui.Container(width=500, height=400) #, background=(220, 220, 220) )\r
- \r
- \r
- main.add(pguGui.Label("File Dialog Example", cls="h1"), 20, 20)\r
- \r
- \r
- td_style = {'padding_right': 10}\r
- t = pguGui.Table()\r
- t.tr()\r
- t.td( pguGui.Label('File Name:') , style=td_style )\r
- self.input_file = pguGui.Input()\r
- t.td( self.input_file, style=td_style )\r
- self.browseButton = pguGui.Button("Browse...")\r
- t.td( self.browseButton, style=td_style )\r
- self.browseButton.connect(pguGui.CLICK, self.open_file_browser, None)\r
- \r
- self.goButton = pguGui.Button("Go")\r
- \r
- self.goButton.connect(pguGui.CLICK, self.goButtonClicked,None)\r
- \r
- self.quitButton = pguGui.Button("Fin")\r
- self.quitButton.connect(pguGui.CLICK,self.quit,None)\r
- \r
- t.td( self.browseButton, style=td_style )\r
- t.td( self.goButton, style=td_style )\r
- t.td( self.quitButton, style=td_style )\r
- \r
- main.add(t, 20, 100)\r
- \r
- self.run(main)\r
- #import profile\r
- #profile.run('app.run(main)')\r
- \r
- def open_file_browser(self,data=None):\r
- d = pguGui.FileDialog(path = "../../../saves")\r
- d.connect(pguGui.CHANGE, self.handle_file_browser_closed, d)\r
- d.open()\r
- \r
- \r
- def handle_file_browser_closed(self,dlg):\r
- if dlg.value: self.input_file.value = dlg.value\r
- \r
- def goButtonClicked(self,data=None):\r
- if self.input_file.value.endswith(".fmwi"):\r
- f = file(self.input_file.value, 'r')\r
- unpickler = pickle.Unpickler(f)\r
- log = unpickler.load()\r
- f.close()\r
- \r
- log.eventLog.setReplayRate(self.replayRate)\r
- \r
- pygame.midi.init()\r
- instruments = [Instrument(log.scale, i + 1, "".join(["../instruments/instrumentImages/", constants.instrumentImagePathList[i], ".jpg"]), constants.octaves[i]) for i in range(9)]\r
- \r
- joys = [[id,pygame.joystick.Joystick(id).get_name()] for id in range(pygame.joystick.get_count())]\r
- for joy in joys:\r
- if joy[1] in constants.joyNames:\r
- pygame.joystick.Joystick(joy[0]).init() \r
- \r
- ports = [pygame.midi.get_device_info(id)[1] for id in range(pygame.midi.get_count())]\r
- portOffset = ports.index(constants.portNames[0])\r
- print(portOffset)\r
- \r
- screen = pygame.display.get_surface()\r
- clock = pygame.time.Clock() \r
- cursorImages=[['../cursor/cursorImages/black/10.png'],['../cursor/cursorImages/red/10.png'],['../cursor/cursorImages/blue/10.png'],['../cursor/cursorImages/green/10.png']]\r
- durations = [75 for i in range(len(cursorImages))]\r
- \r
- extsc = True\r
- casc = False\r
- easyMode = True\r
- \r
- song = Song(constants.scaleDict["majorScale"],[3,9,6,4,1,8,5,7,2,10],True)\r
- \r
- wiimoteCount = 4\r
- \r
- cursors = [WarpingCursor(None, cursorImages[i], durations, (300 * i, 300 * i),'../cursor/cursorImages/black/flash.png') for i in range(wiimoteCount)]\r
- wiimotes = [Wiimote(i, i + portOffset, None, instruments[0], cursors[i]) for i in range(wiimoteCount)]\r
- dummyInstrumentChoice = DummyInstrumentChoice(wiimotes, window, screen, clock, joys, portOffset, log.activeWiimotes)\r
- if log.level < 2 :\r
- familiarize = StaticFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,log.activeWiimotes,level = log.level,eventLog = log.eventLog,replay = True)\r
- self.fillStaticFamiliarizerStats(familiarize)\r
- elif log.level == 2 :\r
- familiarize = SongFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,song,log.activeWiimotes,casc,extsc,easyMode,eventLog = log.eventLog,replay = True)\r
- self.fillSongFamiliarizerStats(familiarize)\r
- else :\r
- familiarize = SongPlayingScreen(dummyInstrumentChoice,constants.songDict["clairdelalune"],easyMode = True,eventLog = log.eventLog,replay = True)\r
- self.fillSongStats(familiarize) \r
- \r
- while familiarize.nextLevel != None :\r
- if familiarize.nextLevel < 2 :\r
- familiarize = StaticFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,log.activeWiimotes,level = familiarize.nextLevel,eventLog = familiarize.eventLog,replay = True)\r
- self.fillStaticFamiliarizerStats(familiarize)\r
- elif familiarize.nextLevel == 2 :\r
- familiarize = SongFamiliarizer(wiimotes, window, screen, clock, joys, portOffset,song,log.activeWiimotes,casc,extsc,easyMode,eventLog = familiarize.eventLog,replay = True)\r
- self.fillSongFamiliarizerStats(familiarize)\r
- else :\r
- familiarize = SongPlayingScreen(dummyInstrumentChoice,constants.songDict["clairdelalune"],easyMode = True,eventLog = familiarize.eventLog,replay = True)\r
- self.fillSongStats(familiarize)\r
- \r
- for wiimote in wiimotes:\r
- del wiimote.port \r
- \r
- pygame.midi.quit()\r
- self.printStatsToFile()\r
- \r
- def fillStaticFamiliarizerStats(self,familiarizer):\r
- if familiarizer.level == 0 :\r
- self.firstStepClicks.append(familiarizer.clicks)\r
- self.firstStepClicksIn.append(familiarizer.clicksIn)\r
- self.firstStepDurations.append(familiarizer.duration)\r
- \r
- if familiarizer.level == 1 :\r
- self.secondStepClicks.append(familiarizer.clicks)\r
- self.secondStepClicksIn.append(familiarizer.clicksIn)\r
- self.secondStepDurations.append(familiarizer.duration)\r
- \r
- def fillSongFamiliarizerStats(self,familiarizer):\r
- self.thirdStepClicks.append(familiarizer.clicks)\r
- self.thirdStepClicksIn.append(familiarizer.clicksIn)\r
- self.thirdStepDurations.append(familiarizer.duration)\r
- \r
- def fillSongStats(self,familiarizer):\r
- self.songClicks.append(familiarizer.clicks)\r
- self.songClicksIn.append(familiarizer.clicksIn)\r
- self.songClicksPerMinute.append(familiarizer.clicksPerMinute)\r
- self.songClicksInPerMinute.append(familiarizer.clicksInPerMinute)\r
- self.songDurations.append(familiarizer.songDurations)\r
- self.songTotalDurations.append(familiarizer.totalDuration)\r
- \r
- def statsToFormattedString(self):\r
- return("First step durations :\n"+"\n"+\r
- str(self.firstStepDurations)+"\n"+"\n"+\r
- "First step clicks :\n"+"\n"+\r
- str(self.firstStepClicks)+"\n"+"\n"+\r
- "First step clicksIn :\n"+"\n"+\r
- str(self.firstStepClicksIn)+"\n"+"\n"+\r
- "Second step durations :\n"+"\n"+\r
- str(self.secondStepDurations)+"\n"+"\n"+\r
- "Second step clicks :\n"+"\n"+\r
- str(self.secondStepClicks)+"\n"+"\n"+\r
- "Second step clicksIn :\n"+"\n"+\r
- str(self.secondStepClicksIn)+"\n"+"\n"+\r
- "Third step durations :\n"+"\n"+\r
- str(self.thirdStepDurations)+"\n"+"\n"+\r
- "Third step clicks :\n"+"\n"+\r
- str(self.thirdStepClicks)+"\n"+"\n"+\r
- "Third step clicksIn :\n"+"\n"+\r
- str(self.thirdStepClicksIn)+"\n"+"\n"+\r
- "song durations :\n"+"\n"+\r
- str(self.songDurations)+"\n"+"\n"+\r
- "song clicks :\n"+"\n"+\r
- str(self.songClicks)+"\n"+"\n"+\r
- "song clicksIn :\n"+"\n"+\r
- str(self.songClicksIn)+"\n"+"\n"+\r
- "song clicks per minute:\n"+"\n"+\r
- str(self.songClicksPerMinute)+"\n"+"\n"+\r
- "song clicksIn per minute :\n"+"\n"+\r
- str(self.songClicksInPerMinute)+"\n"+"\n"+\r
- "song total durations :\n"+"\n"+\r
- str(self.songTotalDurations)+"\n"+"\n")\r
- \r
- def printStatsToFile(self,path=None):\r
- if path == None :\r
- path = self.input_file.value.replace(".fmwi",".txt")\r
- file = open(path,"w")\r
- file.write("Log ID : "+self.input_file.value+"\n"+"\n")\r
- file.write(self.statsToFormattedString())\r
- file.close()\r
- \r
-if __name__ == "__main__":\r
- pygame.init()\r
- modeResolution = (1024,768)\r
- window = pygame.display.set_mode(modeResolution,pygame.FULLSCREEN)\r
- logConfig = LogPGUPlayer(10000)\r
- pygame.quit()\r
-
\ No newline at end of file
+++ /dev/null
-import pygame\r
-import copy\r
-import pickle\r
-\r
-from pygame.event import Event\r
-\r
-class PickleableEvent(object):\r
- "A pygame.Event that can be serialized."\r
- \r
- def __init__(self,type,dict):\r
- self.__dict__ = copy.copy(dict)\r
- self.type = type\r
- self.event = Event(self.type,dict)\r
-\r
- def __getstate__(self):\r
- d = []\r
- d.append(self.type)\r
- d.append(copy.copy(self.event.dict))\r
- return d\r
-\r
- def __setstate__(self, d):\r
- self.__dict__ = copy.copy(d[1])\r
- self.type = d[0]\r
- self.event = Event(d[0],d[1])
\ No newline at end of file
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-from struct import pack, unpack\r
-\r
-"""\r
-This module contains functions for reading and writing the special data types\r
-that a midi file contains.\r
-"""\r
-\r
-"""\r
-nibbles are four bits. A byte consists of two nibles.\r
-hiBits==0xF0, loBits==0x0F Especially used for setting\r
-channel and event in 1. byte of musical midi events\r
-"""\r
-\r
-\r
-\r
-def getNibbles(byte):\r
- """\r
- Returns hi and lo bits in a byte as a tuple\r
- >>> getNibbles(142)\r
- (8, 14)\r
- \r
- Asserts byte value in byte range\r
- >>> getNibbles(256)\r
- Traceback (most recent call last):\r
- ...\r
- ValueError: Byte value out of range 0-255: 256\r
- """\r
- if not 0 <= byte <= 255:\r
- raise ValueError('Byte value out of range 0-255: %s' % byte)\r
- return (byte >> 4 & 0xF, byte & 0xF)\r
-\r
-\r
-def setNibbles(hiNibble, loNibble):\r
- """\r
- Returns byte with value set according to hi and lo bits\r
- Asserts hiNibble and loNibble in range(16)\r
- >>> setNibbles(8, 14)\r
- 142\r
- \r
- >>> setNibbles(8, 16)\r
- Traceback (most recent call last):\r
- ...\r
- ValueError: Nible value out of range 0-15: (8, 16)\r
- """\r
- if not (0 <= hiNibble <= 15) or not (0 <= loNibble <= 15):\r
- raise ValueError('Nible value out of range 0-15: (%s, %s)' % (hiNibble, loNibble))\r
- return (hiNibble << 4) + loNibble\r
-\r
-\r
-\r
-def readBew(value):\r
- """\r
- Reads string as big endian word, (asserts len(value) in [1,2,4])\r
- >>> readBew('aáâã')\r
- 1642193635L\r
- >>> readBew('aá')\r
- 25057\r
- """\r
- return unpack('>%s' % {1:'B', 2:'H', 4:'L'}[len(value)], value)[0]\r
-\r
-\r
-def writeBew(value, length):\r
- """\r
- Write int as big endian formatted string, (asserts length in [1,2,4])\r
- Difficult to print the result in doctest, so I do a simple roundabout test.\r
- >>> readBew(writeBew(25057, 2))\r
- 25057\r
- >>> readBew(writeBew(1642193635L, 4))\r
- 1642193635L\r
- """\r
- return pack('>%s' % {1:'B', 2:'H', 4:'L'}[length], value)\r
-\r
-\r
-\r
-"""\r
-Variable Length Data (varlen) is a data format sprayed liberally throughout\r
-a midi file. It can be anywhere from 1 to 4 bytes long.\r
-If the 8'th bit is set in a byte another byte follows. The value is stored\r
-in the lowest 7 bits of each byte. So max value is 4x7 bits = 28 bits.\r
-"""\r
-\r
-\r
-def readVar(value):\r
- """\r
- Converts varlength format to integer. Just pass it 0 or more chars that\r
- might be a varlen and it will only use the relevant chars.\r
- use varLen(readVar(value)) to see how many bytes the integer value takes.\r
- asserts len(value) >= 0\r
- >>> readVar('\80@')\r
- 64\r
- >>> readVar('áâãa')\r
- 205042145\r
- """\r
- sum = 0\r
- for byte in unpack('%sB' % len(value), value):\r
- sum = (sum << 7) + (byte & 0x7F)\r
- if not 0x80 & byte: break # stop after last byte\r
- return sum\r
-\r
-\r
-\r
-def varLen(value):\r
- """\r
- Returns the the number of bytes an integer will be when\r
- converted to varlength\r
- """\r
- if value <= 127:\r
- return 1\r
- elif value <= 16383:\r
- return 2\r
- elif value <= 2097151:\r
- return 3\r
- else:\r
- return 4\r
-\r
-\r
-def writeVar(value):\r
- "Converts an integer to varlength format"\r
- sevens = to_n_bits(value, varLen(value))\r
- for i in range(len(sevens)-1):\r
- sevens[i] = sevens[i] | 0x80\r
- return fromBytes(sevens)\r
-\r
-\r
-def to_n_bits(value, length=1, nbits=7):\r
- "returns the integer value as a sequence of nbits bytes"\r
- bytes = [(value >> (i*nbits)) & 0x7F for i in range(length)]\r
- bytes.reverse()\r
- return bytes\r
-\r
-\r
-def toBytes(value):\r
- "Turns a string into a list of byte values"\r
- return unpack('%sB' % len(value), value)\r
-\r
-\r
-def fromBytes(value):\r
- "Turns a list of bytes into a string"\r
- if not value:\r
- return ''\r
- return pack('%sB' % len(value), *value)\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
-# print to7bits(0, 3)\r
-# print to7bits(127, 3)\r
-# print to7bits(255, 3)\r
-# print to7bits(65536, 3)\r
-\r
- # simple test cases\r
- \r
-# print 'getHiLoHex', getNibbles(16)\r
-# print 'setHiLoHex', setNibbles(1,0)\r
-# \r
-# print 'readBew', readBew('aáâã')\r
-# print 'writeBew', writeBew(1642193635, 4)\r
-#\r
-# print 'varLen', varLen(1)\r
-#\r
- print 'readVar', readVar('\80@')\r
- print 'writeVar', writeVar(8192)\r
- \r
- print 'readVar', readVar('áâãa')\r
- print 'writeVar', writeVar(205058401)\r
-# \r
-# vartest = '\x82\xF7\x80\x00'\r
-# print 'toBytes', toBytes(vartest)\r
-# print 'fromBytes', fromBytes([48, 49, 50,])\r
- \r
- \r
-# instr = '\xFF\xFF\xFF\x00'\r
-# print 'readVar', readVar(instr)\r
-# inst2 = 268435455\r
-# print inst2\r
-# print writeVar(inst2)\r
-# print writeVar(readVar(instr))\r
-\r
- s1 = 0x00000000\r
- print '%08X -' % s1, '00', writeVar(s1)\r
- s2 = 0x00000040\r
- print '%08X -' % s2, '40', writeVar(s2)\r
- s3 = 0x0000007F\r
- print '%08X -' % s3, '7F', writeVar(s3)\r
- s4 = 0x00000080\r
- print '%08X -' % s4, '81 00', writeVar(s4)\r
- s5 = 0x00002000\r
- print '%08X -' % s5, 'C0 00', writeVar(s5)\r
- s6 = 0x00003FFF\r
- print '%08X -' % s6, 'FF 7F', writeVar(s6)\r
- s7 = 0x00004000\r
- print '%08X -' % s7, '81 80 00', writeVar(s7)\r
- s8 = 0x00100000\r
- print '%08X -' % s8, 'C0 80 00', writeVar(s8)\r
- s9 = 0x001FFFFF\r
- print '%08X -' % s9, 'FF FF 7F', writeVar(s9)\r
- s10 = 0x00200000\r
- print '%08X -' % s10, '81 80 80 00', writeVar(s10)\r
- s11 = 0x08000000\r
- print '%08X -' % s11, 'C0 80 80 00', writeVar(s11)\r
- s12 = 0x0FFFFFFF\r
- print '%08X -' % s12, 'FF FF FF 7F', writeVar(s12)\r
- \r
- \r
- \r
- \r
- \r
- \r
- \r
- \r
- \r
- \r
- \r
-
\ No newline at end of file
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-# std library\r
-from struct import unpack\r
-\r
-# custom\r
-from DataTypeConverters import readBew, readVar, varLen, toBytes\r
-\r
-# uhh I don't really like this, but there are so many constants to \r
-# import otherwise\r
-from constants import *\r
-\r
-\r
-class EventDispatcher:\r
-\r
-\r
- def __init__(self, outstream):\r
- \r
- """\r
- \r
- The event dispatcher generates events on the outstream.\r
- \r
- """\r
- \r
- # internal values, don't mess with 'em directly\r
- self.outstream = outstream\r
- \r
- # public flags\r
-\r
- # A note_on with a velocity of 0x00 is actually the same as a \r
- # note_off with a velocity of 0x40. When \r
- # "convert_zero_velocity" is set, the zero velocity note_on's \r
- # automatically gets converted into note_off's. This is a less \r
- # suprising behaviour for those that are not into the intimate \r
- # details of the midi spec.\r
- self.convert_zero_velocity = 1\r
- \r
- # If dispatch_continuos_controllers is true, continuos \r
- # controllers gets dispatched to their defined handlers. Else \r
- # they just trigger the "continuous_controller" event handler.\r
- self.dispatch_continuos_controllers = 1 # NOT IMPLEMENTED YET\r
- \r
- # If dispatch_meta_events is true, meta events get's dispatched \r
- # to their defined events. Else they all they trigger the \r
- # "meta_event" handler.\r
- self.dispatch_meta_events = 1\r
-\r
-\r
-\r
- def header(self, format, nTracks, division):\r
- "Triggers the header event"\r
- self.outstream.header(format, nTracks, division)\r
-\r
-\r
- def start_of_track(self, current_track):\r
- "Triggers the start of track event"\r
- \r
- # I do this twice so that users can overwrite the \r
- # start_of_track event handler without worrying whether the \r
- # track number is updated correctly.\r
- self.outstream.set_current_track(current_track)\r
- self.outstream.start_of_track(current_track)\r
- \r
- \r
- def sysex_event(self, data):\r
- "Dispatcher for sysex events"\r
- self.outstream.sysex_event(data)\r
- \r
- \r
- def eof(self):\r
- "End of file!"\r
- self.outstream.eof()\r
-\r
-\r
- def update_time(self, new_time=0, relative=1):\r
- "Updates relative/absolute time."\r
- self.outstream.update_time(new_time, relative)\r
- \r
- \r
- def reset_time(self):\r
- "Updates relative/absolute time."\r
- self.outstream.reset_time()\r
- \r
- \r
- # Event dispatchers for similar types of events\r
- \r
- \r
- def channel_messages(self, hi_nible, channel, data):\r
- \r
- "Dispatches channel messages"\r
- \r
- stream = self.outstream\r
- data = toBytes(data)\r
- \r
- if (NOTE_ON & 0xF0) == hi_nible:\r
- note, velocity = data\r
- # note_on with velocity 0x00 are same as note \r
- # off with velocity 0x40 according to spec!\r
- if velocity==0 and self.convert_zero_velocity:\r
- stream.note_off(channel, note, 0x40)\r
- else:\r
- stream.note_on(channel, note, velocity)\r
- \r
- elif (NOTE_OFF & 0xF0) == hi_nible:\r
- note, velocity = data\r
- stream.note_off(channel, note, velocity)\r
- \r
- elif (AFTERTOUCH & 0xF0) == hi_nible:\r
- note, velocity = data\r
- stream.aftertouch(channel, note, velocity)\r
- \r
- elif (CONTINUOUS_CONTROLLER & 0xF0) == hi_nible:\r
- controller, value = data\r
- # A lot of the cc's are defined, so we trigger those directly\r
- if self.dispatch_continuos_controllers:\r
- self.continuous_controllers(channel, controller, value)\r
- else:\r
- stream.continuous_controller(channel, controller, value)\r
- \r
- elif (PATCH_CHANGE & 0xF0) == hi_nible:\r
- program = data[0]\r
- stream.patch_change(channel, program)\r
- \r
- elif (CHANNEL_PRESSURE & 0xF0) == hi_nible:\r
- pressure = data[0]\r
- stream.channel_pressure(channel, pressure)\r
- \r
- elif (PITCH_BEND & 0xF0) == hi_nible:\r
- hibyte, lobyte = data\r
- value = (hibyte<<7) + lobyte\r
- stream.pitch_bend(channel, value)\r
-\r
- else:\r
-\r
- raise ValueError, 'Illegal channel message!'\r
-\r
-\r
-\r
- def continuous_controllers(self, channel, controller, value):\r
- \r
- "Dispatches channel messages"\r
-\r
- stream = self.outstream\r
- \r
- # I am not really shure if I ought to dispatch continuous controllers\r
- # There's so many of them that it can clutter up the OutStream \r
- # classes.\r
- \r
- # So I just trigger the default event handler\r
- stream.continuous_controller(channel, controller, value)\r
-\r
-\r
-\r
- def system_commons(self, common_type, common_data):\r
- \r
- "Dispatches system common messages"\r
- \r
- stream = self.outstream\r
- \r
- # MTC Midi time code Quarter value\r
- if common_type == MTC:\r
- data = readBew(common_data)\r
- msg_type = (data & 0x07) >> 4\r
- values = (data & 0x0F)\r
- stream.midi_time_code(msg_type, values)\r
- \r
- elif common_type == SONG_POSITION_POINTER:\r
- hibyte, lobyte = toBytes(common_data)\r
- value = (hibyte<<7) + lobyte\r
- stream.song_position_pointer(value)\r
-\r
- elif common_type == SONG_SELECT:\r
- data = readBew(common_data)\r
- stream.song_select(data)\r
-\r
- elif common_type == TUNING_REQUEST:\r
- # no data then\r
- stream.tuning_request(time=None)\r
-\r
-\r
-\r
- def meta_event(self, meta_type, data):\r
- \r
- "Dispatches meta events"\r
- \r
- stream = self.outstream\r
- \r
- # SEQUENCE_NUMBER = 0x00 (00 02 ss ss (seq-number))\r
- if meta_type == SEQUENCE_NUMBER:\r
- number = readBew(data)\r
- stream.sequence_number(number)\r
- \r
- # TEXT = 0x01 (01 len text...)\r
- elif meta_type == TEXT:\r
- stream.text(data)\r
- \r
- # COPYRIGHT = 0x02 (02 len text...)\r
- elif meta_type == COPYRIGHT:\r
- stream.copyright(data)\r
- \r
- # SEQUENCE_NAME = 0x03 (03 len text...)\r
- elif meta_type == SEQUENCE_NAME:\r
- stream.sequence_name(data)\r
- \r
- # INSTRUMENT_NAME = 0x04 (04 len text...)\r
- elif meta_type == INSTRUMENT_NAME:\r
- stream.instrument_name(data)\r
- \r
- # LYRIC = 0x05 (05 len text...)\r
- elif meta_type == LYRIC:\r
- stream.lyric(data)\r
- \r
- # MARKER = 0x06 (06 len text...)\r
- elif meta_type == MARKER:\r
- stream.marker(data)\r
- \r
- # CUEPOINT = 0x07 (07 len text...)\r
- elif meta_type == CUEPOINT:\r
- stream.cuepoint(data)\r
- \r
- # PROGRAM_NAME = 0x08 (05 len text...)\r
- elif meta_type == PROGRAM_NAME:\r
- stream.program_name(data)\r
- \r
- # DEVICE_NAME = 0x09 (09 len text...)\r
- elif meta_type == DEVICE_NAME:\r
- stream.device_name(data)\r
- \r
- # MIDI_CH_PREFIX = 0x20 (20 01 channel)\r
- elif meta_type == MIDI_CH_PREFIX:\r
- channel = readBew(data)\r
- stream.midi_ch_prefix(channel)\r
- \r
- # MIDI_PORT = 0x21 (21 01 port (legacy stuff))\r
- elif meta_type == MIDI_PORT:\r
- port = readBew(data)\r
- stream.midi_port(port)\r
- \r
- # END_OFF_TRACK = 0x2F (2F 00)\r
- elif meta_type == END_OF_TRACK:\r
- stream.end_of_track()\r
- \r
- # TEMPO = 0x51 (51 03 tt tt tt (tempo in us/quarternote))\r
- elif meta_type == TEMPO:\r
- b1, b2, b3 = toBytes(data)\r
- # uses 3 bytes to represent time between quarter \r
- # notes in microseconds\r
- stream.tempo((b1<<16) + (b2<<8) + b3)\r
- \r
- # SMTP_OFFSET = 0x54 (54 05 hh mm ss ff xx)\r
- elif meta_type == SMTP_OFFSET:\r
- hour, minute, second, frame, framePart = toBytes(data)\r
- stream.smtp_offset(\r
- hour, minute, second, frame, framePart)\r
- \r
- # TIME_SIGNATURE = 0x58 (58 04 nn dd cc bb)\r
- elif meta_type == TIME_SIGNATURE:\r
- nn, dd, cc, bb = toBytes(data)\r
- stream.time_signature(nn, dd, cc, bb)\r
- \r
- # KEY_SIGNATURE = 0x59 (59 02 sf mi)\r
- elif meta_type == KEY_SIGNATURE:\r
- sf, mi = toBytes(data)\r
- stream.key_signature(sf, mi)\r
- \r
- # SPECIFIC = 0x7F (Sequencer specific event)\r
- elif meta_type == SPECIFIC:\r
- meta_data = toBytes(data)\r
- stream.sequencer_specific(meta_data)\r
- \r
- # Handles any undefined meta events\r
- else: # undefined meta type\r
- meta_data = toBytes(data)\r
- stream.meta_event(meta_type, meta_data)\r
-\r
-\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
-\r
- from MidiToText import MidiToText\r
- \r
- outstream = MidiToText()\r
- dispatcher = EventDispatcher(outstream)\r
- dispatcher.channel_messages(NOTE_ON, 0x00, '\x40\x40')
\ No newline at end of file
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-# std library\r
-from struct import unpack\r
-\r
-# uhh I don't really like this, but there are so many constants to \r
-# import otherwise\r
-from constants import *\r
-\r
-from EventDispatcher import EventDispatcher\r
-\r
-class MidiFileParser:\r
-\r
- """\r
- \r
- The MidiFileParser is the lowest level parser that see the data as \r
- midi data. It generates events that gets triggered on the outstream.\r
- \r
- """\r
-\r
- def __init__(self, raw_in, outstream):\r
-\r
- """\r
- raw_data is the raw content of a midi file as a string.\r
- """\r
-\r
- # internal values, don't mess with 'em directly\r
- self.raw_in = raw_in\r
- self.dispatch = EventDispatcher(outstream)\r
-\r
- # Used to keep track of stuff\r
- self._running_status = None\r
-\r
-\r
-\r
-\r
- def parseMThdChunk(self):\r
- \r
- "Parses the header chunk"\r
- \r
- raw_in = self.raw_in\r
-\r
- header_chunk_type = raw_in.nextSlice(4)\r
- header_chunk_zise = raw_in.readBew(4)\r
-\r
- # check if it is a proper midi file\r
- if header_chunk_type != 'MThd':\r
- raise TypeError, "It is not a valid midi file!"\r
-\r
- # Header values are at fixed locations, so no reason to be clever\r
- self.format = raw_in.readBew(2)\r
- self.nTracks = raw_in.readBew(2)\r
- self.division = raw_in.readBew(2)\r
- \r
- # Theoretically a header larger than 6 bytes can exist\r
- # but no one has seen one in the wild\r
- # But correctly ignore unknown data if it is though\r
- if header_chunk_zise > 6:\r
- raw_in.moveCursor(header_chunk_zise-6)\r
-\r
- # call the header event handler on the stream\r
- self.dispatch.header(self.format, self.nTracks, self.division)\r
-\r
-\r
-\r
- def parseMTrkChunk(self):\r
- \r
- "Parses a track chunk. This is the most important part of the parser."\r
- \r
- # set time to 0 at start of a track\r
- self.dispatch.reset_time()\r
- \r
- dispatch = self.dispatch\r
- raw_in = self.raw_in\r
- \r
- # Trigger event at the start of a track\r
- dispatch.start_of_track(self._current_track)\r
- # position cursor after track header\r
- raw_in.moveCursor(4)\r
- # unsigned long is 4 bytes\r
- tracklength = raw_in.readBew(4)\r
- track_endposition = raw_in.getCursor() + tracklength # absolute position!\r
-\r
- while raw_in.getCursor() < track_endposition:\r
- \r
- # find relative time of the event\r
- time = raw_in.readVarLen()\r
- dispatch.update_time(time)\r
- \r
- # be aware of running status!!!!\r
- peak_ahead = raw_in.readBew(move_cursor=0)\r
- if (peak_ahead & 0x80): \r
- # the status byte has the high bit set, so it\r
- # was not running data but proper status byte\r
- status = self._running_status = raw_in.readBew()\r
- else:\r
- # use that darn running status\r
- status = self._running_status\r
- # could it be illegal data ?? Do we need to test for that?\r
- # I need more example midi files to be shure.\r
- \r
- # Also, while I am almost certain that no realtime \r
- # messages will pop up in a midi file, I might need to \r
- # change my mind later.\r
-\r
- # we need to look at nibbles here\r
- hi_nible, lo_nible = status & 0xF0, status & 0x0F\r
- \r
- # match up with events\r
-\r
- # Is it a meta_event ??\r
- # these only exists in midi files, not in transmitted midi data\r
- # In transmitted data META_EVENT (0xFF) is a system reset\r
- if status == META_EVENT:\r
- meta_type = raw_in.readBew()\r
- meta_length = raw_in.readVarLen()\r
- meta_data = raw_in.nextSlice(meta_length)\r
- dispatch.meta_event(meta_type, meta_data)\r
-\r
-\r
- # Is it a sysex_event ??\r
- elif status == SYSTEM_EXCLUSIVE:\r
- # ignore sysex events\r
- sysex_length = raw_in.readVarLen()\r
- # don't read sysex terminator\r
- sysex_data = raw_in.nextSlice(sysex_length-1)\r
- # only read last data byte if it is a sysex terminator\r
- # It should allways be there, but better safe than sorry\r
- if raw_in.readBew(move_cursor=0) == END_OFF_EXCLUSIVE:\r
- eo_sysex = raw_in.readBew()\r
- dispatch.sysex_event(sysex_data)\r
- # the sysex code has not been properly tested, and might be fishy!\r
-\r
-\r
- # is it a system common event?\r
- elif hi_nible == 0xF0: # Hi bits are set then\r
- data_sizes = {\r
- MTC:1,\r
- SONG_POSITION_POINTER:2,\r
- SONG_SELECT:1,\r
- }\r
- data_size = data_sizes.get(hi_nible, 0)\r
- common_data = raw_in.nextSlice(data_size)\r
- common_type = lo_nible\r
- dispatch.system_common(common_type, common_data)\r
- \r
-\r
- # Oh! Then it must be a midi event (channel voice message)\r
- else:\r
- data_sizes = {\r
- PATCH_CHANGE:1,\r
- CHANNEL_PRESSURE:1,\r
- NOTE_OFF:2,\r
- NOTE_ON:2,\r
- AFTERTOUCH:2,\r
- CONTINUOUS_CONTROLLER:2,\r
- PITCH_BEND:2,\r
- }\r
- data_size = data_sizes.get(hi_nible, 0)\r
- channel_data = raw_in.nextSlice(data_size)\r
- event_type, channel = hi_nible, lo_nible\r
- dispatch.channel_messages(event_type, channel, channel_data)\r
-\r
-\r
- def parseMTrkChunks(self):\r
- "Parses all track chunks."\r
- for t in range(self.nTracks):\r
- self._current_track = t\r
- self.parseMTrkChunk() # this is where it's at!\r
- self.dispatch.eof()\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- # get data\r
- test_file = 'test/midifiles/minimal.mid'\r
- test_file = 'test/midifiles/cubase-minimal.mid'\r
- test_file = 'test/midifiles/Lola.mid'\r
-# f = open(test_file, 'rb')\r
-# raw_data = f.read()\r
-# f.close()\r
-# \r
-# \r
-# # do parsing\r
- from MidiToText import MidiToText\r
- from RawInstreamFile import RawInstreamFile\r
-\r
- midi_in = MidiFileParser(RawInstreamFile(test_file), MidiToText())\r
- midi_in.parseMThdChunk()\r
- midi_in.parseMTrkChunks()\r
-
\ No newline at end of file
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-from RawInstreamFile import RawInstreamFile\r
-from MidiFileParser import MidiFileParser\r
-\r
-\r
-class MidiInFile:\r
-\r
- """\r
- \r
- Parses a midi file, and triggers the midi events on the outStream \r
- object.\r
- \r
- Get example data from a minimal midi file, generated with cubase.\r
- >>> test_file = 'C:/Documents and Settings/maxm/Desktop/temp/midi/src/midi/tests/midifiles/minimal-cubase-type0.mid'\r
- \r
- Do parsing, and generate events with MidiToText,\r
- so we can see what a minimal midi file contains\r
- >>> from MidiToText import MidiToText\r
- >>> midi_in = MidiInFile(MidiToText(), test_file)\r
- >>> midi_in.read()\r
- format: 0, nTracks: 1, division: 480\r
- ----------------------------------\r
- <BLANKLINE>\r
- Start - track #0\r
- sequence_name: Type 0\r
- tempo: 500000\r
- time_signature: 4 2 24 8\r
- note_on - ch:00, note:48, vel:64 time:0\r
- note_off - ch:00, note:48, vel:40 time:480\r
- End of track\r
- <BLANKLINE>\r
- End of file\r
- \r
- \r
- """\r
-\r
- def __init__(self, outStream, infile):\r
- # these could also have been mixins, would that be better? Nah!\r
- self.raw_in = RawInstreamFile(infile)\r
- self.parser = MidiFileParser(self.raw_in, outStream)\r
-\r
-\r
- def read(self):\r
- "Start parsing the file"\r
- p = self.parser\r
- p.parseMThdChunk()\r
- p.parseMTrkChunks()\r
-\r
-\r
- def setData(self, data=''):\r
- "Sets the data from a plain string"\r
- self.raw_in.setData(data)\r
- \r
- \r
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-from MidiOutStream import MidiOutStream\r
-\r
-class MidiInStream:\r
-\r
- """\r
- Takes midi events from the midi input and calls the apropriate\r
- method in the eventhandler object\r
- """\r
-\r
- def __init__(self, midiOutStream, device):\r
-\r
- """\r
-\r
- Sets a default output stream, and sets the device from where\r
- the input comes\r
-\r
- """\r
-\r
- if midiOutStream is None:\r
- self.midiOutStream = MidiOutStream()\r
- else:\r
- self.midiOutStream = midiOutStream\r
-\r
-\r
- def close(self):\r
-\r
- """\r
- Stop the MidiInstream\r
- """\r
-\r
-\r
- def read(self, time=0):\r
-\r
- """\r
-\r
- Start the MidiInstream.\r
-\r
- "time" sets timer to specific start value.\r
-\r
- """\r
-\r
-\r
- def resetTimer(self, time=0):\r
- """\r
-\r
- Resets the timer, probably a good idea if there is some kind\r
- of looping going on\r
-\r
- """\r
-\r
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-from MidiOutStream import MidiOutStream\r
-from RawOutstreamFile import RawOutstreamFile\r
-\r
-from constants import *\r
-from DataTypeConverters import fromBytes, writeVar\r
-\r
-class MidiOutFile(MidiOutStream):\r
-\r
-\r
- """\r
- MidiOutFile is an eventhandler that subclasses MidiOutStream.\r
- """\r
-\r
-\r
- def __init__(self, raw_out=''):\r
-\r
- self.raw_out = RawOutstreamFile(raw_out)\r
- MidiOutStream.__init__(self)\r
- \r
- \r
- def write(self):\r
- self.raw_out.write()\r
-\r
-\r
- def event_slice(self, slc):\r
- """\r
- Writes the slice of an event to the current track. Correctly \r
- inserting a varlen timestamp too.\r
- """\r
- trk = self._current_track_buffer\r
- trk.writeVarLen(self.rel_time())\r
- trk.writeSlice(slc)\r
- \r
- \r
- #####################\r
- ## Midi events\r
-\r
-\r
- def note_on(self, channel=0, note=0x40, velocity=0x40):\r
-\r
- """\r
- channel: 0-15\r
- note, velocity: 0-127\r
- """\r
- slc = fromBytes([NOTE_ON + channel, note, velocity])\r
- self.event_slice(slc)\r
-\r
-\r
- def note_off(self, channel=0, note=0x40, velocity=0x40):\r
-\r
- """\r
- channel: 0-15\r
- note, velocity: 0-127\r
- """\r
- slc = fromBytes([NOTE_OFF + channel, note, velocity])\r
- self.event_slice(slc)\r
-\r
-\r
- def aftertouch(self, channel=0, note=0x40, velocity=0x40):\r
-\r
- """\r
- channel: 0-15\r
- note, velocity: 0-127\r
- """\r
- slc = fromBytes([AFTERTOUCH + channel, note, velocity])\r
- self.event_slice(slc)\r
-\r
-\r
- def continuous_controller(self, channel, controller, value):\r
-\r
- """\r
- channel: 0-15\r
- controller, value: 0-127\r
- """\r
- slc = fromBytes([CONTINUOUS_CONTROLLER + channel, controller, value])\r
- self.event_slice(slc)\r
- # These should probably be implemented\r
- # http://users.argonet.co.uk/users/lenny/midi/tech/spec.html#ctrlnums\r
-\r
-\r
- def patch_change(self, channel, patch):\r
-\r
- """\r
- channel: 0-15\r
- patch: 0-127\r
- """\r
- slc = fromBytes([PATCH_CHANGE + channel, patch])\r
- self.event_slice(slc)\r
-\r
-\r
- def channel_pressure(self, channel, pressure):\r
-\r
- """\r
- channel: 0-15\r
- pressure: 0-127\r
- """\r
- slc = fromBytes([CHANNEL_PRESSURE + channel, pressure])\r
- self.event_slice(slc)\r
-\r
-\r
- def pitch_bend(self, channel, value):\r
-\r
- """\r
- channel: 0-15\r
- value: 0-16383\r
- """\r
- msb = (value>>7) & 0xFF\r
- lsb = value & 0xFF\r
- slc = fromBytes([PITCH_BEND + channel, msb, lsb])\r
- self.event_slice(slc)\r
-\r
-\r
-\r
-\r
- #####################\r
- ## System Exclusive\r
-\r
-# def sysex_slice(sysex_type, data):\r
-# ""\r
-# sysex_len = writeVar(len(data)+1)\r
-# self.event_slice(SYSTEM_EXCLUSIVE + sysex_len + data + END_OFF_EXCLUSIVE)\r
-#\r
- def system_exclusive(self, data):\r
-\r
- """\r
- data: list of values in range(128)\r
- """\r
- sysex_len = writeVar(len(data)+1)\r
- self.event_slice(chr(SYSTEM_EXCLUSIVE) + sysex_len + data + chr(END_OFF_EXCLUSIVE))\r
-\r
-\r
- #####################\r
- ## Common events\r
-\r
- def midi_time_code(self, msg_type, values):\r
- """\r
- msg_type: 0-7\r
- values: 0-15\r
- """\r
- value = (msg_type<<4) + values\r
- self.event_slice(fromBytes([MIDI_TIME_CODE, value]))\r
-\r
-\r
- def song_position_pointer(self, value):\r
-\r
- """\r
- value: 0-16383\r
- """\r
- lsb = (value & 0x7F)\r
- msb = (value >> 7) & 0x7F\r
- self.event_slice(fromBytes([SONG_POSITION_POINTER, lsb, msb]))\r
-\r
-\r
- def song_select(self, songNumber):\r
-\r
- """\r
- songNumber: 0-127\r
- """\r
- self.event_slice(fromBytes([SONG_SELECT, songNumber]))\r
-\r
-\r
- def tuning_request(self):\r
-\r
- """\r
- No values passed\r
- """\r
- self.event_slice(chr(TUNING_REQUEST))\r
-\r
- \r
- #########################\r
- # header does not really belong here. But anyhoo!!!\r
- \r
- def header(self, format=0, nTracks=1, division=96):\r
-\r
- """\r
- format: type of midi file in [0,1,2]\r
- nTracks: number of tracks. 1 track for type 0 file\r
- division: timing division ie. 96 ppq.\r
- \r
- """ \r
- raw = self.raw_out\r
- raw.writeSlice('MThd')\r
- bew = raw.writeBew\r
- bew(6, 4) # header size\r
- bew(format, 2)\r
- bew(nTracks, 2)\r
- bew(division, 2)\r
-\r
-\r
- def eof(self):\r
-\r
- """\r
- End of file. No more events to be processed.\r
- """\r
- # just write the file then.\r
- self.write()\r
-\r
-\r
- #####################\r
- ## meta events\r
-\r
-\r
- def meta_slice(self, meta_type, data_slice):\r
- "Writes a meta event"\r
- slc = fromBytes([META_EVENT, meta_type]) + \\r
- writeVar(len(data_slice)) + data_slice\r
- self.event_slice(slc)\r
-\r
-\r
- def meta_event(self, meta_type, data):\r
- """\r
- Handles any undefined meta events\r
- """\r
- self.meta_slice(meta_type, fromBytes(data))\r
-\r
-\r
- def start_of_track(self, n_track=0):\r
- """\r
- n_track: number of track\r
- """\r
- self._current_track_buffer = RawOutstreamFile()\r
- self.reset_time()\r
- self._current_track += 1\r
-\r
-\r
- def end_of_track(self):\r
- """\r
- Writes the track to the buffer.\r
- """\r
- raw = self.raw_out\r
- raw.writeSlice(TRACK_HEADER)\r
- track_data = self._current_track_buffer.getvalue()\r
- # wee need to know size of track data.\r
- eot_slice = writeVar(self.rel_time()) + fromBytes([META_EVENT, END_OF_TRACK, 0])\r
- raw.writeBew(len(track_data)+len(eot_slice), 4)\r
- # then write\r
- raw.writeSlice(track_data)\r
- raw.writeSlice(eot_slice)\r
- \r
-\r
-\r
- def sequence_number(self, value):\r
-\r
- """\r
- value: 0-65535\r
- """\r
- self.meta_slice(meta_type, writeBew(value, 2))\r
-\r
-\r
- def text(self, text):\r
- """\r
- Text event\r
- text: string\r
- """\r
- self.meta_slice(TEXT, text)\r
-\r
-\r
- def copyright(self, text):\r
-\r
- """\r
- Copyright notice\r
- text: string\r
- """\r
- self.meta_slice(COPYRIGHT, text)\r
-\r
-\r
- def sequence_name(self, text):\r
- """\r
- Sequence/track name\r
- text: string\r
- """\r
- self.meta_slice(SEQUENCE_NAME, text)\r
-\r
-\r
- def instrument_name(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- self.meta_slice(INSTRUMENT_NAME, text)\r
-\r
-\r
- def lyric(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- self.meta_slice(LYRIC, text)\r
-\r
-\r
- def marker(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- self.meta_slice(MARKER, text)\r
-\r
-\r
- def cuepoint(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- self.meta_slice(CUEPOINT, text)\r
-\r
-\r
- def midi_ch_prefix(self, channel):\r
-\r
- """\r
- channel: midi channel for subsequent data\r
- (deprecated in the spec)\r
- """\r
- self.meta_slice(MIDI_CH_PREFIX, chr(channel))\r
-\r
-\r
- def midi_port(self, value):\r
-\r
- """\r
- value: Midi port (deprecated in the spec)\r
- """\r
- self.meta_slice(MIDI_CH_PREFIX, chr(value))\r
-\r
-\r
- def tempo(self, value):\r
-\r
- """\r
- value: 0-2097151\r
- tempo in us/quarternote\r
- (to calculate value from bpm: int(60,000,000.00 / BPM))\r
- """\r
- hb, mb, lb = (value>>16 & 0xff), (value>>8 & 0xff), (value & 0xff)\r
- self.meta_slice(TEMPO, fromBytes([hb, mb, lb]))\r
-\r
-\r
- def smtp_offset(self, hour, minute, second, frame, framePart):\r
-\r
- """\r
- hour,\r
- minute,\r
- second: 3 bytes specifying the hour (0-23), minutes (0-59) and \r
- seconds (0-59), respectively. The hour should be \r
- encoded with the SMPTE format, just as it is in MIDI \r
- Time Code.\r
- frame: A byte specifying the number of frames per second (one \r
- of : 24, 25, 29, 30).\r
- framePart: A byte specifying the number of fractional frames, \r
- in 100ths of a frame (even in SMPTE-based tracks \r
- using a different frame subdivision, defined in the \r
- MThd chunk).\r
- """\r
- self.meta_slice(SMTP_OFFSET, fromBytes([hour, minute, second, frame, framePart]))\r
-\r
-\r
-\r
- def time_signature(self, nn, dd, cc, bb):\r
-\r
- """\r
- nn: Numerator of the signature as notated on sheet music\r
- dd: Denominator of the signature as notated on sheet music\r
- The denominator is a negative power of 2: 2 = quarter \r
- note, 3 = eighth, etc.\r
- cc: The number of MIDI clocks in a metronome click\r
- bb: The number of notated 32nd notes in a MIDI quarter note \r
- (24 MIDI clocks) \r
- """\r
- self.meta_slice(TIME_SIGNATURE, fromBytes([nn, dd, cc, bb]))\r
-\r
-\r
-\r
-\r
- def key_signature(self, sf, mi):\r
-\r
- """\r
- sf: is a byte specifying the number of flats (-ve) or sharps \r
- (+ve) that identifies the key signature (-7 = 7 flats, -1 \r
- = 1 flat, 0 = key of C, 1 = 1 sharp, etc).\r
- mi: is a byte specifying a major (0) or minor (1) key.\r
- """\r
- self.meta_slice(KEY_SIGNATURE, fromBytes([sf, mi]))\r
-\r
-\r
-\r
- def sequencer_specific(self, data):\r
-\r
- """\r
- data: The data as byte values\r
- """\r
- self.meta_slice(SEQUENCER_SPECIFIC, data)\r
-\r
-\r
-\r
-\r
-\r
-# #####################\r
-# ## realtime events\r
-\r
-# These are of no use in a midi file, so they are ignored!!!\r
-\r
-# def timing_clock(self):\r
-# def song_start(self):\r
-# def song_stop(self):\r
-# def song_continue(self):\r
-# def active_sensing(self):\r
-# def system_reset(self):\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- out_file = 'test/midifiles/midiout.mid'\r
- midi = MidiOutFile(out_file)\r
-\r
-#format: 0, nTracks: 1, division: 480\r
-#----------------------------------\r
-#\r
-#Start - track #0\r
-#sequence_name: Type 0\r
-#tempo: 500000\r
-#time_signature: 4 2 24 8\r
-#note_on - ch:00, note:48, vel:64 time:0\r
-#note_off - ch:00, note:48, vel:40 time:480\r
-#End of track\r
-#\r
-#End of file\r
-\r
-\r
- midi.header(0, 1, 480)\r
- \r
- midi.start_of_track()\r
- midi.sequence_name('Type 0')\r
- midi.tempo(750000)\r
- midi.time_signature(4, 2, 24, 8)\r
- ch = 0\r
- for i in range(127):\r
- midi.note_on(ch, i, 0x64)\r
- midi.update_time(96)\r
- midi.note_off(ch, i, 0x40)\r
- midi.update_time(0)\r
- \r
- midi.update_time(0)\r
- midi.end_of_track()\r
- \r
- midi.eof() # currently optional, should it do the write instead of write??\r
-\r
-\r
- midi.write()
\ No newline at end of file
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-class MidiOutStream:\r
-\r
-\r
- """\r
-\r
- MidiOutstream is Basically an eventhandler. It is the most central\r
- class in the Midi library. You use it both for writing events to\r
- an output stream, and as an event handler for an input stream.\r
-\r
- This makes it extremely easy to take input from one stream and\r
- send it to another. Ie. if you want to read a Midi file, do some\r
- processing, and send it to a midiport.\r
-\r
- All time values are in absolute values from the opening of a\r
- stream. To calculate time values, please use the MidiTime and\r
- MidiDeltaTime classes.\r
-\r
- """\r
-\r
- def __init__(self):\r
- \r
- # the time is rather global, so it needs to be stored \r
- # here. Otherwise there would be no really simple way to \r
- # calculate it. The alternative would be to have each event \r
- # handler do it. That sucks even worse!\r
- self._absolute_time = 0\r
- self._relative_time = 0\r
- self._current_track = 0\r
- self._running_status = None\r
-\r
- # time handling event handlers. They should be overwritten with care\r
-\r
- def update_time(self, new_time=0, relative=1):\r
- """\r
- Updates the time, if relative is true, new_time is relative, \r
- else it's absolute.\r
- """\r
- if relative:\r
- self._relative_time = new_time\r
- self._absolute_time += new_time\r
- else:\r
- self._relative_time = new_time - self._absolute_time\r
- self._absolute_time = new_time\r
-\r
- def reset_time(self):\r
- """\r
- reset time to 0\r
- """\r
- self._relative_time = 0\r
- self._absolute_time = 0\r
- \r
- def rel_time(self):\r
- "Returns the relative time"\r
- return self._relative_time\r
-\r
- def abs_time(self):\r
- "Returns the absolute time"\r
- return self._absolute_time\r
-\r
- # running status methods\r
- \r
- def reset_run_stat(self):\r
- "Invalidates the running status"\r
- self._running_status = None\r
-\r
- def set_run_stat(self, new_status):\r
- "Set the new running status"\r
- self._running_status = new_status\r
-\r
- def get_run_stat(self):\r
- "Set the new running status"\r
- return self._running_status\r
-\r
- # track handling event handlers\r
- \r
- def set_current_track(self, new_track):\r
- "Sets the current track number"\r
- self._current_track = new_track\r
- \r
- def get_current_track(self):\r
- "Returns the current track number"\r
- return self._current_track\r
- \r
- \r
- #####################\r
- ## Midi events\r
-\r
-\r
- def channel_message(self, message_type, channel, data):\r
- """The default event handler for channel messages"""\r
- pass\r
-\r
-\r
- def note_on(self, channel=0, note=0x40, velocity=0x40):\r
-\r
- """\r
- channel: 0-15\r
- note, velocity: 0-127\r
- """\r
- pass\r
-\r
-\r
- def note_off(self, channel=0, note=0x40, velocity=0x40):\r
-\r
- """\r
- channel: 0-15\r
- note, velocity: 0-127\r
- """\r
- pass\r
-\r
-\r
- def aftertouch(self, channel=0, note=0x40, velocity=0x40):\r
-\r
- """\r
- channel: 0-15\r
- note, velocity: 0-127\r
- """\r
- pass\r
-\r
-\r
- def continuous_controller(self, channel, controller, value):\r
-\r
- """\r
- channel: 0-15\r
- controller, value: 0-127\r
- """\r
- pass\r
-\r
-\r
- def patch_change(self, channel, patch):\r
-\r
- """\r
- channel: 0-15\r
- patch: 0-127\r
- """\r
- pass\r
-\r
-\r
- def channel_pressure(self, channel, pressure):\r
-\r
- """\r
- channel: 0-15\r
- pressure: 0-127\r
- """\r
- pass\r
-\r
-\r
- def pitch_bend(self, channel, value):\r
-\r
- """\r
- channel: 0-15\r
- value: 0-16383\r
-\r
- """\r
- pass\r
-\r
-\r
-\r
-\r
- #####################\r
- ## System Exclusive\r
-\r
- def system_exclusive(self, data):\r
-\r
- """\r
- data: list of values in range(128)\r
- """\r
- pass\r
-\r
-\r
- #####################\r
- ## Common events\r
-\r
- def song_position_pointer(self, value):\r
-\r
- """\r
- value: 0-16383\r
- """\r
- pass\r
-\r
-\r
- def song_select(self, songNumber):\r
-\r
- """\r
- songNumber: 0-127\r
- """\r
- pass\r
-\r
-\r
- def tuning_request(self):\r
-\r
- """\r
- No values passed\r
- """\r
- pass\r
-\r
- \r
- def midi_time_code(self, msg_type, values):\r
- """\r
- msg_type: 0-7\r
- values: 0-15\r
- """\r
- pass\r
-\r
-\r
- #########################\r
- # header does not really belong here. But anyhoo!!!\r
- \r
- def header(self, format=0, nTracks=1, division=96):\r
-\r
- """\r
- format: type of midi file in [1,2]\r
- nTracks: number of tracks\r
- division: timing division\r
- """\r
- pass\r
-\r
-\r
- def eof(self):\r
-\r
- """\r
- End of file. No more events to be processed.\r
- """\r
- pass\r
-\r
-\r
- #####################\r
- ## meta events\r
-\r
-\r
- def meta_event(self, meta_type, data):\r
- \r
- """\r
- Handles any undefined meta events\r
- """\r
- pass\r
-\r
-\r
- def start_of_track(self, n_track=0):\r
-\r
- """\r
- n_track: number of track\r
- """\r
- pass\r
-\r
-\r
- def end_of_track(self):\r
-\r
- """\r
- n_track: number of track\r
- """\r
- pass\r
-\r
-\r
- def sequence_number(self, value):\r
-\r
- """\r
- value: 0-16383\r
- """\r
- pass\r
-\r
-\r
- def text(self, text):\r
-\r
- """\r
- Text event\r
- text: string\r
- """\r
- pass\r
-\r
-\r
- def copyright(self, text):\r
-\r
- """\r
- Copyright notice\r
- text: string\r
- """\r
- pass\r
-\r
-\r
- def sequence_name(self, text):\r
-\r
- """\r
- Sequence/track name\r
- text: string\r
- """\r
- pass\r
-\r
-\r
- def instrument_name(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- pass\r
-\r
-\r
- def lyric(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- pass\r
-\r
-\r
- def marker(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- pass\r
-\r
-\r
- def cuepoint(self, text):\r
-\r
- """\r
- text: string\r
- """\r
- pass\r
-\r
-\r
- def midi_ch_prefix(self, channel):\r
-\r
- """\r
- channel: midi channel for subsequent data (deprecated in the spec)\r
- """\r
- pass\r
-\r
-\r
- def midi_port(self, value):\r
-\r
- """\r
- value: Midi port (deprecated in the spec)\r
- """\r
- pass\r
-\r
-\r
- def tempo(self, value):\r
-\r
- """\r
- value: 0-2097151\r
- tempo in us/quarternote\r
- (to calculate value from bpm: int(60,000,000.00 / BPM))\r
- """\r
- pass\r
-\r
-\r
- def smtp_offset(self, hour, minute, second, frame, framePart):\r
-\r
- """\r
- hour,\r
- minute,\r
- second: 3 bytes specifying the hour (0-23), minutes (0-59) and \r
- seconds (0-59), respectively. The hour should be \r
- encoded with the SMPTE format, just as it is in MIDI \r
- Time Code.\r
- frame: A byte specifying the number of frames per second (one \r
- of : 24, 25, 29, 30).\r
- framePart: A byte specifying the number of fractional frames, \r
- in 100ths of a frame (even in SMPTE-based tracks \r
- using a different frame subdivision, defined in the \r
- MThd chunk).\r
- """\r
- pass\r
-\r
-\r
-\r
- def time_signature(self, nn, dd, cc, bb):\r
-\r
- """\r
- nn: Numerator of the signature as notated on sheet music\r
- dd: Denominator of the signature as notated on sheet music\r
- The denominator is a negative power of 2: 2 = quarter \r
- note, 3 = eighth, etc.\r
- cc: The number of MIDI clocks in a metronome click\r
- bb: The number of notated 32nd notes in a MIDI quarter note \r
- (24 MIDI clocks) \r
- """\r
- pass\r
-\r
-\r
-\r
- def key_signature(self, sf, mi):\r
-\r
- """\r
- sf: is a byte specifying the number of flats (-ve) or sharps \r
- (+ve) that identifies the key signature (-7 = 7 flats, -1 \r
- = 1 flat, 0 = key of C, 1 = 1 sharp, etc).\r
- mi: is a byte specifying a major (0) or minor (1) key.\r
- """\r
- pass\r
-\r
-\r
-\r
- def sequencer_specific(self, data):\r
-\r
- """\r
- data: The data as byte values\r
- """\r
- pass\r
-\r
-\r
-\r
-\r
- #####################\r
- ## realtime events\r
-\r
- def timing_clock(self):\r
-\r
- """\r
- No values passed\r
- """\r
- pass\r
-\r
-\r
-\r
- def song_start(self):\r
-\r
- """\r
- No values passed\r
- """\r
- pass\r
-\r
-\r
-\r
- def song_stop(self):\r
-\r
- """\r
- No values passed\r
- """\r
- pass\r
-\r
-\r
-\r
- def song_continue(self):\r
-\r
- """\r
- No values passed\r
- """\r
- pass\r
-\r
-\r
-\r
- def active_sensing(self):\r
-\r
- """\r
- No values passed\r
- """\r
- pass\r
-\r
-\r
-\r
- def system_reset(self):\r
-\r
- """\r
- No values passed\r
- """\r
- pass\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- midiOut = MidiOutStream()\r
- midiOut.update_time(0,0)\r
- midiOut.note_on(0, 63, 127)\r
- midiOut.note_off(0, 63, 127)\r
-\r
-
\ No newline at end of file
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-from MidiOutStream import MidiOutStream\r
-class MidiToText(MidiOutStream):\r
-\r
-\r
- """\r
- This class renders a midi file as text. It is mostly used for debugging\r
- """\r
-\r
- #############################\r
- # channel events\r
- \r
- def channel_message(self, message_type, channel, data):\r
- """The default event handler for channel messages"""\r
- print 'message_type:%X, channel:%X, data size:%X' % (message_type, channel, len(data))\r
-\r
-\r
- def note_on(self, channel=0, note=0x40, velocity=0x40):\r
- print 'note_on - ch:%02X, note:%02X, vel:%02X time:%s' % (channel, note, velocity, self.timeInMs())\r
-\r
- def note_off(self, channel=0, note=0x40, velocity=0x40):\r
- print 'note_off - ch:%02X, note:%02X, vel:%02X time:%s' % (channel, note, velocity, self.abs_time())\r
-\r
- def aftertouch(self, channel=0, note=0x40, velocity=0x40):\r
- print 'aftertouch', channel, note, velocity\r
-\r
-\r
- def continuous_controller(self, channel, controller, value):\r
- print 'controller - ch: %02X, cont: #%02X, value: %02X' % (channel, controller, value)\r
-\r
-\r
- def patch_change(self, channel, patch):\r
- print 'patch_change - ch:%02X, patch:%02X' % (channel, patch)\r
-\r
-\r
- def channel_pressure(self, channel, pressure):\r
- print 'channel_pressure', channel, pressure\r
-\r
-\r
- def pitch_bend(self, channel, value):\r
- print 'pitch_bend ch:%s, value:%s' % (channel, value)\r
-\r
-\r
-\r
- #####################\r
- ## Common events\r
-\r
-\r
- def system_exclusive(self, data):\r
- print 'system_exclusive - data size: %s' % len(data)\r
-\r
-\r
- def song_position_pointer(self, value):\r
- print 'song_position_pointer: %s' % value\r
-\r
-\r
- def song_select(self, songNumber):\r
- print 'song_select: %s' % songNumber\r
-\r
-\r
- def tuning_request(self):\r
- print 'tuning_request'\r
-\r
-\r
- def midi_time_code(self, msg_type, values):\r
- print 'midi_time_code - msg_type: %s, values: %s' % (msg_type, values)\r
-\r
-\r
-\r
- #########################\r
- # header does not really belong here. But anyhoo!!!\r
-\r
- def header(self, format=0, nTracks=1, division=96):\r
- print 'format: %s, nTracks: %s, division: %s' % (format, nTracks, division)\r
- print '----------------------------------'\r
- print ''\r
- print division\r
- self.division = division\r
-\r
- def eof(self):\r
- print 'End of file'\r
-\r
-\r
- def start_of_track(self, n_track=0):\r
- print 'Start - track #%s' % n_track\r
-\r
-\r
- def end_of_track(self):\r
- print 'End of track'\r
- print ''\r
-\r
-\r
-\r
- ###############\r
- # sysex event\r
-\r
- def sysex_event(self, data):\r
- print 'sysex_event - datasize: %X' % len(data)\r
-\r
-\r
- #####################\r
- ## meta events\r
-\r
- def meta_event(self, meta_type, data):\r
- print 'undefined_meta_event:', meta_type, len(data)\r
-\r
-\r
- def sequence_number(self, value):\r
- print 'sequence_number', value\r
-\r
-\r
- def text(self, text):\r
- print 'text', text\r
-\r
-\r
- def copyright(self, text):\r
- print 'copyright', text\r
-\r
-\r
- def sequence_name(self, text):\r
- print 'sequence_name:', text\r
-\r
-\r
- def instrument_name(self, text):\r
- print 'instrument_name:', text\r
-\r
-\r
- def lyric(self, text):\r
- print 'lyric', text\r
-\r
-\r
- def marker(self, text):\r
- print 'marker', text\r
-\r
-\r
- def cuepoint(self, text):\r
- print 'cuepoint', text\r
-\r
-\r
- def midi_ch_prefix(self, channel):\r
- print 'midi_ch_prefix', channel\r
-\r
-\r
- def midi_port(self, value):\r
- print 'midi_port:', value\r
-\r
-\r
- def tempo(self, value):\r
- print 'tempo:', value\r
- self.tempo = value\r
-\r
-\r
- def smtp_offset(self, hour, minute, second, frame, framePart):\r
- print 'smtp_offset', hour, minute, second, frame, framePart\r
-\r
-\r
- def time_signature(self, nn, dd, cc, bb):\r
- print 'time_signature:', nn, dd, cc, bb\r
-\r
-\r
- def key_signature(self, sf, mi):\r
- print 'key_signature', sf, mi\r
-\r
-\r
- def sequencer_specific(self, data):\r
- print 'sequencer_specific', len(data)\r
- \r
- def timeInMs(self):\r
- return(long(self.abs_time())*1000000000/(long(self.tempo)*long(self.division)))\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- # get data\r
- test_file = '../songs/midis/test.mid'\r
- f = open(test_file, 'rb')\r
- \r
- # do parsing\r
- from MidiInFile import MidiInFile\r
- midiIn = MidiInFile(MidiToText(), f)\r
- midiIn.read()\r
- f.close()\r
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-# standard library imports\r
-from types import StringType\r
-from struct import unpack\r
-\r
-# custom import\r
-from DataTypeConverters import readBew, readVar, varLen\r
-\r
-\r
-class RawInstreamFile:\r
- \r
- """\r
- \r
- It parses and reads data from an input file. It takes care of big \r
- endianess, and keeps track of the cursor position. The midi parser \r
- only reads from this object. Never directly from the file.\r
- \r
- """\r
- \r
- def __init__(self, infile=''):\r
- """ \r
- If 'file' is a string we assume it is a path and read from \r
- that file.\r
- If it is a file descriptor we read from the file, but we don't \r
- close it.\r
- Midi files are usually pretty small, so it should be safe to \r
- copy them into memory.\r
- """\r
- if infile:\r
- if isinstance(infile, StringType):\r
- infile = open(infile, 'rb')\r
- self.data = infile.read()\r
- infile.close()\r
- else:\r
- # don't close the f\r
- self.data = infile.read()\r
- else:\r
- self.data = ''\r
- # start at beginning ;-)\r
- self.cursor = 0\r
-\r
-\r
- # setting up data manually\r
- \r
- def setData(self, data=''):\r
- "Sets the data from a string."\r
- self.data = data\r
- \r
- # cursor operations\r
-\r
- def setCursor(self, position=0):\r
- "Sets the absolute position if the cursor"\r
- self.cursor = position\r
-\r
-\r
- def getCursor(self):\r
- "Returns the value of the cursor"\r
- return self.cursor\r
- \r
- \r
- def moveCursor(self, relative_position=0):\r
- "Moves the cursor to a new relative position"\r
- self.cursor += relative_position\r
-\r
- # native data reading functions\r
- \r
- def nextSlice(self, length, move_cursor=1):\r
- "Reads the next text slice from the raw data, with length"\r
- c = self.cursor\r
- slc = self.data[c:c+length]\r
- if move_cursor:\r
- self.moveCursor(length)\r
- return slc\r
- \r
- \r
- def readBew(self, n_bytes=1, move_cursor=1):\r
- """\r
- Reads n bytes of date from the current cursor position.\r
- Moves cursor if move_cursor is true\r
- """\r
- return readBew(self.nextSlice(n_bytes, move_cursor))\r
-\r
-\r
- def readVarLen(self):\r
- """\r
- Reads a variable length value from the current cursor position.\r
- Moves cursor if move_cursor is true\r
- """\r
- MAX_VARLEN = 4 # Max value varlen can be\r
- var = readVar(self.nextSlice(MAX_VARLEN, 0))\r
- # only move cursor the actual bytes in varlen\r
- self.moveCursor(varLen(var))\r
- return var\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- test_file = 'test/midifiles/minimal.mid'\r
- fis = RawInstreamFile(test_file)\r
- print fis.nextSlice(len(fis.data))\r
-\r
- test_file = 'test/midifiles/cubase-minimal.mid'\r
- cubase_minimal = open(test_file, 'rb')\r
- fis2 = RawInstreamFile(cubase_minimal)\r
- print fis2.nextSlice(len(fis2.data))\r
- cubase_minimal.close()\r
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-# standard library imports\r
-import sys\r
-from types import StringType\r
-from struct import unpack\r
-from cStringIO import StringIO\r
-\r
-# custom import\r
-from DataTypeConverters import writeBew, writeVar, fromBytes\r
-\r
-class RawOutstreamFile:\r
- \r
- """\r
- \r
- Writes a midi file to disk.\r
- \r
- """\r
-\r
- def __init__(self, outfile=''):\r
- self.buffer = StringIO()\r
- self.outfile = outfile\r
-\r
-\r
- # native data reading functions\r
-\r
-\r
- def writeSlice(self, str_slice):\r
- "Writes the next text slice to the raw data"\r
- self.buffer.write(str_slice)\r
- \r
- \r
- def writeBew(self, value, length=1):\r
- "Writes a value to the file as big endian word"\r
- self.writeSlice(writeBew(value, length))\r
-\r
-\r
- def writeVarLen(self, value):\r
- "Writes a variable length word to the file"\r
- var = self.writeSlice(writeVar(value))\r
-\r
-\r
- def write(self):\r
- "Writes to disc"\r
- if self.outfile:\r
- if isinstance(self.outfile, StringType):\r
- outfile = open(self.outfile, 'wb')\r
- outfile.write(self.getvalue())\r
- outfile.close()\r
- else:\r
- self.outfile.write(self.getvalue())\r
- else:\r
- sys.stdout.write(self.getvalue())\r
- \r
- def getvalue(self):\r
- return self.buffer.getvalue()\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- out_file = 'test/midifiles/midiout.mid'\r
- out_file = ''\r
- rawOut = RawOutstreamFile(out_file)\r
- rawOut.writeSlice('MThd')\r
- rawOut.writeBew(6, 4)\r
- rawOut.writeBew(1, 2)\r
- rawOut.writeBew(2, 2)\r
- rawOut.writeBew(15360, 2)\r
- rawOut.write()\r
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-#import MidiOutStream\r
-#import MidiInStream\r
-#import MidiInFile\r
-#import MidiToText
\ No newline at end of file
+++ /dev/null
-------------------------------------------------------------------------\r
-r409 | maxm | 2006-01-05 16:37:29 +0100 (to, 05 jan 2006) | 1 line\r
-\r
-Made RawOutstreamFile.py write to std out if no outfile is given.\r
-------------------------------------------------------------------------\r
-r403 | maxm | 2006-01-05 13:34:11 +0100 (to, 05 jan 2006) | 1 line\r
-\r
-\r
-------------------------------------------------------------------------\r
-r402 | maxm | 2006-01-05 13:33:56 +0100 (to, 05 jan 2006) | 1 line\r
-\r
-- Fixed minor bugs, added coding headers\r
-------------------------------------------------------------------------\r
-r401 | maxm | 2006-01-01 23:09:17 +0100 (s_, 01 jan 2006) | 1 line\r
-\r
-Fixed sysex dispathcer bug.\r
-------------------------------------------------------------------------\r
-r268 | maxm | 2005-02-04 12:26:59 +0100 (fr, 04 feb 2005) | 1 line\r
-\r
-\r
-------------------------------------------------------------------------\r
-r128 | maxm | 2004-12-18 14:05:27 +0100 (l_, 18 dec 2004) | 1 line\r
-\r
-Fixed bug when using relative time\r
-------------------------------------------------------------------------\r
-r15 | maxm | 2004-03-09 15:01:41 +0100 (ti, 09 mar 2004) | 1 line\r
-\r
-made a copy to meta folder\r
-------------------------------------------------------------------------\r
-r13 | maxm | 2004-03-09 09:17:23 +0100 (ti, 09 mar 2004) | 1 line\r
-\r
-Deleted .pyc files\r
-------------------------------------------------------------------------\r
-r12 | maxm | 2004-03-09 09:15:54 +0100 (ti, 09 mar 2004) | 1 line\r
-\r
-Removed file/folder\r
-------------------------------------------------------------------------\r
-r3 | maxm | 2004-03-08 23:16:25 +0100 (ma, 08 mar 2004) | 1 line\r
-\r
-Adde midi\r
-------------------------------------------------------------------------\r
-r1 | maxm | 2004-03-08 22:49:23 +0100 (ma, 08 mar 2004) | 1 line\r
-\r
-Initial Import\r
-------------------------------------------------------------------------\r
+++ /dev/null
-# -*- coding: ISO-8859-1 -*-\r
-\r
-###################################################\r
-## Definitions of the different midi events\r
-\r
-\r
-\r
-###################################################\r
-## Midi channel events (The most usual events)\r
-## also called "Channel Voice Messages"\r
-\r
-NOTE_OFF = 0x80\r
-# 1000cccc 0nnnnnnn 0vvvvvvv (channel, note, velocity)\r
-\r
-NOTE_ON = 0x90\r
-# 1001cccc 0nnnnnnn 0vvvvvvv (channel, note, velocity)\r
-\r
-AFTERTOUCH = 0xA0\r
-# 1010cccc 0nnnnnnn 0vvvvvvv (channel, note, velocity)\r
-\r
-CONTINUOUS_CONTROLLER = 0xB0 # see Channel Mode Messages!!!\r
-# 1011cccc 0ccccccc 0vvvvvvv (channel, controller, value)\r
-\r
-PATCH_CHANGE = 0xC0\r
-# 1100cccc 0ppppppp (channel, program)\r
-\r
-CHANNEL_PRESSURE = 0xD0\r
-# 1101cccc 0ppppppp (channel, pressure)\r
-\r
-PITCH_BEND = 0xE0\r
-# 1110cccc 0vvvvvvv 0wwwwwww (channel, value-lo, value-hi)\r
-\r
-\r
-###################################################\r
-## Channel Mode Messages (Continuous Controller)\r
-## They share a status byte.\r
-## The controller makes the difference here\r
-\r
-# High resolution continuous controllers (MSB)\r
-\r
-BANK_SELECT = 0x00\r
-MODULATION_WHEEL = 0x01\r
-BREATH_CONTROLLER = 0x02\r
-FOOT_CONTROLLER = 0x04\r
-PORTAMENTO_TIME = 0x05\r
-DATA_ENTRY = 0x06\r
-CHANNEL_VOLUME = 0x07\r
-BALANCE = 0x08\r
-PAN = 0x0A\r
-EXPRESSION_CONTROLLER = 0x0B\r
-EFFECT_CONTROL_1 = 0x0C\r
-EFFECT_CONTROL_2 = 0x0D\r
-GEN_PURPOSE_CONTROLLER_1 = 0x10\r
-GEN_PURPOSE_CONTROLLER_2 = 0x11\r
-GEN_PURPOSE_CONTROLLER_3 = 0x12\r
-GEN_PURPOSE_CONTROLLER_4 = 0x13\r
-\r
-# High resolution continuous controllers (LSB)\r
-\r
-BANK_SELECT = 0x20\r
-MODULATION_WHEEL = 0x21\r
-BREATH_CONTROLLER = 0x22\r
-FOOT_CONTROLLER = 0x24\r
-PORTAMENTO_TIME = 0x25\r
-DATA_ENTRY = 0x26\r
-CHANNEL_VOLUME = 0x27\r
-BALANCE = 0x28\r
-PAN = 0x2A\r
-EXPRESSION_CONTROLLER = 0x2B\r
-EFFECT_CONTROL_1 = 0x2C\r
-EFFECT_CONTROL_2 = 0x2D\r
-GENERAL_PURPOSE_CONTROLLER_1 = 0x30\r
-GENERAL_PURPOSE_CONTROLLER_2 = 0x31\r
-GENERAL_PURPOSE_CONTROLLER_3 = 0x32\r
-GENERAL_PURPOSE_CONTROLLER_4 = 0x33\r
-\r
-# Switches\r
-\r
-SUSTAIN_ONOFF = 0x40\r
-PORTAMENTO_ONOFF = 0x41\r
-SOSTENUTO_ONOFF = 0x42\r
-SOFT_PEDAL_ONOFF = 0x43\r
-LEGATO_ONOFF = 0x44\r
-HOLD_2_ONOFF = 0x45\r
-\r
-# Low resolution continuous controllers\r
-\r
-SOUND_CONTROLLER_1 = 0x46 # (TG: Sound Variation; FX: Exciter On/Off)\r
-SOUND_CONTROLLER_2 = 0x47 # (TG: Harmonic Content; FX: Compressor On/Off)\r
-SOUND_CONTROLLER_3 = 0x48 # (TG: Release Time; FX: Distortion On/Off)\r
-SOUND_CONTROLLER_4 = 0x49 # (TG: Attack Time; FX: EQ On/Off)\r
-SOUND_CONTROLLER_5 = 0x4A # (TG: Brightness; FX: Expander On/Off)75 SOUND_CONTROLLER_6 (TG: Undefined; FX: Reverb OnOff)\r
-SOUND_CONTROLLER_7 = 0x4C # (TG: Undefined; FX: Delay OnOff)\r
-SOUND_CONTROLLER_8 = 0x4D # (TG: Undefined; FX: Pitch Transpose OnOff)\r
-SOUND_CONTROLLER_9 = 0x4E # (TG: Undefined; FX: Flange/Chorus OnOff)\r
-SOUND_CONTROLLER_10 = 0x4F # (TG: Undefined; FX: Special Effects OnOff)\r
-GENERAL_PURPOSE_CONTROLLER_5 = 0x50\r
-GENERAL_PURPOSE_CONTROLLER_6 = 0x51\r
-GENERAL_PURPOSE_CONTROLLER_7 = 0x52\r
-GENERAL_PURPOSE_CONTROLLER_8 = 0x53\r
-PORTAMENTO_CONTROL = 0x54 # (PTC) (0vvvvvvv is the source Note number) (Detail)\r
-EFFECTS_1 = 0x5B # (Ext. Effects Depth)\r
-EFFECTS_2 = 0x5C # (Tremelo Depth)\r
-EFFECTS_3 = 0x5D # (Chorus Depth)\r
-EFFECTS_4 = 0x5E # (Celeste Depth)\r
-EFFECTS_5 = 0x5F # (Phaser Depth)\r
-DATA_INCREMENT = 0x60 # (0vvvvvvv is n/a; use 0)\r
-DATA_DECREMENT = 0x61 # (0vvvvvvv is n/a; use 0)\r
-NON_REGISTERED_PARAMETER_NUMBER = 0x62 # (LSB)\r
-NON_REGISTERED_PARAMETER_NUMBER = 0x63 # (MSB)\r
-REGISTERED_PARAMETER_NUMBER = 0x64 # (LSB)\r
-REGISTERED_PARAMETER_NUMBER = 0x65 # (MSB)\r
-\r
-# Channel Mode messages - (Detail)\r
-\r
-ALL_SOUND_OFF = 0x78\r
-RESET_ALL_CONTROLLERS = 0x79\r
-LOCAL_CONTROL_ONOFF = 0x7A\r
-ALL_NOTES_OFF = 0x7B\r
-OMNI_MODE_OFF = 0x7C # (also causes ANO)\r
-OMNI_MODE_ON = 0x7D # (also causes ANO)\r
-MONO_MODE_ON = 0x7E # (Poly Off; also causes ANO)\r
-POLY_MODE_ON = 0x7F # (Mono Off; also causes ANO)\r
-\r
-\r
-\r
-###################################################\r
-## System Common Messages, for all channels\r
-\r
-SYSTEM_EXCLUSIVE = 0xF0\r
-# 11110000 0iiiiiii 0ddddddd ... 11110111\r
-\r
-MTC = 0xF1 # MIDI Time Code Quarter Frame\r
-# 11110001\r
-\r
-SONG_POSITION_POINTER = 0xF2\r
-# 11110010 0vvvvvvv 0wwwwwww (lo-position, hi-position)\r
-\r
-SONG_SELECT = 0xF3\r
-# 11110011 0sssssss (songnumber)\r
-\r
-#UNDEFINED = 0xF4\r
-## 11110100\r
-\r
-#UNDEFINED = 0xF5\r
-## 11110101\r
-\r
-TUNING_REQUEST = 0xF6\r
-# 11110110\r
-\r
-END_OFF_EXCLUSIVE = 0xF7 # terminator\r
-# 11110111 # End of system exclusive\r
-\r
-\r
-###################################################\r
-## Midifile meta-events\r
-\r
-SEQUENCE_NUMBER = 0x00 # 00 02 ss ss (seq-number)\r
-TEXT = 0x01 # 01 len text...\r
-COPYRIGHT = 0x02 # 02 len text...\r
-SEQUENCE_NAME = 0x03 # 03 len text...\r
-INSTRUMENT_NAME = 0x04 # 04 len text...\r
-LYRIC = 0x05 # 05 len text...\r
-MARKER = 0x06 # 06 len text...\r
-CUEPOINT = 0x07 # 07 len text...\r
-PROGRAM_NAME = 0x08 # 08 len text...\r
-DEVICE_NAME = 0x09 # 09 len text...\r
-\r
-MIDI_CH_PREFIX = 0x20 # MIDI channel prefix assignment (unofficial)\r
-\r
-MIDI_PORT = 0x21 # 21 01 port, legacy stuff but still used\r
-END_OF_TRACK = 0x2F # 2f 00\r
-TEMPO = 0x51 # 51 03 tt tt tt (tempo in us/quarternote)\r
-SMTP_OFFSET = 0x54 # 54 05 hh mm ss ff xx\r
-TIME_SIGNATURE = 0x58 # 58 04 nn dd cc bb\r
-KEY_SIGNATURE = 0x59 # ??? len text...\r
-SPECIFIC = 0x7F # Sequencer specific event\r
-\r
-FILE_HEADER = 'MThd'\r
-TRACK_HEADER = 'MTrk'\r
-\r
-###################################################\r
-## System Realtime messages\r
-## I don't supose these are to be found in midi files?!\r
-\r
-TIMING_CLOCK = 0xF8\r
-# undefined = 0xF9\r
-SONG_START = 0xFA\r
-SONG_CONTINUE = 0xFB\r
-SONG_STOP = 0xFC\r
-# undefined = 0xFD\r
-ACTIVE_SENSING = 0xFE\r
-SYSTEM_RESET = 0xFF\r
-\r
-\r
-###################################################\r
-## META EVENT, it is used only in midi files.\r
-## In transmitted data it means system reset!!!\r
-\r
-META_EVENT = 0xFF\r
-# 11111111\r
-\r
-\r
-###################################################\r
-## Helper functions\r
-\r
-def is_status(byte):\r
- return (byte & 0x80) == 0x80 # 1000 0000\r
-\r
-\r
+++ /dev/null
-from MidiOutFile import MidiOutFile\r
-\r
-"""\r
-This is an example of the smallest possible type 0 midi file, where \r
-all the midi events are in the same track.\r
-"""\r
-\r
-out_file = 'midiout/minimal_type0.mid'\r
-midi = MidiOutFile(out_file)\r
-\r
-# non optional midi framework\r
-midi.header()\r
-midi.start_of_track() \r
-\r
-\r
-# musical events\r
-\r
-midi.update_time(0)\r
-midi.note_on(channel=0, note=0x40)\r
-\r
-midi.update_time(192)\r
-midi.note_off(channel=0, note=0x40)\r
-\r
-\r
-# non optional midi framework\r
-midi.update_time(0)\r
-midi.end_of_track()\r
-\r
-midi.eof()\r
+++ /dev/null
-from MidiOutStream import MidiOutStream\r
-from MidiInFile import MidiInFile\r
-\r
-"""\r
-This prints all note on events on midi channel 0\r
-"""\r
-\r
-\r
-class Transposer(MidiOutStream):\r
- \r
- "Transposes all notes by 1 octave"\r
- \r
- def note_on(self, channel=0, note=0x40, velocity=0x40):\r
- if channel == 0:\r
- print channel, note, velocity, self.rel_time()\r
-\r
-\r
-event_handler = Transposer()\r
-\r
-in_file = 'midiout/minimal_type0.mid'\r
-midi_in = MidiInFile(event_handler, in_file)\r
-midi_in.read()\r
-\r
+++ /dev/null
-from MidiToText import MidiToText\r
-\r
-"""\r
-This is an example that uses the MidiToText eventhandler. When an \r
-event is triggered on it, it prints the event to the console.\r
-"""\r
-\r
-midi = MidiToText()\r
-\r
-# non optional midi framework\r
-midi.header()\r
-midi.start_of_track() \r
-\r
-\r
-# musical events\r
-\r
-midi.update_time(0)\r
-midi.note_on(channel=0, note=0x40)\r
-\r
-midi.update_time(192)\r
-midi.note_off(channel=0, note=0x40)\r
-\r
-\r
-# non optional midi framework\r
-midi.update_time(0)\r
-midi.end_of_track() # not optional!\r
-\r
-midi.eof()\r
+++ /dev/null
-"""\r
-This is an example that uses the MidiToText eventhandler. When an \r
-event is triggered on it, it prints the event to the console.\r
-\r
-It gets the events from the MidiInFile.\r
-\r
-So it prints all the events from the infile to the console. great for \r
-debugging :-s\r
-"""\r
-\r
-\r
-# get data\r
-test_file = 'test/midifiles/minimal-cubase-type0.mid'\r
-\r
-# do parsing\r
-from MidiInFile import MidiInFile\r
-from MidiToText import MidiToText # the event handler\r
-midiIn = MidiInFile(MidiToText(), test_file)\r
-midiIn.read()\r
+++ /dev/null
-from MidiOutFile import MidiOutFile\r
-from MidiInFile import MidiInFile\r
-\r
-"""\r
-This is an example of the smallest possible type 0 midi file, where \r
-all the midi events are in the same track.\r
-"""\r
-\r
-\r
-class Transposer(MidiOutFile):\r
- \r
- "Transposes all notes by 1 octave"\r
- \r
- def _transp(self, ch, note):\r
- if ch != 9: # not the drums!\r
- note += 12\r
- if note > 127:\r
- note = 127\r
- return note\r
-\r
-\r
- def note_on(self, channel=0, note=0x40, velocity=0x40):\r
- note = self._transp(channel, note)\r
- MidiOutFile.note_on(self, channel, note, velocity)\r
- \r
- \r
- def note_off(self, channel=0, note=0x40, velocity=0x40):\r
- note = self._transp(channel, note)\r
- MidiOutFile.note_off(self, channel, note, velocity)\r
-\r
-\r
-out_file = 'midiout/transposed.mid'\r
-midi_out = Transposer(out_file)\r
-\r
-#in_file = 'midiout/minimal_type0.mid'\r
-#in_file = 'test/midifiles/Lola.mid'\r
-in_file = 'test/midifiles/tennessee_waltz.mid'\r
-midi_in = MidiInFile(midi_out, in_file)\r
-midi_in.read()\r
-\r
+++ /dev/null
-class EventDispatcherBase:\r
-\r
-\r
- def __init__(self, outstream):\r
- """\r
- The event dispatcher generates events on the outstream. This \r
- is the base implementation. It is more like an interface for \r
- how the EventDispatcher. It has the methods that are used by \r
- the Midi Parser.\r
- """\r
- # internal values, don't mess with 'em directly\r
- self.outstream = outstream\r
-\r
-\r
- def eof(self):\r
- "End of file!"\r
- self.outstream.eof()\r
-\r
-\r
- def update_time(self, new_time=0, relative=1):\r
- "Updates relative/absolute time."\r
- self.outstream.update_time(new_time, relative)\r
-\r
- # 'official' midi events\r
-\r
- def header(self, format, nTracks, division):\r
- "Triggers the header event"\r
- self.outstream.header(format, nTracks, division)\r
-\r
-\r
- def start_of_track(self, current_track):\r
- "Triggers the start of track event"\r
- \r
- # I do this twice so that users can overwrite the \r
- # start_of_track event handler without worrying whether the \r
- # track number is updated correctly.\r
- self.outstream.set_current_track(current_track)\r
- self.outstream.start_of_track(current_track)\r
-\r
- # Event dispatchers for midi events\r
-\r
- def channel_messages(self, hi_nible, channel, data):\r
- "Dispatches channel messages"\r
- self.outstream.channel_message(hi_nible, channel, data)\r
-\r
-\r
- def continuous_controllers(self, channel, controller, value):\r
- "Dispatches channel messages"\r
- self.outstream.continuous_controller(channel, controller, value)\r
- \r
- \r
- def system_commons(self, common_type, common_data):\r
- "Dispatches system common messages"\r
- self.outstream.system_common(common_type, common_data)\r
-\r
-\r
- def meta_event(self, meta_type, data):\r
- "Dispatches meta events"\r
- self.outstream.meta_event(meta_type, data)\r
-\r
-\r
- def sysex_events(self, data):\r
- "Dispatcher for sysex events"\r
- self.outstream.sysex_event(data)\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
-\r
- from MidiToText import MidiToText\r
- from constants import NOTE_ON\r
- \r
- outstream = MidiToText()\r
- dispatcher = EventDispatcherBase(outstream)\r
- dispatcher.channel_messages(NOTE_ON, 0x00, '\x40\x40')
\ No newline at end of file
+++ /dev/null
-from MidiOutStream import MidiOutStream\r
-\r
-class MidiOutPassThrough(MidiOutStream):\r
-\r
-\r
- """\r
-\r
- This class i mainly used for testing the event dispatcher. The \r
- methods just returns the passed parameters as a tupple.\r
-\r
- """\r
-\r
-\r
- #####################\r
- ## Midi channel events\r
-\r
-\r
- def note_on(self, channel, note, velocity, time=None):\r
- return channel, note, velocity, time\r
-\r
-\r
- def note_off(self, channel, note, velocity, time=None):\r
- return channel, note, velocity, time\r
-\r
-\r
- def aftertouch(self, channel, note, velocity, time=None):\r
- return channel, note, velocity, time\r
-\r
- \r
- def continuous_controller(self, channel, controller, value, time=None):\r
- return channel, controller, value, time\r
-\r
-\r
- def patch_change(self, channel, patch, time=None):\r
- return channel, patch, time\r
-\r
-\r
- def channel_pressure(self, channel, pressure, time=None):\r
- return channel, pressure, time\r
-\r
-\r
- #####################\r
- ## defined continuous controller events\r
- \r
-# def cc_\r
-\r
- #####################\r
- ## Common events\r
-\r
- def system_exclusive(self, data, time=None):\r
- return data, time\r
-\r
-\r
- def song_position_pointer(self, hiPos, loPos, time=None):\r
- return hiPos, loPos, time\r
-\r
-\r
- def song_select(self, songNumber, time=None):\r
- return songNumber, time\r
-\r
-\r
- def tuning_request(self, time=None):\r
- return time\r
-\r
-\r
-\r
- #########################\r
- # header does not really belong here. But anyhoo!!!\r
- \r
- def header(self, format, nTracks, division):\r
- return format, nTracks, division\r
-\r
-\r
- def eof(self):\r
- return 'eof'\r
-\r
-\r
- #####################\r
- ## meta events\r
-\r
- def start_of_track(self, n_track=0):\r
- return n_track\r
-\r
-\r
- def end_of_track(self, n_track=0, time=None):\r
- return n_track, time\r
-\r
-\r
- def sequence_number(self, hiVal, loVal, time=None):\r
- return hiVal, loVal, time\r
-\r
-\r
- def text(self, text, time=None):\r
- return text, time\r
-\r
-\r
- def copyright(self, text, time=None):\r
- return text, time\r
-\r
-\r
- def sequence_name(self, text, time=None):\r
- return text, time\r
-\r
-\r
- def instrument_name(self, text, time=None):\r
- return text, time\r
-\r
-\r
- def lyric(self, text, time=None):\r
- return text, time\r
-\r
-\r
- def marker(self, text, time=None):\r
- return text, time\r
-\r
-\r
- def cuepoint(self, text, time=None):\r
- return text, time\r
-\r
-\r
- def midi_port(self, value, time=None):\r
- return value, time\r
-\r
-\r
- def tempo(self, value, time=None):\r
- return value, time\r
-\r
- def smtp_offset(self, hour, minute, second, frame, framePart, time=None):\r
- return hour, minute, second, frame, framePart, time\r
-\r
-\r
- def time_signature(self, nn, dd, cc, bb, time=None):\r
- return nn, dd, cc, bb, time\r
-\r
-\r
- def key_signature(self, sf, mi, time=None):\r
- return sf, mi, time\r
-\r
-\r
- def sequencer_specific(self, data, time=None):\r
- return data, time\r
-\r
-\r
-\r
-\r
- #####################\r
- ## realtime events\r
-\r
- def timing_clock(self, time=None):\r
- return time\r
-\r
-\r
- def song_start(self, time=None):\r
- return time\r
-\r
-\r
- def song_stop(self, time=None):\r
- return time\r
-\r
-\r
- def song_continue(self, time=None):\r
- return time\r
-\r
-\r
- def active_sensing(self, time=None):\r
- return time\r
-\r
-\r
- def system_reset(self, time=None):\r
- return time\r
-\r
-\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- midiOut = MidiOutStream()\r
- midiOut.note_on(0, 63, 127, 0)\r
- midiOut.note_off(0, 63, 127, 384)\r
-\r
-
\ No newline at end of file
+++ /dev/null
-class MidiOutStreamBase:\r
-\r
-\r
- """\r
-\r
- MidiOutStreamBase is Basically an eventhandler. It is the most central\r
- class in the Midi library. You use it both for writing events to\r
- an output stream, and as an event handler for an input stream.\r
-\r
- This makes it extremely easy to take input from one stream and\r
- send it to another. Ie. if you want to read a Midi file, do some\r
- processing, and send it to a midiport.\r
-\r
- All time values are in absolute values from the opening of a\r
- stream. To calculate time values, please use the MidiTime and\r
- MidiDeltaTime classes.\r
-\r
- """\r
-\r
- def __init__(self):\r
- \r
- # the time is rather global, so it needs to be stored \r
- # here. Otherwise there would be no really simple way to \r
- # calculate it. The alternative would be to have each event \r
- # handler do it. That sucks even worse!\r
- self._absolute_time = 0\r
- self._relative_time = 0\r
- self._current_track = 0\r
-\r
- # time handling event handlers. They should overwritten with care\r
-\r
- def update_time(self, new_time=0, relative=1):\r
- """\r
- Updates the time, if relative is true, new_time is relative, \r
- else it's absolute.\r
- """\r
- if relative:\r
- self._relative_time = new_time\r
- self._absolute_time += new_time\r
- else:\r
- self._absolute_time = new_time\r
- self._relative_time = new_time - self._absolute_time\r
-\r
- def rel_time(self):\r
- "Returns the relative time"\r
- return self._relative_time\r
-\r
- def abs_time(self):\r
- "Returns the absolute time"\r
- return self._absolute_time\r
-\r
- # track handling event handlers\r
- \r
- def set_current_track(self, new_track):\r
- "Sets the current track number"\r
- self._current_track = new_track\r
- \r
- def get_current_track(self):\r
- "Returns the current track number"\r
- return self._current_track\r
- \r
- \r
- #####################\r
- ## Midi events\r
-\r
-\r
- def channel_message(self, message_type, channel, data):\r
- """The default event handler for channel messages"""\r
- pass\r
-\r
-\r
- #####################\r
- ## Common events\r
-\r
- def system_exclusive(self, data):\r
-\r
- """The default event handler for system_exclusive messages"""\r
- pass\r
-\r
-\r
- def system_common(self, common_type, common_data):\r
-\r
- """The default event handler for system common messages"""\r
- pass\r
-\r
-\r
- #########################\r
- # header does not really belong here. But anyhoo!!!\r
- \r
- def header(self, format, nTracks, division):\r
-\r
- """\r
- format: type of midi file in [1,2]\r
- nTracks: number of tracks\r
- division: timing division\r
- """\r
- pass\r
-\r
-\r
- def start_of_track(self, n_track=0):\r
-\r
- """\r
- n_track: number of track\r
- """\r
- pass\r
-\r
-\r
- def eof(self):\r
-\r
- """\r
- End of file. No more events to be processed.\r
- """\r
- pass\r
-\r
-\r
- #####################\r
- ## meta events\r
-\r
-\r
- def meta_event(self, meta_type, data, time):\r
- \r
- """The default event handler for meta_events"""\r
- pass\r
-\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
-\r
- midiOut = MidiOutStreamBase()\r
- midiOut.update_time(0,0)\r
- midiOut.note_on(0, 63, 127)\r
- midiOut.note_off(0, 63, 127)\r
-\r
-
\ No newline at end of file
+++ /dev/null
-Stuff that I am just playing around with
\ No newline at end of file
+++ /dev/null
-This is the documentation for the midi package\r
-==============================================\r
-\r
-\r
-The modules follows the following naming convention:\r
-\r
-\r
-MidiIn<StreamType>.py\r
----------------------\r
-\r
-The MidiIn modules reads midi content for a specific type of stream. Ie. a file or a midi port. It then generates events and triggers them on a MidiOutStream.\r
-\r
-\r
-MidiOut<StreamType>.py\r
-----------------------\r
-\r
-The MidiOut modules are event handlers, that reacts to events generated by a a Midi in module.\r
-\r
-\r
-MidiInBase.py\r
----------------\r
-\r
-The base class for input streams.\r
-\r
-\r
-MidiOutBase.py\r
-----------------\r
-\r
-The base class for the output streams.\r
-\r
-\r
-\r
-\r
-\r
-\r
-Internal modules\r
-================\r
-\r
-\r
-DataTypeConverters.py\r
----------------------\r
-\r
-A collection of functions that converts the special data types used in midi files to and from strings.\r
-\r
-\r
-constants.py\r
-------------\r
-\r
-A collection of constants from the midi spec.\r
-\r
+++ /dev/null
-MThd | Format=1 | # of Tracks=2 | Division=15360\r
-\r
-\r
-\r
-\r
-Track #0 ******************************************\r
- Time Event\r
- \r
- 1: 1: 0 |Time Sig | 4/4 | MIDI-clocks\click=24 | 32nds\quarter=8\r
- |Tempo | BPM=120 | micros\quarter=500000\r
- 101: 1: 0 |End of track| \r
-\r
-\r
-\r
-\r
-\r
-Track #1 ******************************************\r
- Time Event\r
- \r
- 1: 1: 0 |Track Name | len=7 |\r
- 0x53 0x79 0x6E 0x74 0x68 0x20 0x31 <Synth 1>\r
- |Instrument | len=7 |\r
- 0x53 0x79 0x6E 0x74 0x68 0x20 0x31 <Synth 1>\r
- |On Note | chan= 1 | pitch=C 1 | vol=127\r
- 2: 1: 0 |Off Note | chan= 1 | pitch=c 1 | vol=0\r
- 101: 1: 0 |End of track| \r
+++ /dev/null
-4D 54 68 64 MThd\r
-00 00 00 06 len: 6\r
-00 01 Type: 1\r
-00 02 tracks: 2\r
-3C 00 tempo: 15360\r
-\r
-\r
-\r
-4D 54 72 6B MTrk\r
-00 00 00 16 len: 22\r
-\r
-00 time\r
- FF 58 04 Time Signature\r
- 04 02 18 08 4/4 24 8\r
- \r
-00 time\r
- FF 51 03 TEMPO:\r
- 07 A1 20 500.000 mySec\r
-\r
-82 F7 80 00 time ## oh bugger, it's buggy.\r
- FF 2F 00 End Of Track\r
- \r
-\r
-\r
-4D 54 72 6B MTrk\r
-00 00 00 2C len: 44\r
-\r
-00 time\r
- FF 03 Sequence/Track Name\r
- 07 len: 7\r
- 53 79 6E 74\r
- 68 20 31 'Synth 1'\r
-\r
-00 time\r
- FF 04 Instrument\r
- 07 len: 7\r
- 53 79 6E 74\r
- 68 20 31 'Synth 1'\r
-\r
-00 time\r
- FF 21 01 Midi port\r
- 04 Port #5\r
-\r
-00 time\r
- 90 24 7F Note ON\r
- 83 E0 00 Note OFF\r
- \r
-00 time\r
- 80 24 00 Note OFF\r
-\r
-00 82 F3 A0 \r
-\r
-00\r
- FF 2F 00 End Of Track
\ No newline at end of file
+++ /dev/null
-These files are used for testing the midi package\r
-=================================================\r
-\r
-minimal.mid\r
------------\r
-\r
-A minimal working midifile. Plays a one bar "middle C" at 120 bpm. The absolute simplest file I could get to play in midi devices.
\ No newline at end of file
+++ /dev/null
-Embarrasingly empty.\r
-\r
-Why don't you write some tests?
\ No newline at end of file
+++ /dev/null
-0.1.4
\ No newline at end of file
+++ /dev/null
-"""Phil's pyGame Utilities
-
-
-"""
-__version__ = '0.12.3'
-
-# vim: set filetype=python sts=4 sw=4 noet si :
+++ /dev/null
-"""Some handy algorithms for use in games, etc.
-
-<p>please note that this file is alpha, and is subject to modification in
-future versions of pgu!</p>
-"""
-
-# The manhattan distance metric
-def manhattan_dist(a,b):
- return abs(a[0]-b[0]) + abs(a[1]-b[1])
-
-class node:
- def __init__(self, prev, pos, dest, dist):
- self.prev,self.pos,self.dest = prev,pos,dest
- if self.prev == None: self.g = 0
- else: self.g = self.prev.g + 1
- self.h = dist(pos,dest)
- self.f = self.g+self.h
-
-
-def astar(start,end,layer,dist=manhattan_dist):
- """uses the a* algorithm to find a path
-
- <pre>astar(start,end,layer,dist): return [list of positions]</pre>
-
- <dl>
- <dt>start<dd>start position
- <dt>end<dd>end position
- <dt>layer<dd>a grid where zero cells are open and non-zero cells are walls
- <dt>dist<dd>a distance function dist(a,b) - manhattan distance is used by default
- </dl>
-
- <p>returns a list of positions from start to end</p>
- """
-
- w,h = len(layer[0]),len(layer)
- if start[0] < 0 or start[1] < 0 or start[0] >= w or start[1] >= h:
- return [] #start outside of layer
- if end[0] < 0 or end[1] < 0 or end[0] >= w or end[1] >= h:
- return [] #end outside of layer
-
- if layer[start[1]][start[0]]:
- return [] #start is blocked
- if layer[end[1]][end[0]]:
- return [] #end is blocked
-
- opens = []
- open = {}
- closed = {}
- cur = node(None, start, end, dist)
- open[cur.pos] = cur
- opens.append(cur)
- while len(open):
- cur = opens.pop(0)
- if cur.pos not in open: continue
- del open[cur.pos]
- closed[cur.pos] = cur
- if cur.pos == end: break
- for dx,dy in [(0,-1),(1,0),(0,1),(-1,0)]:#(-1,-1),(1,-1),(-1,1),(1,1)]:
- pos = cur.pos[0]+dx,cur.pos[1]+dy
- # Check if the point lies in the grid
- if (pos[0] < 0 or pos[1] < 0 or
- pos[0] >= w or pos[1] >= h or
- layer[pos[0]][pos[1]]):
- continue
- #check for blocks of diagonals
- if layer[cur.pos[1]+dy][cur.pos[0]]: continue
- if layer[cur.pos[1]][cur.pos[0]+dx]: continue
- new = node(cur, pos, end, dist)
- if pos in open and new.f >= open[pos].f: continue
- if pos in closed and new.f >= closed[pos].f: continue
- if pos in open: del open[pos]
- if pos in closed: del closed[pos]
- open[pos] = new
- lo = 0
- hi = len(opens)
- while lo < hi:
- mid = (lo+hi)/2
- if new.f < opens[mid].f: hi = mid
- else: lo = mid + 1
- opens.insert(lo,new)
-
- if cur.pos != end:
- return []
-
- path = []
- while cur.prev != None:
- path.append(cur.pos)
- cur = cur.prev
- path.reverse()
- return path
-
-
-def getline(a,b):
- """returns a path of points from a to b
-
- <pre>getline(a,b): return [list of points]</pre>
-
- <dl>
- <dt>a<dd>starting point
- <dt>b<dd>ending point
- </dl>
-
- <p>returns a list of points from a to b</p>
- """
-
- path = []
-
- x1,y1 = a
- x2,y2 = b
- dx,dy = abs(x2-x1),abs(y2-y1)
-
- if x2 >= x1: xi1,xi2 = 1,1
- else: xi1,xi2 = -1,-1
-
- if y2 >= y1: yi1,yi2 = 1,1
- else: yi1,yi2 = -1,-1
-
- if dx >= dy:
- xi1,yi2 = 0,0
- d = dx
- n = dx/2
- a = dy
- p = dx
- else:
- xi2,yi1 = 0,0
- d = dy
- n = dy/2
- a = dx
- p = dy
-
- x,y = x1,y1
- c = 0
- while c <= p:
- path.append((x,y))
- n += a
- if n > d:
- n -= d
- x += xi1
- y += yi1
- x += xi2
- y += yi2
- c += 1
- return path
+++ /dev/null
-"""animation loading and manipulating functions.
-
-<p>please note that this file is alpha, and is subject to modification in
-future versions of pgu!</p>
-"""
-
-print 'pgu.ani','This module is alpha, and is subject to change.'
-
-import math
-import pygame
-
-def _ani_load(tv,name,parts,frames,shape):
- l = len(frames)
- #print name,parts,l
- n = parts.pop()
- if len(parts):
- s = l/n
- for i in xrange(0,n):
- _ani_load(tv,name + ".%d"%i,parts[:],frames[s*i:s*(i+1)],shape)
- return
-
- for i in xrange(0,n):
- tv.images[name+".%d"%i] = frames[i],shape
-
-def ani_load(tv,name,img,size,shape,parts):
- """load an animation from an image
-
- <pre>ani_load(tv,name,image,size,shape,parts)</pre>
-
- <dl>
- <dt>tv<dd>vid to load into
- <dt>name <dd>prefix name to give the images
- <dt>image <dd>image to load anis from
- <dt>size <dd>w,h size of image
- <dt>shape <dd>shape of image (usually a subset of 0,0,w,h) used for collision detection
- <dt>parts <dd>list of parts to divide the animation into
- <br>for example parts = [4,5] would yield 4 animations 5 frames long, 20 total
- <br>for example parts = [a,b,c] would yield ... images['name.a.b.c'] ..., a*b*c total
- </dl>
-
- """
- parts = parts[:]
- parts.reverse()
- w,h = size
- frames = []
- for y in xrange(0,img.get_height(),h):
- for x in xrange(0,img.get_width(),w):
- frames.append(img.subsurface(x,y,w,h))
- _ani_load(tv,name,parts,frames,shape)
-
-
-def image_rotate(tv,name,img,shape,angles,diff=0):
- """rotate an image and put it into tv.images
-
- <pre>image_rotate(tv,name,image,shape,angles,diff=0)</pre>
-
- <dl>
- <dt>tv <dd>vid to load into
- <dt>name <dd>prefix name to give the images
- <dt>image <dd>image to load anis from
- <dt>shape <dd>shape fimage (usually a subset of 0,0,w,h) used for collision detection
- <dt>angles <dd>a list of angles to render in degrees
- <dt>diff <dd>a number to add to the angles, to correct for source image not actually being at 0 degrees
- </dl>
- """
- w1,h1 = img.get_width(),img.get_height()
- shape = pygame.Rect(shape)
- ps = shape.topleft,shape.topright,shape.bottomleft,shape.bottomright
- for a in angles:
- img2 = pygame.transform.rotate(img,a+diff)
- w2,h2 = img2.get_width(),img2.get_height()
- minx,miny,maxx,maxy = 1024,1024,0,0
- for x,y in ps:
- x,y = x-w1/2,y-h1/2
- a2 = math.radians(a+diff)
- #NOTE: the + and - are switched from the normal formula because of
- #the weird way that pygame does the angle...
- x2 = x*math.cos(a2) + y*math.sin(a2)
- y2 = y*math.cos(a2) - x*math.sin(a2)
- x2,y2 = x2+w2/2,y2+h2/2
- minx = min(minx,x2)
- miny = min(miny,y2)
- maxx = max(maxx,x2)
- maxy = max(maxy,y2)
- r = pygame.Rect(minx,miny,maxx-minx,maxy-miny)
- #print r
- #((ww-w)/2,(hh-h)/2,w,h)
- tv.images["%s.%d"%(name,a)] = img2,r
-
-
+++ /dev/null
-"""a state engine.
-"""
-import pygame
-from pygame.locals import *
-
-class State:
- """Template Class -- for a state.
-
- <pre>State(game,value...)</pre>
-
- <dl>
- <dt>game<dd>The state engine.
- <dt>value<dd>I usually pass in a custom value to a state
- </dl>
-
- <p>For all of the template methods, they should return None unless they return
- a new State to switch the engine to.</p>
- """
- def __init__(self,game,value=None):
- self.game,self.value = game,value
- def init(self):
- """Template Method - Initialize the state, called once the first time a state is selected.
-
- <pre>State.init()</pre>
- """
- return
- def paint(self,screen):
- """Template Method - Paint the screen. Called once after the state is selected.
-
- <p>State is responsible for calling <tt>pygame.display.flip()</tt> or whatever.</p>
-
- <pre>State.paint(screen)</pre>
- """
- return
-
- def repaint(self):
- """Template Method - Request a repaint of this state.
-
- <pre>State.repaint()</pre>
- """
- self._paint = 1
- def update(self,screen):
- """Template Method - Update the screen.
-
- <p>State is responsible for calling <tt>pygame.display.update(updates)</tt> or whatever.</p>
-
- <pre>State.update(screen)</pre>
- """
- return
- def loop(self):
- """Template Method - Run a logic loop, called once per frame.
-
- <pre>State.loop()</pre>
- """
- return
- def event(self,e):
- """Template Method - Recieve an event.
-
- <pre>State.event(e)</pre>
- """
- return
-
-class Quit(State):
- """A state to quit the state engine.
-
- <pre>Quit(game,value)</pre>
- """
-
- def init(self):
- self.game.quit = 1
-
-class Game:
- """Template Class - The state engine.
- """
- def fnc(self,f,v=None):
- s = self.state
- if not hasattr(s,f): return 0
- f = getattr(s,f)
- if v != None: r = f(v)
- else: r = f()
- if r != None:
- self.state = r
- self.state._paint = 1
- return 1
- return 0
-
- def run(self,state,screen=None):
- """Run the state engine, this is a infinite loop (until a quit occurs).
-
- <pre>Game.run(state,screen=None)</pre>
-
- <dl>
- <dt>game<dd>a state engine
- <dt>screen<dd>the screen
- </dl>
- """
- self.quit = 0
- self.state = state
- if screen != None: self.screen = screen
-
- self.init()
-
- while not self.quit:
- self.loop()
-
- def loop(self):
- s = self.state
- if not hasattr(s,'_init') or s._init:
- s._init = 0
- if self.fnc('init'): return
- else:
- if self.fnc('loop'): return
- if not hasattr(s,'_paint') or s._paint:
- s._paint = 0
- if self.fnc('paint',self.screen): return
- else:
- if self.fnc('update',self.screen): return
-
- for e in pygame.event.get():
- #NOTE: this might break API?
- #if self.event(e): return
- if not self.event(e):
- if self.fnc('event',e): return
-
- self.tick()
- return
-
- def init(self):
- """Template Method - called at the beginning of State.run() to initialize things.
-
- <pre>Game.init()</pre>
- """
- return
-
- def tick(self):
- """Template Method - called once per frame, usually for timer purposes.
-
- <pre>Game.tick()</pre>
- """
- pygame.time.wait(10)
-
- def event(self,e):
- """Template Method - called with each event, so the engine can capture special events.
-
- <pre>Game.event(e): return captured</pre>
-
- <p>return a True value if the event is captured and does not need to be passed onto the current
- state</p>
- """
- if e.type is QUIT:
- self.state = Quit(self)
- return 1
-
-# vim: set filetype=python sts=4 sw=4 noet si :
+++ /dev/null
-"""Some handy font-like objects.
-
-<p>please note that this file is alpha, and is subject to modification in
-future versions of pgu!</p>
-"""
-
-print 'pgu.fonts','This module is alpha, and is subject to change.'
-
-import pygame
-from pygame.locals import *
-
-class TileFont:
- """Creates an instance of the TileFont class. Interface compatible with pygame.Font
-
- <p>TileFonts are fonts that are stored in a tiled image. Where the image opaque, it assumed that the font is visible. Font color is changed automatically, so it does not work with
- fonts with stylized coloring.</p>
-
- <pre>TileFont(fname,size,hints,scale=None,sensitive=False)</pre>
-
- <dl>
- <dt>size <dd>the dimensions of the characters
- <dt>hints <dd>a string of hints "abcdefg..."
- <dt>scale <dd>size to scale font to
- <dt>sensitive <dd>case sensitivity
- </dl>
- """
-
- def __init__(self,fname,size,hints,scale=None,sensitive=False):
-
- self.image = pygame.image.load(fname)
-
- w,h = self.image.get_width(),self.image.get_height()
- tw,th = size
- if not scale: scale = size
- self._size = size
- self.scale = scale
-
- self.chars = {}
- x,y = 0,0
- self.sensitive = sensitive
- if not self.sensitive: hints = hints.lower()
- for c in hints:
- if c not in ('\r','\n','\t'):
- img = self.image.subsurface(x,y,tw,th)
- self.chars[c] = img
- x += tw
- if x >= w: x,y = 0,y+th
-
- self.colors = {}
-
- def size(self,text):
- tw,th = self.scale
- return len(text)*tw,th
-
- def render(self,text,antialias=0,color=(255,255,255),background=None):
- size = self.size(text)
- scale = self.scale
- tw,th = self._size
- if background == None:
- s = pygame.Surface(size).convert_alpha()
- s.fill((0,0,0,0))
- else:
- s = pygame.Surface(size).convert()
- s.fill(background)
-
- if not self.sensitive: text = text.lower()
-
- if color not in self.colors: self.colors[color] = {}
- colored = self.colors[color]
-
- x,y = 0,0
- for c in text:
- if c in self.chars:
- if c not in colored:
- img = self.chars[c].convert_alpha()
- for yy in xrange(0,th):
- for xx in xrange(0,tw):
- r,g,b,a = img.get_at((xx,yy))
- if a > 128:
- img.set_at((xx,yy),color)
- colored[c] = img
- img = colored[c]
- if scale != (tw,th): img = pygame.transform.scale(img,scale)
- s.blit(img,(x,y))
- x += scale[0]
- return s
-
-
-class BorderFont:
- """a decorator for normal fonts, adds a border. Interface compatible with pygame.Font.
-
- <pre>BorderFont(font,size=1,color=(0,0,0))</pre>
-
- <dl>
- <dt>size <dd>width of border; defaults 0
- <dt>color <dd>color of border; default (0,0,0)
- </dl>
- """
- def __init__(self,font,size=1,color=(0,0,0)):
-
- self.font = font
- self._size = size
- self.color = color
-
- def size(self,text):
- w,h = self.font.size(text)
- s = self._size
- return w+s*2,h+s*2
-
- def render(self,text,antialias=0,color=(255,255,255),background=None):
- size = self.size(text)
-
- if background == None:
- s = pygame.Surface(size).convert_alpha()
- s.fill((0,0,0,0))
- else:
- s = pygame.Surface(size).convert()
- s.fill(background)
-
- bg = self.font.render(text,antialias,self.color)
- fg = self.font.render(text,antialias,color)
-
- si = self._size
- dirs = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
- for dx,dy in dirs: s.blit(bg,(si+dx*si,si+dy*si))
- s.blit(fg,(si,si))
-
- return s
-
-
+++ /dev/null
-import pygame
-from pygame.locals import *
-
-from theme import Theme
-from style import Style
-from widget import Widget
-from surface import subsurface, ProxySurface
-from const import *
-
-from container import Container
-from app import App, Desktop
-from table import Table
-from document import Document
-#html
-from area import SlideBox, ScrollArea, List
-
-from form import Form
-from group import Group
-
-from basic import Spacer, Color, Label, Image, parse_color
-from button import Icon, Button, Switch, Checkbox, Radio, Tool, Link
-from input import Input, Password
-from keysym import Keysym
-from slider import VSlider, HSlider, VScrollBar, HScrollBar
-from select import Select
-from misc import ProgressBar
-
-from menus import Menus
-from dialog import Dialog, FileDialog
-from textarea import TextArea
-
-from deprecated import Toolbox, action_open, action_setvalue, action_quit, action_exec
+++ /dev/null
-"""
-"""
-import pygame
-from pygame.locals import *
-
-import pguglobals
-import container
-from const import *
-
-class App(container.Container):
- """The top-level widget for an application.
-
- <pre>App(theme=None)</pre>
-
- <dl>
- <dt>theme<dd>an instance of a Theme, optional as it will use the default Theme class.
- </dl>
-
- <strong>Basic Example</strong>
- <code>
- app = gui.App()
- app.run(widget=widget,screen=screen)
- </code>
-
- <strong>Integrated Example</strong>
- <code>
- app = gui.App()
- gui.init(widget=widget)
- while 1:
- for e in pygame.event.get():
- app.event(e)
- app.update(screen)
- </code>
-
-
-
- """
- def __init__(self,theme=None,**params):
- self.set_global_app()
-
- if theme == None:
- from theme import Theme
- theme = Theme()
- self.theme = theme
-
- params['decorate'] = 'app'
- container.Container.__init__(self,**params)
- self._quit = False
- self.widget = None
- self._chsize = False
- self._repaint = False
-
- self.screen = None
- self.container = None
- self.events = []
-
- def set_global_app(self):
- # Keep a global reference to this application instance so that PGU
- # components can easily find it.
- pguglobals.app = self
- # For backwards compatibility we keep a reference in the class
- # itself too.
- App.app = self
-
- def resize(self):
-
- screen = self.screen
- w = self.widget
- wsize = 0
-
- #5 cases
-
- #input screen is already set use its size
- if screen:
- self.screen = screen
- width,height = screen.get_width(),screen.get_height()
-
- #display.screen
- elif pygame.display.get_surface():
- screen = pygame.display.get_surface()
- self.screen = screen
- width,height = screen.get_width(),screen.get_height()
-
- #app has width,height
- elif self.style.width != 0 and self.style.height != 0:
- screen = pygame.display.set_mode((self.style.width,self.style.height),SWSURFACE)
- self.screen = screen
- width,height = screen.get_width(),screen.get_height()
-
- #widget has width,height, or its own size..
- else:
- wsize = 1
- width,height = w.rect.w,w.rect.h = w.resize()
- #w._resize()
- screen = pygame.display.set_mode((width,height),SWSURFACE)
- self.screen = screen
-
- #use screen to set up size of this widget
- self.style.width,self.style.height = width,height
- self.rect.w,self.rect.h = width,height
- self.rect.x,self.rect.y = 0,0
-
- w.rect.x,w.rect.y = 0,0
- w.rect.w,w.rect.h = w.resize(width,height)
-
- for w in self.windows:
- w.rect.w,w.rect.h = w.resize()
-
- self._chsize = False
-
-
- def init(self,widget=None,screen=None): #TODO widget= could conflict with module widget
- """Initialize the application.
-
- <pre>App.init(widget=None,screen=None)</pre>
-
- <dl>
- <dt>widget<dd>main widget
- <dt>screen<dd>pygame.Surface to render to
- </dl>
- """
-
- self.set_global_app()
-
- if widget: self.widget = widget
- if screen: self.screen = screen
-
- self.resize()
-
- w = self.widget
-
- self.widgets = []
- self.widgets.append(w)
- w.container = self
- self.focus(w)
-
- pygame.key.set_repeat(500,30)
-
- self._repaint = True
- self._quit = False
-
- self.send(INIT)
-
- def event(self,e):
- """Pass an event to the main widget.
-
- <pre>App.event(e)</pre>
-
- <dl>
- <dt>e<dd>event
- </dl>
- """
- self.set_global_app()
-
- #NOTE: might want to deal with ACTIVEEVENT in the future.
- self.send(e.type,e)
- container.Container.event(self,e)
- if e.type == MOUSEBUTTONUP:
- if e.button not in (4,5): #ignore mouse wheel
- sub = pygame.event.Event(CLICK,{
- 'button':e.button,
- 'pos':e.pos})
- self.send(sub.type,sub)
- container.Container.event(self,sub)
-
-
- def loop(self):
- self.set_global_app()
-
- s = self.screen
- for e in pygame.event.get():
- if not (e.type == QUIT and self.mywindow):
- self.event(e)
- us = self.update(s)
- pygame.display.update(us)
-
-
- def paint(self,screen):
- self.screen = screen
- if self._chsize:
- self.resize()
- self._chsize = False
- if hasattr(self,'background'):
- self.background.paint(screen)
- container.Container.paint(self,screen)
-
- def update(self,screen):
- """Update the screen.
-
- <dl>
- <dt>screen<dd>pygame surface
- </dl>
- """
- self.screen = screen
- if self._chsize:
- self.resize()
- self._chsize = False
- if self._repaint:
- self.paint(screen)
- self._repaint = False
- return [pygame.Rect(0,0,screen.get_width(),screen.get_height())]
- else:
- us = container.Container.update(self,screen)
- return us
-
- def run(self,widget=None,screen=None):
- """Run an application.
-
- <p>Automatically calls <tt>App.init</tt> and then forever loops <tt>App.event</tt> and <tt>App.update</tt></p>
-
- <dl>
- <dt>widget<dd>main widget
- <dt>screen<dd>pygame.Surface to render to
- </dl>
- """
- self.init(widget,screen)
- while not self._quit:
- self.loop()
- pygame.time.wait(10)
-
- def reupdate(self,w=None): pass
- def repaint(self,w=None): self._repaint = True
- def repaintall(self): self._repaint = True
- def chsize(self):
- self._chsize = True
- self._repaint = True
-
- def quit(self,value=None): self._quit = True
-
- def open(self, w, pos=None):
- w.container = self
-
- if (w.rect.w == 0 or w.rect.h == 0):
- w.rect.size = w.resize()
-
- if (not pos):
- # Auto-center the window
- w.rect.center = self.rect.center
- #w.rect.topleft = ((self.rect.w - w.rect.w)/2,
- # (self.rect.h - w.rect.h)/2)
- else:
- # Show the window in a particular location
- w.rect.topleft = pos
-
- self.windows.append(w)
- self.mywindow = w
- self.focus(w)
- self.repaint(w)
- w.send(OPEN)
-
- def close(self, w):
- if self.myfocus is w: self.blur(w)
-
- if w not in self.windows: return #no need to remove it twice! happens.
-
- self.windows.remove(w)
-
- self.mywindow = None
- if self.windows:
- self.mywindow = self.windows[-1]
- self.focus(self.mywindow)
-
- if not self.mywindow:
- self.myfocus = self.widget #HACK: should be done fancier, i think..
- if not self.myhover:
- self.enter(self.widget)
-
- self.repaintall()
- w.send(CLOSE)
-
-
-class Desktop(App):
- """Create an App using the <tt>desktop</tt> theme class.
-
- <pre>Desktop()</pre>
- """
- def __init__(self,**params):
- params.setdefault('cls','desktop')
- App.__init__(self,**params)
+++ /dev/null
-"""
-"""
-import os
-
-import pguglobals
-from const import *
-import surface
-import container, table
-import group
-import basic, button, slider
-from pygame.font import Font
-
-class SlideBox(container.Container):
- """A scrollable area with no scrollbars.
-
- <pre>SlideBox(widget,width,height)</pre>
-
- <dl>
- <dt>widget<dd>widget to be able to scroll around
- <dt>width, height<dd>size of scrollable area
- </dl>
-
- <strong>Example</strong>
- <code>
- c = SlideBox(w,100,100)
- c.offset = (10,10)
- c.repaint()
- </code>
-
- """
-
- def __init__(self, widget, width, height, **params):
- params.setdefault('width', width)
- params.setdefault('height', height)
- container.Container.__init__(self, **params)
- self.offset = [0, 0]
- self.widget = widget
-
- def __setattr__(self,k,v):
- if k == 'widget':
- if hasattr(self,'widget'):
- self.remove(self.widget)
- self.add(v,0,0)
- self.__dict__[k] = v
-
-
- def paint(self, s):
- #if not hasattr(self,'surface'):
- self.surface = pygame.Surface((self.max_rect.w,self.max_rect.h),0,s)
- #self.surface.fill((0,0,0,0))
- pguglobals.app.theme.render(self.surface,self.style.background,pygame.Rect(0,0,self.max_rect.w,self.max_rect.h))
- self.bkgr = pygame.Surface((s.get_width(),s.get_height()),0,s)
- self.bkgr.blit(s,(0,0))
- container.Container.paint(self,self.surface)
- s.blit(self.surface,(-self.offset[0],-self.offset[1]))
- self._offset = self.offset[:]
- return
-
- def paint_for_when_pygame_supports_other_tricks(self,s):
- #this would be ideal if pygame had support for it!
- #and if pgu also had a paint(self,s,rect) method to paint small parts
- sr = (self.offset[0],self.offset[1],self.max_rect.w,self.max_rect.h)
- cr = (-self.offset[0],-self.offset[1],s.get_width(),s.get_height())
- s2 = s.subsurface(sr)
- s2.set_clip(cr)
- container.Container.paint(self,s2)
-
- def proxy_paint(self, s):
- container.Container.paint(self, surface.ProxySurface(parent=None,
- rect=self.max_rect,
- real_surface=s,
- offset=self.offset))
- def update(self, s):
- rects = container.Container.update(self,self.surface)
-
- rets = []
- s_rect = pygame.Rect(0,0,s.get_width(),s.get_height())
-
- if self.offset == self._offset:
- for r in rects:
- r2 = r.move((-self.offset[0],-self.offset[1]))
- if r2.colliderect(s_rect):
- s.blit(self.surface.subsurface(r),r2)
- rets.append(r2)
- else:
- s.blit(self.bkgr,(0,0))
- sub = pygame.Rect(self.offset[0],self.offset[1],min(s.get_width(),self.max_rect.w-self.offset[0]),min(s.get_height(),self.max_rect.h-self.offset[1]))
-# print sub
-# print self.surface.get_width(),self.surface.get_height()
-# print s.get_width(),s.get_height()
-# print self.offset
-# print self.style.width,self.style.height
- s.blit(self.surface.subsurface(sub),(0,0))
- rets.append(s_rect)
- self._offset = self.offset[:]
- return rets
-
- def proxy_update(self, s):
- rects = container.Container.update(self, surface.ProxySurface(parent=None,
- rect=self.max_rect,
- real_surface=s,
- offset=self.offset))
- result = []
- for r in rects: result.append(pygame.Rect(r).move(self.offset))
- return result
-
- def resize(self, width=None, height=None):
- container.Container.resize(self)
- self.max_rect = pygame.Rect(self.widget.rect)
- #self.max_rect.w = max(self.max_rect.w,self.style.width)
- #self.max_rect.h = max(self.max_rect.h,self.style.height)
- return self.style.width,self.style.height
- #self.rect = pygame.Rect(self.rect[0], self.rect[1], self.style.width, self.style.height)
-
- def event(self, e):
- if e.type in [MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION]:
- pos = (e.pos[0] + self.offset[0], e.pos[1] + self.offset[1])
- if self.max_rect.collidepoint(pos):
- e_params = {'pos': pos }
- if e.type == MOUSEMOTION:
- e_params['buttons'] = e.buttons
- e_params['rel'] = e.rel
- else:
- e_params['button'] = e.button
- e = pygame.event.Event(e.type, e_params)
- container.Container.event(self, e)
-
-#class SlideBox(Area):
-# def __init__(self,*args,**params):
-# print 'gui.SlideBox','Scheduled to be renamed to Area.'
-# Area.__init__(self,*args,**params)
-
-class ScrollArea(table.Table):
- """A scrollable area with scrollbars.
-
- <pre>ScrollArea(widget,width,height,hscrollbar=True)</pre>
-
- <dl>
- <dt>widget<dd>widget to be able to scroll around
- <dt>width, height<dd>size of scrollable area. Set either to 0 to default to size of widget.
- <dt>hscrollbar<dd>set to False if you do not wish to have a horizontal scrollbar
- <dt>vscrollbar<dd>set to False if you do not wish to have a vertical scrollbar
- <dt>step<dd>set to how far clicks on the icons will step
- </dl>
- """
- def __init__(self, widget, width=0, height=0, hscrollbar=True, vscrollbar=True,step=24, **params):
- w= widget
- params.setdefault('cls', 'scrollarea')
- table.Table.__init__(self, width=width,height=height,**params)
-
- self.sbox = SlideBox(w, width=width, height=height, cls=self.cls+".content")
- self.widget = w
- self.vscrollbar = vscrollbar
- self.hscrollbar = hscrollbar
-
- self.step = step
-
- def __setattr__(self,k,v):
- if k == 'widget':
- self.sbox.widget = v
- self.__dict__[k] = v
-
- def resize(self,width=None,height=None):
- widget = self.widget
- box = self.sbox
-
- #self.clear()
- table.Table.clear(self)
- #print 'resize',self,self._rows
-
- self.tr()
- self.td(box)
-
- widget.rect.w, widget.rect.h = widget.resize()
- my_width,my_height = self.style.width,self.style.height
- if not my_width:
- my_width = widget.rect.w
- self.hscrollbar = False
- if not my_height:
- my_height = widget.rect.h
- self.vscrollbar = False
-
- box.style.width,box.style.height = my_width,my_height #self.style.width,self.style.height
-
- box.rect.w,box.rect.h = box.resize()
-
- #print widget.rect
- #print box.rect
- #r = table.Table.resize(self,width,height)
- #print r
- #return r
-
- #print box.offset
-
-# #this old code automatically adds in a scrollbar if needed
-# #but it doesn't always work
-# self.vscrollbar = None
-# if widget.rect.h > box.rect.h:
-# self.vscrollbar = slider.VScrollBar(box.offset[1],0, 65535, 0,step=self.step)
-# self.td(self.vscrollbar)
-# self.vscrollbar.connect(CHANGE, self._vscrollbar_changed, None)
-#
-# vs = self.vscrollbar
-# vs.rect.w,vs.rect.h = vs.resize()
-# box.style.width = self.style.width - vs.rect.w
-#
-#
-# self.hscrollbar = None
-# if widget.rect.w > box.rect.w:
-# self.hscrollbar = slider.HScrollBar(box.offset[0], 0,65535, 0,step=self.step)
-# self.hscrollbar.connect(CHANGE, self._hscrollbar_changed, None)
-# self.tr()
-# self.td(self.hscrollbar)
-#
-# hs = self.hscrollbar
-# hs.rect.w,hs.rect.h = hs.resize()
-# box.style.height = self.style.height - hs.rect.h
-
- xt,xr,xb,xl = pguglobals.app.theme.getspacing(box)
-
-
- if self.vscrollbar:
- self.vscrollbar = slider.VScrollBar(box.offset[1],0, 65535, 0,step=self.step)
- self.td(self.vscrollbar)
- self.vscrollbar.connect(CHANGE, self._vscrollbar_changed, None)
-
- vs = self.vscrollbar
- vs.rect.w,vs.rect.h = vs.resize()
- if self.style.width:
- box.style.width = self.style.width - (vs.rect.w + xl+xr)
-
- if self.hscrollbar:
- self.hscrollbar = slider.HScrollBar(box.offset[0], 0,65535, 0,step=self.step)
- self.hscrollbar.connect(CHANGE, self._hscrollbar_changed, None)
- self.tr()
- self.td(self.hscrollbar)
-
- hs = self.hscrollbar
- hs.rect.w,hs.rect.h = hs.resize()
- if self.style.height:
- box.style.height = self.style.height - (hs.rect.h + xt + xb)
-
- if self.hscrollbar:
- hs = self.hscrollbar
- hs.min = 0
- hs.max = widget.rect.w - box.style.width
- hs.style.width = box.style.width
- hs.size = hs.style.width * box.style.width / max(1,widget.rect.w)
- else:
- box.offset[0] = 0
-
- if self.vscrollbar:
- vs = self.vscrollbar
- vs.min = 0
- vs.max = widget.rect.h - box.style.height
- vs.style.height = box.style.height
- vs.size = vs.style.height * box.style.height / max(1,widget.rect.h)
- else:
- box.offset[1] = 0
-
- #print self.style.width,box.style.width, hs.style.width
-
- r = table.Table.resize(self,width,height)
- return r
-
- def x_resize(self, width=None, height=None):
- w,h = table.Table.resize(self, width, height)
- if self.hscrollbar:
- if self.widget.rect.w <= self.sbox.rect.w:
- self.hscrollbar.size = self.hscrollbar.style.width
- else:
- self.hscrollbar.size = max(20,self.hscrollbar.style.width * self.sbox.rect.w / self.widget.rect.w)
- self._hscrollbar_changed(None)
- if self.widget.rect.h <= self.sbox.rect.h:
- self.vscrollbar.size = self.vscrollbar.style.height
- else:
- self.vscrollbar.size = max(20,self.vscrollbar.style.height * self.sbox.rect.h / self.widget.rect.h)
- self._vscrollbar_changed(None)
- return w,h
-
- def _vscrollbar_changed(self, xxx):
- #y = (self.widget.rect.h - self.sbox.rect.h) * self.vscrollbar.value / 1000
- #if y >= 0: self.sbox.offset[1] = -y
- self.sbox.offset[1] = self.vscrollbar.value
- self.sbox.reupdate()
-
- def _hscrollbar_changed(self, xxx):
- #x = (self.widget.rect.w - self.sbox.rect.w) * self.hscrollbar.value / 1000
- #if x >= 0: self.sbox.offset[0] = -x
- self.sbox.offset[0] = self.hscrollbar.value
- self.sbox.reupdate()
-
-
- def set_vertical_scroll(self, percents):
- #if not self.vscrollbar: return
- if not hasattr(self.vscrollbar,'value'): return
- self.vscrollbar.value = percents #min(max(percents*10, 0), 1000)
- self._vscrollbar_changed(None)
-
- def set_horizontal_scroll(self, percents):
- #if not self.hscrollbar: return
- if not hasattr(self.hscrollbar,'value'): return
- self.hscrollbar.value = percents #min(max(percents*10, 0), 1000)
- self._hscrollbar_changed(None)
-
- def event(self, e):
- #checking for event recipient
- if (table.Table.event(self, e)):
- return True
-
- #mouse wheel scrolling
- if self.vscrollbar:
- if not hasattr(self.vscrollbar,'value'):
- return False
-
- if e.type == pygame.locals.MOUSEBUTTONDOWN:
- if e.button == 4: #wheel up
- self.vscrollbar._click(-1)
- return True
- elif e.button == 5: #wheel down
- self.vscrollbar._click(1)
- return True
- return False
-
-
-
-
-class _List_Item(button._button):
- def __init__(self,label=None,image=None,value=None,**params): #TODO label= could conflict with the module label
- #param image: an imagez.Image object (optional)
- #param text: a string object
- params.setdefault('cls','list.item')
- button._button.__init__(self,**params)
- self.group = None
- self.value = value #(self, value)
- self.widget = None
-
- if type(label) == str:
- label = basic.Label(label, cls=self.cls+".label")
-
- if image and label:
- self.widget = container.Container()
- self.widget.add(image, 0, 0)
- #HACK: improper use of .resize()
- image.rect.w,image.rect.h = image.resize()
- self.widget.add(label, image.rect.w, 0)
- elif image: self.widget = image
- elif label: self.widget = label
-
- self.pcls = ""
-
- def resize(self,width=None,height=None):
- self.widget.rect.w,self.widget.rect.h = self.widget.resize()
- return self.widget.rect.w,self.widget.rect.h
-# self.widget._resize()
-# self.rect.w,self.rect.h = self.widget.rect_margin.w,self.widget.rect_margin.h
-
- def event(self,e):
- button._button.event(self,e)
- if self.group.value == self.value: self.pcls = "down"
-
- def paint(self,s):
- if self.group.value == self.value: self.pcls = "down"
- self.widget.paint(surface.subsurface(s,self.widget.rect))
-
- def click(self):
- self.group.value = self.value
- for w in self.group.widgets:
- if w != self: w.pcls = ""
-
-
-
-class List(ScrollArea):
- """A list of items in an area.
-
- <p>This widget can be a form element, it has a value set to whatever item is selected.</p>
-
- <pre>List(width,height)</pre>
- """
- def _change(self, value):
- self.value = self.group.value
- self.send(CHANGE)
-
- def __init__(self, width, height, **params):
- params.setdefault('cls', 'list')
- self.table = table.Table(width=width)
- ScrollArea.__init__(self, self.table, width, height,hscrollbar=False ,**params)
-
- self.items = []
-
- g = group.Group()
- self.group = g
- g.connect(CHANGE,self._change,None)
- self.value = self.group.value = None
-
- self.add = self._add
- self.remove = self._remove
-
- def clear(self):
- """Clear the list.
-
- <pre>List.clear()</pre>
- """
- self.items = []
- self.group = group.Group()
- self.group.connect(CHANGE,self._change,None)
- self.table.clear()
- self.set_vertical_scroll(0)
- self.blur(self.myfocus)
-
- def _docs(self): #HACK: nasty hack to get the docs in "my way"
- def add(self, label, image=None, value=None):
- """Add an item to the list.
-
- <pre>List.add(label,image=None,value=None)</pre>
-
- <dl>
- <dt>label<dd>a label for the item
- <dt>image<dd>an image for the item
- <dt>value<dd>a value for the item
- </dl>
- """
-
- def remove(self,value):
- """Remove an item from the list.
-
- <pre>List.remove(value)</pre>
-
- <dl>
- <dt>value<dd>a value of an item to remove from the list
- </dl>
- """
-
- def _add(self, label, image = None, value=None):
- item = _List_Item(label,image=image,value=value)
- self.table.tr()
- self.table.add(item)
- self.items.append(item)
- item.group = self.group
- item.group.add(item)
-
- def _remove(self, item):
- for i in self.items:
- if i.value == item: item = i
- if item not in self.items: return
- item.blur()
- self.items.remove(item)
- self.group.widgets.remove(item)
- self.table.remove_row(item.style.row)
-
-#class List(ListArea):
-# def __init__(self,*args,**params):
-# print 'gui.List','Scheduled to be renamed to ListArea. API may also be changed in the future.'
-# ListArea.__init__(self,*args,**params)
+++ /dev/null
-"""These widgets are all grouped together because they are non-interactive widgets.
-"""
-
-import pygame
-
-from const import *
-import widget
-
-# Turns a descriptive string or a tuple into a pygame color
-def parse_color(desc):
- if (is_color(desc)):
- # Already a color
- return desc
- elif (desc and desc[0] == "#"):
- # Because of a bug in pygame 1.8.1 we need to explicitly define the
- # alpha value otherwise it will default to transparent.
- if (len(desc) == 7):
- desc += "FF"
- return pygame.Color(desc)
-
-# Determines if the given object is a pygame-compatible color or not
-def is_color(col):
- # In every version of pygame (up to 1.8.1 so far) will interpret
- # a tuple as a color.
- if (type(col) == tuple):
- return col
- if (hasattr(pygame, "Color") and type(pygame.Color) == type):
- # This is a recent version of pygame that uses a proper type
- # instance for colors.
- return (isinstance(col, pygame.Color))
- # Otherwise, this version of pygame only supports tuple colors
- return False
-
-class Spacer(widget.Widget):
- """A invisible space.
-
- <pre>Spacer(width,height)</pre>
-
- """
- def __init__(self,width,height,**params):
- params.setdefault('focusable',False)
- widget.Widget.__init__(self,width=width,height=height,**params)
-
-
-class Color(widget.Widget):
- """A block of color.
-
- <p>The color can be changed at run-time.</p>
-
- <pre>Color(value=None)</pre>
-
- <strong>Example</strong>
- <code>
- c = Color()
- c.value = (255,0,0)
- c.value = (0,255,0)
- </code>
- """
-
-
- def __init__(self,value=None,**params):
- params.setdefault('focusable',False)
- if value != None: params['value']=value
- widget.Widget.__init__(self,**params)
-
- def paint(self,s):
- if hasattr(self,'value'): s.fill(self.value)
-
- def __setattr__(self,k,v):
- if k == 'value' and type(v) == str:
- v = parse_color(v)
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
-
-class Label(widget.Widget):
- """A text label.
-
- <pre>Label(value)</pre>
-
- <dl>
- <dt>value<dd>text to be displayed
- </dl>
-
- <strong>Example</strong>
- <code>
- w = Label(value="I own a rubber chicken!")
-
- w = Label("3 rubber chickens")
- </code>
- """
- def __init__(self,value,**params):
- params.setdefault('focusable',False)
- params.setdefault('cls','label')
- widget.Widget.__init__(self,**params)
- self.value = value
- self.font = self.style.font
- self.style.width, self.style.height = self.font.size(self.value)
-
- def paint(self,s):
- s.blit(self.font.render(self.value, 1, self.style.color),(0,0))
-
-class Image(widget.Widget):
- """An image.
-
- <pre>Image(value)</pre>
-
- <dl>
- <dt>value<dd>a file name or a pygame.Surface
- </dl>
-
- """
- def __init__(self,value,**params):
- params.setdefault('focusable',False)
- widget.Widget.__init__(self,**params)
- if type(value) == str: value = pygame.image.load(value)
-
- ow,oh = iw,ih = value.get_width(),value.get_height()
- sw,sh = self.style.width,self.style.height
-
- if sw and not sh:
- iw,ih = sw,ih*sw/iw
- elif sh and not sw:
- iw,ih = iw*sh/ih,sh
- elif sw and sh:
- iw,ih = sw,sh
-
- if (ow,oh) != (iw,ih):
- value = pygame.transform.scale(value,(iw,ih))
- self.style.width,self.style.height = iw,ih
- self.value = value
-
- def paint(self,s):
- s.blit(self.value,(0,0))
+++ /dev/null
-"""
-"""
-
-from pygame.locals import *
-
-from const import *
-import widget, surface
-import basic
-
-class _button(widget.Widget):
- def __init__(self,**params):
- widget.Widget.__init__(self,**params)
- self.state = 0
-
- def event(self,e):
- if e.type == ENTER: self.repaint()
- elif e.type == EXIT: self.repaint()
- elif e.type == FOCUS: self.repaint()
- elif e.type == BLUR: self.repaint()
- elif e.type == KEYDOWN:
- if e.key == K_SPACE or e.key == K_RETURN:
- self.state = 1
- self.repaint()
- elif e.type == MOUSEBUTTONDOWN:
- self.state = 1
- self.repaint()
- elif e.type == KEYUP:
- if self.state == 1:
- sub = pygame.event.Event(CLICK,{'pos':(0,0),'button':1})
- #self.send(sub.type,sub)
- self._event(sub)
-
- self.state = 0
- self.repaint()
- elif e.type == MOUSEBUTTONUP:
- self.state = 0
- self.repaint()
- elif e.type == CLICK:
- self.click()
-
- self.pcls = ""
- if self.state == 0 and self.container.myhover is self:
- self.pcls = "hover"
- if self.state == 1 and self.container.myhover is self:
- self.pcls = "down"
-
- def click(self):
- pass
-
-
-class Button(_button):
- """A button, buttons can be clicked, they are usually used to set up callbacks.
-
- <pre>Button(value=None)</pre>
-
- <dl>
- <dt>value<dd>either a widget or a string
- </dl>
-
- <strong>Example</strong>
- <code>
- w = gui.Button("Click Me")
- w.connect(gui.CLICK,fnc,value)
- </code>
- """
- def __init__(self,value=None,**params):
- params.setdefault('cls','button')
- _button.__init__(self,**params)
- self.value = value
-
- def __setattr__(self,k,v):
- if k == 'value' and type(v) == str: v = basic.Label(v,cls=self.cls+".label")
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and v != None:
- pass
-
- if k == 'value' and _v != NOATTR and _v != None and _v != v:
- self.send(CHANGE)
- self.chsize()
-
- def resize(self,width=None,height=None):
- self.value.rect.x,self.value.rect.y = 0,0
- self.value.rect.w,self.value.rect.h = self.value.resize(width,height)
- return self.value.rect.w,self.value.rect.h
-#
-# self.value._resize()
-# self.rect.w,self.rect.h = self.value.rect_margin.w,self.value.rect_margin.h
-#
-# if self.style.width: self.rect.w = max(self.rect.w,self.style.width)
-# if self.style.height: self.rect.w = max(self.rect.w,self.style.height)
-#
-# xt,xr,xb,xl = self.value.getspacing()
-#
-# self.value._resize(self.rect.w-(xl+xr),self.rect.h-(xt+xb))
-#
- def paint(self,s):
- self.value.pcls = self.pcls
- self.value.paint(surface.subsurface(s,self.value.rect))
-
-class Switch(_button):
- """A switch can have two states, True or False.
-
- <pre>Switch(value=False)</pre>
-
- <dl>
- <dt>value<dd>initial value, (True, False)
- </dl>
-
- <strong>Example</strong>
- <code>
- w = gui.Switch(True)
- w.connect(gui.CHANGE,fnc,value)
- </code>
- """
- def __init__(self,value=False,**params):
- params.setdefault('cls','switch')
- _button.__init__(self,**params)
- self.value = value
-
- img = self.style.off
- self.style.width = img.get_width()
- self.style.height = img.get_height()
-
- def paint(self,s):
- #self.pcls = ""
- #if self.container.myhover is self: self.pcls = "hover"
- if self.value: img = self.style.on
- else: img = self.style.off
- s.blit(img,(0,0))
-
- def __setattr__(self,k,v):
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
-
- def click(self):
- self.value = not self.value
-
-class Checkbox(_button):
- """Within a Group of Checkbox widgets several may be selected at a time.
-
- <pre>Checkbox(group,value=None)</pre>
-
- <dl>
- <dt>group<dd>a gui.Group for the Checkbox to belong to
- <dt>value<dd>the value
- </dl>
-
- <strong>Example</strong>
- <code>
- g = gui.Group(name='colors',value=['r','b'])
-
- t = gui.Table()
- t.tr()
- t.td(gui.Label('Red'))
- t.td(gui.Checkbox(g,'r'))
- t.tr()
- t.td(gui.Label('Green'))
- t.td(gui.Checkbox(g,'g'))
- t.tr()
- t.td(gui.Label('Blue'))
- t.td(gui.Checkbox(g,'b'))
- </code>
- """
-
- def __init__(self,group,value=None,**params):
- params.setdefault('cls','checkbox')
- _button.__init__(self,**params)
- self.group = group
- self.group.add(self)
- if self.group.value == None:
- self.group.value = []
- self.value = value
-
- img = self.style.off
- self.style.width = img.get_width()
- self.style.height = img.get_height()
-
- def paint(self,s):
- #self.pcls = ""
- #if self.container.myhover is self: self.pcls = "hover"
- if self.value in self.group.value: img = self.style.on
- else: img = self.style.off
-
- s.blit(img,(0,0))
-
- def click(self):
- if self.value in self.group.value:
- self.group.value.remove(self.value)
- else:
- self.group.value.append(self.value)
- self.group._change()
-
-class Radio(_button):
- """Within a Group of Radio widgets only one may be selected at a time.
-
- <pre>Radio(group,value=None)</pre>
-
- <dl>
- <dt>group<dd>a gui.Group for the Radio to belong to
- <dt>value<dd>the value
- </dl>
-
- <strong>Example</strong>
- <code>
- g = gui.Group(name='colors',value='g')
-
- t = gui.Table()
- t.tr()
- t.td(gui.Label('Red'))
- t.td(gui.Radio(g,'r'))
- t.tr()
- t.td(gui.Label('Green'))
- t.td(gui.Radio(g,'g'))
- t.tr()
- t.td(gui.Label('Blue'))
- t.td(gui.Radio(g,'b'))
- </code>
- """
-
-
- def __init__(self,group=None,value=None,**params):
- params.setdefault('cls','radio')
- _button.__init__(self,**params)
- self.group = group
- self.group.add(self)
- self.value = value
-
- img = self.style.off
- self.style.width = img.get_width()
- self.style.height = img.get_height()
-
- def paint(self,s):
- #self.pcls = ""
- #if self.container.myhover is self: self.pcls = "hover"
- if self.group.value == self.value: img = self.style.on
- else: img = self.style.off
- s.blit(img,(0,0))
-
- def click(self):
- self.group.value = self.value
-
-class Tool(_button):
- """Within a Group of Tool widgets only one may be selected at a time.
-
- <pre>Tool(group,widget=None,value=None)</pre>
-
- <dl>
- <dt>group<dd>a gui.Group for the Tool to belong to
- <dt>widget<dd>a widget to appear on the Tool (similar to a Button)
- <dt>value<dd>the value
- </dl>
-
- <strong>Example</strong>
- <code>
- g = gui.Group(name='colors',value='g')
-
- t = gui.Table()
- t.tr()
- t.td(gui.Tool(g,'Red','r'))
- t.tr()
- t.td(gui.Tool(g,'Green','g'))
- t.tr()
- t.td(gui.Tool(g,'Blue','b'))
- </code>
- """
-
- def __init__(self,group,widget=None,value=None,**params): #TODO widget= could conflict with module widget
- params.setdefault('cls','tool')
- _button.__init__(self,**params)
- self.group = group
- self.group.add(self)
- self.value = value
-
- if widget:
- self.setwidget(widget)
-
- if self.group.value == self.value: self.pcls = "down"
-
- def setwidget(self,w):
- self.widget = w
-
- def resize(self,width=None,height=None):
- self.widget.rect.w,self.widget.rect.h = self.widget.resize()
- #self.widget._resize()
- #self.rect.w,self.rect.h = self.widget.rect_margin.w,self.widget.rect_margin.h
-
- return self.widget.rect.w,self.widget.rect.h
-
- def event(self,e):
- _button.event(self,e)
- if self.group.value == self.value: self.pcls = "down"
-
- def paint(self,s):
- if self.group.value == self.value: self.pcls = "down"
- self.widget.paint(surface.subsurface(s,self.widget.rect))
-
- def click(self):
- self.group.value = self.value
- for w in self.group.widgets:
- if w != self: w.pcls = ""
-
-
-class Icon(_button):
- """TODO - might be deprecated
- """
- def __init__(self,cls,**params):
- params['cls'] = cls
- _button.__init__(self,**params)
- s = self.style.image
- self.style.width = s.get_width()
- self.style.height = s.get_height()
- self.state = 0
-
- def paint(self,s):
- #self.pcls = ""
- #if self.state == 0 and hasattr(self.container,'myhover') and self.container.myhover is self: self.pcls = "hover"
- #if self.state == 1 and hasattr(self.container,'myhover') and self.container.myhover is self: self.pcls = "down"
- s.blit(self.style.image,(0,0))
-
-class Link(_button):
- """A link, links can be clicked, they are usually used to set up callbacks.
- Basically the same as the button widget, just text only with a different cls. Made for
- convenience.
-
- <pre>Link(value=None)</pre>
-
- <dl>
- <dt>value<dd>a string
- </dl>
-
- <strong>Example</strong>
- <code>
- w = gui.Link("Click Me")
- w.connect(gui.CLICK,fnc,value)
- </code>
- """
- def __init__(self,value,**params):
- params.setdefault('focusable',True)
- params.setdefault('cls','link')
- _button.__init__(self,**params)
- self.value = value
- self.font = self.style.font
- self.style.width, self.style.height = self.font.size(self.value)
-
- def paint(self,s):
- s.blit(self.font.render(self.value, 1, self.style.color),(0,0))
-
+++ /dev/null
-"""Constants.
-<br><br>
-<strong>Event Types</strong>
-
-<p>from pygame</p>
-<dl>
-<dt>QUIT
-<dt>MOUSEBUTTONDOWN
-<dt>MOUSEBUTTONUP
-<dt>MOUSEMOTION
-<dt>KEYDOWN
-</dl>
-
-<p>gui specific</p>
-<dl>
-<dt>ENTER
-<dt>EXIT
-<dt>BLUR
-<dt>FOCUS
-<dt>CLICK
-<dt>CHANGE
-<dt>OPEN
-<dt>CLOSE
-<dt>INIT
-</dl>
-
-<strong>Other</strong>
-<dl>
-<dt>NOATTR
-</dl>
-"""
-import pygame
-
-from pygame.locals import QUIT, MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION, KEYDOWN, USEREVENT
-ENTER = pygame.locals.USEREVENT + 0
-EXIT = pygame.locals.USEREVENT + 1
-BLUR = pygame.locals.USEREVENT + 2
-FOCUS = pygame.locals.USEREVENT + 3
-CLICK = pygame.locals.USEREVENT + 4
-CHANGE = pygame.locals.USEREVENT + 5
-OPEN = pygame.locals.USEREVENT + 6
-CLOSE = pygame.locals.USEREVENT + 7
-INIT = 'init'
-
-class NOATTR: pass
\ No newline at end of file
+++ /dev/null
-"""
-"""
-import pygame
-from pygame.locals import *
-
-from const import *
-import widget, surface
-import pguglobals
-
-class Container(widget.Widget):
- """The base container widget, can be used as a template as well as stand alone.
-
- <pre>Container()</pre>
- """
- def __init__(self,**params):
- widget.Widget.__init__(self,**params)
- self.myfocus = None
- self.mywindow = None
- self.myhover = None
- #self.background = 0
- self.widgets = []
- self.windows = []
- self.toupdate = {}
- self.topaint = {}
-
- def update(self,s):
- updates = []
-
- if self.myfocus: self.toupdate[self.myfocus] = self.myfocus
-
- for w in self.topaint:
- if w is self.mywindow:
- continue
- else:
- sub = surface.subsurface(s,w.rect)
- #if (hasattr(w, "_container_bkgr")):
- # sub.blit(w._container_bkgr,(0,0))
- w.paint(sub)
- updates.append(pygame.rect.Rect(w.rect))
-
- for w in self.toupdate:
- if w is self.mywindow:
- continue
- else:
- us = w.update(surface.subsurface(s,w.rect))
- if us:
- for u in us:
- updates.append(pygame.rect.Rect(u.x + w.rect.x,u.y+w.rect.y,u.w,u.h))
-
- for w in self.topaint:
- if w is self.mywindow:
- w.paint(self.top_surface(s,w))
- updates.append(pygame.rect.Rect(w.rect))
- else:
- continue
-
- for w in self.toupdate:
- if w is self.mywindow:
- us = w.update(self.top_surface(s,w))
- else:
- continue
- if us:
- for u in us:
- updates.append(pygame.rect.Rect(u.x + w.rect.x,u.y+w.rect.y,u.w,u.h))
-
- self.topaint = {}
- self.toupdate = {}
-
- return updates
-
- def repaint(self,w=None):
- if not w:
- return widget.Widget.repaint(self)
- self.topaint[w] = w
- self.reupdate()
-
- def reupdate(self,w=None):
- if not w:
- return widget.Widget.reupdate(self)
- self.toupdate[w] = w
- self.reupdate()
-
- def paint(self,s):
- self.toupdate = {}
- self.topaint = {}
- for w in self.widgets:
- try:
- sub = surface.subsurface(s, w.rect)
- except:
- print 'container.paint(): %s not inside %s' % (
- w.__class__.__name__,self.__class__.__name__)
- print s.get_width(), s.get_height(), w.rect
- print ""
- else:
-# if (not hasattr(w,'_container_bkgr') or
-# w._container_bkgr.get_size() != sub.get_size()):
-# #w._container_bkgr.get_width() == sub.get_width() and
-# #w._container_bkgr.get_height() == sub.get_height())):
-# w._container_bkgr = sub.copy()
-# w._container_bkgr.fill((0,0,0,0))
-# w._container_bkgr.blit(sub,(0,0))
- w.paint(sub)
-
- for w in self.windows:
- w.paint(self.top_surface(s,w))
-
- def top_surface(self,s,w):
- x,y = s.get_abs_offset()
- s = s.get_abs_parent()
- return surface.subsurface(s,(x+w.rect.x,y+w.rect.y,w.rect.w,w.rect.h))
-
- def event(self,e):
- used = False
-
- if self.mywindow and e.type == MOUSEBUTTONDOWN:
- w = self.mywindow
- if self.myfocus is w:
- if not w.rect.collidepoint(e.pos): self.blur(w)
- if not self.myfocus:
- if w.rect.collidepoint(e.pos): self.focus(w)
-
- if not self.mywindow:
- #### by Gal Koren
- ##
- ## if e.type == FOCUS:
- if e.type == FOCUS and not self.myfocus:
- #self.first()
- pass
- elif e.type == EXIT:
- if self.myhover: self.exit(self.myhover)
- elif e.type == BLUR:
- if self.myfocus: self.blur(self.myfocus)
- elif e.type == MOUSEBUTTONDOWN:
- h = None
- for w in self.widgets:
- if not w.disabled: #focusable not considered, since that is only for tabs
- if w.rect.collidepoint(e.pos):
- h = w
- if self.myfocus is not w: self.focus(w)
- if not h and self.myfocus:
- self.blur(self.myfocus)
- elif e.type == MOUSEMOTION:
- if 1 in e.buttons:
- if self.myfocus: ws = [self.myfocus]
- else: ws = []
- else: ws = self.widgets
-
- h = None
- for w in ws:
- if w.rect.collidepoint(e.pos):
- h = w
- if self.myhover is not w: self.enter(w)
- if not h and self.myhover:
- self.exit(self.myhover)
- w = self.myhover
-
- if w and w is not self.myfocus:
- sub = pygame.event.Event(e.type,{
- 'buttons':e.buttons,
- 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y),
- 'rel':e.rel})
- used = w._event(sub)
-
- w = self.myfocus
- if w:
- sub = e
-
- if e.type == MOUSEBUTTONUP or e.type == MOUSEBUTTONDOWN:
- sub = pygame.event.Event(e.type,{
- 'button':e.button,
- 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y)})
- used = w._event(sub)
- elif e.type == CLICK and self.myhover is w:
- sub = pygame.event.Event(e.type,{
- 'button':e.button,
- 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y)})
- used = w._event(sub)
- elif e.type == CLICK: #a dead click
- pass
- elif e.type == MOUSEMOTION:
- sub = pygame.event.Event(e.type,{
- 'buttons':e.buttons,
- 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y),
- 'rel':e.rel})
- used = w._event(sub)
- else:
- used = w._event(sub)
-
- if not used:
- if e.type is KEYDOWN:
- if e.key is K_TAB and self.myfocus:
- if (e.mod&KMOD_SHIFT) == 0:
- self.myfocus.next()
- else:
- self.myfocus.previous()
- return True
- elif e.key == K_UP:
- self._move_focus(0,-1)
- return True
- elif e.key == K_RIGHT:
- self._move_focus(1,0)
- return True
- elif e.key == K_DOWN:
- self._move_focus(0,1)
- return True
- elif e.key == K_LEFT:
- self._move_focus(-1,0)
- return True
- return used
-
- def _move_focus(self,dx_,dy_):
- myfocus = self.myfocus
- if not self.myfocus: return
-
- widgets = self._get_widgets(pguglobals.app)
- #if myfocus not in widgets: return
- #widgets.remove(myfocus)
- if myfocus in widgets:
- widgets.remove(myfocus)
- rect = myfocus.get_abs_rect()
- fx,fy = rect.centerx,rect.centery
-
- def sign(v):
- if v < 0: return -1
- if v > 0: return 1
- return 0
-
- dist = []
- for w in widgets:
- wrect = w.get_abs_rect()
- wx,wy = wrect.centerx,wrect.centery
- dx,dy = wx-fx,wy-fy
- if dx_ > 0 and wrect.left < rect.right: continue
- if dx_ < 0 and wrect.right > rect.left: continue
- if dy_ > 0 and wrect.top < rect.bottom: continue
- if dy_ < 0 and wrect.bottom > rect.top: continue
- dist.append((dx*dx+dy*dy,w))
- if not len(dist): return
- dist.sort()
- d,w = dist.pop(0)
- w.focus()
-
- def _get_widgets(self,c):
- widgets = []
- if c.mywindow:
- widgets.extend(self._get_widgets(c.mywindow))
- else:
- for w in c.widgets:
- if isinstance(w,Container):
- widgets.extend(self._get_widgets(w))
- elif not w.disabled and w.focusable:
- widgets.append(w)
- return widgets
-
- def remove(self,w):
- """Remove a widget from the container.
-
- <pre>Container.remove(w)</pre>
- """
- self.blur(w)
- self.widgets.remove(w)
- #self.repaint()
- self.chsize()
-
- def add(self,w,x,y):
- """Add a widget to the container.
-
- <pre>Container.add(w,x,y)</pre>
-
- <dl>
- <dt>x, y<dd>position of the widget
- </dl>
- """
- w.style.x = x
- w.style.y = y
- w.container = self
- #NOTE: this might fix it, sort of...
- #but the thing is, we don't really want to resize
- #something if it is going to get resized again later
- #for no reason...
- #w.rect.x,w.rect.y = w.style.x,w.style.y
- #w.rect.w, w.rect.h = w.resize()
- self.widgets.append(w)
- self.chsize()
-
- def open(self,w=None,x=None,y=None):
- if (not w):
- w = self
-
- if (x != None):
- # The position is relative to this container
- rect = self.get_abs_rect()
- pos = (rect.x + x, rect.y + y)
- else:
- pos = None
- # Have the application open the window
- pguglobals.app.open(w, pos)
-
- def focus(self,w=None):
- widget.Widget.focus(self) ### by Gal koren
-# if not w:
-# return widget.Widget.focus(self)
- if not w: return
- if self.myfocus: self.blur(self.myfocus)
- if self.myhover is not w: self.enter(w)
- self.myfocus = w
- w._event(pygame.event.Event(FOCUS))
-
- #print self.myfocus,self.myfocus.__class__.__name__
-
- def blur(self,w=None):
- if not w:
- return widget.Widget.blur(self)
- if self.myfocus is w:
- if self.myhover is w: self.exit(w)
- self.myfocus = None
- w._event(pygame.event.Event(BLUR))
-
- def enter(self,w):
- if self.myhover: self.exit(self.myhover)
- self.myhover = w
- w._event(pygame.event.Event(ENTER))
-
- def exit(self,w):
- if self.myhover and self.myhover is w:
- self.myhover = None
- w._event(pygame.event.Event(EXIT))
-
-
-# def first(self):
-# for w in self.widgets:
-# if w.focusable:
-# self.focus(w)
-# return
-# if self.container: self.container.next(self)
-
-# def next(self,w):
-# if w not in self.widgets: return #HACK: maybe. this happens in windows for some reason...
-#
-# for w in self.widgets[self.widgets.index(w)+1:]:
-# if w.focusable:
-# self.focus(w)
-# return
-# if self.container: return self.container.next(self)
-
-
- def _next(self,orig=None):
- start = 0
- if orig in self.widgets: start = self.widgets.index(orig)+1
- for w in self.widgets[start:]:
- if not w.disabled and w.focusable:
- if isinstance(w,Container):
- if w._next():
- return True
- else:
- self.focus(w)
- return True
- return False
-
- def _previous(self,orig=None):
- end = len(self.widgets)
- if orig in self.widgets: end = self.widgets.index(orig)
- ws = self.widgets[:end]
- ws.reverse()
- for w in ws:
- if not w.disabled and w.focusable:
- if isinstance(w,Container):
- if w._previous():
- return True
- else:
- self.focus(w)
- return True
- return False
-
- def next(self,w=None):
- if w != None and w not in self.widgets: return #HACK: maybe. this happens in windows for some reason...
-
- if self._next(w): return True
- if self.container: return self.container.next(self)
-
-
- def previous(self,w=None):
- if w != None and w not in self.widgets: return #HACK: maybe. this happens in windows for some reason...
-
- if self._previous(w): return True
- if self.container: return self.container.previous(self)
-
- def resize(self,width=None,height=None):
- #r = self.rect
- #r.w,r.h = 0,0
- ww,hh = 0,0
- if self.style.width: ww = self.style.width
- if self.style.height: hh = self.style.height
-
- for w in self.widgets:
- #w.rect.w,w.rect.h = 0,0
- w.rect.x,w.rect.y = w.style.x,w.style.y
- w.rect.w, w.rect.h = w.resize()
- #w._resize()
-
- ww = max(ww,w.rect.right)
- hh = max(hh,w.rect.bottom)
- return ww,hh
-
- # Returns the widget with the given name
- def find(self, name):
- for w in self.widgets:
- if (w.name == name):
- return w
- elif (isinstance(w, Container)):
- tmp = w.find(name)
- if (tmp): return tmp
- return None
-
+++ /dev/null
-import pygame
-
-from const import *
-import table
-import group
-import button, basic
-import pguglobals
-
-def action_open(value):
- print 'gui.action_open',"Scheduled to be deprecated."
- value.setdefault('x',None)
- value.setdefault('y',None)
- value['container'].open(value['window'],value['x'],value['y'])
-
-def action_setvalue(value):
- print 'gui.action_setvalue',"Scheduled to be deprecated."
- a,b = value
- b.value = a.value
-
-def action_quit(value):
- print 'gui.action_quit',"Scheduled to be deprecated."
- value.quit()
-
-def action_exec(value):
- print 'gui.action_exec',"Scheduled to be deprecated."
- exec(value['script'],globals(),value['dict'])
-
-class Toolbox(table.Table):
- def __setattr__(self,k,v):
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.group.value = v
- for w in self.group.widgets:
- if w.value != v: w.pcls = ""
- else: w.pcls = "down"
- self.repaint()
-
- def _change(self,value):
- self.value = self.group.value
- self.send(CHANGE)
-
- def __init__(self,data,cols=0,rows=0,tool_cls='tool',value=None,**params):
- print 'gui.Toolbox','Scheduled to be deprecated.'
- params.setdefault('cls','toolbox')
- table.Table.__init__(self,**params)
-
- if cols == 0 and rows == 0: cols = len(data)
- if cols != 0 and rows != 0: rows = 0
-
- self.tools = {}
-
- _value = value
-
- g = group.Group()
- self.group = g
- g.connect(CHANGE,self._change,None)
- self.group.value = _value
-
- x,y,p,s = 0,0,None,1
- for ico,value in data:
- #from __init__ import theme
- img = pguglobals.app.theme.get(tool_cls+"."+ico,"","image")
- if img:
- i = basic.Image(img)
- else: i = basic.Label(ico,cls=tool_cls+".label")
- p = button.Tool(g,i,value,cls=tool_cls)
- self.tools[ico] = p
- #p.style.hexpand = 1
- #p.style.vexpand = 1
- self.add(p,x,y)
- s = 0
- if cols != 0: x += 1
- if cols != 0 and x == cols: x,y = 0,y+1
- if rows != 0: y += 1
- if rows != 0 and y == rows: x,y = x+1,0
+++ /dev/null
-"""
-"""
-import os
-
-from const import *
-import table, area
-import basic, input, button
-import pguglobals
-
-class Dialog(table.Table):
- """A dialog window with a title bar and an "close" button on the bar.
-
- <pre>Dialog(title,main)</pre>
-
- <dl>
- <dt>title<dd>title widget, usually a label
- <dt>main<dd>main widget, usually a container
- </dl>
-
- <strong>Example</strong>
- <code>
- title = gui.Label("My Title")
- main = gui.Container()
- #add stuff to the container...
-
- d = gui.Dialog(title,main)
- d.open()
- </code>
- """
- def __init__(self,title,main,**params):
- params.setdefault('cls','dialog')
- table.Table.__init__(self,**params)
-
-
- self.tr()
- self.td(title,align=-1,cls=self.cls+'.bar')
- clos = button.Icon(self.cls+".bar.close")
- clos.connect(CLICK,self.close,None)
- self.td(clos,align=1,cls=self.cls+'.bar')
-
- self.tr()
- self.td(main,colspan=2,cls=self.cls+".main")
-
-
-# self.tr()
-#
-#
-# t = table.Table(cls=self.cls+".bar")
-# t.tr()
-# t.td(title)
-# clos = button.Icon(self.cls+".bar.close")
-# t.td(clos,align=1)
-# clos.connect(CLICK,self.close,None)
-# self.add(t,0,0)
-#
-# main.rect.w,main.rect.h = main.resize()
-# clos.rect.w,clos.rect.h = clos.resize()
-# title.container.style.width = main.rect.w - clos.rect.w
-#
-# self.tr()
-# self.td(main,cls=self.cls+".main")
-#
-
-
-class FileDialog(Dialog):
- """A file picker dialog window.
-
- <pre>FileDialog()</pre>
- <p>Some optional parameters:</p>
- <dl>
- <dt>title_txt<dd>title text
- <dt>button_txt<dd>button text
- <dt>path<dd>initial path
- </dl>
- """
-
- def __init__(self, title_txt="File Browser", button_txt="Okay", cls="dialog", folderText = "Folder", fileText = "File", path=None, customFont = None, showCurDir = True, customWidth = 350, customHeight = 150):
-
- self.customFont = customFont
- self.showCurDir= showCurDir
- cls1 = 'filedialog'
- if not path: self.curdir = os.getcwd()
- else: self.curdir = path
- self.dir_img = basic.Image(
- pguglobals.app.theme.get(cls1+'.folder', '', 'image'))
- td_style = {'padding_left': 4,
- 'padding_right': 4,
- 'padding_top': 2,
- 'padding_bottom': 2}
- self.title = basic.Label(title_txt, cls=cls+".title.label")
- self.body = table.Table()
- self.list = area.List(width=customWidth, height=customHeight)
- self.input_dir = input.Input(customFont = self.customFont)
- self.input_file = input.Input(customFont = self.customFont)
- self._list_dir_()
- self.button_ok = button.Button(button_txt)
- self.body.tr()
- if self.showCurDir :
- self.body.td(basic.Label(folderText), style=td_style, align=-1)
- self.body.td(self.input_dir, style=td_style)
- self.body.tr()
- self.body.td(self.list, colspan=3, style=td_style)
- self.list.connect(CHANGE, self._item_select_changed_, None)
- self.button_ok.connect(CLICK, self._button_okay_clicked_, None)
- self.body.tr()
- self.body.td(basic.Label(fileText), style=td_style, align=-1)
- self.body.td(self.input_file, style=td_style)
- self.body.td(self.button_ok, style=td_style)
- self.value = None
- Dialog.__init__(self, self.title, self.body)
-
- def _list_dir_(self):
- self.input_dir.value = self.curdir
- self.input_dir.pos = len(self.curdir)
- self.input_dir.vpos = 0
- dirs = []
- files = []
- try:
- for i in os.listdir(self.curdir):
- if os.path.isdir(os.path.join(self.curdir, i)): dirs.append(i)
- else: files.append(i)
- except:
- self.input_file.value = "Opps! no access"
- #if '..' not in dirs: dirs.append('..')
- dirs.sort()
- dirs = ['..'] + dirs
-
- files.sort()
- for i in dirs:
- #item = ListItem(image=self.dir_img, text=i, value=i)
- if self.customFont == None :
- self.list.add(i,image=self.dir_img,value=i)
- else :
- label = basic.Label(i,font = self.customFont)
- self.list.add(label,image=self.dir_img,value=i)
- for i in files:
- #item = ListItem(image=None, text=i, value=i)
- if self.customFont == None :
- self.list.add(i,value=i)
- else:
- label = basic.Label(i,font = self.customFont)
- self.list.add(label,value=i)
- #self.list.resize()
- self.list.set_vertical_scroll(0)
- #self.list.repaintall()
-
-
- def _item_select_changed_(self, arg):
- self.input_file.value = self.list.value
- fname = os.path.abspath(os.path.join(self.curdir, self.input_file.value))
- if os.path.isdir(fname):
- self.input_file.value = ""
- self.curdir = fname
- self.list.clear()
- self._list_dir_()
-
-
- def _button_okay_clicked_(self, arg):
- if self.input_dir.value != self.curdir:
- if os.path.isdir(self.input_dir.value):
- self.input_file.value = ""
- self.curdir = os.path.abspath(self.input_dir.value)
- self.list.clear()
- self._list_dir_()
- else:
- self.value = os.path.join(self.curdir, self.input_file.value)
- self.send(CHANGE)
- self.close()
+++ /dev/null
-"""
-"""
-import pygame
-
-import container
-import layout
-
-class _document_widget:
- def __init__(self,w,align=None):
- #w.rect.w,w.rect.h = w.resize()
- #self.rect = w.rect
- self.widget = w
- if align != None: self.align = align
-
-class Document(container.Container):
- """A document container contains many widgets strung together in a document format. (How informative!)
-
- <pre>Document()</pre>
-
- """
- def __init__(self,**params):
- params.setdefault('cls','document')
- container.Container.__init__(self,**params)
- self.layout = layout.Layout(pygame.Rect(0,0,self.rect.w,self.rect.h))
-
- def add(self,e,align=None):
- """Add a widget.
-
- <pre>Document.add(e,align=None)</pre>
-
- <dl>
- <dt>e<dd>widget
- <dt>align<dd>alignment (None,-1,0,1)
- </dl>
- """
- dw = _document_widget(e,align)
- self.layout.add(dw)
- e.container = self
- e._c_dw = dw
- self.widgets.append(e)
- self.chsize()
-
- def remove(self,e):
- self.layout._widgets.remove(e._c_dw)
- self.widgets.remove(e)
- self.chsize()
-
-
- def block(self,align):
- """Start a new block.
-
- <pre>Document.block(align)</pre>
-
- <dl>
- <dt>align<dd>alignment of block (-1,0,1)
- </dl>
- """
- self.layout.add(align)
-
- def space(self,e):
- """Add a spacer.
-
- <pre>Document.space(e)</pre>
-
- <dl>
- <dt>e<dd>a (w,h) size for the spacer
- </dl>
- """
- self.layout.add(e)
-
- def br(self,height):
- """Add a line break.
-
- <pre>Document.br(height)</pre>
-
- <dl>
- <dt>height<dd>height of line break
- </dl>
- """
- self.layout.add((0,height))
-
- def resize(self,width=None,height=None):
- if self.style.width: width = self.style.width
- if self.style.height: height = self.style.height
-
- for w in self.widgets:
- w.rect.w,w.rect.h = w.resize()
-
- if (width != None and w.rect.w > width) or (height != None and w.rect.h > height):
- w.rect.w,w.rect.h = w.resize(width,height)
-
- dw = w._c_dw
- dw.rect = pygame.Rect(0,0,w.rect.w,w.rect.h)
-
- if width == None: width = 65535
- self.layout.rect = pygame.Rect(0,0,width,0)
- self.layout.resize()
-
- _max_w = 0
-
- for w in self.widgets:
- #xt,xl,xb,xr = w.getspacing()
- dw = w._c_dw
- w.style.x,w.style.y,w.rect.w,w.rect.h = dw.rect.x,dw.rect.y,dw.rect.w,dw.rect.h
- #w.resize()
- w.rect.x,w.rect.y = w.style.x,w.style.y
- _max_w = max(_max_w,w.rect.right)
-
- #self.rect.w = _max_w #self.layout.rect.w
- #self.rect.h = self.layout.rect.h
- #print 'document',_max_w,self.layout.rect.h
- return _max_w,self.layout.rect.h
+++ /dev/null
-"""
-"""
-import widget
-
-class Form(widget.Widget):
- """A form that automatically will contain all named widgets.
-
- <p>After a form is created, all named widget that are subsequently created are added
- to that form. You may use dict style access to access named widgets.</p>
-
- <pre>Form()</pre>
-
- <strong>Example</strong>
- <code>
- f = gui.Form()
-
- w = gui.Input("Phil",name="firstname")
- w = gui.Input("Hassey",name="lastname")
-
- print f.results()
- print ''
- print f.items()
- print ''
- print f['firstname'].value
- print f['lastname'].value
- </code>
- """
-
- def __init__(self):
- widget.Widget.__init__(self,decorate=False)
- self._elist = []
- self._emap = {}
- self._dirty = 0
- Form.form = self
-
- def add(self,e,name=None,value=None):
- if name != None: e.name = name
- if value != None: e.value = value
- self._elist.append(e)
- self._dirty = 1
-
- def _clean(self):
- for e in self._elist[:]:
- if not hasattr(e,'name') or e.name == None:
- self._elist.remove(e)
- self._emap = {}
- for e in self._elist:
- self._emap[e.name] = e
- self._dirty = 0
-
- def __getitem__(self,k):
- if self._dirty: self._clean()
- return self._emap[k]
-
- def __contains__(self,k):
- if self._dirty: self._clean()
- if k in self._emap: return True
- return False
-
- def results(self):
- """Return a dict of name => values.
-
- <pre>Form.results(): return dict</pre>
- """
- if self._dirty: self._clean()
- r = {}
- for e in self._elist:
- r[e.name] = e.value
- return r
-
- def items(self):
- """Return a list of name, value keys.
-
- <pre>Form.items(): return list</pre>
- """
- return self.results().items()
-
- #def start(self):
- # Object.start(self,-1)
+++ /dev/null
-"""
-"""
-from const import *
-import widget
-
-class Group(widget.Widget):
- """An object for grouping together Form elements.
-
- <pre>Group(name=None,value=None)</pre>
-
- <dl>
- <dt>name<dd>name as used in the Form
- <dt>value<dd>values that are currently selected in the group
- </dl>
-
- <p>See [[gui-button]] for several examples.</p>
-
- <p>When the value changes, an <tt>gui.CHANGE</tt> event is sent.
- Although note, that when the value is a list, it may have to be sent by hand via
- <tt>g.send(gui.CHANGE)</tt></p>
- """
-
- def __init__(self,name=None,value=None):
- widget.Widget.__init__(self,name=name,value=value)
- self.widgets = []
-
- def add(self,w):
- """Add a widget to this group.
-
- <pre>Group.add(w)</pre>
- """
- self.widgets.append(w)
-
- def __setattr__(self,k,v):
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k] = v
- if k == 'value' and _v != NOATTR and _v != v:
- self._change()
-
- def _change(self):
- self.send(CHANGE)
- for w in self.widgets:
- w.repaint()
+++ /dev/null
-"""
-"""
-import pygame
-from pygame.locals import *
-
-from const import *
-import widget
-
-class Input(widget.Widget):
- """A single line text input.
-
- <pre>Input(value="",size=20)</pre>
-
- <dl>
- <dt>value<dd>initial text
- <dt>size<dd>size for the text box, in characters
- </dl>
-
- <strong>Example</strong>
- <code>
- w = Input(value="Cuzco the Goat",size=20)
-
- w = Input("Marbles")
- </code>
-
- """
- def __init__(self,value="",size=20,customFont = None,**params):
- params.setdefault('cls','input')
- widget.Widget.__init__(self,**params)
- self.value = value
- self.pos = len(str(value))
- self.vpos = 0
- if customFont != None:
- self.font = customFont
- else:
- self.font = self.style.font
- w,h = self.font.size("e"*size)
- if not self.style.height: self.style.height = h
- if not self.style.width: self.style.width = w
- #self.style.height = max(self.style.height,h)
- #self.style.width = max(self.style.width,w)
- #self.rect.w=w+self.style.padding_left+self.style.padding_right;
- #self.rect.h=h+self.style.padding_top+self.style.padding_bottom;
-
- def paint(self,s):
-
- r = pygame.Rect(0,0,self.rect.w,self.rect.h)
-
- cs = 2 #NOTE: should be in a style
-
- w,h = self.font.size(self.value[0:self.pos])
- x = w-self.vpos
- if x < 0: self.vpos -= -x
- if x+cs > s.get_width(): self.vpos += x+cs-s.get_width()
-
- s.blit(self.font.render(self.value, 1, self.style.color),(-self.vpos,0))
-
- if self.container.myfocus is self:
- w,h = self.font.size(self.value[0:self.pos])
- r.x = w-self.vpos
- r.w = cs
- r.h = h
- s.fill(self.style.color,r)
-
- def _setvalue(self,v):
- self.__dict__['value'] = v
- self.send(CHANGE)
-
- def event(self,e):
- used = None
- if e.type == KEYDOWN:
- if e.key == K_BACKSPACE:
- if self.pos:
- self._setvalue(self.value[:self.pos-1] + self.value[self.pos:])
- self.pos -= 1
- elif e.key == K_DELETE:
- if len(self.value) > self.pos:
- self._setvalue(self.value[:self.pos] + self.value[self.pos+1:])
- elif e.key == K_HOME:
- self.pos = 0
- elif e.key == K_END:
- self.pos = len(self.value)
- elif e.key == K_LEFT:
- if self.pos > 0: self.pos -= 1
- used = True
- elif e.key == K_RIGHT:
- if self.pos < len(self.value): self.pos += 1
- used = True
- elif e.key == K_RETURN:
- self.next()
- elif e.key == K_TAB:
- pass
- else:
- #c = str(e.unicode)
- try:
- c = (e.unicode).encode('latin-1')
- if c:
- self._setvalue(self.value[:self.pos] + c + self.value[self.pos:])
- self.pos += 1
- except: #ignore weird characters
- pass
- self.repaint()
- elif e.type == FOCUS:
- self.repaint()
- elif e.type == BLUR:
- self.repaint()
-
- self.pcls = ""
- if self.container.myfocus is self: self.pcls = "focus"
-
- return used
-
- def __setattr__(self,k,v):
- if k == 'value':
- if v == None: v = ''
- v = str(v)
- self.pos = len(v)
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
-
-class Password(Input):
- """A password input, text is *-ed out.
-
- <pre>Password(value="",size=20)</pre>
-
- <dl>
- <dt>value<dd>initial text
- <dt>size<dd>size for the text box, in characters
- </dl>
-
- <strong>Example</strong>
- <code>
- w = Password(value="password",size=20)
-
- w = Password("53[r3+")
- </code>
-
- """
-
- def paint(self,s):
- hidden="*"
- show=len(self.value)*hidden
-
- #print "self.value:",self.value
-
- if self.pos == None: self.pos = len(self.value)
-
- r = pygame.Rect(0,0,self.rect.w,self.rect.h)
-
- cs = 2 #NOTE: should be in a style
-
- w,h = self.font.size(show)
- x = w-self.vpos
- if x < 0: self.vpos -= -x
- if x+cs > s.get_width(): self.vpos += x+cs-s.get_width()
-
- s.blit(self.font.render(show, 1, self.style.color),(-self.vpos,0))
-
- if self.container.myfocus is self:
- #w,h = self.font.size(self.value[0:self.pos])
- w,h = self.font.size(show[0:self.pos])
- r.x = w-self.vpos
- r.w = cs
- r.h = h
- s.fill(self.style.color,r)
-
+++ /dev/null
-"""
-"""
-import pygame
-from pygame.locals import *
-
-from const import *
-import widget
-
-class Keysym(widget.Widget):
- """A keysym input.
-
- <p>This widget records the keysym of the key pressed while this widget is in focus.</p>
-
- <pre>Keysym(value=None)</pre>
-
- <dl>
- <dt>value<dd>initial keysym, see <a href="http://www.pygame.org/docs/ref/key.html">pygame keysyms</a> </dl>
-
- <strong>Example</strong>
- <code>
- w = Input(value=pygame.locals.K_g)
-
- w = Input(pygame.locals.K_g)
-
- w = Input()
- </code>
-
- """
-
- def __init__(self,value=None,**params):
- params.setdefault('cls','keysym')
- widget.Widget.__init__(self,**params)
- self.value = value
-
- self.font = self.style.font
- w,h = self.font.size("Right Super") #"Right Shift")
- self.style.width,self.style.height = w,h
- #self.rect.w=w+self.style.padding_left+self.style.padding_right
- #self.rect.h=h+self.style.padding_top+self.style.padding_bottom
-
- def event(self,e):
- used = None
- if e.type == FOCUS or e.type == BLUR: self.repaint()
- elif e.type == KEYDOWN:
- if e.key != K_TAB:
- self.value = e.key
- self.repaint()
- self.send(CHANGE)
- used = True
- self.next()
- self.pcls = ""
- if self.container.myfocus is self: self.pcls = "focus"
- return used
-
- def paint(self,s):
- r = pygame.rect.Rect(0,0,self.rect.w,self.rect.h)
- #render_box(s,self.style.background,r)
- if self.value == None: return
- name = ""
- for p in pygame.key.name(self.value).split(): name += p.capitalize()+" "
- #r.x = self.style.padding_left;
- #r.y = self.style.padding_bottom;
- s.blit(self.style.font.render(name, 1, self.style.color), r)
-
- def __setattr__(self,k,v):
- if k == 'value' and v != None:
- v = int(v)
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
+++ /dev/null
-"""document layout engine."""
-class Layout:
- """the document layout engine
-
- .widgets -- elements are kept in this list. read-only, use add to add items to it.
- """
-
- def __init__(self,rect=None):
- """initialize the object with the size of the box."""
- self._widgets = []
- self.rect = rect
-
- def add(self,e):
- """add a document element to the layout.
-
- a document element may be
- - a tuple (w,h) if it is a whitespace element
- - a tuple (0,h) if it is a linebreak element
- - an integer -1,0,1 if it is a command to start a new block of elements that are aligned either left,center, or right.
- - an object with a .rect (for size) -- such as a word element
- - an object with a .rect (for size) and .align -- such as an image element
- """
-
- self._widgets.append(e)
-
-
- def resize(self):
- """resize the layout
- this method recalculates the position of all document elements
- after they have been added to the document. .rect.x,y will be updated for all
- objects.
- """
- self.init()
- self.widgets = []
- for e in self._widgets:
- if type(e) is tuple and e[0] != 0:
- self.do_space(e)
- elif type(e) is tuple and e[0] == 0:
- self.do_br(e[1])
- elif type(e) is int:
- self.do_block(align=e)
- elif hasattr(e,'align'):
- self.do_align(e)
- else:
- self.do_item(e)
- self.line()
- self.rect.h = max(self.y,self.left_bottom,self.right_bottom)
-
- def init(self):
- self.x,self.y = self.rect.x,self.rect.y
- self.left = self.rect.left
- self.right = self.rect.right
- self.left_bottom = 0
- self.right_bottom = 0
- self.y = self.rect.y
- self.x = self.rect.x
- self.h = 0
-
- self.items = []
- self.align = -1
-
- def getleft(self):
- if self.y > self.left_bottom:
- self.left = self.rect.left
- return self.left
-
- def getright(self):
- if self.y > self.right_bottom:
- self.right = self.rect.right
- return self.right
-
- def do_br(self,h):
- self.line()
- self.h = h
-
- def do_block(self,align=-1):
- self.line()
- self.align = align
-
- def do_align(self,e):
- align = e.align
- ox,oy,oh = self.x,self.y,self.h
- w,h = e.rect.w,e.rect.h
-
- if align == 0:
- self.line()
- self.x = self.rect.left + (self.rect.width-w)/2
- self.fit = 0
- elif align == -1:
- self.line()
- self.y = max(self.left_bottom,self.y + self.h)
- self.h = 0
- self.x = self.rect.left
- elif align == 1:
- self.line()
- self.y = max(self.right_bottom,self.y + self.h)
- self.h = 0
- self.x = self.rect.left + (self.rect.width-w)
-
- e.rect.x,e.rect.y = self.x,self.y
-
- self.x = self.x + w
- self.y = self.y
-
- if align == 0:
- self.h = max(self.h,h)
- self.y = self.y + self.h
- self.x = self.getleft()
- self.h = 0
- elif align == -1:
- self.left = self.x
- self.left_bottom = self.y + h
- self.x,self.y,self.h = ox + w,oy,oh
- elif align == 1:
- self.right = self.x - w
- self.right_bottom = self.y + h
- self.x,self.y,self.h = ox,oy,oh
-
- self.widgets.append(e)
-
- def do_space(self,e):
- w,h = e
- if self.x+w >= self.getright():
- self.line()
- else:
- self.items.append(e)
- self.h = max(self.h,h)
- self.x += w
-
- def do_item(self,e):
- w,h = e.rect.w,e.rect.h
- if self.x+w >= self.getright():
- self.line()
- self.items.append(e)
- self.h = max(self.h,h)
- self.x += w
-
- def line(self):
- x1 = self.getleft()
- x2 = self.getright()
- align = self.align
- y = self.y
-
- if len(self.items) != 0 and type(self.items[-1]) == tuple:
- del self.items[-1]
-
- w = 0
- for e in self.items:
- if type(e) == tuple: w += e[0]
- else: w += e.rect.w
-
- if align == -1: x = x1
- elif align == 0:
- x = x1 + ((x2-x1)-w)/2
- self.fit = 0
- elif align == 1: x = x2 - w
-
- for e in self.items:
- if type(e) == tuple: x += e[0]
- else:
- e.rect.x,e.rect.y = x,y
- self.widgets.append(e)
- x += e.rect.w
-
- self.items = []
- self.y = self.y + self.h
- self.x = self.getleft()
- self.h = 0
-
-
-
-# vim: set filetype=python sts=4 sw=4 noet si :
+++ /dev/null
-"""
-"""
-from const import *
-import table
-import basic, button
-
-class _Menu_Options(table.Table):
- def __init__(self,menu,**params):
- table.Table.__init__(self,**params)
-
- self.menu = menu
-
- def event(self,e):
- handled = False
- arect = self.get_abs_rect()
-
- if e.type == MOUSEMOTION:
- abspos = e.pos[0]+arect.x,e.pos[1]+arect.y
- for w in self.menu.container.widgets:
- if not w is self.menu:
- mrect = w.get_abs_rect()
- if mrect.collidepoint(abspos):
- self.menu._close(None)
- w._open(None)
- handled = True
-
- if not handled: table.Table.event(self,e)
-
-class _Menu(button.Button):
- def __init__(self,parent,widget=None,**params): #TODO widget= could conflict with module widget
- params.setdefault('cls','menu')
- button.Button.__init__(self,widget,**params)
-
- self.parent = parent
-
- self._cls = self.cls
- self.options = _Menu_Options(self, cls=self.cls+".options")
-
- self.connect(CLICK,self._open,None)
-
- self.pos = 0
-
- def _open(self,value):
- self.parent.value = self
- self.pcls = 'down'
-
- self.repaint()
- self.container.open(self.options,self.rect.x,self.rect.bottom)
- self.options.connect(BLUR,self._close,None)
- self.options.focus()
- self.repaint()
-
- def _pass(self,value):
- pass
-
- def _close(self,value):
- self.pcls = ''
- self.parent.value = None
- self.repaint()
- self.options.close()
-
- def _value(self,value):
- self._close(None)
- if value['fnc'] != None:
- value['fnc'](value['value'])
-
- def event(self,e):
- button.Button.event(self,e)
-
- if self.parent.value == self:
- self.pcls = 'down'
-
- def add(self,w,fnc=None,value=None):
- w.style.align = -1
- b = button.Button(w,cls=self.cls+".option")
- b.connect(CLICK,self._value,{'fnc':fnc,'value':value})
-
- self.options.tr()
- self.options.add(b)
-
- return b
-
-class Menus(table.Table):
- """A drop down menu bar.
-
- <pre>Menus(data)</pre>
-
- <dl>
- <dt>data<dd>Menu data, a list of (path,fnc,value), see example below
- </dl>
-
- <strong>Example</strong>
- <code>
- data = [
- ('File/Save',fnc_save,None),
- ('File/New',fnc_new,None),
- ('Edit/Copy',fnc_copy,None),
- ('Edit/Cut',fnc_cut,None),
- ('Help/About',fnc_help,help_about_content),
- ('Help/Reference',fnc_help,help_reference_content),
- ]
- w = Menus(data)
- """
-
- def __init__(self,data,menu_cls='menu',**params):
- params.setdefault('cls','menus')
- table.Table.__init__(self,**params)
-
- self.value = None
-
- n,m,mt = 0,None,None
- for path,cmd,value in data:
- parts = path.split("/")
- if parts[0] != mt:
- mt = parts[0]
- m = _Menu(self,basic.Label(mt,cls=menu_cls+".label"),cls=menu_cls)
- self.add(m,n,0)
- n += 1
- m.add(basic.Label(parts[1],cls=m.cls+".option.label"),cmd,value)
+++ /dev/null
-from const import *
-import widget
-import pguglobals
-
-class ProgressBar(widget.Widget):
- """A progress bar.
-
- <pre>ProgressBar(value,min,max)</pre>
-
- <dl>
- <dt>value<dd>starting value
- <dt>min<dd>minimum value rendered on the screen (usually 0)
- <dt>max<dd>maximum value
- </dl>
-
- <strong>Example</strong>
- <code>
- w = gui.ProgressBar(0,0,100)
- w.value = 25
- </code>
- """
-
- def __init__(self,value,min,max,**params):
- params.setdefault('cls','progressbar')
- widget.Widget.__init__(self,**params)
- self.min,self.max,self.value = min,max,value
-
- def paint(self,s):
- r = pygame.rect.Rect(0,0,self.rect.w,self.rect.h)
- r.w = r.w*(self.value-self.min)/(self.max-self.min)
- self.bar = r
- pguglobals.app.theme.render(s,self.style.bar,r)
-
- def __setattr__(self,k,v):
- if k == 'value':
- v = int(v)
- v = max(v,self.min)
- v = min(v,self.max)
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
+++ /dev/null
-# pguglobals.py - A place to stick global variables that need to be accessed
-# from other modules. To avoid problems with circular imports
-# this module should not import any other PGU module.
-
-# A global reference to the application instance (App class)
-app = None
-
+++ /dev/null
-"""
-"""
-
-import traceback
-
-from const import *
-from button import Button
-from basic import Label, Image
-from table import Table
-
-class Select(Table):
- """A select input.
-
- <pre>Select(value=None)</pre>
-
- <dl>
- <dt>value<dd>initial value
- </dl>
-
- <strong>Example</strong>
- <code>
- w = Select(value="goats")
- w.add("Cats","cats")
- w.add("Goats","goats")
- w.add("Dogs","Dogs")
-
- w.value = 'dogs' #changes the value from goats to dogs
- </code>
-
- """
-
- # The drop-down arrow button for the selection widget
- top_arrow = None
- # A button displaying the currently selected item
- top_selection = None
- # The first option added to the selector
- firstOption = None
- # The PGU table of options
- options = None
-
- def __init__(self,value=None,**params):
- params.setdefault('cls','select')
- Table.__init__(self,**params)
-
- label = Label(" ",cls=self.cls+".option.label")
- self.top_selected = Button(label, cls=self.cls+".selected")
- Table.add(self,self.top_selected) #,hexpand=1,vexpand=1)#,0,0)
-
- self.top_arrow = Button(Image(self.style.arrow), cls=self.cls+".arrow")
- Table.add(self,self.top_arrow) #,hexpand=1,vexpand=1) #,1,0)
-
- self.options = Table(cls=self.cls+".options")
- self.options.connect(BLUR,self._close,None)
- self.options.name = "pulldown-table"
-
- self.values = []
- self.value = value
-
- def resize(self,width=None,height=None):
- max_w,max_h = 0,0
- for w in self.options.widgets:
- w.rect.w,w.rect.h = w.resize()
- max_w,max_h = max(max_w,w.rect.w),max(max_h,w.rect.h)
-
- #xt,xr,xb,xl = self.top_selected.getspacing()
- self.top_selected.style.width = max_w #+ xl + xr
- self.top_selected.style.height = max_h #+ xt + xb
-
- self.top_arrow.connect(CLICK,self._open,None)
- self.top_selected.connect(CLICK,self._open,None)
-
- w,h = Table.resize(self,width,height)
-
- self.options.style.width = w
- #HACK: sort of, but not a big one..
- self.options.resize()
-
- return w,h
-
- def _open(self,value):
- opts = self.options
-
- opts.rect.w, opts.rect.h = opts.resize()
-
-# y = self.rect.y
-# c = self.container
-# while hasattr(c, 'container'):
-# y += c.rect.y
-# if (not c.container):
-# break
-# c = c.container
-
-# if y + self.rect.h + opts.rect.h <= c.rect.h: #down
-# dy = self.rect.y + self.rect.h
-# else: #up
-# dy = self.rect.y - self.rect.h
-
- opts.rect.w, opts.rect.h = opts.resize()
-
- # TODO - make sure there is enough space to open down
- # ...
- yp = self.rect.bottom-1
-
- self.container.open(opts, self.rect.x, yp)
- self.firstOption.focus()
-
- # TODO - this is a hack
- for opt in self.options.widgets:
- opt.repaint()
-
- def _close(self,value):
- self.options.close()
- self.top_selected.focus()
-
- def _setvalue(self,value):
- self.value = value._value
- if hasattr(self,'container'):
- #self.chsize()
- #HACK: improper use of resize()
- #self.resize() #to recenter the new value, etc.
- pass
- # #self._resize()
-
- self._close(None)
- #self.repaint() #this will happen anyways
-
-
-
- def __setattr__(self,k,v):
- mywidget = None
- if k == 'value':
- for w in self.values:
- if w._value == v:
- mywidget = w
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
- if k == 'value':
- if not mywidget:
- mywidget = Label(" ",cls=self.cls+".option.label")
- self.top_selected.value = mywidget
-
- def add(self,w,value=None):
- """Add a widget, value item to the Select.
-
- <pre>Select.add(widget,value=None)</pre>
-
- <dl>
- <dt>widget<dd>Widget or string to represent the item
- <dt>value<dd>value for this item
- </dl>
-
- <strong>Example</strong>
- <code>
- w = Select()
- w.add("Goat") #adds a Label
- w.add("Goat","goat") #adds a Label with the value goat
- w.add(gui.Label("Cuzco"),"goat") #adds a Label with value goat
- </code>
- """
-
- if type(w) == str: w = Label(w,cls=self.cls+".option.label")
-
- w.style.align = -1
- btn = Button(w,cls=self.cls+".option")
- btn.connect(CLICK,self._setvalue,w)
-
- self.options.tr()
- self.options.add(btn)
-
- if (not self.firstOption):
- self.firstOption = btn
-
- if value != None: w._value = value
- else: w._value = w
- if self.value == w._value:
- self.top_selected.value = w
- self.values.append(w)
+++ /dev/null
-"""All sliders and scroll bar widgets have the same parameters.
-
-<pre>Slider(value,min,max,size)</pre>
-<dl>
-<dt>value<dd>initial value
-<dt>min<dd>minimum value
-<dt>max<dd>maximum value
-<dt>size<dd>size of bar in pixels
-</dl>
-"""
-import pygame
-from pygame.locals import *
-
-from const import *
-import widget
-import table
-import basic
-import pguglobals
-
-_SLIDER_HORIZONTAL = 0
-_SLIDER_VERTICAL = 1
-
-class _slider(widget.Widget):
- def __init__(self,value,orient,min,max,size,step=1,**params):
- params.setdefault('cls','slider')
- widget.Widget.__init__(self,**params)
- self.min,self.max,self.value,self.orient,self.size,self.step = min,max,value,orient,size,step
-
-
- def paint(self,s):
-
- self.value = self.value
- r = pygame.rect.Rect(0,0,self.style.width,self.style.height)
- if self.orient == _SLIDER_HORIZONTAL:
- r.x = (self.value-self.min) * (r.w-self.size) / max(1,self.max-self.min);
- r.w = self.size;
- else:
- r.y = (self.value-self.min) * (r.h-self.size) / max(1,self.max-self.min);
- r.h = self.size;
-
- self.bar = r
-
- pguglobals.app.theme.render(s,self.style.bar,r)
-
- def event(self,e):
- used = None
- r = pygame.rect.Rect(0,0,self.style.width,self.style.height)
- adj = 0
- if e.type == ENTER: self.repaint()
- elif e.type == EXIT: self.repaint()
- elif e.type == MOUSEBUTTONDOWN:
- if self.bar.collidepoint(e.pos):
- self.grab = e.pos[0],e.pos[1]
- self.grab_value = self.value
- else:
- x,y,adj = e.pos[0],e.pos[1],1
- self.grab = None
- self.repaint()
- elif e.type == MOUSEBUTTONUP:
- #x,y,adj = e.pos[0],e.pos[1],1
- self.repaint()
- elif e.type == MOUSEMOTION:
- if 1 in e.buttons and self.container.myfocus is self:
- if self.grab != None:
- rel = e.pos[0]-self.grab[0],e.pos[1]-self.grab[1]
- if self.orient == _SLIDER_HORIZONTAL:
- d = (r.w - self.size)
- if d != 0: self.value = self.grab_value + ((self.max-self.min) * rel[0] / d)
- else:
- d = (r.h - self.size)
- if d != 0: self.value = self.grab_value + ((self.max-self.min) * rel[1] / d)
- else:
- x,y,adj = e.pos[0],e.pos[1],1
-
- elif e.type is KEYDOWN:
- if self.orient == _SLIDER_HORIZONTAL and e.key == K_LEFT:
- self.value -= self.step
- used = True
- elif self.orient == _SLIDER_HORIZONTAL and e.key == K_RIGHT:
- self.value += self.step
- used = True
- elif self.orient == _SLIDER_VERTICAL and e.key == K_UP:
- self.value -= self.step
- used = True
- elif self.orient == _SLIDER_VERTICAL and e.key == K_DOWN:
- self.value += self.step
- used = True
-
- if adj:
- if self.orient == _SLIDER_HORIZONTAL:
- d = self.size/2 - (r.w/(self.max-self.min+1))/2
- self.value = (x-d) * (self.max-self.min) / (r.w-self.size+1) + self.min
- else:
- d = self.size/2 - (r.h/(self.max-self.min+1))/2
- self.value = (y-d) * (self.max-self.min) / (r.h-self.size+1) + self.min
-
- self.pcls = ""
- if self.container.myhover is self: self.pcls = "hover"
- if (self.container.myfocus is self and 1 in pygame.mouse.get_pressed()): self.pcls = "down"
-
- return used
-
-
- def __setattr__(self,k,v):
- if k == 'value':
- v = int(v)
- v = max(v,self.min)
- v = min(v,self.max)
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
-
- if hasattr(self,'size'):
- sz = min(self.size,max(self.style.width,self.style.height))
- sz = max(sz,min(self.style.width,self.style.height))
- self.__dict__['size'] = sz
-
- if hasattr(self,'max') and hasattr(self,'min'):
- if self.max < self.min: self.max = self.min
-
-class VSlider(_slider):
- """A verticle slider.
-
- <pre>VSlider(value,min,max,size)</pre>
- """
- def __init__(self,value,min,max,size,step=1,**params):
- params.setdefault('cls','vslider')
- _slider.__init__(self,value,_SLIDER_VERTICAL,min,max,size,step,**params)
-
-class HSlider(_slider):
- """A horizontal slider.
-
- <pre>HSlider(value,min,max,size)</pre>
- """
- def __init__(self,value,min,max,size,step=1,**params):
- params.setdefault('cls','hslider')
- _slider.__init__(self,value,_SLIDER_HORIZONTAL,min,max,size,step,**params)
-
-class HScrollBar(table.Table):
- """A horizontal scroll bar.
-
- <pre>HScrollBar(value,min,max,size,step=1)</pre>
- """
- def __init__(self,value,min,max,size,step=1,**params):
- params.setdefault('cls','hscrollbar')
-
- table.Table.__init__(self,**params)
-
- self.slider = _slider(value,_SLIDER_HORIZONTAL,min,max,size,step=step,cls=self.cls+'.slider')
-
- self.minus = basic.Image(self.style.minus)
- self.minus.connect(MOUSEBUTTONDOWN,self._click,-1)
- self.slider.connect(CHANGE,self.send,CHANGE)
-
- self.minus2 = basic.Image(self.style.minus)
- self.minus2.connect(MOUSEBUTTONDOWN,self._click,-1)
-
- self.plus = basic.Image(self.style.plus)
- self.plus.connect(MOUSEBUTTONDOWN,self._click,1)
-
- self.size = size
-
- def _click(self,value):
- self.slider.value += self.slider.step*value
-
- def resize(self,width=None,height=None):
- self.clear()
- self.tr()
-
- w = self.style.width
- h = self.slider.style.height
- ww = 0
-
- if w > (h*2 + self.minus.style.width+self.plus.style.width):
- self.td(self.minus)
- ww += self.minus.style.width
-
- self.td(self.slider)
-
- if w > (h*2 + self.minus.style.width+self.minus2.style.width+self.plus.style.width):
- self.td(self.minus2)
- ww += self.minus2.style.width
-
- if w > (h*2 + self.minus.style.width+self.plus.style.width):
- self.td(self.plus)
- ww += self.plus.style.width
-
-
- #HACK: handle theme sizing properly
- xt,xr,xb,xl = pguglobals.app.theme.getspacing(self.slider)
- ww += xr+xl
-
- self.slider.style.width = self.style.width - ww
- setattr(self.slider,'size',self.size * self.slider.style.width / max(1,self.style.width))
- return table.Table.resize(self,width,height)
-
-
- def __setattr__(self,k,v):
- if k in ('min','max','value','step'):
- return setattr(self.slider,k,v)
- self.__dict__[k]=v
-
- def __getattr__(self,k):
- if k in ('min','max','value','step'):
- return getattr(self.slider,k)
- return table.Table.__getattr__(self,k) #self.__dict__[k]
-
-class VScrollBar(table.Table):
- """A vertical scroll bar.
-
- <pre>VScrollBar(value,min,max,size,step=1)</pre>
- """
- def __init__(self,value,min,max,size,step=1,**params):
- params.setdefault('cls','vscrollbar')
-
- table.Table.__init__(self,**params)
-
- self.minus = basic.Image(self.style.minus)
- self.minus.connect(MOUSEBUTTONDOWN,self._click,-1)
-
- self.minus2 = basic.Image(self.style.minus)
- self.minus2.connect(MOUSEBUTTONDOWN,self._click,-1)
-
- self.plus = basic.Image(self.style.plus)
- self.plus.connect(MOUSEBUTTONDOWN,self._click,1)
-
- self.slider = _slider(value,_SLIDER_VERTICAL,min,max,size,step=step,cls=self.cls+'.slider')
- self.slider.connect(CHANGE,self.send,CHANGE)
-
- self.size = size
-
- def _click(self,value):
- self.slider.value += self.slider.step*value
-
- def resize(self,width=None,height=None):
- self.clear()
-
- h = self.style.height
- w = self.slider.style.width
- hh = 0
-
- if h > (w*2 + self.minus.style.height+self.plus.style.height):
- self.tr()
- self.td(self.minus)
- hh += self.minus.style.height
-
- self.tr()
- self.td(self.slider)
-
- if h > (w*2 + self.minus.style.height+self.minus2.style.height+self.plus.style.height):
- self.tr()
- self.td(self.minus2)
- hh += self.minus2.style.height
-
- if h > (w*2 + self.minus.style.height+self.plus.style.height):
- self.tr()
- self.td(self.plus)
- hh += self.plus.style.height
-
-
- #HACK: handle theme sizing properly
- xt,xr,xb,xl = pguglobals.app.theme.getspacing(self.slider)
- hh += xt+xb
-
- self.slider.style.height = self.style.height - hh
- setattr(self.slider,'size',self.size * self.slider.style.height / max(1,self.style.height))
- return table.Table.resize(self,width,height)
-
- def __setattr__(self,k,v):
- if k in ('min','max','value','step'):
- return setattr(self.slider,k,v)
- self.__dict__[k]=v
-
- def __getattr__(self,k):
- if k in ('min','max','value','step'):
- return getattr(self.slider,k)
- return table.Table.__getattr__(self,k)
+++ /dev/null
-"""
-"""
-
-import pguglobals
-
-class Style:
- """The class used by widget for the widget.style
-
- <p>This object is used mainly as a dictionary, accessed via <tt>widget.style.attr</tt>, as opposed to
- <tt>widget.style['attr']</tt>. It automatically grabs information from the theme via <tt>value = theme.get(widget.cls,widget.pcls,attr)</tt>.</p>
-
- """
- def __init__(self,o,dict):
- self.obj = o
- for k,v in dict.items(): self.__dict__[k]=v
- self._cache = {}
-
- def __getattr__(self,k):
- key = self.obj.cls,self.obj.pcls,k
- if key not in self._cache:
- self._cache[key] = Style_get(self.obj.cls,self.obj.pcls,k)
- v = self._cache[key]
- if k in (
- 'border_top','border_right','border_bottom','border_left',
- 'padding_top','padding_right','padding_bottom','padding_left',
- 'margin_top','margin_right','margin_bottom','margin_left',
- 'align','valign','width','height',
- ): self.__dict__[k] = v
- return v
-
- def __setattr__(self,k,v):
- self.__dict__[k] = v
-
-
-Style_cache = {}
-def Style_get(cls,pcls,k):
- key = cls,pcls,k
- if key not in Style_cache:
- Style_cache[key] = pguglobals.app.theme.get(cls,pcls,k)
- return Style_cache[key]
-
+++ /dev/null
-"""
-"""
-import pygame
-
-def subsurface(s,r):
- """Return the subsurface of a surface, with some help, checks.
-
- <pre>subsurface(s,r): return surface</pre>
- """
- r = pygame.Rect(r)
- if r.x < 0 or r.y < 0:
- raise "gui.subsurface: %d %d %s"%(s.get_width(),s.get_height(),r)
- w,h = s.get_width(),s.get_height()
- if r.right > w:
- r.w -= r.right-w
- if r.bottom > h:
- r.h -= r.bottom-h
- assert(r.w >= 0 and r.h >= 0)
- return s.subsurface(r)
-
-class ProxySurface:
- """
- A surface-like object which smartly handle out-of-area blitting.
-
- <pre>ProxySurface(parent, rect, real_surface=None, offset=(0, 0))</pre>
-
- <p>only one of parent and real_surface should be supplied (non None)</p>
- <dl>
- <dt>parent<dd>a ProxySurface object
- <dt>real_surface<dd>a pygame Surface object
- </dl>
-
- <strong>Variables</strong>
-
- <dl>
- <dt>mysubsurface<dd>a real and valid pygame.Surface object to be used
- for blitting.
- <dt>x, y<dd>if the proxy surface is lefter or higher than the parent,
- x, y hold the diffs.
- <dt>offset<dd>an optional feature which let you scroll the whole blitted
- content.
- </dl>
- """
- def __init__(self, parent, rect, real_surface, offset=(0, 0)):
- self.offset = offset
- self.x = self.y = 0
- if rect.x < 0: self.x = rect.x
- if rect.y < 0: self.y = rect.y
- self.real_surface = real_surface
- if real_surface == None:
- self.mysubsurface = parent.mysubsurface.subsurface(
- parent.mysubsurface.get_rect().clip(rect))
- else:
- self.mysubsurface = real_surface.subsurface(
- real_surface.get_rect().clip(rect))
- rect.topleft = (0, 0)
- self.rect = rect
-
- def blit(self, s, pos, rect=None):
- if rect == None: rect = s.get_rect()
- pos = (pos[0] + self.offset[0] + self.x, pos[1] + self.offset[1] + self.y)
- self.mysubsurface.blit(s, pos, rect)
-
- def subsurface(self, rect):
- r = pygame.Rect(rect).move(self.offset[0] + self.x,
- self.offset[1] + self.y)
- return ProxySurface(self, r, self.real_surface)
-
- def fill(self, color, rect=None):
- if rect != None: self.mysubsurface.fill(color, rect)
- else: self.mysubsurface.fill(color)
- def get_rect(self): return self.rect
- def get_width(self): return self.rect[2]
- def get_height(self): return self.rect[3]
- def get_abs_offset(): return self.rect[:2]
- def get_abs_parent(): return self.mysubsurface.get_abs_parent()
- def set_clip(self, rect=None):
- if rect == None: self.mysubsurface.set_clip()
- else:
- rect = [rect[0] + self.offset[0] + self.x, rect[1] + self.offset[0] + self.y, rect[2], rect[3]]
- self.mysubsurface.set_clip(rect)
-
-
-
-
-
-
-class xProxySurface:
- """
- A surface-like object which smartly handle out-of-area blitting.
-
- <pre>ProxySurface(parent, rect, real_surface=None, offset=(0, 0))</pre>
-
- <p>only one of parent and real_surface should be supplied (non None)</p>
- <dl>
- <dt>parent<dd>a ProxySurface object
- <dt>real_surface<dd>a pygame Surface object
- </dl>
-
- <strong>Variables</strong>
-
- <dl>
- <dt>mysubsurface<dd>a real and valid pygame.Surface object to be used
- for blitting.
- <dt>x, y<dd>if the proxy surface is lefter or higher than the parent,
- x, y hold the diffs.
- <dt>offset<dd>an optional feature which let you scroll the whole blitted
- content.
- </dl>
- """
- def __init__(self, parent, rect, real_surface, offset=(0, 0)):
- self.offset = offset
- self.x = self.y = 0
- if rect[0] < 0: self.x = rect[0]
- if rect[1] < 0: self.y = rect[1]
- self.real_surface = real_surface
- if real_surface == None:
- self.mysubsurface = parent.mysubsurface.subsurface(parent.mysubsurface.get_rect().clip(rect))
- else:
- self.mysubsurface = real_surface.subsurface(real_surface.get_rect().clip(rect))
- rect[0], rect[1] = 0, 0
- self.rect = rect
-
- def blit(self, s, pos, rect=None):
- if rect == None: rect = s.get_rect()
- pos = (pos[0] + self.offset[0] + self.x, pos[1] + self.offset[1] + self.y)
- self.mysubsurface.blit(s, pos, rect)
-
- def subsurface(self, rect): return ProxySurface(self, pygame.Rect(rect).move(self.offset[0] + self.x, self.offset[1] + self.y),self.real_surface)
- def fill(self, color, rect=None):
- if rect != None: self.mysubsurface.fill(color, rect)
- else: self.mysubsurface.fill(color)
- def get_rect(self): return self.rect
- def get_width(self): return self.rect[2]
- def get_height(self): return self.rect[3]
- def get_abs_offset(): return self.rect[:2]
- def get_abs_parent(): return self.mysubsurface.get_abs_parent()
- def set_clip(self, rect=None):
- if rect == None: self.mysubsurface.set_clip()
- else:
- rect = [rect[0] + self.offset[0] + self.x, rect[1] + self.offset[0] + self.y, rect[2], rect[3]]
- self.mysubsurface.set_clip(rect)
-
+++ /dev/null
-"""
-"""
-from const import *
-import container
-
-class Table(container.Container):
- """A table style container.
-
- <p>If you know HTML, this should all work roughly how you would expect. If you are not
- familiar with HTML, please read <a href="http://www.w3.org/TR/REC-html40/struct/tables.html">Tables in HTML Documents</a>. Pay attention to TABLE, TR, TD related parts of the document.</p>
-
- <pre>Table()</pre>
-
- <strong>Example</strong>
- <code>
- t = gui.Table()
-
- t.tr()
- t.td(gui.Label("First Name"), align=-1)
- t.td(gui.Input())
-
- t.tr()
- t.td(gui.Label("Last Name"), align=-1)
- t.td(gui.Input())
- </code>
-
- """
-
-
- def __init__(self, **params):
- params.setdefault('cls','table')
- container.Container.__init__(self, **params)
- self._rows = []
- self._curRow = 0
- self._trok = False
-
- def getRows(self):
- return len(self._rows)
-
- def getColumns(self):
- if self._rows:
- return len(self._rows[0])
- else:
- return 0
-
- def remove_row(self, n): #NOTE: won't work in all cases.
- if n >= self.getRows():
- print "Trying to remove a nonexistant row:", n, "there are only", self.getRows(), "rows"
- return
-
- for cell in self._rows[n]:
- if isinstance(cell, dict) and cell["widget"] in self.widgets:
- #print 'removing widget'
- self.widgets.remove(cell["widget"])
- del self._rows[n]
- #print "got here"
-
- for w in self.widgets:
- if w.style.row > n: w.style.row -= 1
-
- if self._curRow >= n:
- self._curRow -= 1
-
- #self.rect.w, self.rect.h = self.resize()
- #self.repaint()
-
- self.chsize()
-
- def clear(self):
- self._rows = []
- self._curRow = 0
- self._trok = False
-
- self.widgets = []
-
- self.chsize()
-
- #print 'clear',self,self._rows
-
- def _addRow(self):
- self._rows.append([None for x in xrange(self.getColumns())])
-
- def tr(self):
- """Start on the next row."""
- if not self._trok:
- self._trok = True
- return
- self._curRow += 1
- if self.getRows() <= self._curRow:
- self._addRow()
-
- def _addColumn(self):
- if not self._rows:
- self._addRow()
- for row in self._rows:
- row.append(None)
-
- def _setCell(self, w, col, row, colspan=1, rowspan=1):
- #make room for the widget by adding columns and rows
- while self.getColumns() < col + colspan:
- self._addColumn()
- while self.getRows() < row + rowspan:
- self._addRow()
-
- #print w.__class__.__name__,col,row,colspan,rowspan
-
- #actual widget setting and modification stuff
- w.container = self
- w.style.row = row #HACK - to work with gal's list
- w.style.col = col #HACK - to work with gal's list
- self._rows[row][col] = {"widget":w, "colspan":colspan, "rowspan":rowspan}
- self.widgets.append(self._rows[row][col]["widget"])
-
- #set the spanned columns
- #for acell in xrange(col + 1, col + colspan):
- # self._rows[row][acell] = True
-
- #set the spanned rows and the columns on them
- #for arow in xrange(row + 1, row + rowspan):
- # for acell in xrange(col, col + colspan): #incorrect?
- # self._rows[arow][acell] = True
-
- for arow in xrange(row, row + rowspan):
- for acell in xrange(col, col + colspan): #incorrect?
- if row != arow or col != acell:
- self._rows[arow][acell] = True
-
-
- def td(self, w, col=None, row=None, colspan=1, rowspan=1, **params):
- """Add a widget to a table after wrapping it in a TD container.
-
- <pre>Table.td(w,col=None,row=None,colspan=1,rowspan=1,**params)</pre>
-
- <dl>
- <dt>w<dd>widget
- <dt>col<dd>column
- <dt>row<dd>row
- <dt>colspan<dd>colspan
- <dt>rowspan<dd>rowspan
- <dt>align<dd>horizontal alignment (-1,0,1)
- <dt>valign<dd>vertical alignment (-1,0,1)
- <dt>params<dd>other params for the TD container, style information, etc
- </dl>
- """
-
- Table.add(self,_Table_td(w, **params), col=col, row=row, colspan=colspan, rowspan=rowspan)
-
- def add(self, w, col=None, row=None, colspan=1, rowspan=1):
- """Add a widget directly into the table, without wrapping it in a TD container.
-
- <pre>Table.add(w,col=None,row=None,colspan=1,rowspan=1)</pre>
-
- <p>See Table.td for an explanation of the parameters.</p>
- """
- self._trok = True
- #if no row was specifically specified, set it to the current row
- if row is None:
- row = self._curRow
- #print row
-
- #if its going to be a new row, have it be on the first column
- if row >= self.getRows():
- col = 0
-
- #try to find an open cell for the widget
- if col is None:
- for cell in xrange(self.getColumns()):
- if col is None and not self._rows[row][cell]:
- col = cell
- break
-
- #otherwise put the widget in a new column
- if col is None:
- col = self.getColumns()
-
- self._setCell(w, col, row, colspan=colspan, rowspan=rowspan)
-
- self.chsize()
- return
-
- def remove(self,w):
- if hasattr(w,'_table_td'): w = w._table_td
- row,col = w.style.row,w.style.col
- cell = self._rows[row][col]
- colspan,rowspan = cell['colspan'],cell['rowspan']
-
- for arow in xrange(row , row + rowspan):
- for acell in xrange(col, col + colspan): #incorrect?
- self._rows[arow][acell] = False
- self.widgets.remove(w)
- self.chsize()
-
-
-
- def resize(self, width=None, height=None):
- #if 1 or self.getRows() == 82:
- #print ''
- #print 'resize',self.getRows(),self.getColumns(),width,height
- #import inspect
- #for obj,fname,line,fnc,code,n in inspect.stack()[9:20]:
- # print fname,line,':',fnc,code[0].strip()
-
-
- #resize the widgets to their smallest size
- for w in self.widgets:
- w.rect.w, w.rect.h = w.resize()
-
- #calculate row heights and column widths
- rowsizes = [0 for y in xrange(self.getRows())]
- columnsizes = [0 for x in xrange(self.getColumns())]
- for row in xrange(self.getRows()):
- for cell in xrange(self.getColumns()):
- if self._rows[row][cell] and self._rows[row][cell] is not True:
- if not self._rows[row][cell]["colspan"] > 1:
- columnsizes[cell] = max(columnsizes[cell], self._rows[row][cell]["widget"].rect.w)
- if not self._rows[row][cell]["rowspan"] > 1:
- rowsizes[row] = max(rowsizes[row], self._rows[row][cell]["widget"].rect.h)
-
- #distribute extra space if necessary for wide colspanning/rowspanning
- for row in xrange(self.getRows()):
- for cell in xrange(self.getColumns()):
- if self._rows[row][cell] and self._rows[row][cell] is not True:
- if self._rows[row][cell]["colspan"] > 1:
- columns = xrange(cell, cell + self._rows[row][cell]["colspan"])
- totalwidth = 0
- for acol in columns:
- totalwidth += columnsizes[acol]
- if totalwidth < self._rows[row][cell]["widget"].rect.w:
- for acol in columns:
- columnsizes[acol] += _table_div(self._rows[row][cell]["widget"].rect.w - totalwidth, self._rows[row][cell]["colspan"],acol)
- if self._rows[row][cell]["rowspan"] > 1:
- rows = xrange(row, row + self._rows[row][cell]["rowspan"])
- totalheight = 0
- for arow in rows:
- totalheight += rowsizes[arow]
- if totalheight < self._rows[row][cell]["widget"].rect.h:
- for arow in rows:
- rowsizes[arow] += _table_div(self._rows[row][cell]["widget"].rect.h - totalheight, self._rows[row][cell]["rowspan"],arow)
-
- #make everything fill out to self.style.width, self.style.heigh, not exact, but pretty close...
- w, h = sum(columnsizes), sum(rowsizes)
- if w > 0 and w < self.style.width and len(columnsizes):
- d = (self.style.width - w)
- for n in xrange(0, len(columnsizes)):
- v = columnsizes[n]
- columnsizes[n] += v * d / w
- if h > 0 and h < self.style.height and len(rowsizes):
- d = (self.style.height - h) / len(rowsizes)
- for n in xrange(0, len(rowsizes)):
- v = rowsizes[n]
- rowsizes[n] += v * d / h
-
- #set the widget's position by calculating their row/column x/y offset
- cellpositions = [[[sum(columnsizes[0:cell]), sum(rowsizes[0:row])] for cell in xrange(self.getColumns())] for row in xrange(self.getRows())]
- for row in xrange(self.getRows()):
- for cell in xrange(self.getColumns()):
- if self._rows[row][cell] and self._rows[row][cell] is not True:
- x, y = cellpositions[row][cell]
- w = sum(columnsizes[cell:cell+self._rows[row][cell]["colspan"]])
- h = sum(rowsizes[row:row+self._rows[row][cell]["rowspan"]])
-
- widget = self._rows[row][cell]["widget"]
- widget.rect.x = x
- widget.rect.y = y
- if 1 and (w,h) != (widget.rect.w,widget.rect.h):
-# if h > 20:
-# print widget.widget.__class__.__name__, (widget.rect.w,widget.rect.h),'=>',(w,h)
- widget.rect.w, widget.rect.h = widget.resize(w, h)
-
- #print self._rows[row][cell]["widget"].rect
-
- #print columnsizes
- #print sum(columnsizes)
- #size = sum(columnsizes), sum(rowsizes); print size
-
- #return the tables final size
- return sum(columnsizes),sum(rowsizes)
-
-
-def _table_div(a,b,c):
- v,r = a/b, a%b
- if r != 0 and (c%b)<r: v += 1
- return v
-
-class _Table_td(container.Container):
- def __init__(self,widget,**params):#hexpand=0,vexpand=0,
- container.Container.__init__(self,**params)
- self.widget = widget
- #self.hexpand=hexpand
- #self.vexpand=vexpand
- widget._table_td = self
- self.add(widget,0,0)
-
- def resize(self,width=None,height=None):
- w = self.widget
-
- #expansion code, but i didn't like the idea that much..
- #a bit obscure, fairly useless when a user can just
- #add a widget to a table instead of td it in.
- #ww,hh=None,None
- #if self.hexpand: ww = self.style.width
- #if self.vexpand: hh = self.style.height
- #if self.hexpand and width != None: ww = max(ww,width)
- #if self.vexpand and height != None: hh = max(hh,height)
- #w.rect.w,w.rect.h = w.resize(ww,hh)
-
- #why bother, just do the lower mentioned item...
- w.rect.w,w.rect.h = w.resize()
-
- #this should not be needed, widgets should obey their sizing on their own.
-
-# if (self.style.width!=0 and w.rect.w > self.style.width) or (self.style.height!=0 and w.rect.h > self.style.height):
-# ww,hh = None,None
-# if self.style.width: ww = self.style.width
-# if self.style.height: hh = self.style.height
-# w.rect.w,w.rect.h = w.resize(ww,hh)
-
-
- #in the case that the widget is too big, we try to resize it
- if (width != None and width < w.rect.w) or (height != None and height < w.rect.h):
- w.rect.w,w.rect.h = w.resize(width,height)
-
- width = max(width,w.rect.w,self.style.width) #,self.style.cell_width)
- height = max(height,w.rect.h,self.style.height) #,self.style.cell_height)
-
- dx = width-w.rect.w
- dy = height-w.rect.h
- w.rect.x = (self.style.align+1)*dx/2
- w.rect.y = (self.style.valign+1)*dy/2
-
- return width,height
+++ /dev/null
-"""
-"""
-import pygame
-from pygame.locals import *
-
-from const import *
-import widget
-
-class TextArea(widget.Widget):
- """A multi-line text input.
-
- <pre>TextArea(value="",width = 120, height = 30, size=20)</pre>
-
- <dl>
- <dt>value<dd>initial text
- <dt>size<dd>size for the text box, in characters
- </dl>
-
- <strong>Example</strong>
- <code>
- w = TextArea(value="Cuzco the Goat",size=20)
-
- w = TextArea("Marbles")
-
- w = TextArea("Groucho\nHarpo\nChico\nGummo\nZeppo\n\nMarx", 200, 400, 12)
- </code>
-
- """
- def __init__(self,value="",width = 120, height = 30, size=20,**params):
- params.setdefault('cls','input')
- params.setdefault('width', width)
- params.setdefault('height', height)
-
- widget.Widget.__init__(self,**params)
- self.value = value # The value of the TextArea
- self.pos = len(str(value)) # The position of the cursor
- self.vscroll = 0 # The number of lines that the TextArea is currently scrolled
- self.font = self.style.font # The font used for rendering the text
- self.cursor_w = 2 # Cursor width (NOTE: should be in a style)
- w,h = self.font.size("e"*size)
- if not self.style.height: self.style.height = h
- if not self.style.width: self.style.width = w
-
- def resize(self,width=None,height=None):
- if (width != None) and (height != None):
- self.rect = pygame.Rect(self.rect.x, self.rect.y, width, height)
- return self.rect.w, self.rect.h
-
- def paint(self,s):
-
- # TODO: What's up with this 20 magic number? It's the margin of the left and right sides, but I'm not sure how this should be gotten other than by trial and error.
- max_line_w = self.rect.w - 20
-
- # Update the line allocation for the box's value
- self.doLines(max_line_w)
-
- # Make sure that the vpos and hpos of the cursor is set properly
- self.updateCursorPos()
-
- # Make sure that we're scrolled vertically such that the cursor is visible
- if (self.vscroll < 0):
- self.vscroll = 0
- if (self.vpos < self.vscroll):
- self.vscroll = self.vpos
- elif ((self.vpos - self.vscroll + 1) * self.line_h > self.rect.h):
- self.vscroll = - (self.rect.h / self.line_h - self.vpos - 1)
-
- # Blit each of the lines in turn
- cnt = 0
- for line in self.lines:
- line_pos = (0, (cnt - self.vscroll) * self.line_h)
- if (line_pos[1] >= 0) and (line_pos[1] < self.rect.h):
- s.blit( self.font.render(line, 1, self.style.color), line_pos )
- cnt += 1
-
- # If the textarea is focused, then also show the cursor
- if self.container.myfocus is self:
- r = self.getCursorRect()
- s.fill(self.style.color,r)
-
- # This function updates self.vpos and self.hpos based on self.pos
- def updateCursorPos(self):
- self.vpos = 0 # Reset the current line that the cursor is on
- self.hpos = 0
-
- line_cnt = 0
- char_cnt = 0
-
- for line in self.lines:
- line_char_start = char_cnt # The number of characters at the start of the line
-
- # Keep track of the character count for words
- char_cnt += len(line)
-
- # If our cursor count is still less than the cursor position, then we can update our cursor line to assume that it's at least on this line
- if (char_cnt > self.pos):
- self.vpos = line_cnt
- self.hpos = self.pos - line_char_start
-
- break # Now that we know where our cursor is, we exit the loop
-
- line_cnt += 1
-
- if (char_cnt <= self.pos) and (len(self.lines) > 0):
- self.vpos = len(self.lines) - 1
- self.hpos = len(self.lines[ self.vpos ] )
-
- # Returns a rectangle that is of the size and position of where the cursor is drawn
- def getCursorRect(self):
- lw = 0
- if (len(self.lines) > 0):
- lw, lh = self.font.size( self.lines[ self.vpos ][ 0:self.hpos ] )
-
- r = pygame.Rect(lw, (self.vpos - self.vscroll) * self.line_h, self.cursor_w, self.line_h)
- return r
-
- # This function sets the cursor position according to an x/y value (such as by from a mouse click)
- def setCursorByXY(self, (x, y)):
- self.vpos = ((int) (y / self.line_h)) + self.vscroll
- if (self.vpos >= len(self.lines)):
- self.vpos = len(self.lines) - 1
-
- currentLine = self.lines[ self.vpos ]
-
- for cnt in range(0, len(currentLine) ):
- self.hpos = cnt
- lw, lh = self.font.size( currentLine[ 0:self.hpos + 1 ] )
- if (lw > x):
- break
-
- lw, lh = self.font.size( currentLine )
- if (lw < x):
- self.hpos = len(currentLine)
-
- self.setCursorByHVPos()
-
- # This function sets the cursor position by the horizontal/vertical cursor position.
- def setCursorByHVPos(self):
- line_cnt = 0
- char_cnt = 0
-
- for line in self.lines:
- line_char_start = char_cnt # The number of characters at the start of the line
-
- # Keep track of the character count for words
- char_cnt += len(line)
-
- # If we're on the proper line
- if (line_cnt == self.vpos):
- # Make sure that we're not trying to go over the edge of the current line
- if ( self.hpos >= len(line) ):
- self.hpos = len(line) - 1
- # Set the cursor position
- self.pos = line_char_start + self.hpos
- break # Now that we've set our cursor position, we exit the loop
-
- line_cnt += 1
-
- # Splits up the text found in the control's value, and assigns it into the lines array
- def doLines(self, max_line_w):
- self.line_h = 10
- self.lines = [] # Create an empty starter list to start things out.
-
- inx = 0
- line_start = 0
- while inx >= 0:
- # Find the next breakable whitespace
- # HACK: Find a better way to do this to include tabs and system characters and whatnot.
- prev_word_start = inx # Store the previous whitespace
- spc_inx = self.value.find(' ', inx+1)
- nl_inx = self.value.find('\n', inx+1)
-
- if (min(spc_inx, nl_inx) == -1):
- inx = max(spc_inx, nl_inx)
- else:
- inx = min(spc_inx, nl_inx)
-
- # Measure the current line
- lw, self.line_h = self.font.size( self.value[ line_start : inx ] )
-
- # If we exceeded the max line width, then create a new line
- if (lw > max_line_w):
- #Fall back to the previous word start
- self.lines.append(self.value[ line_start : prev_word_start + 1 ])
- line_start = prev_word_start + 1
- # TODO: Check for extra-long words here that exceed the length of a line, to wrap mid-word
-
- # If we reached the end of our text
- if (inx < 0):
- # Then make sure we added the last of the line
- if (line_start < len( self.value ) ):
- self.lines.append( self.value[ line_start : len( self.value ) ] )
- # If we reached a hard line break
- elif (self.value[inx] == "\n"):
- # Then make a line break here as well.
- newline = self.value[ line_start : inx + 1 ]
- newline = newline.replace("\n", " ") # HACK: We know we have a newline character, which doesn't print nicely, so make it into a space. Comment this out to see what I mean.
- self.lines.append( newline )
-
- line_start = inx + 1
- else:
- # Otherwise, we just continue progressing to the next space
- pass
-
- def _setvalue(self,v):
- self.__dict__['value'] = v
- self.send(CHANGE)
-
- def event(self,e):
- used = None
- if e.type == KEYDOWN:
- if e.key == K_BACKSPACE:
- if self.pos:
- self._setvalue(self.value[:self.pos-1] + self.value[self.pos:])
- self.pos -= 1
- elif e.key == K_DELETE:
- if len(self.value) > self.pos:
- self._setvalue(self.value[:self.pos] + self.value[self.pos+1:])
- elif e.key == K_HOME:
- # Find the previous newline
- newPos = self.value.rfind('\n', 0, self.pos)
- if (newPos >= 0):
- self.pos = newPos
- elif e.key == K_END:
- # Find the previous newline
- newPos = self.value.find('\n', self.pos, len(self.value) )
- if (newPos >= 0):
- self.pos = newPos
- elif e.key == K_LEFT:
- if self.pos > 0: self.pos -= 1
- used = True
- elif e.key == K_RIGHT:
- if self.pos < len(self.value): self.pos += 1
- used = True
- elif e.key == K_UP:
- self.vpos -= 1
- self.setCursorByHVPos()
- elif e.key == K_DOWN:
- self.vpos += 1
- self.setCursorByHVPos()
- # The following return/tab keys are standard for PGU widgets, but I took them out here to facilitate multi-line text editing
-# elif e.key == K_RETURN:
-# self.next()
-# elif e.key == K_TAB:
-# pass
- else:
- #c = str(e.unicode)
- try:
- if (e.key == K_RETURN):
- c = "\n"
- elif (e.key == K_TAB):
- c = " "
- else:
- c = (e.unicode).encode('latin-1')
- if c:
- self._setvalue(self.value[:self.pos] + c + self.value[self.pos:])
- self.pos += len(c)
- except: #ignore weird characters
- pass
- self.repaint()
- elif e.type == MOUSEBUTTONDOWN:
- self.setCursorByXY(e.pos)
- self.repaint()
-
- elif e.type == FOCUS:
- self.repaint()
- elif e.type == BLUR:
- self.repaint()
-
- self.pcls = ""
- if self.container.myfocus is self: self.pcls = "focus"
-
- return used
-
- def __setattr__(self,k,v):
- if k == 'value':
- if v == None: v = ''
- v = str(v)
- self.pos = len(v)
- _v = self.__dict__.get(k,NOATTR)
- self.__dict__[k]=v
- if k == 'value' and _v != NOATTR and _v != v:
- self.send(CHANGE)
- self.repaint()
-
-# The first version of this code was done by Clint Herron, and is a modified version of input.py (by Phil Hassey).
-# It is under the same license as the rest of the PGU library.
\ No newline at end of file
+++ /dev/null
-# theme.py
-
-"""
-"""
-import os, re
-import pygame
-
-from const import *
-import widget
-import surface
-from basic import parse_color, is_color
-
-__file__ = os.path.abspath(__file__)
-
-def _list_themes(dir):
- d = {}
- for entry in os.listdir(dir):
- if os.path.exists(os.path.join(dir, entry, 'config.txt')):
- d[entry] = os.path.join(dir, entry)
- return d
-
-class Theme:
- """Theme interface.
-
- <p>If you wish to create your own theme, create a class with this interface, and
- pass it to gui.App via <tt>gui.App(theme=MyTheme())</tt>.</p>
-
- <strong>Default Theme</strong>
-
- <pre>Theme(dirs='default')</pre>
- <dl>
- <dt>dirs<dd>Name of the theme dir to load a theme from. May be an absolute path to a theme, if pgu is not installed, or if you created your own theme. May include several dirs in a list if data is spread across several themes.
- </dl>
-
- <strong>Example</strong>
-
- <code>
- theme = gui.Theme("default")
- theme = gui.Theme(["mytheme","mytheme2"])
- </code>
- """
- def __init__(self,dirs='default'):
- self.config = {}
- self.dict = {}
- self._loaded = []
- self.cache = {}
- self._preload(dirs)
- pygame.font.init()
-
- def _preload(self,ds):
- if not isinstance(ds, list):
- ds = [ds]
- for d in ds:
- if d not in self._loaded:
- self._load(d)
- self._loaded.append(d)
-
- def _load(self, name):
- #theme_dir = themes[name]
-
- #try to load the local dir, or absolute path
- dnames = [name]
-
- #if the package isn't installed and people are just
- #trying out the scripts or examples
- dnames.append(os.path.join(os.path.dirname(__file__),"..","..","data","themes",name))
-
- #if the package is installed, and the package is installed
- #in /usr/lib/python2.3/site-packages/pgu/
- #or c:\python23\lib\site-packages\pgu\
- #the data is in ... lib/../share/ ...
- dnames.append(os.path.join(os.path.dirname(__file__),"..","..","..","..","share","pgu","themes",name))
- dnames.append(os.path.join(os.path.dirname(__file__),"..","..","..","..","..","share","pgu","themes",name))
- dnames.append(os.path.join(os.path.dirname(__file__),"..","..","share","pgu","themes",name))
- for dname in dnames:
- if os.path.isdir(dname): break
- if not os.path.isdir(dname):
- raise 'could not find theme '+name
-
- fname = os.path.join(dname,"config.txt")
- if os.path.isfile(fname):
- try:
- f = open(fname)
- for line in f.readlines():
- vals = line.strip().split()
- if len(vals) < 3: continue
- cls = vals[0]
- del vals[0]
- pcls = ""
- if cls.find(":")>=0:
- cls,pcls = cls.split(":")
- attr = vals[0]
- del vals[0]
- self.config[cls+":"+pcls+" "+attr] = (dname, vals)
- finally:
- f.close()
- fname = os.path.join(dname,"style.ini")
- if os.path.isfile(fname):
- import ConfigParser
- cfg = ConfigParser.ConfigParser()
- f = open(fname,'r')
- cfg.readfp(f)
- for section in cfg.sections():
- cls = section
- pcls = ''
- if cls.find(":")>=0:
- cls,pcls = cls.split(":")
- for attr in cfg.options(section):
- vals = cfg.get(section,attr).strip().split()
- self.config[cls+':'+pcls+' '+attr] = (dname,vals)
-
- is_image = re.compile('\.(gif|jpg|bmp|png|tga)$', re.I)
- def _get(self,key):
- if not key in self.config: return
- if key in self.dict: return self.dict[key]
- dvals = self.config[key]
- dname, vals = dvals
- #theme_dir = themes[name]
- v0 = vals[0]
- if v0[0] == '#':
- v = parse_color(v0)
- #if (len(v0) == 7):
- # # Due to a bug in pygame 1.8 (?) we need to explicitly
- # # specify the alpha value (otherwise it defaults to zero)
- # v0 += "FF"
- #v = pygame.color.Color(v0)
- elif v0.endswith(".ttf") or v0.endswith(".TTF"):
- v = pygame.font.Font(os.path.join(dname, v0),int(vals[1]))
- elif self.is_image.search(v0) is not None:
- v = pygame.image.load(os.path.join(dname, v0))
- else:
- try: v = int(v0)
- except: v = pygame.font.SysFont(v0, int(vals[1]))
- self.dict[key] = v
- return v
-
- def get(self,cls,pcls,attr):
- """Interface method -- get the value of a style attribute.
-
- <pre>Theme.get(cls,pcls,attr): return value</pre>
-
- <dl>
- <dt>cls<dd>class, for example "checkbox", "button", etc.
- <dt>pcls<dd>pseudo class, for example "hover", "down", etc.
- <dt>attr<dd>attribute, for example "image", "background", "font", "color", etc.
- </dl>
-
- <p>returns the value of the attribute.</p>
-
- <p>This method is called from [[gui-style]].</p>
- """
-
- if not self._loaded: self._preload("default")
-
- o = cls+":"+pcls+" "+attr
-
- #if not hasattr(self,'_count'):
- # self._count = {}
- #if o not in self._count: self._count[o] = 0
- #self._count[o] += 1
-
- if o in self.cache:
- return self.cache[o]
-
- v = self._get(cls+":"+pcls+" "+attr)
- if v:
- self.cache[o] = v
- return v
-
- pcls = ""
- v = self._get(cls+":"+pcls+" "+attr)
- if v:
- self.cache[o] = v
- return v
-
- cls = "default"
- v = self._get(cls+":"+pcls+" "+attr)
- if v:
- self.cache[o] = v
- return v
-
- v = 0
- self.cache[o] = v
- return v
-
- def box(self,w,s):
- style = w.style
-
- c = (0,0,0)
- if style.border_color != 0: c = style.border_color
- w,h = s.get_width(),s.get_height()
-
- s.fill(c,(0,0,w,style.border_top))
- s.fill(c,(0,h-style.border_bottom,w,style.border_bottom))
- s.fill(c,(0,0,style.border_left,h))
- s.fill(c,(w-style.border_right,0,style.border_right,h))
-
-
- def getspacing(self,w):
- # return the top, right, bottom, left spacing around the widget
- if not hasattr(w,'_spacing'): #HACK: assume spacing doesn't change re pcls
- s = w.style
- xt = s.margin_top+s.border_top+s.padding_top
- xr = s.padding_right+s.border_right+s.margin_right
- xb = s.padding_bottom+s.border_bottom+s.margin_bottom
- xl = s.margin_left+s.border_left+s.padding_left
- w._spacing = xt,xr,xb,xl
- return w._spacing
-
-
- def resize(self,w,m):
- # Returns the rectangle expanded in each direction
- def expand_rect(rect, left, top, right, bottom):
- return pygame.Rect(rect.x - left,
- rect.y - top,
- rect.w + left + right,
- rect.h + top + bottom)
-
- def func(width=None,height=None):
- s = w.style
-
- pt,pr,pb,pl = s.padding_top,s.padding_right,s.padding_bottom,s.padding_left
- bt,br,bb,bl = s.border_top,s.border_right,s.border_bottom,s.border_left
- mt,mr,mb,ml = s.margin_top,s.margin_right,s.margin_bottom,s.margin_left
- # Calculate the total space on each side
- top = pt+bt+mt
- right = pr+br+mr
- bottom = pb+bb+mb
- left = pl+bl+ml
- ttw = left+right
- tth = top+bottom
-
- ww,hh = None,None
- if width != None: ww = width-ttw
- if height != None: hh = height-tth
- ww,hh = m(ww,hh)
-
- if width == None: width = ww
- if height == None: height = hh
-
- #if the widget hasn't respected the style.width,
- #style height, we'll add in the space for it...
- width = max(width-ttw, ww, w.style.width)
- height = max(height-tth, hh, w.style.height)
-
- #width = max(ww,w.style.width-tw)
- #height = max(hh,w.style.height-th)
-
- r = pygame.Rect(left,top,width,height)
-
- w._rect_padding = expand_rect(r, pl, pt, pr, pb)
- w._rect_border = expand_rect(w._rect_padding, bl, bt, br, bb)
- w._rect_margin = expand_rect(w._rect_border, ml, mt, mr, mb)
-
- #w._rect_padding = pygame.Rect(r.x-pl,r.y-pt,r.w+pl+pr,r.h+pt+pb)
- #r = w._rect_padding
- #w._rect_border = pygame.Rect(r.x-bl,r.y-bt,r.w+bl+br,r.h+bt+bb)
- #r = w._rect_border
- #w._rect_margin = pygame.Rect(r.x-ml,r.y-mt,r.w+ml+mr,r.h+mt+mb)
-
- # align it within it's zone of power.
- rect = pygame.Rect(left, top, ww, hh)
- dx = width-rect.w
- dy = height-rect.h
- rect.x += (w.style.align+1)*dx/2
- rect.y += (w.style.valign+1)*dy/2
-
- w._rect_content = rect
-
- return (w._rect_margin.w, w._rect_margin.h)
- return func
-
-
- def paint(self,w,m):
- def func(s):
-# if w.disabled:
-# if not hasattr(w,'_disabled_bkgr'):
-# w._disabled_bkgr = s.convert()
-# orig = s
-# s = w._disabled_bkgr.convert()
-
-# if not hasattr(w,'_theme_paint_bkgr'):
-# w._theme_paint_bkgr = s.convert()
-# else:
-# s.blit(w._theme_paint_bkgr,(0,0))
-#
-# if w.disabled:
-# orig = s
-# s = w._theme_paint_bkgr.convert()
-
- if w.disabled:
- if (not (hasattr(w,'_theme_bkgr') and
- w._theme_bkgr.get_width() == s.get_width() and
- w._theme_bkgr.get_height() == s.get_height())):
- w._theme_bkgr = s.copy()
- orig = s
- s = w._theme_bkgr
- s.fill((0,0,0,0))
- s.blit(orig,(0,0))
-
- if hasattr(w,'background'):
- w.background.paint(surface.subsurface(s,w._rect_border))
- self.box(w,surface.subsurface(s,w._rect_border))
- r = m(surface.subsurface(s,w._rect_content))
-
- if w.disabled:
- s.set_alpha(128)
- orig.blit(s,(0,0))
-
-# if w.disabled:
-# orig.blit(w._disabled_bkgr,(0,0))
-# s.set_alpha(128)
-# orig.blit(s,(0,0))
-
- w._painted = True
- return r
- return func
-
- def event(self,w,m):
- def func(e):
- rect = w._rect_content
- if e.type == MOUSEBUTTONUP or e.type == MOUSEBUTTONDOWN:
- sub = pygame.event.Event(e.type,{
- 'button':e.button,
- 'pos':(e.pos[0]-rect.x,e.pos[1]-rect.y)})
- elif e.type == CLICK:
- sub = pygame.event.Event(e.type,{
- 'button':e.button,
- 'pos':(e.pos[0]-rect.x,e.pos[1]-rect.y)})
- elif e.type == MOUSEMOTION:
- sub = pygame.event.Event(e.type,{
- 'buttons':e.buttons,
- 'pos':(e.pos[0]-rect.x,e.pos[1]-rect.y),
- 'rel':e.rel})
- else:
- sub = e
- r = m(sub)
- return r
- return func
-
- def update(self,w,m):
- def func(s):
- if w.disabled: return []
- r = m(surface.subsurface(s,w._rect_content))
- if type(r) == list:
- dx,dy = w._rect_content.topleft
- for rr in r:
- rr.x,rr.y = rr.x+dx,rr.y+dy
- return r
- return func
-
- def open(self,w,m):
- def func(widget=None,x=None,y=None):
- if not hasattr(w,'_rect_content'): w.rect.w,w.rect.h = w.resize() #HACK: so that container.open won't resize again!
- rect = w._rect_content
- ##print w.__class__.__name__, rect
- if x != None: x += rect.x
- if y != None: y += rect.y
- return m(widget,x,y)
- return func
-
- #def open(self,w,m):
- # def func(widget=None):
- # return m(widget)
- # return func
-
- def decorate(self,widget,level):
- """Interface method -- decorate a widget.
-
- <p>The theme system is given the opportunity to decorate a widget methods at the
- end of the Widget initializer.</p>
-
- <pre>Theme.decorate(widget,level)</pre>
-
- <dl>
- <dt>widget<dd>the widget to be decorated
- <dt>level<dd>the amount of decoration to do, False for none, True for normal amount, 'app' for special treatment of App objects.
- </dl>
- """
-
- w = widget
- if level == False: return
-
- if type(w.style.background) != int:
- w.background = Background(w,self)
-
- if level == 'app': return
-
- for k,v in w.style.__dict__.items():
- if k in ('border','margin','padding'):
- for kk in ('top','bottom','left','right'):
- setattr(w.style,'%s_%s'%(k,kk),v)
-
- w.paint = self.paint(w,w.paint)
- w.event = self.event(w,w.event)
- w.update = self.update(w,w.update)
- w.resize = self.resize(w,w.resize)
- w.open = self.open(w,w.open)
-
- def render(self,s,box,r):
- """Interface method - render a special widget feature.
-
- <pre>Theme.render(s,box,r)</pre>
-
- <dl>
- <dt>s<dt>pygame.Surface
- <dt>box<dt>box data, a value returned from Theme.get, typically a pygame.Surface
- <dt>r<dt>pygame.Rect with the size that the box data should be rendered
- </dl>
-
- """
-
- if box == 0: return
-
- if is_color(box):
- s.fill(box,r)
- return
-
- x,y,w,h=r.x,r.y,r.w,r.h
- ww,hh=box.get_width()/3,box.get_height()/3
- xx,yy=x+w,y+h
- src = pygame.rect.Rect(0,0,ww,hh)
- dest = pygame.rect.Rect(0,0,ww,hh)
-
- s.set_clip(pygame.Rect(x+ww,y+hh,w-ww*2,h-hh*2))
- src.x,src.y = ww,hh
- for dest.y in xrange(y+hh,yy-hh,hh):
- for dest.x in xrange(x+ww,xx-ww,ww): s.blit(box,dest,src)
-
- s.set_clip(pygame.Rect(x+ww,y,w-ww*3,hh))
- src.x,src.y,dest.y = ww,0,y
- for dest.x in xrange(x+ww,xx-ww*2,ww): s.blit(box,dest,src)
- dest.x = xx-ww*2
- s.set_clip(pygame.Rect(x+ww,y,w-ww*2,hh))
- s.blit(box,dest,src)
-
- s.set_clip(pygame.Rect(x+ww,yy-hh,w-ww*3,hh))
- src.x,src.y,dest.y = ww,hh*2,yy-hh
- for dest.x in xrange(x+ww,xx-ww*2,ww): s.blit(box,dest,src)
- dest.x = xx-ww*2
- s.set_clip(pygame.Rect(x+ww,yy-hh,w-ww*2,hh))
- s.blit(box,dest,src)
-
- s.set_clip(pygame.Rect(x,y+hh,xx,h-hh*3))
- src.y,src.x,dest.x = hh,0,x
- for dest.y in xrange(y+hh,yy-hh*2,hh): s.blit(box,dest,src)
- dest.y = yy-hh*2
- s.set_clip(pygame.Rect(x,y+hh,xx,h-hh*2))
- s.blit(box,dest,src)
-
- s.set_clip(pygame.Rect(xx-ww,y+hh,xx,h-hh*3))
- src.y,src.x,dest.x=hh,ww*2,xx-ww
- for dest.y in xrange(y+hh,yy-hh*2,hh): s.blit(box,dest,src)
- dest.y = yy-hh*2
- s.set_clip(pygame.Rect(xx-ww,y+hh,xx,h-hh*2))
- s.blit(box,dest,src)
-
- s.set_clip()
- src.x,src.y,dest.x,dest.y = 0,0,x,y
- s.blit(box,dest,src)
-
- src.x,src.y,dest.x,dest.y = ww*2,0,xx-ww,y
- s.blit(box,dest,src)
-
- src.x,src.y,dest.x,dest.y = 0,hh*2,x,yy-hh
- s.blit(box,dest,src)
-
- src.x,src.y,dest.x,dest.y = ww*2,hh*2,xx-ww,yy-hh
- s.blit(box,dest,src)
-
-
-class Background(widget.Widget):
- def __init__(self,value,theme,**params):
- params['decorate'] = False
- widget.Widget.__init__(self,**params)
- self.value = value
- self.theme = theme
-
- def paint(self,s):
- r = pygame.Rect(0,0,s.get_width(),s.get_height())
- v = self.value.style.background
- if is_color(v):
- s.fill(v)
- else:
- self.theme.render(s,v,r)
+++ /dev/null
-"""
-"""
-import pygame
-
-import pguglobals
-import style
-
-class SignalCallback:
- # The function to call
- func = None
- # The parameters to pass to the function (as a list)
- params = None
-
-class Widget:
- """Template object - base for all widgets.
-
- <pre>Widget(**params)</pre>
-
- <p>A number of optional params may be passed to the Widget initializer.</p>
-
- <dl>
- <dt>decorate<dd>defaults to True. If true, will call <tt>theme.decorate(self)</tt> to allow the theme a chance to decorate the widget.
- <dt>style<dd>a dict of style parameters.
- <dt>x, y, width, height<dd>position and size parameters, passed along to style
- <dt>align, valign<dd>alignment parameters, passed along to style
- <dt>font, color, background<dd>other common parameters that are passed along to style
- <dt>cls<dd>class name as used by Theme
- <dt>name<dd>name of widget as used by Form. If set, will call <tt>form.add(self,name)</tt> to add the widget to the most recently created Form.
- <dt>focusable<dd>True if this widget can receive focus via Tab, etc. Defaults to True.
- <dt>disabled<dd>True of this widget is disabled. Defaults to False.
- <dt>value<dd>initial value
- </dl>
-
- <strong>Example - Creating your own Widget</strong>
- <p>This example shows which methods are template methods.</p>
- <code>
- class Draw(gui.Widget):
- def paint(self,s):
- #paint the pygame.Surface
- return
-
- def update(self,s):
- #update the pygame.Surface and return the update rects
- return [pygame.Rect(0,0,self.rect.w,self.rect.h)]
-
- def event(self,e):
- #handle the pygame.Event
- return
-
- def resize(self,width=None,height=None):
- #return the width and height of this widget
- return 256,256
- </code>
- """
-
- # The name of the widget (or None if not defined)
- name = None
-
- def __init__(self,**params):
- #object.Object.__init__(self)
- self.connects = {}
- params.setdefault('decorate',True)
- params.setdefault('style',{})
- params.setdefault('focusable',True)
- params.setdefault('disabled',False)
-
- self.focusable = params['focusable']
- self.disabled = params['disabled']
-
- self.rect = pygame.Rect(params.get('x',0),params.get('y',0),params.get('width',0),params.get('height',0))
-
- s = params['style']
- #some of this is a bit "theme-ish" but it is very handy, so these
- #things don't have to be put directly into the style.
- for att in ('align','valign','x','y','width','height','color','font','background'):
- if att in params: s[att] = params[att]
- self.style = style.Style(self,s)
-
- self.cls = 'default'
- if 'cls' in params: self.cls = params['cls']
- if 'name' in params:
- import form
- self.name = params['name']
- if hasattr(form.Form,'form') and form.Form.form != None:
- form.Form.form.add(self)
- self.form = form.Form.form
- if 'value' in params: self.value = params['value']
- self.pcls = ""
-
- if params['decorate'] != False:
- if (not pguglobals.app):
- # TODO - fix this somehow
- import app
- print 'gui.widget: creating an App'
- app.App()
- pguglobals.app.theme.decorate(self,params['decorate'])
-
- def focus(self):
- """Focus this Widget.
-
- <pre>Widget.focus()</pre>
- """
- if getattr(self,'container',None) != None:
- if self.container.myfocus != self: ## by Gal Koren
- self.container.focus(self)
-
- def blur(self):
- """Blur this Widget.
-
- <pre>Widget.blur()</pre>
- """
- if getattr(self,'container',None) != None: self.container.blur(self)
-
- def open(self):
- """Open this Widget as a modal dialog.
-
- <pre>Widget.open()</pre>
- """
- #if getattr(self,'container',None) != None: self.container.open(self)
- pguglobals.app.open(self)
-
- def close(self, w=None):
- """Close this Widget (if it is a modal dialog.)
-
- <pre>Widget.close()</pre>
- """
- #if getattr(self,'container',None) != None: self.container.close(self)
- if (not w):
- w = self
- pguglobals.app.close(w)
-
- def resize(self,width=None,height=None):
- """Template method - return the size and width of this widget.
-
- <p>Responsible for also resizing all sub-widgets.</p>
-
- <pre>Widget.resize(width,height): return width,height</pre>
-
- <dl>
- <dt>width<dd>suggested width
- <dt>height<dd>suggested height
- </dl>
-
- <p>If not overridden, will return self.style.width, self.style.height</p>
- """
- return self.style.width, self.style.height
-
- def chsize(self):
- """Change the size of this widget.
-
- <p>Calling this method will cause a resize on all the widgets,
- including this one.</p>
-
- <pre>Widget.chsize()</pre>
- """
-
- if not hasattr(self,'_painted'): return
-
- if not hasattr(self,'container'): return
-
- if pguglobals.app:
- if pguglobals.app._chsize:
- return
- pguglobals.app.chsize()
- return
-
- #if hasattr(app.App,'app'):
- # w,h = self.rect.w,self.rect.h
- # w2,h2 = self.resize()
- # if w2 != w or h2 != h:
- # app.App.app.chsize()
- # else:
- # self.repaint()
-
-
- def update(self,s):
- """Template method - update the surface
-
- <pre>Widget.update(s): return list of pygame.Rect(s)</pre>
-
- <dl>
- <dt>s<dd>pygame.Surface to update
- </dl>
-
- <p>return - a list of the updated areas as pygame.Rect(s).</p>
- """
- return
-
- def paint(self,s):
- """Template method - paint the surface
-
- <pre>Widget.paint(s)</pre>
-
- <dl>
- <dt>s<dd>pygame.Surface to paint
- </dl>
- """
- return
-
- def repaint(self):
- """Request a repaint of this Widget.
-
- <pre>Widget.repaint()</pre>
- """
- if getattr(self,'container',None) != None: self.container.repaint(self)
- def repaintall(self):
- """Request a repaint of all Widgets.
-
- <pre>Widget.repaintall()</pre>
- """
- if getattr(self,'container',None) != None: self.container.repaintall()
- def reupdate(self):
- """Request a reupdate of this Widget
-
- <pre>Widget.reupdate()</pre>
- """
- if getattr(self,'container',None) != None: self.container.reupdate(self)
- def next(self):
- """Pass focus to next Widget.
-
- <p>Widget order determined by the order they were added to their container.</p>
-
- <pre>Widget.next()</pre>
- """
- if getattr(self,'container',None) != None: self.container.next(self)
- def previous(self):
- """Pass focus to previous Widget.
-
- <p>Widget order determined by the order they were added to their container.</p>
-
- <pre>Widget.previous()</pre>
- """
-
- if getattr(self,'container',None) != None: self.container.previous(self)
-
- def get_abs_rect(self):
- """Get the absolute rect of this widget on the App screen
-
- <pre>Widget.get_abs_rect(): return pygame.Rect</pre>
- """
- x, y = self.rect.x, self.rect.y
- x += self._rect_content.x
- y += self._rect_content.y
- c = getattr(self,'container',None)
- while c:
- x += c.rect.x
- y += c.rect.y
- if hasattr(c,'_rect_content'):
- x += c._rect_content.x
- y += c._rect_content.y
- c = getattr(c,'container',None)
- return pygame.Rect(x, y, self.rect.w, self.rect.h)
-
- def connect(self,code,func,*params):
- """Connect a event code to a callback function.
-
- <p>There may be multiple callbacks per event code.</p>
-
- <pre>Object.connect(code,fnc,value)</pre>
-
- <dl>
- <dt>code<dd>event type [[gui-const]]
- <dt>fnc<dd>callback function
- <dt>*values<dd>values to pass to callback. Please note that callbacks may also have "magicaly" parameters. Such as:
- <dl>
- <dt>_event<dd>receive the event
- <dt>_code<dd>receive the event code
- <dt>_widget<dd>receive the sending widget
- </dl>
- </dl>
-
- <strong>Example</strong>
- <code>
- def onclick(value):
- print 'click',value
-
- w = Button("PGU!")
- w.connect(gui.CLICK,onclick,'PGU Button Clicked')
- </code>
- """
- if (not code in self.connects):
- self.connects[code] = []
- for cb in self.connects[code]:
- if (cb.func == func):
- # Already connected to this callback function
- return
- # Wrap the callback function and add it to the list
- cb = SignalCallback()
- cb.func = func
- cb.params = params
- self.connects[code].append(cb)
-
- # Remove signal handlers from the given event code. If func is specified,
- # only those handlers will be removed. If func is None, all handlers
- # will be removed.
- def disconnect(self, code, func=None):
- if (not code in self.connects):
- return
- if (not func):
- # Remove all signal handlers
- del self.connects[code]
- else:
- # Remove handlers that call 'func'
- n = 0
- callbacks = self.connects[code]
- while (n < len(callbacks)):
- if (callbacks[n].func == func):
- # Remove this callback
- del callbacks[n]
- else:
- n += 1
-
- def send(self,code,event=None):
- """Send a code, event callback trigger.
-
- <pre>Object.send(code,event=None)</pre>
-
- <dl>
- <dt>code<dd>event code
- <dt>event<dd>event
- </dl>
- """
- if (not code in self.connects):
- return
- # Trigger all connected signal handlers
- for cb in self.connects[code]:
- func = cb.func
- values = list(cb.params)
-
- nargs = func.func_code.co_argcount
- names = list(func.func_code.co_varnames)[:nargs]
- if hasattr(func,'im_class'): names.pop(0)
-
- args = []
- magic = {'_event':event,'_code':code,'_widget':self}
- for name in names:
- if name in magic.keys():
- args.append(magic[name])
- elif len(values):
- args.append(values.pop(0))
- else:
- break
- args.extend(values)
- func(*args)
-
- def _event(self,e):
- if self.disabled: return
- self.send(e.type,e)
- return self.event(e)
-# return
-# import app
-# if hasattr(app.App,'app'):
-# app.App.app.events.append((self,e))
-
- def event(self,e):
- """Template method - called when an event is passed to this object.
-
- <p>Please note that if you use an event, returning the value True
- will stop parent containers from also using the event. (For example, if
- your widget handles TABs or arrow keys, and you don't want those to
- also alter the focus.)</p>
-
- <dl>
- <dt>e<dd>event
- </dl>
- """
-
- return
-
- # Returns the top-level widget (usually the Desktop) by following the
- # chain of 'container' references.
- def get_toplevel(self):
- top = self
- while (getattr(top, "container", None)):
- top = top.container
- return top
-
+++ /dev/null
-"""Hexagonal tile engine.
-
-<p>Note -- this engine is not finished. Sprites are not supported. It
-can still be useful for using the level editor, and for rendering hex
-terrains, however. If you are able to update it and use it in a real game,
-help would be greatly appreciated!</p>
-
-<p>please note that this file is alpha, and is subject to modification in
-future versions of pgu!</p>
-
-"""
-print 'pgu.hexvid','This module is alpha, and is subject to change.'
-
-from pgu.vid import *
-import pygame
-
-
-class Hexvid(Vid):
- """Create an hex vid engine. See [[vid]]"""
- def update(self,screen):
- return self.paint(screen)
-
- def paint(self,screen):
- sw,sh = screen.get_width(),screen.get_height()
- self.view.w,self.view.h = sw,sh
-
- tlayer = self.tlayer
- blayer = self.blayer
- #zlayer = self.zlayer
- w,h = len(tlayer[0]),len(tlayer)
-
- #iso_w,iso_h,iso_z,tile_w,tile_h,base_w,base_h = self.iso_w,self.iso_h,self.iso_z,self.tile_w,self.tile_h,self.base_w,self.base_h
-
- tile_w,tile_h = self.tile_w,self.tile_h
- tile_w2,tile_h2 = tile_w/2,tile_h/2
-
- view = self.view
- adj = self.adj = pygame.Rect(-self.view.x,-self.view.y,0,0)
-
- w,h = len(tlayer[0]),len(tlayer)
- tiles = self.tiles
-
- #""
- if self.bounds == None:
- tmp,y1 = self.tile_to_view((0,0))
- x1,tmp = self.tile_to_view((0,h+1))
- tmp,y2 = self.tile_to_view((w+1,h+1))
- x2,tmp = self.tile_to_view((w+1,0))
- self.bounds = pygame.Rect(x1,y1,x2-x1,y2-y1)
- print self.bounds
- #""
-
- if self.bounds != None: self.view.clamp_ip(self.bounds)
-
- ox,oy = self.screen_to_tile((0,0))
- sx,sy = self.tile_to_view((ox,oy))
- dx,dy = sx - self.view.x,sy - self.view.y
-
- bot = 1
-
- tile_wi = tile_w + tile_w/2
- tile_wi2 = tile_wi/2
-
- #dx += tile_w/2
-
- for i2 in xrange(-bot,self.view.h/tile_h2+bot*3): #NOTE: 3 seems a bit much, but it works.
- tx,ty = ox + i2/2 + i2%2,oy + i2/2
- x,y = (i2%2)*tile_wi2 + dx,i2*tile_h2 + dy
-
- #to adjust for the -1 in i1
- x,tx,ty = x-tile_wi,tx-1,ty+1
-
- x -= tile_w/2
- for i1 in xrange(-1,self.view.w/tile_wi+1):
- if ty >= 0 and ty < h and tx >= 0 and tx < w:
- if blayer != None:
- n = blayer[ty][tx]
- if n != 0:
- t = tiles[n]
- if t != None and t.image != None:
- screen.blit(t.image,(x,y))
- n = tlayer[ty][tx]
- if n != 0:
- t = tiles[n]
- if t != None and t.image != None:
- screen.blit(t.image,(x,y))
-
-
- tx += 1
- ty -= 1
- x += tile_wi
-
- return [pygame.Rect(0,0,screen.get_width(),screen.get_height())]
-
- def view_to_tile(self,pos):
- x,y = pos
- #x = x + (self.tile_w*1/2)
-
- x,y = int(x*4/(self.tile_w*3)), y*2/self.tile_h
- nx = (x + y) / 2
- ny = (y - x) / 2
- return nx,ny
-
- def tile_to_view(self,pos):
- x,y = pos
- nx = x - y
- ny = x + y
- nx,ny = int(nx*(self.tile_w*3)/4), ny*self.tile_h/2
-
- #nx = nx - (self.tile_w*1/2)
- return nx,ny
-
- def screen_to_tile(self,pos): #NOTE HACK : not sure if the 3/8 is right or not, but it is pretty close...
- pos = pos[0]+self.view.x + self.tile_w*3/8,pos[1]+self.view.y
- pos = self.view_to_tile(pos)
- return pos
-
- def tile_to_screen(self,pos):
- pos = self.tile_to_view(pos)
- pos = pos[0]-self.view.x,pos[1]-self.view.y
- return pos
-
-
- def tga_load_tiles(self,fname,size,tdata={}):
- Vid.tga_load_tiles(self,fname,size,tdata)
-
- self.tile_w,self.tile_h = size
\ No newline at end of file
+++ /dev/null
-"""Classes for handling high score tables.
-"""
-
-import os
-
-def High(fname,limit=10):
- """Create a Highs object and returns the default high score table.
-
- <pre>High(fname,limit=10)</pre>
-
- <dl>
- <dt>fname <dd>filename to store high scores in
- <dt>limit <dd>limit of scores to be recorded, defaults to 10
- </dl>
- """
- return Highs(fname,limit)['default']
-
-class _Score:
- def __init__(self,score,name,data=None):
- self.score,self.name,self.data=score,name,data
-
-class _High:
- """A high score table. These objects are passed to the user, but should not be created directly.
-
- <p>You can iterate them:</p>
- <code>
- for e in myhigh:
- print e.score,e.name,e.data
- </code>
-
- <p>You can modify them:</p>
- <code>
- myhigh[0].name = 'Cuzco'
- </code>
-
- <p>You can find out their length:</p>
- <code>
- print len(myhigh)
- </code>
- """
-
- def __init__(self,highs,limit=10):
- self.highs = highs
- self._list = []
- self.limit = limit
-
- def save(self):
- """Save the high scores.
-
- <pre>_High.save()</pre>
- """
- self.highs.save()
-
- def submit(self,score,name,data=None):
- """Submit a high score to this table.
-
- <pre>_High.submit(score,name,data=None)</pre>
-
- <p>return -- the position in the table that the score attained. None if the score did not attain a position in the table.</p>
- """
- n = 0
- for e in self._list:
- if score > e.score:
- self._list.insert(n,_Score(score,name,data))
- self._list = self._list[0:self.limit]
- return n
- n += 1
- if len(self._list) < self.limit:
- self._list.append(_Score(score,name,data))
- return len(self._list)-1
-
- def check(self,score):
- """Check if a score will attain a position in the table.
-
- <pre>_High.check(score)</pre>
-
- <p>return -- the position the score will attain, else None</p>
- """
- n = 0
- for e in self._list:
- if score > e.score:
- return n
- n += 1
- if len(self._list) < self.limit:
- return len(self._list)
-
-
- def __iter__(self):
- return self._list.__iter__()
-
- def __getitem__(self,key):
- return self._list[key]
-
- def __len__(self):
- return self._list.__len__()
-
-
-class Highs:
- """The high score object.
-
- <pre>Highs(fname,limit=10)</pre>
- <ul>
- <dt>fname <dd>filename to store high scores in
- <dt>limit <dd>limit of scores to be recorded, defaults to 10
- </ul>
-
- <p>You may access _High objects through this object:</p>
-
- <code>
- my_easy_hs = highs['easy']
- my_hard_hs = highs['hard']
- </code>
-
- """
- def __init__(self,fname,limit=10):
- self.fname = fname
- self.limit = limit
- self.load()
-
- def load(self):
- """Re-load the high scores.
-
- <pre>Highs.load()</pre>
- """
-
- self._dict = {}
- try:
- f = open(self.fname)
- for line in f.readlines():
- key,score,name,data = line.strip().split("\t")
- if key not in self._dict:
- self._dict[key] = _High(self,self.limit)
- high = self._dict[key]
- high.submit(int(score),name,data)
- f.close()
- except:
- pass
-
- def save(self):
- """Save the high scores.
-
- <pre>Highs.save()</pre>
- """
-
- f = open(self.fname,"w")
- for key,high in self._dict.items():
- for e in high:
- f.write("%s\t%d\t%s\t%s\n"%(key,e.score,e.name,str(e.data)))
- f.close()
-
- def __getitem__(self,key):
- if key not in self._dict:
- self._dict[key] = _High(self,self.limit)
- return self._dict[key]
+++ /dev/null
-"""a html renderer
-"""
-
-import sys
-import htmllib
-import re
-import pygame
-from pygame.locals import *
-
-from pgu import gui
-
-_amap = {'left':-1,'right':1,'center':0,None:None,'':None,}
-_vamap = {'top':-1,'bottom':1,'center':0,'middle':0,None:None,'':None,}
-
-# Used by the HTML parser to load external resources (like images). This
-# class loads content from the local file system. But you can pass your own
-# resource loader to the HTML parser to find images by other means.
-class ResourceLoader(object):
- # Loads an image and returns it as a pygame image
- def load_image(this, path):
- return pygame.image.load(path)
-
-class _dummy:
- pass
-
-class _flush:
- def __init__(self):
- self.style = _dummy()
- self.style.font = None
- self.style.color = None
- self.cls = None
- def add(self,w): pass
- def space(self,v): pass
-
-class _hr(gui.Color):
- def __init__(self,**params):
- gui.Color.__init__(self,(0,0,0),**params)
- def resize(self,width=None,height=None):
- w,h = self.style.width,self.style.height
- #if width != None: self.rect.w = width
- #else: self.rect.w = 1
-
- #xt,xr,xb,xl = self.getspacing()
-
- if width != None: w = max(w,width)
- if height != None: h = max(h,height)
- w = max(w,1)
- h = max(h,1)
-
- return w,h #self.container.rect.w,h
-
- #self.rect.w = max(1,width,self.container.rect.w-(xl+xr))
-
- #print self.rect
- #self.rect.w = 1
-
-class _html(htmllib.HTMLParser):
- def init(self,doc,font,color,_globals,_locals,loader=None):
- self.mystack = []
- self.document = doc
- if (loader):
- self.loader = loader
- else:
- # Use the default resource loader
- self.loader = ResourceLoader()
- self.myopen('document',self.document)
-
- self.myfont = self.font = font
- self.mycolor = self.color = color
-
- self.form = None
-
- self._globals = _globals
- self._locals = _locals
-
- def myopen(self,type_,w):
-
- self.mystack.append((type_,w))
- self.type,self.item = type_,w
-
- self.font = self.item.style.font
- self.color = self.item.style.color
-
- if not self.font: self.font = self.myfont
- if not self.color: self.color = self.mycolor
-
- def myclose(self,type_):
- t = None
- self.mydone()
- while t != type_:
- #if len(self.mystack)==0: return
- t,w = self.mystack.pop()
- t,w = self.mystack.pop()
- self.myopen(t,w)
-
- def myback(self,type_):
- if type(type_) == str: type_ = [type_,]
- self.mydone()
- #print 'myback',type_
- t = None
- while t not in type_:
- #if len(self.mystack)==0: return
- t,w = self.mystack.pop()
- self.myopen(t,w)
-
- def mydone(self):
- #clearing out the last </p>
- if not hasattr(self.item,'layout'): return
- if len(self.item.layout._widgets) == 0: return
- w = self.item.layout._widgets[-1]
- if type(w) == tuple:
- del self.item.layout._widgets[-1]
-
-
- def start_b(self,attrs): self.font.set_bold(1)
- def end_b(self): self.font.set_bold(0)
- def start_i(self,attrs): self.font.set_italic(1)
- def end_i(self): self.font.set_italic(0)
- def start_u(self,attrs): self.font.set_underline(1)
- def end_u(self): self.font.set_underline(0)
- def start_br(self,attrs): self.do_br(attrs)
- def do_br(self,attrs): self.item.br(self.font.size(" ")[1])
- def attrs_to_map(self,attrs):
- k = None
- r = {}
- for k,v in attrs: r[k] = v
- return r
-
- def map_to_params(self,r):
- anum = re.compile("\D")
-
- params = {'style':{}}
- style = params['style']
-
- if 'bgcolor' in r:
- style['background'] = gui.parse_color(r['bgcolor'])
- if 'background' in r:
- style['background'] = self.loader.load_image(r['background'])
- if 'border' in r: style['border'] = int(r['border'])
-
- for k in ['width','height','colspan','rowspan','size','min','max']:
- if k in r: params[k] = int(anum.sub("",r[k]))
-
- for k in ['name','value']:
- if k in r: params[k] = r[k]
-
- if 'class' in r: params['cls'] = r['class']
-
- if 'align' in r:
- params['align'] = _amap[r['align']]
- if 'valign' in r:
- params['valign'] = _vamap[r['valign']]
-
- if 'style' in r:
- for st in r['style'].split(";"):
- #print st
- if ":" in st:
- #print st.split(":")
- k,v = st.split(":")
- k = k.replace("-","_")
- k = k.replace(" ","")
- v = v.replace(" ","")
- if k == 'color' or k == 'border_color' or k == 'background':
- v = gui.parse_color(v)
- else:
- v = int(anum.sub("",v))
- style[k] = v
- return params
-
- def map_to_connects(self,e,r):
- for k,evt in [('onclick',gui.CLICK),('onchange',gui.CHANGE)]: #blah blah blah
-
- if k in r:
- #print k,r[k]
- e.connect(evt,self.myexec,(e,r[k]))
-
- def start_p(self,attrs):
- r = self.attrs_to_map(attrs)
- align = r.get("align","left")
-
- self.check_p()
- self.item.block(_amap[align])
-
- def check_p(self):
- if len(self.item.layout._widgets) == 0: return
- if type(self.item.layout._widgets[-1]) == tuple:
- w,h = self.item.layout._widgets[-1]
- if w == 0: return
- self.do_br(None)
-
- def end_p(self):
- #print 'end p'
- self.check_p()
-
-
- def start_block(self,t,attrs,align=-1):
- r = self.attrs_to_map(attrs)
- params = self.map_to_params(r)
- if 'cls' in params: params['cls'] = t+"."+params['cls']
- else: params['cls'] = t
- b = gui.Document(**params)
- b.style.font = self.item.style.font
- if 'align' in params:
- align = params['align']
- self.item.block(align)
- self.item.add(b)
- self.myopen(t,b)
-
-
-
- def end_block(self,t):
- self.myclose(t)
- self.item.block(-1)
-
- def start_div(self,attrs): self.start_block('div',attrs)
- def end_div(self): self.end_block('div')
- def start_center(self,attrs): self.start_block('div',attrs,0)
- def end_center(self): self.end_block('div')
-
- def start_h1(self,attrs): self.start_block('h1',attrs)
- def end_h1(self): self.end_block('h1')
- def start_h2(self,attrs): self.start_block('h2',attrs)
- def end_h2(self): self.end_block('h2')
- def start_h3(self,attrs): self.start_block('h3',attrs)
- def end_h3(self): self.end_block('h3')
- def start_h4(self,attrs): self.start_block('h4',attrs)
- def end_h4(self): self.end_block('h4')
- def start_h5(self,attrs): self.start_block('h5',attrs)
- def end_h5(self): self.end_block('h5')
- def start_h6(self,attrs): self.start_block('h6',attrs)
- def end_h6(self): self.end_block('h6')
-
- def start_ul(self,attrs): self.start_block('ul',attrs)
- def end_ul(self): self.end_block('ul')
- def start_ol(self,attrs):
- self.start_block('ol',attrs)
- self.item.counter = 0
- def end_ol(self): self.end_block('ol')
- def start_li(self,attrs):
- self.myback(['ul','ol'])
- cur = self.item
- self.start_block('li',attrs)
- if hasattr(cur,'counter'):
- cur.counter += 1
- self.handle_data("%d. "%cur.counter)
- else:
- self.handle_data("- ")
- #def end_li(self): self.end_block('li') #this isn't needed because of how the parser works
-
- def start_pre(self,attrs): self.start_block('pre',attrs)
- def end_pre(self): self.end_block('pre')
- def start_code(self,attrs): self.start_block('code',attrs)
- def end_code(self): self.end_block('code')
-
- def start_table(self,attrs):
- r = self.attrs_to_map(attrs)
- params = self.map_to_params(r)
-
- align = r.get("align","left")
- self.item.block(_amap[align])
-
- t = gui.Table(**params)
- self.item.add(t)
-
- self.myopen('table',t)
-
- def start_tr(self,attrs):
- self.myback('table')
- self.item.tr()
-
- def _start_td(self,t,attrs):
- r = self.attrs_to_map(attrs)
- params = self.map_to_params(r)
- if 'cls' in params: params['cls'] = t+"."+params['cls']
- else: params['cls'] = t
- b = gui.Document(cls=t)
-
- self.myback('table')
- self.item.td(b,**params)
- self.myopen(t,b)
-
- self.font = self.item.style.font
- self.color = self.item.style.color
-
- def start_td(self,attrs):
- self._start_td('td',attrs)
-
- def start_th(self,attrs):
- self._start_td('th',attrs)
-
- def end_table(self):
- self.myclose('table')
- self.item.block(-1)
-
- def start_form(self,attrs):
- r = self.attrs_to_map(attrs)
- e = self.form = gui.Form()
- e.groups = {}
-
- self._locals[r.get('id',None)] = e
-
- def start_input(self,attrs):
- r = self.attrs_to_map(attrs)
- params = self.map_to_params(r) #why bother
- #params = {}
-
- type_,name,value = r.get('type','text'),r.get('name',None),r.get('value',None)
- f = self.form
- if type_ == 'text':
- e = gui.Input(**params)
- self.map_to_connects(e,r)
- self.item.add(e)
- elif type_ == 'radio':
- if name not in f.groups:
- f.groups[name] = gui.Group(name=name)
- g = f.groups[name]
- del params['name']
- e = gui.Radio(group=g,**params)
- self.map_to_connects(e,r)
- self.item.add(e)
- if 'checked' in r: g.value = value
- elif type_ == 'checkbox':
- if name not in f.groups:
- f.groups[name] = gui.Group(name=name)
- g = f.groups[name]
- del params['name']
- e = gui.Checkbox(group=g,**params)
- self.map_to_connects(e,r)
- self.item.add(e)
- if 'checked' in r: g.value = value
-
- elif type_ == 'button':
- e = gui.Button(**params)
- self.map_to_connects(e,r)
- self.item.add(e)
- elif type_ == 'submit':
- e = gui.Button(**params)
- self.map_to_connects(e,r)
- self.item.add(e)
- elif type_ == 'file':
- e = gui.Input(**params)
- self.map_to_connects(e,r)
- self.item.add(e)
- b = gui.Button(value='Browse...')
- self.item.add(b)
- def _browse(value):
- d = gui.FileDialog();
- d.connect(gui.CHANGE,gui.action_setvalue,(d,e))
- d.open();
- b.connect(gui.CLICK,_browse,None)
-
- self._locals[r.get('id',None)] = e
-
- def start_object(self,attrs):
- r = self.attrs_to_map(attrs)
- params = self.map_to_params(r)
- code = "e = %s(**params)"%r['type']
- #print code
- #print params
- exec(code)
- #print e
- #print e.style.width,e.style.height
- self.map_to_connects(e,r)
- self.item.add(e)
-
- self._locals[r.get('id',None)] = e
-
- def start_select(self,attrs):
- r = self.attrs_to_map(attrs)
- params = {}
-
- name,value = r.get('name',None),r.get('value',None)
- e = gui.Select(name=name,value=value,**params)
- self.map_to_connects(e,r)
- self.item.add(e)
- self.myopen('select',e)
-
- def start_option(self,attrs):
- r = self.attrs_to_map(attrs)
- params = {} #style = self.map_to_style(r)
-
- self.myback('select')
- e = gui.Document(**params)
- self.item.add(e,value=r.get('value',None))
- self.myopen('option',e)
-
-
- def end_select(self):
- self.myclose('select')
-
- def start_hr(self,attrs):
- self.do_hr(attrs)
- def do_hr(self,attrs):
- h = self.font.size(" ")[1]/2
-
- r = self.attrs_to_map(attrs)
- params = self.map_to_params(r)
- params['style']['padding'] = h
- print params
-
- self.item.block(0)
- self.item.add(_hr(**params))
- self.item.block(-1)
-
- def anchor_begin(self,href,name,type_):
- pass
-
- def anchor_end(self):
- pass
-
- def start_title(self,attrs): self.myopen('title',_flush())
- def end_title(self): self.myclose('title')
-
- def myexec(self,value):
- w,code = value
- g = self._globals
- l = self._locals
- l['self'] = w
- exec(code,g,l)
-
- def handle_image(self,src,alt,ismap,align,width,height):
- try:
- w = gui.Image(self.loader.load_image(src))
- if align != '':
- self.item.add(w,_amap[align])
- else:
- self.item.add(w)
- except:
- print 'handle_image: missing %s'%src
-
- def handle_data(self,txt):
- if self.type == 'table': return
- elif self.type in ('pre','code'):
- txt = txt.replace("\t"," ")
- ss = txt.split("\n")
- if ss[-1] == "": del ss[-1]
- for sentence in ss:
- img = self.font.render(sentence,1,self.color)
- w = gui.Image(img)
- self.item.add(w)
- self.item.block(-1)
- return
-
- txt = re.compile("^[\t\r\n]+").sub("",txt)
- txt = re.compile("[\t\r\n]+$").sub("",txt)
-
- tst = re.compile("[\t\r\n]+").sub("",txt)
- if tst == "": return
-
- txt = re.compile("\s+").sub(" ",txt)
- if txt == "": return
-
- if txt == " ":
- self.item.space(self.font.size(" "))
- return
-
- for word in txt.split(" "):
- word = word.replace(chr(160)," ") #
- #print self.item.cls
- w = gui.Image(self.font.render(word,1,self.color))
- self.item.add(w)
- self.item.space(self.font.size(" "))
-
-
-class HTML(gui.Document):
- """a gui HTML object
-
- <pre>HTML(data,globals=None,locals=None)</pre>
-
- <dl>
- <dt>data <dd>html data
- <dt>globals <dd>global variables (for scripting)
- <dt>locals <dd>local variables (for scripting)
- <dt>loader <dd>the resource loader
- </dl>
-
- <p>you may access html elements that have an id via widget[id]</p>
- """
- def __init__(self,data,globals=None,locals=None,loader=None,**params):
- gui.Document.__init__(self,**params)
- # This ensures that the whole HTML document is left-aligned within
- # the rendered surface.
- self.style.align = -1
-
- _globals,_locals = globals,locals
-
- if _globals == None: _globals = {}
- if _locals == None: _locals = {}
- self._globals = _globals
- self._locals = _locals
-
- #font = gui.theme.get("label","","font")
- p = _html(htmllib.AS_IS,0)
- p.init(self,self.style.font,self.style.color,_globals,_locals,
- loader=loader)
- p.feed(data)
- p.close()
- p.mydone()
-
-
- def __getitem__(self,k):
- return self._locals[k]
-
- # Returns a box (pygame rectangle) surrounding all widgets in this document
- def get_bounding_box(this):
- minx = miny = sys.maxint
- maxx = maxy = -sys.maxint
- for e in this.layout.widgets:
- minx = min(minx, e.rect.left)
- miny = min(miny, e.rect.top)
- maxx = max(maxx, e.rect.right+1)
- maxy = max(maxy, e.rect.bottom+1)
- return pygame.Rect(minx, miny, maxx-minx, maxy-miny)
-
-
-def render_ext(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params):
- """Renders some html and returns the rendered surface, plus the
- HTML instance that produced it.
- """
-
- htm = HTML(text, font=font, color=color, **params)
-
- if (rect == -1):
- # Make the surface large enough to fit the rendered text
- htm.resize(width=sys.maxint)
- (width, height) = htm.get_bounding_box().size
- # Now set the proper document width (computed from the bounding box)
- htm.resize(width=width)
- elif (type(rect) == int):
- # Fix the width of the document, while the height is variable
- width = rect
- height = htm.resize(width=width)[1]
- else:
- # Otherwise the width and height of the document is fixed
- (width, height) = rect.size
- htm.resize(width=width)
-
- # Now construct a surface and paint to it
- surf = pygame.Surface((width, height)).convert_alpha()
- surf.fill(bgcolor)
- htm.paint(surf)
- return (surf, htm)
-
-def render(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params):
- """Renders some html
-
- <pre>render(font,rect,text,aa,color,bgcolor=(0,0,0,0))</pre>
- """
- return render_ext(font, rect, text, aa, color, bgcolor, **params)[0]
-
-def rendertrim(font,rect,text,aa,color,bgcolor=(0,0,0,0),**params):
- """render html, and make sure to trim the size
-
- rendertrim(font,rect,text,aa,color,bgcolor=(0,0,0,0))
- """
- # Render the HTML
- (surf, htm) = render_ext(font, rect, text, aa, color, bgcolor, **params)
- return surf.subsurface(htm.get_bounding_box())
-
-
-def write(s,font,rect,text,aa=0,color=(0,0,0), **params):
- """write html to a surface
-
- write(s,font,rect,text,aa=0,color=(0,0,0))
- """
- htm = HTML(text, font=font, color=color, **params)
- htm.resize(width=rect.w)
- s = s.subsurface(rect)
- htm.paint(s)
-
-# vim: set filetype=python sts=4 sw=4 noet si :
+++ /dev/null
-"""Isometric tile engine.
-
-<p>Note -- this engine is not finished, any may not work for your
-particular needs. If you are able to update it, help would be
-greatly appreciated!</p>
-
-<p>please note that this file is alpha, and is subject to modification in
-future versions of pgu!</p>
-
-"""
-print 'pgu.isovid','This module is alpha, and is subject to change.'
-
-from pgu.vid import *
-import pygame
-
-class Isovid(Vid):
- """Create an iso vid engine. See [[vid]]"""
- def update(self,screen):
- return self.paint(screen)
-
- def paint(self,screen):
- sw,sh = screen.get_width(),screen.get_height()
-
- tlayer = self.tlayer
- blayer = self.blayer
- zlayer = self.zlayer
- w,h = len(tlayer[0]),len(tlayer)
-
- iso_w,iso_h,iso_z,tile_w,tile_h,base_w,base_h = self.iso_w,self.iso_h,self.iso_z,self.tile_w,self.tile_h,self.base_w,self.base_h
-
- base_h2 = base_h/2
- base_w2 = base_w/2
-
- bot = tile_h/base_h2
- todo_max = sh/base_h2+bot
- todo = [[] for y in xrange(0,todo_max)]
-
- self.view.w,self.view.h = sw,sh
- view = self.view
- adj = self.adj = pygame.Rect(-self.view.x,-self.view.y,0,0)
-
- for s in self.sprites:
- self.sprite_calc_irect(s)
- x,y = self.iso_to_view((s.rect.centerx,s.rect.centery))
- v = (y+adj.y)/base_h2 - 1
- if v >= 0 and v < todo_max:
- todo[v].append((s.image,s.irect))
- #else: print 'doesnt fit',v
-
- w,h = len(tlayer[0]),len(tlayer)
- tiles = self.tiles
-
- #""
- if self.bounds == None:
- tmp,y1 = self.tile_to_view((0,0))
- x1,tmp = self.tile_to_view((0,h+1))
- tmp,y2 = self.tile_to_view((w+1,h+1))
- x2,tmp = self.tile_to_view((w+1,0))
- self.bounds = pygame.Rect(x1,y1,x2-x1,y2-y1)
- #""
-
- if self.bounds != None: self.view.clamp_ip(self.bounds)
-
- ox,oy = self.screen_to_tile((0,0))
- sx,sy = self.iso_to_view((ox*iso_w,oy*iso_h))
- dx,dy = sx - self.view.x,sy - self.view.y
-
- for i2 in xrange(-bot,self.view.h/base_h2+bot):
- tx,ty = ox + i2/2 + i2%2,oy + i2/2
- x,y = (i2%2)*base_w2 + dx,i2*base_h2 + dy
-
- #to adjust for the -1 in i1
- x,tx,ty = x-base_w,tx-1,ty+1
- for i1 in xrange(-1,self.view.w/base_w+2): #NOTE: not sure why +2
- if ty >= 0 and ty < h and tx >= 0 and tx < w:
- z = zlayer[ty][tx]*iso_z
- if blayer != None:
- n = blayer[ty][tx]
- if n != 0:
- t = tiles[n]
- if t != None and t.image != None:
- screen.blit(t.image,(x-base_w2,y+z))
- n = tlayer[ty][tx]
- if n != 0:
- t = tiles[n]
- if t != None and t.image != None:
- screen.blit(t.image,(x-base_w2,y-(t.image_h-base_h)+z))
-
- tx += 1
- ty -= 1
- x += base_w
- for img,irect in todo[y/base_h2]:
- screen.blit(img,(irect.x+adj.x,irect.y+adj.y))
-
- return [pygame.Rect(0,0,screen.get_width(),screen.get_height())]
-
- def iso_to_view(self,pos):
- tlayer = self.tlayer
- w,h = len(tlayer[0]),len(tlayer)
-
- x,y = pos
-
- #nx,ny = (h*self.iso_w + x - y)/2, (0 + x + y)/2
- nx,ny = (x - y)/2, (0 + x + y)/2
-
- return (nx * self.base_w / self.iso_w), (ny * self.base_h / self.iso_h)
-
- def view_to_iso(self,pos):
- tlayer = self.tlayer
- w,h = len(tlayer[0]),len(tlayer)
-
- x,y = pos
-
- x,y = x*self.iso_w/self.base_w, y*self.iso_h/self.base_h
-
- #x -= (self.iso_w/2) * h
- #x -= (self.iso_w/2) * h
-
- nx = (x+y)
- ny = y*2-nx
-
- return nx,ny
-
- def tile_to_view(self,pos):
- return self.iso_to_view((pos[0]*self.iso_w,pos[1]*self.iso_h))
-
- def screen_to_tile(self,pos):
- x,y = pos
- x += self.view.x
- y += self.view.y
- x,y = self.view_to_iso((x,y))
- return x/self.iso_w,y/self.iso_h
-
- def tile_to_screen(self,pos):
- x,y = self.iso_to_view((pos[0]*self.iso_w,pos[1]*self.iso_h))
- return x-self.view.x,y-self.view.y
-
- def tga_load_tiles(self,fname,size,tdata={}):
- Vid.tga_load_tiles(self,fname,size,tdata)
-
- self.tile_w,self.tile_h = size
- self.iso_w,self.iso_h,self.iso_z = self.tile_w,self.tile_w,1
- self.base_w,self.base_h = self.tile_w,self.tile_w/2
-
-
-
- def resize(self,size,bg=0):
- Vid.resize(self,size,bg)
-
- tlayer = self.tlayer
- w,h = len(tlayer[0]),len(tlayer)
-
- self.zlayer = [[0 for x in xrange(0,w)] for y in xrange(0,h)]
-
-
-
-
- def sprite_calc_irect(self,s):
- tlayer = self.tlayer
- w,h = len(tlayer[0]),len(tlayer)
- zlayer = self.zlayer
-
- x,y = self.iso_to_view((s.rect.centerx,s.rect.centery))
- tx,ty = s.rect.centerx/self.iso_w,s.rect.centery/self.iso_h
- z = 0
- if ty >= 0 and ty < h and tx >= 0 and tx < w:
- z = zlayer[ty][tx]*self.iso_z
-
- nx,ny = x - s.shape.centerx, y - s.shape.centery + z
-
- s.irect.x,s.irect.y = nx,ny
-
- def run_codes(self,cdata,rect):
- #HACK to make run_codes work
- w,h = self.iso_w,self.iso_h
-
- img = self.tiles[0].image
-
- self.tiles[0].image = pygame.Surface((w,h))
- r = Vid.run_codes(self,cdata,rect)
- self.tiles[0].image = img
- return r
+++ /dev/null
-print 'pgu.layout','Scheduled to be deprecated.'
-
-from pgu.gui.layout import *
-
+++ /dev/null
-"""a collection of text rendering functions
-"""
-def write(s,font,pos,color,text,border=1):
- """write text to a surface with a black border
-
- <pre>write(s,font,pos,color,text,border=1)</pre>
- """
- i = font.render(text,1,(0,0,0))
- si = border
- dirs = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
- for dx,dy in dirs: s.blit(i,(pos[0]+dx*si,pos[1]+dy*si))
- i = font.render(text,1,color)
- s.blit(i,pos)
-
-def writec(s,font,color,text,border=1):
- """write centered text to a surface with a black border
-
- <pre>writec(s,font,color,text,border=1)</pre>
- """
- w,h = font.size(text)
- x = (s.get_width()-w)/2
- y = (s.get_height()-h)/2
- write(s,font,(x,y),color,text,border)
-
-def writepre(s,font,rect,color,text):
- """write preformatted text
-
- <pre>writepre(s,font,rect,color,text)</pre>
- """
- r,c,txt = rect,color,text
- txt = txt.replace("\t"," ")
- i = font.render(" ",1,c)
- sw,sh = i.get_width(),i.get_height()
- y = r.top
- for sentence in txt.split("\n"):
- x = r.left
- i = font.render(sentence,1,c)
- s.blit(i,(x,y))
- y += sh
-
-def writewrap(s,font,rect,color,text):
- """write wrapped text
-
- <pre>writewrap(s,font,rect,color,text)</pre>
- """
- r,c,txt = rect,color,text
- txt = txt.replace("\t"," ")
- i = font.render(" ",1,c)
- sw,sh = i.get_width(),i.get_height()
- y = r.top
- for sentence in txt.split("\n"):
- x = r.left
- for word in sentence.split(" "):
- i = font.render(word,1,c)
- iw,ih = i.get_width(),i.get_height()
- if x+iw > r.right: x,y = r.left,y+sh
- s.blit(i,(x,y))
- x += iw+sw
- y += sh
-
-# vim: set filetype=python sts=4 sw=4 noet si :
+++ /dev/null
-"""Square tile based engine."""
-
-from pgu.vid import *
-import pygame
-
-class Tilevid(Vid):
- """Based on [[vid]] -- see for reference."""
- def paint(self,s):
- sw,sh = s.get_width(),s.get_height()
- self.view.w,self.view.h = sw,sh
-
- tiles = self.tiles
- tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
- w,h = self.size
-
- if self.bounds != None: self.view.clamp_ip(self.bounds)
-
- ox,oy = self.view.x,self.view.y
- tlayer = self.tlayer
- blayer = self.blayer
- alayer = self.alayer
- sprites = self.sprites
-
- blit = s.blit
- yy = - (self.view.y%th)
- my = (oy+sh)/th
- if (oy+sh)%th: my += 1
-
- if blayer != None:
- for y in xrange(oy/th,my):
- if y >=0 and y < h:
- trow = tlayer[y]
- brow = blayer[y]
- arow = alayer[y]
- xx= - (self.view.x%tw)
- mx = (ox+sw)/tw
- #if (ox+sh)%tw: mx += 1
- for x in xrange(ox/tw,mx+1):
- if x >=0and x<w:
- blit(tiles[brow[x]].image,(xx,yy))
- blit(tiles[trow[x]].image,(xx,yy))
- arow[x]=0
- xx += tw
- yy+=th
- else:
- for y in xrange(oy/th,my):
- if y >=0 and y<h:
- trow = tlayer[y]
- arow = alayer[y]
- xx= - (self.view.x%tw)
- mx = (ox+sw)/tw
- #if (ox+sh)%tw: mx += 1
- for x in xrange(ox/tw,mx+1):
- if x >=0 and x<w:
- blit(tiles[trow[x]].image,(xx,yy))
- arow[x]=0
- xx += tw
- yy+=th
-
- for s in sprites:
- s.irect.x = s.rect.x-s.shape.x
- s.irect.y = s.rect.y-s.shape.y
- blit(s.image,(s.irect.x-ox,s.irect.y-oy))
- s.updated=0
- s._irect = Rect(s.irect)
- #s._rect = Rect(s.rect)
-
- self.updates = []
- self._view = pygame.Rect(self.view)
- return [Rect(0,0,sw,sh)]
-
- def update(self,s):
- sw,sh = s.get_width(),s.get_height()
- self.view.w,self.view.h = sw,sh
-
- if self.bounds != None: self.view.clamp_ip(self.bounds)
- if self.view.x != self._view.x or self.view.y != self._view.y:
- return self.paint(s)
-
- ox,oy = self.view.x,self.view.y
- sw,sh = s.get_width(),s.get_height()
- w,h = self.size
- tlayer = self.tlayer
- blayer = self.blayer
- alayer = self.alayer
- tiles = self.tiles
- tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
- sprites = self.sprites
- blit = s.blit
-
- us = []
-
- #mark places where sprites have moved, or been removed
-
- ss = self.sprites.removed
- self.sprites.removed = []
- ss.extend(sprites)
- for s in ss:
- #figure out what has been updated.
- s.irect.x = s.rect.x-s.shape.x
- s.irect.y = s.rect.y-s.shape.y
- if (s.irect.x != s._irect.x or s.irect.y != s._irect.y
- or s.image != s._image):
- #w,h can be skipped, image covers that...
- s.updated = 1
- if s.updated:
- r = s._irect
- y = max(0,r.y/th)
- yy = min(h,r.bottom/th+1)
- while y < yy:
- x = max(0,r.x/tw)
- xx = min(w,r.right/tw+1)
- while x < xx:
- if alayer[y][x] == 0:
- self.updates.append((x,y))
- alayer[y][x]=1
- x += 1
- y += 1
-
- r = s.irect
- y = max(0,r.y/th)
- yy = min(h,r.bottom/th+1)
- while y < yy:
- x = r.x/tw
- xx = min(w,r.right/tw+1)
- while x < xx:
- if alayer[y][x]==0:
- alayer[y][x]=2
- self.updates.append((x,y))
- x += 1
- y += 1
-
-
- #mark sprites that are not being updated that need to be updated because
- #they are being overwritte by sprites / tiles
- for s in sprites:
- if s.updated==0:
- r = s.irect
- y = max(0,r.y/th)
- yy = min(h,r.bottom/th+1)
- while y < yy:
- x = max(0,r.x/tw)
- xx = min(w,r.right/tw+1)
- while x < xx:
- if alayer[y][x]==1:
- s.updated=1
- x += 1
- y += 1
-
-
- for u in self.updates:
- x,y=u
- xx,yy=x*tw-ox,y*th-oy
- if alayer[y][x] == 1:
- if blayer != None: blit(tiles[blayer[y][x]].image,(xx,yy))
- blit(tiles[tlayer[y][x]].image,(xx,yy))
- alayer[y][x]=0
- us.append(Rect(xx,yy,tw,th))
-
- for s in sprites:
- if s.updated:
- blit(s.image,(s.irect.x-ox, s.irect.y-oy))
- s.updated=0
- s._irect = Rect(s.irect)
- s._image = s.image
-
- self.updates = []
- return us
-
- def view_to_tile(self,pos):
- x,y = pos
- tiles = self.tiles
- tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
- return x/tw,y/th
-
- def tile_to_view(self,pos):
- x,y = pos
- tiles = self.tiles
- tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
- x,y = x*tw, y*th
- return x,y
-
-
- def screen_to_tile(self,pos):
- x,y = pos
- x,y = x+self.view.x,y+self.view.y
- return self.view_to_tile((x,y))
-
- def tile_to_screen(self,pos):
- x,y = pos
- x,y = self.tile_to_view(pos)
- x,y = x - self.view.x, y - self.view.y
- return x,y
-
-# vim: set filetype=python sts=4 sw=4 noet si :
+++ /dev/null
-"""A timer for games with set-rate FPS.
-"""
-
-import pygame
-
-class Timer:
- """A timer for games with set-rate FPS.
-
- <pre>Timer(fps)</pre>
- """
-
- def __init__(self,fps):
- if fps == 0:
- self.tick = self._blank
- return
- self.wait = 1000/fps
- self.nt = pygame.time.get_ticks()
- pygame.time.wait(0)
-
- def _blank(self):
- pass
-
- def tick(self):
- """Wait correct amount of time each frame. Call this once per frame.
-
- <pre>Timer.tick()</pre>
- """
- self.ct = pygame.time.get_ticks()
- if self.ct < self.nt:
- pygame.time.wait(self.nt-self.ct)
- self.nt+=self.wait
- else:
- self.nt = pygame.time.get_ticks()+self.wait
-
-
-class Speedometer:
- """A timer replacement that returns out FPS once a second.
- <pre>Speedometer()</pre>
-
- <strong>Attributes</strong>
- <dl>
- <dt>fps <dd>always set to the current FPS
- </dl>
- """
- def __init__(self):
- self.frames = 0
- self.st = pygame.time.get_ticks()
- self.fps = 0
-
- def tick(self):
- """ Call this once per frame.
-
- <pre>Speedometer.tick()</pre>
- """
- r = None
- self.frames += 1
- self.ct = pygame.time.get_ticks()
- if (self.ct - self.st) >= 1000:
- r = self.fps = self.frames
- #print "%s: %d fps"%(self.__class__.__name__,self.fps)
- self.frames = 0
- self.st += 1000
- pygame.time.wait(0) #NOTE: not sure why, but you gotta call this now and again
- return r
-
-
-
-# vim: set filetype=python sts=4 sw=4 noet si :
+++ /dev/null
-"""Sprite and tile engine.
-
-<p>[[tilevid]], [[isovid]], [[hexvid]] are all subclasses of
-this interface.</p>
-
-<p>Includes support for:</p>
-
-<ul>
-<li> Foreground Tiles
-<li> Background Tiles
-<li> Sprites
-<li> Sprite-Sprite Collision handling
-<li> Sprite-Tile Collision handling
-<li> Scrolling
-<li> Loading from PGU tile and sprite formats (optional)
-<li> Set rate FPS (optional)
-</ul>
-
-<p>This code was previously known as the King James Version (named after the
-Bible of the same name for historical reasons.)</p>
-"""
-
-import pygame
-from pygame.rect import Rect
-from pygame.locals import *
-import math
-
-class Sprite:
- """The object used for Sprites.
-
- <pre>Sprite(ishape,pos)</pre>
-
- <dl>
- <dt>ishape <dd>an image, or an image, rectstyle. The rectstyle will
- describe the shape of the image, used for collision
- detection.
- <dt>pos <dd>initial (x,y) position of the Sprite.
- </dl>
-
- <strong>Attributes</strong>
- <dl>
- <dt>rect <dd>the current position of the Sprite
- <dt>_rect <dd>the previous position of the Sprite
- <dt>groups <dd>the groups the Sprite is in
- <dt>agroups <dd>the groups the Sprite can hit in a collision
- <dt>hit <dd>the handler for hits -- hit(g,s,a)
- <dt>loop <dd>the loop handler, called once a frame
- </dl>
- """
- def __init__(self,ishape,pos):
- if not isinstance(ishape, tuple):
- ishape = ishape,None
- image,shape = ishape
- if shape == None:
- shape = pygame.Rect(0,0,image.get_width(),image.get_height())
- if isinstance(shape, tuple): shape = pygame.Rect(shape)
- self.image = image
- self._image = self.image
- self.shape = shape
- self.rect = pygame.Rect(pos[0],pos[1],shape.w,shape.h)
- self._rect = pygame.Rect(self.rect)
- self.irect = pygame.Rect(pos[0]-self.shape.x,pos[1]-self.shape.y,
- image.get_width(),image.get_height())
- self._irect = pygame.Rect(self.irect)
- self.groups = 0
- self.agroups = 0
- self.updated = 1
-
- def setimage(self,ishape):
- """Set the image of the Sprite.
-
- <pre>Sprite.setimage(ishape)</pre>
-
- <dl>
- <dt>ishape <dd>an image, or an image, rectstyle. The rectstyle will
- describe the shape of the image, used for collision detection.
- </dl>
- """
- if not isinstance(ishape, tuple):
- ishape = ishape,None
- image,shape = ishape
- if shape == None:
- shape = pygame.Rect(0,0,image.get_width(),image.get_height())
- if isinstance(shape, tuple):
- shape = pygame.Rect(shape)
- self.image = image
- self.shape = shape
- self.rect.w,self.rect.h = shape.w,shape.h
- self.irect.w,self.irect.h = image.get_width(),image.get_height()
- self.updated = 1
-
-
-class Tile:
- """Tile Object used by TileCollide.
-
- <pre>Tile(image=None)</pre>
- <dl>
- <dt>image <dd>an image for the Tile.
- </dl>
-
- <strong>Attributes</strong>
- <dl>
- <dt>agroups <dd>the groups the Tile can hit in a collision
- <dt>hit <dd>the handler for hits -- hit(g,t,a)
- </dl>
- """
- def __init__(self,image=None):
- self.image = image
- self.agroups = 0
-
- def __setattr__(self,k,v):
- if k == 'image' and v != None:
- self.image_h = v.get_height()
- self.image_w = v.get_width()
- self.__dict__[k] = v
-
-class _Sprites(list):
- def __init__(self):
- list.__init__(self)
- self.removed = []
-
- def append(self,v):
- list.append(self,v)
- v.updated = 1
-
- def remove(self,v):
- list.remove(self,v)
- v.updated = 1
- self.removed.append(v)
-
-class Vid:
- """An engine for rendering Sprites and Tiles.
-
- <pre>Vid()</pre>
-
- <strong>Attributes</strong>
- <dl>
- <dt>sprites <dd>a list of the Sprites to be displayed. You may append and
- remove Sprites from it.
- <dt>images <dd>a dict for images to be put in.
- <dt>size <dd>the width, height in Tiles of the layers. Do not modify.
- <dt>view <dd>a pygame.Rect of the viewed area. You may change .x, .y,
- etc to move the viewed area around.
- <dt>bounds <dd>a pygame.Rect (set to None by default) that sets the bounds
- of the viewable area. Useful for setting certain borders
- as not viewable.
- <dt>tlayer <dd>the foreground tiles layer
- <dt>clayer <dd>the code layer (optional)
- <dt>blayer <dd>the background tiles layer (optional)
- <dt>groups <dd>a hash of group names to group values (32 groups max, as a tile/sprites
- membership in a group is determined by the bits in an integer)
- </dl>
- """
-
- def __init__(self):
- self.tiles = [None for x in xrange(0,256)]
- self.sprites = _Sprites()
- self.images = {} #just a store for images.
- self.layers = None
- self.size = None
- self.view = pygame.Rect(0,0,0,0)
- self._view = pygame.Rect(self.view)
- self.bounds = None
- self.updates = []
- self.groups = {}
-
-
- def resize(self,size,bg=0):
- """Resize the layers.
-
- <pre>Vid.resize(size,bg=0)</pre>
-
- <dl>
- <dt>size <dd>w,h in Tiles of the layers
- <dt>bg <dd>set to 1 if you wish to use both a foreground layer and a
- background layer
- </dl>
- """
- self.size = size
- w,h = size
- self.layers = [[[0 for x in xrange(0,w)] for y in xrange(0,h)]
- for z in xrange(0,4)]
- self.tlayer = self.layers[0]
- self.blayer = self.layers[1]
- if not bg: self.blayer = None
- self.clayer = self.layers[2]
- self.alayer = self.layers[3]
-
- self.view.x, self.view.y = 0,0
- self._view.x, self.view.y = 0,0
- self.bounds = None
-
- self.updates = []
-
- def set(self,pos,v):
- """Set a tile in the foreground to a value.
-
- <p>Use this method to set tiles in the foreground, as it will make
- sure the screen is updated with the change. Directly changing
- the tlayer will not guarantee updates unless you are using .paint()
- </p>
-
- <pre>Vid.set(pos,v)</pre>
-
- <dl>
- <dt>pos <dd>(x,y) of tile
- <dt>v <dd>value
- </dl>
- """
- if self.tlayer[pos[1]][pos[0]] == v: return
- self.tlayer[pos[1]][pos[0]] = v
- self.alayer[pos[1]][pos[0]] = 1
- self.updates.append(pos)
-
- def get(self,pos):
- """Get the tlayer at pos.
-
- <pre>Vid.get(pos): return value</pre>
-
- <dl>
- <dt>pos <dd>(x,y) of tile
- </dl>
- """
- return self.tlayer[pos[1]][pos[0]]
-
- def paint(self,s):
- """Paint the screen.
-
- <pre>Vid.paint(screen): return [updates]</pre>
-
- <dl>
- <dt>screen <dd>a pygame.Surface to paint to
- </dl>
-
- <p>returns the updated portion of the screen (all of it)</p>
- """
- return []
-
- def update(self,s):
- """Update the screen.
-
- <pre>Vid.update(screen): return [updates]</pre>
-
- <dl>
- <dt>screen <dd>a pygame.Rect to update
- </dl>
-
- <p>returns a list of updated rectangles.</p>
- """
- self.updates = []
- return []
-
- def tga_load_level(self,fname,bg=0):
- """Load a TGA level.
-
- <pre>Vid.tga_load_level(fname,bg=0)</pre>
-
- <dl>
- <dt>g <dd>a Tilevid instance
- <dt>fname <dd>tga image to load
- <dt>bg <dd>set to 1 if you wish to load the background layer
- </dl>
- """
- if type(fname) == str: img = pygame.image.load(fname)
- else: img = fname
- w,h = img.get_width(),img.get_height()
- self.resize((w,h),bg)
- for y in range(0,h):
- for x in range(0,w):
- t,b,c,_a = img.get_at((x,y))
- self.tlayer[y][x] = t
- if bg: self.blayer[y][x] = b
- self.clayer[y][x] = c
-
- def tga_save_level(self,fname):
- """Save a TGA level.
-
- <pre>Vid.tga_save_level(fname)</pre>
-
- <dl>
- <dt>fname <dd>tga image to save to
- </dl>
- """
- w,h = self.size
- img = pygame.Surface((w,h),SWSURFACE,32)
- img.fill((0,0,0,0))
- for y in range(0,h):
- for x in range(0,w):
- t = self.tlayer[y][x]
- b = 0
- if self.blayer:
- b = self.blayer[y][x]
- c = self.clayer[y][x]
- _a = 0
- img.set_at((x,y),(t,b,c,_a))
- pygame.image.save(img,fname)
-
-
-
- def tga_load_tiles(self,fname,size,tdata={}):
- """Load a TGA tileset.
-
- <pre>Vid.tga_load_tiles(fname,size,tdata={})</pre>
-
- <dl>
- <dt>g <dd>a Tilevid instance
- <dt>fname <dd>tga image to load
- <dt>size <dd>(w,h) size of tiles in pixels
- <dt>tdata <dd>tile data, a dict of tile:(agroups, hit handler, config)
- </dl>
- """
- TW,TH = size
- if type(fname) == str: img = pygame.image.load(fname).convert_alpha()
- else: img = fname
- w,h = img.get_width(),img.get_height()
-
- n = 0
- for y in range(0,h,TH):
- for x in range(0,w,TW):
- i = img.subsurface((x,y,TW,TH))
- tile = Tile(i)
- self.tiles[n] = tile
- if n in tdata:
- agroups,hit,config = tdata[n]
- tile.agroups = self.string2groups(agroups)
- tile.hit = hit
- tile.config = config
- n += 1
-
-
- def load_images(self,idata):
- """Load images.
-
- <pre>Vid.load_images(idata)</pre>
-
- <dl>
- <dt>idata <dd>a list of (name, fname, shape)
- </dl>
- """
- for name,fname,shape in idata:
- self.images[name] = pygame.image.load(fname).convert_alpha(),shape
-
- def run_codes(self,cdata,rect):
- """Run codes.
-
- <pre>Vid.run_codes(cdata,rect)</pre>
-
- <dl>
- <dt>cdata <dd>a dict of code:(handler function, value)
- <dt>rect <dd>a tile rect of the parts of the layer that should have
- their codes run
- </dl>
- """
- tw,th = self.tiles[0].image.get_width(),self.tiles[0].image.get_height()
-
- x1,y1,w,h = rect
- clayer = self.clayer
- t = Tile()
- for y in range(y1,y1+h):
- for x in range(x1,x1+w):
- n = clayer[y][x]
- if n in cdata:
- fnc,value = cdata[n]
- t.tx,t.ty = x,y
- t.rect = pygame.Rect(x*tw,y*th,tw,th)
- fnc(self,t,value)
-
-
- def string2groups(self,str):
- """Convert a string to groups.
-
- <pre>Vid.string2groups(str): return groups</pre>
- """
- if str == None: return 0
- return self.list2groups(str.split(","))
-
- def list2groups(self,igroups):
- """Convert a list to groups.
- <pre>Vid.list2groups(igroups): return groups</pre>
- """
- for s in igroups:
- if not s in self.groups:
- self.groups[s] = 2**len(self.groups)
- v = 0
- for s,n in self.groups.items():
- if s in igroups: v|=n
- return v
-
- def groups2list(self,groups):
- """Convert a groups to a list.
- <pre>Vid.groups2list(groups): return list</pre>
- """
- v = []
- for s,n in self.groups.items():
- if (n&groups)!=0: v.append(s)
- return v
-
- def hit(self,x,y,t,s):
- tiles = self.tiles
- tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
- t.tx = x
- t.ty = y
- t.rect = Rect(x*tw,y*th,tw,th)
- t._rect = t.rect
- if hasattr(t,'hit'):
- t.hit(self,t,s)
-
- def loop(self):
- """Update and hit testing loop. Run this once per frame.
- <pre>Vid.loop()</pre>
- """
- self.loop_sprites() #sprites may move
- self.loop_tilehits() #sprites move
- self.loop_spritehits() #no sprites should move
- for s in self.sprites:
- s._rect = pygame.Rect(s.rect)
-
- def loop_sprites(self):
- as_ = self.sprites[:]
- for s in as_:
- if hasattr(s,'loop'):
- s.loop(self,s)
-
- def loop_tilehits(self):
- tiles = self.tiles
- tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
-
- layer = self.layers[0]
-
- as_ = self.sprites[:]
- for s in as_:
- self._tilehits(s)
-
- def _tilehits(self,s):
- tiles = self.tiles
- tw,th = tiles[0].image.get_width(),tiles[0].image.get_height()
- layer = self.layers[0]
-
- for _z in (0,):
- if s.groups != 0:
-
- _rect = s._rect
- rect = s.rect
-
- _rectx = _rect.x
- _recty = _rect.y
- _rectw = _rect.w
- _recth = _rect.h
-
- rectx = rect.x
- recty = rect.y
- rectw = rect.w
- recth = rect.h
-
- rect.y = _rect.y
- rect.h = _rect.h
-
- hits = []
- ct,cb,cl,cr = rect.top,rect.bottom,rect.left,rect.right
- #nasty ol loops
- y = ct/th*th
- while y < cb:
- x = cl/tw*tw
- yy = y/th
- while x < cr:
- xx = x/tw
- t = tiles[layer[yy][xx]]
- if (s.groups & t.agroups)!=0:
- #self.hit(xx,yy,t,s)
- d = math.hypot(rect.centerx-(xx*tw+tw/2),
- rect.centery-(yy*th+th/2))
- hits.append((d,t,xx,yy))
-
- x += tw
- y += th
-
- hits.sort()
- #if len(hits) > 0: print self.frame,hits
- for d,t,xx,yy in hits:
- self.hit(xx,yy,t,s)
-
- #switching directions...
- _rect.x = rect.x
- _rect.w = rect.w
- rect.y = recty
- rect.h = recth
-
- hits = []
- ct,cb,cl,cr = rect.top,rect.bottom,rect.left,rect.right
- #nasty ol loops
- y = ct/th*th
- while y < cb:
- x = cl/tw*tw
- yy = y/th
- while x < cr:
- xx = x/tw
- t = tiles[layer[yy][xx]]
- if (s.groups & t.agroups)!=0:
- d = math.hypot(rect.centerx-(xx*tw+tw/2),
- rect.centery-(yy*th+th/2))
- hits.append((d,t,xx,yy))
- #self.hit(xx,yy,t,s)
- x += tw
- y += th
-
- hits.sort()
- #if len(hits) > 0: print self.frame,hits
- for d,t,xx,yy in hits:
- self.hit(xx,yy,t,s)
-
- #done with loops
- _rect.x = _rectx
- _rect.y = _recty
-
-
- def loop_spritehits(self):
- as_ = self.sprites[:]
-
- groups = {}
- for n in range(0,31):
- groups[1<<n] = []
- for s in as_:
- g = s.groups
- n = 1
- while g:
- if (g&1)!=0: groups[n].append(s)
- g >>= 1
- n <<= 1
-
- for s in as_:
- if s.agroups!=0:
- rect1,rect2 = s.rect,Rect(s.rect)
- #if rect1.centerx < 320: rect2.x += 640
- #else: rect2.x -= 640
- g = s.agroups
- n = 1
- while g:
- if (g&1)!=0:
- for b in groups[n]:
- if (s != b and (s.agroups & b.groups)!=0
- and s.rect.colliderect(b.rect)):
- s.hit(self,s,b)
-
- g >>= 1
- n <<= 1
-
-
- def screen_to_tile(self,pos):
- """Convert a screen position to a tile position.
- <pre>Vid.screen_to_tile(pos): return pos</pre>
- """
- return pos
-
- def tile_to_screen(self,pos):
- """Convert a tile position to a screen position.
- <pre>Vid.tile_to_screen(pos): return pos</pre>
- """
- return pos
-
-# vim: set filetype=python sts=4 sw=4 noet si :