commands; post events/commands with delegate

This commit is contained in:
Frank DeMarco 2013-03-07 22:01:08 +09:00
parent 796999eb8f
commit 917370d502
9 changed files with 122 additions and 78 deletions

View File

@ -27,7 +27,7 @@ class Audio(GameChild):
self.fx = fx
def mute(self, event):
if self.is_command(event, "mute"):
if self.get_delegate().compare(event, "mute"):
self.muted = not self.muted
self.set_volume()

View File

@ -93,8 +93,9 @@ class Configuration(RawConfigParser):
set_option(section, "pause", "7")
section = "event"
add_section(section)
set_option(section, "custom-event-id", "USEREVENT")
set_option(section, "custom-event-name", "command")
set_option(section, "user-event-id", "USEREVENT")
set_option(section, "command-id-offset", "1")
set_option(section, "command-key", "command")
section = "audio"
add_section(section)
set_option(section, "sfx-path", "aud/fx/")
@ -252,7 +253,8 @@ class TypeDeclarations(dict):
"bool": "visible"},
"keys": {"list": ["up", "right", "down", "left"]},
"joy": {"int": ["advance", "pause"]},
"audio": {"path": "sfx-path"}}
"audio": {"path": "sfx-path"},
"event": {"int": "command-id-offset"}}
additional_defaults = {}
def __init__(self):

82
pgfw/Delegate.py Normal file
View File

@ -0,0 +1,82 @@
from pygame.event import get, pump, Event, post
from pygame.locals import *
from GameChild import GameChild
class Delegate(GameChild):
def __init__(self, game):
GameChild.__init__(self, game)
self.subscribers = dict()
self.disable()
def enable(self):
self.enabled = True
def disable(self):
self.enabled = False
def dispatch(self):
if self.enabled:
subscribers = self.subscribers
for evt in get():
kind = evt.type
if kind in subscribers:
for subscriber in subscribers[kind]:
self.print_debug("Passing %s to %s" % (evt, subscriber))
subscriber(evt)
else:
pump()
def add_subscriber(self, callback, kind=None):
self.print_debug("Subscribing %s to %s" % (callback, kind))
if kind is None:
kind = self.get_command_event_id()
subscribers = self.subscribers
if kind not in subscribers:
subscribers[kind] = list()
subscribers[kind].append(callback)
def get_command_event_id(self):
config = self.get_configuration("event")
return config["command-id-offset"] + globals()[config["user-event-id"]]
def remove_subscriber(self, callback, kind=None):
if kind is None:
kind = self.get_command_event_id()
self.subscribers[kind].remove(callback)
def compare(self, evt, commands=None, **attributes):
if commands is not None and not isinstance(commands, list):
commands = [commands]
if not attributes:
return self.command_in_list(evt, commands)
if commands is not None:
if not self.command_in_list(evt, commands):
return False
return all(key in evt.dict and evt.dict[key] == value for \
key, value in attributes.iteritems())
def command_in_list(self, evt, commands):
return self.get_command_attribute(evt) in commands
def get_command_attribute(self, evt):
return evt.dict[self.get_command_key()]
def get_command_key(self):
return self.get_configuration("event", "command-key")
def build_command(self, command, **attributes):
return Event(self.get_command_event_id(),
self.add_command_to_attributes(command, attributes))
def add_command_to_attributes(self, command, attributes):
attributes[self.get_command_key()] = command
return attributes
def post(self, command=None, kind=None, **attributes):
if kind == None:
event = self.build_command(command, **attributes)
else:
event = Event(kind, attributes)
post(event)

View File

@ -12,7 +12,7 @@ class Display(GameChild):
self.set_caption()
self.set_icon()
self.set_mouse_visibility()
self.subscribe(self.get_custom_event_id(), self.toggle_fullscreen)
self.subscribe(self.toggle_fullscreen)
def set_screen(self, flags=0):
self.screen = display.set_mode(self.config["dimensions"], flags)
@ -37,7 +37,7 @@ class Display(GameChild):
return self.screen.get_size()
def toggle_fullscreen(self, event):
if self.is_command(event, "toggle-fullscreen"):
if self.get_delegate().compare(event, "toggle-fullscreen"):
screen = self.screen
cpy = screen.convert()
self.set_screen(self.screen.get_flags() ^ FULLSCREEN)

View File

@ -1,41 +0,0 @@
from pygame import event
from pygame.locals import *
from GameChild import *
class EventDelegate(GameChild):
def __init__(self, game):
GameChild.__init__(self, game)
self.subscribers = dict()
self.disable()
def enable(self):
self.enabled = True
def disable(self):
self.enabled = False
def dispatch_events(self):
if self.enabled:
subscribers = self.subscribers
for evt in event.get():
kind = evt.type
if kind in subscribers:
for subscriber in subscribers[kind]:
self.print_debug("Passing %s to %s" %\
(evt, subscriber))
subscriber(evt)
else:
event.pump()
def add_subscriber(self, kind, callback):
self.print_debug("Subscribing %s to %s" %\
(callback, kind))
subscribers = self.subscribers
if kind not in subscribers:
subscribers[kind] = list()
subscribers[kind].append(callback)
def remove_subscriber(self, kind, callback):
self.subscribers[kind].remove(callback)

View File

@ -9,7 +9,7 @@ from Animation import *
from Audio import *
from Display import *
from Configuration import *
from EventDelegate import *
from Delegate import *
from Input import *
from ScreenGrabber import *
@ -59,7 +59,7 @@ class Game(GameChild, Animation):
self.display = Display(self)
def set_delegate(self):
self.delegate = EventDelegate(self)
self.delegate = Delegate(self)
def set_input(self):
self.input = Input(self)
@ -71,7 +71,7 @@ class Game(GameChild, Animation):
self.screen_grabber = ScreenGrabber(self)
def sequence(self):
self.delegate.dispatch_events()
self.delegate.dispatch()
self.update()
display.update()
@ -79,5 +79,5 @@ class Game(GameChild, Animation):
pass
def end(self, evt):
if evt.type == QUIT or self.is_command(evt, "quit"):
if evt.type == QUIT or self.delegate.compare(evt, "quit"):
self.stop()

View File

@ -1,7 +1,7 @@
from os.path import exists, join, basename, normpath, abspath
from sys import argv
from pygame import mixer, event
from pygame import mixer, event, time
from pygame.locals import *
import Game
@ -63,36 +63,34 @@ class GameChild:
return normpath(path) == abspath(path)
def subscribe(self, callback, kind=None):
kind = self.resolve_event_type(kind)
self.get_game().delegate.add_subscriber(kind, callback)
self.get_game().delegate.add_subscriber(callback, kind)
def resolve_event_type(self, kind):
if kind is None:
kind = self.get_custom_event_id()
return kind
def unsubscribe(self, callback, kind=None):
kind = self.resolve_event_type(kind)
self.get_game().delegate.remove_subscriber(kind, callback)
self.get_game().delegate.remove_subscriber(callback, kind)
def get_custom_event_id(self):
return globals()[self.get_configuration().get("event",
"custom-event-id")]
# def get_command_event_id(self):
# config = self.get_configuration("event")
# return config["command-id-offset"] + globals()[config("user-event-id")]
def is_command(self, evt, command, **attributes):
if not isinstance(command, list):
command = [command]
return evt.type == self.get_custom_event_id() and \
evt.dict[self.get_custom_event_name()] in command and \
self.event_contains(evt, attributes)
# def is_command(self, evt, names, **attributes):
# if not isinstance(names, list):
# names = [names]
# return evt.type == self.get_custom_event_id() and \
# evt.dict[self.get_command_attribute()] in names and \
# self.event_matches(evt, attributes)
def event_contains(self, evt, attributes):
return all(key in evt.dict and evt.dict[key] == value for \
key, value in attributes.iteritems())
# def event_matches(self, evt, attributes):
# return all(key in evt.dict and evt.dict[key] == value for \
# key, value in attributes.iteritems())
def get_custom_event_name(self):
return self.get_configuration("event", "custom-event-name")
# def get_command_attribute(self):
# return self.get_configuration("event", "command-attribute")
def post_command(self, command, **attributes):
attributes[self.get_custom_event_name()] = command
event.post(event.Event(self.get_custom_event_id(), attributes))
# def post_command(self, command, interval=None, **attributes):
# attributes[self.get_command_default_attribute()] = command
# evt = event.Event(self.get_command_event_id(), attributes)
# if interval is not None:
# time.set_timer(evt, interval)
# else:
# event.post(evt)

View File

@ -47,6 +47,9 @@ class Input(GameChild):
if key in keys:
self.post_command(cmd)
def post_command(self, cmd):
self.get_delegate().post(cmd)
def translate_joy_button(self, evt):
if not self.suppressed:
button = evt.button

View File

@ -15,7 +15,7 @@ class ScreenGrabber(GameChild):
self.subscribe(self.save_display)
def save_display(self, event):
if self.is_command(event, "capture-screen"):
if self.get_delegate().compare(event, "capture-screen"):
directory = self.get_configuration().get("screen-captures", "path")
try:
if not exists(directory):