88 lines
2.0 KiB
C++
88 lines
2.0 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "GestureTap.hpp"
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
namespace OpenVulkano::Input
|
|
{
|
|
namespace
|
|
{
|
|
constexpr auto MAX_DURATION = 1s;
|
|
constexpr float MAX_DISTANCE = 12.0f;
|
|
constexpr float MAX_DISTANCE2 = MAX_DISTANCE * MAX_DISTANCE;
|
|
}
|
|
|
|
int GestureTap::GetTouchCount() const
|
|
{
|
|
return std::count_if(m_touchMap.begin(), m_touchMap.end(), [](const std::pair<TouchId, bool>& t) { return t.second; });
|
|
}
|
|
|
|
void GestureTap::Cancel()
|
|
{
|
|
SetActive(false);
|
|
m_tapInfo.position = {};
|
|
}
|
|
|
|
void GestureTap::Reset()
|
|
{
|
|
Cancel();
|
|
m_touchMap.clear();
|
|
m_startTime = {};
|
|
}
|
|
|
|
void GestureTap::TouchMoved(const Touch& touch)
|
|
{
|
|
if (IsActive())
|
|
{
|
|
if ((std::chrono::steady_clock::now() - m_startTime > MAX_DURATION) ||
|
|
(Math::Utils::distance2(touch.GetPosition(), m_initialPoint) > MAX_DISTANCE2) ||
|
|
((m_distance += Math::Utils::distance2(touch.GetPosition(), touch.GetLastPosition()) > 3 * MAX_DISTANCE2)))
|
|
{
|
|
Cancel();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_tapInfo.position = touch.GetPosition();
|
|
}
|
|
}
|
|
|
|
void GestureTap::TouchDown(const Touch& touch)
|
|
{
|
|
m_touchMap[touch.GetId()] = true;
|
|
if (1 == m_touchMap.size()) // single tap only
|
|
{
|
|
m_startTime = std::chrono::steady_clock::now();
|
|
m_initialPoint = touch.GetPosition();
|
|
m_distance = 0.0f;
|
|
m_tapInfo.position = m_initialPoint;
|
|
SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
Cancel();
|
|
}
|
|
}
|
|
|
|
void GestureTap::TouchUp(const Touch& touch)
|
|
{
|
|
m_touchMap[touch.GetId()] = false;
|
|
if (IsActive())
|
|
{
|
|
m_tapInfo.duration = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - m_startTime);
|
|
m_tapInfo.position = touch.GetPosition();
|
|
if (m_tapInfo.duration <= MAX_DURATION)
|
|
{
|
|
OnTap.NotifyAll(this, m_tapInfo);
|
|
}
|
|
Cancel();
|
|
}
|
|
if (!GetTouchCount()) Reset(); // empty map if no touch
|
|
}
|
|
}
|