Simbody
3.5
|
This pre-built InputListener is extremely useful for processing user input that is intended to affect a running simulation. More...
Public Member Functions | |
InputSilo () | |
Default construction is all that is needed; there are no options. More... | |
~InputSilo () | |
Throws away any unprocessed input. More... | |
bool | isAnyUserInput () const |
This is a very fast test that does not require locking; you don't have to use this but it is a good idea to do so. More... | |
void | waitForAnyUserInput () const |
This will wait quietly until the user has provided some input to the visualizer. Any kind of input will terminate the wait; you'll have to look to see what it was. More... | |
bool | takeKeyHit (unsigned &key, unsigned &modifiers) |
This will return user key hits until they have all been consumed, in the same order they were received. More... | |
void | waitForKeyHit (unsigned &key, unsigned &modifiers) |
Same as takeKeyHit() except that if there is no key hit input available it waits until there is, then returns the first one (which is removed from the silo just as takeKeyHit() would do. More... | |
bool | takeMenuPick (int &menu, int &item) |
This will return user menu picks until they have all been consumed, in the same order they were received. More... | |
void | waitForMenuPick (int &menu, int &item) |
Same as takeMenuPick() except that if there is no menu pick input available it waits until there is, then returns the first one (which is removed from the silo just as takeMenuPick() would do. More... | |
bool | takeSliderMove (int &slider, Real &value) |
This will return user changes to slider positions until they have all been consumed, in the same order they were received. More... | |
void | waitForSliderMove (int &slider, Real &value) |
Same as takeSliderMove() except that if there is no slider move input available it waits until there is, then returns the first one (which is removed from the silo just as takeSliderMove() would do. More... | |
void | clear () |
Throw away any pending unprocessed input of all types. More... | |
Public Member Functions inherited from SimTK::Visualizer::InputListener | |
virtual | ~InputListener () |
Destructor is virtual; be sure to override it if you need to clean up. More... | |
Additional Inherited Members | |
Public Types inherited from SimTK::Visualizer::InputListener | |
enum | Modifier { ShiftIsDown = 0x01, ControlIsDown = 0x02, AltIsDown = 0x04, IsSpecialKey = 0xC0 } |
These represent modifications to the character that is passed into the keyPressed() method, including whether any of Shift/Control/Alt were down and whether a special non-ASCII code is being supplied, such as is required for an arrow key. More... | |
enum | KeyCode { KeyControlC = 3, KeyBeep = 7, KeyBackspace = 8, KeyTab = 9, KeyLF = 10, KeyReturn = 13, KeyEnter = KeyReturn, KeyEsc = 27, KeyDelete = 127, KeyF1 = SpecialKeyOffset + 1, KeyF2 = SpecialKeyOffset + 2, KeyF3 = SpecialKeyOffset + 3, KeyF4 = SpecialKeyOffset + 4, KeyF5 = SpecialKeyOffset + 5, KeyF6 = SpecialKeyOffset + 6, KeyF7 = SpecialKeyOffset + 7, KeyF8 = SpecialKeyOffset + 8, KeyF9 = SpecialKeyOffset + 9, KeyF10 = SpecialKeyOffset + 10, KeyF11 = SpecialKeyOffset + 11, KeyF12 = SpecialKeyOffset + 12, KeyLeftArrow = SpecialKeyOffset + 100, KeyUpArrow = SpecialKeyOffset + 101, KeyRightArrow = SpecialKeyOffset + 102, KeyDownArrow = SpecialKeyOffset + 103, KeyPageUp = SpecialKeyOffset + 104, KeyPageDown = SpecialKeyOffset + 105, KeyHome = SpecialKeyOffset + 106, KeyEnd = SpecialKeyOffset + 107, KeyInsert = SpecialKeyOffset + 108 } |
These are the special keys that the Visualizer may report via the keyPressed() method. More... | |
Static Public Attributes inherited from SimTK::Visualizer::InputListener | |
static const unsigned | SpecialKeyOffset = 0x100 |
This pre-built InputListener is extremely useful for processing user input that is intended to affect a running simulation.
The idea is that this object saves up all the user input in a set of "silos", which are first-in-first-out (FIFO) queues. The simulation periodically checks ("polls") to see if there is anything in the silos that needs processing, pulling off one user input at a time until they have all been consumed. This eliminates any need for tricky asynchronous handling of user input, and all thread synchronization issues are handled invisibly.
You can also request to wait quietly until some input arrives, which is useful when you can't proceed without some instruction from the user that you expect to get through the visualizer.
When the InputSilo receives user input through one of the InputListener methods it implements, it return true
indicating that it has processed the input and that no further InputListeners should be called. So if you have other InputListeners that you would like to have called, be sure to add them to the Visulizer prior to adding an InputSilo, which is the last refuge for unwanted user input.
Here's how you can use this:
If you want to wait until some input arrives, create the InputSilo and add it to the Visualizer as above, then in your main program (that is, not in the Handler) use code like this:
Similar methods are available for all the different input types, and you can also wait on the arrival of any input.
The InputSilo implementations of the InputListener methods are called from the Visualizer's listener thread, which is a different thread than the one that is simultaneously running the simulation. The internal silos are double-ended queues (deques) that allow inputs to be pushed onto one end and pulled off the other, so that they can be consumed in FIFO order. There is a single mutex lock associated with all the silos together, and the lock must be held while anything is pushed onto or pulled off of any one of the silos.
Each of the methods for getting the input out of the silos is called from the simulation thread, which must obtain the lock before removing anything, thus safely synchronizing the listener and simulation threads.
A count is maintained of the total number of items in all the silos. It is incremented only when the listener thread holds the lock and adds something to a silo; it is decremented only when the simulation thread holds the lock and pulls something from a silo. The count may be examined without locking; it will have a value that was recently correct and can thus be used for a very fast check on whether there is likely to be any input worth holding a lock for; the isAnyUserInput() method returns true
when the count is non-zero. It may occasionally return zero in cases where there is input, but only if that input just arrived so you can safely pick it up on the next poll.
When possible we optimize for the case where many inputs arrive from the same device by just keeping the most recent value. That applies to slider and mouse moves.
SimTK::Visualizer::InputSilo::InputSilo | ( | ) |
Default construction is all that is needed; there are no options.
SimTK::Visualizer::InputSilo::~InputSilo | ( | ) |
Throws away any unprocessed input.
bool SimTK::Visualizer::InputSilo::isAnyUserInput | ( | ) | const |
This is a very fast test that does not require locking; you don't have to use this but it is a good idea to do so.
void SimTK::Visualizer::InputSilo::waitForAnyUserInput | ( | ) | const |
This will wait quietly until the user has provided some input to the visualizer. Any kind of input will terminate the wait; you'll have to look to see what it was.
bool SimTK::Visualizer::InputSilo::takeKeyHit | ( | unsigned & | key, |
unsigned & | modifiers | ||
) |
This will return user key hits until they have all been consumed, in the same order they were received.
The key and modifiers values are those that were provided to our implementation of the InputListener::keyPressed() method.
[out] | key | The key code for the key that was hit. See InputListener::KeyCode for interpretation. |
[out] | modifiers | Status of Shift,Ctrl,Alt and "special" key code. See InputListener::Modifier for interpretation. |
true
if a key and modifiers have been returned; false
if the character silo is now empty in which case both key and modifiers will be set to zero. void SimTK::Visualizer::InputSilo::waitForKeyHit | ( | unsigned & | key, |
unsigned & | modifiers | ||
) |
Same as takeKeyHit() except that if there is no key hit input available it waits until there is, then returns the first one (which is removed from the silo just as takeKeyHit() would do.
The behavior is like calling waitForAnyUserInput() repeatedly until takeKeyHit() returns true
.
bool SimTK::Visualizer::InputSilo::takeMenuPick | ( | int & | menu, |
int & | item | ||
) |
This will return user menu picks until they have all been consumed, in the same order they were received.
The item value returned is the value that was provided to our implementation of the InputListener::menuSelected() method.
[out] | menu | The id number of the menu that was selected. This is the value that was assigned to this menu in the Visualizer::addMenu() call. |
[out] | item | The menu item number for the entry that the user selected. This is the number that was assigned at the time the menu was added via the Visualizer::addMenu() method. |
true
if a menu item number has been returned; false
if the menu pick silo is now empty in which case item will be set to zero. void SimTK::Visualizer::InputSilo::waitForMenuPick | ( | int & | menu, |
int & | item | ||
) |
Same as takeMenuPick() except that if there is no menu pick input available it waits until there is, then returns the first one (which is removed from the silo just as takeMenuPick() would do.
The behavior is like calling waitForAnyUserInput() repeatedly until takeMenuPick() returns true
.
bool SimTK::Visualizer::InputSilo::takeSliderMove | ( | int & | slider, |
Real & | value | ||
) |
This will return user changes to slider positions until they have all been consumed, in the same order they were received.
The slider and value returns are those that were provided to our implementation of the InputListener::sliderMoved() method.
[out] | slider | The id number of the slider that was moved. This is the value that was assigned to this slider in the Visualizer::addSlider() call. |
[out] | value | This is the new value associated with the slider position to which the user moved it. |
true
if a slider move has been returned; false
if the slider move silo is now empty in which case which will be set to zero and value will be NaN. void SimTK::Visualizer::InputSilo::waitForSliderMove | ( | int & | slider, |
Real & | value | ||
) |
Same as takeSliderMove() except that if there is no slider move input available it waits until there is, then returns the first one (which is removed from the silo just as takeSliderMove() would do.
The behavior is like calling waitForAnyUserInput() repeatedly until takeSliderMove() returns true
.
void SimTK::Visualizer::InputSilo::clear | ( | ) |
Throw away any pending unprocessed input of all types.