Mirra
2D OpenGL graphics Python framework by www.ixi-software.net
version alpha 0.3.5 - May 08.
Contribute : If you want to contribute drop us a mail. Current plans are to port some modules to C as a extension to Python, we would need some help here from people with experience developing Python extensions in C.
Download page : http://www.ixi-software.net/mirra
Contents of documentation:
- Description
- License
- System requirements
- Mailing list
- Installation
- Changes
- Short tutorial (how to
use, built-in classes description, tips about Mirra, event system
description, etc...)
- API, command reference
- OpenSoundControl module description
- Creating executables and apps under
windows and macintosh
- Extending Mirra
- To do
- Contents of Mirra
- Aknowledgements
- Feedback
Mirra is a 2D OpenGL graphics library based on Python. Mirra allows
for the creation of 2D interfaces, games or applications. It defines a
set of classes to render primitive shapes (Text, Pixel, Line, Circle,
Rect, Bitmap, BitmapPolygon), it manages rendering and user input
(mouse and keyboard). Mirra focuses on interaction and implements an
event managing system and classes that capture mouse events (in a way
like Macromedia Director or Flash do).
Mirra can send and receive OpenSoundControl messages via the
OSC module. It allows to easily create exe and apps out of your scripts
and also offers some basic sound features.
Mirra can be run with the following window systems : wxPython,
Pygame-SDL (by default).
Using either Pygame or WxPython gives you access to various different
features from those libraries such as import menus, drag&drop,
basic sound features, etc... Check their websites for more info about
what can be done with them --> www.pygame.org
| www.wxpython.org
Mirra has been also thought to be used to teach basics of programming to students by manipulating graphics.
This library is free software; you can redistribute it and/or modify it
under the terms of the Lesser GNU, Lesser General Public License as
published by the Free Software Foundation.
This library is distributed in the hope that it will be
useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Mirra contains small parts by others such as OSC.py by Daniel Holth
under Lesser GPL. Licence and credits are included on those parts from
others.
Mirra works under any platform where Python runs (OS X, GNU/Linux,
Windows, etc...).
You will need to have Python plus some Python libraries (PyOpenGL and
Pygame(SDL)) installed on your machine. You might need as well wxPython
(if you choose to use wxPython to handle the application's window
instead of Pygame). If you want to export your scripts as exe (windows)
or app (Mac) you will need py2exe (windows users) or pyapp (mac users).
- Must be there:
Python - www.python.org
Pygame - www.pygame.org
PyOpenGL - pyopengl.sourceforge.net
- Optional :
WxPython - www.wxpython.org
Py2exe (win) - www.py2exe.org
Py2app (mac) - www.pythonmac.org/wiki/py2app
OS X users http://pythonmac.org/packages/
(*) Under some versions of Windows you might need to install as well GLUT32.dll to get OpenGL running. This can be downloaded from http://www.xmission.com/%7Enate/glut.html . Just copy the glut32.dll into your c:\windows\system32 folder
For questions, info about updates, etc.... subscribe to Mirra
mailing list here :
http://lists.goto10.org/cgi-bin/mailman/listinfo/mirra
Uncompress the zip cd to the mirra folder and on the terminal type : 'python
setup.py install'. Windows users can use the exe installer provided.
0.3.5 :
- Engine class from graphics.py converted to module engine.py with functions this allows to avoid having to pass the reference to engine
on each render. Drawing functions are now accesed by importing engine. (First step towards moving this part of code into C)
- removed visible property
0.3.2 :
- killMe() renamed to end()
- implement properties for the Base class like rect or quad that update on the
fly when you change location, etc...
- added preferences system (check example provided)
- removed pygame from main,py and events.py this disables self.env and should
slightly improve performance on event handling
- added end() function to App
0.3.1 :
- fullscreen overwrites pos and size properties to fit display's size
- added self.width and self.height to main app. they return same as self.size[0]
and self.size[1]
- fixed data folder problem on export.py for windows. need to be checked yet
on mac
0.3 :
- (finally!) Fixed basic integration with wxPython
- fixed error in some linux system with sound from externals sound engines colliding with pygame audio. From now on
audio needs to be initalised manually with self.initAudio()
- tested ChucK and SuperCollider as external sound engines.
- fixed mayor errors with wxpython
- fixed export.py module errors under windows
- added startup preferences system. Check example 16 and prefs.txt files
0.2.8.2 (Piksel):
- added rect class as property of graphical objects. This allows to have
x,y,loc properties connected to a rect left,top,right,bottom, quad properties.
- trying experimental 3D mode
- added draw styles to Circles, Arcs, Lines, Rects and Polygons
- changes on rendering stack system
- added Arc drawing primitive class
- added end() method to primitive classes
- massive changes on render engine to optimise performance: reduced amount of
code executed on the render loop, optimised loops, optimised drawing methods
- improving documentation files to include a better API description
- improving documentation and comments on the code
0.2.8.1 :
- fixed errors on setup.py installer script, exe installer provided for
windows users - fixed bugs on Bitmap instances when calling tile() and
setImage() - Implemented support for images with transparencies -
graphics.py cleaned, there where some old lines of code not used
anymore.
0.2.8 :
- Using py2exe / py2app now it can easily be created self executables
(mac and win, linux users dont need this) non dependent from Python
interpreter or library dependencies. Check 15export.py example.
- added mouseVisible property to App. self.mouseVisible = 0 will hide
the mouse (but itwill keep active!)
- end() happends now just before quiting pygame and not after
- Bitmap and tmapPolygon images can be changed on the fly with
setImage(pathtoimage) method, check examples related to textures
- several changes to optimise performance
- more extendingclasses examples added
- modified opengl setup suggested by tom betts to get rid of unnecesary
coordinate and angle translations.
- finally fixed wx problems with refresh thanks to tip from robin dunn.
Currently reconstructing wx support and creating examples. gui.py added
back.
- fixed bug on mouse click that caused some mouse clicks not to be
recognised properly.
- top app's mouseLoc implemented as a python property on pygame
- small changes on events.py to add mouseLoc to wx
0.2.7 :
- added pong.py to examples
- changed resources importing method to allow mirra to work as a proper
python library
- added start method to Base class to avoid having to extend __init__
always when extending bult-in classes
- solved bug with start() on main.App class - added more examples
0.2.6.1 :
- changed tabs to spaces in all files to avoid problems in some editors.
- bug fixed, property blend was not active.
- bug fixed, killMe() method was not working properly. Thanks to Dan Law.
- bug fixed, instances where added twice to rendering stack because of
new z property system. Thanks to Dan Law.
- bug fixed, setting the loc now work on Line class. Thanks to Dan Law.
0.2.6 :
- removed setters and getters for a more pythonic Mirra. This causes
mayor changes on the API, check 'Short tutorial' section for more
details.
- added visible property to all shapes
- small optimisation changes and code clean up
- license changed to LGPL to allow for commercial use of Mirra
0.2.5.7 :
- wxPython frames (with menus, status bars etc..) can be defined in a
custom module. Before it was hard wired (just for testing) inside the
mirra package. Check example6wxPython.py for usage
- render stack performance improved. Before it was a bidimensional
array a 'bucket' for each Z depth(and they where 1000!), every time it
rendered it had to go through each bucket rendering its shapes. Now it
is one dimensional array where objects are shorted depending on their Z
when created. The work is done on creation time and not every time it
renders! . We are tying to improve...
- small changes to improve performance here and there ...
- joystick support added (only under pygame at the moment). Example
provided.
- added keyUp() event to event manager. Modified KeyDown() now it only
receives an argument with the pressed key code. (many thanks to Peter
Goode for pointing this out)
- added render() method to MirraApp. This
feature has been added just for completenes, it is handy to test
drawing methods. Check example11directdrawing.py
- added end() method to MirraApp. It is called
just before
the application is closed. Good place to kill processes, write
preferences to disk, etc...
0.2.5.6 :
- added basic audio functionality using pygame (to be extended and
improved over next releases).
- fixed bug on setColor(). Alpha was default to 0 instead of 1 causing
shapes to disapear if no alpha was passed.
- fixed bug on intersection with rotated Rects.
- hard-coded wxPython dependency removed and coded proper system exits
if PyOpenGL or Pygame are not found.
- improved documentation and examples
- circles diameter argument is now called width.
0.2.5.5 :
- GLUT dropped in favor of Pygame. This way dependency from PIL library
has been removed.
- support for more image file types added thanks to pygame
- mayor changes on graphics.py module to make class structure more
clear and simple trying to avoid using multiple inheritance too much.
- added constrain to dragged shapes --> self.setConstrainRect(left,
top, right, bottom). To reset do self.setConstrainRect(0,0,0,0)
- All shapes have now (inherited from Base) a built it
self.getMouseLoc() method
- Base class keeps now a reference to the main App instance so that all
objects inheriting from Base can comunicate back. This makes for
example the access to mouseLoc more easy and clear to implement.
Because main App knows about the mouseLoc it can be asked for its value
using that reference. A class called Test could do
Test.app.getMouseLoc() and would get a tupple containing x and y of
current mouseloc. The previous system was more obscure than this one.
0.2.5.4 :
- bug fixed : eventhandler instance didnt receive the MirraApp instance
so it couldnt pass back events to it.
- small changes in documentation and examples
- added to MirraApp class a method to access the mouse location
-->
getMouseLoc()
0.2.5 :
- optimised bitmap handling system (images are stored as static
property of graphics engine class)
- WxPython and Pygame support added.
- new examples added and documentation improved
- small changes on rendering method to improve performance and some z
location errors.
- bug fixed : when shape.setInteractiveState(1) and draggged there was
a weird behavior
- Text class implements now setText(string) and getText()
- Text class implements default GLUT fonts
- Rects have now height and width allowing to create rectangles as well
as squares
- small changes and cleanup on utilities.py module
- Base object implents :
self.mouseLoc --> gives access to mouse location
self.blend = float --> sets alpha component of instance's color
self.blend --> returns alpha component of instance's color
0.2.2 : solved flickering when two shapes are in the same z location
0.2.1 : solved bug with flipH() and flipV() in Rects
:: How to use it? ::
The mirratemplate.py module provides a
template for your application. The simplest way to start working is to
code using this template as a base. Basically you need to create a .py
module where there is a class that extends main.App (like MirraApp
does). Check examples 1 to 4
By intialising this app class, the main window and rendering system
will be initialised according to the parameters you pass to the
MirraApp during setUp() (environment, caption, size, position,
framerate, fullscreen).
You will be able to use several methods inherited from
main.App where you can place code such as start(), step() and several
mouse and joystick events. By extending those methods you can create
complex applications. There are several system properties that can be
set or checked on the fly such as trails, mouseVisible and bgColor.
Primitive drawing classes can be used to draw shapes that can be moved,
clicked and dragged. By extending those classes you will be able to
create complex graphics and behaviors.
It is a good idea to place images, sounds, etc... in the 'data' folder
as they get automatically packed when you export you script as exe or
app. Mirra supports for many image file types, SDL is used to load
media.
To run your code just run with the Python interpreter the file you are
working on. On windows just double click your .py file. Under unix
systems (GNU/linux, OSX ..) you would type on the console something
like 'python mirratemplate.py' (windows users can also run it from
command line, this will actually give better feedback about errors as
the console wont quit after the end of the script).
Several other examples are available in the main folder for you to
learn using the basics of this framework. They are named '01example.py',
'02example_events.py', 'example_osc.py'
and so on.
Mirra allows to create self executables non dependent from Python interpreter and dependencies by using the py2app and py2exe, check example 15export_app.py or the section of this file 'Creating executables for windows or mac
:: Some tips about Mirra ::
- About MirraApp:
MirraApp is the application class, lets say it is the place where
everything lives. It can set and get few properties of the main window
(described above) like :
self.trails --> boolean
self.bgColor --> r,g,b
About all graphical classes :
All graphical classes (Rect, Circle, ...) are subclass of Base class.
This means that they inherit few handy methods and properties from it,
like loc, z, color or app
(which is a reference to the top application instance, this allows to
comunicate back to the application for example to ask for the mouse
location or the background color and size of the window). Check the
description of Base class above to see the methods available for all
graphical classes.
- Instanciating built-in classes in MirraApp:
Built-in classes' instances are automagically added to the rendering
stack as soon as you instanciate them. This means that the rendering is
done under the hood and that you should not, in principle, worry about
it too much. This is why just by calling Text('hi there', 100, 100)
renders that text without us having to save a reference to the instance
of the Text class initialised. A reference to that particular object
has been added to the rendering stack, under the hood, as soon as it
has been created. The graphic engine uses this reference to render the
instance in the right place and order. Iif you want to know more about
this check the render() function
in engine.py module.
So, what if we want to manipulate the location or some other property of the instance? We should keep as well a reference to that instance. To do this we should save it, for example, as a property of the MirraApp or some other class where this instance should live. For example in start() we would create a property self.label = Text('number 5', 100, 100). The reference would allow us to change the loc of the instance from mainApp's step() method by calling the instance's internal method self.label.loc = x,y. Check the examples provided. We could as well save it as a global variable in our working module.
- Extending built-in classes:
Check example 7 to 8, and others like snow.py, orbit.py etc...
If you want to make something more complex that just displaying some
basic shapes, like for example you want to have objects that move and
bounce agains window limits, you will need to extend the basic classes
to define methods that calculate movement and collision against walls.
- Event system description :
Events are controlled by the window system(wxPython or Pygame(SDL)) and
binded to functions in the eventListener instance (in events.py) whose
instance lives in the main App. The event listener asks the graphics
engine for intersections between mouse and some clickable/draggable
graphical object on the graphical stack of the engine. If intersection
is true then it passes the event to the intersected object, if none is
intersected it tries to pass the event up to the main App you are
working in (usually MirraApp). In case you dont define those events on
the main app then it just skips the event.
Mouse location can be accessed from the main App as property
self.mouseLoc. It is a tuple containing the current x and y loc of the
mouse. Because all graphical objects extend Base they can access the
mouse location by calling self.app.mouseLoc
questions or suggestions are welcome to info@ixi-software.net or to the
Mirra mailing list
This API reference describes the main public commands you can use to manipulate Mirra. It is structured in three main areas (main app class, graphic primitive classes and utilities).
:: Main app class (defined in main.py)::
Here there is a complete description of your MirraApp class where most of your code will live
> General system functions. Check mirratemplate.py
start(self) | # just when starting the app. Good place to initialise variables, objects or general stuff | ||||||||||
step(self) | # called every frame, frequency depends on frameRate set on setUp() | ||||||||||
end(self) | # called just before killing the application | ||||||||||
setUp(self) | # In setUp we initialise the whole application and set
the main application's parameters *Note*: fullScreen=1 overwrites size and pos |
||||||||||
render() |
# we can extend this method to draw directly by using
the engine's module drawing functions or by coding directly
OpenGL. For example |
||||||||||
> Environment properties that are defined during setUp() | |||||||||||
|
|||||||||||
|
> Mouse and keyboard events functions- Read 'Event system description' paragraph in this file for more info. Check 03.events.py
mouseDown(self, x,y) | # x and y is the mouse coordinates at the moment when the event is triggered |
mouseUp(self, x,y) | |
mouseDragged(self, x,y) | |
rightMouseDown(self, x,y) | |
rightMouseUp(self, x,y) | |
keyDown(self, key) | # key arg is the key being pressed : Check key reference for more details |
keyUp(self, key) | # key arg is the key being released : Check key reference for more details |
> Joystick events, (not working if using wxPython on OSX, otherwise is runs fine). Check 12joystick.py
(more joystick/gamepad events to be implemented) | |
joyAxisMotion(self, joystick, index, value) | |
joyBallMotion(self, joystick, index, value) | |
joyHatMotion(self, joystick, index, value) | |
joyButtonDown(self, joystick, button) | |
joyButtonUp(self, joystick, button) |
> General properties of the sytem that cab be get and/or set at any point
# can only be get : | |
self.width | # returns windows width, same as size[0] --> int |
self.height | # returns windows height, same as size[1] --> int |
# can be set and get : | |
self.mouseVisible = 1 | # mouse visibility on/off --> boolean |
self.bgColor = r,g,b,a | # window's background color --> rgba tuple like (0.1, 0, 0, 0.04) |
self.trails = b | # trails on or off --> boolean |
> General SDL audio system functions that can be called. Check example 09audio.py
Audio methods : | |
self.initAudio() | # starts SDL audio |
self.playSound(self, path, volume=1.0, pan=0.5, channel=0, loop=0, maxtime=-1) | # plays a sound |
self.findFreeChannel(self) | # returns a free channel in the mixer |
setVolume(self,channel, volume=1, pan=0.5 | # sets volume and pan of given chanel |
self.preLoadSound(self, path) | # preload a sound file |
self.getVolume(self,channel) | # get channel volume |
self.stopSound(self,channel) | # stop channel |
self.pauseAll(self) | # pause all channels |
self.unpauseAll(self) | # resume all channels |
self.stopAll(self) | # stop all channels |
> Preferences related functions. Check example 16preferences.py and prefs.txt
self.readSetUpPrefs(self, aprefsfile) | # executes lines in file UNTIL 'others' keyword |
self.readOtherPrefs(self, aprefsfile) | # executes lines in file AFTER 'others' keyword |
The basic idea is that there is a txt file with python commands. Those commands
are executed by python
when readSetUpPrefs() or readOtherPrefs() are called. We need to keep setUp
preferences separated from other
preferences by a comment line with 'others' keyword on it. Check prefs.txt for
format example. Each of the functions will read its part of the file. SetUp
prefs need to be executed from setUp() function and others can be executed and
any time after setUp, for example start() is a good moment.
This system can be used to set an initial state for your application, this only makes sense if you have created a exe or app with py2exe and py2app or if you dont want to edit the initial values for your variables in the source. Otherwise you would do the same result by editing the source. This was developed for situations where source can not be edited.
::: Description of graphic primitive classes defined by Mirra (defined
in graphics.py module) :::
Primitive graphic classes available currently are: Text, Pixel, Line, Rect, Polygon, Circle, Bitmap, BitmapPolygon
> Primitive classes details (defined in graphics.py).
Check 01allclasses.py and 01allclasses2.py
Text:
Draws a text given x,y,z, font family, font size, and color.
args : string, x, y, z, font, size, color
example : Text("hello world", 10, 100,
1, 'helvetica', 10, (0.1, 1, 0.3, 0.8))
NOTE - available fonts ans sizes are:
> typewriter 13 and 15
> timesroman 10 and 24
> helvetica 10, 12 and 18
other values would cause an error.
Text class also implements :
text = string # to update
displayed string on the fly
example: myLabel.text = 'bye world'
Pixel:
Pixel(x, y, z, color)
Draws a pixel given x,y,z and color.
example : self.pixel =
Pixel(x=12, y=100, z=900, color=(1,0,0,0.5))
Line:
Line(a, b, z, color, stroke, rotation)
example : self.line = Line( a=(1,1), b=(100,100), z=20,
color=(0.2,0,0,1), stroke=10, rotation=45, style=0)
Draws a line given the begining and end point (as tupples with x,y),
color (tupple) and stroke (thickness of line) and rotation. style is a
value like 0xF0F0 (dashed line), 0xF00F (long dashed line) or 0x8888
(dotted lines)
Polygon:
Polygon(vertexarray, z, color, stroke,
rotation)
Polygon described with an array that contains tuple points of each
vertex.
example : self.poly = Polygon(vertexarray=[(0, 0), (29, 100), (30,
200)], z=100, color=(0,0.3,0.1,1), stroke=0, rotation=23, style=0)
style is a value like 0xF0F0 (dashed line), 0xF00F (long dashed line)
or 0x8888 (dotted lines)
Rect:
Rect(x, y, z, width, height, color,
stroke, rotation)
example : self.rect = Rect(x=10, y=100, z=1, width=40, height=60,
color=(0.5,0.5,0.5,1), stroke=0, rotation=90, style=0)
style is a value like 0xF0F0 (dashed line), 0xF00F (long dashed line)
or 0x8888 (dotted lines)
Circle:
Circle(x, y, z, width, color, stroke,
rotation)
example : self.circle = Circle(x=20, y=100, z=1, width=300,
color=(1,1,0,0.3), stroke=5, rotation=0, style=GLU_FILL)
style choices are : GLU_LINE, GLU_FILL, GLU_SILHOUETTE, GLU_POINT)
Arc:
Arc(x, y, z, width, color, stroke,
rotation)
example : self.arc = Arc(x=10, y=10, z=0, radius=1, start=0, sweep=1,
color=(0,0,0,1), stroke=0, rotation=0.0, style=GLU_FILL)
start is an angle, sweep is arc lenght in angles *anticlockwise*
style choices are : GLU_LINE, GLU_FILL, GLU_SILHOUETTE, GLU_POINT)
Bitmap:
Bitmap(file, x, y, z, width, height,
rotation)
example : self.bmp = Bitmap(file='data/pict.bmp', x=300, y=500, z=3,
width=300, height=250, rotation=45)
Bitmaps respond as well to these methods:
flipH()
flipV()
Both flip commands cause the image of the image of the shape
to be flipped (*but not the shape itself!!*)
tile(int)
example : mybitmap.tile(10)
This modifies property called 'texCoord' which defines the way the
image is mapped into the rect or polygon. Check the example2textures.py
and example2textures2.pymodule.
setImage(self, path)
example : mybitmap.setIMage("data/image.bmp")
changes the image of the shape for a new one, path is relative
BitmapPolygon:
BitmapPolygon(file, vertexarray, z,
rotation)
Described with an array that contains tuple points of each vertex.
args : file, vertexarray, z, rotation
example : self.bmpoly = BitmapPolygon(file='data/pict.bmp',
vertexarray=[(0, 0), (29, 100), (30, 200)], z=2, rotation=0)
BitmapPolygon also implements :
tile(self, int)
example : mybitmap.tile(10)
This modifies property called 'texCoord' which defines the way the
image is mapped into the rect or polygon. Check the tiled() example at
the sometests.py module.
setImage(self, path)
example : mybitmap.setImage("data/image.bmp")
changes the image of the shape for a new one, path is relative
* Note for Bitmaps and BitmapPolygon *
Both can receive an extra argument texCoord which
is an array of tupples that defines how the image is mapped into the
shape and it can be used to cause the image to be twisted. It is
defaulted to [(0, 1), (1, 1), (1, 0), (0, 0)] .
Check out some tutorial about OpenGL textures if you want to learn
about this.
> ALL of primitive graphic classes inherit from Base class the following PROPERTIES:
# can be get : | |
app | # reference to the top app (MirraApp or whatever you name it). It can be used to access variables from mirraApp such as mouseLoc, trails, bgcolor or any other that you might define. |
mouseLoc | # returns current mouse location --> x,y |
# can be set and get : | |
z | # z depth buffer position. Below 0 shapes are not visible - integer |
loc | # loc of instance - x,y |
color | # color of shape (alpha is default to 1) - r,g,b,a all must be float between 0 to 1 |
blend | # alpha component of color - float between 0 to 1 value |
rotation | # instances rotation clockwise in degrees - integer or float |
stroke | # instances drawing thinkness, 0 for filled shapes. Bitmap and BitmapPolygon dont use it. - integer |
interactiveState | # instance's interaction level to be : 2 (draggable), 1 (clickable) or 0 (no interactive). |
constrainRect | # constrains an object being dragged within the given rect. Check example10constrain.py - left,top,right,bottom |
clicked | # am i clicked by the mouse? - boolean |
textID | # Only Bitmap and BitmatPolygon. |
rect | # left, top, right, bottom position. Connected to x,y
and loc. You can do self.square.rect.left +=100 Does not work ok when rotation is on - To be changed soon |
-- to be added soon: | |
left, top,right, bottom | |
quad | # lefttop, righttop, bottomright, bottomleft locations of rect |
For more details check Base class at graphics.py
> ALL of primitive graphic classes inherit from Base class the following METHODS:
start(self) | # just after __init__ |
intersects(self, x,y) | # check intersection of shape with given x,y. Used for mouse events --> boolean |
step(self) | # called every frame, depends on fps set on main app setup. |
end(self) | # removes the instance from rendering stack. |
mouseDown(self, x,y) | # clicked by mouse |
mouseUp(self, x,y) | # unclicked by mouse |
rightMouseDown(self, x,y) | ... |
rightMouseUp(self, x,y) | ... |
mouseDragged(self, x,y) | ... |
render() | # render method called from engine following the right rendering order. Each shape has a different render method which can be extended (using render drawing methods from engine module or pure OpenGL) to allow for more complex shapes to be drawn. |
For more details check Base class at graphics.py
::: Utilities (defined in utilities.py) :::
path(res = '') | returns the absolute path to a file or folder passed as argument -> string |
Some random utilities : | |
randint(min, max) | returns random integer between min and max -> int |
random() | returns random float between 0 and 1 -> float between 0 and 1 |
randRGB() | returns random RGB tuple color -> tuple r,g,b |
randRGBA() | returns random RGBA tuple color -> tuple r,g,b,a |
randPoint(l, t, r, b) | returns a random point within a given a rect or four
limits-> x, y It can receive four limits (left, top, right, bottom) |
choice(seq) | choose one in a list with few items -> whatever
the choosen item is receives a sequence of items |
Some rect and quad utilities : | |
calcPolygonRect(pointArray) | receives a point list and returns the rect that contains them as a tupple -> tuple left, top, right, bottom |
calcRectCenter(l,t,r,b) | returns rect center point -> x,y receives left, top, right and bottom of a rect |
calcRectRect(x, y, width, height) | calcs surrounding rect of a rectangular shape ->
tuple left, top, right, bottom receives x, y , width, height |
calcRectQuad(x, y, width, height) | returns a list containing the vertex points of a rect
providing its x,y, width and height -> list [lefttop, righttop, rightbottom, leftbottom] receives x, y , width, height |
constrainToRect(x,y, r) | constrains a given x,y location to a given rect
-> tupple x,y receives x, y , rect as a tupple |
Some intersection utilities : | |
pointInLine(p, linePoints) | TO BE DONE -> returns false |
pointInRect(p, r) | returns true if a point is inside a rect. rect is
(left, top, right, bottom) -> Boolean receives a tuple (x,y) and a tuple(left,top,right,bottom) |
pointInCircle(p, p2, r) | if distance from point to circle center is smaller than
radius then it must be inside -> Boolean receives two tuples (x,y) and the radius of the circle |
pointInPoly(point, pointsList) | Return True if point is contained in polygon (defined
by given list of points.) -> Boolean receives a tuple (x,y) and a sequence of tuple locations ((x,y),(x,y),(x,y).(x,y)) |
distance(p1, p2) | Return the distance between two points, which may be
given as (x,y) tuples or as complex numbers. -> float receives two tuples (x,y) |
rotPoint(point, axis, ang) | Orbit. calcs the new loc for a point that rotates a
given num of degrees around an axis point, +clockwise, -anticlockwise
-> tuple x,y receives a tuple (x,y), tuple (x,y), and ang in degrees |
reverseAng(ang) | converts angles from OpenGL anticlockwise to clockwise
and the other way around -> int ang in degrees receives ang in degrees |
getAng(p1, p2) |
returns the ang in degrees between two points
*clockwise!* -> int ang in degrees |
::: Drawing methods from engine class (graphics.py) :::
Check example 11directdrawing.py, 04extendingclasses4.py and
04extendingclasses5.py
drawPixel(self, x=1, y=1, z=0,
color=(0,0,0,1))
Draws a pixel at a given x and y with given color .
Color = 3 or 4 arg tuple. RGB values from 0 to 1 being 1 max value (1,
1, 1) would be white
drawLine(self, p1, p2, z=0,
color=(0,0,0,1), stroke=0, rotation=0.0, style=0)
p1, p2 are two tuple points and color is tuple rgb, values range 0 to 1
Rotation in degrees. clockwise.
style is a value like 0xF0F0 (dashed line), 0xF00F (long dashed line)
or 0x8888 (dotted lines)
drawPolygon(self, v=[], z=0,
color=(0,0,0,1), stroke=0, rotation=0.0, texID=None, texCoord=[],
style=0)
v is an array with tuple points like [(x, y), (x2, y2), (x3, y3)]
min vertex number to draw a polygon is 3
stroke=0 to fill with color the inside of the shape or stroke=integer
just to draw N-px thick outline.
style is a value like 0xF0F0 (dashed line), 0xF00F (long dashed line)
or 0x8888 (dotted lines)
Note. It doesnt work with non covex polygons, need to implement
tesselation yet
drawRect(self, x=1, y=1, z=0,
width=10, height=10, color=(0,0,0,1), stroke=0, rotation=0.0,
texID=None, texCoord=[], style=0)
draws a rect
style is a value like 0xF0F0 (dashed line), 0xF00F (long dashed line)
or 0x8888 (dotted lines)
drawCircle(self, x=1, y=1,
z=0, radius=5, color=(0,0,0,1), stroke=0, rotation=0.0, style=GLU_FILL)
x, y, z, width in pixel, rotation, color and line width in px
style choices are : GLU_LINE, GLU_FILL, GLU_SILHOUETTE, GLU_POINT)
TO DO : textured circles
drawArc(self, x, y, z=0,
radius=1, start=0, sweep=1, color=(0,0,0,1), stroke = 0, rotation=0.0,
style=GLU_FILL)
start angle, sweep is arc lenght in angles *anticlockwise*
style choices are : GLU_LINE, GLU_FILL, GLU_SILHOUETTE, GLU_POINT
This methods can be used to extend the render method of Mirra's built in graphic primitives or to draw directly from the render method of our mainApp. For example you could extend the drawing method or a Rect to draw a circle around it, lets see how it would look:
class myCustomRect(Rect): # extends mirra.graphics.Rect class
def render() :
super(myCustomRect, self).render() # call superclass
method
e.drawCircle(self.x, self.y, z, self.width, self.color) #
calling engine instance drawing methods
To check wxPython key reference
def keyDown(self, k):
print k # this just prints the key number
the OSC module within Mirra allows to send and receive OSC
messages. OSC is a very handy network protocol, read more about it at http://www.cnmat.berkeley.edu/OpenSoundControl/
There is a exampleosc.py module where you are
provided with
a template of a Mirra file that sends and receives OpenSoundControl
messages. A PureData (http://pd.iem.org) patch called osc.pd explains
how to communicate Mirra with other software able to communicate via
OSC.
It can be as simple as doing this:
import osc
osc.init()
# defaults to ip 127.1.1.1 port 9000
osc.sendMsg(/hello, [666])
Check the exampleosc.py file for more details
Creating executables/apps for windows or mac :
Mirra allows to create self executables non dependent from Python interpreter and dependencies by using the py2app (http://undefined.org/python/#py2app) module on OSX and py2exe (http://www.py2exe.org) under windows. So you MUST have either of those libraries installed. On linux does not make much sense to do this so you have to install the libraries requiered.
**Note that currently (November 07) if you use PyOpenGL 3 under windows there are some issues with the way py2exe handles python eggs. This has to be solved by the py2exe developers. On the mean time you have to manually copy the pyOpenGL and setuptools eggs to your dist/lib folder after you pack your app with mirra. Check the example provided for details. The rest of this help is correct.
To make our lives easier, we created a crossplatform module inside Mirra that takes care off all this automatically. So all you need to do it to place this three lines in your setup()
import sys
from mirra import export
export.pack('myscript.py')
Next time you run your script, the export.pack() function will perform all steps required and after that it will quit. The process imports all the libraries and packages your app needs, it also imports all the files inside a folder called data next to your main script. So if you are importing images or audio you might want to place them there. After your script has quited you should find an folder called dist with the app (on mac) or with few files and folders (on windows) with the yourscript.exe file included. Copying the dist folder and to any machine should be enough to run it despite of that machine not having python or any libray installed. Note that the script might raise some error at some point, check the console output to see if everything went right.
In general you wont really need to change the command and the three lines above should be enough. But in case you want to do extra things like specify an icon, extra folders containing files (not included in data folder) or extra Python packages you can specify parameters to the command.
Note that on MAC the script deletes the previous dist during the process.
This the API for export.pack
pack(mainFile=, extraPackages=[], extraFiles=[], iconPath='')
Extra packages :
export.pack('myscript.py', extraPackages = [mypackage])
Custom icons :
export.pack('myscript.py', iconPath = 'myicon.ico') # OR myicon.icns on mac
Specifying extraFiles is a bit more complex, this is an
example of how to specify extra files and folders to be added to the
application:
files = [ ("stuff", ["stuff/slicer_pd.pd", "stuff/sampler.pd"]) ]
export.pack('myscript.py', extraFiles = files)
So a full complex example of the use would be:
import sys
from mirra import export
files = [ ("stuff", ["stuff/slicer_pd.pd", "stuff/sampler.pd"]),
("anotherfolder", ["anotherfolder/blah.txt"]) ]
export.pack('myscript.py', extraPackages = [mypackage], extraFiles = files,
iconPath = "data\\icon\\myicon.ico" )
More advanced users can create their own setup.py file for
py2app or py2exe, just remember to add mirra to the packages
included
and to manually copy the site-packages/OpenGL folder to the dist folder
on windows But you probably just want to stick to the simple use which
should be enough for most of us.
Because currently Mirra is just 100% Python plus some widely
used libraries (PyOpenGL, Pygame) you can easily use any part of the
Python standard library and other Python library to extend Mirra for
you needs, please let us know if you add something that would be of
interest for all Mirra users.
- wx : Joystick events implement (check if wxpython supports joysticks on
OSX)
- wx : update wx key reference example 03eventskey.py
- exceptions sometimes come from not the actual error, this is confussing for
debugging
- textured circles
- drop pygame to use only wx?
- add center button event
- delete textures from opengl memory when textured objects are deleted
- when trials is set to True it forces background to white color, need to find
a way to do this if possible.
- explore possibility to use Polygon library
- include pyode physics engine support
- posibility to use opengl scale. This would require to update with, height,
vertex etc... on the fly for the intersections and also to implement intersection
between point and elipse.
- more mouse events on objects like mouseUpOutSide, mouseOver, etc...
- optimise rendering:
explore possibility to delegate to C some rendering loops
# explore display lists # done: no much improvement
render by object types to call glBegin(GL_LINES) etc... only once rendering
all similar shapes in the same call
- support antialias
- tesselation on polygons
- try to create hierarchy systems (glPopMatrix and glPushMatrix) and allow for
relative locations.
- event driven (pop and not push) OSC system, maybe using Twisted?
- SuperCollider, OSW and Chuck sound examples with OSC
- implement some kind of object subgrouping system like in Flash. Maybe the
easiest way to do this is the user to use own lists to store objects instances
in groups?
- MIDI support
- video (Myron for webcams?)
- try nested ifs --> hash tables
- pygame : extend sound functionality
- wx : drag and drop
- wx : right/control click menu
- wx : other widgets? to be able to draw openGL window within a defined boxer
in the window
...
email us with your request or ideas to info@ixi-software.net or to the Mirra
mailing list
> /documentation
documentation.html
license.txt
> /examples
mirratemplate.py --> Application example
exampleosc.py --> OpenSoundControl example
examples 1 to N --> some examples using and extending the
built-in classes
wxgui.py --> (for wxpython only) example description of own menus, dialogues
and their functionality.
osc.pd --> PureData patch sending and receiving OSC to
exampleosc.py
+ other examples ...
> /mirra package folder:
main.py --> main application class
graphics.py --> main drawing classes and graphicsStack instance
events.py --> event handling classes
export.py --> py2exe / py2app setup script
utilities.py --> a handy bunch of functions (collisions, random
nums and colors, rotations, some triginometry and maths) and utility
classes such as the Stack class.
export.py --> py2exe and py2app functionality
> /mirra/OSC package folder:
OSC.py --> Open Sound Control library by daniel Holth
oscAPI.py --> simple interface to OSC.py by ixi
Currently Mirra is made thanks to the support and help of:
- The Digital Research Unit / Center for Excelence on Digital Design at
the University of Huddersfield. http://www.druh.co.uk
- Goto10 collective www.goto10.org
Thanks to Goto10 collective www.goto10.org for thir SVN hosting and mailing list.
Some parts of the development of Mirra were developed with the support from different institutions :
- The Digital Research Unit at the University of Huddersfield. http://www.druh.co.uk
- The Lansdown Center for Electronic Arts at Middlesex University who helped
providing expertise and support for developing the early versions of Mirra.
http://www.cea.mdx.ac.uk/
- Bizkaiko Diputazioa, Basque Country.
- Buchsenhausen Kunstlerhaus, Innsbruck, Austria.
Tom Schoulten, John Cox, Daniel Holth and Tom Betts for the technical help.
We would more than happy to hear your comments, suggestions or to incorporte
any improvement you might do to our code. Contact us on www.ixi-software.net
, Mirra's mailing list (http://lists.goto10.org/cgi-bin/mailman/listinfo/mirra)
or info@ixi-software.net
enjoy.