Files
OpenVulkano/openVulkanoCpp/Input/Touch/GestureTap.cpp
2023-10-15 13:39:22 +02:00

87 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 auto& 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
}
}