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))