Squashed 'external/gainput/' content from commit 2be0a50
git-subtree-dir: external/gainput git-subtree-split: 2be0a50089eafcc6fccb66142180082e48f27f4c
This commit is contained in:
228
lib/include/gainput/GainputAllocator.h
Normal file
228
lib/include/gainput/GainputAllocator.h
Normal file
@@ -0,0 +1,228 @@
|
||||
|
||||
#ifndef GAINPUTALLOCATOR_H_
|
||||
#define GAINPUTALLOCATOR_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Interface used to pass custom allocators to the library.
|
||||
/**
|
||||
* If you want the library to use your custom allocator you should implement this interface.
|
||||
* Specifically, you should provide implementations for the Allocate() and Deallocate()
|
||||
* functions. All other (template) member functions are simply based on those two functions.
|
||||
*
|
||||
* \sa DefaultAllocator
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT Allocator
|
||||
{
|
||||
public:
|
||||
enum { DefaultAlign = 0 };
|
||||
|
||||
/// Allocates a number of bytes and returns a pointer to the allocated memory.
|
||||
/**
|
||||
* \param size The number of bytes to allocate.
|
||||
* \return A memory block encompassing at least size bytes.
|
||||
*/
|
||||
virtual void* Allocate(size_t size, size_t align = DefaultAlign) = 0;
|
||||
/// Deallocates the given memory.
|
||||
/**
|
||||
* \param ptr The memory block to deallocate.
|
||||
*/
|
||||
virtual void Deallocate(void* ptr) = 0;
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T>
|
||||
T* New()
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T();
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with one parameter.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0>
|
||||
T* New(P0& p0)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with one parameter.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0>
|
||||
T* New(const P0& p0)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with two parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1>
|
||||
T* New(P0& p0, P1& p1)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with two parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1>
|
||||
T* New(const P0& p0, P1& p1)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with two parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1>
|
||||
T* New(P0& p0, const P1& p1)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with the given parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1, class P2>
|
||||
T* New(P0& p0, const P1& p1, const P2& p2)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1, p2);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with the given parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1, class P2>
|
||||
T* New(P0& p0, const P1& p1, P2& p2)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1, p2);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with the given parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1, class P2, class P3>
|
||||
T* New(P0& p0, P1& p1, P2& p2, P3& p3)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1, p2, p3);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with the given parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1, class P2, class P3>
|
||||
T* New(P0& p0, const P1& p1, P2& p2, P3& p3)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1, p2, p3);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with the given parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1, class P2, class P3, class P4>
|
||||
T* New(P0& p0, P1& p1, P2& p2, P3& p3, P4& p4)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
/// An operator new-like function that allocates memory and calls T's constructor with the given parameters.
|
||||
/**
|
||||
* \return A pointer to an initialized instance of T.
|
||||
*/
|
||||
template <class T, class P0, class P1, class P2, class P3, class P4>
|
||||
T* New(P0& p0, const P1& p1, P2& p2, P3& p3, P4& p4)
|
||||
{
|
||||
return new (Allocate(sizeof(T))) T(p0, p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
/// An operator delete-like function that calls ptr's constructor and deallocates the memory.
|
||||
/**
|
||||
* \param ptr The object to destruct and deallocate.
|
||||
*/
|
||||
template <class T>
|
||||
void Delete(T* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
ptr->~T();
|
||||
Deallocate(ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// The default allocator used by the library.
|
||||
/**
|
||||
* Any allocation/deallocation calls are simply forwarded to \c malloc and \c free. Any
|
||||
* requested alignment is ignored.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT DefaultAllocator : public Allocator
|
||||
{
|
||||
public:
|
||||
void* Allocate(size_t size, size_t /*align*/)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void Deallocate(void* ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
/// Returns the default instance of the default allocator.
|
||||
/**
|
||||
* \sa DefaultAllocator
|
||||
*/
|
||||
GAINPUT_LIBEXPORT DefaultAllocator& GetDefaultAllocator();
|
||||
|
||||
template<class K, class V>
|
||||
class GAINPUT_LIBEXPORT HashMap;
|
||||
|
||||
/// An allocator that tracks an allocations that were done
|
||||
/**
|
||||
* Any allocation/deallocation calls are simply forwarded to \c malloc and \c free. Any
|
||||
* requested alignment is ignored.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT TrackingAllocator : public Allocator
|
||||
{
|
||||
public:
|
||||
TrackingAllocator(Allocator& backingAllocator, Allocator& internalAllocator = GetDefaultAllocator());
|
||||
~TrackingAllocator();
|
||||
|
||||
void* Allocate(size_t size, size_t align = DefaultAlign);
|
||||
void Deallocate(void* ptr);
|
||||
|
||||
size_t GetAllocateCount() const { return allocateCount_; }
|
||||
size_t GetDeallocateCount() const { return deallocateCount_; }
|
||||
size_t GetAllocatedMemory() const { return allocatedMemory_; }
|
||||
|
||||
private:
|
||||
Allocator& backingAllocator_;
|
||||
Allocator& internalAllocator_;
|
||||
HashMap<void*, size_t>* allocations_;
|
||||
size_t allocateCount_;
|
||||
size_t deallocateCount_;
|
||||
size_t allocatedMemory_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
508
lib/include/gainput/GainputContainers.h
Normal file
508
lib/include/gainput/GainputContainers.h
Normal file
@@ -0,0 +1,508 @@
|
||||
|
||||
#ifndef GAINPUTCONTAINERS_H_
|
||||
#define GAINPUTCONTAINERS_H_
|
||||
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
|
||||
// -- MurmurHash3 begin --
|
||||
// http://code.google.com/p/smhasher/wiki/MurmurHash3
|
||||
// MurmurHash3 was written by Austin Appleby, and is placed in the public
|
||||
// domain. The author hereby disclaims copyright to this source code.
|
||||
|
||||
inline uint32_t rotl32(uint32_t x, int8_t r)
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
inline uint32_t getblock(const uint32_t * p, int i)
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
|
||||
|
||||
inline uint32_t fmix(uint32_t h)
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/// Calculates MurmurHash3 for the given key.
|
||||
/**
|
||||
* \param key The key to calculate the hash of.
|
||||
* \param len Length of the key in bytes.
|
||||
* \param seed Seed for the hash.
|
||||
* \param[out] out The hash value, a uint32_t in this case.
|
||||
*/
|
||||
inline void MurmurHash3_x86_32(const void * key, int len, uint32_t seed, void * out)
|
||||
{
|
||||
const uint8_t * data = (const uint8_t*)key;
|
||||
const int nblocks = len / 4;
|
||||
|
||||
uint32_t h1 = seed;
|
||||
|
||||
const uint32_t c1 = 0xcc9e2d51;
|
||||
const uint32_t c2 = 0x1b873593;
|
||||
|
||||
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
|
||||
|
||||
for(int i = -nblocks; i; i++)
|
||||
{
|
||||
uint32_t k1 = getblock(blocks,i);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = rotl32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = rotl32(h1,13);
|
||||
h1 = h1*5+0xe6546b64;
|
||||
}
|
||||
|
||||
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
|
||||
|
||||
uint32_t k1 = 0;
|
||||
|
||||
switch(len & 3)
|
||||
{
|
||||
case 3: k1 ^= tail[2] << 16;
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0];
|
||||
k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
|
||||
h1 ^= len;
|
||||
|
||||
h1 = fmix(h1);
|
||||
|
||||
*(uint32_t*)out = h1;
|
||||
}
|
||||
|
||||
// -- MurmurHash3 end --
|
||||
|
||||
|
||||
/// A std::vector-like data container for POD-types.
|
||||
/**
|
||||
* \tparam T A POD-type to hold in this container.
|
||||
*/
|
||||
template<class T>
|
||||
class GAINPUT_LIBEXPORT Array
|
||||
{
|
||||
public:
|
||||
static const size_t DefaultCapacity = 8;
|
||||
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
typedef T value_type;
|
||||
|
||||
Array(Allocator& allocator, size_t capacity = DefaultCapacity) :
|
||||
allocator_(allocator),
|
||||
size_(0),
|
||||
capacity_(capacity)
|
||||
{
|
||||
data_ = static_cast<T*>(allocator_.Allocate(sizeof(T)*capacity_));
|
||||
}
|
||||
|
||||
~Array()
|
||||
{
|
||||
allocator_.Delete(data_);
|
||||
}
|
||||
|
||||
iterator begin() { return data_; }
|
||||
const_iterator begin() const { return data_; }
|
||||
iterator end() { return data_ + size_; }
|
||||
const_iterator end() const { return data_ + size_; }
|
||||
|
||||
T& operator[] (size_t i)
|
||||
{
|
||||
GAINPUT_ASSERT(i < size_);
|
||||
return data_[i];
|
||||
}
|
||||
|
||||
const T& operator[] (size_t i) const
|
||||
{
|
||||
GAINPUT_ASSERT(i < size_);
|
||||
return data_[i];
|
||||
}
|
||||
|
||||
void push_back(const value_type& val)
|
||||
{
|
||||
if (size_ + 1 > capacity_)
|
||||
{
|
||||
reserve(size_ + 1);
|
||||
}
|
||||
data_[size_++] = val;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
if (size_ > 0)
|
||||
--size_;
|
||||
}
|
||||
|
||||
void reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= capacity_)
|
||||
return;
|
||||
capacity = (capacity_*2) < capacity ? capacity : (capacity_*2);
|
||||
T* newData = static_cast<T*>(allocator_.Allocate(sizeof(T)*capacity));
|
||||
memcpy(newData, data_, sizeof(T)*capacity_);
|
||||
allocator_.Deallocate(data_);
|
||||
data_ = newData;
|
||||
capacity_ = capacity;
|
||||
}
|
||||
|
||||
void swap(Array<T>& x)
|
||||
{
|
||||
GAINPUT_ASSERT(&allocator_ == &x.allocator_);
|
||||
|
||||
const size_t thisSize = size_;
|
||||
const size_t capacity = capacity_;
|
||||
T* data = data_;
|
||||
|
||||
size_ = x.size_;
|
||||
capacity_ = x.capacity_;
|
||||
data_ = x.data_;
|
||||
|
||||
x.size_ = thisSize;
|
||||
x.capacity_ = capacity;
|
||||
x.data_ = data;
|
||||
}
|
||||
|
||||
iterator erase(iterator pos)
|
||||
{
|
||||
if (size_ == 0)
|
||||
return end();
|
||||
GAINPUT_ASSERT(pos >= begin() && pos < end());
|
||||
memcpy(pos, pos+1, sizeof(T)*(end()-(pos+1)));
|
||||
--size_;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void clear() { size_ = 0; }
|
||||
|
||||
bool empty() const { return size_ == 0; }
|
||||
size_t size() const { return size_; }
|
||||
|
||||
iterator find(const value_type& val)
|
||||
{
|
||||
for (size_t i = 0; i < size_; ++i)
|
||||
{
|
||||
if (data_[i] == val)
|
||||
{
|
||||
return data_ + i;
|
||||
}
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
const_iterator find(const value_type& val) const
|
||||
{
|
||||
for (size_t i = 0; i < size_; ++i)
|
||||
{
|
||||
if (data_[i] == val)
|
||||
{
|
||||
return data_ + i;
|
||||
}
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
private:
|
||||
Allocator& allocator_;
|
||||
size_t size_;
|
||||
size_t capacity_;
|
||||
T* data_;
|
||||
};
|
||||
|
||||
|
||||
/// A hash table mapping keys to POD-type values.
|
||||
/**
|
||||
* \tparam K The key pointing to a value.
|
||||
* \tparam V POD-type being stored in the table.
|
||||
*/
|
||||
template<class K, class V>
|
||||
class GAINPUT_LIBEXPORT HashMap
|
||||
{
|
||||
public:
|
||||
static const unsigned Seed = 329856235;
|
||||
enum { InvalidKey = unsigned(-1) };
|
||||
|
||||
/// An element of the hash table.
|
||||
struct Node
|
||||
{
|
||||
K first; ///< The element's key.
|
||||
V second; ///< The element's value.
|
||||
uint32_t next; ///< The index of the next element with the same (wrapped) hash; Do not use.
|
||||
};
|
||||
|
||||
typedef Node* iterator;
|
||||
typedef const Node* const_iterator;
|
||||
|
||||
|
||||
HashMap(Allocator& allocator = GetDefaultAllocator()) :
|
||||
allocator_(allocator),
|
||||
keys_(allocator_),
|
||||
values_(allocator_),
|
||||
size_(0)
|
||||
{ }
|
||||
|
||||
iterator begin() { return values_.begin(); }
|
||||
const_iterator begin() const { return values_.begin(); }
|
||||
iterator end() { return values_.begin() + values_.size(); }
|
||||
const_iterator end() const { return values_.begin() + values_.size(); }
|
||||
|
||||
size_t size() const { return size_; }
|
||||
bool empty() const { return size_ == 0; }
|
||||
|
||||
size_t count(const K& k) const
|
||||
{
|
||||
return find(k) != end() ? 1 : 0;
|
||||
}
|
||||
|
||||
iterator find(const K& k)
|
||||
{
|
||||
if (keys_.empty() || values_.empty())
|
||||
return end();
|
||||
uint32_t h;
|
||||
MurmurHash3_x86_32(&k, sizeof(K), Seed, &h);
|
||||
const uint32_t ha = h % keys_.size();
|
||||
volatile uint32_t vi = keys_[ha];
|
||||
while (vi != InvalidKey)
|
||||
{
|
||||
if (values_[vi].first == k)
|
||||
{
|
||||
return &values_[vi];
|
||||
}
|
||||
vi = values_[vi].next;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
const_iterator find(const K& k) const
|
||||
{
|
||||
if (keys_.empty() || values_.empty())
|
||||
return end();
|
||||
uint32_t h;
|
||||
MurmurHash3_x86_32(&k, sizeof(K), Seed, &h);
|
||||
const uint32_t ha = h % keys_.size();
|
||||
volatile uint32_t vi = keys_[ha];
|
||||
while (vi != InvalidKey)
|
||||
{
|
||||
if (values_[vi].first == k)
|
||||
{
|
||||
return &values_[vi];
|
||||
}
|
||||
vi = values_[vi].next;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
iterator insert(const K& k, const V& v)
|
||||
{
|
||||
if (values_.size() >= 0.6f*keys_.size())
|
||||
{
|
||||
Rehash(values_.size()*2 + 10);
|
||||
}
|
||||
|
||||
uint32_t h;
|
||||
MurmurHash3_x86_32(&k, sizeof(K), Seed, &h);
|
||||
const uint32_t ha = h % keys_.size();
|
||||
uint32_t vi = keys_[ha];
|
||||
|
||||
if (vi == InvalidKey)
|
||||
{
|
||||
keys_[ha] = values_.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (values_[vi].next == InvalidKey)
|
||||
{
|
||||
values_[vi].next = values_.size();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
vi = values_[vi].next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Node node;
|
||||
node.first = k;
|
||||
node.second = v;
|
||||
node.next = InvalidKey;
|
||||
values_.push_back(node);
|
||||
|
||||
++size_;
|
||||
|
||||
return &values_[values_.size()-1];
|
||||
}
|
||||
|
||||
V& operator[] (const K& k)
|
||||
{
|
||||
iterator it = find(k);
|
||||
if (it == end())
|
||||
{
|
||||
return insert(k, V())->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
size_t erase(const K& k)
|
||||
{
|
||||
if (keys_.empty())
|
||||
return 0;
|
||||
uint32_t h;
|
||||
MurmurHash3_x86_32(&k, sizeof(K), Seed, &h);
|
||||
const uint32_t ha = h % keys_.size();
|
||||
uint32_t vi = keys_[ha];
|
||||
uint32_t prevVi = InvalidKey;
|
||||
while (vi != InvalidKey)
|
||||
{
|
||||
if (values_[vi].first == k)
|
||||
{
|
||||
if (prevVi == InvalidKey)
|
||||
{
|
||||
keys_[ha] = values_[vi].next;
|
||||
}
|
||||
else
|
||||
{
|
||||
values_[prevVi].next = values_[vi].next;
|
||||
}
|
||||
|
||||
--size_;
|
||||
if (vi == values_.size() - 1)
|
||||
{
|
||||
values_.pop_back();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t lastVi = values_.size()-1;
|
||||
values_[vi] = values_[lastVi];
|
||||
values_.pop_back();
|
||||
|
||||
for (typename Array<uint32_t>::iterator it = keys_.begin(); it != keys_.end(); ++it)
|
||||
{
|
||||
if (*it == lastVi)
|
||||
{
|
||||
*it = vi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (typename Array<Node>::iterator it = values_.begin(); it != values_.end(); ++it)
|
||||
{
|
||||
if (it->next == lastVi)
|
||||
{
|
||||
it->next = vi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
prevVi = vi;
|
||||
vi = values_[vi].next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
keys_.clear();
|
||||
values_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
Allocator& allocator_;
|
||||
Array<uint32_t> keys_;
|
||||
Array<Node> values_;
|
||||
size_t size_;
|
||||
|
||||
void Rehash(size_t newSize)
|
||||
{
|
||||
Array<uint32_t> keys(allocator_, newSize);
|
||||
Array<Node> values(allocator_, values_.size());
|
||||
|
||||
for (size_t i = 0; i < newSize; ++i)
|
||||
keys.push_back(InvalidKey);
|
||||
|
||||
keys_.swap(keys);
|
||||
values_.swap(values);
|
||||
size_ = 0;
|
||||
|
||||
for (typename Array<Node>::const_iterator it = values.begin();
|
||||
it != values.end();
|
||||
++it)
|
||||
{
|
||||
insert(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// A ring buffer.
|
||||
/**
|
||||
* \tparam N The number of elements that can be stored in the ring buffer.
|
||||
* \tparam T Type of the elements stored in the ring buffer.
|
||||
*/
|
||||
template<int N, class T>
|
||||
class GAINPUT_LIBEXPORT RingBuffer
|
||||
{
|
||||
public:
|
||||
RingBuffer() :
|
||||
nextRead_(0),
|
||||
nextWrite_(0)
|
||||
{ }
|
||||
|
||||
|
||||
bool CanGet() const
|
||||
{
|
||||
return nextRead_ < nextWrite_;
|
||||
}
|
||||
|
||||
size_t GetCount() const
|
||||
{
|
||||
const size_t d = nextWrite_ - nextRead_;
|
||||
return d > N ? N : d;
|
||||
}
|
||||
|
||||
T Get()
|
||||
{
|
||||
return buf_[(nextRead_++) % N];
|
||||
}
|
||||
|
||||
void Put(T d)
|
||||
{
|
||||
buf_[(nextWrite_++) % N] = d;
|
||||
while (nextRead_ + N < nextWrite_)
|
||||
++nextRead_;
|
||||
}
|
||||
|
||||
private:
|
||||
T buf_[N];
|
||||
size_t nextRead_;
|
||||
size_t nextWrite_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
34
lib/include/gainput/GainputDebugRenderer.h
Normal file
34
lib/include/gainput/GainputDebugRenderer.h
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
#ifndef GAINPUTDEBUGRENDERER_H_
|
||||
#define GAINPUTDEBUGRENDERER_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Interface for debug rendering of input device states.
|
||||
/**
|
||||
* Coordinates and other measures passed to the interface's functions are in the
|
||||
* range of 0.0f to 1.0f.
|
||||
*
|
||||
* The functions are called as part InputManager::Update().
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT DebugRenderer
|
||||
{
|
||||
public:
|
||||
/// Empty virtual destructor.
|
||||
virtual ~DebugRenderer() { }
|
||||
|
||||
/// Called to draw a circle with the given radius.
|
||||
virtual void DrawCircle(float x, float y, float radius) = 0;
|
||||
|
||||
/// Called to draw a line between the two given points.
|
||||
virtual void DrawLine(float x1, float y1, float x2, float y2) = 0;
|
||||
|
||||
/// Called to draw some text at the given position.
|
||||
virtual void DrawText(float x, float y, const char* const text) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
71
lib/include/gainput/GainputHelpers.h
Normal file
71
lib/include/gainput/GainputHelpers.h
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
#ifndef GAINPUTHELPERS_H_
|
||||
#define GAINPUTHELPERS_H_
|
||||
|
||||
#include <gainput/GainputLog.h>
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
inline void HandleButton(InputDevice& device, InputState& state, InputDeltaState* delta, DeviceButtonId buttonId, bool value)
|
||||
{
|
||||
#ifdef GAINPUT_DEBUG
|
||||
if (value != state.GetBool(buttonId))
|
||||
{
|
||||
GAINPUT_LOG("Button changed: %d, %i\n", buttonId, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (delta)
|
||||
{
|
||||
const bool oldValue = state.GetBool(buttonId);
|
||||
if (value != oldValue)
|
||||
{
|
||||
delta->AddChange(device.GetDeviceId(), buttonId, oldValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
state.Set(buttonId, value);
|
||||
}
|
||||
|
||||
inline void HandleAxis(InputDevice& device, InputState& state, InputDeltaState* delta, DeviceButtonId buttonId, float value)
|
||||
{
|
||||
const float deadZone = device.GetDeadZone(buttonId);
|
||||
if (deadZone > 0.0f)
|
||||
{
|
||||
const float absValue = Abs(value);
|
||||
const float sign = value < 0.0f ? -1.0f : 1.0f;
|
||||
if (absValue < deadZone)
|
||||
{
|
||||
value = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
value -= sign*deadZone;
|
||||
value *= 1.0f / (1.0f - deadZone);
|
||||
}
|
||||
}
|
||||
#ifdef GAINPUT_DEBUG
|
||||
if (value != state.GetFloat(buttonId))
|
||||
{
|
||||
GAINPUT_LOG("Axis changed: %d, %f\n", buttonId, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (delta)
|
||||
{
|
||||
const float oldValue = state.GetFloat(buttonId);
|
||||
if (value != oldValue)
|
||||
{
|
||||
delta->AddChange(device.GetDeviceId(), buttonId, oldValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
state.Set(buttonId, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
59
lib/include/gainput/GainputInputDeltaState.h
Normal file
59
lib/include/gainput/GainputInputDeltaState.h
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
#ifndef GAINPUTINPUTDELTASTATE_H_
|
||||
#define GAINPUTINPUTDELTASTATE_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Stores a list of input state changes.
|
||||
class GAINPUT_LIBEXPORT InputDeltaState
|
||||
{
|
||||
public:
|
||||
InputDeltaState(Allocator& allocator);
|
||||
|
||||
/// Add a state change for a bool-type button.
|
||||
/**
|
||||
* \param device The input device the change occurred on.
|
||||
* \param deviceButton The input button that was changed.
|
||||
* \param oldValue The old button state.
|
||||
* \param newValue The new button state.
|
||||
*/
|
||||
void AddChange(DeviceId device, DeviceButtonId deviceButton, bool oldValue, bool newValue);
|
||||
/// Add a state change for a float-type button.
|
||||
/**
|
||||
* \param device The input device the change occurred on.
|
||||
* \param deviceButton The input button that was changed.
|
||||
* \param oldValue The old button state.
|
||||
* \param newValue The new button state.
|
||||
*/
|
||||
void AddChange(DeviceId device, DeviceButtonId deviceButton, float oldValue, float newValue);
|
||||
|
||||
/// Clear list of state changes.
|
||||
void Clear();
|
||||
|
||||
/// Notifies all input listeners of the previously recorded state changes.
|
||||
/**
|
||||
* \param listeners A list of input listeners to notify.
|
||||
*/
|
||||
void NotifyListeners(Array<InputListener*>& listeners) const;
|
||||
|
||||
private:
|
||||
struct Change
|
||||
{
|
||||
DeviceId device;
|
||||
DeviceButtonId deviceButton;
|
||||
ButtonType type;
|
||||
union
|
||||
{
|
||||
bool b;
|
||||
float f;
|
||||
} oldValue, newValue;
|
||||
};
|
||||
|
||||
Array<Change> changes_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
271
lib/include/gainput/GainputInputDevice.h
Normal file
271
lib/include/gainput/GainputInputDevice.h
Normal file
@@ -0,0 +1,271 @@
|
||||
|
||||
#ifndef GAINPUTINPUTDEVICE_H_
|
||||
#define GAINPUTINPUTDEVICE_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
|
||||
/// Type of an input device button.
|
||||
enum ButtonType
|
||||
{
|
||||
BT_BOOL, ///< A boolean value button, either down (true) or up (false).
|
||||
BT_FLOAT, ///< A floating-point value button, between -1.0f and 1.0f or 0.0f and 1.0f.
|
||||
BT_COUNT ///< The number of different button types.
|
||||
};
|
||||
|
||||
|
||||
/// Interface for anything that provides device inputs.
|
||||
/**
|
||||
* An InputDevice can be anything from a physical device, like a mouse or keyboard, to the more abstract
|
||||
* concept of gestures that in turn themselves depend on other InputDevices. What they have in common is
|
||||
* that they provide a number of device buttons (identified by a DeviceButtonId) which can be queried for
|
||||
* their state.
|
||||
*
|
||||
* Note that you may not instantiate an InputDevice (or any derived implementation) directly. Instead you
|
||||
* have to call InputManager::CreateDevice() or InputManager::CreateAndGetDevice() with the device you want
|
||||
* to instantiate as the template parameter. That way the device will be properly registered with the
|
||||
* InputManager and continuously updated.
|
||||
*
|
||||
* Normally, you won't interact with an InputDevice directly, but instead use its device ID and its device
|
||||
* buttons' IDs to map the device buttons to user buttons (see InputMap).
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputDevice
|
||||
{
|
||||
public:
|
||||
/// Type of an input device.
|
||||
enum DeviceType
|
||||
{
|
||||
DT_MOUSE, ///< A mouse/cursor input device featuring one pointer.
|
||||
DT_KEYBOARD, ///< A keyboard input device.
|
||||
DT_PAD, ///< A joypad/gamepad input device.
|
||||
DT_TOUCH, ///< A touch-sensitive input device supporting multiple simultaneous pointers.
|
||||
DT_BUILTIN, ///< Any controls directly built into the device that also contains the screen.
|
||||
DT_REMOTE, ///< A generic networked input device.
|
||||
DT_GESTURE, ///< A gesture input device, building on top of other input devices.
|
||||
DT_CUSTOM, ///< A custom, user-created input device.
|
||||
DT_COUNT ///< The count of input device types.
|
||||
};
|
||||
|
||||
/// Variant of an input device type.
|
||||
enum DeviceVariant
|
||||
{
|
||||
DV_STANDARD, ///< The standard implementation of the given device type.
|
||||
DV_RAW, ///< The raw input implementation of the given device type.
|
||||
DV_NULL ///< The null/empty implementation of the given device type.
|
||||
};
|
||||
|
||||
/// State of an input device.
|
||||
enum DeviceState
|
||||
{
|
||||
DS_OK, ///< Everything is okay.
|
||||
DS_LOW_BATTERY, ///< The input device is low on battery.
|
||||
DS_UNAVAILABLE ///< The input device is currently not available.
|
||||
};
|
||||
|
||||
static const unsigned AutoIndex = unsigned(-1);
|
||||
|
||||
/// Initializes the input device.
|
||||
/**
|
||||
* Do not instantiate any input device directly. Call InputManager::CreateDevice() instead.
|
||||
*/
|
||||
InputDevice(InputManager& manager, DeviceId device, unsigned index);
|
||||
|
||||
/// Empty virtual destructor.
|
||||
virtual ~InputDevice();
|
||||
|
||||
/// Update this device, internally called by InputManager.
|
||||
/**
|
||||
* \param delta The delta state to add changes to. May be 0.
|
||||
*/
|
||||
void Update(InputDeltaState* delta);
|
||||
|
||||
/// Returns this device's ID.
|
||||
DeviceId GetDeviceId() const { return deviceId_; }
|
||||
/// Returns the device's index among devices of the same type.
|
||||
unsigned GetIndex() const { return index_; }
|
||||
|
||||
/// Returns the device type.
|
||||
virtual DeviceType GetType() const = 0;
|
||||
/// Returns the device variant.
|
||||
virtual DeviceVariant GetVariant() const { return DV_STANDARD; }
|
||||
/// Returns the device type's name.
|
||||
virtual const char* GetTypeName() const = 0;
|
||||
/// Returns if this device should be updated after other devices.
|
||||
virtual bool IsLateUpdate() const { return false; }
|
||||
/// Returns the device state.
|
||||
DeviceState GetState() const;
|
||||
/// Returns if this device is available.
|
||||
virtual bool IsAvailable() const { return GetState() == DS_OK || GetState() == DS_LOW_BATTERY; }
|
||||
|
||||
/// Returns if the given button is valid for this device.
|
||||
virtual bool IsValidButtonId(DeviceButtonId deviceButton) const = 0;
|
||||
|
||||
/// Returns the current state of the given button.
|
||||
bool GetBool(DeviceButtonId deviceButton) const;
|
||||
/// Returns the previous state of the given button.
|
||||
bool GetBoolPrevious(DeviceButtonId deviceButton) const;
|
||||
/// Returns the current state of the given button.
|
||||
float GetFloat(DeviceButtonId deviceButton) const;
|
||||
/// Returns the previous state of the given button.
|
||||
float GetFloatPrevious(DeviceButtonId deviceButton) const;
|
||||
|
||||
/// Checks if any button on this device is down.
|
||||
/**
|
||||
* \param[out] outButtons An array with maxButtonCount fields to receive the device buttons that are down.
|
||||
* \param maxButtonCount The number of fields in outButtons.
|
||||
* \return The number of device buttons written to outButtons.
|
||||
*/
|
||||
virtual size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const { GAINPUT_UNUSED(outButtons); GAINPUT_UNUSED(maxButtonCount); return 0; }
|
||||
|
||||
/// Gets the name of the given button.
|
||||
/**
|
||||
* \param deviceButton ID of the button.
|
||||
* \param buffer A char-buffer to receive the button name.
|
||||
* \param bufferLength Length of the buffer receiving the button name in bytes.
|
||||
* \return The number of bytes written to buffer (includes the trailing \0).
|
||||
*/
|
||||
virtual size_t GetButtonName(DeviceButtonId deviceButton, char* buffer, size_t bufferLength) const { GAINPUT_UNUSED(deviceButton); GAINPUT_UNUSED(buffer); GAINPUT_UNUSED(bufferLength); return 0; }
|
||||
/// Returns the type of the given button.
|
||||
virtual ButtonType GetButtonType(DeviceButtonId deviceButton) const = 0;
|
||||
|
||||
/// Returns the button's ID if the name is of this device's buttons.
|
||||
/**
|
||||
* \param name Name of the device button to look for.
|
||||
* \return The device button ID.
|
||||
*/
|
||||
virtual DeviceButtonId GetButtonByName(const char* name) const { GAINPUT_UNUSED(name); return InvalidDeviceButtonId; }
|
||||
|
||||
/// Returns the device's state, probably best if only used internally.
|
||||
InputState* GetInputState() { return state_; }
|
||||
/// Returns the device's state, probably best if only used internally.
|
||||
const InputState* GetInputState() const { return state_; }
|
||||
/// Returns the device's previous state, probably best if only used internally.
|
||||
InputState* GetPreviousInputState() { return previousState_; }
|
||||
/// Returns the device's state that is currently being determined, may be 0 if not available.
|
||||
virtual InputState* GetNextInputState() { return 0; }
|
||||
|
||||
/// Returns the previously set dead zone for the given button or 0.0f if none was set yet.
|
||||
float GetDeadZone(DeviceButtonId buttonId) const;
|
||||
/// Sets the dead zone for the given button.
|
||||
void SetDeadZone(DeviceButtonId buttonId, float value);
|
||||
|
||||
/// Enable/disable debug rendering of this device.
|
||||
void SetDebugRenderingEnabled(bool enabled);
|
||||
/// Returns true if debug rendering is enabled, false otherwise.
|
||||
bool IsDebugRenderingEnabled() const { return debugRenderingEnabled_; }
|
||||
|
||||
#if defined(GAINPUT_DEV) || defined(GAINPUT_ENABLE_RECORDER)
|
||||
/// Returns true if this device is being controlled by a remote device
|
||||
/// or a recorded input sequence, false otherwise.
|
||||
bool IsSynced() const { return synced_; }
|
||||
/// Sets if this device is being controlled remotely or from a recording.
|
||||
/**
|
||||
* \sa IsSynced()
|
||||
*/
|
||||
void SetSynced(bool synced) { synced_ = synced; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/// The manager this device belongs to.
|
||||
InputManager& manager_;
|
||||
|
||||
/// The ID of this device.
|
||||
DeviceId deviceId_;
|
||||
|
||||
/// Index of this device among devices of the same type.
|
||||
unsigned index_;
|
||||
|
||||
/// The current state of this device.
|
||||
InputState* state_;
|
||||
/// The previous state of this device.
|
||||
InputState* previousState_;
|
||||
|
||||
float* deadZones_;
|
||||
|
||||
/// Specifies if this device is currently rendering debug information.
|
||||
bool debugRenderingEnabled_;
|
||||
|
||||
#if defined(GAINPUT_DEV) || defined(GAINPUT_ENABLE_RECORDER)
|
||||
/// Specifies if this device's state is actually set from a device
|
||||
/// or manually set by some other system.
|
||||
bool synced_;
|
||||
#endif
|
||||
|
||||
/// Implementation of the device's Update function.
|
||||
/**
|
||||
* \param delta The delta state to add changes to. May be 0.
|
||||
*/
|
||||
virtual void InternalUpdate(InputDeltaState* delta) = 0;
|
||||
|
||||
/// Implementation of the device's GetState function.
|
||||
/**
|
||||
* \return The device's state.
|
||||
*/
|
||||
virtual DeviceState InternalGetState() const = 0;
|
||||
|
||||
/// Checks which buttons are down.
|
||||
/**
|
||||
* This function is normally used by GetAnyButtonDown implementations internally.
|
||||
* \param outButtons An array to write buttons that are down to.
|
||||
* \param maxButtonCount The size of outButtons.
|
||||
* \param start The lowest device button ID to check.
|
||||
* \param end The biggest device button ID to check.
|
||||
* \return The number of buttons written to outButtons.
|
||||
*/
|
||||
size_t CheckAllButtonsDown(DeviceButtonSpec* outButtons, size_t maxButtonCount, unsigned start, unsigned end) const;
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
bool
|
||||
InputDevice::GetBool(DeviceButtonId deviceButton) const
|
||||
{
|
||||
if (!IsAvailable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
GAINPUT_ASSERT(state_);
|
||||
return state_->GetBool(deviceButton);
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
InputDevice::GetBoolPrevious(DeviceButtonId deviceButton) const
|
||||
{
|
||||
if (!IsAvailable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
GAINPUT_ASSERT(previousState_);
|
||||
return previousState_->GetBool(deviceButton);
|
||||
}
|
||||
|
||||
inline
|
||||
float
|
||||
InputDevice::GetFloat(DeviceButtonId deviceButton) const
|
||||
{
|
||||
if (!IsAvailable())
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
GAINPUT_ASSERT(state_);
|
||||
return state_->GetFloat(deviceButton);
|
||||
}
|
||||
|
||||
inline
|
||||
float
|
||||
InputDevice::GetFloatPrevious(DeviceButtonId deviceButton) const
|
||||
{
|
||||
if (!IsAvailable())
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
GAINPUT_ASSERT(previousState_);
|
||||
return previousState_->GetFloat(deviceButton);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
68
lib/include/gainput/GainputInputDeviceBuiltIn.h
Normal file
68
lib/include/gainput/GainputInputDeviceBuiltIn.h
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
#ifndef GAINPUTINPUTDEVICEBUILTIN_H_
|
||||
#define GAINPUTINPUTDEVICEBUILTIN_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// All valid device buttons for InputDeviceBuiltIn.
|
||||
enum BuiltInButton
|
||||
{
|
||||
BuiltInButtonAccelerationX,
|
||||
BuiltInButtonAccelerationY,
|
||||
BuiltInButtonAccelerationZ,
|
||||
BuiltInButtonGravityX,
|
||||
BuiltInButtonGravityY,
|
||||
BuiltInButtonGravityZ,
|
||||
BuiltInButtonGyroscopeX,
|
||||
BuiltInButtonGyroscopeY,
|
||||
BuiltInButtonGyroscopeZ,
|
||||
BuiltInButtonMagneticFieldX,
|
||||
BuiltInButtonMagneticFieldY,
|
||||
BuiltInButtonMagneticFieldZ,
|
||||
BuiltInButtonCount_
|
||||
};
|
||||
|
||||
class InputDeviceBuiltInImpl;
|
||||
|
||||
/// An input device for inputs that are directly built into the executing device (for example, sensors in a phone).
|
||||
class GAINPUT_LIBEXPORT InputDeviceBuiltIn : public InputDevice
|
||||
{
|
||||
public:
|
||||
/// Initializes the device.
|
||||
/**
|
||||
* Instantiate the device using InputManager::CreateDevice().
|
||||
*
|
||||
* \param manager The input manager this device is managed by.
|
||||
* \param device The ID of this device.
|
||||
*/
|
||||
InputDeviceBuiltIn(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Shuts down the device.
|
||||
~InputDeviceBuiltIn();
|
||||
|
||||
/// Returns DT_BUILTIN.
|
||||
DeviceType GetType() const { return DT_BUILTIN; }
|
||||
DeviceVariant GetVariant() const;
|
||||
const char* GetTypeName() const { return "builtin"; }
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const;
|
||||
|
||||
size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
|
||||
|
||||
size_t GetButtonName(DeviceButtonId deviceButton, char* buffer, size_t bufferLength) const;
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const;
|
||||
DeviceButtonId GetButtonByName(const char* name) const;
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
DeviceState InternalGetState() const;
|
||||
|
||||
private:
|
||||
InputDeviceBuiltInImpl* impl_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
267
lib/include/gainput/GainputInputDeviceKeyboard.h
Normal file
267
lib/include/gainput/GainputInputDeviceKeyboard.h
Normal file
@@ -0,0 +1,267 @@
|
||||
|
||||
#ifndef GAINPUTINPUTDEVICEKEYBOARD_H_
|
||||
#define GAINPUTINPUTDEVICEKEYBOARD_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// All valid device buttons for InputDeviceKeyboard.
|
||||
enum Key
|
||||
{
|
||||
KeyEscape,
|
||||
KeyF1,
|
||||
KeyF2,
|
||||
KeyF3,
|
||||
KeyF4,
|
||||
KeyF5,
|
||||
KeyF6,
|
||||
KeyF7,
|
||||
KeyF8,
|
||||
KeyF9,
|
||||
KeyF10,
|
||||
KeyF11,
|
||||
KeyF12,
|
||||
KeyF13,
|
||||
KeyF14,
|
||||
KeyF15,
|
||||
KeyF16,
|
||||
KeyF17,
|
||||
KeyF18,
|
||||
KeyF19,
|
||||
KeyPrint,
|
||||
KeyScrollLock,
|
||||
KeyBreak,
|
||||
|
||||
KeySpace = 0x0020,
|
||||
|
||||
KeyApostrophe = 0x0027,
|
||||
KeyComma = 0x002c,
|
||||
KeyMinus = 0x002d,
|
||||
KeyPeriod = 0x002e,
|
||||
KeySlash = 0x002f,
|
||||
|
||||
Key0 = 0x0030,
|
||||
Key1 = 0x0031,
|
||||
Key2 = 0x0032,
|
||||
Key3 = 0x0033,
|
||||
Key4 = 0x0034,
|
||||
Key5 = 0x0035,
|
||||
Key6 = 0x0036,
|
||||
Key7 = 0x0037,
|
||||
Key8 = 0x0038,
|
||||
Key9 = 0x0039,
|
||||
|
||||
KeySemicolon = 0x003b,
|
||||
KeyLess = 0x003c,
|
||||
KeyEqual = 0x003d,
|
||||
|
||||
KeyA = 0x0041,
|
||||
KeyB = 0x0042,
|
||||
KeyC = 0x0043,
|
||||
KeyD = 0x0044,
|
||||
KeyE = 0x0045,
|
||||
KeyF = 0x0046,
|
||||
KeyG = 0x0047,
|
||||
KeyH = 0x0048,
|
||||
KeyI = 0x0049,
|
||||
KeyJ = 0x004a,
|
||||
KeyK = 0x004b,
|
||||
KeyL = 0x004c,
|
||||
KeyM = 0x004d,
|
||||
KeyN = 0x004e,
|
||||
KeyO = 0x004f,
|
||||
KeyP = 0x0050,
|
||||
KeyQ = 0x0051,
|
||||
KeyR = 0x0052,
|
||||
KeyS = 0x0053,
|
||||
KeyT = 0x0054,
|
||||
KeyU = 0x0055,
|
||||
KeyV = 0x0056,
|
||||
KeyW = 0x0057,
|
||||
KeyX = 0x0058,
|
||||
KeyY = 0x0059,
|
||||
KeyZ = 0x005a,
|
||||
|
||||
KeyBracketLeft = 0x005b,
|
||||
KeyBackslash = 0x005c,
|
||||
KeyBracketRight = 0x005d,
|
||||
|
||||
KeyGrave = 0x0060,
|
||||
|
||||
KeyLeft,
|
||||
KeyRight,
|
||||
KeyUp,
|
||||
KeyDown,
|
||||
KeyInsert,
|
||||
KeyHome,
|
||||
KeyDelete,
|
||||
KeyEnd,
|
||||
KeyPageUp,
|
||||
KeyPageDown,
|
||||
|
||||
KeyNumLock,
|
||||
KeyKpEqual,
|
||||
KeyKpDivide,
|
||||
KeyKpMultiply,
|
||||
KeyKpSubtract,
|
||||
KeyKpAdd,
|
||||
KeyKpEnter,
|
||||
KeyKpInsert, // 0
|
||||
KeyKpEnd, // 1
|
||||
KeyKpDown, // 2
|
||||
KeyKpPageDown, // 3
|
||||
KeyKpLeft, // 4
|
||||
KeyKpBegin, // 5
|
||||
KeyKpRight, // 6
|
||||
KeyKpHome, // 7
|
||||
KeyKpUp, // 8
|
||||
KeyKpPageUp, // 9
|
||||
KeyKpDelete, // ,
|
||||
|
||||
KeyBackSpace,
|
||||
KeyTab,
|
||||
KeyReturn,
|
||||
KeyCapsLock,
|
||||
KeyShiftL,
|
||||
KeyCtrlL,
|
||||
KeySuperL,
|
||||
KeyAltL,
|
||||
KeyAltR,
|
||||
KeySuperR,
|
||||
KeyMenu,
|
||||
KeyCtrlR,
|
||||
KeyShiftR,
|
||||
|
||||
KeyBack,
|
||||
KeySoftLeft,
|
||||
KeySoftRight,
|
||||
KeyCall,
|
||||
KeyEndcall,
|
||||
KeyStar,
|
||||
KeyPound,
|
||||
KeyDpadCenter,
|
||||
KeyVolumeUp,
|
||||
KeyVolumeDown,
|
||||
KeyPower,
|
||||
KeyCamera,
|
||||
KeyClear,
|
||||
KeySymbol,
|
||||
KeyExplorer,
|
||||
KeyEnvelope,
|
||||
KeyEquals,
|
||||
KeyAt,
|
||||
KeyHeadsethook,
|
||||
KeyFocus,
|
||||
KeyPlus,
|
||||
KeyNotification,
|
||||
KeySearch,
|
||||
KeyMediaPlayPause,
|
||||
KeyMediaStop,
|
||||
KeyMediaNext,
|
||||
KeyMediaPrevious,
|
||||
KeyMediaRewind,
|
||||
KeyMediaFastForward,
|
||||
KeyMute,
|
||||
KeyPictsymbols,
|
||||
KeySwitchCharset,
|
||||
|
||||
KeyForward,
|
||||
KeyExtra1,
|
||||
KeyExtra2,
|
||||
KeyExtra3,
|
||||
KeyExtra4,
|
||||
KeyExtra5,
|
||||
KeyExtra6,
|
||||
KeyFn,
|
||||
|
||||
KeyCircumflex,
|
||||
KeySsharp,
|
||||
KeyAcute,
|
||||
KeyAltGr,
|
||||
KeyNumbersign,
|
||||
KeyUdiaeresis,
|
||||
KeyAdiaeresis,
|
||||
KeyOdiaeresis,
|
||||
KeySection,
|
||||
KeyAring,
|
||||
KeyDiaeresis,
|
||||
KeyTwosuperior,
|
||||
KeyRightParenthesis,
|
||||
KeyDollar,
|
||||
KeyUgrave,
|
||||
KeyAsterisk,
|
||||
KeyColon,
|
||||
KeyExclam,
|
||||
|
||||
KeyBraceLeft,
|
||||
KeyBraceRight,
|
||||
KeySysRq,
|
||||
|
||||
KeyCount_
|
||||
};
|
||||
|
||||
|
||||
class InputDeviceKeyboardImpl;
|
||||
|
||||
/// A keyboard input device.
|
||||
/**
|
||||
* This input device provides support for standard keyboard devices. The valid device buttons are defined
|
||||
* in the ::Key enum.
|
||||
*
|
||||
* This device is implemented on Android NDK, Linux, and Windows. Note that no support for
|
||||
* virtual keyboards (on-screen) is present.
|
||||
*
|
||||
* The raw variants (InputDevice::DV_RAW) of this device do not support text input.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputDeviceKeyboard : public InputDevice
|
||||
{
|
||||
public:
|
||||
/// Initializes the device.
|
||||
/**
|
||||
* Instantiate the device using InputManager::CreateDevice().
|
||||
*
|
||||
* \param manager The input manager this device is managed by.
|
||||
* \param device The ID of this device.
|
||||
*/
|
||||
InputDeviceKeyboard(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Shuts down the device.
|
||||
~InputDeviceKeyboard();
|
||||
|
||||
/// Returns DT_KEYBOARD.
|
||||
DeviceType GetType() const { return DT_KEYBOARD; }
|
||||
DeviceVariant GetVariant() const;
|
||||
const char* GetTypeName() const { return "keyboard"; }
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton < KeyCount_; }
|
||||
|
||||
size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
|
||||
|
||||
size_t GetButtonName(DeviceButtonId deviceButton, char* buffer, size_t bufferLength) const;
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const;
|
||||
DeviceButtonId GetButtonByName(const char* name) const;
|
||||
|
||||
InputState* GetNextInputState();
|
||||
|
||||
/// Returns if text input is enabled.
|
||||
bool IsTextInputEnabled() const;
|
||||
/// Sets if text input is enabled and therefore if calling GetNextCharacter() make sense.
|
||||
void SetTextInputEnabled(bool enabled);
|
||||
/// Returns the next pending input character if text input is enabled.
|
||||
char GetNextCharacter();
|
||||
|
||||
/// Returns the platform-specific implementation of this device (internal use only).
|
||||
InputDeviceKeyboardImpl* GetPimpl() { return impl_; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
DeviceState InternalGetState() const;
|
||||
|
||||
private:
|
||||
InputDeviceKeyboardImpl* impl_;
|
||||
|
||||
HashMap<Key, const char*> keyNames_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
101
lib/include/gainput/GainputInputDeviceMouse.h
Normal file
101
lib/include/gainput/GainputInputDeviceMouse.h
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
#ifndef GAINPUTINPUTDEVICEMOUSE_H_
|
||||
#define GAINPUTINPUTDEVICEMOUSE_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// All valid device buttons for InputDeviceMouse.
|
||||
enum MouseButton
|
||||
{
|
||||
MouseButton0 = 0,
|
||||
MouseButtonLeft = MouseButton0,
|
||||
MouseButton1,
|
||||
MouseButtonMiddle = MouseButton1,
|
||||
MouseButton2,
|
||||
MouseButtonRight = MouseButton2,
|
||||
MouseButton3,
|
||||
MouseButtonWheelUp = MouseButton3,
|
||||
MouseButton4,
|
||||
MouseButtonWheelDown = MouseButton4,
|
||||
MouseButton5,
|
||||
MouseButton6,
|
||||
MouseButton7,
|
||||
MouseButton8,
|
||||
MouseButton9,
|
||||
MouseButton10,
|
||||
MouseButton11,
|
||||
MouseButton12,
|
||||
MouseButton13,
|
||||
MouseButton14,
|
||||
MouseButton15,
|
||||
MouseButton16,
|
||||
MouseButton17,
|
||||
MouseButton18,
|
||||
MouseButton19,
|
||||
MouseButton20,
|
||||
MouseButtonMax = MouseButton20,
|
||||
MouseButtonCount,
|
||||
MouseAxisX = MouseButtonCount,
|
||||
MouseAxisY,
|
||||
MouseButtonCount_,
|
||||
MouseAxisCount = MouseButtonCount_ - MouseAxisX
|
||||
};
|
||||
|
||||
|
||||
|
||||
class InputDeviceMouseImpl;
|
||||
|
||||
/// A mouse input device.
|
||||
/**
|
||||
* This input device provides support for standard mouse devices. The valid device buttons are defined
|
||||
* in the ::MouseButton enum.
|
||||
*
|
||||
* This device is implemented on Linux and Windows.
|
||||
*
|
||||
* The raw variants (InputDevice::DV_RAW) of this device do not offer normalized absolute axis values.
|
||||
* That means that the values of MouseAxisX and MouseAxisY don't have defined mininum or maximum
|
||||
* values. Therefore only the delta (InputMap::GetFloatDelta()) should be used with raw mouse devices.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputDeviceMouse : public InputDevice
|
||||
{
|
||||
public:
|
||||
/// Initializes the device.
|
||||
/**
|
||||
* Instantiate the device using InputManager::CreateDevice().
|
||||
*
|
||||
* \param manager The input manager this device is managed by.
|
||||
* \param device The ID of this device.
|
||||
*/
|
||||
InputDeviceMouse(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Shuts down the device.
|
||||
~InputDeviceMouse();
|
||||
|
||||
/// Returns DT_MOUSE.
|
||||
DeviceType GetType() const { return DT_MOUSE; }
|
||||
DeviceVariant GetVariant() const;
|
||||
const char* GetTypeName() const { return "mouse"; }
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton < MouseButtonCount_; }
|
||||
|
||||
size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
|
||||
|
||||
size_t GetButtonName(DeviceButtonId deviceButton, char* buffer, size_t bufferLength) const;
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const;
|
||||
DeviceButtonId GetButtonByName(const char* name) const;
|
||||
|
||||
/// Returns the platform-specific implementation of this device (internal use only).
|
||||
InputDeviceMouseImpl* GetPimpl() { return impl_; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
DeviceState InternalGetState() const;
|
||||
|
||||
private:
|
||||
InputDeviceMouseImpl* impl_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
163
lib/include/gainput/GainputInputDevicePad.h
Normal file
163
lib/include/gainput/GainputInputDevicePad.h
Normal file
@@ -0,0 +1,163 @@
|
||||
|
||||
#ifndef GAINPUTINPUTDEVICEPAD_H_
|
||||
#define GAINPUTINPUTDEVICEPAD_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// The maximum number of pads supported.
|
||||
enum { MaxPadCount = 10 };
|
||||
|
||||
/// All valid device buttons for InputDevicePad.
|
||||
enum PadButton
|
||||
{
|
||||
PadButtonLeftStickX,
|
||||
PadButtonLeftStickY,
|
||||
PadButtonRightStickX,
|
||||
PadButtonRightStickY,
|
||||
PadButtonAxis4, // L2/Left trigger
|
||||
PadButtonAxis5, // R2/Right trigger
|
||||
PadButtonAxis6,
|
||||
PadButtonAxis7,
|
||||
PadButtonAxis8,
|
||||
PadButtonAxis9,
|
||||
PadButtonAxis10,
|
||||
PadButtonAxis11,
|
||||
PadButtonAxis12,
|
||||
PadButtonAxis13,
|
||||
PadButtonAxis14,
|
||||
PadButtonAxis15,
|
||||
PadButtonAxis16,
|
||||
PadButtonAxis17,
|
||||
PadButtonAxis18,
|
||||
PadButtonAxis19,
|
||||
PadButtonAxis20,
|
||||
PadButtonAxis21,
|
||||
PadButtonAxis22,
|
||||
PadButtonAxis23,
|
||||
PadButtonAxis24,
|
||||
PadButtonAxis25,
|
||||
PadButtonAxis26,
|
||||
PadButtonAxis27,
|
||||
PadButtonAxis28,
|
||||
PadButtonAxis29,
|
||||
PadButtonAxis30,
|
||||
PadButtonAxis31,
|
||||
PadButtonAccelerationX,
|
||||
PadButtonAccelerationY,
|
||||
PadButtonAccelerationZ,
|
||||
PadButtonGravityX,
|
||||
PadButtonGravityY,
|
||||
PadButtonGravityZ,
|
||||
PadButtonGyroscopeX,
|
||||
PadButtonGyroscopeY,
|
||||
PadButtonGyroscopeZ,
|
||||
PadButtonMagneticFieldX,
|
||||
PadButtonMagneticFieldY,
|
||||
PadButtonMagneticFieldZ,
|
||||
PadButtonStart,
|
||||
PadButtonAxisCount_ = PadButtonStart,
|
||||
PadButtonSelect,
|
||||
PadButtonLeft,
|
||||
PadButtonRight,
|
||||
PadButtonUp,
|
||||
PadButtonDown,
|
||||
PadButtonA, // Cross
|
||||
PadButtonB, // Circle
|
||||
PadButtonX, // Square
|
||||
PadButtonY, // Triangle
|
||||
PadButtonL1,
|
||||
PadButtonR1,
|
||||
PadButtonL2,
|
||||
PadButtonR2,
|
||||
PadButtonL3, // Left thumb
|
||||
PadButtonR3, // Right thumb
|
||||
PadButtonHome, // PS button
|
||||
PadButton17,
|
||||
PadButton18,
|
||||
PadButton19,
|
||||
PadButton20,
|
||||
PadButton21,
|
||||
PadButton22,
|
||||
PadButton23,
|
||||
PadButton24,
|
||||
PadButton25,
|
||||
PadButton26,
|
||||
PadButton27,
|
||||
PadButton28,
|
||||
PadButton29,
|
||||
PadButton30,
|
||||
PadButton31,
|
||||
PadButtonMax_,
|
||||
PadButtonCount_ = PadButtonMax_ - PadButtonAxisCount_
|
||||
};
|
||||
|
||||
class InputDevicePadImpl;
|
||||
|
||||
/// A pad input device.
|
||||
/**
|
||||
* This input device provides support for gamepad devices. The valid device buttons are defined
|
||||
* in the ::PadButton enum.
|
||||
*
|
||||
* This device is implemented on Android NDK, Linux and Windows.
|
||||
*
|
||||
* Note that the Android implementation does not support any external pads, but only internal
|
||||
* sensors (acceleration, gyroscope, magnetic field).
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputDevicePad : public InputDevice
|
||||
{
|
||||
public:
|
||||
/// The operating system device IDs for all possible pads.
|
||||
static const char* PadDeviceIds[MaxPadCount];
|
||||
// TODO SetPadDeviceId(padIndex, const char* id);
|
||||
|
||||
/// Initializes the device.
|
||||
/**
|
||||
* Instantiate the device using InputManager::CreateDevice().
|
||||
*
|
||||
* \param manager The input manager this device is managed by.
|
||||
* \param device The ID of this device.
|
||||
*/
|
||||
InputDevicePad(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Shuts down the device.
|
||||
~InputDevicePad();
|
||||
|
||||
/// Returns DT_PAD.
|
||||
DeviceType GetType() const { return DT_PAD; }
|
||||
DeviceVariant GetVariant() const;
|
||||
const char* GetTypeName() const { return "pad"; }
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const;
|
||||
|
||||
size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
|
||||
|
||||
size_t GetButtonName(DeviceButtonId deviceButton, char* buffer, size_t bufferLength) const;
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const;
|
||||
DeviceButtonId GetButtonByName(const char* name) const;
|
||||
|
||||
InputState* GetNextInputState();
|
||||
|
||||
/// Enables the rumble feature of the pad.
|
||||
/**
|
||||
* \param leftMotor Speed of the left motor, between 0.0 and 1.0.
|
||||
* \param rightMotor Speed of the right motor, between 0.0 and 1.0.
|
||||
* \return true if rumble was enabled successfully, false otherwise.
|
||||
*/
|
||||
bool Vibrate(float leftMotor, float rightMotor);
|
||||
|
||||
/// Returns the platform-specific implementation of this device.
|
||||
InputDevicePadImpl* GetPimpl() { return impl_; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
DeviceState InternalGetState() const;
|
||||
|
||||
private:
|
||||
InputDevicePadImpl* impl_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
107
lib/include/gainput/GainputInputDeviceTouch.h
Normal file
107
lib/include/gainput/GainputInputDeviceTouch.h
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
#ifndef GAINPUTINPUTDEVICETOUCH_H_
|
||||
#define GAINPUTINPUTDEVICETOUCH_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// All valid device inputs for InputDeviceTouch.
|
||||
enum TouchButton
|
||||
{
|
||||
Touch0Down,
|
||||
Touch0X,
|
||||
Touch0Y,
|
||||
Touch0Pressure,
|
||||
Touch1Down,
|
||||
Touch1X,
|
||||
Touch1Y,
|
||||
Touch1Pressure,
|
||||
Touch2Down,
|
||||
Touch2X,
|
||||
Touch2Y,
|
||||
Touch2Pressure,
|
||||
Touch3Down,
|
||||
Touch3X,
|
||||
Touch3Y,
|
||||
Touch3Pressure,
|
||||
Touch4Down,
|
||||
Touch4X,
|
||||
Touch4Y,
|
||||
Touch4Pressure,
|
||||
Touch5Down,
|
||||
Touch5X,
|
||||
Touch5Y,
|
||||
Touch5Pressure,
|
||||
Touch6Down,
|
||||
Touch6X,
|
||||
Touch6Y,
|
||||
Touch6Pressure,
|
||||
Touch7Down,
|
||||
Touch7X,
|
||||
Touch7Y,
|
||||
Touch7Pressure,
|
||||
TouchCount_
|
||||
};
|
||||
|
||||
|
||||
|
||||
class InputDeviceTouchImpl;
|
||||
|
||||
/// A touch input device.
|
||||
/**
|
||||
* This input device provides support for touch screen/surface devices. The valid device buttons are defined
|
||||
* in the ::TouchButton enum. For each touch point, there is a boolean input (Touch*Down) showing if the
|
||||
* touch point is active, two float inputs (Touch*X, Touch*Y) showing the touch point's position, and a
|
||||
* float input (Touch*Pressure) showing the touch's pressure.
|
||||
*
|
||||
* Not all touch points must be numbered consecutively, i.e. point #2 may be down even though #0 and #1 are not.
|
||||
*
|
||||
* The number of simultaneously possible touch points is implementaion-dependent.
|
||||
*
|
||||
* This device is implemented on Android NDK.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputDeviceTouch : public InputDevice
|
||||
{
|
||||
public:
|
||||
/// Initializes the device.
|
||||
/**
|
||||
* Instantiate the device using InputManager::CreateDevice().
|
||||
*
|
||||
* \param manager The input manager this device is managed by.
|
||||
* \param device The ID of this device.
|
||||
*/
|
||||
InputDeviceTouch(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Shuts down the device.
|
||||
~InputDeviceTouch();
|
||||
|
||||
/// Returns DT_TOUCH.
|
||||
DeviceType GetType() const { return DT_TOUCH; }
|
||||
DeviceVariant GetVariant() const;
|
||||
const char* GetTypeName() const { return "touch"; }
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const;
|
||||
|
||||
size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
|
||||
|
||||
size_t GetButtonName(DeviceButtonId deviceButton, char* buffer, size_t bufferLength) const;
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const;
|
||||
DeviceButtonId GetButtonByName(const char* name) const;
|
||||
|
||||
InputState* GetNextInputState();
|
||||
|
||||
/// Returns the platform-specific implementation of this device.
|
||||
InputDeviceTouchImpl* GetPimpl() { return impl_; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
DeviceState InternalGetState() const;
|
||||
|
||||
private:
|
||||
InputDeviceTouchImpl* impl_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
77
lib/include/gainput/GainputInputListener.h
Normal file
77
lib/include/gainput/GainputInputListener.h
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
#ifndef GAINPUTINPUTLISTENER_H_
|
||||
#define GAINPUTINPUTLISTENER_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Listener interface that allows to receive notifications when device button states change.
|
||||
class GAINPUT_LIBEXPORT InputListener
|
||||
{
|
||||
public:
|
||||
virtual ~InputListener() { }
|
||||
|
||||
/// Called when a bool-type button state changes.
|
||||
/**
|
||||
* \param device The input device's ID the state change occurred on.
|
||||
* \param deviceButton The ID of the device button that changed.
|
||||
* \param oldValue Previous state of the button.
|
||||
* \param newValue New state of the button.
|
||||
* \return true if the button may be processed by listeners with a lower priority, false otherwise.
|
||||
*/
|
||||
virtual bool OnDeviceButtonBool(DeviceId device, DeviceButtonId deviceButton, bool oldValue, bool newValue) { GAINPUT_UNUSED(device); GAINPUT_UNUSED(deviceButton); GAINPUT_UNUSED(oldValue); GAINPUT_UNUSED(newValue); return true; }
|
||||
|
||||
/// Called when a float-type button state changes.
|
||||
/**
|
||||
* \param device The input device's ID the state change occurred on.
|
||||
* \param deviceButton The ID of the device button that changed.
|
||||
* \param oldValue Previous state of the button.
|
||||
* \param newValue New state of the button.
|
||||
* \return true if the button may be processed by listeners with a lower priority, false otherwise.
|
||||
*/
|
||||
virtual bool OnDeviceButtonFloat(DeviceId device, DeviceButtonId deviceButton, float oldValue, float newValue) { GAINPUT_UNUSED(device); GAINPUT_UNUSED(deviceButton); GAINPUT_UNUSED(oldValue); GAINPUT_UNUSED(newValue); return true; }
|
||||
|
||||
/// Returns the priority which influences the order in which listeners are called by InputManager.
|
||||
/**
|
||||
* \sa InputManager::ReorderListeners()
|
||||
*/
|
||||
virtual int GetPriority() const { return 0; }
|
||||
};
|
||||
|
||||
|
||||
/// Listener interface that allows to receive notifications when user button states change.
|
||||
class GAINPUT_LIBEXPORT MappedInputListener
|
||||
{
|
||||
public:
|
||||
virtual ~MappedInputListener() { }
|
||||
|
||||
/// Called when a bool-type button state changes.
|
||||
/**
|
||||
* \param userButton The user button's ID.
|
||||
* \param oldValue Previous state of the button.
|
||||
* \param newValue New state of the button.
|
||||
* \return true if the button may be processed by listeners with a lower priority, false otherwise.
|
||||
*/
|
||||
virtual bool OnUserButtonBool(UserButtonId userButton, bool oldValue, bool newValue) { GAINPUT_UNUSED(userButton); GAINPUT_UNUSED(oldValue); GAINPUT_UNUSED(newValue); return true; }
|
||||
|
||||
/// Called when a float-type button state changes.
|
||||
/**
|
||||
* \param userButton The user button's ID.
|
||||
* \param oldValue Previous state of the button.
|
||||
* \param newValue New state of the button.
|
||||
* \return true if the button may be processed by listeners with a lower priority, false otherwise.
|
||||
*/
|
||||
virtual bool OnUserButtonFloat(UserButtonId userButton, float oldValue, float newValue) { GAINPUT_UNUSED(userButton); GAINPUT_UNUSED(oldValue); GAINPUT_UNUSED(newValue); return true; }
|
||||
|
||||
/// Returns the priority which influences the order in which listeners are called by InputMap.
|
||||
/**
|
||||
* \sa InputMap::ReorderListeners()
|
||||
*/
|
||||
virtual int GetPriority() const { return 0; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
331
lib/include/gainput/GainputInputManager.h
Normal file
331
lib/include/gainput/GainputInputManager.h
Normal file
@@ -0,0 +1,331 @@
|
||||
|
||||
#ifndef GAINPUTINPUTMANAGER_H_
|
||||
#define GAINPUTINPUTMANAGER_H_
|
||||
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Manages all input devices and some other helpful stuff.
|
||||
/**
|
||||
* This manager takes care of all device-related things. Normally, you should only need one that contains
|
||||
* all your input devices.
|
||||
*
|
||||
* After instantiating an InputManager, you have to call SetDisplaySize(). You should also create some
|
||||
* input devices using the template function CreateDevice() which returns the device ID that is needed
|
||||
* to do anything further with the device (for example, see InputMap).
|
||||
*
|
||||
* The manager has to be updated every frame by calling Update(). Depending on the platform,
|
||||
* you may have to call another function as part of your message handling code (see HandleMessage(), HandleInput()).
|
||||
*
|
||||
* Note that destruction of an InputManager invalidates all input maps based on it and all devices created
|
||||
* through it.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputManager
|
||||
{
|
||||
public:
|
||||
/// Initializes the manager.
|
||||
/**
|
||||
* Further initialization is typically necessary.
|
||||
* \param useSystemTime Specifies if the GetTime() function uses system time or the time
|
||||
* supplied to Update(uint64_t).
|
||||
* \param allocator The memory allocator to be used for all allocations.
|
||||
* \see SetDisplaySize
|
||||
* \see GetTime
|
||||
*/
|
||||
InputManager(bool useSystemTime = true, Allocator& allocator = GetDefaultAllocator());
|
||||
|
||||
/// Destructs the manager.
|
||||
~InputManager();
|
||||
|
||||
/// Sets the window resolution.
|
||||
/**
|
||||
* Informs the InputManager and its devices of the size of the window that is used for
|
||||
* receiving inputs. For example, the size is used to to normalize mouse inputs.
|
||||
*/
|
||||
void SetDisplaySize(int width, int height) { displayWidth_ = width; displayHeight_ = height; }
|
||||
|
||||
#if defined(GAINPUT_PLATFORM_LINUX)
|
||||
/// [LINUX ONLY] Lets the InputManager handle the given X event.
|
||||
/**
|
||||
* Call this function for event types MotionNotify, ButtonPress,
|
||||
* ButtonRelease, KeyPress, KeyRelease.
|
||||
*/
|
||||
void HandleEvent(XEvent& event);
|
||||
#endif
|
||||
#if defined(GAINPUT_PLATFORM_WIN)
|
||||
/// [WINDOWS ONLY] Lets the InputManager handle the given Windows message.
|
||||
/**
|
||||
* Call this function for message types WM_CHAR, WM_KEYDOWN, WM_KEYUP,
|
||||
* WM_SYSKEYDOWN, WM_SYSKEYUP, WM_?BUTTON*, WM_MOUSEMOVE, WM_MOUSEWHEEL.
|
||||
*/
|
||||
void HandleMessage(const MSG& msg);
|
||||
#endif
|
||||
#if defined(GAINPUT_PLATFORM_ANDROID)
|
||||
/// [ANDROID ONLY] Lets the InputManager handle the given input event.
|
||||
int32_t HandleInput(AInputEvent* event);
|
||||
|
||||
struct DeviceInput
|
||||
{
|
||||
InputDevice::DeviceType deviceType;
|
||||
unsigned deviceIndex;
|
||||
ButtonType buttonType;
|
||||
DeviceButtonId buttonId;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
bool b;
|
||||
} value;
|
||||
};
|
||||
void HandleDeviceInput(DeviceInput const& input);
|
||||
#endif
|
||||
|
||||
/// Updates the input state, call this every frame.
|
||||
/**
|
||||
* If the InputManager was initialized with `useSystemTime` set to `false`, you have to
|
||||
* call Update(uint64_t) instead.
|
||||
* \see GetTime
|
||||
*/
|
||||
void Update();
|
||||
|
||||
/// Updates the input state and the manager's time, call this every frame.
|
||||
/**
|
||||
* Updates the time returned by GetTime() and then calls the regular Update(). This function
|
||||
* should only be called if the InputManager was initialized with `useSystemTime`
|
||||
* set to `false`.
|
||||
* \param deltaTime The provided must be in milliseconds.
|
||||
* \see Update
|
||||
* \see GetTime
|
||||
*/
|
||||
void Update(uint64_t deltaTime);
|
||||
|
||||
/// Returns the allocator to be used for memory allocations.
|
||||
Allocator& GetAllocator() const { return allocator_; }
|
||||
|
||||
/// Returns a monotonic time in milliseconds.
|
||||
uint64_t GetTime() const;
|
||||
|
||||
/// Creates an input device and registers it with the manager.
|
||||
/**
|
||||
* \tparam T The input device class, muste be derived from InputDevice.
|
||||
* \param variant Requests the specified device variant. Note that this is only
|
||||
* a request. Another implementation variant of the device may silently be instantiated
|
||||
* instead. To determine what variant was instantiated, call InputDevice::GetVariant().
|
||||
* \return The ID of the newly created input device.
|
||||
*/
|
||||
template<class T> DeviceId CreateDevice(unsigned index = InputDevice::AutoIndex, InputDevice::DeviceVariant variant = InputDevice::DV_STANDARD);
|
||||
/// Creates an input device, registers it with the manager and returns it.
|
||||
/**
|
||||
* \tparam T The input device class, muste be derived from InputDevice.
|
||||
* \param variant Requests the specified device variant. Note that this is only
|
||||
* a request. Another implementation variant of the device may silently be instantiated
|
||||
* instead. To determine what variant was instantiated, call InputDevice::GetVariant().
|
||||
* \return The newly created input device.
|
||||
*/
|
||||
template<class T> T* CreateAndGetDevice(unsigned index = InputDevice::AutoIndex, InputDevice::DeviceVariant variant = InputDevice::DV_STANDARD);
|
||||
/// Returns the input device with the given ID.
|
||||
/**
|
||||
* \return The input device or 0 if it doesn't exist.
|
||||
*/
|
||||
InputDevice* GetDevice(DeviceId deviceId);
|
||||
/// Returns the input device with the given ID.
|
||||
/**
|
||||
* \return The input device or 0 if it doesn't exist.
|
||||
*/
|
||||
const InputDevice* GetDevice(DeviceId deviceId) const;
|
||||
/// Returns the ID of the device with the given type and index.
|
||||
/**
|
||||
* \param typeName The name of the device type. Should come from InputDevice::GetTypeName().
|
||||
* \param index The index of the device. Should come from InputDevice::GetIndex().
|
||||
* \return The device's ID or InvalidDeviceId if no matching device exists.
|
||||
*/
|
||||
DeviceId FindDeviceId(const char* typeName, unsigned index) const;
|
||||
/// Returns the ID of the device with the given type and index.
|
||||
/**
|
||||
* \param type The device type. Should come from InputDevice::GetType().
|
||||
* \param index The index of the device. Should come from InputDevice::GetIndex().
|
||||
* \return The device's ID or InvalidDeviceId if no matching device exists.
|
||||
*/
|
||||
DeviceId FindDeviceId(InputDevice::DeviceType type, unsigned index) const;
|
||||
|
||||
typedef HashMap<DeviceId, InputDevice*> DeviceMap;
|
||||
/// Iterator over all registered devices.
|
||||
typedef DeviceMap::iterator iterator;
|
||||
/// Const iterator over all registered devices.
|
||||
typedef DeviceMap::const_iterator const_iterator;
|
||||
|
||||
/// Returns the begin iterator over all registered devices.
|
||||
iterator begin() { return devices_.begin(); }
|
||||
/// Returns the end iterator over all registered devices.
|
||||
iterator end() { return devices_.end(); }
|
||||
/// Returns the begin iterator over all registered devices.
|
||||
const_iterator begin() const { return devices_.begin(); }
|
||||
/// Returns the end iterator over all registered devices.
|
||||
const_iterator end() const { return devices_.end(); }
|
||||
|
||||
/// Registers a listener to be notified when a button state changes.
|
||||
/**
|
||||
* If there are listeners registered, all input devices will have to record their state changes. This incurs extra runtime costs.
|
||||
*/
|
||||
ListenerId AddListener(InputListener* listener);
|
||||
/// De-registers the given listener.
|
||||
void RemoveListener(ListenerId listenerId);
|
||||
/// Sorts the list of listeners which controls the order in which listeners are called.
|
||||
/**
|
||||
* The order of listeners may be important as the functions being called to notify a listener of a state change can control if
|
||||
* the state change will be passed to any consequent listeners. Call this function whenever listener priorites have changed. It
|
||||
* is automatically called by AddListener() and RemoveListener().
|
||||
*/
|
||||
void ReorderListeners();
|
||||
|
||||
/// Checks if any button on any device is down.
|
||||
/**
|
||||
* \param[out] outButtons An array with maxButtonCount fields to receive the device buttons that are down.
|
||||
* \param maxButtonCount The number of fields in outButtons.
|
||||
* \return The number of device buttons written to outButtons.
|
||||
*/
|
||||
size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
|
||||
|
||||
/// Returns the number of devices with the given type.
|
||||
unsigned GetDeviceCountByType(InputDevice::DeviceType type) const;
|
||||
/// Returns the graphical display's width in pixels.
|
||||
int GetDisplayWidth() const { return displayWidth_; }
|
||||
/// Returns the graphical display's height in pixels.
|
||||
int GetDisplayHeight() const { return displayHeight_; }
|
||||
|
||||
/// Registers a modifier that will be called after devices have been updated.
|
||||
ModifierId AddDeviceStateModifier(DeviceStateModifier* modifier);
|
||||
/// De-registers the given modifier.
|
||||
void RemoveDeviceStateModifier(ModifierId modifierId);
|
||||
|
||||
void EnqueueConcurrentChange(InputDevice& device, InputState& state, InputDeltaState* delta, DeviceButtonId buttonId, bool value);
|
||||
void EnqueueConcurrentChange(InputDevice& device, InputState& state, InputDeltaState* delta, DeviceButtonId buttonId, float value);
|
||||
|
||||
/// [IN dev BUILDS ONLY] Connect to a remote host to send device state changes to.
|
||||
void ConnectForStateSync(const char* ip, unsigned port);
|
||||
/// [IN dev BUILDS ONLY] Initiate sending of device state changes to the given device.
|
||||
void StartDeviceStateSync(DeviceId deviceId);
|
||||
|
||||
/// Enable/disable debug rendering of input devices.
|
||||
void SetDebugRenderingEnabled(bool enabled);
|
||||
/// Returns true if debug rendering is enabled, false otherwise.
|
||||
bool IsDebugRenderingEnabled() const { return debugRenderingEnabled_; }
|
||||
/// Sets the debug renderer to be used if debug rendering is enabled.
|
||||
void SetDebugRenderer(DebugRenderer* debugRenderer);
|
||||
/// Returns the previously set debug renderer.
|
||||
DebugRenderer* GetDebugRenderer() const { return debugRenderer_; }
|
||||
|
||||
private:
|
||||
Allocator& allocator_;
|
||||
|
||||
DeviceMap devices_;
|
||||
unsigned nextDeviceId_;
|
||||
|
||||
HashMap<ListenerId, InputListener*> listeners_;
|
||||
unsigned nextListenerId_;
|
||||
Array<InputListener*> sortedListeners_;
|
||||
|
||||
HashMap<ModifierId, DeviceStateModifier*> modifiers_;
|
||||
unsigned nextModifierId_;
|
||||
|
||||
InputDeltaState* deltaState_;
|
||||
|
||||
uint64_t currentTime_;
|
||||
struct Change
|
||||
{
|
||||
InputDevice* device;
|
||||
InputState* state;
|
||||
InputDeltaState* delta;
|
||||
DeviceButtonId buttonId;
|
||||
ButtonType type;
|
||||
union
|
||||
{
|
||||
bool b;
|
||||
float f;
|
||||
};
|
||||
};
|
||||
|
||||
GAINPUT_CONC_QUEUE(Change) concurrentInputs_;
|
||||
|
||||
int displayWidth_;
|
||||
int displayHeight_;
|
||||
bool useSystemTime_;
|
||||
|
||||
bool debugRenderingEnabled_;
|
||||
DebugRenderer* debugRenderer_;
|
||||
|
||||
void DeviceCreated(InputDevice* device);
|
||||
|
||||
// Do not copy.
|
||||
InputManager(const InputManager &);
|
||||
InputManager& operator=(const InputManager &);
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
DeviceId
|
||||
InputManager::CreateDevice(unsigned index, InputDevice::DeviceVariant variant)
|
||||
{
|
||||
T* device = allocator_.New<T>(*this, nextDeviceId_, index, variant);
|
||||
devices_[nextDeviceId_] = device;
|
||||
DeviceCreated(device);
|
||||
return nextDeviceId_++;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
T*
|
||||
InputManager::CreateAndGetDevice(unsigned index, InputDevice::DeviceVariant variant)
|
||||
{
|
||||
T* device = allocator_.New<T>(*this, nextDeviceId_, index, variant);
|
||||
devices_[nextDeviceId_] = device;
|
||||
++nextDeviceId_;
|
||||
DeviceCreated(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
inline
|
||||
InputDevice*
|
||||
InputManager::GetDevice(DeviceId deviceId)
|
||||
{
|
||||
DeviceMap::iterator it = devices_.find(deviceId);
|
||||
if (it == devices_.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
inline
|
||||
const InputDevice*
|
||||
InputManager::GetDevice(DeviceId deviceId) const
|
||||
{
|
||||
DeviceMap::const_iterator it = devices_.find(deviceId);
|
||||
if (it == devices_.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
/// Interface for modifiers that change device input states after they have been updated.
|
||||
class DeviceStateModifier
|
||||
{
|
||||
public:
|
||||
/// Called after non-dependent devices have been updated.
|
||||
/**
|
||||
* This function is called by InputManager::Update() after InputDevice::Update() has been
|
||||
* called on all registered devices that have InputDevice::IsLateUpdate() return \c false.
|
||||
*
|
||||
* \param delta All device state changes should be registered with this delta state, may be 0.
|
||||
*/
|
||||
virtual void Update(InputDeltaState* delta) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
195
lib/include/gainput/GainputInputMap.h
Normal file
195
lib/include/gainput/GainputInputMap.h
Normal file
@@ -0,0 +1,195 @@
|
||||
|
||||
#ifndef GAINPUTINPUTMAP_H_
|
||||
#define GAINPUTINPUTMAP_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
class UserButton;
|
||||
|
||||
/// Type for filter functions that can be used to filter mapped float inputs.
|
||||
typedef float (*FilterFunc_T)(float const value, void* userData);
|
||||
|
||||
/// Maps user buttons to device buttons.
|
||||
/**
|
||||
* This is the interface that should be used to get input. You can have several maps that are used
|
||||
* simultaneously or use different ones depending on game state. The user button IDs have to be unique per input map.
|
||||
*
|
||||
* InputMap uses the provided InputManager to get devices inputs and process them into user-mapped inputs. After creating
|
||||
* an InputMap, you should map some device buttons to user buttons (using MapBool() or MapFloat()). User buttons are identified
|
||||
* by an ID provided by you. In order to ensure their uniqueness, it's a good idea to define an enum containing all your user buttons
|
||||
* for any given InputMap. It's of course possible to map multiple different device button to one user button.
|
||||
*
|
||||
* After a user button has been mapped, you can query its state by calling one of the several GetBool* and GetFloat* functions. The
|
||||
* result will depend on the mapped device button(s) and the policy (set using SetUserButtonPolicy()).
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputMap
|
||||
{
|
||||
public:
|
||||
/// Initializes the map.
|
||||
/**
|
||||
* \param manager The input manager used to get device inputs.
|
||||
* \param name The name for the input map (optional). If a name is provided, it is copied to an internal buffer.
|
||||
* \param allocator The allocator to be used for all memory allocations.
|
||||
*/
|
||||
InputMap(InputManager& manager, const char* name = 0, Allocator& allocator = GetDefaultAllocator());
|
||||
/// Unitializes the map.
|
||||
~InputMap();
|
||||
|
||||
/// Clears all mapped inputs.
|
||||
void Clear();
|
||||
|
||||
/// Returns the input manager this input map uses.
|
||||
const InputManager& GetManager() const { return manager_; }
|
||||
/// Returns the map's name, if any.
|
||||
/**
|
||||
* \return The map's name or 0 if no name was set.
|
||||
*/
|
||||
const char* GetName() const { return name_; }
|
||||
/// Returns the map's auto-generated ID (that should not be used outside of the library).
|
||||
unsigned GetId() const { return id_; }
|
||||
|
||||
/// Maps a bool-type button.
|
||||
/**
|
||||
* \param userButton The user ID for this mapping.
|
||||
* \param device The device's ID of the device button to be mapped.
|
||||
* \param deviceButton The ID of the device button to be mapped.
|
||||
* \return true if the mapping was created.
|
||||
*/
|
||||
bool MapBool(UserButtonId userButton, DeviceId device, DeviceButtonId deviceButton);
|
||||
/// Maps a float-type button, possibly to a custom range.
|
||||
/**
|
||||
* \param userButton The user ID for this mapping.
|
||||
* \param device The device's ID of the device button to be mapped.
|
||||
* \param deviceButton The ID of the device button to be mapped.
|
||||
* \param min Optional minimum value of the mapped button.
|
||||
* \param max Optional maximum value of the mapped button.
|
||||
* \param filterFunc Optional filter functions that modifies the device button value.
|
||||
* \param filterUserData Optional user data pointer that is passed to filterFunc.
|
||||
* \return true if the mapping was created.
|
||||
*/
|
||||
bool MapFloat(UserButtonId userButton, DeviceId device, DeviceButtonId deviceButton,
|
||||
float min = 0.0f, float max = 1.0f,
|
||||
FilterFunc_T filterFunc = 0, void* filterUserData = 0);
|
||||
/// Removes all mappings for the given user button.
|
||||
void Unmap(UserButtonId userButton);
|
||||
/// Returns if the given user button has any mappings.
|
||||
bool IsMapped(UserButtonId userButton) const;
|
||||
|
||||
/// Gets all device buttons mapped to the given user button.
|
||||
/**
|
||||
* \param userButton The user button ID of the button to return all mappings for.
|
||||
* \param[out] outButtons An array with maxButtonCount fields to receive the device buttons that are mapped.
|
||||
* \param maxButtonCount The number of fields in outButtons.
|
||||
* \return The number of device buttons written to outButtons.
|
||||
*/
|
||||
size_t GetMappings(UserButtonId userButton, DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
|
||||
|
||||
/// Policy for how multiple device buttons are summarized in one user button.
|
||||
enum UserButtonPolicy
|
||||
{
|
||||
UBP_FIRST_DOWN, ///< The first device buttons that is down (or not 0.0f) determines the result.
|
||||
UBP_MAX, ///< The maximum of all device button states is the result.
|
||||
UBP_MIN, ///< The minimum of all device button states is the result.
|
||||
UBP_AVERAGE ///< The average of all device button states is the result.
|
||||
};
|
||||
/// Sets how a user button handles inputs from multiple device buttons.
|
||||
/**
|
||||
* \return true if the policy was set, false otherwise (i.e. the user button doesn't exist).
|
||||
*/
|
||||
bool SetUserButtonPolicy(UserButtonId userButton, UserButtonPolicy policy);
|
||||
|
||||
/// Sets a dead zone for a float-type button.
|
||||
/**
|
||||
* If a dead zone is set for a button anything less or equal to the given value will be treated
|
||||
* as 0.0f. The absolute input value is used in order to determine if the input value falls within the dead
|
||||
* zone (i.e. with a dead zone of 0.2f, both -0.1f and 0.1f will result in 0.0f).
|
||||
*
|
||||
* \param userButton The user button's ID.
|
||||
* \param deadZone The dead zone to be set.
|
||||
* \return true if the dead zone was set, false otherwise (i.e. the user button doesn't exist).
|
||||
*/
|
||||
bool SetDeadZone(UserButtonId userButton, float deadZone);
|
||||
|
||||
/// Returns the bool state of a user button.
|
||||
bool GetBool(UserButtonId userButton) const;
|
||||
/// Returns if the user button is newly down.
|
||||
bool GetBoolIsNew(UserButtonId userButton) const;
|
||||
/// Returns the bool state of a user button from the previous frame.
|
||||
bool GetBoolPrevious(UserButtonId userButton) const;
|
||||
/// Returns if the user button has been released.
|
||||
bool GetBoolWasDown(UserButtonId userButton) const;
|
||||
|
||||
/// Returns the float state of a user button.
|
||||
float GetFloat(UserButtonId userButton) const;
|
||||
/// Returns the float state of a user button from the previous frame.
|
||||
float GetFloatPrevious(UserButtonId userButton) const;
|
||||
/// Returns the delta between the previous and the current frame of the float state of the given user button.
|
||||
float GetFloatDelta(UserButtonId userButton) const;
|
||||
|
||||
/// Gets the name of the device button mapped to the given user button.
|
||||
/**
|
||||
* \param userButton ID of the user button.
|
||||
* \param buffer A char-buffer to receive the button name.
|
||||
* \param bufferLength Length of the buffer receiving the button name in bytes.
|
||||
* \return The number of bytes written to buffer (includes the trailing \0).
|
||||
*/
|
||||
size_t GetUserButtonName(UserButtonId userButton, char* buffer, size_t bufferLength) const;
|
||||
|
||||
/// Returns the user button ID the given device button is mapped to.
|
||||
/**
|
||||
* This function iterates over all mapped buttons and therefore shouldn't be used in a performance critical
|
||||
* situation.
|
||||
*
|
||||
* \param device The device's ID of the device button to be checked.
|
||||
* \param deviceButton The ID of the device button to be checked.
|
||||
* \return The user button ID the device button is mapped to or InvalidDeviceButtonId if the device button is not mapped.
|
||||
*/
|
||||
UserButtonId GetUserButtonId(DeviceId device, DeviceButtonId deviceButton) const;
|
||||
|
||||
/// Registers a listener to be notified when a button state changes.
|
||||
/**
|
||||
* If there are listeners registered, all input devices will have to record their state changes. This incurs extra runtime costs.
|
||||
*/
|
||||
ListenerId AddListener(MappedInputListener* listener);
|
||||
/// De-registers the given listener.
|
||||
void RemoveListener(ListenerId listenerId);
|
||||
/// Sorts the list of listeners which controls the order in which listeners are called.
|
||||
/**
|
||||
* The order of listeners may be important as the functions being called to notify a listener of a state change can control if
|
||||
* the state change will be passed to any consequent listeners. Call this function whenever listener priorites have changed. It
|
||||
* is automatically called by AddListener() and RemoveListener().
|
||||
*/
|
||||
void ReorderListeners();
|
||||
|
||||
private:
|
||||
InputManager& manager_;
|
||||
char* name_;
|
||||
unsigned id_;
|
||||
Allocator& allocator_;
|
||||
|
||||
typedef HashMap<UserButtonId, UserButton*> UserButtonMap;
|
||||
UserButtonMap userButtons_;
|
||||
UserButtonId nextUserButtonId_;
|
||||
|
||||
HashMap<ListenerId, MappedInputListener*> listeners_;
|
||||
Array<MappedInputListener*> sortedListeners_;
|
||||
unsigned nextListenerId_;
|
||||
InputListener* managerListener_;
|
||||
ListenerId managerListenerId_;
|
||||
|
||||
float GetFloatState(UserButtonId userButton, bool previous) const;
|
||||
|
||||
UserButton* GetUserButton(UserButtonId userButton);
|
||||
const UserButton* GetUserButton(UserButtonId userButton) const;
|
||||
|
||||
// Do not copy.
|
||||
InputMap(const InputMap &);
|
||||
InputMap& operator=(const InputMap &);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
60
lib/include/gainput/GainputInputState.h
Normal file
60
lib/include/gainput/GainputInputState.h
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
#ifndef GAINPUTINPUTSTATE_H_
|
||||
#define GAINPUTINPUTSTATE_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// State of an input device.
|
||||
class GAINPUT_LIBEXPORT InputState
|
||||
{
|
||||
public:
|
||||
/// Initializes the state.
|
||||
/**
|
||||
* \param allocator The allocator to be used for all memory allocations.
|
||||
* \param buttonCount The maximum number of device buttons.
|
||||
*/
|
||||
InputState(Allocator& allocator, unsigned int buttonCount);
|
||||
/// Unitializes the state.
|
||||
~InputState();
|
||||
|
||||
/// Returns the number of buttons in this state.
|
||||
/**
|
||||
* Note that not all buttons may be valid.
|
||||
*
|
||||
* \sa InputDevice::IsValidButtonId()
|
||||
*/
|
||||
unsigned GetButtonCount() const { return buttonCount_; }
|
||||
|
||||
/// Returns the bool state of the given device button.
|
||||
bool GetBool(DeviceButtonId buttonId) const { return buttons_[buttonId].b; }
|
||||
/// Sets the bool state of the given device button.
|
||||
void Set(DeviceButtonId buttonId, bool value) { buttons_[buttonId].b = value; }
|
||||
/// Returns the float state of the given device button.
|
||||
float GetFloat(DeviceButtonId buttonId) const { return buttons_[buttonId].f; }
|
||||
/// Sets the float state of the given device button.
|
||||
void Set(DeviceButtonId buttonId, float value) { buttons_[buttonId].f = value; }
|
||||
|
||||
/// Sets the states of all buttons in this input state to the states of all buttons in the given input state.
|
||||
InputState& operator=(const InputState& other);
|
||||
|
||||
private:
|
||||
Allocator& allocator_;
|
||||
unsigned int buttonCount_;
|
||||
|
||||
struct Button
|
||||
{
|
||||
union
|
||||
{
|
||||
bool b;
|
||||
float f;
|
||||
};
|
||||
};
|
||||
|
||||
Button* buttons_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
26
lib/include/gainput/GainputIos.h
Normal file
26
lib/include/gainput/GainputIos.h
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#ifndef GAINPUTIOS_H_
|
||||
#define GAINPUTIOS_H_
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
class InputManager;
|
||||
}
|
||||
|
||||
/// [IOS ONLY] UIKit view that captures touch inputs.
|
||||
/**
|
||||
* In order to enable touch input on iOS devices (i.e. make the InputDeviceTouch work),
|
||||
* an instance of this view has to be attached as a subview to the view of your application.
|
||||
* Note that, for touches to work in portrait and landscape mode, the subview has to be
|
||||
* rotated correctly with its parent.
|
||||
*/
|
||||
@interface GainputView : UIView
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame inputManager:(gainput::InputManager&)inputManager;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
39
lib/include/gainput/GainputLog.h
Normal file
39
lib/include/gainput/GainputLog.h
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
#ifndef GAINPUT_LOG_H_
|
||||
#define GAINPUT_LOG_H_
|
||||
|
||||
#include <gainput/gainput.h>
|
||||
|
||||
#if defined(GAINPUT_PLATFORM_LINUX)
|
||||
|
||||
#if defined(GAINPUT_DEBUG) || defined(GAINPUT_DEV)
|
||||
#include <stdio.h>
|
||||
#define GAINPUT_LOG(...) printf(__VA_ARGS__);
|
||||
#endif
|
||||
|
||||
#elif defined(GAINPUT_PLATFORM_WIN)
|
||||
|
||||
#if defined(GAINPUT_DEBUG) || defined(GAINPUT_DEV)
|
||||
#include <stdio.h>
|
||||
#include <Windows.h>
|
||||
#define GAINPUT_LOG(...) { char buf[1024]; sprintf(buf, __VA_ARGS__); OutputDebugStringA(buf); }
|
||||
#endif
|
||||
|
||||
#elif defined(GAINPUT_PLATFORM_ANDROID)
|
||||
|
||||
#if defined(GAINPUT_DEBUG) || defined(GAINPUT_DEV)
|
||||
#include <android/log.h>
|
||||
#define GAINPUT_LOG(...) ((void)__android_log_print(ANDROID_LOG_INFO, "gainput", __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#elif defined(GAINPUT_PLATFORM_IOS) || defined(GAINPUT_PLATFORM_MAC) || defined(GAINPUT_PLATFORM_TVOS)
|
||||
#include <stdio.h>
|
||||
#define GAINPUT_LOG(...) printf(__VA_ARGS__);
|
||||
#endif
|
||||
|
||||
#ifndef GAINPUT_LOG
|
||||
#define GAINPUT_LOG(...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
17
lib/include/gainput/GainputMapFilters.h
Normal file
17
lib/include/gainput/GainputMapFilters.h
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
#ifndef GAINPUTMAPFILTERS_H_
|
||||
#define GAINPUTMAPFILTERS_H_
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Inverts the given input value in the range [-1.0f, 1.0f].
|
||||
GAINPUT_LIBEXPORT float InvertSymmetricInput(float const value, void*);
|
||||
|
||||
/// Inverts the given input value in the range [0.0f, 1.0f].
|
||||
GAINPUT_LIBEXPORT float InvertInput(float const value, void*);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
193
lib/include/gainput/gainput.h
Normal file
193
lib/include/gainput/gainput.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* Gainput - C++ input library for games.
|
||||
*
|
||||
* Copyright (c) 2013-2017 Johannes Kuhlmann.
|
||||
* Licensed under the MIT license. See LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GAINPUT_H_
|
||||
#define GAINPUT_H_
|
||||
|
||||
#if defined(__ANDROID__) || defined(ANDROID)
|
||||
#define GAINPUT_PLATFORM_ANDROID
|
||||
#define GAINPUT_LIBEXPORT
|
||||
#elif defined(__linux) || defined(__linux__) || defined(linux) || defined(LINUX)
|
||||
#define GAINPUT_PLATFORM_LINUX
|
||||
#define GAINPUT_LIBEXPORT
|
||||
#elif defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER)
|
||||
#define GAINPUT_PLATFORM_WIN
|
||||
#if defined(GAINPUT_LIB_DYNAMIC)
|
||||
#define GAINPUT_LIBEXPORT __declspec(dllexport)
|
||||
#elif defined(GAINPUT_LIB_DYNAMIC_USE)
|
||||
#define GAINPUT_LIBEXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define GAINPUT_LIBEXPORT
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#define GAINPUT_LIBEXPORT
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_TV
|
||||
#define GAINPUT_PLATFORM_TVOS
|
||||
#elif TARGET_OS_IPHONE
|
||||
#define GAINPUT_PLATFORM_IOS
|
||||
#elif TARGET_OS_MAC
|
||||
#define GAINPUT_PLATFORM_MAC
|
||||
#else
|
||||
#error Gainput: Unknown/unsupported Apple platform!
|
||||
#endif
|
||||
#else
|
||||
#error Gainput: Unknown/unsupported platform!
|
||||
#endif
|
||||
|
||||
|
||||
//#define GAINPUT_DEBUG
|
||||
//#define GAINPUT_DEV
|
||||
#define GAINPUT_ENABLE_ALL_GESTURES
|
||||
#define GAINPUT_ENABLE_RECORDER
|
||||
#define GAINPUT_TEXT_INPUT_QUEUE_LENGTH 32
|
||||
|
||||
#ifdef GAINPUT_ENABLE_CONCURRENCY
|
||||
#define MOODYCAMEL_EXCEPTIONS_DISABLED
|
||||
#include "concurrentqueue.h"
|
||||
#define GAINPUT_CONC_QUEUE(TYPE) moodycamel::ConcurrentQueue<TYPE>
|
||||
#define GAINPUT_CONC_CONSTRUCT(queue) queue()
|
||||
#define GAINPUT_CONC_ENQUEUE(queue, obj) queue.enqueue(obj)
|
||||
#define GAINPUT_CONC_DEQUEUE(queue, obj) queue.try_dequeue(obj)
|
||||
#else
|
||||
#define GAINPUT_CONC_QUEUE(TYPE) gainput::Array<TYPE>
|
||||
#define GAINPUT_CONC_CONSTRUCT(queue) queue(allocator)
|
||||
#define GAINPUT_CONC_ENQUEUE(queue, obj) queue.push_back(obj)
|
||||
#define GAINPUT_CONC_DEQUEUE(queue, obj) (!queue.empty() ? (obj = queue[queue.size()-1], queue.pop_back(), true) : false)
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
#define GAINPUT_ASSERT assert
|
||||
#define GAINPUT_UNUSED(x) (void)(x)
|
||||
|
||||
#if defined(GAINPUT_PLATFORM_LINUX)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <stdint.h>
|
||||
|
||||
union _XEvent;
|
||||
typedef _XEvent XEvent;
|
||||
|
||||
#elif defined(GAINPUT_PLATFORM_WIN)
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
typedef struct tagMSG MSG;
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
}
|
||||
|
||||
#elif defined(GAINPUT_PLATFORM_ANDROID)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
struct AInputEvent;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// Contains all Gainput related classes, types, and functions.
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// ID of an input device.
|
||||
typedef unsigned int DeviceId;
|
||||
/// ID of a specific button unique to an input device.
|
||||
typedef unsigned int DeviceButtonId;
|
||||
|
||||
/// Describes a device button on a specific device.
|
||||
struct DeviceButtonSpec
|
||||
{
|
||||
/// ID of the input device.
|
||||
DeviceId deviceId;
|
||||
/// ID of the button on the given input device.
|
||||
DeviceButtonId buttonId;
|
||||
};
|
||||
|
||||
/// ID of a user-defined, mapped button.
|
||||
typedef unsigned int UserButtonId;
|
||||
/// ID of an input listener.
|
||||
typedef unsigned int ListenerId;
|
||||
/// ID of a device state modifier.
|
||||
typedef unsigned int ModifierId;
|
||||
|
||||
/// An invalid device ID.
|
||||
static const DeviceId InvalidDeviceId = -1;
|
||||
/// An invalid device button ID.
|
||||
static const DeviceButtonId InvalidDeviceButtonId = -1;
|
||||
/// An invalid user button ID.
|
||||
static const UserButtonId InvalidUserButtonId = -1;
|
||||
|
||||
/// Returns the name of the library, should be "Gainput".
|
||||
const char* GetLibName();
|
||||
/// Returns the version number of the library.
|
||||
uint32_t GetLibVersion();
|
||||
/// Returns the version number of the library as a printable string.
|
||||
const char* GetLibVersionString();
|
||||
|
||||
class InputDeltaState;
|
||||
class InputListener;
|
||||
class InputManager;
|
||||
class DebugRenderer;
|
||||
class DeviceStateModifier;
|
||||
|
||||
template <class T> T Abs(T a) { return a < T() ? -a : a; }
|
||||
|
||||
/// Switches the library's internal development server to HTTP mode.
|
||||
/**
|
||||
* When the server is in HTTP mode, it is possible to control touch
|
||||
* input using an external HTML page that connects to the library
|
||||
* via HTTP.
|
||||
*
|
||||
* The HTML page(s) can be found under `tools/html5client/` and should
|
||||
* be placed on an HTTP server that can be reached from the touch device
|
||||
* that should send touch events to the library. The touch device then
|
||||
* in turn connects to the library's internal HTTP server and periodically
|
||||
* sends touch input information.
|
||||
*
|
||||
* The pages can also be found hosted here:
|
||||
* http://gainput.johanneskuhlmann.de/html5client/
|
||||
*/
|
||||
void DevSetHttp(bool enable);
|
||||
}
|
||||
|
||||
#define GAINPUT_VER_MAJOR_SHIFT 16
|
||||
#define GAINPUT_VER_GET_MAJOR(ver) (ver >> GAINPUT_VER_MAJOR_SHIFT)
|
||||
#define GAINPUT_VER_GET_MINOR(ver) (ver & (uint32_t(-1) >> GAINPUT_VER_MAJOR_SHIFT))
|
||||
|
||||
|
||||
#include <gainput/GainputAllocator.h>
|
||||
#include <gainput/GainputContainers.h>
|
||||
#include <gainput/GainputInputState.h>
|
||||
#include <gainput/GainputInputDevice.h>
|
||||
#include <gainput/GainputInputListener.h>
|
||||
#include <gainput/GainputInputManager.h>
|
||||
#include <gainput/GainputInputMap.h>
|
||||
|
||||
#include <gainput/GainputInputDeviceMouse.h>
|
||||
#include <gainput/GainputInputDeviceKeyboard.h>
|
||||
#include <gainput/GainputInputDevicePad.h>
|
||||
#include <gainput/GainputInputDeviceTouch.h>
|
||||
#include <gainput/GainputInputDeviceBuiltIn.h>
|
||||
|
||||
#include <gainput/gestures/GainputGestures.h>
|
||||
|
||||
#include <gainput/recorder/GainputInputRecording.h>
|
||||
#include <gainput/recorder/GainputInputPlayer.h>
|
||||
#include <gainput/recorder/GainputInputRecorder.h>
|
||||
|
||||
#endif
|
||||
|
||||
47
lib/include/gainput/gestures/GainputButtonStickGesture.h
Normal file
47
lib/include/gainput/gestures/GainputButtonStickGesture.h
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
#ifndef GAINPUTBUTTONSTICKGESTURE_H_
|
||||
#define GAINPUTBUTTONSTICKGESTURE_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_BUTTON_STICK_GESTURE
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Buttons provided by the ButtonStickGesture.
|
||||
enum ButtonStickAction
|
||||
{
|
||||
ButtonStickAxis
|
||||
};
|
||||
|
||||
|
||||
class GAINPUT_LIBEXPORT ButtonStickGesture : public InputGesture
|
||||
{
|
||||
public:
|
||||
/// Initializes the gesture.
|
||||
ButtonStickGesture(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Uninitializes the gesture.
|
||||
~ButtonStickGesture();
|
||||
|
||||
/// Sets up the gesture for operation with the given axes and buttons.
|
||||
void Initialize(DeviceId negativeAxisDevice, DeviceButtonId negativeAxis,
|
||||
DeviceId positiveAxisDevice, DeviceButtonId positiveAxis);
|
||||
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton == ButtonStickAxis; }
|
||||
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const { GAINPUT_UNUSED(deviceButton); GAINPUT_ASSERT(IsValidButtonId(deviceButton)); return BT_FLOAT; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
private:
|
||||
DeviceButtonSpec negativeAxis_;
|
||||
DeviceButtonSpec positiveAxis_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
99
lib/include/gainput/gestures/GainputDoubleClickGesture.h
Normal file
99
lib/include/gainput/gestures/GainputDoubleClickGesture.h
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
#ifndef GAINPUTDOUBLECLICKGESTURE_H_
|
||||
#define GAINPUTDOUBLECLICKGESTURE_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_DOUBLE_CLICK_GESTURE
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Buttons provided by the DoubleClickGesture.
|
||||
enum DoubleClickAction
|
||||
{
|
||||
DoubleClickTriggered ///< The button triggered by double-clicking.
|
||||
};
|
||||
|
||||
/// A double-click gesture.
|
||||
/**
|
||||
* This gesture implements the classic double-click functionality. Its only device button ::DoubleClickTriggered is
|
||||
* true for one frame after the specified button has been active for a specified number of times in a given
|
||||
* time frame. It's also possible to disallow the pointer from travelling too far between and during clicks.
|
||||
*
|
||||
* After instantiating the gesture like any other input device, call one of the Initialize() functions to properly
|
||||
* set it up.
|
||||
*
|
||||
* In order for this gesture to be available, Gainput must be built with \c GAINPUT_ENABLE_ALL_GESTURES or
|
||||
* \c GAINPUT_ENABLE_DOUBLE_CLICK_GESTURE defined.
|
||||
*
|
||||
* \sa Initialize
|
||||
* \sa SetClicksTargetCount
|
||||
* \sa InputManager::CreateDevice
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT DoubleClickGesture : public InputGesture
|
||||
{
|
||||
public:
|
||||
/// Initializes the gesture.
|
||||
DoubleClickGesture(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Uninitializes the gesture.
|
||||
~DoubleClickGesture();
|
||||
|
||||
/// Sets up the gesture for operation without position checking.
|
||||
/**
|
||||
* \param actionButtonDevice ID of the input device containing the action button.
|
||||
* \param actionButton ID of the device button to be used as the action button.
|
||||
* \param timeSpan Allowed time between clicks in milliseconds.
|
||||
*/
|
||||
void Initialize(DeviceId actionButtonDevice, DeviceButtonId actionButton, uint64_t timeSpan = 300);
|
||||
/// Sets up the gesture for operation with position checking, i.e. the user may not move the mouse too far between clicks.
|
||||
/**
|
||||
* \param actionButtonDevice ID of the input device containing the action button.
|
||||
* \param actionButton ID of the device button to be used as the action button.
|
||||
* \param xAxisDevice ID of the input device containing the X coordinate of the pointer.
|
||||
* \param xAxis ID of the device button/axis to be used for the X coordinate of the pointer.
|
||||
* \param xTolerance The amount the pointer may travel in the X coordinate to still be valid.
|
||||
* \param yAxisDevice ID of the input device containing the Y coordinate of the pointer.
|
||||
* \param yAxis ID of the device button/axis to be used for the Y coordinate of the pointer.
|
||||
* \param yTolerance The amount the pointer may travel in the Y coordinate to still be valid.
|
||||
* \param timeSpan Allowed time between clicks in milliseconds.
|
||||
*/
|
||||
void Initialize(DeviceId actionButtonDevice, DeviceButtonId actionButton,
|
||||
DeviceId xAxisDevice, DeviceButtonId xAxis, float xTolerance,
|
||||
DeviceId yAxisDevice, DeviceButtonId yAxis, float yTolerance,
|
||||
uint64_t timeSpan = 300);
|
||||
|
||||
/// Sets the number of clicks to trigger an action.
|
||||
/**
|
||||
* \param count The number of clicks that will trigger this gesture; the default is 2, i.e. double-click.
|
||||
*/
|
||||
void SetClicksTargetCount(unsigned count) { clicksTargetCount_ = count; }
|
||||
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton == DoubleClickTriggered; }
|
||||
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const { GAINPUT_UNUSED(deviceButton); GAINPUT_ASSERT(IsValidButtonId(deviceButton)); return BT_BOOL; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
private:
|
||||
DeviceButtonSpec actionButton_;
|
||||
DeviceButtonSpec xAxis_;
|
||||
float xTolerance_;
|
||||
DeviceButtonSpec yAxis_;
|
||||
float yTolerance_;
|
||||
|
||||
uint64_t timeSpan_;
|
||||
uint64_t firstClickTime_;
|
||||
|
||||
float firstClickX_;
|
||||
float firstClickY_;
|
||||
|
||||
unsigned clicksRegistered_;
|
||||
unsigned clicksTargetCount_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
69
lib/include/gainput/gestures/GainputGestures.h
Normal file
69
lib/include/gainput/gestures/GainputGestures.h
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
#ifndef GAINPUTGESTURES_H_
|
||||
#define GAINPUTGESTURES_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_ALL_GESTURES
|
||||
#define GAINPUT_ENABLE_BUTTON_STICK_GESTURE
|
||||
#define GAINPUT_ENABLE_DOUBLE_CLICK_GESTURE
|
||||
#define GAINPUT_ENABLE_HOLD_GESTURE
|
||||
#define GAINPUT_ENABLE_PINCH_GESTURE
|
||||
#define GAINPUT_ENABLE_ROTATE_GESTURE
|
||||
#define GAINPUT_ENABLE_SIMULTANEOUSLY_DOWN_GESTURE
|
||||
#define GAINPUT_ENABLE_TAP_GESTURE
|
||||
#endif
|
||||
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Base class for all input gestures.
|
||||
/**
|
||||
* Input gestures are a way to process basic input data into more complex input data. For example,
|
||||
* multiple buttons may be interpreted over time to form a new button. A very simple gesture would the
|
||||
* ubiquitous double-click.
|
||||
*
|
||||
* Mainly for consistency and convenience reasons, all gestures should derive from this class though it's not
|
||||
* strictly necessary (deriving from InputDevice would suffice).
|
||||
*
|
||||
* Input gestures are basically just input devices that don't get their data from some hardware device
|
||||
* but from other input devices instead. Therefore gestures must also be created by calling
|
||||
* InputManager::CreateDevice() or InputManager::CreateAndGetDevice(). Most gestures require further
|
||||
* initialization which is done by calling one of their \c Initialize() member functions. After that,
|
||||
* they should be good to go and their buttons can be used like any other input device button, i.e.
|
||||
* they can be mapped to some user button.
|
||||
*
|
||||
* Gestures can be excluded from compilation if they are not required. In order to include all gestures
|
||||
* \c GAINPUT_ENABLE_ALL_GESTURES should be defined in \c gainput.h . This define must be present when
|
||||
* the library is built, otherwise the actual functionality won't be present. Similarly, there is one
|
||||
* define for each gesture. The names of these are documented in the descriptions of the
|
||||
* individual gesture classes. If no such define is defined, no gesture will be included.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputGesture : public InputDevice
|
||||
{
|
||||
public:
|
||||
/// Returns DT_GESTURE.
|
||||
DeviceType GetType() const { return DT_GESTURE; }
|
||||
const char* GetTypeName() const { return "gesture"; }
|
||||
bool IsLateUpdate() const { return true; }
|
||||
|
||||
protected:
|
||||
/// Gesture base constructor.
|
||||
InputGesture(InputManager& manager, DeviceId device, unsigned index) : InputDevice(manager, device, index == InputDevice::AutoIndex ? manager.GetDeviceCountByType(DT_GESTURE) : 0) { }
|
||||
|
||||
DeviceState InternalGetState() const { return DS_OK; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include <gainput/gestures/GainputButtonStickGesture.h>
|
||||
#include <gainput/gestures/GainputDoubleClickGesture.h>
|
||||
#include <gainput/gestures/GainputHoldGesture.h>
|
||||
#include <gainput/gestures/GainputPinchGesture.h>
|
||||
#include <gainput/gestures/GainputRotateGesture.h>
|
||||
#include <gainput/gestures/GainputSimultaneouslyDownGesture.h>
|
||||
#include <gainput/gestures/GainputTapGesture.h>
|
||||
|
||||
#endif
|
||||
|
||||
94
lib/include/gainput/gestures/GainputHoldGesture.h
Normal file
94
lib/include/gainput/gestures/GainputHoldGesture.h
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
#ifndef GAINPUTHOLDGESTURE_H_
|
||||
#define GAINPUTHOLDGESTURE_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_HOLD_GESTURE
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Buttons provided by the HoldGesture.
|
||||
enum HoldAction
|
||||
{
|
||||
HoldTriggered ///< The button that triggers after holding for the given time.
|
||||
};
|
||||
|
||||
/// A hold-to-trigger gesture.
|
||||
/**
|
||||
* This gesture, mainly meant for touch devices, triggers after the specified button has been down for at least
|
||||
* the specified amount of time. Its button ::HoldTriggered is then either active for one frame or as long as
|
||||
* the source button is down.
|
||||
*
|
||||
* After instantiating the gesture like any other input device, call one of the Initialize() functions to properly
|
||||
* set it up.
|
||||
*
|
||||
* In order for this gesture to be available, Gainput must be built with \c GAINPUT_ENABLE_ALL_GESTURES or
|
||||
* \c GAINPUT_ENABLE_HOLD_GESTURE defined.
|
||||
*
|
||||
* \sa Initialize
|
||||
* \sa InputManager::CreateDevice
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT HoldGesture : public InputGesture
|
||||
{
|
||||
public:
|
||||
/// Initializes the gesture.
|
||||
HoldGesture(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Uninitializes the gesture.
|
||||
~HoldGesture();
|
||||
|
||||
/// Sets up the gesture for operation without position checking.
|
||||
/**
|
||||
* \param actionButtonDevice ID of the input device containing the action button.
|
||||
* \param actionButton ID of the device button to be used as the action button.
|
||||
* \param oneShot Specifies if the gesture triggers only once after the given time or if it triggers as long as the source button is down.
|
||||
* \param timeSpan Time in milliseconds the user needs to hold in order to trigger the gesture.
|
||||
*/
|
||||
void Initialize(DeviceId actionButtonDevice, DeviceButtonId actionButton, bool oneShot = true, uint64_t timeSpan = 800);
|
||||
/// Sets up the gesture for operation with position checking, i.e. the user may not move the mouse too far while holding.
|
||||
/**
|
||||
* \param actionButtonDevice ID of the input device containing the action button.
|
||||
* \param actionButton ID of the device button to be used as the action button.
|
||||
* \param xAxisDevice ID of the input device containing the X coordinate of the pointer.
|
||||
* \param xAxis ID of the device button/axis to be used for the X coordinate of the pointer.
|
||||
* \param xTolerance The amount the pointer may travel in the X coordinate to still be valid.
|
||||
* \param yAxisDevice ID of the input device containing the Y coordinate of the pointer.
|
||||
* \param yAxis ID of the device button/axis to be used for the Y coordinate of the pointer.
|
||||
* \param yTolerance The amount the pointer may travel in the Y coordinate to still be valid.
|
||||
* \param oneShot Specifies if the gesture triggers only once after the given time or if it triggers as long as the source button is down.
|
||||
* \param timeSpan Time in milliseconds the user needs to hold in order to trigger the gesture.
|
||||
*/
|
||||
void Initialize(DeviceId actionButtonDevice, DeviceButtonId actionButton,
|
||||
DeviceId xAxisDevice, DeviceButtonId xAxis, float xTolerance,
|
||||
DeviceId yAxisDevice, DeviceButtonId yAxis, float yTolerance,
|
||||
bool oneShot = true,
|
||||
uint64_t timeSpan = 800);
|
||||
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton == HoldTriggered; }
|
||||
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const { GAINPUT_UNUSED(deviceButton); GAINPUT_ASSERT(IsValidButtonId(deviceButton)); return BT_BOOL; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
private:
|
||||
DeviceButtonSpec actionButton_;
|
||||
DeviceButtonSpec xAxis_;
|
||||
float xTolerance_;
|
||||
DeviceButtonSpec yAxis_;
|
||||
float yTolerance_;
|
||||
|
||||
bool oneShot_;
|
||||
bool oneShotReset_;
|
||||
uint64_t timeSpan_;
|
||||
uint64_t firstDownTime_;
|
||||
|
||||
float firstDownX_;
|
||||
float firstDownY_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
86
lib/include/gainput/gestures/GainputPinchGesture.h
Normal file
86
lib/include/gainput/gestures/GainputPinchGesture.h
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
#ifndef GAINPUTPINCHGESTURE_H_
|
||||
#define GAINPUTPINCHGESTURE_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_PINCH_GESTURE
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Buttons provided by the PinchGesture.
|
||||
enum PinchAction
|
||||
{
|
||||
PinchTriggered, ///< The button that triggers when both pinch buttons are down.
|
||||
PinchScale ///< The current pinch scale value if pinching is active.
|
||||
};
|
||||
|
||||
/// A multi-touch pinch-to-scale gesture.
|
||||
/**
|
||||
* This gesture, mainly meant for multi-touch devices, triggers (::PinchTriggered is down) when both specified
|
||||
* source buttons are down. It will then determine the distance between the two 2D touch points and report
|
||||
* any change in distance as a factor of the initial distance using ::PinchScale.
|
||||
*
|
||||
* After instantiating the gesture like any other input device, call Initialize() to properly
|
||||
* set it up.
|
||||
*
|
||||
* In order for this gesture to be available, Gainput must be built with \c GAINPUT_ENABLE_ALL_GESTURES or
|
||||
* \c GAINPUT_ENABLE_PINCH_GESTURE defined.
|
||||
*
|
||||
* \sa Initialize
|
||||
* \sa InputManager::CreateDevice
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT PinchGesture : public InputGesture
|
||||
{
|
||||
public:
|
||||
/// Initializes the gesture.
|
||||
PinchGesture(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Uninitializes the gesture.
|
||||
~PinchGesture();
|
||||
|
||||
/// Sets up the gesture for operation with the given axes and buttons.
|
||||
/**
|
||||
* \param downDevice ID of the input device containing the first touch button.
|
||||
* \param downButton ID of the device button to be used as the first touch button.
|
||||
* \param xAxisDevice ID of the input device containing the X coordinate of the first touch point.
|
||||
* \param xAxis ID of the device button/axis to be used for the X coordinate of the first touch point.
|
||||
* \param yAxisDevice ID of the input device containing the Y coordinate of the first touch point.
|
||||
* \param yAxis ID of the device button/axis to be used for the Y coordinate of the first touch point.
|
||||
* \param down2Device ID of the input device containing the second touch button.
|
||||
* \param downButton2 ID of the device button to be used as the second touch button.
|
||||
* \param xAxis2Device ID of the input device containing the X coordinate of the second touch point.
|
||||
* \param xAxis2 ID of the device button/axis to be used for the X coordinate of the second touch point.
|
||||
* \param yAxis2Device ID of the input device containing the Y coordinate of the second touch point.
|
||||
* \param yAxis2 ID of the device button/axis to be used for the Y coordinate of the second touch point.
|
||||
*/
|
||||
void Initialize(DeviceId downDevice, DeviceButtonId downButton,
|
||||
DeviceId xAxisDevice, DeviceButtonId xAxis,
|
||||
DeviceId yAxisDevice, DeviceButtonId yAxis,
|
||||
DeviceId down2Device, DeviceButtonId downButton2,
|
||||
DeviceId xAxis2Device, DeviceButtonId xAxis2,
|
||||
DeviceId yAxis2Device, DeviceButtonId yAxis2);
|
||||
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton == PinchTriggered || deviceButton == PinchScale; }
|
||||
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const { GAINPUT_ASSERT(IsValidButtonId(deviceButton)); return deviceButton == PinchTriggered ? BT_BOOL : BT_FLOAT; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
private:
|
||||
DeviceButtonSpec downButton_;
|
||||
DeviceButtonSpec xAxis_;
|
||||
DeviceButtonSpec yAxis_;
|
||||
DeviceButtonSpec downButton2_;
|
||||
DeviceButtonSpec xAxis2_;
|
||||
DeviceButtonSpec yAxis2_;
|
||||
|
||||
bool pinching_;
|
||||
float initialDistance_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
87
lib/include/gainput/gestures/GainputRotateGesture.h
Normal file
87
lib/include/gainput/gestures/GainputRotateGesture.h
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
#ifndef GAINPUTROTATEGESTURE_H_
|
||||
#define GAINPUTROTATEGESTURE_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_ROTATE_GESTURE
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Buttons provided by the RotateGesture.
|
||||
enum RotateAction
|
||||
{
|
||||
RotateTriggered, ///< The button that triggers when both rotate buttons are down.
|
||||
RotateAngle ///< The current rotation angle in radians if rotation is triggered (::RotateTriggered).
|
||||
};
|
||||
|
||||
/// A multi-touch rotate gesture.
|
||||
/**
|
||||
* This gesture, mainly meant for multi-touch devices, triggers (::RotateTriggered is down) when both specified
|
||||
* source buttons are down. It then determines the angle between the two specified 2D touch points and reports any
|
||||
* change in angle using ::RotateAngle. The initial angle between the two points is defined as no rotation.
|
||||
*
|
||||
* After instantiating the gesture like any other input device, call Initialize() to properly
|
||||
* set it up.
|
||||
*
|
||||
* In order for this gesture to be available, Gainput must be built with \c GAINPUT_ENABLE_ALL_GESTURES or
|
||||
* \c GAINPUT_ENABLE_ROTATE_GESTURE defined.
|
||||
*
|
||||
* \sa Initialize
|
||||
* \sa InputManager::CreateDevice
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT RotateGesture : public InputGesture
|
||||
{
|
||||
public:
|
||||
/// Initializes the gesture.
|
||||
RotateGesture(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Uninitializes the gesture.
|
||||
~RotateGesture();
|
||||
|
||||
/// Sets up the gesture for operation with the given axes and buttons.
|
||||
/**
|
||||
* \param downDevice ID of the input device containing the first touch button.
|
||||
* \param downButton ID of the device button to be used as the first touch button.
|
||||
* \param xAxisDevice ID of the input device containing the X coordinate of the first touch point.
|
||||
* \param xAxis ID of the device button/axis to be used for the X coordinate of the first touch point.
|
||||
* \param yAxisDevice ID of the input device containing the Y coordinate of the first touch point.
|
||||
* \param yAxis ID of the device button/axis to be used for the Y coordinate of the first touch point.
|
||||
* \param down2Device ID of the input device containing the second touch button.
|
||||
* \param downButton2 ID of the device button to be used as the second touch button.
|
||||
* \param xAxis2Device ID of the input device containing the X coordinate of the second touch point.
|
||||
* \param xAxis2 ID of the device button/axis to be used for the X coordinate of the second touch point.
|
||||
* \param yAxis2Device ID of the input device containing the Y coordinate of the second touch point.
|
||||
* \param yAxis2 ID of the device button/axis to be used for the Y coordinate of the second touch point.
|
||||
*/
|
||||
void Initialize(DeviceId downDevice, DeviceButtonId downButton,
|
||||
DeviceId xAxisDevice, DeviceButtonId xAxis,
|
||||
DeviceId yAxisDevice, DeviceButtonId yAxis,
|
||||
DeviceId down2Device, DeviceButtonId downButton2,
|
||||
DeviceId xAxis2Device, DeviceButtonId xAxis2,
|
||||
DeviceId yAxis2Device, DeviceButtonId yAxis2);
|
||||
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton == RotateTriggered || deviceButton == RotateAngle; }
|
||||
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const { GAINPUT_ASSERT(IsValidButtonId(deviceButton)); return deviceButton == RotateTriggered ? BT_BOOL : BT_FLOAT; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
private:
|
||||
DeviceButtonSpec downButton_;
|
||||
DeviceButtonSpec xAxis_;
|
||||
DeviceButtonSpec yAxis_;
|
||||
DeviceButtonSpec downButton2_;
|
||||
DeviceButtonSpec xAxis2_;
|
||||
DeviceButtonSpec yAxis2_;
|
||||
|
||||
bool rotating_;
|
||||
float initialAngle_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
#ifndef GAINPUTSIMULTANEOUSLYDOWNGESTURE_H_
|
||||
#define GAINPUTSIMULTANEOUSLYDOWNGESTURE_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_SIMULTANEOUSLY_DOWN_GESTURE
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Buttons provided by the SimultaneouslyDownGesture.
|
||||
enum SimultaneouslyDownAction
|
||||
{
|
||||
SimultaneouslyDownTriggered ///< The button triggered by double-clicking.
|
||||
};
|
||||
|
||||
/// A gesture that tracks if a number of buttons is down simultaneously.
|
||||
/**
|
||||
* This gesture can be used to detect if multiple buttons are down at the same time. Its only
|
||||
* device button ::SimultaneouslyDownTriggered is true while all buttons provided through AddButton()
|
||||
* are down.
|
||||
*
|
||||
* After instantiating the gesture like any other input device, call AddButton() as often as necessary
|
||||
* to properly set it up.
|
||||
*
|
||||
* In order for this gesture to be available, Gainput must be built with \c GAINPUT_ENABLE_ALL_GESTURES or
|
||||
* \c GAINPUT_ENABLE_SIMULTANEOUSLY_DOWN_GESTURE defined.
|
||||
*
|
||||
* \sa AddButton
|
||||
* \sa InputManager::CreateDevice
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT SimultaneouslyDownGesture : public InputGesture
|
||||
{
|
||||
public:
|
||||
/// Initializes the gesture.
|
||||
SimultaneouslyDownGesture(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Uninitializes the gesture.
|
||||
~SimultaneouslyDownGesture();
|
||||
|
||||
/// Adds the given button as a button to check.
|
||||
/**
|
||||
* \param device ID of the input device containing the button to be checked.
|
||||
* \param button ID of the device button to be checked.
|
||||
*/
|
||||
void AddButton(DeviceId device, DeviceButtonId button);
|
||||
|
||||
/// Removes all buttons previously registered through AddButton().
|
||||
void ClearButtons();
|
||||
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton == SimultaneouslyDownTriggered; }
|
||||
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const { GAINPUT_UNUSED(deviceButton); GAINPUT_ASSERT(IsValidButtonId(deviceButton)); return BT_BOOL; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
private:
|
||||
Array<DeviceButtonSpec> buttons_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
66
lib/include/gainput/gestures/GainputTapGesture.h
Normal file
66
lib/include/gainput/gestures/GainputTapGesture.h
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
#ifndef GAINPUTTAPGESTURE_H_
|
||||
#define GAINPUTTAPGESTURE_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_TAP_GESTURE
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Buttons provided by the TapGesture.
|
||||
enum TapAction
|
||||
{
|
||||
TapTriggered ///< The button that is triggered by tapping.
|
||||
};
|
||||
|
||||
/// A tap-to-trigger gesture.
|
||||
/**
|
||||
* This gesture, mainly meant for touch devices, triggers after the specified button has been down and released
|
||||
* during the specified time frame. If the button is down for a longer time, no action is triggered.
|
||||
*
|
||||
* After instantiating the gesture like any other input device, call Initialize() to properly
|
||||
* set it up.
|
||||
*
|
||||
* In order for this gesture to be available, Gainput must be built with \c GAINPUT_ENABLE_ALL_GESTURES or
|
||||
* \c GAINPUT_ENABLE_TAP_GESTURE defined.
|
||||
*
|
||||
* \sa Initialize
|
||||
* \sa InputManager::CreateDevice
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT TapGesture : public InputGesture
|
||||
{
|
||||
public:
|
||||
/// Initializes the gesture.
|
||||
TapGesture(InputManager& manager, DeviceId device, unsigned index, DeviceVariant variant);
|
||||
/// Uninitializes the gesture.
|
||||
~TapGesture();
|
||||
|
||||
/// Sets up the gesture.
|
||||
/**
|
||||
* \param actionButtonDevice ID of the input device containing the action button.
|
||||
* \param actionButton ID of the device button to be used as the action button.
|
||||
* \param timeSpan Time in milliseconds the user may hold at most.
|
||||
*/
|
||||
void Initialize(DeviceId actionButtonDevice, DeviceButtonId actionButton, uint64_t timeSpan = 500);
|
||||
|
||||
bool IsValidButtonId(DeviceButtonId deviceButton) const { return deviceButton == TapTriggered; }
|
||||
|
||||
ButtonType GetButtonType(DeviceButtonId deviceButton) const { GAINPUT_UNUSED(deviceButton); GAINPUT_ASSERT(IsValidButtonId(deviceButton)); return BT_BOOL; }
|
||||
|
||||
protected:
|
||||
void InternalUpdate(InputDeltaState* delta);
|
||||
|
||||
private:
|
||||
DeviceButtonSpec actionButton_;
|
||||
|
||||
uint64_t timeSpan_;
|
||||
uint64_t firstDownTime_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
65
lib/include/gainput/recorder/GainputInputPlayer.h
Normal file
65
lib/include/gainput/recorder/GainputInputPlayer.h
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
#ifndef GAINPUTINPUTPLAYER_H_
|
||||
#define GAINPUTINPUTPLAYER_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_RECORDER
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Plays back a previously recorded sequence of device state changes.
|
||||
/**
|
||||
* In order for input recording to be available, Gainput must have been built with
|
||||
* \c GAINPUT_ENABLE_RECORDER defined.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputPlayer : public DeviceStateModifier
|
||||
{
|
||||
public:
|
||||
/// Initializes the player.
|
||||
/**
|
||||
* \param manager The manager to receive the device state changes.
|
||||
* \param recording The recording to play, may be 0.
|
||||
*/
|
||||
InputPlayer(InputManager& manager, InputRecording* recording = 0);
|
||||
/// Destructs the player.
|
||||
~InputPlayer();
|
||||
|
||||
/// Updates the player, called internally from InputManager::Update().
|
||||
void Update(InputDeltaState* delta);
|
||||
|
||||
/// Starts the playback.
|
||||
/**
|
||||
* A recording must have been provided before doing this, either through the
|
||||
* constructor or SetRecording().
|
||||
*/
|
||||
void Start();
|
||||
/// Stops the Playback.
|
||||
void Stop();
|
||||
/// Returns if the player is currently playing.
|
||||
bool IsPlaying() const { return isPlaying_; }
|
||||
|
||||
/// Sets the recording to play.
|
||||
void SetRecording(InputRecording* recording);
|
||||
/// Returns the currently set recording.
|
||||
InputRecording* GetRecording() { return recording_; }
|
||||
/// Returns the currently set recording.
|
||||
const InputRecording* GetRecording() const { return recording_; }
|
||||
|
||||
private:
|
||||
InputManager& manager_;
|
||||
|
||||
bool isPlaying_;
|
||||
InputRecording* recording_;
|
||||
uint64_t startTime_;
|
||||
|
||||
Array<DeviceId> devicesToReset_;
|
||||
|
||||
ModifierId playingModifierId_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
73
lib/include/gainput/recorder/GainputInputRecorder.h
Normal file
73
lib/include/gainput/recorder/GainputInputRecorder.h
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
#ifndef GAINPUTINPUTRECORDER_H_
|
||||
#define GAINPUTINPUTRECORDER_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_RECORDER
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// Records a sequence of button state changes.
|
||||
/**
|
||||
* In order for input recording to be available, Gainput must have been built with
|
||||
* \c GAINPUT_ENABLE_RECORDER defined.
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputRecorder
|
||||
{
|
||||
public:
|
||||
/// Initializes the recorder.
|
||||
/**
|
||||
* \param manager The InputManager to receive button state changes from.
|
||||
*/
|
||||
InputRecorder(InputManager& manager);
|
||||
/// Destructs the recorder.
|
||||
~InputRecorder();
|
||||
|
||||
/// Starts recording.
|
||||
/**
|
||||
* Also clears the InputRecording that is being recorded to so that it's not possible
|
||||
* to resume recording after stopping to record.
|
||||
*/
|
||||
void Start();
|
||||
/// Stops recording.
|
||||
void Stop();
|
||||
/// Returns if the recorder is currently recording.
|
||||
bool IsRecording() const { return isRecording_; }
|
||||
|
||||
/// Adds a device to record the button state changes of.
|
||||
/**
|
||||
* If no device is set, all devices are recorded.
|
||||
* \param device The ID of the device to record.
|
||||
*/
|
||||
void AddDeviceToRecord(DeviceId device) { recordedDevices_[device] = true; }
|
||||
/// Returns if the given device should be recorded.
|
||||
/**
|
||||
* \param device The ID of the device to check.
|
||||
*/
|
||||
bool IsDeviceToRecord(DeviceId device) { return recordedDevices_.empty() || recordedDevices_.count(device) > 0; }
|
||||
|
||||
/// Returns the recording that is being recorded to, may be 0.
|
||||
InputRecording* GetRecording() { return recording_; }
|
||||
/// Returns the recording that is being recorded to, may be 0.
|
||||
const InputRecording* GetRecording() const { return recording_; }
|
||||
/// Returns the time the recording was started.
|
||||
uint64_t GetStartTime() const { return startTime_; }
|
||||
|
||||
private:
|
||||
InputManager& manager_;
|
||||
|
||||
bool isRecording_;
|
||||
InputListener* recordingListener_;
|
||||
ListenerId recordingListenerId_;
|
||||
InputRecording* recording_;
|
||||
uint64_t startTime_;
|
||||
HashMap<DeviceId, bool> recordedDevices_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
125
lib/include/gainput/recorder/GainputInputRecording.h
Normal file
125
lib/include/gainput/recorder/GainputInputRecording.h
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
#ifndef GAINPUTINPUTRECORDING_H_
|
||||
#define GAINPUTINPUTRECORDING_H_
|
||||
|
||||
#ifdef GAINPUT_ENABLE_RECORDER
|
||||
|
||||
namespace gainput
|
||||
{
|
||||
|
||||
/// A single recorded change for a device button.
|
||||
struct GAINPUT_LIBEXPORT RecordedDeviceButtonChange
|
||||
{
|
||||
/// The time at which the change occurred.
|
||||
uint64_t time;
|
||||
/// The ID of the device owning the button that changed.
|
||||
DeviceId deviceId;
|
||||
/// The ID of the button that changed.
|
||||
DeviceButtonId buttonId;
|
||||
|
||||
union
|
||||
{
|
||||
/// If the button's type is ::BT_BOOL, this contains the new value.
|
||||
bool b;
|
||||
/// If the button's type is ::BT_FLOAT, this contains the new value.
|
||||
float f;
|
||||
};
|
||||
};
|
||||
|
||||
/// A recorded sequence of input changes.
|
||||
/**
|
||||
* The recording can be recorded to, played, or serialized/deserialized.
|
||||
*
|
||||
* In order for input recording to be available, Gainput must have been built with
|
||||
* \c GAINPUT_ENABLE_RECORDER defined.
|
||||
*
|
||||
* \sa InputPlayer
|
||||
* \sa InputRecorder
|
||||
*/
|
||||
class GAINPUT_LIBEXPORT InputRecording
|
||||
{
|
||||
public:
|
||||
/// Initializes the recording in an empty state.
|
||||
/**
|
||||
* \param allocator The allocator to be used for all memory allocations.
|
||||
*/
|
||||
InputRecording(Allocator& allocator = GetDefaultAllocator());
|
||||
/// Initializes the recording from the given serialized data.
|
||||
/**
|
||||
* The recording is reconstructed from a previously serialized recording obtained through
|
||||
* GetSerialized().
|
||||
*
|
||||
* \param manager Used to resolve device and button references in the recording.
|
||||
* \param data The serialized recording as obtained from GetSerialized().
|
||||
* \param size The length of the serialized recording as obtained from GetSerializedSize().
|
||||
* \param allocator The allocator to be used for all memory allocations.
|
||||
*/
|
||||
InputRecording(InputManager& manager, void* data, size_t size, Allocator& allocator = GetDefaultAllocator());
|
||||
|
||||
/// Appends a device button change to the recording.
|
||||
/**
|
||||
* The changes must be added in chronological order, i.e. time must always greater or equal to the time
|
||||
* AddChange() was last called with.
|
||||
*
|
||||
* \param time The time elapsed before the change occurred.
|
||||
* \param deviceId The ID of the device owning the button that changed.
|
||||
* \param buttonId The ID of the button that changed.
|
||||
* \param value The new value of the button.
|
||||
*/
|
||||
void AddChange(uint64_t time, DeviceId deviceId, DeviceButtonId buttonId, bool value);
|
||||
/// Appends a device button change to the recording.
|
||||
/**
|
||||
* The changes must be added in chronological order, i.e. time must always greater or equal to the time
|
||||
* AddChange() was last called with.
|
||||
*
|
||||
* \param time The time elapsed before the change occurred.
|
||||
* \param deviceId The ID of the device owning the button that changed.
|
||||
* \param buttonId The ID of the button that changed.
|
||||
* \param value The new value of the button.
|
||||
*/
|
||||
void AddChange(uint64_t time, DeviceId deviceId, DeviceButtonId buttonId, float value);
|
||||
|
||||
/// Removes all state changes.
|
||||
void Clear();
|
||||
|
||||
/// Gets the next button change before and including the given time and returns it.
|
||||
/**
|
||||
* \param time The time up to which to return changes.
|
||||
* \param[out] outChange The change properties will be written to this if this function returns true.
|
||||
* \return true if a change matching the given time was found, false otherwise.
|
||||
*/
|
||||
bool GetNextChange(uint64_t time, RecordedDeviceButtonChange& outChange);
|
||||
/// Resets the playback position.
|
||||
/**
|
||||
* After calling this function, GetNextChange() will return changes from the beginning of the recorded
|
||||
* sequence of changes again.
|
||||
*/
|
||||
void Reset() { position_ = 0; }
|
||||
|
||||
/// Returns what time frame this recording spans.
|
||||
uint64_t GetDuration() const;
|
||||
|
||||
/// Returns the size required to serialize this recording.
|
||||
size_t GetSerializedSize() const;
|
||||
/// Serializes this recording to the given buffer.
|
||||
/**
|
||||
* This function serializes this recording so that it can be saved and read back in and deserialized later.
|
||||
*
|
||||
* \param manager Used to resolve device and button references in the recording.
|
||||
* \param data A buffer of (at least) a size as returned by GetSerializedSize().
|
||||
*/
|
||||
void GetSerialized(InputManager& manager, void* data) const;
|
||||
|
||||
private:
|
||||
Array<RecordedDeviceButtonChange> changes_;
|
||||
|
||||
/// The position in changes_ for reading.
|
||||
unsigned position_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user