I wish to make a keyboard user interface such that if the user presses 1 you get one action and if they press 1-1 or 1-3-4 you would get other actions. Has anyone ever done this before? Any ideas about how best to pull it off?
In my case I hope to use the number key pad for this.
It would seem to me that you would get the key down and key up or key press and then start a timer. If the timer times out then you have just the one number but if they press again before that times out then you have more than one number as your entered command. I am really unsure about how best to do this with panda3d.
Thanks for any ideas or code that references that you know of about pulling this off.
In the manual seems to be useful functions (accept, acceptOnce, repeat,…) to make such keystroke processing. I have not needed that functions much in my code and don’t know of snippets for that either (maybe this threadhelps a bit), although I think what you explain is pretty feasible.
I have been working on this a bit and have found that I need to change the design just a little bit. I want it to work so that if a button is press for longer than a certain time then it sends the event for that set of keys. Not sure if it should place it over and over or just give a key down and key up for the group of key presses.
So for example they would press 1-5-2 and hold the 2 down. This would cause and event called 152 down to be sent and then when the 2 was released then you would get 152 up.
import direct.directbase.DirectStart
from direct.showbase import DirectObject
from pandac.PandaModules import *
from direct.task.Timer import Timer
class ReadNumPad(DirectObject.DirectObject):
def __init__(self, holdTime = .4, tweenWait = .5, holdUpTime = .5):
self.holdTime = holdTime # If this time is exceded with a key in the down possition then send the string as DOWN
self.tweenWate = tweenWait # if this time is not exceded with a key in the up possition then add to the string.
self.holdUpTime = holdUpTime # if this time is exceded then start a new string
self.buttonString = ''
self.buttonDown = False # a button is pressed already
self.startString = True # time to make a new string
self.currenKey = ''
#keyboard buttons
self._buttons =['0','1','2','3','4','5','6','7','8','9']
self._buttonTimes = dict([(x, 0) for x in self._buttons])
for key in self._buttons:
base.accept('time-'+key, self._downBut, [key])
base.accept('time-'+key+'-up', self._upBut,[key])
base.accept('123', self.helloTest)
self.t = Timer('end')
def _downBut(self, key, time):
self._buttonTimes[key] = time
if not self.buttonDown : # Only one button pressed.
self.t.startCallback(self.holdTime, self.stringDown) # Start the DownTimer. to see if we are to send a string down message
if self.startString : # new string
self.buttonDown = True
self.startString = False
self.buttonString = key
else :
# of a new string or we are within tweentime :
self.buttonString += key
self.buttonDown = True
# If DownTimer runs out then string down is sent and repeat timer is started.
def _upBut(self, key, time):
held_time = time - self._buttonTimes[key]
print 'up', held_time, key
if held_time < self.tweenWate :
self.stringAdd()
self.t.startCallback(self.holdUpTime, self.stringUp) # must wait to see if this is end of adding, long pause
else :
self.stringUp()
# If the DownTimers has not run out then add this key to the string and stop the timer.
# If the down timer has run out then this is a string key up event.
def stringAdd(self):
self.startString = False
self.buttonDown = False
def stringUp(self):
messenger.send(self.buttonString + '-up')
self.buttonDown = False
self.startString = True
print '--StringUp', self.buttonString
print
def stringDown(self):
messenger.send(self.buttonString)
print '--StringDown', self.buttonString
self.buttonDown = True
self.startString = True
# what happens if 2 keys are down? But they never are together on the keypad.
def helloTest(self):
print 'helloTest'
# if you can't seem to get the keypad to work with your typing, change these numbers.
h = ReadNumPad(.4, .6, .6)
run()
Hmm, I’m not very familiar with events, maybe you can do it that way if you work it, nevertheless if you have difficulties with that I think it could also be done with alternative approaches like a queue of keys or with a finite state machine.
Edit: Wow almost simultaneous posts, happy for you to get it working
Events are an ideal way to do it. The code only runs if someone types a number. When they type a set of numbers in generates a new event named by that group of numbers. You can see in this code the place where it calls helloTest if you type 123 and hold the 3 down. In normal language events are just interrupts.