ev.apply(self)
def change_scene(self, scene):
- self._apply_events(self._scene.exit(self._world))
+ self._apply_events(self._scene.exit(self._world.proxy()))
self._scene = scene
- self._apply_events(self._scene.enter(self._world))
+ self._apply_events(self._scene.enter(self._world.proxy()))
def change_world(self, *args, **kw):
self._world.apply_event(*args, **kw)
@apply_events
def update(self, dt):
- return self._scene.update(self._world, dt)
+ return self._scene.update(self._world.proxy(), dt)
def draw(self):
self._scene.draw(self._app.screen, self._viewport)
def update(self, world, dt):
for i, roach in enumerate(world.roaches):
- if roach["name"] in self._roach_actors:
- actor = self._roach_actors[roach["name"]]
+ if roach.name in self._roach_actors:
+ actor = self._roach_actors[roach.name]
else:
actor = TextButton("%s [%s]" % (
- roach["name"],
+ roach.name,
", ".join("%s=%s" % kv for kv in sorted(
- roach["attributes"].items()),
+ roach.attributes.items()),
)))
- self._roach_actors[roach["name"]] = actor
+ self._roach_actors[roach.name] = actor
self.actors.add(actor)
# TODO: remove missing roaches
actor.pos = (300, 100 + i * 100)
""" World and player state. """
+from .scenes.base import WorldEvent
+
class World:
""" World and player state. """
parts = name.split(".")
obj = self._state
for p in parts[:-1]:
- obj = obj[p]
+ if isinstance(obj, dict):
+ obj = obj[p]
+ elif isinstance(obj, list):
+ obj = obj[int(p)]
+ else:
+ raise KeyError("%r not found in world" % (name,))
obj[parts[-1]] = value
+ def proxy(self):
+ return WorldDictProxy(self._state)
+
def apply_event(self, action, *args, **kw):
if action == "set":
return self._apply_set(*args, **kw)
raise ValueError("Unknown world event action: %r" % (action,))
+
+
+def _maybe_subproxy(proxy, name, value):
+ """ Return a sub world proxy if appropriate. """
+ if isinstance(value, dict):
+ prefix = "%s%s." % (proxy._prefix, name)
+ return WorldDictProxy(value, _prefix=prefix, _top=proxy._top)
+ elif isinstance(value, list):
+ prefix = "%s%s." % (proxy._prefix, name)
+ return WorldListProxy(value, _prefix=prefix, _top=proxy._top)
+ return value
+
+
+class WorldBaseProxy:
+ """ Base for world proxies. """
+
+ def __init__(self, state, _prefix='', _top=None):
+ if _top is None:
+ _top = self
+ _events = []
+ else:
+ _events = None
+ self.__dict__.update({
+ "_state": state,
+ "_prefix": _prefix,
+ "_top": _top,
+ "_events": _events,
+ })
+
+ def _record_change(self, fullname, value):
+ self._events.append(WorldEvent("set", {
+ fullname: value
+ }))
+
+ def pop_events(self):
+ events, self._events = self._events, []
+ return events
+
+
+class WorldDictProxy(WorldBaseProxy):
+ """ World dictionary proxy that records changes and produces events. """
+
+ def items(self):
+ return (
+ (k, _maybe_subproxy(self, k, v)) for k, v in self._state.items())
+
+ def __setattr__(self, name, value):
+ self._top._record_change("%s%s" % (self._prefix, name), value)
+
+ def __getattr__(self, name):
+ return _maybe_subproxy(self, name, self._state[name])
+
+
+class WorldListProxy(WorldBaseProxy):
+ """ World list proxy that records changes and produces events. """
+
+ def __setitem__(self, index, value):
+ self._top._record_change("%s%s" % (self._prefix, index), value)
+
+ def __getitem__(self, index):
+ return _maybe_subproxy(self, index, self._state[index])