/* * 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 "InputDeviceTouch.hpp" #include "Base/Logger.hpp" #include namespace OpenVulkano::Input { void InputDeviceTouch::Init() { InputDevice::Init(InputDeviceType::TOUCH, 0, "Touch"); m_gestureProcessor.Init(); m_gestureProcessor.m_gestureTap.OnTap += EventHandler(this, &InputDeviceTouch::UpdateTap); m_gestureProcessor.m_gesturePan.OnPanStarted += EventHandler(this, &InputDeviceTouch::UpdatePanStarted); m_gestureProcessor.m_gesturePan.OnPanMoved += EventHandler(this, &InputDeviceTouch::UpdatePanMoved); m_gestureProcessor.m_gesturePan.OnPanEnded += EventHandler(this, &InputDeviceTouch::UpdatePanStarted); m_gestureProcessor.m_gesturePanTwoFingers.OnPanStarted += EventHandler(this, &InputDeviceTouch::UpdatePanTwoFingersStarted); m_gestureProcessor.m_gesturePanTwoFingers.OnPanMoved += EventHandler(this, &InputDeviceTouch::UpdatePanTwoFingersMoved); m_gestureProcessor.m_gesturePanTwoFingers.OnPanEnded += EventHandler(this, &InputDeviceTouch::UpdatePanTwoFingersStarted); m_gestureProcessor.m_gesturePinch.OnPinchStarted += EventHandler(this, &InputDeviceTouch::UpdatePinchStarted); m_gestureProcessor.m_gesturePinch.OnPinchMoved += EventHandler(this, &InputDeviceTouch::UpdatePinchMoved); m_gestureProcessor.m_gesturePinch.OnPinchEnded += EventHandler(this, &InputDeviceTouch::UpdatePinchStarted); } decltype(InputDeviceTouch::m_touches)::iterator InputDeviceTouch::FindTouch(TouchId id) { return std::find_if(m_touches.begin(), m_touches.end(), [id](const Touch& touch) { return (id == touch.GetId()); }); } TouchId InputDeviceTouch::AddTouch(const Math::Vector2f& position) { m_touches.emplace_back(m_nextId, position); OnTouchAdded(m_touches.back()); return m_nextId++; } void InputDeviceTouch::TouchDown(TouchId id) { auto touchIter = FindTouch(id); if (touchIter != m_touches.end()) { touchIter->m_down = true; if (!m_multiTouch && m_touches.size() > 1) { int count = 0; for (const auto &touch : m_touches) { if(touch.IsDown()) count++; if (count > 1) { Logger::INPUT->debug("Begin multitouch"); m_multiTouch = true; break; } } } OnTouchDown.NotifyAll(*touchIter); m_gestureProcessor.TouchDown(*touchIter); } else { Logger::INPUT->warn("Received touch down event for unknown touch id."); } } void InputDeviceTouch::TouchUp(TouchId id) { auto touchIter = FindTouch(id); if (touchIter != m_touches.end()) { touchIter->m_down = false; if (m_multiTouch) { bool hasDown = false; for (const auto &touch : m_touches) { if (touch.IsDown()) { hasDown = true; break; } } if (!hasDown) { Logger::INPUT->debug("End multitouch"); m_multiTouch = false; } } OnTouchUp.NotifyAll(*touchIter); m_gestureProcessor.TouchUp(*touchIter); } else { Logger::INPUT->warn("Received touch up for unknown touch id."); } } void InputDeviceTouch::TouchMoved(TouchId id, const Math::Vector2f& position) { auto touchIter = FindTouch(id); if (touchIter != m_touches.end()) { touchIter->m_lastPosition = touchIter->m_position; touchIter->m_position = position; OnTouchMoved.NotifyAll(*touchIter); m_gestureProcessor.TouchMoved(*touchIter); } else { Logger::INPUT->warn("Received touch moved for unknown touch id"); } } void InputDeviceTouch::RemoveTouch(TouchId id) { auto touchIter = FindTouch(id); if (touchIter != m_touches.end()) { auto removedTouch = *touchIter; m_touches.erase(touchIter); if (m_touches.empty()) { m_multiTouch = false; } OnTouchRemoved.NotifyAll(removedTouch); } else { Logger::INPUT->warn("Received remove request for unknown touch id"); } } void InputDeviceTouch::UpdatePinchStarted(const Gesture* pinch, const PinchInfo& info) { m_lastPinchInfo = m_nextPinchInfo = info; } void InputDeviceTouch::UpdatePanStarted(const Gesture* pan, const PanInfo& info) { m_lastPanInfo = m_nextPanInfo = info; } void InputDeviceTouch::UpdatePanTwoFingersStarted(const Gesture* pan, const PanInfo& info) { m_last2FPanInfo = m_next2FPanInfo = info; } void InputDeviceTouch::UpdatePinchMoved(const Gesture* pinch, const PinchInfo& info) { m_nextPinchInfo = info; } void InputDeviceTouch::UpdatePanMoved(const Gesture* pan, const PanInfo& info) { m_nextPanInfo = info; } void InputDeviceTouch::UpdatePanTwoFingersMoved(const Gesture* pan, const PanInfo& info) { m_next2FPanInfo = info; } void InputDeviceTouch::UpdateTap(const Gesture* tap, const TapInfo& info) { m_toBePressedButtons = 1; m_nextTap = info.position; m_axes[InputKey::Touch::Axis::AXIS_TAP_DURATION] = info.duration.count(); } void InputDeviceTouch::Tick() { if (m_nextPanInfo.position.x > 0 && m_nextPanInfo.position.y > 0) m_toBePressedButtons |= 1 << InputKey::Touch::BUTTON_PAN; // Handle pan press m_lastPressedButtons = m_pressedButtons; m_pressedButtons = m_toBePressedButtons; m_toBePressedButtons = 0; // Tap auto diff = m_nextTap - m_lastTap; m_axes[InputKey::Touch::Axis::AXIS_TAP_X] = diff.x; m_axes[InputKey::Touch::Axis::AXIS_TAP_Y] = diff.y; m_axes[InputKey::Touch::Axis::AXIS_TAP_X_ABS] = m_nextTap.x; m_axes[InputKey::Touch::Axis::AXIS_TAP_Y_ABS] = m_nextTap.y; m_lastTap = m_nextTap; // Pan diff = m_nextPanInfo.position - m_lastPanInfo.position; m_axes[InputKey::Touch::Axis::AXIS_PAN_X] = diff.x; m_axes[InputKey::Touch::Axis::AXIS_PAN_Y] = diff.y; m_axes[InputKey::Touch::Axis::AXIS_PAN_X_ABS] = m_nextPanInfo.position.x; m_axes[InputKey::Touch::Axis::AXIS_PAN_Y_ABS] = m_nextPanInfo.position.y; m_lastPanInfo = m_nextPanInfo; diff = m_next2FPanInfo.position - m_last2FPanInfo.position; m_axes[InputKey::Touch::Axis::AXIS_PAN_TWO_FINGERS_X] = diff.x; m_axes[InputKey::Touch::Axis::AXIS_PAN_TWO_FINGERS_Y] = diff.y; m_last2FPanInfo = m_next2FPanInfo; // Pinch m_axes[InputKey::Touch::Axis::AXIS_PINCH] = m_nextPinchInfo.scale - m_lastPinchInfo.scale; diff = m_nextPinchInfo.position - m_lastPinchInfo.position; m_axes[InputKey::Touch::Axis::AXIS_PINCH_CENTER_X] = diff.x; m_axes[InputKey::Touch::Axis::AXIS_PINCH_CENTER_Y] = diff.y; m_lastPinchInfo = m_nextPinchInfo; } }