/* * 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& 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::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 } }