Level editing

Now I have a level editor! The exact API needs a bit of work so it's not checked into Cocos yet. The code is below though. It's fired whenever I press "e" and saves the XML to "editor-save.xml" when I close the tile palette window.
    @director.window.event
    def on_text(s):
        global editor
        if s == 'e':
            editor = TileEditorLayer(level, 'data/level-tiles.xml',
                'level-tiles', lambda layer: scene.remove(layer))
            scene.add(editor)
            director.window.push_handlers(editor)
            return True

class TileEditorLayer(cocos.layer.Layer):
    def __init__(self, map_layer, filename, id, on_done):
        super(TileEditorLayer, self).__init__()
        self.map_layer = map_layer
        tileset = cocos.tiles.load(filename)[id]
        tilesets = [
            (filename, ''),
        ]
        self.selector = TileSetWidget(tileset)

        @self.selector.window.event
        def on_close():
            self.map_layer.save_xml(tilesets)
            director.window.pop_handlers()
            self.selector.close()
            self.selector = None
            on_done(self)
            return True

    def on_mouse_press(self, x, y, buttons, modifiers):
        x, y = self.map_layer.get_virtual_coordinates(x, y)
        cell = self.map_layer.get(x, y)
        cell.tile = self.selector.tileset[self.selector.current.tile_id]
        self.map_layer.set_dirty()

class TileSetWidget(object):
    def __init__(self, tileset):
        self.window = pyglet.window.Window(width=64,height=256,
            style=pyglet.window.Window.WINDOW_STYLE_TOOL)
        self.window.push_handlers(self)
        self.tileset = tileset
        y = 0
        self.batch = pyglet.graphics.Batch()
        self.sprites = []
        for n, k in enumerate(tileset):
            s = pyglet.sprite.Sprite(tileset[k].image, y=y, batch=self.batch)
            if not n:
                self.current = s
                s.color = (255, 200, 200)
            s.tile_id = k
            self.sprites.append(s)
            s.scale = 32. / s.width
            y += 32

    def on_mouse_press(self, x, y, buttons, modifiers):
        for s in self.sprites:
            if x < s.x or x > s.x + s.width: continue
            if y < s.y or y > s.y + s.height: continue
            self.current.color = (255, 255, 255)
            self.current = s
            s.color = (255, 200, 200)
            return True

    def on_draw(self):
        self.batch.draw()

    def close(self):
        self.window.pop_handlers()
        self.window.close()

Oh, and see that dual-window thing going on there? pyglet rocks :)

richard on 2008/03/31 10:53 of Flat Bot
edited on 2008/03/31 06:14