Gestures-Samples/VideoPlayerGestureControlUw.../MainPage.xaml.cpp

127 строки
6.6 KiB
C++

//
// MainPage.xaml.cpp
// Implementation of the MainPage class.
//
#include "pch.h"
#include "MainPage.xaml.h"
#include "GesturesNative/Motions/HandMotion.hpp"
using namespace std;
using namespace Microsoft::Gestures::Common;
using namespace Microsoft::Gestures::Endpoint;
using namespace Microsoft::Gestures;
using namespace VideoPlayerGestureControlUwpNative;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::UI::Core;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
MainPage::MainPage()
{
InitializeComponent();
Loaded += ref new RoutedEventHandler(this, &MainPage::OnPageLoaded);
}
void MainPage::OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
/*
* This sample demonstrates how to incorporate hand motions into gestures !
*/
// Step 1: Connect to Microsoft Gestures service
_gesturesServiceEndpoint = GesturesServiceEndpoint::Make();
auto dispatcher = CoreApplication::MainView->CoreWindow->Dispatcher;
_gestureServiceStatusChangedEventScoper = _gesturesServiceEndpoint->SubscribeToStatusChangedEvent([dispatcher, this](EventProvider*, const StatusChangedEventArgs& args)
{
dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([args, this]()
{
auto endPointStatusStr = EndpointStatusToString(args.GetEndpointStatus());
auto statusStr = std::wstring(L"[").append(endPointStatusStr).append(L"]");
GesturesServiceStatus->Text = ref new String(statusStr.c_str());
}));
});
auto future = _gesturesServiceEndpoint->ConnectAsync();
future.wait(); // One can of course wait for the connection to be established in non blocking fashion via event loops or other async techniques
// Step 2: Define the RewindGesture gesture as follows:
// ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
// │ │ │ │ │ │ │ │ │ │ │ │ │ │
// │ Idle │ -> │ Spread │ -> │ Pause │ -> │ Rewind │ -> │KeepRewind│ -> │ Release │ -> │ Idle │
// │ │ │(unpinch) │ │ (pinch) │ │ (left) │ │ (pinch) │ │(unpinch) │ │ │
// └──────────┘ └──────────┘ └────┬─────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
// │ ^
// └───────────────────────────────────────────────┘
//
// Whenever the gesture returns to the Idle state, playback will resume
//
auto spreadPose = GeneratePinchPose(L"Spread", true);
auto pausePose = GeneratePinchPose(L"Pause");
_pausePoseTriggeredEventScoper = pausePose->SubscribeToGestureSegmentTriggeredEvent([dispatcher, this](EventProvider*, const GestureSegmentTriggeredEventArgs&)
{
dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]()
{
VideoStatus->Text = ref new String(L"");
}));
});
auto rewindMotion = HandMotion::Make(L"Rewind", PalmMotion::Make(VerticalMotionSegment::GetLeft()));
_rewindMotionTriggeredEventScoper = rewindMotion->SubscribeToGestureSegmentTriggeredEvent([dispatcher, this](EventProvider*, const GestureSegmentTriggeredEventArgs&)
{
dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]()
{
VideoStatus->Text = ref new String(L"");
}));
});
auto keepRewindingPose = GeneratePinchPose(L"KeepRewind");
auto releasePose = GeneratePinchPose(L"Release", true);
// Then define the gesture by concatenating the previous objects to form a simple state machine
_rewindGesture = Gesture::Make(L"RewindGesture", spreadPose, pausePose, rewindMotion, keepRewindingPose, releasePose);
// Detect if the user releases the pinch-grab hold in order to resume the playback
_rewindGesture->AddSubPath(pausePose, releasePose);
// Continue playing the video when the gesture resets (either successful or aborted)
_rewindGestureTriggeredEventScoper = _rewindGesture->SubscribeToGestureSegmentTriggeredEvent([dispatcher, this](EventProvider*, const GestureSegmentTriggeredEventArgs&)
{
dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]()
{
VideoStatus->Text = ref new String(L"");
}));
});
_rewindGestureIdleTriggeredEventScoper = _rewindGesture->SubscribeToIdleTriggeredEvent([dispatcher, this](EventProvider*, const GestureSegmentTriggeredEventArgs&)
{
dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]()
{
VideoStatus->Text = ref new String(L"");
}));
});
// Step 3: Register the gesture (When window focus is lost (gained) the service will automatically unregister (register) the gesture)
// To manually control the gesture registration, pass 'isGlobal: true' parameter in the function call below
future = _gesturesServiceEndpoint->RegisterGestureAsync(_rewindGesture);
future.wait();
}
std::shared_ptr<HandPose> MainPage::GeneratePinchPose(const std::wstring& name, bool pinchSpread)
{
std::vector<Finger> pinchingFingers{ Finger::Thumb, Finger::Index };
auto openFingersContext = pinchSpread ? (std::shared_ptr<FingersContext>)AllFingersContext::Make(pinchingFingers) : AnyFingerContext::Make(pinchingFingers);
return HandPose::Make(name,
FingerPose::Make(openFingersContext, FingerFlexion::Open),
FingertipDistanceRelation::Make(pinchingFingers, pinchSpread ? RelativeDistance::NotTouching : RelativeDistance::Touching),
FingertipDistanceRelation::Make(pinchingFingers, RelativeDistance::NotTouching, Finger::Middle));
}