46 lines
1.4 KiB
Python
46 lines
1.4 KiB
Python
|
|
"""UNWRITTEN - modal input dispatch. Owner: Agent A.
|
||
|
|
|
||
|
|
One InputStack per scene owns scene.on_key and dispatches to a stack of
|
||
|
|
handlers, top-most first. A handler is fn(key, state) -> bool; returning True
|
||
|
|
consumes the event (lower handlers do not see it). Overworld pushes its
|
||
|
|
movement handler; a DialogueBox / menu pushes itself while open and pops on
|
||
|
|
close, freezing everything beneath it.
|
||
|
|
"""
|
||
|
|
|
||
|
|
|
||
|
|
class InputStack:
|
||
|
|
def __init__(self, scene):
|
||
|
|
self.scene = scene
|
||
|
|
self.stack = [] # list of (name, handler)
|
||
|
|
scene.on_key = self._dispatch
|
||
|
|
|
||
|
|
def push(self, handler, name=""):
|
||
|
|
self.stack.append((name, handler))
|
||
|
|
|
||
|
|
def pop(self, name=""):
|
||
|
|
"""Pop the top handler, or the top-most handler matching name."""
|
||
|
|
if name:
|
||
|
|
for i in range(len(self.stack) - 1, -1, -1):
|
||
|
|
if self.stack[i][0] == name:
|
||
|
|
return self.stack.pop(i)
|
||
|
|
return None
|
||
|
|
if self.stack:
|
||
|
|
return self.stack.pop()
|
||
|
|
return None
|
||
|
|
|
||
|
|
def replace(self, handler, name=""):
|
||
|
|
"""Replace the top handler with a new one."""
|
||
|
|
self.pop()
|
||
|
|
self.push(handler, name)
|
||
|
|
|
||
|
|
def clear(self):
|
||
|
|
self.stack = []
|
||
|
|
|
||
|
|
def has(self, name):
|
||
|
|
return any(n == name for n, _ in self.stack)
|
||
|
|
|
||
|
|
def _dispatch(self, key, state):
|
||
|
|
for i in range(len(self.stack) - 1, -1, -1):
|
||
|
|
handler = self.stack[i][1]
|
||
|
|
if handler(key, state):
|
||
|
|
return
|