109 lines
3.7 KiB
Python
Executable File
109 lines
3.7 KiB
Python
Executable File
|
|
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from direct.showbase import DirectObject
|
|
|
|
|
|
class InputState(DirectObject.DirectObject):
|
|
"""
|
|
InputState is for tracking the on/off state of some events.
|
|
The initial usage is to watch some keyboard keys so that another
|
|
task can poll the key states. By the way, in general polling is
|
|
not a good idea, but it is useful in some situations. Know when
|
|
to use it :) If in doubt, don't use this class and listen for
|
|
events instead.
|
|
"""
|
|
|
|
notify = DirectNotifyGlobal.directNotify.newCategory("InputState")
|
|
|
|
def __init__(self):
|
|
self.state = {}
|
|
assert(self.debugPrint("InputState()"))
|
|
self.watching = {}
|
|
self.forcing = {}
|
|
|
|
def delete(self):
|
|
self.ignoreAll()
|
|
|
|
def watch(self, name, eventOn, eventOff, default = 0):
|
|
"""
|
|
name is any string (or actually any valid dictionary key).
|
|
eventOn is the string name of the Messenger event that will
|
|
set the state (set to 1).
|
|
eventOff is the string name of the Messenger event that will
|
|
clear the state (set to 0).
|
|
default is the initial value (this will be returned from
|
|
isSet() if a call is made before any eventOn or eventOff
|
|
events occur.
|
|
See Also: ignore()
|
|
"""
|
|
assert(self.debugPrint(
|
|
"watch(name=%s, eventOn=%s, eventOff=%s, default=%s)"%(
|
|
name, eventOn, eventOff, default)))
|
|
self.accept(eventOn, self.set, [name, 1])
|
|
self.accept(eventOff, self.set, [name, 0])
|
|
self.state[name] = default
|
|
# self.watching is a dict of the form:
|
|
# {name : [(eventOn, eventOff), (eventOn, eventOff)...]}
|
|
eventList = self.watching.get(name)
|
|
if eventList:
|
|
eventList.append((eventOn, eventOff))
|
|
else:
|
|
# Start a new list
|
|
self.watching[name] = [(eventOn, eventOff)]
|
|
|
|
def watchWithModifiers(self, name, event, default = 0):
|
|
patterns = ('%s', 'control-%s', 'shift-control-%s', 'alt-%s',
|
|
'control-alt-%s', 'shift-%s',)
|
|
for pattern in patterns:
|
|
self.watch(name, pattern % event, '%s-up' % event, default)
|
|
|
|
def force(self, name, value):
|
|
"""
|
|
Force isSet(name) to return value.
|
|
See Also: unforce()
|
|
"""
|
|
self.forcing[name] = value
|
|
|
|
def unforce(self, name):
|
|
"""
|
|
Stop forcing a value.
|
|
See Also: force()
|
|
"""
|
|
del self.forcing[name]
|
|
|
|
def ignore(self, name):
|
|
"""
|
|
The opposite of watch(name, ...)
|
|
See Also: watch()
|
|
"""
|
|
for event in self.watching[name]:
|
|
eventOn, eventOff = event
|
|
DirectObject.DirectObject.ignore(self, eventOn)
|
|
DirectObject.DirectObject.ignore(self, eventOff)
|
|
del self.watching[name]
|
|
del self.state[name]
|
|
|
|
def set(self, name, isSet):
|
|
assert(self.debugPrint("set(name=%s, isSet=%s)"%(name, isSet)))
|
|
self.state[name] = isSet
|
|
# We change the name before sending it because this may
|
|
# be the same name that messenger used to call InputState.set()
|
|
# this avoids running in circles:
|
|
messenger.send("InputState-%s"%(name,), [isSet])
|
|
|
|
def isSet(self, name):
|
|
"""
|
|
returns 0, 1
|
|
"""
|
|
#assert(self.debugPrint("isSet(name=%s)"%(name)))
|
|
r = self.forcing.get(name)
|
|
if r is not None:
|
|
return r
|
|
return self.state.get(name, 0)
|
|
|
|
def debugPrint(self, message):
|
|
"""for debugging"""
|
|
return self.notify.debug(
|
|
"%s (%s) %s"%(id(self), len(self.state), message))
|