Extensions:Uni-Verse/PyVerse
目次
Introduction
This page briefly describes PyVerse, which is makes it possible to write Verse applications in the Python language.
PyVerse was not written by an "official" Uni-Verse developer, but it is mentioned here since it is of big general interest, and very high-quality. It was developed volunteerly in true open source/free software fashion by Brecht Van Lommel. We are very grateful that he did the work, and also that he made the results public.
Installation
Installing PyVerse is currently very simple in Linux, where you simply build it from the source code. Download the code from the page linked above, enter a few simple commands, and install the resulting Python module into your system's Python environment, and you're done.
For Windows, it's easiest to rely on Brecht's pre-compiled binary releases, which are also on the above page.
Benefits
Compared to writing Verse applications in Python, there are some advantages:
- You get to use Python. Of course, this is only a benefit if you know Python. On the other hand, Python is nice, so why not learn it? Since you're reading this in the first place, chances are of course that you already do.
- Development can be quicker when you are free from the edit-compile-test cycle, and can cut it down to just edit-test.
- Save on code. Python is very expressive, and has powerful data structures and object orientation features built in, so you can really cut down on the number of lines of code you need to write to accomplish a given task.
Examples
Just to provide a few pointers on how to use PyVerse, here are a couple of sample programs. More examples can be found on Brecht's site, too.
"Hello Verse"
This is perhaps the simplest Verse program that makes sense. All it does is connect to a Verse server, request a list of all nodes, and print them as they are described by the server.
#!/usr/bin/env python
#
# Simple PyVerse example, that just prints the ID and type
# of each node it can find on a server on localhost.
#
import verse
def cb_node_create(node_id, node_type, owner):
print "There is a node called %u, of type %d" % (node_id, node_type)
verse.callback_set(verse.SEND_NODE_CREATE, cb_node_create)
verse.send_connect("hello", "<secret>", "localhost", 0)
verse.send_node_index_subscribe(~0)
while 1:
verse.callback_update(100000)
There are several points worthy of noting, here:
- The PyVerse module is named "verse", as seen in the import statement. Often, to save on typing and make the code easier to read, the module is given a local (shorter) name, e.g.
import verse as v
. - Callbacks are "keyed" by a set of constants whose names mimic the command-sending functions'. This is unlike the C API, where the actual command-sending functions are used directly (as function pointers).
- You can use ~0 as argument to the
node_index_subscribe
command to ask for nodes of all types. This saves on typing. - The sample program does not terminate, it sits forever waiting for node_create callbacks.
Checker
This slightly more advanced program creates content dynamically on a server. The content is not very interesting visually, being just a checkered bitmap, but the principle is important.
#!/usr/bin/env python
#
# Another PyVerse example. This creates a checkerboard bitmap.
#
SIZE=256
TOGO=3
import verse
def check(x, y):
if y & 1:
return x & 1 != 0
return not ((x & 1) != 0)
def cb_b_layer_create(node_id, layer_id, layer_type, name):
global TOGO
for y in xrange(SIZE / verse.B_TILE_SIZE):
for x in xrange(SIZE / verse.B_TILE_SIZE):
if check(x, y):
tile = verse.B_TILE_SIZE * verse.B_TILE_SIZE * [0]
else:
tile = verse.B_TILE_SIZE * verse.B_TILE_SIZE * [255]
verse.send_b_tile_set(node_id, layer_id, x, y, 0, verse.B_LAYER_UINT8, tile)
TOGO -= 1
def cb_node_create(node_id, node_type, owner):
verse.send_b_dimensions_set(node_id, SIZE, SIZE, 1)
verse.send_b_layer_create(node_id, ~0, "color_r", verse.B_LAYER_UINT8)
verse.send_b_layer_create(node_id, ~0, "color_g", verse.B_LAYER_UINT8)
verse.send_b_layer_create(node_id, ~0, "color_b", verse.B_LAYER_UINT8)
verse.send_node_subscribe(node_id)
verse.send_node_name_set(node_id, "checker%u" % node_id)
def cb_connect(avatar, address, host_id):
verse.send_node_index_subscribe(1 << verse.BITMAP)
verse.send_node_create(~0, verse.BITMAP, True)
verse.callback_set(verse.SEND_CONNECT_ACCEPT, cb_connect)
verse.callback_set(verse.SEND_NODE_CREATE, cb_node_create)
verse.callback_set(verse.SEND_B_LAYER_CREATE, cb_b_layer_create)
verse.send_connect("checker", "<secret>", "localhost", 0)
while TOGO > 0:
verse.callback_update(100000)
while verse.session_get_size() > 10:
verse.callback_update(100000)
The program follows a very simple flow, having three distinct steps, each of which is implemented by a separate Verse callback:
- When connected, create a new bitmap node
- When the node is created, create three layers in it
- When each layer is created, set its tiles to a checkerboard
The TOGO
variable counts down as layers are created, and the program is donw when it reaches zero. It starts out at three, since we create red, green and blue layers (resulting in a black/white checkerboard).
A few further points to note:
- PyVerse has node-type constants named just OBJECT, BITMAP, and so on. This is in contrast to the C API's V_NT_OBJECT etc.
- The bitmap is checkered at the tile resolution, meaning that entire tiles are set to either black or white. Adjusting this to have an arbitrary checker size, in tiles (or, harder, pixels) is a good exercise for the interested reader.
- The check() function returns a boolean fill-status for the given tile.
- The final
while
-loop attempts to flush the session's outbound packet queue, to avoid quitting too soon after being "done".
More Examples
If you want to see more sample code using PyVerse, one good place to start looking is in the puyo CVS module. This module holds an experimental user interface client for the Purple data flow computation engine, and is written in Python.
Compared to the examples above, puyo is very large (around 2,100 lines), so it is perhaps best to begin with programs like the above, to get more used to the concepts involved.