CUGL 2.1
Cornell University Game Library
Public Types | Public Member Functions | Protected Member Functions | Protected Attributes | Friends | List of all members
cugl::CoreGesture Class Reference

#include <CUCoreGesture.h>

Inheritance diagram for cugl::CoreGesture:
cugl::InputDevice

Public Types

typedef std::function< void(const CoreGestureEvent &event, bool focus)> Listener
 

Public Member Functions

bool isTouchScreen () const
 
void setTouchScreen (bool flag)
 
bool isPanActive () const
 
void setPanActive (bool flag)
 
bool isPinchActive () const
 
void setPinchActive (bool flag)
 
bool isSpinActive () const
 
void setSpinActive (bool flag)
 
float getPanThreshold () const
 
void setPanThreshold (float threshold)
 
float getPinchThreshold () const
 
void setPinchThreshold (float threshold)
 
float getSpinThreshold () const
 
void setSpinThreshold (float threshold)
 
float getSpinRadius () const
 
void setSpinRadius (float radius)
 
virtual bool requestFocus (Uint32 key) override
 
bool isListener (Uint32 key) const
 
const Listener getBeginListener (Uint32 key) const
 
const Listener getEndListener (Uint32 key) const
 
const Listener getChangeListener (Uint32 key) const
 
bool addBeginListener (Uint32 key, Listener listener)
 
bool addEndListener (Uint32 key, Listener listener)
 
bool addChangeListener (Uint32 key, Listener listener)
 
bool removeBeginListener (Uint32 key)
 
bool removeEndListener (Uint32 key)
 
bool removeChangeListener (Uint32 key)
 
- Public Member Functions inherited from cugl::InputDevice
Uint32 acquireKey ()
 
Uint32 currentFocus () const
 
void releaseFocus ()
 

Protected Member Functions

 CoreGesture ()
 
virtual ~CoreGesture ()
 
bool init ()
 
virtual void dispose () override
 
virtual void clearState () override
 
virtual bool updateState (const SDL_Event &event, const Timestamp &stamp) override
 
Vec2 getScaledPosition (float x, float y) const
 
virtual void queryEvents (std::vector< Uint32 > &eventset) override
 
- Protected Member Functions inherited from cugl::InputDevice
 InputDevice ()
 
virtual ~InputDevice ()
 
bool initWithName (const std::string name)
 

Protected Attributes

bool _screen
 
bool _active
 
CoreGestureEvent _data
 
bool _activePan
 
bool _activePinch
 
bool _activeSpin
 
float _panThreshold
 
float _pinchThreshold
 
float _spinThreshold
 
float _spinRadius
 
std::unordered_map< Sint64, Vec2_fingers
 
size_t _updated
 
std::unordered_map< Uint32, Listener_startListeners
 
std::unordered_map< Uint32, Listener_deltaListeners
 
std::unordered_map< Uint32, Listener_endListeners
 
- Protected Attributes inherited from cugl::InputDevice
std::string _name
 
Uint32 _focus
 
Uint32 _nextKey
 

Friends

class Input
 

Additional Inherited Members

- Static Public Attributes inherited from cugl::InputDevice
static const Uint32 RESERVED_KEY = UINT32_MAX
 

Detailed Description

This class is an input device recognizing the core two-finger gestures.

There are three code two-finger gestures: pan (for translating a scene), pinch (for zooming in or out of a scene), and spin (for rotating a scene). We do have gesture inputs for each type: PanGesture, PinchGesture, and SpinGesture. However, the problem with using these inputs individually is that this would allow the user to perform these gestures simultaneously. This is typically not what you want, as it could cause the scene to rotate unstably while the user tries to pan or pinch.

Instead, most applications attempt to detect which of three gestures the user is trying to perform and chose the best one. Once the gesture is type is detected, the other gesture types will not be recognized until the gesture is completed. Doing this requires combining all gestures into a single input device, which is exactly what this class does.

In order to destinguish between the three gesture types, this device has several threshold factors that can be defined by the user. For example, a CoreGestureType::PAN is recognized when the cumulative distance exceeds the getPanThreshold. A CoreGestureType::PINCH is recognized when the change in pinch distance exceeds getPinchThreshold. And a CoreGestureType::SPIN is recognized when the change in angle exceeds getSpinThreshold. The priority is to recognize a pan before a pinch and a pinch before a spin.

By default all pan and pinch information will scale with the display, and be measured in pixels. However, this assumes that the touch input and the display are one and the same (e.g. most mobile devices). However, there are some touch devices, like the MacBook trackpad, that cannot be measure in pixels. For those types of devices, any pan or pinch will be normalized to a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1).

Member Typedef Documentation

◆ Listener

This type represents a listener for a two-finger gesture.

In CUGL, listeners are implemented as a set of callback functions, not as objects. This allows each listener to implement as much or as little functionality as it wants. A listener is identified by a key which should be a globally unique unsigned int.

While gesture listeners do not traditionally require focus like a keyboard does, we have included that functionality. While only one listener can have focus at a time, all listeners will receive input from the CoreGesture device.

The function type is equivalent to

 std::function<void(const CoreGestureEvent& event, bool focus)>
Parameters
eventThe touch event for this pinch/zoom
focusWhether the listener currently has focus

Constructor & Destructor Documentation

◆ CoreGesture()

cugl::CoreGesture::CoreGesture ( )
protected

Creates and initializes a new input device to detect core gestures.

WARNING: Never allocate a gesture input device directly. Always use the Input#activate() method instead.

◆ ~CoreGesture()

virtual cugl::CoreGesture::~CoreGesture ( )
inlineprotectedvirtual

Deletes this input device, disposing of all resources

Member Function Documentation

◆ addBeginListener()

bool cugl::CoreGesture::addBeginListener ( Uint32  key,
Listener  listener 
)

Adds a gesture begin listener for the given object key

There can only be one begin listener for a given key. If there is already a listener for the key, the method will fail and return false. You must remove a listener before adding a new one for the same key.

This listener is invoked when two fingers are detected on the device. Note that the gesture type is rarely determined at the start. Instead, the gesture type is only assigned (via a change listener) once it crosses a certain threshold.

Parameters
keyThe identifier for the begin listener
listenerThe listener to add
Returns
true if the listener was succesfully added

◆ addChangeListener()

bool cugl::CoreGesture::addChangeListener ( Uint32  key,
Listener  listener 
)

Adds a gesture change listener for the given object key

There can only be one change listener for a given key. If there is already a listener for the key, the method will fail and return false. You must remove a listener before adding a new one for the same key.

This listener is invoked when the gesture is updated. A gesture is only updated once it has a definitive type. Hence the first time this listener is called after a start event, the gesture will have an assigned type.

Parameters
keyThe identifier for the change listener
listenerThe listener to add
Returns
true if the listener was succesfully added

◆ addEndListener()

bool cugl::CoreGesture::addEndListener ( Uint32  key,
Listener  listener 
)

Adds a gesture end listener for the given object key

There can only be one end listener for a given key. If there is already a listener for the key, the method will fail and return false. You must remove a listener before adding a new one for the same key.

This listener is invoked when there are no longer only two fingers on the device. This could mean that one or more fingers was removed. Or it could mean that a third finger (or more) was added.

Parameters
keyThe identifier for the end listener
listenerThe listener to add
Returns
true if the listener was succesfully added

◆ clearState()

virtual void cugl::CoreGesture::clearState ( )
inlineoverrideprotectedvirtual

Clears the state of this input device, readying it for the next frame.

Many devices keep track of what happened "this" frame. This method is necessary to advance the frame.

Implements cugl::InputDevice.

◆ dispose()

virtual void cugl::CoreGesture::dispose ( )
overrideprotectedvirtual

Unintializes this device, returning it to its default state

An uninitialized device may not work without reinitialization.

Reimplemented from cugl::InputDevice.

◆ getBeginListener()

const Listener cugl::CoreGesture::getBeginListener ( Uint32  key) const

Returns the gesture begin listener for the given object key

This listener is invoked when two fingers are detected on the device. Note that the gesture type is rarely determined at the start. Instead, the gesture type is only assigned (via a change listener) once it crosses a certain threshold.

If there is no listener for the given key, this method returns nullptr.

Parameters
keyThe identifier for the begin listener
Returns
the gesture begin listener for the given object key

◆ getChangeListener()

const Listener cugl::CoreGesture::getChangeListener ( Uint32  key) const

Returns the gesture end listener for the given object key

This listener is invoked when the gesture is updated. A gesture is only updated once it has a definitive type. Hence the first time this listener is called after a start event, the gesture will have an assigned type.

If there is no listener for the given key, this method returns nullptr.

Parameters
keyThe identifier for the change listener
Returns
the gesture begin listener for the given object key

◆ getEndListener()

const Listener cugl::CoreGesture::getEndListener ( Uint32  key) const

Returns the gesture end listener for the given object key

This listener is invoked when there are no longer only two fingers on the device. This could mean that one or more fingers was removed. Or it could mean that a third finger (or more) was added.

If there is no listener for the given key, this method returns nullptr.

Parameters
keyThe identifier for the end listener
Returns
the gesture begin listener for the given object key

◆ getPanThreshold()

float cugl::CoreGesture::getPanThreshold ( ) const
inline

Returns the distance threshold for pan events.

In order to separate the gestures, pan events have an initial resistance. The device will only recognize a gesture as a pan event once the cumulative pan has exceeded the provided threshold. Once the device has recognized the gesture as a pan event, it will not recognize it as a pinch or spin, no matter how the fingers are moved. The user will need to remove one or both fingers to reset the gesture.

If this device is a touch screen, this value should be measured in pixels. Otherwise, this value should be set assuming a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1). By default this value is 5% of the length of the diagonal of the touch device.

Returns
the distance threshold for pan events.

◆ getPinchThreshold()

float cugl::CoreGesture::getPinchThreshold ( ) const
inline

Returns the distance threshold for pinch events.

In order to separate the gestures, pinch events have an initial resistance. The device will only recognize a gesture as a pinch event once the absolute value of the difference between the current pinch and the initial pinch has has exceeded the provided threshold. Once the device has recognized the gesture as a pinch event, it will not recognize it as a pan or spin, no matter how the fingers are moved. The user will need to remove one or both fingers to reset the gesture.

If this device is a touch screen, this value should be measured in pixels. Otherwise, this value should be set assuming a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1). By default this value is 5% of the length of the diagonal of the touch device.

Returns
the distance threshold for pinch events.

◆ getScaledPosition()

Vec2 cugl::CoreGesture::getScaledPosition ( float  x,
float  y 
) const
protected

Returns the scale/unscaled touch position.

The value returned depends on the value of attribute _screen. If this attribute is false, the position is normalized to the unit square. Otherwise it is scaled to the touch screen.

Returns
the scale/unscaled touch position.

◆ getSpinRadius()

float cugl::CoreGesture::getSpinRadius ( ) const
inline

Returns the minimum radius for a spin event.

All spins have an additional rquirement that all the fingers must be separated by a minimum distance. This is a natural requirement for spins, and it greatly reduces the possibility of accidental spins.

If this device is a touch screen, this value should be measured in pixels. Otherwise, this value should be set assuming a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1). By default this value is 10% of the length of the diagonal of the touch device.

Returns
the minimum radius for a spin event.

◆ getSpinThreshold()

float cugl::CoreGesture::getSpinThreshold ( ) const
inline

Returns the angle threshold for spin events.

In order to separate the gestures, spin events have an initial resistance. The device will only recognize a gesture as a spin event once the absolute value of the difference between the current angle and the initial angle has has exceeded the provided threshold. Once the device has recognized the gesture as a pinch event, it will not recognize it as a pan or spin, no matter how the fingers are moved. The user will need to remove one or both fingers to reset the gesture.

Since angles measurements do not depend on the size of the touch device, this threshold is the same regardless of whether or not this devices is a touch screen. However, spins have an addition requirement that the fingers must be separated by a minimum distance, as given by getSpinRadius. The default value is 4 degrees.

Returns
the angle threshold for spin events.

◆ init()

bool cugl::CoreGesture::init ( )
inlineprotected

Initializes this device, acquiring any necessary resources

Returns
true if initialization was successful

◆ isListener()

bool cugl::CoreGesture::isListener ( Uint32  key) const

Returns true if key represents a listener object

An object is a listener if it is a listener for any of the three actions: gesture begin, gesture end, or gesture change.

Parameters
keyThe identifier for the listener
Returns
true if key represents a listener object

◆ isPanActive()

bool cugl::CoreGesture::isPanActive ( ) const
inline

Returns true if pan detection is active.

If pan detection is not active, all pan events will be ignored. By default, this value is true.

Returns
true if pan detection is active.

◆ isPinchActive()

bool cugl::CoreGesture::isPinchActive ( ) const
inline

Returns true if pinch detection is active.

If pan detection is not active, all pan events will be ignored. By default, this value is true.

Returns
true if pinch detection is active.

◆ isSpinActive()

bool cugl::CoreGesture::isSpinActive ( ) const
inline

Returns true if spin detection is active.

If pan detection is not active, all spin events will be ignored. By default, this value is true.

Returns
true if spin detection is active.

◆ isTouchScreen()

bool cugl::CoreGesture::isTouchScreen ( ) const
inline

Returns true if this device is a touch screen.

This device is not guaranteed to be a touch screen. For example, the trackpad on MacBooks support pinches. We do try to make our best guess about whether or not a device is a touch screen, but on some devices this may need to be set manually.

If this value is true, all pan and pinch information will scale with the display (and be measured in pixels) Otherwise, any pan or pinch will be normalized to a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1).

You may want to set this value to false for true cross-platform gesture support.

Returns
true if this device is a touch screen.

◆ queryEvents()

virtual void cugl::CoreGesture::queryEvents ( std::vector< Uint32 > &  eventset)
overrideprotectedvirtual

Determine the SDL events of relevance and store there types in eventset.

An SDL_EventType is really a Uint32. This method stores the SDL event types for this input device into the vector eventset, appending them to the end. The Input dispatcher then uses this information to set up subscriptions.

Parameters
eventsetThe set to store the event types.

Implements cugl::InputDevice.

◆ removeBeginListener()

bool cugl::CoreGesture::removeBeginListener ( Uint32  key)

Removes a gesture begin listener for the given object key

If there is no active listener for the given key, this method fails and returns false.

This listener is invoked when the gesture is updated. A gesture is only updated once it has a definitive type. Hence the first time this listener is called after a start event, the gesture will have an assigned type.

Parameters
keyThe identifier for the begin listener
Returns
true if the listener was succesfully removed

◆ removeChangeListener()

bool cugl::CoreGesture::removeChangeListener ( Uint32  key)

Removes a gesture change listener for the given object key

If there is no active listener for the given key, this method fails and returns false.

This listener is invoked when the gesture is updated. A gesture is only updated once it has a definitive type. Hence the first time this listener is called after a start event, the gesture will have an assigned type.

Parameters
keyThe identifier for the begin listener
Returns
true if the listener was succesfully removed

◆ removeEndListener()

bool cugl::CoreGesture::removeEndListener ( Uint32  key)

Removes a gesture end listener for the given object key

If there is no active listener for the given key, this method fails and returns false.

This listener is invoked when the gesture is updated. A gesture is only updated once it has a definitive type. Hence the first time this listener is called after a start event, the gesture will have an assigned type.

Parameters
keyThe identifier for the begin listener
Returns
true if the listener was succesfully removed

◆ requestFocus()

virtual bool cugl::CoreGesture::requestFocus ( Uint32  key)
overridevirtual

Requests focus for the given identifier

Only a listener can have focus. This method returns false if key does not refer to an active listener

Parameters
keyThe identifier for the focus object
Returns
false if key does not refer to an active listener

Reimplemented from cugl::InputDevice.

◆ setPanActive()

void cugl::CoreGesture::setPanActive ( bool  flag)
inline

Sets whether pan detection is active.

If pan detection is not active, all pan events will be ignored. By default, this value is true.

Parameters
flagWhether pan detection is active.

◆ setPanThreshold()

void cugl::CoreGesture::setPanThreshold ( float  threshold)

Sets the delta threshold for pan events.

In order to separate the gestures, pan events have an initial resistance. The device will only recognize a gesture as a pan event once the cumulative pan has exceeded the provided threshold. Once the device has recognized the gesture as a pan event, it will not recognize it as a pinch or spin, no matter how the fingers are moved. The user will need to remove one or both fingers to reset the gesture.

If this device is a touch screen, this value should be measured in pixels. Otherwise, this value should be set assuming a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1). By default this value is 5% of the length of the diagonal of the touch device.

Parameters
thresholdThe distance threshold for pan events.

◆ setPinchActive()

void cugl::CoreGesture::setPinchActive ( bool  flag)
inline

Sets whether pinch detection is active.

If pan detection is not active, all pinch events will be ignored. By default, this value is true.

Parameters
flagWhether pinch detection is active.

◆ setPinchThreshold()

void cugl::CoreGesture::setPinchThreshold ( float  threshold)

Sets the distance threshold for pinch events.

In order to separate the gestures, pinch events have an initial resistance. The device will only recognize a gesture as a pinch event once the absolute value of the difference between the current pinch and the initial pinch has has exceeded the provided threshold. Once the device has recognized the gesture as a pinch event, it will not recognize it as a pan or spin, no matter how the fingers are moved. The user will need to remove one or both fingers to reset the gesture.

If this device is a touch screen, this value should be measured in pixels. Otherwise, this value should be set assuming a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1). By default this value is 5% of the length of the diagonal of the touch device.

Parameters
thresholdThe distance threshold for pinch events.

◆ setSpinActive()

void cugl::CoreGesture::setSpinActive ( bool  flag)
inline

Sets whether pinch detection is active.

If pan detection is not active, all spin events will be ignored. By default, this value is true.

Parameters
flagWhether spin detection is active.

◆ setSpinRadius()

void cugl::CoreGesture::setSpinRadius ( float  radius)

Sets the minimum radius for a spin event.

All spins have an additional rquirement that all the fingers must be separated by a minimum distance. This is a natural requirement for spins, and it greatly reduces the possibility of accidental spins.

If this device is a touch screen, this value should be measured in pixels. Otherwise, this value should be set assuming a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1). By default this value is 10% of the length of the diagonal of the touch device.

Parameters
radiusThe minimum radius for a spin event.

◆ setSpinThreshold()

void cugl::CoreGesture::setSpinThreshold ( float  threshold)

Sets the angle threshold for spin events.

In order to separate the gestures, spin events have an initial resistance. The device will only recognize a gesture as a spin event once the absolute value of the difference between the current angle and the initial angle has has exceeded the provided threshold. Once the device has recognized the gesture as a pinch event, it will not recognize it as a pan or spin, no matter how the fingers are moved. The user will need to remove one or both fingers to reset the gesture.

Since angles measurements do not depend on the size of the touch device, this threshold is the same regardless of whether or not this devices is a touch screen. However, spins have an addition requirement that the fingers must be separated by a minimum distance, as given by getSpinRadius. The default value is 4 degrees.

Parameters
thresholdThe angle threshold for spin events.

◆ setTouchScreen()

void cugl::CoreGesture::setTouchScreen ( bool  flag)

Sets whether this device is a touch screen.

This device is not guaranteed to be a touch screen. For example, the trackpad on MacBooks support pinches. We do try to make our best guess about whether or not a device is a touch screen, but on some devices this may need to be set manually.

If this value is true, all pan and pinch information will scale with the display (and be measured in pixels) Otherwise, any pan or pinch will be normalized to a unit square, where the top left corner of the touch device is (0,0) and the lower right is (1,1).

You may want to set this value to false for true cross-platform gesture support.

Parameters
flagWhether this device is a touch screen.

◆ updateState()

virtual bool cugl::CoreGesture::updateState ( const SDL_Event &  event,
const Timestamp stamp 
)
overrideprotectedvirtual

Processes an SDL_Event

The dispatcher guarantees that an input device only receives events that it subscribes to.

Parameters
eventThe input event to process
stampThe event timestamp in CUGL time
Returns
false if the input indicates that the application should quit.

Implements cugl::InputDevice.

Member Data Documentation

◆ _active

bool cugl::CoreGesture::_active
protected

Whether or not a gesture is currently being processed

◆ _activePan

bool cugl::CoreGesture::_activePan
protected

Whether pan recognition is active

◆ _activePinch

bool cugl::CoreGesture::_activePinch
protected

Whether pinch recognition is active

◆ _activeSpin

bool cugl::CoreGesture::_activeSpin
protected

Whether spin recognition is active

◆ _data

CoreGestureEvent cugl::CoreGesture::_data
protected

The current core gesture information (continually updated)

◆ _deltaListeners

std::unordered_map<Uint32, Listener> cugl::CoreGesture::_deltaListeners
protected

The set of listeners called whenever a gesture updates

◆ _endListeners

std::unordered_map<Uint32, Listener> cugl::CoreGesture::_endListeners
protected

The set of listeners called whenever a gesture ends

◆ _fingers

std::unordered_map<Sint64, Vec2> cugl::CoreGesture::_fingers
protected

The current finger positions

◆ _panThreshold

float cugl::CoreGesture::_panThreshold
protected

The movement threshold for generating a pan event

◆ _pinchThreshold

float cugl::CoreGesture::_pinchThreshold
protected

The pinch distance threshold for generating a pinch event.

◆ _screen

bool cugl::CoreGesture::_screen
protected

Whether or not this input device is a touch screen

◆ _spinRadius

float cugl::CoreGesture::_spinRadius
protected

The minimum radius for a spin event

◆ _spinThreshold

float cugl::CoreGesture::_spinThreshold
protected

The angle threshold for generating a spin event.

◆ _startListeners

std::unordered_map<Uint32, Listener> cugl::CoreGesture::_startListeners
protected

The set of listeners called whenever a gesture begins

◆ _updated

size_t cugl::CoreGesture::_updated
protected

The number of fingers updated this pass


The documentation for this class was generated from the following file: