diff --git a/.gitignore b/.gitignore index c5d6618e09..9e8c2abd19 100644 --- a/.gitignore +++ b/.gitignore @@ -198,6 +198,9 @@ FakesAssemblies/ # Visual Studio 6 workspace options file *.opt +# Files generated by samples with custom Direct2D effects +*.fxlib + # Custom ignores gallery.xml project.lock.json diff --git a/README.md b/README.md index 6533fdf1e1..4de269934c 100644 --- a/README.md +++ b/README.md @@ -67,57 +67,61 @@ For additional Windows samples, see [Windows on GitHub](http://microsoft.github. + - + - + - + - + - + - + - + - + + + + + - + -
360-degree video playback Adaptive streaming Advanced captureAdvanced casting
Advanced casting Audio categories Audio graphsBackground media playback
Background media playback Basic camera app Basic face detectionBasic face tracking
Basic face tracking Basic media casting Camera face detectionCamera frames
Camera frames Camera preview frame Camera profilesCamera resolution
Camera resolution Camera stream correlation DASH streamingDirect2D photo adjustment
Direct2D photo adjustment Media editing Media importMedia transport controls
Media transport controls MIDI PlaylistsPlayReady
PlayReadyProcessing frames with OpenCV Simple imaging
Spatial audio System media transport controlsTranscoding media
Transcoding media Video playback Video playback synchronizationVideo stabilization
Video stabilization Windows audio session (WASAPI)
@@ -408,15 +412,16 @@ For additional Windows samples, see [Windows on GitHub](http://microsoft.github. Composition visual without framework + Direct2D advanced color image rendering Direct2D custom image effects - Direct2D gradient mesh + Direct2D gradient mesh Direct2D SVG image rendering Efficient animations (HTML) - Transform3D animations + Transform3D animations Transform3D parallax @@ -431,10 +436,11 @@ For additional Windows samples, see [Windows on GitHub](http://microsoft.github. Holographic spatial mapping + Holographic spatial stage Holographic voice input - Spatial interaction source + Spatial interaction source Tag-along hologram diff --git a/Samples/360VideoPlayback/README.md b/Samples/360VideoPlayback/README.md new file mode 100644 index 0000000000..ccf1d64551 --- /dev/null +++ b/Samples/360VideoPlayback/README.md @@ -0,0 +1,114 @@ + + +# 360-degree Video Playback sample + +Shows how to play 360-degree video. + +The sample uses the MediaPlayer class for 360-degree playback. +For flat devices (PC, Xbox, Mobile) the MediaPlayer handles all aspects of the rendering. +The developer need only provide the look direction. +For Mixed Reality, this sample shows how to use +the MediaPlayer to obtain individual video frames, and render them to a head-mounted display. + +> **Note:** This sample is part of a large collection of UWP feature samples. +> If you are unfamiliar with Git and GitHub, you can download the entire collection as a +> [ZIP file](https://github.com/Microsoft/Windows-universal-samples/archive/master.zip), but be +> sure to unzip everything to access shared dependencies. For more info on working with the ZIP file, +> the samples collection, and GitHub, see [Get the UWP samples from GitHub](https://aka.ms/ovu2uq). +> For more samples, see the [Samples portal](https://aka.ms/winsamples) on the Windows Dev Center. + +Specifically, this samples covers: + +- Creating a hybrid application which works across flat devices (PC, Xbox, Mobile) and Mixed Reality devices (MR headset, Hololens). +- Handling various forms of user input including mouse, keyboard and gamepad. +- Selecting the playback mode (flat or immersive) based on the environment the app is running in. +- Creating multiple windows or views of the app and switching between the XAML (flat) and DirectX (immersive) Windows. +- The C++ version of the sample also implements some transport controls during immersive playback. + +## Additional remarks + +**Note** The Windows universal samples for Windows 10 Holographic require Visual Studio 2017 Update 2 +to build, and a Windows Holographic device to execute. Windows Holographic devices include the +Microsoft HoloLens and the Microsoft HoloLens Emulator. + +To obtain information about Windows 10 development, go to the [Windows Dev Center](http://go.microsoft.com/fwlink/?LinkID=532421). + +To obtain information about the tools used for Windows Holographic development, including +Visual Studio and the Microsoft HoloLens Emulator, go to +[Install the tools](https://developer.microsoft.com/windows/mixed-reality/install_the_tools). + +### Reference +[MediaPlayer](https://docs.microsoft.com/en-us/uwp/api/windows.media.playback.mediaplayer) +[Mixed Reality Development](https://developer.microsoft.com/en-us/windows/mixed-reality/development) +[Creating a Holographic DirextX Project](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_a_holographic_directx_project) +[Using XAML with Holographic DirectX Apps](https://developer.microsoft.com/en-us/windows/mixed-reality/using_xaml_with_holographic_directx_apps) +[ApplicationViewSwitcher](http://msdn.microsoft.com/library/windows/apps/dn281094) + +## System requirements + +**Client:** Windows 10 build 15063, Windows 10 Holographic + +**Phone:** Windows 10 build 15063 + +## Build the sample + +1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with + the sample you want to build. +2. Start Microsoft Visual Studio 2017 and select **File** \> **Open** \> **Project/Solution**. +3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the + subfolder for this specific sample, then the subfolder for your preferred language (C++, C#, or + JavaScript). Double-click the Visual Studio Solution (.sln) file. +4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**. + +## Run the sample + +The next steps depend on whether you just want to deploy the sample or you want to both deploy and +run it. + +### Deploying the sample + +- Select Build > Deploy Solution. + +### Deploying and running the sample + +- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging. + +### Deploying the sample to the Microsoft HoloLens emulator + +- Click the debug target drop-down, and select **Microsoft HoloLens Emulator**. +- Select **Build** \> **Deploy** Solution. + +### Deploying the sample to a Microsoft HoloLens + +- Developer unlock your Microsoft HoloLens. For instructions, go to + [Enable your device for development](https://msdn.microsoft.com/windows/uwp/get-started/enable-your-device-for-development#enable-your-windows-10-devices). +- Find the IP address of your Microsoft HoloLens. The IP address can be found in **Settings** + \> **Network & Internet** \> **Wi-Fi** \> **Advanced options**. Or, you can ask Cortana for this + information by saying: "Hey Cortana, what's my IP address?" +- Right-click on your project in Visual Studio, and then select **Properties**. +- In the Debugging pane, click the drop-down and select **Remote Machine**. +- Enter the IP address of your Microsoft HoloLens into the field labelled **Machine Name**. +- Click **OK**. +- Select **Build** \> **Deploy** Solution. + +### Pairing your developer-unlocked Microsoft HoloLens with Visual Studio + +The first time you deploy from your development PC to your developer-unlocked Microsoft HoloLens, +you will need to use a PIN to pair your PC with the Microsoft HoloLens. +- When you select **Build** \> **Deploy Solution**, a dialog box will appear for Visual Studio to + accept the PIN. +- On your Microsoft HoloLens, go to **Settings** \> **Update** \> **For developers**, and click on + **Pair**. +- Type the PIN displayed by your Microsoft HoloLens into the Visual Studio dialog box and click + **OK**. +- On your Microsoft HoloLens, select **Done** to accept the pairing. +- The solution will then start to deploy. + +### Deploying and running the sample + +- To debug the sample and then run it, follow the steps listed above to connect your + developer-unlocked Microsoft HoloLens, then press F5 or select **Debug** \> **Start Debugging**. + To run the sample without debugging, press Ctrl+F5 or select **Debug** \> **Start Without Debugging**. diff --git a/Samples/360VideoPlayback/cpp/360VideoPlayback.sln b/Samples/360VideoPlayback/cpp/360VideoPlayback.sln new file mode 100644 index 0000000000..20b477ac8f --- /dev/null +++ b/Samples/360VideoPlayback/cpp/360VideoPlayback.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26403.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "360VideoPlayback", "360VideoPlayback.vcxproj", "{70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Debug|x64.ActiveCfg = Debug|x64 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Debug|x64.Build.0 = Debug|x64 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Debug|x64.Deploy.0 = Debug|x64 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Debug|x86.ActiveCfg = Debug|Win32 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Debug|x86.Build.0 = Debug|Win32 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Debug|x86.Deploy.0 = Debug|Win32 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Release|x64.ActiveCfg = Release|x64 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Release|x64.Build.0 = Release|x64 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Release|x64.Deploy.0 = Release|x64 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Release|x86.ActiveCfg = Release|Win32 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Release|x86.Build.0 = Release|Win32 + {70E4B7FA-6346-4DB9-B2BE-B27068B19B4F}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/360VideoPlayback/cpp/360VideoPlayback.vcxproj b/Samples/360VideoPlayback/cpp/360VideoPlayback.vcxproj new file mode 100644 index 0000000000..0d39a99339 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/360VideoPlayback.vcxproj @@ -0,0 +1,271 @@ + + + + {70e4b7fa-6346-4db9-b2be-b27068b19b4f} + HolographicApp + _360VideoPlayback + en-US + 15.0 + true + Windows Store + 10.0.15063.0 + 10.0.15063.0 + 10.0 + true + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + Application + true + v141 + + + Application + false + true + v141 + + + Application + true + v141 + + + Application + false + true + v141 + + + + + + + + + + + + + + + + + + + + + + $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);..\..\..\SharedContent\cpp + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + _DEBUG;%(PreprocessorDefinitions) + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + _DEBUG;%(PreprocessorDefinitions) + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + + + + + Assets\splash-sdk.png + + + Assets\squareTile-sdk.png + + + Assets\smallTile-sdk.png + + + Assets\StoreLogo-sdk.png + + + + + ..\shared\App.xaml + + + + + + + + + + + ..\shared\MainPage.xaml + + + ..\shared\PlaybackPage.xaml + + + ..\shared\VideoGallery.xaml + + + + + + + + + + + + + + ..\shared\App.xaml + + + + + + + + + + + ..\shared\MainPage.xaml + + + ..\shared\PlaybackPage.xaml + + + ..\shared\VideoGallery.xaml + + + + + + + Create + + + + + Designer + + + + + Geometry + 5.0 + 5.0 + Geometry + + + Pixel + 5.0 + 5.0 + Pixel + + + Vertex + 5.0 + 5.0 + Vertex + + + Pixel + 5.0 + + + Vertex + 5.0 + + + Vertex + 5.0 + + + Geometry + 5.0 + + + + + Document + + + Designer + + + Designer + + + + + + + + + + + true + + \ No newline at end of file diff --git a/Samples/360VideoPlayback/cpp/360VideoPlayback.vcxproj.filters b/Samples/360VideoPlayback/cpp/360VideoPlayback.vcxproj.filters new file mode 100644 index 0000000000..3838cf9be7 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/360VideoPlayback.vcxproj.filters @@ -0,0 +1,156 @@ + + + + + 70e4b7fa-6346-4db9-b2be-b27068b19b4f + + + a32756d0-ab5c-487c-81e1-5113c37943d7 + bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + 7a3f21c3-861d-492c-99df-fc27a164c78a + + + 5d50e774-3a5f-4551-aa54-06a64b57860f + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + + + + + Content + + + Content + + + + + + + Common + + + Common + + + Common + + + Common + + + Content + + + Common + + + + + + + + Content + + + Content + + + Content + + + + + + + Common + + + Common + + + Common + + + Common + + + Content + + + Common + + + + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/360VideoPlayback/cpp/360VideoPlaybackMain.cpp b/Samples/360VideoPlayback/cpp/360VideoPlaybackMain.cpp new file mode 100644 index 0000000000..4c7c4e2b6e --- /dev/null +++ b/Samples/360VideoPlayback/cpp/360VideoPlaybackMain.cpp @@ -0,0 +1,495 @@ +#include "pch.h" +#include "360VideoPlaybackMain.h" +#include "Common\DirectXHelper.h" +#include +#include + +using namespace _360VideoPlayback; +using namespace concurrency; +using namespace Platform; +using namespace std; +using namespace std::placeholders; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Numerics; +using namespace Windows::Gaming::Input; +using namespace Windows::Graphics::Holographic; +using namespace Windows::Perception::Spatial; +using namespace Windows::System; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input::Spatial; + +const float MTC_SPAWN_DISTANCE = 1.35f; + +std::shared_ptr _360VideoPlaybackMain::m_deviceResources = nullptr; + +shared_ptr _360VideoPlaybackMain::GetDeviceResources() +{ + if (_360VideoPlaybackMain::m_deviceResources == nullptr) + { + _360VideoPlaybackMain::m_deviceResources = make_shared(); + } + return _360VideoPlaybackMain::m_deviceResources; +} + +// Loads and initializes application assets when the application is loaded. +_360VideoPlaybackMain::_360VideoPlaybackMain() +{ + // Register to be notified if the device is lost or recreated. + m_deviceResources->RegisterDeviceNotify(this); +} + +void _360VideoPlaybackMain::SetHolographicSpace(HolographicSpace^ holographicSpace) +{ + UnregisterHolographicEventHandlers(); + + m_holographicSpace = holographicSpace; + + // + // TODO: Add code here to initialize your holographic content. + // + +#ifdef DRAW_SAMPLE_CONTENT + // Initialize the sample hologram. + m_videoRenderer = std::make_unique(); + m_mediaTransportControls = std::make_unique(); + + m_spatialInputHandler = std::make_unique(); +#endif + + // Use the default SpatialLocator to track the motion of the device. + m_locator = SpatialLocator::GetDefault(); + + // Be able to respond to changes in the positional tracking state. + m_locatabilityChangedToken = + m_locator->LocatabilityChanged += + ref new TypedEventHandler( + std::bind(&_360VideoPlaybackMain::OnLocatabilityChanged, this, _1, _2) + ); + + // Respond to camera added events by creating any resources that are specific + // to that camera, such as the back buffer render target view. + // When we add an event handler for CameraAdded, the API layer will avoid putting + // the new camera in new HolographicFrames until we complete the deferral we created + // for that handler, or return from the handler without creating a deferral. This + // allows the app to take more than one frame to finish creating resources and + // loading assets for the new holographic camera. + // This function should be registered before the app creates any HolographicFrames. + m_cameraAddedToken = + m_holographicSpace->CameraAdded += + ref new TypedEventHandler( + std::bind(&_360VideoPlaybackMain::OnCameraAdded, this, _1, _2) + ); + + // Respond to camera removed events by releasing resources that were created for that + // camera. + // When the app receives a CameraRemoved event, it releases all references to the back + // buffer right away. This includes render target views, Direct2D target bitmaps, and so on. + // The app must also ensure that the back buffer is not attached as a render target, as + // shown in DeviceResources::ReleaseResourcesForBackBuffer. + m_cameraRemovedToken = + m_holographicSpace->CameraRemoved += + ref new TypedEventHandler( + std::bind(&_360VideoPlaybackMain::OnCameraRemoved, this, _1, _2) + ); + + // The simplest way to render video frame is to create a stationary reference frame + // when the app is launched. This is roughly analogous to creating a "world" coordinate system + // with the origin placed at the device's position as the app is launched. + m_referenceFrame = m_locator->CreateAttachedFrameOfReferenceAtCurrentHeading(); + + // Notes on spatial tracking APIs: + // * Stationary reference frames are designed to provide a best-fit position relative to the + // overall space. Individual positions within that reference frame are allowed to drift slightly + // as the device learns more about the environment. + // * When precise placement of individual holograms is required, a SpatialAnchor should be used to + // anchor the individual hologram to a position in the real world - for example, a point the user + // indicates to be of special interest. Anchor positions do not drift, but can be corrected; the + // anchor will use the corrected position starting in the next frame after the correction has + // occurred. +} + +void _360VideoPlaybackMain::UnregisterHolographicEventHandlers() +{ + if (m_holographicSpace != nullptr) + { + // Clear previous event registrations. + + if (m_cameraAddedToken.Value != 0) + { + m_holographicSpace->CameraAdded -= m_cameraAddedToken; + m_cameraAddedToken.Value = 0; + } + + if (m_cameraRemovedToken.Value != 0) + { + m_holographicSpace->CameraRemoved -= m_cameraRemovedToken; + m_cameraRemovedToken.Value = 0; + } + } + + if (m_locator != nullptr) + { + m_locator->LocatabilityChanged -= m_locatabilityChangedToken; + } + + if (m_videoRenderer != nullptr) + { + m_videoRenderer->ReleaseDeviceDependentResources(); + } +} + +_360VideoPlaybackMain::~_360VideoPlaybackMain() +{ + // Deregister device notification. + m_deviceResources->RegisterDeviceNotify(nullptr); + + UnregisterHolographicEventHandlers(); +} + +// Updates the application state once per frame. +HolographicFrame^ _360VideoPlaybackMain::Update() +{ + // Before doing the timer update, there is some work to do per-frame + // to maintain holographic rendering. First, we will get information + // about the current frame. + + // The HolographicFrame has information that the app needs in order + // to update and render the current frame. The app begins each new + // frame by calling CreateNextFrame. + HolographicFrame^ holographicFrame = m_holographicSpace->CreateNextFrame(); + + // Get a prediction of where holographic cameras will be when this frame + // is presented. + HolographicFramePrediction^ prediction = holographicFrame->CurrentPrediction; + + // Back buffers can change from frame to frame. Validate each buffer, and recreate + // resource views and depth buffers as needed. + m_deviceResources->EnsureCameraResources(holographicFrame, prediction); + + // Next, we get a coordinate system from the attached frame of reference that is + // associated with the current frame. Later, this coordinate system is used for + // for creating the stereo view matrices when rendering the sample content. + SpatialCoordinateSystem^ currentCoordinateSystem = m_referenceFrame->GetStationaryCoordinateSystemAtTimestamp(prediction->Timestamp); + SpatialPointerPose^ position = SpatialPointerPose::TryGetAtTimestamp(currentCoordinateSystem, prediction->Timestamp); + + bool inputReceived = false; + + + // Check for new input state since the last frame. + SpatialInteractionSourceState^ pointerState = m_spatialInputHandler->CheckForInput(); + if (pointerState != nullptr) + { + inputReceived = true; + } + + // Check for Gamepad input + auto gamepads = Gamepad::Gamepads; + if (gamepads->Size > 0) + { + auto currentButtonState = gamepads->GetAt(0)->GetCurrentReading().Buttons; // We are only going to support 1 controller at the moment + if (static_cast(currentButtonState & GamepadButtons::A)) // Marking 'A' Button as our click button + { + if (!m_isGamepadPressed) // Control the frequency of calls in Update + { + inputReceived = true; + m_isGamepadPressed = true; + } + } + else + { + m_isGamepadPressed = false; + } + } + + // Check Mouse Input + if (static_cast(CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::LeftButton) & CoreVirtualKeyStates::Down)) + { + if (!m_isMouseLeftKeyPressed) // Control the frequency of calls in Update + { + inputReceived = true; + m_isMouseLeftKeyPressed = true; + } + } + else + { + m_isMouseLeftKeyPressed = false; + } + + // Handle input + if (inputReceived) + { + if (m_mediaTransportControls->IsVisible()) + { + m_mediaTransportControls->PerformPressedAction(); + } + else if (position != nullptr) + { + m_mediaTransportControls->Show(position, MTC_SPAWN_DISTANCE); + } + } + + m_timer.Tick([this, position]() + { + // + // TODO: Update scene objects. + // + // Put time-based updates here. By default this code will run once per frame, + // but if you change the StepTimer to use a fixed time step this code will + // run as many times as needed to get to the current step. + // + +#ifdef DRAW_SAMPLE_CONTENT + m_videoRenderer->Update(m_timer); + m_mediaTransportControls->Update(m_timer, position); +#endif + }); + + // We complete the frame update by using information about our content positioning + // to set the focus point. + + for (auto cameraPose : prediction->CameraPoses) + { +#ifdef DRAW_SAMPLE_CONTENT + // The HolographicCameraRenderingParameters class provides access to set + // the image stabilization parameters. + HolographicCameraRenderingParameters^ renderingParameters = holographicFrame->GetRenderingParameters(cameraPose); + + // SetFocusPoint informs the system about a specific point in your scene to + // prioritize for image stabilization. The focus point is set independently + // for each holographic camera. + // You should set the focus point near the content that the user is looking at. + // In this example, we put the focus point at the center of the sample hologram, + // since that is the only hologram available for the user to focus on. + // You can also set the relative velocity and facing of that content; the sample + // hologram is at a fixed point so we only need to indicate its position. + float3 position = { 0.f, 0.f, 0.f }; + renderingParameters->SetFocusPoint( + currentCoordinateSystem, + position); +#endif + } + + // The holographic frame will be used to get up-to-date view and projection matrices and + // to present the swap chain. + return holographicFrame; +} + +// Renders the current frame to each holographic camera, according to the +// current application and spatial positioning state. Returns true if the +// frame was rendered to at least one camera. +bool _360VideoPlaybackMain::Render(HolographicFrame^ holographicFrame) +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return false; + } + + // + // TODO: Add code for pre-pass rendering here. + // + // Take care of any tasks that are not specific to an individual holographic + // camera. This includes anything that doesn't need the final view or projection + // matrix, such as lighting maps. + // + + // Lock the set of holographic camera resources, then draw to each camera + // in this frame. + return m_deviceResources->UseHolographicCameraResources( + [this, holographicFrame](std::map>& cameraResourceMap) + { + // Up-to-date frame predictions enhance the effectiveness of image stablization and + // allow more accurate positioning of holograms. + holographicFrame->UpdateCurrentPrediction(); + HolographicFramePrediction^ prediction = holographicFrame->CurrentPrediction; + + bool atLeastOneCameraRendered = false; + for (auto cameraPose : prediction->CameraPoses) + { + // This represents the device-based resources for a HolographicCamera. + DX::CameraResources* pCameraResources = cameraResourceMap[cameraPose->HolographicCamera->Id].get(); + + // Get the device context. + const auto context = m_deviceResources->GetD3DDeviceContext(); + const auto depthStencilView = pCameraResources->GetDepthStencilView(); + + // Set render targets to the current holographic camera. + ID3D11RenderTargetView *const targets[1] = { pCameraResources->GetBackBufferRenderTargetView() }; + context->OMSetRenderTargets(1, targets, depthStencilView); + + // Clear the back buffer and depth stencil view. + context->ClearRenderTargetView(targets[0], DirectX::Colors::Transparent); + context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + // + // TODO: Replace the sample content with your own content. + // + // Notes regarding holographic content: + // * For drawing, remember that you have the potential to fill twice as many pixels + // in a stereoscopic render target as compared to a non-stereoscopic render target + // of the same resolution. Avoid unnecessary or repeated writes to the same pixel, + // and only draw holograms that the user can see. + // * To help occlude hologram geometry, you can create a depth map using geometry + // data obtained via the surface mapping APIs. You can use this depth map to avoid + // rendering holograms that are intended to be hidden behind tables, walls, + // monitors, and so on. + // * Black pixels will appear transparent to the user wearing the device, but you + // should still use alpha blending to draw semitransparent holograms. You should + // also clear the screen to Transparent as shown above. + // + + + // The view and projection matrices for each holographic camera will change + // every frame. This function refreshes the data in the constant buffer for + // the holographic camera indicated by cameraPose. + pCameraResources->UpdateViewProjectionBuffer(m_deviceResources, cameraPose, m_referenceFrame->GetStationaryCoordinateSystemAtTimestamp(prediction->Timestamp)); + + // Attach the view/projection constant buffer for this camera to the graphics pipeline. + bool cameraActive = pCameraResources->AttachViewProjectionBuffer(m_deviceResources); + +#ifdef DRAW_SAMPLE_CONTENT + // Only render world-locked content when positional tracking is active. + if (cameraActive) + { + // Draw the sample hologram. + m_videoRenderer->Render(); + m_mediaTransportControls->Render(); + } +#endif + atLeastOneCameraRendered = true; + } + + return atLeastOneCameraRendered; + }); +} + +void _360VideoPlaybackMain::SaveAppState() +{ + // + // TODO: Insert code here to save your app state. + // This method is called when the app is about to suspend. + // + // For example, store information in the SpatialAnchorStore. + // +} + +void _360VideoPlaybackMain::LoadAppState() +{ + // + // TODO: Insert code here to load your app state. + // This method is called when the app resumes. + // + // For example, load information from the SpatialAnchorStore. + // +} + +// Notifies classes that use Direct3D device resources that the device resources +// need to be released before this method returns. +void _360VideoPlaybackMain::OnDeviceLost() +{ +#ifdef DRAW_SAMPLE_CONTENT + m_videoRenderer->ReleaseDeviceDependentResources(); +#endif +} + +// Notifies classes that use Direct3D device resources that the device resources +// may now be recreated. +void _360VideoPlaybackMain::OnDeviceRestored() +{ +#ifdef DRAW_SAMPLE_CONTENT + m_videoRenderer->CreateDeviceDependentResources(); +#endif +} + +void _360VideoPlaybackMain::OnLocatabilityChanged(SpatialLocator^ sender, Object^ args) +{ + switch (sender->Locatability) + { + case SpatialLocatability::Unavailable: + // Holograms cannot be rendered. + { + String^ message = L"Warning! Positional tracking is " + + sender->Locatability.ToString() + L".\n"; + OutputDebugStringW(message->Data()); + } + break; + + // In the following three cases, it is still possible to place holograms using a + // SpatialLocatorAttachedFrameOfReference. + case SpatialLocatability::PositionalTrackingActivating: + // The system is preparing to use positional tracking. + + case SpatialLocatability::OrientationOnly: + // Positional tracking has not been activated. + + case SpatialLocatability::PositionalTrackingInhibited: + // Positional tracking is temporarily inhibited. User action may be required + // in order to restore positional tracking. + break; + + case SpatialLocatability::PositionalTrackingActive: + // Positional tracking is active. World-locked content can be rendered. + break; + } +} + +void _360VideoPlaybackMain::OnCameraAdded( + HolographicSpace^ sender, + HolographicSpaceCameraAddedEventArgs^ args +) +{ + Deferral^ deferral = args->GetDeferral(); + HolographicCamera^ holographicCamera = args->Camera; + create_task([this, deferral, holographicCamera]() + { + // + // TODO: Allocate resources for the new camera and load any content specific to + // that camera. Note that the render target size (in pixels) is a property + // of the HolographicCamera object, and can be used to create off-screen + // render targets that match the resolution of the HolographicCamera. + // + + // Create device-based resources for the holographic camera and add it to the list of + // cameras used for updates and rendering. Notes: + // * Since this function may be called at any time, the AddHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // adding the new camera. At 60 frames per second this wait should not take long. + // * A subsequent Update will take the back buffer from the RenderingParameters of this + // camera's CameraPose and use it to create the ID3D11RenderTargetView for this camera. + // Content can then be rendered for the HolographicCamera. + m_deviceResources->AddHolographicCamera(holographicCamera); + + // Holographic frame predictions will not include any information about this camera until + // the deferral is completed. + deferral->Complete(); + }); +} + +void _360VideoPlaybackMain::OnCameraRemoved( + HolographicSpace^ sender, + HolographicSpaceCameraRemovedEventArgs^ args +) +{ + create_task([this]() + { + // + // TODO: Asynchronously unload or deactivate content resources (not back buffer + // resources) that are specific only to the camera that was removed. + // + }); + + // Before letting this callback return, ensure that all references to the back buffer + // are released. + // Since this function may be called at any time, the RemoveHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // deallocating resources for this camera. At 60 frames per second this wait should + // not take long. + m_deviceResources->RemoveHolographicCamera(args->Camera); +} + +void _360VideoPlaybackMain::CreateVideoShaders() +{ + m_videoRenderer->CreateDeviceDependentResources(); + m_mediaTransportControls->Initialize(); + m_mediaTransportControls->ApplyShaders(); +} diff --git a/Samples/360VideoPlayback/cpp/360VideoPlaybackMain.h b/Samples/360VideoPlayback/cpp/360VideoPlaybackMain.h new file mode 100644 index 0000000000..034320e27d --- /dev/null +++ b/Samples/360VideoPlayback/cpp/360VideoPlaybackMain.h @@ -0,0 +1,103 @@ +#pragma once + +// +// Comment out this preprocessor definition to disable all of the +// sample content. +// +// To remove the content after disabling it: +// * Remove the unused code from your app's Main class. +// * Delete the Content folder provided with this template. +// +#define DRAW_SAMPLE_CONTENT + +#include "Common\DeviceResources.h" +#include "Common\StepTimer.h" + +#ifdef DRAW_SAMPLE_CONTENT +#include "Content\VideoRenderer.h" +#include "Content\SpatialInputHandler.h" +#include "Content\MediaTransportControls.h" +#endif + +// Updates, renders, and presents holographic content using Direct3D. +namespace _360VideoPlayback +{ + class _360VideoPlaybackMain : public DX::IDeviceNotify + { + public: + _360VideoPlaybackMain(); + ~_360VideoPlaybackMain(); + + // Sets the holographic space. This is our closest analogue to setting a new window + // for the app. + void SetHolographicSpace(Windows::Graphics::Holographic::HolographicSpace^ holographicSpace); + + // Starts the holographic frame and updates the content. + Windows::Graphics::Holographic::HolographicFrame^ Update(); + + // Renders holograms, including world-locked content. + bool Render(Windows::Graphics::Holographic::HolographicFrame^ holographicFrame); + + // Handle saving and loading of app state owned by AppMain. + void SaveAppState(); + void LoadAppState(); + + // IDeviceNotify + virtual void OnDeviceLost(); + virtual void OnDeviceRestored(); + void CreateVideoShaders(); + // Clears event registration state. Used when changing to a new HolographicSpace + // and when tearing down AppMain. + void UnregisterHolographicEventHandlers(); + static std::shared_ptr GetDeviceResources(); + + private: + // Asynchronously creates resources for new holographic cameras. + void OnCameraAdded( + Windows::Graphics::Holographic::HolographicSpace^ sender, + Windows::Graphics::Holographic::HolographicSpaceCameraAddedEventArgs^ args); + + // Synchronously releases resources for holographic cameras that are no longer + // attached to the system. + void OnCameraRemoved( + Windows::Graphics::Holographic::HolographicSpace^ sender, + Windows::Graphics::Holographic::HolographicSpaceCameraRemovedEventArgs^ args); + + // Used to notify the app when the positional tracking state changes. + void OnLocatabilityChanged( + Windows::Perception::Spatial::SpatialLocator^ sender, + Platform::Object^ args); + +#ifdef DRAW_SAMPLE_CONTENT + // Renders a colorful holographic cube that's 20 centimeters wide. This sample content + // is used to demonstrate world-locked rendering. + std::unique_ptr m_videoRenderer; + std::unique_ptr m_mediaTransportControls; + + // Listens for the Pressed spatial input event. + std::shared_ptr m_spatialInputHandler; +#endif + + // static pointer to device resources. + static std::shared_ptr m_deviceResources; + + // Render loop timer. + DX::StepTimer m_timer; + + // Represents the holographic space around the user. + Windows::Graphics::Holographic::HolographicSpace^ m_holographicSpace; + + // SpatialLocator that is attached to the primary camera. + Windows::Perception::Spatial::SpatialLocator^ m_locator; + + // A reference frame attached to the holographic camera. + Windows::Perception::Spatial::SpatialLocatorAttachedFrameOfReference^ m_referenceFrame; + + // Event registration tokens. + Windows::Foundation::EventRegistrationToken m_cameraAddedToken; + Windows::Foundation::EventRegistrationToken m_cameraRemovedToken; + Windows::Foundation::EventRegistrationToken m_locatabilityChangedToken; + bool m_isGamepadPressed = false; + bool m_isMouseLeftKeyPressed = false; + }; +} diff --git a/Samples/360VideoPlayback/cpp/App.xaml.cpp b/Samples/360VideoPlayback/cpp/App.xaml.cpp new file mode 100644 index 0000000000..c8f9bf2df4 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/App.xaml.cpp @@ -0,0 +1,111 @@ +// +// App.xaml.cpp +// Implementation of the App class. +// + +#include "pch.h" +#include "MainPage.xaml.h" + +using namespace _360VideoPlayback; + +using namespace Platform; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::Foundation; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Interop; +using namespace Windows::UI::Xaml::Navigation; + +/// +/// Initializes the singleton application object. This is the first line of authored code +/// executed, and as such is the logical equivalent of main() or WinMain(). +/// +App::App() +{ + InitializeComponent(); + Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); +} + +/// +/// Invoked when the application is launched normally by the end user. Other entry points +/// will be used such as when the application is launched to open a specific file. +/// +/// Details about the launch request and process. +void App::OnLaunched(LaunchActivatedEventArgs^ e) +{ + auto rootFrame = dynamic_cast(Window::Current->Content); + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == nullptr) + { + // Create a Frame to act as the navigation context and associate it with + // a SuspensionManager key + rootFrame = ref new Frame(); + + rootFrame->NavigationFailed += ref new NavigationFailedEventHandler(this, &App::OnNavigationFailed); + + if (e->PreviousExecutionState == ApplicationExecutionState::Terminated) + { + // TODO: Restore the saved session state only when appropriate, scheduling the + // final launch steps after the restore is complete + + } + + if (e->PrelaunchActivated == false) + { + if (rootFrame->Content == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); + } + // Place the frame in the current Window + Window::Current->Content = rootFrame; + // Ensure the current window is active + Window::Current->Activate(); + } + } + else + { + if (e->PrelaunchActivated == false) + { + if (rootFrame->Content == nullptr) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments); + } + // Ensure the current window is active + Window::Current->Activate(); + } + } +} + +/// +/// Invoked when application execution is being suspended. Application state is saved +/// without knowing whether the application will be terminated or resumed with the contents +/// of memory still intact. +/// +/// The source of the suspend request. +/// Details about the suspend request. +void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e) +{ + (void) sender; // Unused parameter + (void) e; // Unused parameter + + //TODO: Save application state and stop any background activity +} + +/// +/// Invoked when Navigation to a certain page fails +/// +/// The Frame which failed navigation +/// Details about the navigation failure +void App::OnNavigationFailed(Object^ sender, NavigationFailedEventArgs^ e) +{ + throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name); +} diff --git a/Samples/360VideoPlayback/cpp/App.xaml.h b/Samples/360VideoPlayback/cpp/App.xaml.h new file mode 100644 index 0000000000..646c1e408e --- /dev/null +++ b/Samples/360VideoPlayback/cpp/App.xaml.h @@ -0,0 +1,27 @@ +// +// App.xaml.h +// Declaration of the App class. +// + +#pragma once + +#include "App.g.h" + +namespace _360VideoPlayback +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + ref class App sealed + { + protected: + virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override; + + internal: + App(); + + private: + void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e); + void OnNavigationFailed(Platform::Object^ sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs^ e); + }; +} diff --git a/Samples/360VideoPlayback/cpp/AppView.cpp b/Samples/360VideoPlayback/cpp/AppView.cpp new file mode 100644 index 0000000000..75b1a9bef6 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/AppView.cpp @@ -0,0 +1,289 @@ +#include "pch.h" +#include "AppView.h" +#include "VideoGallery.xaml.h" +#include + +using namespace _360VideoPlayback; +using namespace concurrency; +using namespace Platform; +using namespace std; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Holographic; +using namespace Windows::Media::Core; +using namespace Windows::Media::Playback; +using namespace Windows::UI::Core; +using namespace Windows::UI::ViewManagement; + +MediaPlayer^ AppView::m_mediaPlayer = nullptr; + +MediaPlayer^ AppView::GetMediaPlayer() +{ + return m_mediaPlayer; +} + +AppViewSource::AppViewSource(Uri^ sourceUri) + : m_sourceUri(sourceUri) +{ +} + +IFrameworkView^ AppViewSource::CreateView() +{ + return ref new AppView(m_sourceUri); +} + +AppView::AppView(Uri^ sourceUri) + : m_sourceUri(sourceUri) +{ + m_mediaPlayer = ref new MediaPlayer(); +} + +// IFrameworkView methods + +// The first method called when the IFrameworkView is being created. +// Use this method to subscribe for Windows shell events and to initialize your app. +void AppView::Initialize(CoreApplicationView^ applicationView) +{ + CoreWindow^ window = CoreWindow::GetForCurrentThread(); + if (window != nullptr) + { + window->Activated += ref new TypedEventHandler(this, &AppView::OnMainViewActivated); + } + applicationView->Activated += + ref new TypedEventHandler(this, &AppView::OnViewActivated); +} + +void AppView::OnMainViewActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args) +{ + m_mainWindowReactivated = true; + m_windowClosed = true; + TryCloseWindow(); +} + +// Called when the CoreWindow object is created (or re-created). +void AppView::SetWindow(CoreWindow^ window) +{ + ApplicationView::GetForCurrentView()->Consolidated += + ref new TypedEventHandler(this, &AppView::OnConsolidated); + + // Register event handlers for app lifecycle. + CoreApplication::Suspending += + ref new EventHandler(this, &AppView::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &AppView::OnResuming); + + // Register for keypress notifications. + window->KeyDown += + ref new TypedEventHandler(this, &AppView::OnKeyPressed); + + // Register for notification that the app window is being closed. + window->Closed += + ref new TypedEventHandler(this, &AppView::OnWindowClosed); + + // Register for notifications that the app window is losing focus. + window->VisibilityChanged += + ref new TypedEventHandler(this, &AppView::OnVisibilityChanged); + + // At this point we have access to the device and we can create device-dependent + // resources. + m_deviceResources = _360VideoPlaybackMain::GetDeviceResources(); + + m_main = std::make_unique<_360VideoPlaybackMain>(); + + // Create a holographic space for the core window for the current view. + // Presenting holographic frames that are created by this holographic space will put + // the app into exclusive mode. + m_holographicSpace = HolographicSpace::CreateForCoreWindow(window); + + // The DeviceResources class uses the preferred DXGI adapter ID from the holographic + // space (when available) to create a Direct3D device. The HolographicSpace + // uses this ID3D11Device to create and manage device-based resources such as + // swap chains. + m_deviceResources->SetHolographicSpace(m_holographicSpace); + + // The main class uses the holographic space for updates and rendering. + m_main->SetHolographicSpace(m_holographicSpace); + + MediaSource^ source = MediaSource::CreateFromUri(m_sourceUri); + m_mediaPlayer->MediaOpened += ref new TypedEventHandler(this, &AppView::OnMediaOpened); + m_mediaPlayer->Source = source; + + m_mediaPlayer->IsVideoFrameServerEnabled = true; + m_mediaPlayer->IsLoopingEnabled = true; +} + +// The Load method can be used to initialize scene resources or to load a +// previously saved app state. +void AppView::Load(String^ entryPoint) +{ +} + +// This method is called after the window becomes active. It oversees the +// update, draw, and present loop, and it also oversees window message processing. +void AppView::Run() +{ + CoreWindow^ window = CoreWindow::GetForCurrentThread(); + window->Activate(); + + while (!m_windowClosed) + { + if (m_ShadersNeed) + { + if (!m_ShadersCreated) + { + m_main->CreateVideoShaders(); + m_ShadersCreated = true; + } + } + else + { + window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + continue; + } + + if (m_appViewConsolidated || m_mainWindowReactivated) + { + m_windowClosed = true; + TryCloseWindow(); + } + else + { + window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + if (m_windowVisible && (m_holographicSpace != nullptr)) + { + HolographicFrame^ holographicFrame = m_main->Update(); + + if (m_main->Render(holographicFrame)) + { + // The holographic frame has an API that presents the swap chain for each + // holographic camera. + m_deviceResources->Present(holographicFrame); + } + } + } + } +} + +// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView +// class is torn down while the app is in the foreground. +// This method is not often used, but IFrameworkView requires it and it will be called for +// holographic apps. +void AppView::Uninitialize() +{ + if (m_mediaPlayer != nullptr) + { + m_mediaPlayer->Source = nullptr; + m_mediaPlayer = nullptr; + } + if (m_main != nullptr) + { + m_main->UnregisterHolographicEventHandlers(); + } +} + + +// Application lifecycle event handlers + +// Called when the app view is activated. Activates the app's CoreWindow. +void AppView::OnViewActivated(CoreApplicationView^ sender, IActivatedEventArgs^ args) +{ + // Run() won't start until the CoreWindow is activated. + sender->CoreWindow->Activate(); +} + +void AppView::OnSuspending(Object^ sender, SuspendingEventArgs^ args) +{ + // Save app state asynchronously after requesting a deferral. Holding a deferral + // indicates that the application is busy performing suspending operations. Be + // aware that a deferral may not be held indefinitely; after about five seconds, + // the app will be forced to exit. + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral]() + { + m_deviceResources->Trim(); + + if (m_main != nullptr) + { + m_main->SaveAppState(); + } + + // + // TODO: Insert code here to save your app state. + // + + deferral->Complete(); + }); +} + +void AppView::OnResuming(Object^ sender, Object^ args) +{ + // Restore any data or state that was unloaded on suspend. By default, data + // and state are persisted when resuming from suspend. Note that this event + // does not occur if the app was previously terminated. + + if (m_main != nullptr) + { + m_main->LoadAppState(); + } + + // + // TODO: Insert code here to load your app state. + // +} + + +// Window event handlers + +void AppView::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) +{ + m_windowVisible = args->Visible; +} + +void AppView::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) +{ + m_windowClosed = true; +} + + +// Input event handlers + +void AppView::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ args) +{ + // + // TODO: Bluetooth keyboards are supported by HoloLens. You can use this method for + // keyboard input if you want to support it as an optional input method for + // your holographic app. + // + + if (args->VirtualKey == Windows::System::VirtualKey::Escape) + { + ApplicationViewSwitcher::SwitchAsync(VideoGallery::GetMainViewId(), ApplicationView::GetForCurrentView()->Id, ApplicationViewSwitchingOptions::ConsolidateViews); + } +} + + +void AppView::OnConsolidated(ApplicationView^ sender, ApplicationViewConsolidatedEventArgs^ args) +{ + m_appViewConsolidated = true; + m_windowClosed = true; + TryCloseWindow(); + Uninitialize(); +} + +void AppView::OnMediaOpened(MediaPlayer^ sender, Object^ args) +{ + m_ShadersNeed = true; +} + +void AppView::TryCloseWindow() +{ + CoreWindow^ window = CoreWindow::GetForCurrentThread(); + if (window != nullptr) + { + window->Close(); + } +} diff --git a/Samples/360VideoPlayback/cpp/AppView.h b/Samples/360VideoPlayback/cpp/AppView.h new file mode 100644 index 0000000000..1c91197606 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/AppView.h @@ -0,0 +1,64 @@ +#pragma once + +#include "Common\DeviceResources.h" +#include "360VideoPlaybackMain.h" + +namespace _360VideoPlayback +{ + // IFrameworkView class. Connects the app with the Windows shell and handles application lifecycle events. + ref class AppView sealed : public Windows::ApplicationModel::Core::IFrameworkView + { + public: + AppView(Windows::Foundation::Uri^ sourceUri); + + // IFrameworkView methods. + virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView); + virtual void SetWindow(Windows::UI::Core::CoreWindow^ window); + virtual void Load(Platform::String^ entryPoint); + virtual void Run(); + virtual void Uninitialize(); + static Windows::Media::Playback::MediaPlayer^ GetMediaPlayer(); + + protected: + // Application lifecycle event handlers. + void OnViewActivated(Windows::ApplicationModel::Core::CoreApplicationView^ sender, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args); + void OnMainViewActivated(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ args); + void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args); + void OnResuming(Platform::Object^ sender, Platform::Object^ args); + + // Window event handlers. + void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); + void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args); + + // CoreWindow input event handlers. + void OnKeyPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args); + + private: + std::unique_ptr<_360VideoPlaybackMain> m_main; + std::shared_ptr m_deviceResources; + bool m_windowClosed = false; + bool m_windowVisible = true; + bool m_ShadersNeed = false; + bool m_ShadersCreated = false; + bool m_appViewConsolidated = false; + bool m_mainWindowReactivated = false; + // The holographic space the app will use for rendering. + Windows::Graphics::Holographic::HolographicSpace^ m_holographicSpace = nullptr; + static Windows::Media::Playback::MediaPlayer^ m_mediaPlayer; + void OnConsolidated(Windows::UI::ViewManagement::ApplicationView^ sender, Windows::UI::ViewManagement::ApplicationViewConsolidatedEventArgs^ args); + void OnMediaOpened(Windows::Media::Playback::MediaPlayer^ sender, Platform::Object^ args); + void TryCloseWindow(); + Windows::Foundation::Uri^ m_sourceUri; + }; + + // The entry point for the app. + ref class AppViewSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource + { + public: + AppViewSource(Windows::Foundation::Uri^ sourceUri); + virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView(); + private: + Windows::Foundation::Uri^ m_sourceUri; + }; +} + diff --git a/Samples/360VideoPlayback/cpp/Common/BaseControl.cpp b/Samples/360VideoPlayback/cpp/Common/BaseControl.cpp new file mode 100644 index 0000000000..81d71aafe1 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/BaseControl.cpp @@ -0,0 +1,505 @@ +#include "pch.h" +#include "BaseControl.h" +#include "DirectXHelper.h" +#include "DirectXCollision.h" +#include "..\360VideoPlaybackMain.h" + +using namespace _360VideoPlayback; +using namespace Concurrency; +using namespace DirectX; +using namespace DirectX::TriangleTests; +using namespace D2D1; +using namespace DX; +using namespace Microsoft::WRL; +using namespace Windows::Foundation::Numerics; +using namespace Windows::UI::Input::Spatial; + +const float4 defaultGlassColor = { 0.0f, 0.0f, 0.0f, 0.5f }; +const float4 constantFocusPointColor = { 1.0f, 1.0f, 1.0f, 1.0f }; +const float constantFocusPointRadius = 0.1f; +const float constantFocusPointIntensity = 1.0f; + +BaseControl::BaseControl(const std::shared_ptr geometry) +{ + m_deviceResources = _360VideoPlaybackMain::GetDeviceResources(); + m_isVisible = false; + m_isInitialized = false; + m_isFocused = false; + m_textureWidth = DEFAULT_TEXTURE_SIZE; + m_textureHeight = DEFAULT_TEXTURE_SIZE; + m_geometry = geometry; + m_scale = float3(1.0f, 1.0f, 1.0f); + m_position = float3(0, 0, 0); + m_isVisible = true; + m_transform = float4x4::identity(); + m_parentTransform = float4x4::identity(); + m_relativeIntersectionPoint = float2(0.0f); +} + +void BaseControl::Initialize() +{ + const CD3D11_BUFFER_DESC constantBufferDesc(sizeof(_360VideoPlayback::ModelConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); + + DX::ThrowIfFailed(m_deviceResources->GetD3DDevice()->CreateBuffer( + &constantBufferDesc, + nullptr, + &m_modelConstantBuffer)); + + CalculateInitialSize(); + + AllocateTexture(); + + InitializeFocusPoint(); + + m_isInitialized = true; +} + +void BaseControl::AllocateTexture() +{ + // Create the texture to render the glyph for this control as well as the glyph for the control. + // NOTE: If we want visual fidelity that better matches the distance the user is from the button we should + // have different sizes of textures (and glyphs) depending on how close the user is to the control. + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + auto d3ddevice = m_deviceResources->GetD3DDevice(); + ComPtr cubeTextureSurface; + CD3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc; + D3D11_SAMPLER_DESC samplerDescription; + CD3D11_TEXTURE2D_DESC textureDesc; + FLOAT dpiX; + FLOAT dpiY; + + // Create texture for rendering d2d onto + textureDesc = CD3D11_TEXTURE2D_DESC( + DXGI_FORMAT_B8G8R8A8_UNORM, + m_textureWidth, // Width + m_textureHeight, // Height + 1, // MipLevels + 1, // ArraySize + D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET + ); + + DX::ThrowIfFailed(d3ddevice->CreateTexture2D( + &textureDesc, + nullptr, + &m_texture)); + shaderResourceViewDesc = CD3D11_SHADER_RESOURCE_VIEW_DESC( + m_texture.Get(), + D3D11_SRV_DIMENSION_TEXTURE2D); + DX::ThrowIfFailed(d3ddevice->CreateShaderResourceView( + m_texture.Get(), + &shaderResourceViewDesc, + &m_textureShaderResourceView)); + + d2dContext->GetDpi(&dpiX, &dpiY); + D2D1_BITMAP_PROPERTIES1 bitmapProperties = + D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), + dpiX, + dpiY); + m_texture.As(&cubeTextureSurface); + + DX::ThrowIfFailed(d2dContext->CreateBitmapFromDxgiSurface( + cubeTextureSurface.Get(), + &bitmapProperties, + &m_textureTarget)); + + // create the sampler + ZeroMemory(&samplerDescription, sizeof(D3D11_SAMPLER_DESC)); + samplerDescription.Filter = D3D11_FILTER_ANISOTROPIC; + samplerDescription.AddressU = D3D11_TEXTURE_ADDRESS_BORDER; + samplerDescription.AddressV = D3D11_TEXTURE_ADDRESS_BORDER; + samplerDescription.AddressW = D3D11_TEXTURE_ADDRESS_BORDER; + samplerDescription.MipLODBias = 0.0f; + samplerDescription.MaxAnisotropy = 4; + samplerDescription.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDescription.BorderColor[0] = defaultGlassColor.x; + samplerDescription.BorderColor[1] = defaultGlassColor.y; + samplerDescription.BorderColor[2] = defaultGlassColor.z; + samplerDescription.BorderColor[3] = defaultGlassColor.w; + // allow use of all mip levels + samplerDescription.MinLOD = 0; + samplerDescription.MaxLOD = D3D11_FLOAT32_MAX; + DX::ThrowIfFailed(d3ddevice->CreateSamplerState( + &samplerDescription, + &m_sampler)); + DX::ThrowIfFailed(m_deviceResources->GetD2DFactory()->CreateDrawingStateBlock(&m_stateBlock)); +} + +void BaseControl::Update(const StepTimer& timer, SpatialPointerPose^ cameraPose) +{ + auto scale = m_scale; + const XMMATRIX modelScale = XMMatrixScalingFromVector(XMLoadFloat3(&scale)); + const XMMATRIX modelTranslation = XMMatrixTranslationFromVector(XMLoadFloat3(&m_position)); + const XMMATRIX localTransform = XMMatrixMultiply(modelScale, modelTranslation); + const XMMATRIX parentTransform = XMLoadFloat4x4(&m_parentTransform); + const XMMATRIX modelTransform = XMMatrixMultiply(localTransform, parentTransform); + + XMStoreFloat4x4(&m_transform, modelTransform); + // Update local copy of Constant buffer + XMStoreFloat4x4(&m_modelConstantBufferData.model, XMMatrixTranspose(XMLoadFloat4x4(&m_transform))); + + if (m_isVisible && cameraPose != nullptr) + { + m_isFocused = IsFocusOnControl(XMLoadFloat4x4(&m_transform), cameraPose); + } + + // Update spot light parameters + m_focusPointConstantBufferData.focusPointOrigin = { cameraPose->Head->Position.x, cameraPose->Head->Position.y, cameraPose->Head->Position.z, 1.0f }; + m_focusPointConstantBufferData.focusPointDirection = { cameraPose->Head->ForwardDirection.x, cameraPose->Head->ForwardDirection.y, cameraPose->Head->ForwardDirection.z, 1.0f }; + m_deviceResources->GetD3DDeviceContext()->UpdateSubresource( + m_focusPointConstantBuffer.Get(), + 0, + nullptr, + &m_focusPointConstantBufferData, + 0, + 0); + m_renderItem->SetParentControlInformation(m_isFocused, m_relativeIntersectionPoint, m_textureWidth, m_textureHeight); + m_renderItem->Update(timer, cameraPose); + if (m_renderItem->GetIsRenderPassNeeded()) + { + m_isUITextureRenderNeeded = true; + } +} + +void BaseControl::Render() +{ + if (m_isVisible) + { + UploadGeometryAndShaders(); + ApplyPixelShader(); + // At this point everything should be set, so Draw the objects. + m_deviceResources->GetD3DDeviceContext()->DrawIndexedInstanced( + m_geometry->IndexCount, // Index count per instance. + 2, // Instance count. + 0, // Start index location. + 0, // Base vertex location. + 0); // Start instance location. + } +} + +void BaseControl::UploadGeometryAndShaders() +{ + const auto context = m_deviceResources->GetD3DDeviceContext(); + + // Update the model transform buffer + context->UpdateSubresource( + m_modelConstantBuffer.Get(), + 0, + nullptr, + &m_modelConstantBufferData, + 0, + 0); + + const UINT stride = m_geometry->VertexStride; + const UINT offset = 0; + context->IASetVertexBuffers( + 0, + 1, + m_geometry->VertexBuffer.GetAddressOf(), + &stride, + &offset); + context->IASetIndexBuffer( + m_geometry->IndexBuffer.Get(), + DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short). + 0); + context->IASetPrimitiveTopology(m_geometry->Topology); + context->IASetInputLayout(m_inputLayout.Get()); + + // Attach the vertex shader. + context->VSSetShader( + m_vertexShader.Get(), + nullptr, 0); + // Apply the model constant buffer to the vertex shader. + context->VSSetConstantBuffers( + 0, + 1, + m_modelConstantBuffer.GetAddressOf()); + m_deviceResources->GetD3DDeviceContext()->GSSetShader( + m_geometryShader.Get(), + nullptr, + 0); +} + +void BaseControl::ApplyPixelShader() +{ + m_deviceResources->GetD3DDeviceContext()->PSSetShader( + m_pixelShader.Get(), + nullptr, + 0); + + m_deviceResources->GetD3DDeviceContext()->PSSetConstantBuffers( + 1, /*StartSlot*/ + 1, /*NumBuffers*/ + m_focusPointConstantBuffer.GetAddressOf() + ); + + if (m_isUITextureRenderNeeded) + { + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + d2dContext->SaveDrawingState(m_stateBlock.Get()); + d2dContext->GetTarget(m_d2dContextTargetToRestore.GetAddressOf()); + // Set target to current texture + d2dContext->SetTarget(m_textureTarget.Get()); + d2dContext->BeginDraw(); + ColorF clearColor = D2D1::ColorF(defaultGlassColor.x, defaultGlassColor.y, defaultGlassColor.z, defaultGlassColor.w); + d2dContext->Clear(clearColor); + + m_renderItem->TryRender(); + + // We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device + // is lost. It will be handled during the next call to Present. + auto endDrawHR = d2dContext->EndDraw(); + if (endDrawHR == D2DERR_RECREATE_TARGET) + { + return; + } + // We need to restore the previously set d2dContext target so + // future draw calls draw to the correct place. + d2dContext->SetTarget(m_d2dContextTargetToRestore.Get()); + d2dContext->RestoreDrawingState(m_stateBlock.Get()); + m_isUITextureRenderNeeded = false; + } + + // Tell the shader to use the texture + m_deviceResources->GetD3DDeviceContext()->PSSetShaderResources( + 0, + 1, + m_textureShaderResourceView.GetAddressOf()); + + m_deviceResources->GetD3DDeviceContext()->PSSetSamplers( + 0, + 1, + m_sampler.GetAddressOf()); +} + +void BaseControl::SetParentTransform(float4x4 transform) +{ + m_parentTransform = transform; +} + +void BaseControl::SetScale(float3 value) +{ + m_scale = value; +} + +void BaseControl::SetPosition(float3 value) +{ + m_position = value; +} + + +void BaseControl::InitializeFocusPoint() +{ + const CD3D11_BUFFER_DESC constantBufferDesc(sizeof(FocusPointConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateBuffer( + &constantBufferDesc, + nullptr, + &m_focusPointConstantBuffer)); + + m_focusPointConstantBufferData.focusPointIntensity = { constantFocusPointIntensity, constantFocusPointIntensity, constantFocusPointIntensity, constantFocusPointIntensity }; + m_focusPointConstantBufferData.focusPointColor = { constantFocusPointColor.x, constantFocusPointColor.y, constantFocusPointColor.z, constantFocusPointColor.w }; + m_focusPointConstantBufferData.focusPointRadius = { constantFocusPointRadius, constantFocusPointRadius, constantFocusPointRadius, constantFocusPointRadius }; + m_deviceResources->GetD3DDeviceContext()->UpdateSubresource( + m_focusPointConstantBuffer.Get(), + 0, + nullptr, + &m_focusPointConstantBufferData, + 0, + 0 + ); +} + +void BaseControl::SetIsVisible(bool value) +{ + m_isVisible = value; + if (!m_isVisible) // clear focus if you are turned off + { + m_isFocused = false; + } +} + +void BaseControl::PerformPressedAction() +{ + if (m_renderItem->IsFocused()) + { + m_renderItem->PerformAction(); + } +} + +void BaseControl::ApplyShaders() +{ + task> loadVSTask = DX::ReadDataAsync(L"ms-appx:///GlassVertexShader.cso"); + task createVSTask = loadVSTask.then([this](const std::vector& fileData) + { + std::vector vertexPositionTextureDesc = + { { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + } }; + DX::ThrowIfFailed(m_deviceResources->GetD3DDevice()->CreateVertexShader( + fileData.data(), + fileData.size(), + nullptr, + &m_vertexShader)); + + DX::ThrowIfFailed(m_deviceResources->GetD3DDevice()->CreateInputLayout( + vertexPositionTextureDesc.data(), + static_cast(vertexPositionTextureDesc.size()), + fileData.data(), + fileData.size(), + &m_inputLayout)); + }); + + task> loadPSTask = DX::ReadDataAsync(L"ms-appx:///GlassPixelShader.cso"); + task createPSTask = loadPSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed(m_deviceResources->GetD3DDevice()->CreatePixelShader( + fileData.data(), + fileData.size(), + nullptr, + &m_pixelShader)); + }); + + task> loadGSTask = DX::ReadDataAsync(L"ms-appx:///GlassGeometryShader.cso"); + + task createGSTask = loadGSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed(m_deviceResources->GetD3DDevice()->CreateGeometryShader( + fileData.data(), + fileData.size(), + nullptr, + &m_geometryShader)); + }); + + task shaderTaskGroup = (createPSTask && createVSTask && createGSTask); + task createSphereTask = shaderTaskGroup.then([this]() + { + }); +} + +void BaseControl::SnapInitialSizeToRootElement() +{ + m_snapSizeToRootElement = true; +} + +void BaseControl::CalculateInitialSize() +{ + // Calculate the geometry scale based on the texture dimensions + if (m_snapSizeToRootElement) + { + m_textureWidth = static_cast(m_renderItem->GetElementSize().x); + if (m_textureWidth == 0) + { + m_textureWidth = DEFAULT_TEXTURE_SIZE; + } + m_textureHeight = static_cast(m_renderItem->GetElementSize().y); + if (m_textureHeight == 0) + { + m_textureHeight = DEFAULT_TEXTURE_SIZE; + } + + // Scale the geometry so we fit 128 texture pixels per geometry unit. + float geometryWidth = m_textureWidth / static_cast(DEFAULT_TEXTURE_SIZE); + float geomeryHeight = m_textureHeight / static_cast(DEFAULT_TEXTURE_SIZE); + + m_scale.x *= geometryWidth; + m_scale.y *= geomeryHeight; + } + else + { + // Scale the geometry so we fit 128 texture pixels per geometry unit. + float geometryWidth = m_textureWidth / static_cast(DEFAULT_TEXTURE_SIZE); + float geomeryHeight = m_textureHeight / static_cast(DEFAULT_TEXTURE_SIZE); + + m_scale.x *= geometryWidth; + m_scale.y *= geomeryHeight; + } +} + +void BaseControl::SetRenderElement(std::shared_ptr renderItem) +{ + m_renderItem = renderItem; +} + +bool BaseControl::IsFocusOnControl(const XMMATRIX& transform, SpatialPointerPose^ cameraPose) +{ + // Compute Base Plane Cube Bounds + float4 topLeft = float4(-0.5f, 0.5f, 0.5f, 1.0f); + float4 topRight = float4(0.5f, 0.5f, 0.5f, 1.0f); + float4 bottomRight = float4(0.5f, -0.5f, 0.5f, 1.0f); + float4 bottomLeft = float4(-0.5f, -0.5f, 0.5f, 1.0f); + + XMVECTOR transformedVerts[4]; + transformedVerts[0] = XMVector4Transform(XMLoadFloat4(&topLeft), transform); + transformedVerts[1] = XMVector4Transform(XMLoadFloat4(&topRight), transform); + transformedVerts[2] = XMVector4Transform(XMLoadFloat4(&bottomRight), transform); + transformedVerts[3] = XMVector4Transform(XMLoadFloat4(&bottomLeft), transform); + + // After applying trasformation, W component of the transformed 4 value vectors to be 1 +#ifdef _XM_SSE_INTRINSICS_ + _ASSERTE(transformedVerts[0].m128_f32[3] == 1); +#endif // _XM_SSE_INTRINSICS_ +#ifdef _XM_ARM_NEON_INTRINSICS_ + _ASSERTE(transformedVerts[0].n128_f32[3] == 1); +#endif // _XM_ARM_NEON_INTRINSICS_ + + // This is fine to do Vector3 + XMVECTOR normal = XMVector3Cross(XMVectorSubtract(transformedVerts[3], transformedVerts[0]), XMVectorSubtract(transformedVerts[1], transformedVerts[0])); + + float3 rayPosition = cameraPose->Head->Position; + float3 rayDirection = cameraPose->Head->ForwardDirection; + // If the Dot product between two vectors is less than 0, then the two normals are pointing the same direction + // The normal computed above points in the direction that the front face is facing, so if another vector points the same direction as it, then it is looking at the back side + // When using XMVector3Dot(), the scalar result of the Dot product is copied to all members of the returned XMVECTOR type. To get the result you just need to + // access a member of the XMVECTOR +#ifdef _XM_SSE_INTRINSICS_ + if (XMVector3Dot(XMLoadFloat3(&rayDirection), normal).m128_f32[0] < 0.0f) // only perform intersection if we're looking at the front of the plane +#endif // _XM_SSE_INTRINSICS_ +#ifdef _XM_ARM_NEON_INTRINSICS_ + if (XMVector3Dot(XMLoadFloat3(&rayDirection), normal).n128_f32[0] < 0.0f) // only perform intersection if we're looking at the front of the plane +#endif // _XM_ARM_NEON_INTRINSICS_ + { + float t1IntersectDistance; + float t2IntersectDistance; + float focusedDistance; + bool t1Intersects = Intersects( + XMLoadFloat3(&rayPosition), + XMLoadFloat3(&rayDirection), + transformedVerts[0], + transformedVerts[1], + transformedVerts[3], + OUT t1IntersectDistance); + bool t2Intersects = Intersects( + XMLoadFloat3(&rayPosition), + XMLoadFloat3(&rayDirection), + transformedVerts[3], + transformedVerts[2], + transformedVerts[1], + OUT t2IntersectDistance); + if (t1Intersects || t2Intersects) + { + if (t1Intersects && t2Intersects) + { + focusedDistance = t1IntersectDistance < t2IntersectDistance ? t1IntersectDistance : t2IntersectDistance; + } + else + { + focusedDistance = t1Intersects ? t1IntersectDistance : t2IntersectDistance; + } + float3 intersectionPosition = rayPosition + (focusedDistance * rayDirection); + XMVECTOR modelSpaceIntersectionPoint = XMVector3Transform(XMLoadFloat3(&intersectionPosition), XMMatrixInverse(nullptr, transform)); + +#ifdef _XM_SSE_INTRINSICS_ + m_relativeIntersectionPoint = float2(abs(modelSpaceIntersectionPoint.m128_f32[0] - (-0.5f)), abs(modelSpaceIntersectionPoint.m128_f32[1] - 0.5f)); +#endif // _XM_SSE_INTRINSICS_ +#ifdef _XM_ARM_NEON_INTRINSICS_ + m_relativeIntersectionPoint = float2(abs(modelSpaceIntersectionPoint.n128_f32[0] - m_minXY.x), abs(modelSpaceIntersectionPoint.n128_f32[1] - m_minXY.y)); +#endif // _XM_ARM_NEON_INTRINSICS_ + + return true; + } + } + return false; +} diff --git a/Samples/360VideoPlayback/cpp/Common/BaseControl.h b/Samples/360VideoPlayback/cpp/Common/BaseControl.h new file mode 100644 index 0000000000..2bb6e5e60e --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/BaseControl.h @@ -0,0 +1,79 @@ +#pragma once +#include "CameraResources.h" +#include "DeviceResources.h" +#include "BaseElement.h" +#include "MeshGeometry.h" +#include "StepTimer.h" +#include "BaseElement.h" + +#define DEFAULT_TEXTURE_SIZE 128 + +namespace DX +{ + class BaseControl + { + public: + BaseControl( + const std::shared_ptr geometry = MeshGeometry::MakeTexturedCube()); + // Whether to use the child element to determine the initial texture dimensions and geometry scale. + void SnapInitialSizeToRootElement(); + void Initialize(); + void Update(const DX::StepTimer& timer, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose); + void Render(); + void SetScale(Windows::Foundation::Numerics::float3 value); + void SetPosition(Windows::Foundation::Numerics::float3 value); + void SetParentTransform(Windows::Foundation::Numerics::float4x4 transform); + void ApplyShaders(); + // Render stage overrides + bool IsFocused() { return m_isFocused; }; + void SetIsVisible(bool value); + void PerformPressedAction(); + void SetRenderElement(std::shared_ptr renderItem); + void SetTextureWidth(UINT width) { m_textureWidth = width; m_calculateTextureDimensionsFromScale = false; } + void SetTextureHeight(UINT height) { m_textureHeight = height; m_calculateTextureDimensionsFromScale = false; } + + private: + // Calculate the initial texture dimensions and geometry scale. + virtual void CalculateInitialSize(); + void AllocateTexture(); + void UploadGeometryAndShaders(); + void InitializeFocusPoint(); + void ApplyPixelShader(); + + bool m_isInitialized; + bool m_isFocused; + bool m_isVisible; + bool m_isUITextureRenderNeeded = true; + Microsoft::WRL::ComPtr m_focusPointConstantBuffer; + _360VideoPlayback::FocusPointConstantBuffer m_focusPointConstantBufferData; + float m_calculateTextureDimensionsFromScale = true; + UINT m_textureWidth; + UINT m_textureHeight; + // Resources + std::shared_ptr m_deviceResources; + std::shared_ptr m_renderItem; + bool m_snapSizeToRootElement = false; + std::shared_ptr m_geometry; + _360VideoPlayback::ModelConstantBuffer m_modelConstantBufferData; + Microsoft::WRL::ComPtr m_modelConstantBuffer; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_pixelShader; + Microsoft::WRL::ComPtr m_geometryShader; + Windows::Foundation::Numerics::float3 m_scale; + Windows::Foundation::Numerics::float4 m_rotation; + Windows::Foundation::Numerics::float3 m_position; + Windows::Foundation::Numerics::float4x4 m_transform; + // Parent Transform for objects within a parent + Windows::Foundation::Numerics::float4x4 m_parentTransform; + // Status + Windows::Foundation::Numerics::float2 m_relativeIntersectionPoint; + bool IsFocusOnControl(const DirectX::XMMATRIX& transform, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose); + Microsoft::WRL::ComPtr m_d2dContextTargetToRestore; + Microsoft::WRL::ComPtr m_sampler; + Microsoft::WRL::ComPtr m_stateBlock; + Microsoft::WRL::ComPtr m_texture; + Microsoft::WRL::ComPtr m_textureTarget; + Microsoft::WRL::ComPtr m_textureShaderResourceView; + }; +} diff --git a/Samples/360VideoPlayback/cpp/Common/BaseElement.cpp b/Samples/360VideoPlayback/cpp/Common/BaseElement.cpp new file mode 100644 index 0000000000..3166d24dc1 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/BaseElement.cpp @@ -0,0 +1,480 @@ +#include "pch.h" +#include "BaseElement.h" +#include "DirectXHelper.h" +#include "..\360VideoPlaybackMain.h" + +using namespace _360VideoPlayback; +using namespace D2D1; +using namespace DirectX; +using namespace DX; +using namespace Microsoft::WRL; +using namespace Platform; +using namespace Windows::Foundation::Numerics; +using namespace Windows::UI::Input::Spatial; + +const float MAX_TEXT_LAYOUT_SIZE = 500; + +BaseElement::BaseElement() : + m_isInitialized(false), + m_transformRecalculationNeeded(false), + m_isRenderPassNeeded(true), + m_isVisible(true), + m_translation(0.0f, 0.0f), + m_transformedTranslation(0.0f, 0.0f), + m_parentTranslation(0.0f, 0.0f), + m_elementSize(0.0f, 0.0f), + m_ignoreLayout(true), + m_brush(nullptr) +{ + m_deviceResources = _360VideoPlaybackMain::GetDeviceResources(); +} +void BaseElement::ArrangeElements() +{ + float maxWidth = 0.0f; + float maxHeight = 0.0f; + float containerWidth = 0.0f; + float containerHeight = 0.0f; + + // Arrange Children And Compute whole ContainerSize + for (const auto& element : m_childElements) + { + if (!element->GetIgnoreLayout()) + { + // Skip stuff that doesn't want to be stacked in its container (like the focus rect). + continue; + } + + maxWidth = max(maxWidth, element->GetElementSize().x); + maxHeight = max(maxHeight, element->GetElementSize().y); + + if (m_isLayoutHorizontal) + { + containerWidth += element->GetElementSize().x + element->GetElementMargin().left + element->GetElementMargin().right; + containerHeight = max(containerHeight, element->GetElementSize().y + element->GetElementMargin().top + element->GetElementMargin().bottom); + } + else + { + containerWidth = max(containerWidth, element->GetElementSize().x + element->GetElementMargin().left + element->GetElementMargin().right); + containerHeight = max(containerHeight, element->GetElementSize().y + element->GetElementMargin().top + element->GetElementMargin().bottom); + } + } + + float minWidth = m_elementSize.x; + float minHeight = m_elementSize.y; + + containerWidth = max(minWidth, containerWidth); + containerHeight = max(minHeight, containerHeight); + m_elementSize.x = containerWidth; + m_elementSize.y = containerHeight; + + // Actually position the elements. We need to do this after calculating the container size so we can center the elements. + float currentStackPosition = 0.0; + for (const auto& element : m_childElements) + { + if (!element->GetIgnoreLayout()) + { + // Skip stuff that doesn't want to be stacked in its container (like the focus rect). + continue; + } + + if (m_isLayoutHorizontal) + { + // Position element along the stacking axis + float elementPositionX = currentStackPosition + element->GetElementMargin().left; + + // Center the element so the stacking axis bisects the element + float elementPositionY = (containerHeight / 2.0f) - (element->GetElementSize().y / 2.0f); + + // Adjust centered position to respect top margin + if (elementPositionY < element->GetElementMargin().top) + { + elementPositionY = element->GetElementMargin().top; + } + + // Adjust centered position to respect bottom margin + if (elementPositionY + element->GetElementSize().y + element->GetElementMargin().bottom > containerHeight) + { + elementPositionY = containerHeight - element->GetElementSize().y - element->GetElementMargin().bottom; + } + + element->SetTranslation({ elementPositionX, elementPositionY }); + + currentStackPosition += element->GetElementMargin().left + element->GetElementSize().x + element->GetElementMargin().right; + } + else + { + float elementPositionX = (containerWidth / 2.0f) - (element->GetElementSize().x / 2.0f); + float elementPositionY = (containerHeight / 2.0f) - (element->GetElementSize().y / 2.0f); + element->SetTranslation({ elementPositionX, elementPositionY }); + } + } +} + +void BaseElement::Initialize() +{ + for (const auto& child : m_childElements) + { + child->Initialize(); + } + m_isInitialized = true; +} + +void BaseElement::SetBrush(ID2D1SolidColorBrush* brush) +{ + m_brush = brush; + m_isRenderPassNeeded = true; +} + +void BaseElement::Update(const DX::StepTimer& timer, SpatialPointerPose^ cameraPose) +{ + // If one of BaseElement's transforms have changed or its parent's transforms have been updated + // we will recalculate the BaseElement's transforms and tell its children to update their transforms + // as well. + // NOTE: For BaseElement's with complex nested children we should try not to update the transforms too + // frequently because this can cause perf issues. (fonts, textures, and glyphs may need to be resized) + if (m_transformRecalculationNeeded) + { + m_transformedTranslation = m_translation + m_parentTranslation; + m_transformMatrix = D2D1::Matrix3x2F::Translation(m_transformedTranslation.x, m_transformedTranslation.y); + + // Update children with updated transforms + for (const auto& child : m_childElements) + { + child->SetParentTransform(m_transformedTranslation); + } + + m_transformRecalculationNeeded = false; + m_isRenderPassNeeded = true; + } + + if (!m_isInitialized) + { + Initialize(); + } + + for (const auto& child : m_childElements) + { + child->Update(timer, cameraPose); + m_isRenderPassNeeded |= child->GetIsRenderPassNeeded(); + } +} + +void BaseElement::TryRender() +{ + if (m_isVisible) + { + Render(); + + for (const auto& child : m_childElements) + { + child->TryRender(); + } + } + + m_isRenderPassNeeded = false; +} + +void BaseElement::Render() +{ +} + +void BaseElement::SetTranslation(float2 translation) +{ + m_transformRecalculationNeeded |= m_translation != translation; + m_translation = translation; +} + +void BaseElement::SetParentTransform(float2 translation) +{ + m_transformRecalculationNeeded |= (m_parentTranslation != translation); + m_parentTranslation = translation; +} + +void BaseElement::AddChildElement(const std::shared_ptr& childElement) +{ + childElement->SetParentTransform(m_transformedTranslation); + m_childElements.push_back(childElement); +} + +void BaseElement::SetIsVisible(bool visible) +{ + m_isRenderPassNeeded |= (visible != m_isVisible); + m_isVisible = visible; +}; + +FocusableElement::FocusableElement() : + BaseElement(), + m_isFocused(false), + m_isParentFocused(false), + m_isFocusIntersectionCalculated(false), + m_elementCoordIntersectionPoint({ 0.0f,0.0f }), + m_parentTextureWidth(0), + m_parentTextureHeight(0), + m_parentFocusedPosition(float2(0.0f)) +{ +} + +void FocusableElement::Update(const StepTimer& timer, SpatialPointerPose^ cameraPose) +{ + __super::Update(timer, cameraPose); + if (m_isParentFocused) + { + bool isFocused = false; + + float2 minBounds = m_transformedTranslation; + float2 maxBounds = m_transformedTranslation + m_elementSize; + // The focused position is relative to the model size, so we need to scale it to the texture size + float2 textureScaledParentFocusedPosition = float2(m_parentFocusedPosition.x * m_parentTextureWidth, m_parentFocusedPosition.y * m_parentTextureHeight); + if (minBounds.x <= textureScaledParentFocusedPosition.x && minBounds.y <= textureScaledParentFocusedPosition.y && + textureScaledParentFocusedPosition.x <= maxBounds.x && textureScaledParentFocusedPosition.y <= maxBounds.y) + { + isFocused = true; + } + + if (m_isFocused != isFocused) + { + m_isRenderPassNeeded = true; // If this is a change in focus, mark we need a render pass + m_isFocused = isFocused; + FocusUpdate(); + } + + if (m_isFocused && m_isFocusIntersectionCalculated) // This is mainly used by Slider Elements, which is why its behind a flag + { + m_elementCoordIntersectionPoint = float2( + textureScaledParentFocusedPosition.x - (m_parentTextureWidth - m_elementSize.x), + textureScaledParentFocusedPosition.y - (m_parentTextureHeight - m_elementSize.y)); + } + } + else + { + m_isFocused = false; + } +} + +void FocusableElement::SetParentControlInformation(bool focused, Windows::Foundation::Numerics::float2 focusedPosition, UINT parentTextureWidth, UINT parentTextureHeight) +{ + m_isParentFocused = focused; + if (!m_isParentFocused) + { + if (m_isFocused) + { + m_isFocused = false; + FocusUpdate(); + } + } + m_parentFocusedPosition = focusedPosition; + m_parentTextureWidth = parentTextureWidth; + m_parentTextureHeight = parentTextureHeight; +} + +Text::Text(std::wstring text, FLOAT fontSize, DWRITE_FONT_WEIGHT fontWeight) : + m_transformedFontSize(fontSize), + m_fontWeight(fontWeight) +{ + this->SetText(text); +} + +void Text::Render() +{ + D2D1_SIZE_F renderTargetSize = m_deviceResources->GetD2DDeviceContext()->GetSize(); + D2D1_POINT_2F textOrigin{ 0.0, 0.0 }; + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + d2dContext->SetTransform(D2D1::Matrix3x2F::Translation(m_transformedTranslation.x, m_transformedTranslation.y)); + d2dContext->DrawTextLayout(textOrigin, m_textLayout.Get(), m_brush.Get()); + d2dContext->SetTransform(D2D1::IdentityMatrix()); +} + +void Text::CreateTextContext() +{ + DX::ThrowIfFailed(m_deviceResources->GetDWriteFactory()->CreateTextFormat( + L"Segoe UI", + nullptr, + m_fontWeight, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + m_transformedFontSize, + Windows::Globalization::ApplicationLanguages::Languages->GetAt(0)->Data(), + &m_textFormat)); + + m_textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); + + DX::ThrowIfFailed(m_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING)); + DX::ThrowIfFailed(m_deviceResources->GetDWriteFactory()->CreateTextLayout( + m_text.data(), + static_cast(m_text.size()), + m_textFormat.Get(), + MAX_TEXT_LAYOUT_SIZE, + MAX_TEXT_LAYOUT_SIZE, + &m_textLayout)); + + DWRITE_TEXT_METRICS textMetrics; + m_textLayout->GetMetrics(&textMetrics); + m_elementSize = { textMetrics.width, textMetrics.height }; + m_isRenderPassNeeded = true; +} + +void Text::SetText(std::wstring text) +{ + if (text != m_text) + { + m_text = text; + this->CreateTextContext(); + } +} + +Line::Line(FLOAT strokeThickness) : + m_strokeThickness(strokeThickness) +{ + m_lineStart = D2D1::Point2F(0.0f, 0.0f); + m_lineEnd = D2D1::Point2F(1.0f, 0.0f); +} + +void Line::Render() +{ + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + d2dContext->SetTransform(m_transformMatrix); + d2dContext->DrawLine(m_lineStart, m_lineEnd, m_brush.Get(), m_strokeThickness); + d2dContext->SetTransform(D2D1::IdentityMatrix()); +} + +void Line::SetStartPoint(D2D1_POINT_2F& point) +{ + m_transformRecalculationNeeded |= (point.x != m_lineStart.x || point.y != m_lineStart.y); + m_lineStart = point; +} + +void Line::SetEndPoint(D2D1_POINT_2F& point) +{ + m_transformRecalculationNeeded |= (point.x != m_lineEnd.x || point.y != m_lineEnd.y); + m_lineEnd = point; +} + +Ellipse::Ellipse(FLOAT radiusX, FLOAT radiusY, FLOAT strokeThickness, ColorF brushColor) : + BaseElement(), + m_radiusX(radiusX), + m_radiusY(radiusY), + m_strokeThickness(strokeThickness), + m_brushColor(brushColor) +{ + this->SetRadius(radiusX, radiusY); +} + +void Ellipse::Initialize() +{ + if (m_brush == nullptr) + { + const auto d2dcontext = m_deviceResources->GetD2DDeviceContext(); + DX::ThrowIfFailed(d2dcontext->CreateSolidColorBrush( + m_brushColor, + &m_brush)); + } + __super::Initialize(); +} + +void Ellipse::SetRadius(FLOAT x, FLOAT y) +{ + m_radiusX = x; m_radiusY = y; + m_elementSize = { m_radiusX * 2.0f, m_radiusY * 2.0f }; + m_ellipse = D2D1::Ellipse(D2D1::Point2F(m_radiusX, m_radiusY), m_radiusX, m_radiusY); +} + +void Ellipse::Render() +{ + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + d2dContext->SetTransform(m_transformMatrix); + d2dContext->DrawEllipse(m_ellipse, m_brush.Get(), m_strokeThickness); + d2dContext->SetTransform(D2D1::IdentityMatrix()); +} + +FilledEllipse::FilledEllipse(FLOAT radiusX, FLOAT radiusY, ColorF brushColor) : + BaseElement(), + m_radiusX(radiusX), + m_radiusY(radiusY), + m_brushColor(brushColor) +{ + this->SetRadius(radiusX, radiusY); +} + +void FilledEllipse::SetRadius(FLOAT x, FLOAT y) +{ + m_radiusX = x; m_radiusY = y; + m_elementSize = { m_radiusX * 2.0f, m_radiusY * 2.0f }; + m_ellipse = D2D1::Ellipse(D2D1::Point2F(m_radiusX, m_radiusY), m_radiusX, m_radiusY); +} + +void FilledEllipse::Initialize() +{ + if (m_brush == nullptr) + { + const auto d2dcontext = m_deviceResources->GetD2DDeviceContext(); + d2dcontext->CreateSolidColorBrush( + m_brushColor, + &m_brush); + } + __super::Initialize(); +} + +void FilledEllipse::Render() +{ + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + d2dContext->SetTransform(m_transformMatrix); + d2dContext->FillEllipse(m_ellipse, m_brush.Get()); + d2dContext->SetTransform(D2D1::IdentityMatrix()); +} + +Rectangle::Rectangle(FLOAT width, FLOAT height, FLOAT strokeThickness, ColorF brushColor) : + BaseElement(), + m_rect(D2D1::RectF(0.0f, 0.0f, width, height)), + m_strokeThickness(strokeThickness), + m_brushColor(brushColor) +{ +} + +void Rectangle::Initialize() +{ + if (m_brush == nullptr) + { + const auto d2dcontext = m_deviceResources->GetD2DDeviceContext(); + DX::ThrowIfFailed(d2dcontext->CreateSolidColorBrush( + m_brushColor, + &m_brush)); + } + + __super::Initialize(); +} + +void Rectangle::Render() +{ + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + d2dContext->SetTransform(m_transformMatrix); + d2dContext->DrawRectangle(m_rect, m_brush.Get(), m_strokeThickness); + d2dContext->SetTransform(D2D1::IdentityMatrix()); +} + +FilledRectangle::FilledRectangle(FLOAT width, FLOAT height, ColorF brushColor) : + BaseElement(), + m_rect(D2D1::RectF(0.0f, 0.0f, width, height)), + m_brushColor(brushColor) +{ +} + +void FilledRectangle::Initialize() +{ + if (m_brush == nullptr) + { + const auto d2dcontext = m_deviceResources->GetD2DDeviceContext(); + d2dcontext->CreateSolidColorBrush( + m_brushColor, + &m_brush + ); + } + __super::Initialize(); +} + +void FilledRectangle::Render() +{ + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + d2dContext->SetTransform(m_transformMatrix); + d2dContext->FillRectangle(m_rect, m_brush.Get()); + d2dContext->SetTransform(D2D1::IdentityMatrix()); +} diff --git a/Samples/360VideoPlayback/cpp/Common/BaseElement.h b/Samples/360VideoPlayback/cpp/Common/BaseElement.h new file mode 100644 index 0000000000..e771206f6d --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/BaseElement.h @@ -0,0 +1,217 @@ +#pragma once +#include "StepTimer.h" +#include "DeviceResources.h" + +#define FONT_SIZE 10.667f +#define BUTTON_SIZE 64 + +namespace DX +{ + // Margin in terms of left, top, right, bottom. + // "Pushes" the element away from its sibling elements and away from boundaries of its parent container. + // Does not change the intristic size of the element; the parent element will take the margin of its child elements into consideration during arrangement. + struct ElementMargin + { + ElementMargin() = default; + + ElementMargin(float l, float t, float r, float b) : + left(l), + top(t), + right(r), + bottom(b) + { + _ASSERTE(left >= 0.0f); + _ASSERTE(top >= 0.0f); + _ASSERTE(right >= 0.0f); + _ASSERTE(bottom >= 0.0f); + } + + float left = 0.0f; + float top = 0.0f; + float right = 0.0f; + float bottom = 0.0f; + }; + + class BaseElement + { + public: + BaseElement(); + virtual ~BaseElement() = default; + virtual void Initialize(); + virtual void Update(const DX::StepTimer& timer, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose); + void TryRender(); + void SetIsVisible(bool visible); + bool GetIsVisible() { return m_isVisible; }; + void SetElementSize(Windows::Foundation::Numerics::float2 size) { m_elementSize = size; } + bool GetIsRenderPassNeeded() { return m_isRenderPassNeeded; }; + Windows::Foundation::Numerics::float2 GetElementSize() { return m_elementSize; }; + // NOTE: This translation is the translation of the 2D BaseElement from the texture's origin + virtual void SetTranslation(Windows::Foundation::Numerics::float2 translation); + void SetParentTransform(Windows::Foundation::Numerics::float2 translation); + void AddChildElement(const std::shared_ptr& childElement); + void SetElementMargin(ElementMargin margin) { m_elementMargin = margin; }; + void SetIgnoreLayout(bool ignoreLayout) { m_ignoreLayout = ignoreLayout; } + ElementMargin& GetElementMargin() { return m_elementMargin; }; + bool GetIgnoreLayout() { return m_ignoreLayout; }; + void SetLayoutHorizontal(bool isLayoutHorizontal) { m_isLayoutHorizontal = isLayoutHorizontal; } + void SetBrush(ID2D1SolidColorBrush* brush); + // Applies layout properties down the element tree. + // ArrangeElements must be manually called any time: + // - The element's layout properties have changed (layout direction, content alignment, etc.) + // - Any child's layout properties are updated. + // - Children elements are added or removed. + virtual void ArrangeElements(); + + protected: + virtual void Render(); + + bool m_isInitialized; + bool m_transformRecalculationNeeded; + bool m_isRenderPassNeeded; + bool m_isVisible; + bool m_ignoreLayout; + + Windows::Foundation::Numerics::float2 m_translation; + Windows::Foundation::Numerics::float2 m_transformedTranslation; + Windows::Foundation::Numerics::float2 m_parentTranslation; + // Width and height dimensions + Windows::Foundation::Numerics::float2 m_elementSize; + D2D1::Matrix3x2F m_transformMatrix = D2D1::Matrix3x2F::Identity(); + bool m_isLayoutHorizontal = false; + ElementMargin m_elementMargin; + + std::shared_ptr m_deviceResources; + std::vector> m_childElements; + Microsoft::WRL::ComPtr m_brush; + // Cached pointer to device resources. + }; + + // Manage focus across multiple Elements + class FocusableElement : public BaseElement + { + public: + FocusableElement(); + virtual ~FocusableElement() = default; + virtual void Update(const DX::StepTimer& timer, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose) override; + virtual bool IsFocused() { return m_isFocused; }; + virtual void PerformAction() {}; + virtual void SetParentControlInformation(bool focused, Windows::Foundation::Numerics::float2 focusedPosition, UINT parentTextureWidth, UINT parentTextureHeight); + virtual void FocusUpdate() {}; + protected: + bool m_isFocused; + bool m_isParentFocused; + // If an Element needs to know where the intersection occurs relative to its coordinates, set m_isSubElementIntersectionInfoNeeded true + // For example, the parentTexture might be 100x100 and your Element might be 50x50 centered on the texture and lets say the Focus is also the center of the texture. + // For most Elements, simply knowing that the coordinate 50,50 is inside the Element and thus its focused. But, some Elements such as Sliders need to know + // Where in its Element Coordinate system did the intersection occur (so you can adjust the seekbar). In this case, by turning this parameter on, it will store the + // Element Coordinate Intersection into the below field. So sticking with the above example, it would store 25,25 since the Element is centered in the Parent Texture + bool m_isFocusIntersectionCalculated; + Windows::Foundation::Numerics::float2 m_elementCoordIntersectionPoint; + UINT m_parentTextureWidth; + UINT m_parentTextureHeight; + Windows::Foundation::Numerics::float2 m_parentFocusedPosition; + }; + + class Text : public BaseElement + { + public: + Text(std::wstring text, + FLOAT fontSize, + DWRITE_FONT_WEIGHT fontWeight = DWRITE_FONT_WEIGHT_ULTRA_BOLD); + void SetText(std::wstring text); + + protected: + virtual void Render() override; + + private: + void CreateTextContext(); + std::wstring m_text; + Microsoft::WRL::ComPtr m_textFormat; + Microsoft::WRL::ComPtr m_textLayout; + DWRITE_FONT_WEIGHT m_fontWeight; + float m_transformedFontSize; + }; + + class Line : public BaseElement + { + public: + Line(FLOAT strokeThickness); + void SetStartPoint(D2D1_POINT_2F& point); + void SetEndPoint(D2D1_POINT_2F& point); + + protected: + virtual void Render() override; + + private: + FLOAT m_strokeThickness; + D2D1_POINT_2F m_lineStart; + D2D1_POINT_2F m_lineEnd; + }; + + class Ellipse : public BaseElement + { + public: + Ellipse(FLOAT radiusX, FLOAT radiusY, FLOAT strokeThickness, D2D1::ColorF brushColor); + virtual void Initialize() override; + void SetRadius(FLOAT x, FLOAT y); + + protected: + virtual void Render() override; + + private: + D2D1::ColorF m_brushColor; + FLOAT m_strokeThickness; + FLOAT m_radiusX; + FLOAT m_radiusY; + D2D1_ELLIPSE m_ellipse; + }; + + class FilledEllipse : public BaseElement + { + public: + FilledEllipse(FLOAT radiusX, FLOAT radiusY, D2D1::ColorF brushColor); + virtual void Initialize() override; + void SetRadius(FLOAT x, FLOAT y); + + protected: + virtual void Render() override; + + private: + D2D1::ColorF m_brushColor; + FLOAT m_radiusX; + FLOAT m_radiusY; + D2D1_ELLIPSE m_ellipse; + }; + + class Rectangle : public BaseElement + { + public: + Rectangle(FLOAT width, FLOAT height, FLOAT strokeThickness, D2D1::ColorF brushColor); + virtual void Initialize() override; + void SetRect(const D2D1_RECT_F& rect) { m_rect = rect; } + FLOAT GetStrokeThickness() { return m_strokeThickness; }; + + protected: + virtual void Render() override; + + private: + D2D1_RECT_F m_rect; + FLOAT m_strokeThickness; + D2D1::ColorF m_brushColor; + }; + + class FilledRectangle : public BaseElement + { + public: + FilledRectangle(FLOAT width, FLOAT height, D2D1::ColorF brushColor); + virtual void Initialize() override; + void SetRect(const D2D1_RECT_F& rect) { m_rect = rect; } + + protected: + virtual void Render() override; + + private: + D2D1_RECT_F m_rect; + D2D1::ColorF m_brushColor; + }; +} diff --git a/Samples/360VideoPlayback/cpp/Common/CameraResources.cpp b/Samples/360VideoPlayback/cpp/Common/CameraResources.cpp new file mode 100644 index 0000000000..169d63c110 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/CameraResources.cpp @@ -0,0 +1,274 @@ +#include "pch.h" + +#include "CameraResources.h" +#include "Common\DirectXHelper.h" +#include "DeviceResources.h" +#include + +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace Windows::Graphics::DirectX::Direct3D11; +using namespace Windows::Graphics::Holographic; +using namespace Windows::Perception::Spatial; + +DX::CameraResources::CameraResources(HolographicCamera^ camera) : + m_holographicCamera(camera), + m_isStereo(camera->IsStereo), + m_d3dRenderTargetSize(camera->RenderTargetSize) +{ + m_d3dViewport = CD3D11_VIEWPORT( + 0.f, 0.f, + m_d3dRenderTargetSize.Width, + m_d3dRenderTargetSize.Height + ); +}; + +// Updates resources associated with a holographic camera's swap chain. +// The app does not access the swap chain directly, but it does create +// resource views for the back buffer. +void DX::CameraResources::CreateResourcesForBackBuffer( + DX::DeviceResources* pDeviceResources, + HolographicCameraRenderingParameters^ cameraParameters + ) +{ + const auto device = pDeviceResources->GetD3DDevice(); + + // Get the WinRT object representing the holographic camera's back buffer. + IDirect3DSurface^ surface = cameraParameters->Direct3D11BackBuffer; + + // Get a DXGI interface for the holographic camera's back buffer. + // Holographic cameras do not provide the DXGI swap chain, which is owned + // by the system. The Direct3D back buffer resource is provided using WinRT + // interop APIs. + ComPtr resource; + ThrowIfFailed( + GetDXGIInterfaceFromObject(surface, IID_PPV_ARGS(&resource)) + ); + + // Get a Direct3D interface for the holographic camera's back buffer. + ComPtr cameraBackBuffer; + ThrowIfFailed( + resource.As(&cameraBackBuffer) + ); + + // Determine if the back buffer has changed. If so, ensure that the render target view + // is for the current back buffer. + if (m_d3dBackBuffer.Get() != cameraBackBuffer.Get()) + { + // This can change every frame as the system moves to the next buffer in the + // swap chain. This mode of operation will occur when certain rendering modes + // are activated. + m_d3dBackBuffer = cameraBackBuffer; + + // Create a render target view of the back buffer. + // Creating this resource is inexpensive, and is better than keeping track of + // the back buffers in order to pre-allocate render target views for each one. + DX::ThrowIfFailed( + device->CreateRenderTargetView( + m_d3dBackBuffer.Get(), + nullptr, + &m_d3dRenderTargetView + ) + ); + + // Get the DXGI format for the back buffer. + // This information can be accessed by the app using CameraResources::GetBackBufferDXGIFormat(). + D3D11_TEXTURE2D_DESC backBufferDesc; + m_d3dBackBuffer->GetDesc(&backBufferDesc); + m_dxgiFormat = backBufferDesc.Format; + + // Check for render target size changes. + Windows::Foundation::Size currentSize = m_holographicCamera->RenderTargetSize; + if (m_d3dRenderTargetSize != currentSize) + { + // Set render target size. + m_d3dRenderTargetSize = currentSize; + + // A new depth stencil view is also needed. + m_d3dDepthStencilView.Reset(); + } + } + + // Refresh depth stencil resources, if needed. + if (m_d3dDepthStencilView == nullptr) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + DXGI_FORMAT_D16_UNORM, + static_cast(m_d3dRenderTargetSize.Width), + static_cast(m_d3dRenderTargetSize.Height), + m_isStereo ? 2 : 1, // Create two textures when rendering in stereo. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + DX::ThrowIfFailed( + device->CreateTexture2D( + &depthStencilDesc, + nullptr, + &depthStencil + ) + ); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc( + m_isStereo ? D3D11_DSV_DIMENSION_TEXTURE2DARRAY : D3D11_DSV_DIMENSION_TEXTURE2D + ); + DX::ThrowIfFailed( + device->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + &m_d3dDepthStencilView + ) + ); + } + + // Create the constant buffer, if needed. + if (m_viewProjectionConstantBuffer == nullptr) + { + // Create a constant buffer to store view and projection matrices for the camera. + CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); + DX::ThrowIfFailed( + device->CreateBuffer( + &constantBufferDesc, + nullptr, + &m_viewProjectionConstantBuffer + ) + ); + } +} + +// Releases resources associated with a back buffer. +void DX::CameraResources::ReleaseResourcesForBackBuffer(DX::DeviceResources* pDeviceResources) +{ + const auto context = pDeviceResources->GetD3DDeviceContext(); + + // Release camera-specific resources. + m_d3dBackBuffer.Reset(); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_viewProjectionConstantBuffer.Reset(); + + // Ensure system references to the back buffer are released by clearing the render + // target from the graphics pipeline state, and then flushing the Direct3D context. + ID3D11RenderTargetView* nullViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = { nullptr }; + context->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); + context->Flush(); +} + +// Updates the view/projection constant buffer for a holographic camera. +void DX::CameraResources::UpdateViewProjectionBuffer( + std::shared_ptr deviceResources, + HolographicCameraPose^ cameraPose, + SpatialCoordinateSystem^ coordinateSystem + ) +{ + // The system changes the viewport on a per-frame basis for system optimizations. + m_d3dViewport = CD3D11_VIEWPORT( + cameraPose->Viewport.Left, + cameraPose->Viewport.Top, + cameraPose->Viewport.Width, + cameraPose->Viewport.Height + ); + + // The projection transform for each frame is provided by the HolographicCameraPose. + HolographicStereoTransform cameraProjectionTransform = cameraPose->ProjectionTransform; + + // Get a container object with the view and projection matrices for the given + // pose in the given coordinate system. + Platform::IBox^ viewTransformContainer = cameraPose->TryGetViewTransform(coordinateSystem); + + // If TryGetViewTransform returns a null pointer, that means the pose and coordinate + // system cannot be understood relative to one another; content cannot be rendered + // in this coordinate system for the duration of the current frame. + // This usually means that positional tracking is not active for the current frame, in + // which case it is possible to use a SpatialLocatorAttachedFrameOfReference to render + // content that is not world-locked instead. + DX::ViewProjectionConstantBuffer viewProjectionConstantBufferData; + bool viewTransformAcquired = viewTransformContainer != nullptr; + if (viewTransformAcquired) + { + // Otherwise, the set of view transforms can be retrieved. + HolographicStereoTransform viewCoordinateSystemTransform = viewTransformContainer->Value; + + // Update the view matrices. Holographic cameras (such as Microsoft HoloLens) are + // constantly moving relative to the world. The view matrices need to be updated + // every frame. + XMStoreFloat4x4( + &viewProjectionConstantBufferData.viewProjection[0], + XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Left) * XMLoadFloat4x4(&cameraProjectionTransform.Left)) + ); + XMStoreFloat4x4( + &viewProjectionConstantBufferData.viewProjection[1], + XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Right) * XMLoadFloat4x4(&cameraProjectionTransform.Right)) + ); + } + + // Use the D3D device context to update Direct3D device-based resources. + const auto context = deviceResources->GetD3DDeviceContext(); + + // Loading is asynchronous. Resources must be created before they can be updated. + if (context == nullptr || m_viewProjectionConstantBuffer == nullptr || !viewTransformAcquired) + { + m_framePending = false; + } + else + { + // Update the view and projection matrices. + context->UpdateSubresource( + m_viewProjectionConstantBuffer.Get(), + 0, + nullptr, + &viewProjectionConstantBufferData, + 0, + 0 + ); + + m_framePending = true; + } +} + +// Gets the view-projection constant buffer for the HolographicCamera and attaches it +// to the shader pipeline. +bool DX::CameraResources::AttachViewProjectionBuffer( + std::shared_ptr deviceResources + ) +{ + // This method uses Direct3D device-based resources. + const auto context = deviceResources->GetD3DDeviceContext(); + + // Loading is asynchronous. Resources must be created before they can be updated. + // Cameras can also be added asynchronously, in which case they must be initialized + // before they can be used. + if (context == nullptr || m_viewProjectionConstantBuffer == nullptr || m_framePending == false) + { + return false; + } + + // Set the viewport for this camera. + context->RSSetViewports(1, &m_d3dViewport); + + // Send the constant buffer to the vertex shader. + context->VSSetConstantBuffers( + 1, + 1, + m_viewProjectionConstantBuffer.GetAddressOf() + ); + + // The template includes a pass-through geometry shader that is used by + // default on systems that don't support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer extension. The shader + // will be enabled at run-time on systems that require it. + // If your app will also use the geometry shader for other tasks and those + // tasks require the view/projection matrix, uncomment the following line + // of code to send the constant buffer to the geometry shader as well. + /*context->GSSetConstantBuffers( + 1, + 1, + m_viewProjectionConstantBuffer.GetAddressOf() + );*/ + + m_framePending = false; + + return true; +} diff --git a/Samples/360VideoPlayback/cpp/Common/CameraResources.h b/Samples/360VideoPlayback/cpp/Common/CameraResources.h new file mode 100644 index 0000000000..64bfaccd76 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/CameraResources.h @@ -0,0 +1,76 @@ +#pragma once + +namespace DX +{ + class DeviceResources; + + // Constant buffer used to send the view-projection matrices to the shader pipeline. + struct ViewProjectionConstantBuffer + { + DirectX::XMFLOAT4X4 viewProjection[2]; + }; + + // Assert that the constant buffer remains 16-byte aligned (best practice). + static_assert((sizeof(ViewProjectionConstantBuffer) % (sizeof(float) * 4)) == 0, "ViewProjection constant buffer size must be 16-byte aligned (16 bytes is the length of four floats)."); + + // Manages DirectX device resources that are specific to a holographic camera, such as the + // back buffer, ViewProjection constant buffer, and viewport. + class CameraResources + { + public: + CameraResources(Windows::Graphics::Holographic::HolographicCamera^ holographicCamera); + + void CreateResourcesForBackBuffer( + DX::DeviceResources* pDeviceResources, + Windows::Graphics::Holographic::HolographicCameraRenderingParameters^ cameraParameters + ); + void ReleaseResourcesForBackBuffer( + DX::DeviceResources* pDeviceResources + ); + + void UpdateViewProjectionBuffer( + std::shared_ptr deviceResources, + Windows::Graphics::Holographic::HolographicCameraPose^ cameraPose, + Windows::Perception::Spatial::SpatialCoordinateSystem^ coordinateSystem); + + bool AttachViewProjectionBuffer( + std::shared_ptr deviceResources); + + // Direct3D device resources. + ID3D11RenderTargetView* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + ID3D11Texture2D* GetBackBufferTexture2D() const { return m_d3dBackBuffer.Get(); } + D3D11_VIEWPORT GetViewport() const { return m_d3dViewport; } + DXGI_FORMAT GetBackBufferDXGIFormat() const { return m_dxgiFormat; } + + // Render target properties. + Windows::Foundation::Size GetRenderTargetSize() const { return m_d3dRenderTargetSize; } + bool IsRenderingStereoscopic() const { return m_isStereo; } + + // The holographic camera these resources are for. + Windows::Graphics::Holographic::HolographicCamera^ GetHolographicCamera() const { return m_holographicCamera; } + + private: + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + Microsoft::WRL::ComPtr m_d3dBackBuffer; + + // Device resource to store view and projection matrices. + Microsoft::WRL::ComPtr m_viewProjectionConstantBuffer; + + // Direct3D rendering properties. + DXGI_FORMAT m_dxgiFormat; + Windows::Foundation::Size m_d3dRenderTargetSize; + D3D11_VIEWPORT m_d3dViewport; + + // Indicates whether the camera supports stereoscopic rendering. + bool m_isStereo = false; + + // Indicates whether this camera has a pending frame. + bool m_framePending = false; + + // Pointer to the holographic camera these resources are for. + Windows::Graphics::Holographic::HolographicCamera^ m_holographicCamera = nullptr; + }; +} diff --git a/Samples/360VideoPlayback/cpp/Common/Controls.cpp b/Samples/360VideoPlayback/cpp/Common/Controls.cpp new file mode 100644 index 0000000000..fffad4154f --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/Controls.cpp @@ -0,0 +1,247 @@ +#include "pch.h" +#include "Controls.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" +#include "..\AppView.h" +#include "..\VideoGallery.xaml.h" + +using namespace _360VideoPlayback; +using namespace D2D1; +using namespace DirectX; +using namespace DX; +using namespace Microsoft::WRL; +using namespace std; +using namespace Windows::Foundation::Numerics; +using namespace Windows::Media::Core; +using namespace Windows::Media::Playback; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input::Spatial; +using namespace Windows::UI::ViewManagement; + +const ColorF focusOutlineColor(0xFFFFFF); +const ColorF pressedBackgroundFillColor(0x00AFFF); +const ColorF enabledForegroundColor(0xFFFFFF); +const float c_maxSecondsInPerformPressedFeedbackState = 0.25f; +UINT DEFAULT_SIZE = 18; +ElementMargin TEXT_MARGIN{ 15.0f, 12.0f, 15.0f, 12.0f }; + +Button::Button(UINT initialSize, ButtonShape shape) : + FocusableElement(), + m_pressingTimeOut(0.0f), + m_shape(shape) +{ + m_elementSize = float2(static_cast(initialSize)); + + // Add the button pressed UI element first so it appears under the focus rect. + if (m_shape == ButtonShape::Rectangle) + { + m_RectPressedBackgroundFill = make_shared(m_elementSize.x, m_elementSize.y, pressedBackgroundFillColor); + m_RectFocusOutline = make_shared(m_elementSize.x, m_elementSize.y, 1.5f, focusOutlineColor); + m_RectPressedBackgroundFill->SetIgnoreLayout(false); + m_RectFocusOutline->SetIgnoreLayout(false); + m_RectPressedBackgroundFill->SetIsVisible(false); + m_RectFocusOutline->SetIsVisible(false); + this->AddChildElement(m_RectPressedBackgroundFill); + this->AddChildElement(m_RectFocusOutline); + + } + else if (m_shape == ButtonShape::Circle) + { + m_ElliPressedBackgroundFill = make_shared(m_elementSize.x * 0.5f, m_elementSize.y * 0.5f, pressedBackgroundFillColor); + m_ElliFocusOutline = make_shared(m_elementSize.x * 0.5f, m_elementSize.y* 0.5f, 5.0f, focusOutlineColor); + m_ElliPressedBackgroundFill->SetIgnoreLayout(false); + m_ElliFocusOutline->SetIgnoreLayout(false); + m_ElliPressedBackgroundFill->SetIsVisible(false); + m_ElliFocusOutline->SetIsVisible(false); + this->AddChildElement(m_ElliPressedBackgroundFill); + this->AddChildElement(m_ElliFocusOutline); + } +} + +void Button::ArrangeElements() +{ + __super::ArrangeElements(); + + if (m_shape == ButtonShape::Rectangle) + { + // Update the focus rect to be the same size as the button. + FLOAT selectionBorderStrokeThickness = m_RectFocusOutline->GetStrokeThickness(); + m_RectFocusOutline->SetRect({ + selectionBorderStrokeThickness, + selectionBorderStrokeThickness, + m_elementSize.x - selectionBorderStrokeThickness, + m_elementSize.y - selectionBorderStrokeThickness }); + + m_RectPressedBackgroundFill->SetRect({ 0.0f, 0.0f, m_elementSize.x, m_elementSize.y }); + } + else if (m_shape == ButtonShape::Circle) + { + m_ElliFocusOutline->SetRadius(m_elementSize.x * 0.5f, m_elementSize.y * 0.5f); + m_ElliPressedBackgroundFill->SetRadius(m_elementSize.x * 0.5f, m_elementSize.y * 0.5f); + } +} + +void Button::Initialize() +{ + auto d2dcontext = m_deviceResources->GetD2DDeviceContext(); + + __super::Initialize(); + + // Recreate the brush for the glyphs, font, etc. This is the final brush we want to hold on to in the button + DX::ThrowIfFailed( + d2dcontext->CreateSolidColorBrush( + enabledForegroundColor, + &m_brush)); +} + +void Button::Update(const DX::StepTimer& timer, SpatialPointerPose^ cameraPose) +{ + __super::Update(timer, cameraPose); + if (m_buttonState == ButtonState::Pressing) + { + if (m_pressingTimeOut > m_maxSecondsInPressingState) + { + m_buttonState = ButtonState::Pressed; + if (m_shape == ButtonShape::Rectangle) + { + m_RectPressedBackgroundFill->SetIsVisible(false); + } + else + { + m_ElliPressedBackgroundFill->SetIsVisible(false); + } + Button::PerformAction(); + m_pressingTimeOut = 0.0f; + } + else + { + m_pressingTimeOut += static_cast(timer.GetElapsedSeconds()); + if (m_shape == ButtonShape::Rectangle) + { + if (!m_RectPressedBackgroundFill->GetIsVisible()) + { + m_RectPressedBackgroundFill->SetIsVisible(true); + } + } + else + { + if (!m_ElliPressedBackgroundFill->GetIsVisible()) + { + m_ElliPressedBackgroundFill->SetIsVisible(true); + } + } + } + } +} + +void Button::FocusUpdate() +{ + bool update = false; + if (this->IsFocused()) + { + update = true; + } + (m_shape == ButtonShape::Rectangle) ? m_RectFocusOutline->SetIsVisible(update) : m_ElliFocusOutline->SetIsVisible(update); +} + +void Button::PerformAction() +{ + // If the user invokes a button we need to trigger the invoked state + // and give visual feedback to the user that the button has been pressed. + if (m_buttonState == ButtonState::None) + { + m_buttonState = ButtonState::Pressing; + m_pressingTimeOut = 0.0f; + } + else if (m_buttonState == ButtonState::Pressed) + { + __super::PerformAction(); + m_buttonState = ButtonState::None; + } +} + +PlayPauseButton::PlayPauseButton(UINT buttonSize, UINT iconSize) : + Button(iconSize, ButtonShape::Circle) +{ + this->SetElementSize({ static_cast(buttonSize), static_cast(buttonSize) }); + m_playText = std::make_shared(L"Play", FONT_SIZE * 4, DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL); + m_playText->SetElementMargin(TEXT_MARGIN); + this->AddChildElement(m_playText); + + m_pauseText = std::make_shared(L"Pause", FONT_SIZE * 4, DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL); + m_pauseText->SetElementMargin(TEXT_MARGIN); + this->AddChildElement(m_pauseText); + + this->ArrangeElements(); +} + +void PlayPauseButton::Initialize() +{ + __super::Initialize(); + m_playText->SetBrush(m_brush.Get()); + m_playText->Initialize(); + m_pauseText->SetBrush(m_brush.Get()); + m_pauseText->Initialize(); +} + +void PlayPauseButton::Update(const StepTimer& timer, SpatialPointerPose^ cameraPose) +{ + __super::Update(timer, cameraPose); + + // Update the playback state. + bool isPlaying = (AppView::GetMediaPlayer()->PlaybackSession->PlaybackState == MediaPlaybackState::Playing); + + // When the video is playing, you show the Pause Text since hitting the button in this state will pause the video + if (isPlaying) + { + m_playText->SetIsVisible(false); + m_pauseText->SetIsVisible(true); + } + // When the video is Paused, you show the P:ay Text since hitting the button in this state will play the video + else + { + m_playText->SetIsVisible(true); + m_pauseText->SetIsVisible(false); + } +} + +void PlayPauseButton::PerformAction() +{ + __super::PerformAction(); + if (AppView::GetMediaPlayer()->PlaybackSession->PlaybackState != MediaPlaybackState::None) + { + if (AppView::GetMediaPlayer()->PlaybackSession->PlaybackState == MediaPlaybackState::Playing) + { + AppView::GetMediaPlayer()->Pause(); + } + else + { + AppView::GetMediaPlayer()->Play(); + } + } +} + +ExitButton::ExitButton() : + Button(DEFAULT_SIZE) +{ + m_exitText = std::make_shared(L"Exit Playback", FONT_SIZE * 2, DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL); + m_exitText->SetElementMargin(TEXT_MARGIN); + this->AddChildElement(m_exitText); + + this->SetLayoutHorizontal(true); +} + +void ExitButton::Initialize() +{ + __super::Initialize(); + + m_exitText->SetBrush(m_brush.Get()); + + m_exitText->Initialize(); +} + +void ExitButton::PerformAction() +{ + __super::PerformAction(); + ApplicationViewSwitcher::SwitchAsync(VideoGallery::GetMainViewId(), ApplicationView::GetForCurrentView()->Id, ApplicationViewSwitchingOptions::ConsolidateViews); +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/cpp/Common/Controls.h b/Samples/360VideoPlayback/cpp/Common/Controls.h new file mode 100644 index 0000000000..e7549a7326 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/Controls.h @@ -0,0 +1,69 @@ +#pragma once +#include "BaseElement.h" + +namespace DX +{ + enum class ButtonShape + { + Rectangle, + Circle, + }; + + enum class ButtonState + { + None, + Pressing, + Pressed + }; + + class Button : public FocusableElement + { + public: + Button( + UINT initialSize = BUTTON_SIZE, + ButtonShape shape = ButtonShape::Rectangle); + + virtual void ArrangeElements() override; + virtual void Initialize() override; + virtual void Update(const DX::StepTimer& timer, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose) override; + virtual void PerformAction() override; + virtual void FocusUpdate() override; + protected: + bool m_forceIconCentered; + Windows::Foundation::Numerics::float4x4 m_parentControlTransform; + Microsoft::WRL::ComPtr m_brush; + ButtonState m_buttonState = ButtonState::None; + float m_pressingTimeOut; + const ButtonShape m_shape = ButtonShape::Rectangle; + const float m_maxSecondsInPressingState = 0.25f; + private: + std::shared_ptr m_RectFocusOutline; + std::shared_ptr m_RectPressedBackgroundFill; + std::shared_ptr m_ElliFocusOutline; + std::shared_ptr m_ElliPressedBackgroundFill; + }; + + class PlayPauseButton : public Button + { + public: + PlayPauseButton(UINT buttonSize, UINT iconSize); + virtual void Initialize() override; + virtual void Update(const DX::StepTimer& timer, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose) override; + virtual void PerformAction() override; + + private: + std::shared_ptr m_playText; + std::shared_ptr m_pauseText; + }; + + class ExitButton : public Button + { + public: + ExitButton(); + virtual void Initialize() override; + virtual void PerformAction() override; + + private: + std::shared_ptr m_exitText; + }; +} diff --git a/Samples/360VideoPlayback/cpp/Common/DeviceResources.cpp b/Samples/360VideoPlayback/cpp/Common/DeviceResources.cpp new file mode 100644 index 0000000000..340b7d087e --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/DeviceResources.cpp @@ -0,0 +1,391 @@ +#include "pch.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" + +#include +#include + +using namespace D2D1; +using namespace Microsoft::WRL; +using namespace Windows::Graphics::DirectX::Direct3D11; +using namespace Windows::Graphics::Display; +using namespace Windows::Graphics::Holographic; + +const FLOAT dxgiDefaultDPI = 96; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources() +{ + CreateDeviceIndependentResources(); +} + +// Configures resources that don't depend on the Direct3D device. +void DX::DeviceResources::CreateDeviceIndependentResources() +{ + // Initialize Direct2D resources. + D2D1_FACTORY_OPTIONS options{}; + +#if defined(_DEBUG) + // If the project is in a debug build, enable Direct2D debugging via SDK Layers. + options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; +#endif + + // Initialize the Direct2D Factory. + DX::ThrowIfFailed( + D2D1CreateFactory( + D2D1_FACTORY_TYPE_SINGLE_THREADED, + __uuidof(ID2D1Factory2), + &options, + &m_d2dFactory + ) + ); + + // Initialize the DirectWrite Factory. + DX::ThrowIfFailed( + DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory2), + &m_dwriteFactory + ) + ); + + // Initialize the Windows Imaging Component (WIC) Factory. + DX::ThrowIfFailed( + CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&m_wicFactory) + ) + ); +} + +void DX::DeviceResources::SetHolographicSpace(HolographicSpace^ holographicSpace) +{ + // Cache the holographic space. Used to re-initalize during device-lost scenarios. + m_holographicSpace = holographicSpace; + + InitializeUsingHolographicSpace(); +} + +void DX::DeviceResources::InitializeUsingHolographicSpace() +{ + // The holographic space might need to determine which adapter supports + // holograms, in which case it will specify a non-zero PrimaryAdapterId. + LUID id = + { + m_holographicSpace->PrimaryAdapterId.LowPart, + m_holographicSpace->PrimaryAdapterId.HighPart + }; + + // When a primary adapter ID is given to the app, the app should find + // the corresponding DXGI adapter and use it to create Direct3D devices + // and device contexts. Otherwise, there is no restriction on the DXGI + // adapter the app can use. + if ((id.HighPart != 0) || (id.LowPart != 0)) + { + UINT createFlags = 0; +#ifdef DEBUG + if (DX::SdkLayersAvailable()) + { + createFlags |= DXGI_CREATE_FACTORY_DEBUG; + } +#endif + // Create the DXGI factory. + ComPtr dxgiFactory; + DX::ThrowIfFailed( + CreateDXGIFactory2( + createFlags, + IID_PPV_ARGS(&dxgiFactory) + ) + ); + ComPtr dxgiFactory4; + DX::ThrowIfFailed(dxgiFactory.As(&dxgiFactory4)); + + // Retrieve the adapter specified by the holographic space. + DX::ThrowIfFailed( + dxgiFactory4->EnumAdapterByLuid( + id, + IID_PPV_ARGS(&m_dxgiAdapter) + ) + ); + } + else + { + m_dxgiAdapter.Reset(); + } + + CreateDeviceResources(); + + m_holographicSpace->SetDirect3D11Device(m_d3dInteropDevice); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#if defined(_DEBUG) + if (DX::SdkLayersAvailable()) + { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } +#endif + + // This array defines the set of DirectX hardware feature levels this app will support. + // Note the ordering should be preserved. + // Note that HoloLens supports feature level 11.1. The HoloLens emulator is also capable + // of running on graphics cards starting with feature level 10.0. + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0 + }; + + D3D11_RASTERIZER_DESC rasterDesc{ + D3D11_FILL_SOLID, + D3D11_CULL_NONE, + false, + 0, + 0.0f, + 0.0f, + true, + false, + true, + true }; + + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + const D3D_DRIVER_TYPE driverType = m_dxgiAdapter == nullptr ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN; + const HRESULT hr = D3D11CreateDevice( + m_dxgiAdapter.Get(), // Either nullptr, or the primary adapter determined by Windows Holographic. + driverType, // Create a device using the hardware graphics driver. + 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. + creationFlags, // Set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), // Size of the list above. + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + &device, // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + &context // Returns the device immediate context. + ); + + if (FAILED(hr)) + { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + DX::ThrowIfFailed( + D3D11CreateDevice( + nullptr, // Use the default DXGI adapter for WARP. + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. + 0, + creationFlags, + featureLevels, + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, + &device, + &m_d3dFeatureLevel, + &context + ) + ); + } + + + // Store pointers to the Direct3D device and immediate context. + DX::ThrowIfFailed( + device.As(&m_d3dDevice) + ); + + DX::ThrowIfFailed( + context.As(&m_d3dContext) + ); + + // Acquire the DXGI interface for the Direct3D device. + ComPtr dxgiDevice; + DX::ThrowIfFailed( + m_d3dDevice.As(&dxgiDevice) + ); + + // Wrap the native device using a WinRT interop object. + m_d3dInteropDevice = CreateDirect3DDevice(dxgiDevice.Get()); + + // Cache the DXGI adapter. + // This is for the case of no preferred DXGI adapter, or fallback to WARP. + ComPtr dxgiAdapter; + DX::ThrowIfFailed( + dxgiDevice->GetAdapter(&dxgiAdapter) + ); + DX::ThrowIfFailed( + dxgiAdapter.As(&m_dxgiAdapter) + ); + + + DX::ThrowIfFailed( + m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice) + ); + + DX::ThrowIfFailed( + m_d2dDevice->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, + &m_d2dContext + ) + ); + // Set DPI that will be used when drawing to D2D + m_d2dContext->SetDpi(dxgiDefaultDPI, dxgiDefaultDPI); + + // Check for device support for the optional feature that allows setting the render target array index from the vertex shader stage. + D3D11_FEATURE_DATA_D3D11_OPTIONS3 options; + m_d3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &options, sizeof(options)); + if (options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer) + { + m_supportsVprt = true; + } + + ID3D11RasterizerState* praster; + DX::ThrowIfFailed(m_d3dDevice->CreateRasterizerState(&rasterDesc, &praster)); + m_d3dContext->RSSetState(praster); + + ComPtr spMultithread; + DX::ThrowIfFailed( + m_d3dDevice->QueryInterface(IID_PPV_ARGS(&spMultithread)) + ); + spMultithread->SetMultithreadProtected(TRUE); +} + +// Validates the back buffer for each HolographicCamera and recreates +// resources for back buffers that have changed. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::EnsureCameraResources( + HolographicFrame^ frame, + HolographicFramePrediction^ prediction) +{ + UseHolographicCameraResources([this, frame, prediction](std::map>& cameraResourceMap) + { + for (HolographicCameraPose^ pose : prediction->CameraPoses) + { + HolographicCameraRenderingParameters^ renderingParameters = frame->GetRenderingParameters(pose); + CameraResources* pCameraResources = cameraResourceMap[pose->HolographicCamera->Id].get(); + + pCameraResources->CreateResourcesForBackBuffer(this, renderingParameters); + } + }); +} + +// Prepares to allocate resources and adds resource views for a camera. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::AddHolographicCamera(HolographicCamera^ camera) +{ + UseHolographicCameraResources([this, camera](std::map>& cameraResourceMap) + { + cameraResourceMap[camera->Id] = std::make_unique(camera); + }); +} + +// Deallocates resources for a camera and removes the camera from the set. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::RemoveHolographicCamera(HolographicCamera^ camera) +{ + UseHolographicCameraResources([this, camera](std::map>& cameraResourceMap) + { + CameraResources* pCameraResources = cameraResourceMap[camera->Id].get(); + + if (pCameraResources != nullptr) + { + pCameraResources->ReleaseResourcesForBackBuffer(this); + cameraResourceMap.erase(camera->Id); + } + }); +} + +// Recreate all device resources and set them back to the current state. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::HandleDeviceLost() +{ + if (m_deviceNotify != nullptr) + { + m_deviceNotify->OnDeviceLost(); + } + + UseHolographicCameraResources([this](std::map>& cameraResourceMap) + { + for (auto& pair : cameraResourceMap) + { + CameraResources* pCameraResources = pair.second.get(); + pCameraResources->ReleaseResourcesForBackBuffer(this); + } + }); + + InitializeUsingHolographicSpace(); + + if (m_deviceNotify != nullptr) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Register our DeviceNotify to be informed on device lost and creation. +void DX::DeviceResources::RegisterDeviceNotify(DX::IDeviceNotify* deviceNotify) +{ + m_deviceNotify = deviceNotify; +} + +// Call this method when the app suspends. It provides a hint to the driver that the app +// is entering an idle state and that temporary buffers can be reclaimed for use by other apps. +void DX::DeviceResources::Trim() +{ + m_d3dContext->ClearState(); + + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + dxgiDevice->Trim(); +} + +// Present the contents of the swap chain to the screen. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::Present(HolographicFrame^ frame) +{ + // By default, this API waits for the frame to finish before it returns. + // Holographic apps should wait for the previous frame to finish before + // starting work on a new frame. This allows for better results from + // holographic frame predictions. + HolographicFramePresentResult presentResult = frame->PresentUsingCurrentPrediction(); + + HolographicFramePrediction^ prediction = frame->CurrentPrediction; + UseHolographicCameraResources([this, prediction](std::map>& cameraResourceMap) + { + for (auto cameraPose : prediction->CameraPoses) + { + // This represents the device-based resources for a HolographicCamera. + DX::CameraResources* pCameraResources = cameraResourceMap[cameraPose->HolographicCamera->Id].get(); + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be + // entirely overwritten. If dirty or scroll rects are used, this call + // should be removed. + m_d3dContext->DiscardView(pCameraResources->GetBackBufferRenderTargetView()); + + // Discard the contents of the depth stencil. + m_d3dContext->DiscardView(pCameraResources->GetDepthStencilView()); + } + }); + + // The PresentUsingCurrentPrediction API will detect when the graphics device + // changes or becomes invalid. When this happens, it is considered a Direct3D + // device lost scenario. + if (presentResult == HolographicFramePresentResult::DeviceRemoved) + { + // The Direct3D device, context, and resources should be recreated. + HandleDeviceLost(); + } +} diff --git a/Samples/360VideoPlayback/cpp/Common/DeviceResources.h b/Samples/360VideoPlayback/cpp/Common/DeviceResources.h new file mode 100644 index 0000000000..7dc952c4ee --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/DeviceResources.h @@ -0,0 +1,112 @@ + +#pragma once + +#include "CameraResources.h" + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Creates and manages a Direct3D device and immediate context, Direct2D device and context (for debug), and the holographic swap chain. + class DeviceResources + { + public: + DeviceResources(); + + // Public methods related to Direct3D devices. + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify); + void Trim(); + void Present(Windows::Graphics::Holographic::HolographicFrame^ frame); + + // Public methods related to holographic devices. + void SetHolographicSpace(Windows::Graphics::Holographic::HolographicSpace^ space); + void EnsureCameraResources( + Windows::Graphics::Holographic::HolographicFrame^ frame, + Windows::Graphics::Holographic::HolographicFramePrediction^ prediction); + + void AddHolographicCamera(Windows::Graphics::Holographic::HolographicCamera^ camera); + void RemoveHolographicCamera(Windows::Graphics::Holographic::HolographicCamera^ camera); + + // Holographic accessors. + template + RetType UseHolographicCameraResources(const LCallback& callback); + + Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice^ + GetD3DInteropDevice() const { return m_d3dInteropDevice; } + + // D3D accessors. + ID3D11Device4* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContext3* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + bool GetDeviceSupportsVprt() const { return m_supportsVprt; } + + // DXGI acessors. + IDXGIAdapter3* GetDXGIAdapter() const { return m_dxgiAdapter.Get(); } + + // D2D accessors. + ID2D1Factory2* GetD2DFactory() const { return m_d2dFactory.Get(); } + ID2D1Device1* GetD2DDevice() const { return m_d2dDevice.Get(); } + ID2D1DeviceContext1* GetD2DDeviceContext() const { return m_d2dContext.Get(); } + IDWriteFactory2* GetDWriteFactory() const { return m_dwriteFactory.Get(); } + IWICImagingFactory2* GetWicImagingFactory() const { return m_wicFactory.Get(); } + Windows::Foundation::Size m_logicalSize; + + private: + // Private methods related to the Direct3D device, and resources based on that device. + void CreateDeviceIndependentResources(); + void InitializeUsingHolographicSpace(); + void CreateDeviceResources(); + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_dxgiAdapter; + + // Direct3D interop objects. + Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice^ m_d3dInteropDevice; + + // Direct2D factories. + Microsoft::WRL::ComPtr m_d2dFactory; + Microsoft::WRL::ComPtr m_d2dDevice; + Microsoft::WRL::ComPtr m_d2dContext; + Microsoft::WRL::ComPtr m_dwriteFactory; + Microsoft::WRL::ComPtr m_wicFactory; + + // The holographic space provides a preferred DXGI adapter ID. + Windows::Graphics::Holographic::HolographicSpace^ m_holographicSpace = nullptr; + + // Properties of the Direct3D device currently in use. + D3D_FEATURE_LEVEL m_d3dFeatureLevel = D3D_FEATURE_LEVEL_10_0; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify = nullptr; + + // Whether or not the current Direct3D device supports the optional feature + // for setting the render target array index from the vertex shader stage. + bool m_supportsVprt = false; + + // Back buffer resources, etc. for attached holographic cameras. + std::map> m_cameraResources; + std::mutex m_cameraResourcesLock; + }; +} + +// Device-based resources for holographic cameras are stored in a std::map. Access this list by providing a +// callback to this function, and the std::map will be guarded from add and remove +// events until the callback returns. The callback is processed immediately and must +// not contain any nested calls to UseHolographicCameraResources. +// The callback takes a parameter of type std::map>& +// through which the list of cameras will be accessed. +template +RetType DX::DeviceResources::UseHolographicCameraResources(const LCallback& callback) +{ + std::lock_guard guard(m_cameraResourcesLock); + return callback(m_cameraResources); +} + diff --git a/Samples/360VideoPlayback/cpp/Common/DirectXHelper.h b/Samples/360VideoPlayback/cpp/Common/DirectXHelper.h new file mode 100644 index 0000000000..f73985f6e3 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/DirectXHelper.h @@ -0,0 +1,59 @@ +#pragma once + +#include // For create_task + +namespace DX +{ + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + // Set a breakpoint on this line to catch Win32 API errors. + throw Platform::Exception::CreateException(hr); + } + } + + // Function that reads from a binary file asynchronously. + inline Concurrency::task> ReadDataAsync(const std::wstring& filename) + { + using namespace Windows::Storage; + using namespace Concurrency; + + return create_task(PathIO::ReadBufferAsync(Platform::StringReference(filename.c_str()))).then( + [] (Streams::IBuffer^ fileBuffer) -> std::vector + { + std::vector returnBuffer; + returnBuffer.resize(fileBuffer->Length); + Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference(returnBuffer.data(), static_cast(returnBuffer.size()))); + return returnBuffer; + }); + } + + // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. + inline float ConvertDipsToPixels(float dips, float dpi) + { + constexpr float dipsPerInch = 96.0f; + return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. + } + +#if defined(_DEBUG) + // Check for SDK Layer support. + inline bool SdkLayersAvailable() + { + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + + return SUCCEEDED(hr); + } +#endif +} diff --git a/Samples/360VideoPlayback/cpp/Common/MeshGeometry.cpp b/Samples/360VideoPlayback/cpp/Common/MeshGeometry.cpp new file mode 100644 index 0000000000..02f7cee78e --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/MeshGeometry.cpp @@ -0,0 +1,306 @@ +#include "pch.h" +#include "MeshGeometry.h" +#include "..\360VideoPlaybackMain.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" +#include "..\Content\ShaderStructures.h" + +using namespace _360VideoPlayback; +using namespace DirectX; +using namespace DX; +using namespace Microsoft::WRL; +using namespace std; +using namespace Windows::Foundation::Numerics; + +shared_ptr MeshGeometry::MakeTexturedCube() +{ + _360VideoPlayback::VertexPositionTexture cubeVertices[] = + { + { XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, // +Y (top face) + { XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, + + { XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, // -Y (bottom face) + { XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + + { XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, // +X (right face) + { XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, + + { XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, // -X (left face) + { XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + + { XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f) }, // +Z (front face) + { XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(1.0f, 0.0f) }, // WARNING: This Front face is tied directly to the DEFAULT_CUBE_BOUNDING_PLANE. If you modify this, update both + { XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(1.0f, 1.0f) }, + { XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 1.0f) }, + + { XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, // -Z (back face) + { XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT2(-1.0f, -1.0f) }, + }; + + unsigned short cubeIndices[] = + { + 0, 1, 2, + 0, 2, 3, + + 4, 5, 6, + 4, 6, 7, + + 8, 9, 10, + 8, 10, 11, + + 12, 13, 14, + 12, 14, 15, + + 16, 17, 18, + 16, 18, 19, + + 20, 21, 22, + 20, 22, 23 + }; + + ComPtr vertexBuffer = CreateVertexBuffer(ARRAYSIZE(cubeVertices), cubeVertices); + ComPtr indexBuffer = CreateIndexBuffer(ARRAYSIZE(cubeIndices), cubeIndices); + + return make_shared( + D3D11_PRIMITIVE_TOPOLOGY::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, + vertexBuffer, + indexBuffer, + static_cast(sizeof(_360VideoPlayback::VertexPositionTexture)), + static_cast(ARRAYSIZE(cubeIndices)) + ); +} + +shared_ptr MeshGeometry::MakeTexturedCylinder(unsigned short tessellation) +{ + const float frontFaceZ = 0.5f; + const float backFaceZ = -0.5f; + vector vertices = { + {{ 0.0f, 0.0f, frontFaceZ }, { 0.5f, 0.5f }}, // Front face center vertex + {{ 0.0f, 0.0f, backFaceZ }, { 0.0f, 0.0f }} // Back face center vertex + }; + + const unsigned short frontFaceCenterVertexIndex = 0; + const unsigned short backFaceCenterVertexIndex = 1; + + unsigned short frontFaceVerticesStartIndex = static_cast(vertices.size()); + auto frontFaceVertices = MeshGeometry::MakeCylinderFaceVertices( + tessellation, + frontFaceZ, + [](float x, float y) -> XMFLOAT2 + { + const float u = x + 0.5f; + const float v = -y + 0.5f; + + return { u, v }; + } + ); + copy(begin(frontFaceVertices), end(frontFaceVertices), back_inserter(vertices)); + + // While the vertex positions of the front face and the "front" side vertices are the same, + // we want the UV coordinates to be different. + // So duplicate the vertices and set the UV coordinates to [0,0] + unsigned short frontFaceSideVerticesStartIndex = static_cast(vertices.size()); + auto frontFaceSideVertices = MeshGeometry::MakeCylinderFaceVertices( + tessellation, + frontFaceZ, + [](float /*x*/, float /*y*/) -> XMFLOAT2 + { + return { 0.0f, 0.0f }; + } + ); + copy(begin(frontFaceSideVertices), end(frontFaceSideVertices), back_inserter(vertices)); + + // Shared by the back face and "back" side vertices. + unsigned short backFaceVerticesStartIndex = static_cast(vertices.size()); + auto backFaceVertices = MeshGeometry::MakeCylinderFaceVertices( + tessellation, + backFaceZ, + [](float /*x*/, float /*y*/) -> XMFLOAT2 + { + return { 0.0f, 0.0f }; + } + ); + copy(begin(backFaceVertices), end(backFaceVertices), back_inserter(vertices)); + + // Front face indices + vector indices = MeshGeometry::MakeCylinderFaceIndices( + tessellation, + /*vertexIndexOffset*/ frontFaceVerticesStartIndex, + /*centerVertexIndex*/ frontFaceCenterVertexIndex, + /*isFrontFace*/ true); + + // Back face indices. + // This may be shown brifly during intro/outro animations so we need to show it. + vector backFaceIndices = MeshGeometry::MakeCylinderFaceIndices( + tessellation, + /*vertexIndexOffset*/ backFaceVerticesStartIndex, + /*centerVertexIndex*/ backFaceCenterVertexIndex, + /*isFrontFace*/ false); + copy(begin(backFaceIndices), end(backFaceIndices), back_inserter(indices)); + + // Side indices + vector sideIndices = MeshGeometry::MakeCylinderSideIndices( + tessellation, + /*vertexIndexOffset*/ frontFaceSideVerticesStartIndex, + /*cylinderFaceVertexStride*/ static_cast(frontFaceSideVertices.size())); + copy(begin(sideIndices), end(sideIndices), back_inserter(indices)); + + ComPtr vertexBuffer = CreateVertexBuffer( + static_cast(vertices.size()), + vertices.data() + ); + + ComPtr indexBuffer = CreateIndexBuffer( + static_cast(indices.size()), + indices.data()); + + return make_shared( + D3D11_PRIMITIVE_TOPOLOGY::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, + vertexBuffer, + indexBuffer, + static_cast(sizeof(VertexPositionTexture)), + static_cast(indices.size()) + ); +} + +vector MeshGeometry::MakeCylinderFaceVertices(unsigned short tessellation, float z, function uvGenerator) +{ + // Create a fan of triangles from the center of the circle. + // Reserve space for all vertices along the outer edges and the center vertex. + vector vertices; + vertices.resize(tessellation + 1); + for (int i = 0; i < tessellation; i++) + { + const float angle = XM_2PI * (static_cast(i) / tessellation); + + const float x = 0.5f * cos(angle); + const float y = 0.5f * sin(angle); + + const XMFLOAT3 pos{ x, y, z }; + const XMFLOAT2 uv = uvGenerator(x, y); + + vertices[i] = { pos, uv }; + } + + return vertices; +} + +vector MeshGeometry::MakeCylinderFaceIndices(unsigned short tessellation, unsigned short vertexIndexOffset, unsigned short centerVertexIndex, bool isFrontFace) +{ + vector indices; + indices.resize(tessellation * 3); + + for (unsigned short i = 0; i < tessellation; i++) + { + // The next 3 vertices are for the i-th triangle + const int baseTriangleIndex = (i * 3); + + unsigned short currentVertexIndex = vertexIndexOffset + i; + unsigned short nextVertexIndex = vertexIndexOffset + ((i + 1) % tessellation); + + if (isFrontFace) + { + // Clockwise ordering + indices[baseTriangleIndex] = currentVertexIndex; + indices[baseTriangleIndex + 1] = centerVertexIndex; + indices[baseTriangleIndex + 2] = nextVertexIndex; + } + else + { + // Counter-clockwise ordering + indices[baseTriangleIndex] = nextVertexIndex; + indices[baseTriangleIndex + 1] = centerVertexIndex; + indices[baseTriangleIndex + 2] = currentVertexIndex; + } + } + + return indices; +} + +vector MeshGeometry::MakeCylinderSideIndices(unsigned short tessellation, unsigned short vertexIndexOffset, unsigned short cylinderFaceVertexStride) +{ + vector indices; + indices.resize(tessellation * 6); + + for (unsigned short i = 0; i < tessellation; i++) + { + // The next 6 vertices are for the i-th quad making up the i-th side of the cylinder + const int baseTriangleIndex = (i * 6); + + unsigned short currentVertexIndexFrontFace = vertexIndexOffset + i; + unsigned short currentVertexIndexBackFace = vertexIndexOffset + i + cylinderFaceVertexStride; + unsigned short nextVertexIndexFrontFace = vertexIndexOffset + ((i + 1) % tessellation); + unsigned short nextVertexIndexBackFace = vertexIndexOffset + ((i + 1) % tessellation) + cylinderFaceVertexStride; + + indices[baseTriangleIndex] = currentVertexIndexFrontFace; + indices[baseTriangleIndex + 1] = nextVertexIndexFrontFace; + indices[baseTriangleIndex + 2] = currentVertexIndexBackFace; + + indices[baseTriangleIndex + 3] = nextVertexIndexFrontFace; + indices[baseTriangleIndex + 4] = nextVertexIndexBackFace; + indices[baseTriangleIndex + 5] = currentVertexIndexBackFace; + } + + return indices; +} + +ComPtr MeshGeometry::CreateVertexBuffer(unsigned int numVertices, const VertexPositionTexture* vertexData) +{ + ComPtr vertexBufferInternal; + D3D11_BUFFER_DESC VertexBufferDesc; + VertexBufferDesc.ByteWidth = sizeof(_360VideoPlayback::VertexPositionTexture) * numVertices; + VertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; + VertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + VertexBufferDesc.CPUAccessFlags = 0; + VertexBufferDesc.MiscFlags = 0; + VertexBufferDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA VertexBufferData; + VertexBufferData.pSysMem = vertexData; + VertexBufferData.SysMemPitch = 0; + VertexBufferData.SysMemSlicePitch = 0; + + DX::ThrowIfFailed( + _360VideoPlaybackMain::GetDeviceResources()->GetD3DDevice()->CreateBuffer( + &VertexBufferDesc, + &VertexBufferData, + &vertexBufferInternal)); + + return vertexBufferInternal; +} + +ComPtr MeshGeometry::CreateIndexBuffer(unsigned int numIndices, const unsigned short* indexData) +{ + ComPtr indexBufferInternal; + + D3D11_BUFFER_DESC IndexBufferDesc; + IndexBufferDesc.ByteWidth = sizeof(unsigned short) * numIndices; + IndexBufferDesc.Usage = D3D11_USAGE_DEFAULT; + IndexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + IndexBufferDesc.CPUAccessFlags = 0; + IndexBufferDesc.MiscFlags = 0; + IndexBufferDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA IndexBufferData; + IndexBufferData.pSysMem = indexData; + IndexBufferData.SysMemPitch = 0; + IndexBufferData.SysMemSlicePitch = 0; + + DX::ThrowIfFailed( + _360VideoPlaybackMain::GetDeviceResources()->GetD3DDevice()->CreateBuffer( + &IndexBufferDesc, + &IndexBufferData, + &indexBufferInternal)); + + return indexBufferInternal; +} diff --git a/Samples/360VideoPlayback/cpp/Common/MeshGeometry.h b/Samples/360VideoPlayback/cpp/Common/MeshGeometry.h new file mode 100644 index 0000000000..b4b0cf20cd --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/MeshGeometry.h @@ -0,0 +1,39 @@ +#pragma once +#include "..\Content\ShaderStructures.h" +namespace DX +{ + struct MeshGeometry + { + public: + const D3D11_PRIMITIVE_TOPOLOGY Topology; + const Microsoft::WRL::ComPtr VertexBuffer; + const Microsoft::WRL::ComPtr IndexBuffer; + const uint32 VertexStride; + const uint32 IndexCount; + + static std::shared_ptr MakeTexturedCube(); + static std::shared_ptr MakeTexturedCylinder(unsigned short tessellation); + + MeshGeometry( + D3D11_PRIMITIVE_TOPOLOGY topology, + const Microsoft::WRL::ComPtr& vertexBuffer, + const Microsoft::WRL::ComPtr& indexBuffer, + uint32 vertexStride, + uint32 indexCount) : + Topology(topology), + VertexBuffer(vertexBuffer), + IndexBuffer(indexBuffer), + VertexStride(vertexStride), + IndexCount(indexCount) + { + } + + private: + static Microsoft::WRL::ComPtr CreateVertexBuffer(unsigned int numVertices, const _360VideoPlayback::VertexPositionTexture* vertexData); + static Microsoft::WRL::ComPtr CreateIndexBuffer(unsigned int numIndices, const unsigned short* indexData); + + static std::vector<_360VideoPlayback::VertexPositionTexture> MakeCylinderFaceVertices(unsigned short tessellation, float z, std::function uvGenerator); + static std::vector MakeCylinderFaceIndices(unsigned short tessellation, unsigned short vertexIndexOffset, unsigned short centerVertexIndex, bool isFrontFace); + static std::vector MakeCylinderSideIndices(unsigned short tessellation, unsigned short vertexIndexOffset, unsigned short cylinderFaceVertexStride); + }; +} diff --git a/Samples/360VideoPlayback/cpp/Common/SeekBarElement.cpp b/Samples/360VideoPlayback/cpp/Common/SeekBarElement.cpp new file mode 100644 index 0000000000..ae29231f83 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/SeekBarElement.cpp @@ -0,0 +1,216 @@ +#include "pch.h" +#include "SeekBarElement.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" +#include "..\360VideoPlaybackMain.h" +#include "..\AppView.h" + +using namespace _360VideoPlayback; +using namespace DX; +using namespace Microsoft::WRL; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation::Numerics; +using namespace Windows::Globalization::NumberFormatting; +using namespace Windows::Media::Core; +using namespace Windows::Media::Playback; +using namespace Windows::UI::Input::Spatial; + +const long long s_hnsPerMillisecond = 10000; +const int64 ticksPerSecond = 10000000LL; +const UINT millisecondsPerSecond = 1000; +const unsigned int END_OF_PLAYBACK_BUFFER_MS = 200; + +SeekBarElement::SeekBarElement(float elementWidth, float elementHeight, float leftRightPadding, float topBottomPadding) : + m_leftRightPadding(leftRightPadding), + m_topBottomPadding(topBottomPadding), + m_currentPlayPosition(0), + m_currentVideoDuration(0), + m_secondsElapsedSinceTimeUpdate(0.0) +{ + m_isFocusIntersectionCalculated = true; + m_elementSize = float2(elementWidth, elementHeight); + m_sliderPosition = 0.0f; + m_sliderWidth = max((m_elementSize.x - (m_leftRightPadding * 2.0f)), 0.0f); + m_sliderHeight = max((m_elementSize.y - (m_topBottomPadding * 2.0f)), 0.0f); + + m_sliderFrontSegment = std::make_shared(m_sliderHeight); + AddChildElement(m_sliderFrontSegment); + + m_sliderRemainingSegment = std::make_shared(m_sliderHeight); + AddChildElement(m_sliderRemainingSegment); + + float seekBarYCoordinate = m_topBottomPadding + (m_sliderHeight * 0.5f); + m_sliderFrontSegmentStart = D2D1::Point2F(m_leftRightPadding, 0.0f); + m_sliderFrontSegment->SetStartPoint(m_sliderFrontSegmentStart); + m_sliderFrontSegment->SetTranslation({ 0.0f, seekBarYCoordinate }); + + m_sliderRemainingSegmentEnd = D2D1::Point2F(m_elementSize.x - m_leftRightPadding, 0.0f); + m_sliderRemainingSegment->SetEndPoint(m_sliderRemainingSegmentEnd); + m_sliderRemainingSegment->SetTranslation({ 0.0f, seekBarYCoordinate }); + m_textSize = FONT_SIZE * 1.25f; + m_elapsedTimeText = std::make_shared(L"", m_textSize, DWRITE_FONT_WEIGHT_NORMAL); + AddChildElement(m_elapsedTimeText); + + m_remainingTimeText = std::make_shared(L"", m_textSize, DWRITE_FONT_WEIGHT_NORMAL); + AddChildElement(m_remainingTimeText); +} + +void SeekBarElement::Initialize() +{ + auto d2dcontext = m_deviceResources->GetD2DDeviceContext(); + __super::Initialize(); + + DX::ThrowIfFailed( + d2dcontext->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF::White), + &m_frontSegmentBrush)); + + DX::ThrowIfFailed( + d2dcontext->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF::Gray), + &m_endSegmentBrush)); + + DX::ThrowIfFailed( + d2dcontext->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF::White), + &m_brush)); + + m_sliderFrontSegment->SetBrush(m_frontSegmentBrush.Get()); + m_sliderFrontSegment->Initialize(); + + m_sliderRemainingSegment->SetBrush(m_endSegmentBrush.Get()); + m_sliderRemainingSegment->Initialize(); + + + m_elapsedTimeText->SetBrush(m_brush.Get()); + m_elapsedTimeText->Initialize(); + m_remainingTimeText->SetBrush(m_brush.Get()); + m_remainingTimeText->Initialize(); + // Text goes below the seekbar + float startYCoordinateOfText = m_elementSize.y - m_topBottomPadding + 4.0f; + m_elapsedTimeText->SetTranslation({ m_leftRightPadding, startYCoordinateOfText }); + m_remainingTimeText->SetTranslation({ (m_elementSize.x - m_leftRightPadding - (FONT_SIZE * 3.0f)), startYCoordinateOfText }); + + UpdateLayoutFromCurrentTime(); +} + +void SeekBarElement::UpdateSliderPosition(float value) +{ + m_sliderPosition = value; + // Clamp [0,1] + if (m_sliderPosition < 0.0f) + { + m_sliderPosition = 0.0f; + } + else if (m_sliderPosition > 1.0f) + { + m_sliderPosition = 1.0f; + } + + float sliderUIPosition = m_sliderPosition > 0.0f ? (m_sliderWidth * m_sliderPosition) + m_leftRightPadding : m_leftRightPadding; + m_sliderFrontSegmentEnd = D2D1::Point2F(sliderUIPosition, 0.0f); + m_sliderFrontSegment->SetEndPoint(m_sliderFrontSegmentEnd); + m_sliderRemainingSegmentStart = D2D1::Point2F(sliderUIPosition, 0.0f); + m_sliderRemainingSegment->SetStartPoint(m_sliderRemainingSegmentStart); +} + +void SeekBarElement::Update(const DX::StepTimer& timer, SpatialPointerPose^ cameraPose) +{ + __super::Update(timer, cameraPose); + m_secondsElapsedSinceTimeUpdate += timer.GetElapsedSeconds(); + + // Update the current seek bar time no more than once every second. + if (m_secondsElapsedSinceTimeUpdate > 1.0) + { + UpdateLayoutFromCurrentTime(); + m_secondsElapsedSinceTimeUpdate = 0.0; + } +} + +void SeekBarElement::UpdateLayoutFromCurrentTime() +{ + m_currentVideoDuration = AppView::GetMediaPlayer()->PlaybackSession->NaturalDuration.Duration / s_hnsPerMillisecond; + if (m_currentVideoDuration != 0) + { + m_currentPlayPosition = AppView::GetMediaPlayer()->PlaybackSession->Position.Duration / s_hnsPerMillisecond; + if (m_currentPlayPosition > m_currentVideoDuration) + { + m_currentVideoDuration = m_currentPlayPosition; + } + } + // Update current and remaining time indicators + m_elapsedTimeString = FormatTimeString(m_currentPlayPosition)->Data(); + m_remainingTimeString = FormatTimeString(m_currentVideoDuration - m_currentPlayPosition)->Data(); + m_elapsedTimeText->SetText(m_elapsedTimeString); + m_remainingTimeText->SetText(m_remainingTimeString); + + float currentTimeSliderPosition = static_cast(m_currentVideoDuration) > 0.0f ? static_cast(m_currentPlayPosition) / static_cast(m_currentVideoDuration) : 0.0f; + UpdateSliderPosition(currentTimeSliderPosition); +} + +void SeekBarElement::PerformAction() +{ + // Update the Slider's position + float xIntersectionPoint = m_elementCoordIntersectionPoint.x; + // Clamp before and after the slider + // Otherwise compute slider based on relative position + if (xIntersectionPoint < m_leftRightPadding) + { + UpdateSliderPosition(0.0f); + } + else if (xIntersectionPoint > (m_leftRightPadding + m_sliderWidth)) + { + UpdateSliderPosition(1.0f); + } + else + { + UpdateSliderPosition((xIntersectionPoint - m_leftRightPadding) / m_sliderWidth); + } + + unsigned int seekTime = static_cast(m_currentVideoDuration * m_sliderPosition); + + if (seekTime >= (static_cast(AppView::GetMediaPlayer()->PlaybackSession->NaturalDuration.Duration / s_hnsPerMillisecond)) - END_OF_PLAYBACK_BUFFER_MS) + { + seekTime = (static_cast(AppView::GetMediaPlayer()->PlaybackSession->NaturalDuration.Duration / s_hnsPerMillisecond)) - END_OF_PLAYBACK_BUFFER_MS; + } + auto seekTimeSpan = TimeSpan(); + seekTimeSpan.Duration = static_cast(seekTime) * s_hnsPerMillisecond; + AppView::GetMediaPlayer()->PlaybackSession->Position = seekTimeSpan; +} + +String^ SeekBarElement::FormatTimeString(int64 intervalValue) +{ + String^ formattedTimeSpan; + std::chrono::milliseconds duration{ intervalValue }; + auto seconds = static_cast(std::chrono::duration_cast(duration).count()); + auto minutes = static_cast(std::chrono::duration_cast(duration).count()); + seconds -= minutes * 60; + auto hours = static_cast(std::chrono::duration_cast(duration).count()); + minutes -= hours * 60; + + DecimalFormatter^ twoDigitNumberFormatter = ref new DecimalFormatter( + Windows::System::UserProfile::GlobalizationPreferences::Languages, + Windows::System::UserProfile::GlobalizationPreferences::HomeGeographicRegion); + twoDigitNumberFormatter->FractionDigits = 0; + twoDigitNumberFormatter->IsGrouped = false; + twoDigitNumberFormatter->IntegerDigits = 2; + + if (hours > 0) + { + // Display Hours naturally, but display minutes and seconds using 2 digits + formattedTimeSpan = ref new String( + (twoDigitNumberFormatter->FormatUInt(hours) + L":" + + twoDigitNumberFormatter->FormatUInt(minutes) + L":" + + twoDigitNumberFormatter->FormatUInt(seconds))->Data()); + } + else + { + // If the hour count is 0, then only display minutes and seconds + formattedTimeSpan = ref new String( + (twoDigitNumberFormatter->FormatUInt(minutes) + L":" + + twoDigitNumberFormatter->FormatUInt(seconds))->Data()); + } + return formattedTimeSpan; +} diff --git a/Samples/360VideoPlayback/cpp/Common/SeekBarElement.h b/Samples/360VideoPlayback/cpp/Common/SeekBarElement.h new file mode 100644 index 0000000000..7606747047 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/SeekBarElement.h @@ -0,0 +1,51 @@ +#pragma once +#include "BaseElement.h" + +namespace DX +{ + class SeekBarElement : public FocusableElement + { + public: + SeekBarElement( + float elementWidth, + float elementHeight = FONT_SIZE * 5.0f, + float leftRightPadding = FONT_SIZE * 2.0f, + float topBottomPadding = FONT_SIZE * 2.0f); + + virtual void Initialize() override; + virtual void Update(const DX::StepTimer& timer, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose) override; + + virtual void PerformAction() override; + + + private: + void UpdateLayoutFromCurrentTime(); + void UpdateSliderPosition(float position); + Platform::String^ FormatTimeString(int64 intervalValue); + + float m_sliderPosition; + float m_sliderWidth; + float m_sliderHeight; + float m_leftRightPadding; + float m_topBottomPadding; + Microsoft::WRL::ComPtr m_frontSegmentBrush; + Microsoft::WRL::ComPtr m_endSegmentBrush; + D2D1_POINT_2F m_sliderFrontSegmentStart; + D2D1_POINT_2F m_sliderFrontSegmentEnd; + D2D1_POINT_2F m_sliderRemainingSegmentStart; + D2D1_POINT_2F m_sliderRemainingSegmentEnd; + std::shared_ptr m_sliderFrontSegment; + std::shared_ptr m_sliderRemainingSegment; + Microsoft::WRL::ComPtr m_brush; + int64 m_currentVideoDuration; + int64 m_currentPlayPosition; + std::wstring m_elapsedTimeString; + std::wstring m_remainingTimeString; + std::shared_ptr m_elapsedTimeText; + std::shared_ptr m_remainingTimeText; + float m_textSize; + double m_secondsElapsedSinceTimeUpdate; + + }; + +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/cpp/Common/StepTimer.h b/Samples/360VideoPlayback/cpp/Common/StepTimer.h new file mode 100644 index 0000000000..eb9f8f6d72 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Common/StepTimer.h @@ -0,0 +1,189 @@ +#pragma once + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + m_qpcFrequency = GetPerformanceFrequency(); + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency / 10; + } + + // Get elapsed time since the previous Update call. + uint64 GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64 GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32 GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32 GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64 targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64 TicksPerSecond = 10'000'000; + + static double TicksToSeconds(uint64 ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64 SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // Convenient wrapper for QueryPerformanceFrequency. Throws an exception if + // the call to QueryPerformanceFrequency fails. + static inline uint64 GetPerformanceFrequency() + { + LARGE_INTEGER freq; + if (!QueryPerformanceFrequency(&freq)) + { + throw ref new Platform::FailureException(); + } + return freq.QuadPart; + } + + // Gets the current number of ticks from QueryPerformanceCounter. Throws an + // exception if the call to QueryPerformanceCounter fails. + static inline int64 GetTicks() + { + LARGE_INTEGER ticks; + if (!QueryPerformanceCounter(&ticks)) + { + throw ref new Platform::FailureException(); + } + return ticks.QuadPart; + } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + m_qpcLastTime = GetTicks(); + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + uint64 currentTime = GetTicks(); + uint64 timeDelta = currentTime - m_qpcLastTime; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency; + + uint32 lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency; + } + } + + private: + + // Source timing data uses QPC units. + uint64 m_qpcFrequency; + uint64 m_qpcLastTime; + uint64 m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64 m_elapsedTicks; + uint64 m_totalTicks; + uint64 m_leftOverTicks; + + // Members for tracking the framerate. + uint32 m_frameCount; + uint32 m_framesPerSecond; + uint32 m_framesThisSecond; + uint64 m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64 m_targetElapsedTicks; + }; +} diff --git a/Samples/360VideoPlayback/cpp/Content/GeometryShader.hlsl b/Samples/360VideoPlayback/cpp/Content/GeometryShader.hlsl new file mode 100644 index 0000000000..4065a36e62 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/GeometryShader.hlsl @@ -0,0 +1,31 @@ +// Per-vertex data from the vertex shader. +struct GeometryShaderInput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint instId : TEXCOORD0; +}; + +// Per-vertex data passed to the rasterizer. +struct GeometryShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint rtvId : SV_RenderTargetArrayIndex; +}; + +// This geometry shader is a pass-through that leaves the geometry unmodified +// and sets the render target array index. +[maxvertexcount(3)] +void main(triangle GeometryShaderInput input[3], inout TriangleStream outStream) +{ + GeometryShaderOutput output; + [unroll(3)] + for (int i = 0; i < 3; ++i) + { + output.pos = input[i].pos; + output.tex = input[i].tex; + output.rtvId = input[i].instId; + outStream.Append(output); + } +} diff --git a/Samples/360VideoPlayback/cpp/Content/GlassGeometryShader.hlsl b/Samples/360VideoPlayback/cpp/Content/GlassGeometryShader.hlsl new file mode 100644 index 0000000000..d0def7e652 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/GlassGeometryShader.hlsl @@ -0,0 +1,34 @@ +// Per-vertex data from the vertex shader. +struct GeometryShaderInput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + float4 worldCoord : TEXCOORD2; + uint instId : TEXCOORD0; +}; + +// Per-vertex data passed to the rasterizer. +struct GeometryShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + float4 worldCoord : TEXCOORD2; + uint rtvId : SV_RenderTargetArrayIndex; +}; + +// This geometry shader is a pass-through that leaves the geometry unmodified +// and sets the render target array index. +[maxvertexcount(3)] +void main(triangle GeometryShaderInput input[3], inout TriangleStream outStream) +{ + GeometryShaderOutput output; + [unroll(3)] + for (int i = 0; i < 3; ++i) + { + output.pos = input[i].pos; + output.tex = input[i].tex; + output.worldCoord = input[i].worldCoord; + output.rtvId = input[i].instId; + outStream.Append(output); + } +} diff --git a/Samples/360VideoPlayback/cpp/Content/GlassPixelShader.hlsl b/Samples/360VideoPlayback/cpp/Content/GlassPixelShader.hlsl new file mode 100644 index 0000000000..1fcbf3bb42 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/GlassPixelShader.hlsl @@ -0,0 +1,41 @@ +cbuffer FocusPointConstantBuffer : register(b1) +{ + min16float4 focusPointOrigin; + min16float4 focusPointDirection; + min16float4 focusPointColor; + min16float4 focusPointRadius; // Using XMFLOAT4 for byte alignment + min16float4 focusPointIntensity; // Using XMFLOAT4 for byte alignment +}; + +Texture2D Texture : register(t0); +SamplerState Sampler : register(s0); + +// Per-pixel color data passed through the pixel shader. +struct PixelShaderInput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + float4 worldCoord : TEXCOORD2; +}; + +// Apply the glass shader color and look to anything marked +// as glass. +min16float4 main(PixelShaderInput input) : SV_TARGET +{ + float4 textureColor = Texture.Sample(Sampler, input.tex); + + // Apply light + float fallOffDistance = focusPointRadius.x; + float3 worldPos = float3(input.worldCoord.x, input.worldCoord.y, input.worldCoord.z); + float3 normalizedFocusDirectionVector = normalize(float3(focusPointDirection.x, focusPointDirection.y, focusPointDirection.z)); + float3 normalizedFocusToPointVect = normalize(worldPos - float3(focusPointOrigin.x, focusPointOrigin.y, focusPointOrigin.z)); + float dotProduct = dot(normalizedFocusDirectionVector, normalizedFocusToPointVect); + float focusDirectionToPointAngle = acos(dotProduct); + float sinAngle = sin(focusDirectionToPointAngle); + float focusToPointVectLength = (length(worldPos - float3(focusPointOrigin.x, focusPointOrigin.y, focusPointOrigin.z))); + float distance = sinAngle * focusToPointVectLength; + float focusIntensity = focusPointIntensity.x * (1.0f - saturate(distance / fallOffDistance)); + + float4 outputColor = lerp(textureColor, focusPointColor, focusIntensity); + return (min16float4)outputColor; +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/cpp/Content/GlassVertexShader.hlsl b/Samples/360VideoPlayback/cpp/Content/GlassVertexShader.hlsl new file mode 100644 index 0000000000..54b182161e --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/GlassVertexShader.hlsl @@ -0,0 +1,61 @@ +// A constant buffer that stores the model transform. +cbuffer ModelConstantBuffer : register(b0) +{ + float4x4 model; +}; + +// A constant buffer that stores each set of view and projection matrices in column-major format. +cbuffer ViewProjectionConstantBuffer : register(b1) +{ + float4x4 viewProjection[2]; +}; + +// Per-vertex data used as input to the vertex shader. +struct VertexShaderInput +{ + min16float3 pos : POSITION; + min16float2 tex : TEXCOORD1; + uint instId : SV_InstanceID; +}; + +// Per-vertex data passed to the geometry shader. +// Note that the render target array index will be set by the geometry shader +// using the value of viewId. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + float4 worldCoord : TEXCOORD2; + uint viewId : TEXCOORD0; // SV_InstanceID % 2 +}; + +// Simple shader to do vertex processing on the GPU. +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Note which view this vertex has been sent to. Used for matrix lookup. + // Taking the modulo of the instance ID allows geometry instancing to be used + // along with stereo instanced drawing; in that case, two copies of each + // instance would be drawn, one for left and one for right. + int idx = input.instId % 2; + + // Transform the vertex position into world space. + pos = mul(pos, model); + + output.worldCoord = pos; + + // Correct for perspective and project the vertex position onto the screen. + pos = mul(pos, viewProjection[idx]); + output.pos = (min16float4)pos; + + // Pass the texture through without modification. + output.tex = input.tex; + + // Set the instance ID. The pass-through geometry shader will set the + // render target array index to whatever value is set here. + output.viewId = idx; + + return output; +} diff --git a/Samples/360VideoPlayback/cpp/Content/MediaTransportControls.cpp b/Samples/360VideoPlayback/cpp/Content/MediaTransportControls.cpp new file mode 100644 index 0000000000..50ac6258aa --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/MediaTransportControls.cpp @@ -0,0 +1,204 @@ +#include "pch.h" +#include "MediaTransportControls.h" +#include "..\Common\DirectXHelper.h" +#include "..\Common\Controls.h" +#include "VideoRenderer.h" +#include "..\Common\SeekbarElement.h" +#include "..\Common\MeshGeometry.h" + +using namespace _360VideoPlayback; +using namespace DX; +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace std; +using namespace Windows::Foundation::Numerics; +using namespace Windows::UI::Input::Spatial; + +const float MAX_INACTIVE_TIME_TO_HIDE = 5.0f; //In seconds +const float3 EXITBUTTON_SCALE{ 0.25f, 0.25f, 0.025f }; +const float3 EXITBUTTON_POSITION{ 0.0f, -0.2f, 0.0f }; +const float3 PLAYPAUSE_SCALE{ 0.25f, 0.25f, 0.025f }; +const float3 PLAYPAUSE_POSITION{ 0.0f, 0.1f, 0.0f }; +const float3 SEEKBAR_POSITION{ 0.0f, -0.08f, 0.0f }; +const unsigned short PLAYPAUSE_TESSELATION = 24; +const UINT PLAYPAUSE_CONTAINER_SIZE = BUTTON_SIZE * 2; +const UINT PLAYPAUSE_TEXT_SIZE = PLAYPAUSE_CONTAINER_SIZE / 2; + +MediaTransportControls::MediaTransportControls() +{ + m_isVisible = false; + m_rotation = float4(0, 0, 0, 0); + m_position = float3(0, 0, 0); + m_shadersLoaded = false; + m_transform = float4x4::identity(); +} + +void MediaTransportControls::Initialize() +{ + this->AddPlayPauseButton(); + this->AddSeekbar(); + this->AddExitButton(); +} + +void MediaTransportControls::AddPlayPauseButton() +{ + auto playPauseButtonElement = std::make_shared(PLAYPAUSE_CONTAINER_SIZE, PLAYPAUSE_TEXT_SIZE); + playPauseButtonElement->Initialize(); + + // Play/pause button control + m_playPauseButtonControl = std::make_shared(MeshGeometry::MakeTexturedCylinder(PLAYPAUSE_TESSELATION)); + m_playPauseButtonControl->SetScale(PLAYPAUSE_SCALE); + m_playPauseButtonControl->SetPosition(PLAYPAUSE_POSITION); + m_playPauseButtonControl->SnapInitialSizeToRootElement(); + m_playPauseButtonControl->SetRenderElement(playPauseButtonElement); + m_playPauseButtonControl->Initialize(); + m_baseControls.push_back(m_playPauseButtonControl); +} + +void MediaTransportControls::AddSeekbar() +{ + auto seekBarStripSize = float2(300.0f, 50.0f); + + auto seekbarElement = std::make_shared( + static_cast(seekBarStripSize.x), + static_cast(seekBarStripSize.y), + static_cast(seekBarStripSize.x) * 0.05f, /*left/right padding*/ + static_cast(seekBarStripSize.y) * 0.44f /*bottom/top padding*/); + + seekbarElement->Initialize(); + seekbarElement->SetTranslation(float2(0.0f, static_cast(seekBarStripSize.y) - seekbarElement->GetElementSize().y)); + + m_seekbarControl = std::make_shared(); + m_seekbarControl->SetTextureWidth(static_cast(seekBarStripSize.x)); + m_seekbarControl->SetTextureHeight(static_cast(seekBarStripSize.y)); + m_seekbarControl->SetScale(float3(0.25f, 0.25f, 0.25f)); + m_seekbarControl->SetPosition(SEEKBAR_POSITION); + m_seekbarControl->SetRenderElement(seekbarElement); + m_seekbarControl->Initialize(); + + m_baseControls.push_back(m_seekbarControl); +} + +void MediaTransportControls::AddExitButton() +{ + // Exit button element + auto exitButtonElement = std::make_shared(); + exitButtonElement->ArrangeElements(); + exitButtonElement->Initialize(); + + // Exit button control + m_exitButtonControl = std::make_shared(); + m_exitButtonControl->SetScale(EXITBUTTON_SCALE); + m_exitButtonControl->SetPosition(EXITBUTTON_POSITION); + m_exitButtonControl->SnapInitialSizeToRootElement(); + m_exitButtonControl->SetRenderElement(exitButtonElement); + m_exitButtonControl->Initialize(); + + m_baseControls.push_back(m_exitButtonControl); +} + +void MediaTransportControls::Update(const StepTimer& timer, SpatialPointerPose^ cameraPose) +{ + const XMMATRIX modelRotation = XMMatrixRotationQuaternion(XMLoadFloat4(&m_rotation)); + const XMMATRIX modelTranslation = XMMatrixTranslationFromVector(XMLoadFloat3(&m_position)); + const XMMATRIX localTransform = XMMatrixMultiply(modelRotation, modelTranslation); + XMStoreFloat4x4(&m_transform, localTransform); + + if (m_isVisible) + { + if (this->IsFocused()) + { + m_inactiveSecondsCounter = 0.0f; + } + else + { + m_inactiveSecondsCounter += static_cast(timer.GetElapsedSeconds()); + if (m_inactiveSecondsCounter >= MAX_INACTIVE_TIME_TO_HIDE) + { + Hide(); + } + } + } + + // Update the Controls + for (const auto& control : m_baseControls) + { + control->SetParentTransform(m_transform); + control->Update(timer, cameraPose); + } +} + +void MediaTransportControls::Render() +{ + if (m_isVisible && m_shadersLoaded) + { + for (const auto& control : m_baseControls) + { + control->Render(); + } + } +} + +void MediaTransportControls::PerformPressedAction() +{ + bool pressedFocusedElement = false; + for (const auto& control : m_baseControls) + { + if (control->IsFocused()) + { + control->PerformPressedAction(); + pressedFocusedElement = true; + break; + } + } + + if (!pressedFocusedElement) + { + Hide(); + } +} + +void MediaTransportControls::Show(SpatialPointerPose^ cameraPose, float distance) +{ + const float3 headPosition = cameraPose->Head->Position; + const float3 headDirection = cameraPose->Head->ForwardDirection; + m_position = headPosition + (distance * headDirection); + m_rotation = ComputeLookAtQuaternion(m_position, cameraPose->Head->Position, float3(0.0f, 1.0f, 0.0f)); + m_isVisible = true; + for (const auto& control : m_baseControls) + { + control->SetIsVisible(true); + } + m_inactiveSecondsCounter = 0.0f; +} + +void MediaTransportControls::Hide() +{ + m_isVisible = false; + for (const auto& control : m_baseControls) + { + control->SetIsVisible(false); + } + m_inactiveSecondsCounter = 0.0f; +} + +void MediaTransportControls::ApplyShaders() +{ + for (const auto& control : m_baseControls) + { + control->ApplyShaders(); + } + m_shadersLoaded = true; +} + +bool MediaTransportControls::IsFocused() +{ + for (const auto& control : m_baseControls) + { + if (control->IsFocused()) + { + return true; + } + } + return false; +} diff --git a/Samples/360VideoPlayback/cpp/Content/MediaTransportControls.h b/Samples/360VideoPlayback/cpp/Content/MediaTransportControls.h new file mode 100644 index 0000000000..03ee6b2beb --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/MediaTransportControls.h @@ -0,0 +1,55 @@ +#pragma once + +#include "..\Common\CameraResources.h" +#include "..\Common\DeviceResources.h" +#include "..\Common\StepTimer.h" +#include "..\Common\BaseControl.h" + +using namespace DX; +namespace _360VideoPlayback +{ + // Media Transport Controls (MTC) for playback in a 3D environment + // Although structured to a RenderObject, the MTC itself has no Geometry, it contains other items which are renderable + class MediaTransportControls + { + public: + MediaTransportControls(); + + void Initialize(); + void Update(const DX::StepTimer& timer, Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose); + void Render(); + void PerformPressedAction(); + void ApplyShaders(); + void Show(Windows::UI::Input::Spatial::SpatialPointerPose^ cameraPose, float distance); + void Hide(); + bool IsFocused(); + bool IsVisible() { return m_isVisible; }; + + private: + float m_inactiveSecondsCounter = 0.0f; + void AddExitButton(); + void AddPlayPauseButton(); + void AddSeekbar(); + inline Windows::Foundation::Numerics::float4 ComputeLookAtQuaternion(Windows::Foundation::Numerics::float3 objectPosition, Windows::Foundation::Numerics::float3 targetPosition, Windows::Foundation::Numerics::float3 upVector) + { + // The Windows::Foundation::Numerics::make_float4x4_look_at() and DirectX::XMLookAtRH() functions are both designed to compute ViewProjection Matrices + // View Projection Matrices are typically the inverse of the Camera's transform matrices and are used to convert vertices from World space to View space + // To "fix" this for our application of pointing models at things, we just need to inverse the resulting ViewProjection from your inputs. + // You can also roll your own vector math to just compute the rotation directly, but we'll stick with the platform calls for now since the inverse call is a minor tax. + Windows::Foundation::Numerics::float4x4 lookAtViewMatrix = Windows::Foundation::Numerics::make_float4x4_look_at(targetPosition, objectPosition, upVector); + Windows::Foundation::Numerics::quaternion worldSpaceLookAtQuaternion = Windows::Foundation::Numerics::inverse(Windows::Foundation::Numerics::make_quaternion_from_rotation_matrix(lookAtViewMatrix)); + return Windows::Foundation::Numerics::float4(worldSpaceLookAtQuaternion.x, worldSpaceLookAtQuaternion.y, worldSpaceLookAtQuaternion.z, worldSpaceLookAtQuaternion.w); + }; + + std::shared_ptr m_exitButtonControl; + std::list> m_baseControls; + std::shared_ptr m_playPauseButtonControl; + std::shared_ptr m_seekbarControl; + bool m_isVisible; + bool m_shadersLoaded; + Windows::Foundation::Numerics::float4 m_rotation; + Windows::Foundation::Numerics::float3 m_position; + Windows::Foundation::Numerics::float4x4 m_transform; + }; + +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/cpp/Content/PixelShader.hlsl b/Samples/360VideoPlayback/cpp/Content/PixelShader.hlsl new file mode 100644 index 0000000000..ad94d557d1 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/PixelShader.hlsl @@ -0,0 +1,17 @@ +Texture2D objectTexture: t0; +SamplerState samp: s0; + +// Per-pixel color data passed through the pixel shader. +struct PixelShaderInput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; +}; + +// The pixel shader passes through the color data. The color data from +// is interpolated and assigned to a pixel at the rasterization step. +min16float4 main(PixelShaderInput input) : SV_TARGET +{ + min16float4 output = min16float4(objectTexture.Sample(samp, input.tex)); + return output; +} diff --git a/Samples/360VideoPlayback/cpp/Content/ShaderStructures.h b/Samples/360VideoPlayback/cpp/Content/ShaderStructures.h new file mode 100644 index 0000000000..1bb62a6700 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/ShaderStructures.h @@ -0,0 +1,31 @@ +#pragma once + +namespace _360VideoPlayback +{ + // Constant buffer used to send hologram position transform to the shader pipeline. + struct ModelConstantBuffer + { + DirectX::XMFLOAT4X4 model; + }; + + // Assert that the constant buffer remains 16-byte aligned (best practice). + static_assert((sizeof(ModelConstantBuffer) % (sizeof(float) * 4)) == 0, "Model constant buffer size must be 16-byte aligned (16 bytes is the length of four floats)."); + + + // Used to send per-vertex data to the vertex shader. + struct VertexPositionTexture + { + DirectX::XMFLOAT3 position; + DirectX::XMFLOAT2 textureCoordinate; + }; + + struct FocusPointConstantBuffer + { + DirectX::XMFLOAT4 focusPointOrigin; + DirectX::XMFLOAT4 focusPointDirection; + DirectX::XMFLOAT4 focusPointColor; + DirectX::XMFLOAT4 focusPointRadius; // Using XMFLOAT4 for byte alignment + DirectX::XMFLOAT4 focusPointIntensity; // Using XMFLOAT4 for byte alignment + }; + static_assert((sizeof(FocusPointConstantBuffer) % (sizeof(float) * 4)) == 0, "FocusPointConstantBuffer size must be 16-byte aligned (16 bytes is the length of four floats)."); +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/cpp/Content/SpatialInputHandler.cpp b/Samples/360VideoPlayback/cpp/Content/SpatialInputHandler.cpp new file mode 100644 index 0000000000..27d3ecc960 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/SpatialInputHandler.cpp @@ -0,0 +1,55 @@ +#include "pch.h" +#include "SpatialInputHandler.h" +#include + +using namespace _360VideoPlayback; + +using namespace std::placeholders; +using namespace Windows::Foundation; +using namespace Windows::UI::Input::Spatial; + +// Creates and initializes a GestureRecognizer that listens to a Person. +SpatialInputHandler::SpatialInputHandler() +{ + // The interaction manager provides an event that informs the app when + // spatial interactions are detected. + m_interactionManager = SpatialInteractionManager::GetForCurrentView(); + + // Bind a handler to the SourcePressed event. + m_sourcePressedEventToken = + m_interactionManager->SourcePressed += + ref new TypedEventHandler( + bind(&SpatialInputHandler::OnSourcePressed, this, _1, _2) + ); + + // + // TODO: Expand this class to use other gesture-based input events as applicable to + // your app. + // +} + +SpatialInputHandler::~SpatialInputHandler() +{ + // Unregister our handler for the OnSourcePressed event. + m_interactionManager->SourcePressed -= m_sourcePressedEventToken; +} + +// Checks if the user performed an input gesture since the last call to this method. +// Allows the main update loop to check for asynchronous changes to the user +// input state. +SpatialInteractionSourceState^ SpatialInputHandler::CheckForInput() +{ + SpatialInteractionSourceState^ sourceState = m_sourceState; + m_sourceState = nullptr; + return sourceState; +} + +void SpatialInputHandler::OnSourcePressed(SpatialInteractionManager^ sender, SpatialInteractionSourceEventArgs^ args) +{ + m_sourceState = args->State; + + // + // TODO: In your app or game engine, rewrite this method to queue + // input events in your input class or event handler. + // +} diff --git a/Samples/360VideoPlayback/cpp/Content/SpatialInputHandler.h b/Samples/360VideoPlayback/cpp/Content/SpatialInputHandler.h new file mode 100644 index 0000000000..0f4663c91a --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/SpatialInputHandler.h @@ -0,0 +1,30 @@ +#pragma once + +namespace _360VideoPlayback +{ + // Sample gesture handler. + // Hooks up events to recognize a tap gesture, and keeps track of input using a boolean value. + class SpatialInputHandler + { + public: + SpatialInputHandler(); + ~SpatialInputHandler(); + + Windows::UI::Input::Spatial::SpatialInteractionSourceState^ CheckForInput(); + + private: + // Interaction event handler. + void OnSourcePressed( + Windows::UI::Input::Spatial::SpatialInteractionManager^ sender, + Windows::UI::Input::Spatial::SpatialInteractionSourceEventArgs^ args); + + // API objects used to process gesture input, and generate gesture events. + Windows::UI::Input::Spatial::SpatialInteractionManager^ m_interactionManager; + + // Event registration token. + Windows::Foundation::EventRegistrationToken m_sourcePressedEventToken; + + // Used to indicate that a Pressed input event was received this frame. + Windows::UI::Input::Spatial::SpatialInteractionSourceState^ m_sourceState = nullptr; + }; +} diff --git a/Samples/360VideoPlayback/cpp/Content/VPRTVertexShader.hlsl b/Samples/360VideoPlayback/cpp/Content/VPRTVertexShader.hlsl new file mode 100644 index 0000000000..56dd228107 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/VPRTVertexShader.hlsl @@ -0,0 +1,58 @@ +// A constant buffer that stores the model transform. +cbuffer ModelConstantBuffer : register(b0) +{ + float4x4 model; +}; + +// A constant buffer that stores each set of view and projection matrices in column-major format. +cbuffer ViewProjectionConstantBuffer : register(b1) +{ + float4x4 viewProjection[2]; +}; + +// Per-vertex data used as input to the vertex shader. +struct VertexShaderInput +{ + min16float3 pos : POSITION; + min16float2 tex : TEXCOORD1; + uint instId : SV_InstanceID; +}; + +// Per-vertex data passed to the geometry shader. +// Note that the render target array index will be set by the geometry shader +// using the value of viewId. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint viewId : SV_RenderTargetArrayIndex; // SV_InstanceID % 2 +}; + + +// Simple shader to do vertex processing on the GPU. +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Note which view this vertex has been sent to. Used for matrix lookup. + // Taking the modulo of the instance ID allows geometry instancing to be used + // along with stereo instanced drawing; in that case, two copies of each + // instance would be drawn, one for left and one for right. + int idx = input.instId % 2; + + // Transform the vertex position into world space. + pos = mul(pos, model); + + // Correct for perspective and project the vertex position onto the screen. + pos = mul(pos, viewProjection[idx]); + output.pos = (min16float4)pos; + + // Pass the color through without modification. + output.tex = input.tex; + + // Set the render target array index. + output.viewId = idx; + + return output; +} diff --git a/Samples/360VideoPlayback/cpp/Content/VertexShader.hlsl b/Samples/360VideoPlayback/cpp/Content/VertexShader.hlsl new file mode 100644 index 0000000000..76b2a63b30 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/VertexShader.hlsl @@ -0,0 +1,58 @@ +// A constant buffer that stores the model transform. +cbuffer ModelConstantBuffer : register(b0) +{ + float4x4 model; +}; + +// A constant buffer that stores each set of view and projection matrices in column-major format. +cbuffer ViewProjectionConstantBuffer : register(b1) +{ + float4x4 viewProjection[2]; +}; + +// Per-vertex data used as input to the vertex shader. +struct VertexShaderInput +{ + min16float3 pos : POSITION; + min16float2 tex : TEXCOORD1; + uint instId : SV_InstanceID; +}; + +// Per-vertex data passed to the geometry shader. +// Note that the render target array index will be set by the geometry shader +// using the value of viewId. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint viewId : TEXCOORD0; // SV_InstanceID % 2 +}; + +// Simple shader to do vertex processing on the GPU. +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Note which view this vertex has been sent to. Used for matrix lookup. + // Taking the modulo of the instance ID allows geometry instancing to be used + // along with stereo instanced drawing; in that case, two copies of each + // instance would be drawn, one for left and one for right. + int idx = input.instId % 2; + + // Transform the vertex position into world space. + pos = mul(pos, model); + + // Correct for perspective and project the vertex position onto the screen. + pos = mul(pos, viewProjection[idx]); + output.pos = (min16float4)pos; + + // Pass the text through without modification. + output.tex = input.tex; + + // Set the instance ID. The pass-through geometry shader will set the + // render target array index to whatever value is set here. + output.viewId = idx; + + return output; +} diff --git a/Samples/360VideoPlayback/cpp/Content/VideoRenderer.cpp b/Samples/360VideoPlayback/cpp/Content/VideoRenderer.cpp new file mode 100644 index 0000000000..ff6840e414 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/VideoRenderer.cpp @@ -0,0 +1,441 @@ +#include "pch.h" +#include "VideoRenderer.h" +#include "Common\DirectXHelper.h" +#include "Windows.Graphics.DirectX.Direct3D11.interop.h" +#include "AppView.h" + +using namespace _360VideoPlayback; +using namespace concurrency; +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace std::placeholders; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Numerics; +using namespace Windows::Graphics::DirectX::Direct3D11; +using namespace Windows::Media::Core; +using namespace Windows::Media::Playback; +using namespace Windows::UI::Input::Spatial; + +// Loads vertex and pixel shaders from files and instantiates the cube geometry. +VideoRenderer::VideoRenderer() + +{ + m_deviceResources = _360VideoPlaybackMain::GetDeviceResources(); + const CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateBuffer( + &constantBufferDesc, + nullptr, + &m_modelConstantBuffer)); +} + +// Called once per frame. +void VideoRenderer::Update(const DX::StepTimer& timer) +{ + float3 scale = 10.0f; + const XMMATRIX modelScale = XMMatrixScalingFromVector(XMLoadFloat3(&scale)); + const XMMATRIX localTransform = modelScale; + XMStoreFloat4x4(&m_modelConstantBufferData.model, XMMatrixTranspose(localTransform)); +} + +// Renders one frame using the vertex and pixel shaders. +// On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3:: +// VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature, +// a pass-through geometry shader is also used to set the render +// target array index. +void VideoRenderer::Render() +{ + critical_section::scoped_lock lock(m_critical); + // Loading is asynchronous. Resources must be created before drawing can occur. + if (!m_loadingComplete) + { + return; + } + + // Use the D3D device context to update Direct3D device-based resources. + const auto context = m_deviceResources->GetD3DDeviceContext(); + + // Update the model transform buffer for the hologram. + context->UpdateSubresource( + m_modelConstantBuffer.Get(), + 0, + nullptr, + &m_modelConstantBufferData, + 0, + 0 + ); + + + // Each vertex is one instance of the VertexPositionColor struct. + const UINT stride = sizeof(VertexPositionTexture); + const UINT offset = 0; + context->IASetVertexBuffers( + 0, + 1, + m_vertexBuffer.GetAddressOf(), + &stride, + &offset + ); + context->IASetIndexBuffer( + m_indexBuffer.Get(), + DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short). + 0 + ); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->IASetInputLayout(m_inputLayout.Get()); + + // Attach the vertex shader. + context->VSSetShader( + m_vertexShader.Get(), + nullptr, + 0 + ); + // Apply the model constant buffer to the vertex shader. + context->VSSetConstantBuffers( + 0, + 1, + m_modelConstantBuffer.GetAddressOf() + ); + + if (!m_usingVprtShaders) + { + // On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature, + // a pass-through geometry shader is used to set the render target + // array index. + context->GSSetShader( + m_geometryShader.Get(), + nullptr, + 0 + ); + } + + // Attach the pixel shader. + context->PSSetShader( + m_pixelShader.Get(), + nullptr, + 0 + ); + + // Set the Texture Shader resource and samplers + context->PSSetShaderResources(0, 1, m_textureView.GetAddressOf()); + context->PSSetSamplers( + 0, + 1, + m_quadTextureSamplerState.GetAddressOf() + ); + + + // Draw the objects. + context->DrawIndexedInstanced( + m_indexCount, // Index count per instance. + 2, // Instance count. + 0, // Start index location. + 0, // Base vertex location. + 0 // Start instance location. + ); + +} + +void VideoRenderer::CreateDeviceDependentResources() +{ + m_usingVprtShaders = m_deviceResources->GetDeviceSupportsVprt(); + + // Create the Texture, ShaderResource and Sampler state + + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateTexture2D( + &CD3D11_TEXTURE2D_DESC( + DXGI_FORMAT_R8G8B8A8_UNORM, + AppView::GetMediaPlayer()->PlaybackSession->NaturalVideoWidth, // Width + AppView::GetMediaPlayer()->PlaybackSession->NaturalVideoHeight, // Height + 1, // MipLevels + 1, // ArraySize + D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET + ), + nullptr, + &m_texture + ) + ); + + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateShaderResourceView( + m_texture.Get(), nullptr, + &m_textureView + ) + ); + + + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(D3D11_SAMPLER_DESC)); + + + desc.Filter = D3D11_FILTER_ANISOTROPIC; + desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.MaxAnisotropy = 3; + desc.MinLOD = 0; + desc.MaxLOD = 3; + desc.MipLODBias = 0.f; + desc.BorderColor[0] = 0.f; + desc.BorderColor[1] = 0.f; + desc.BorderColor[2] = 0.f; + desc.BorderColor[3] = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateSamplerState( + &desc, + &m_quadTextureSamplerState + ) + ); + + CreateD3D11Surface(); + LoadShaders(); +} + +void VideoRenderer::LoadShaders() +{ + // On devices that do support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature + // we can avoid using a pass-through geometry shader to set the render + // target array index, thus avoiding any overhead that would be + // incurred by setting the geometry shader stage. + std::wstring vertexShaderFileName = m_usingVprtShaders ? L"ms-appx:///VprtVertexShader.cso" : L"ms-appx:///VertexShader.cso"; + + // Load shaders asynchronously. + task> loadVSTask = DX::ReadDataAsync(vertexShaderFileName); + task> loadPSTask = DX::ReadDataAsync(L"ms-appx:///PixelShader.cso"); + + task> loadGSTask; + if (!m_usingVprtShaders) + { + // Load the pass-through geometry shader. + loadGSTask = DX::ReadDataAsync(L"ms-appx:///GeometryShader.cso"); + } + + // After the vertex shader file is loaded, create the shader and input layout. + task createVSTask = loadVSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateVertexShader( + fileData.data(), + fileData.size(), + nullptr, + &m_vertexShader + ) + ); + + constexpr std::array vertexDesc = + { { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + } }; + + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateInputLayout( + vertexDesc.data(), + static_cast(vertexDesc.size()), + fileData.data(), + static_cast(fileData.size()), + &m_inputLayout + ) + ); + }); + + // After the pixel shader file is loaded, create the shader and constant buffer. + task createPSTask = loadPSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreatePixelShader( + fileData.data(), + fileData.size(), + nullptr, + &m_pixelShader + ) + ); + + + }); + + task createGSTask; + if (!m_usingVprtShaders) + { + // After the pass-through geometry shader file is loaded, create the shader. + createGSTask = loadGSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateGeometryShader( + fileData.data(), + fileData.size(), + nullptr, + &m_geometryShader + ) + ); + }); + } + + // Once all shaders are loaded, create the mesh. + task shaderTaskGroup = m_usingVprtShaders ? (createPSTask && createVSTask) : (createPSTask && createVSTask && createGSTask); + task createSphereTask = shaderTaskGroup.then([this]() + { + ComputeSphere(16, true); + }); + + // Once the Sphere is created, the object is ready to be rendered. + createSphereTask.then([this]() + { + m_loadingComplete = true; + }); +} + +void VideoRenderer::ReleaseDeviceDependentResources() +{ + m_loadingComplete = false; + m_usingVprtShaders = false; + m_vertexShader.Reset(); + m_inputLayout.Reset(); + m_pixelShader.Reset(); + m_geometryShader.Reset(); + m_modelConstantBuffer.Reset(); + m_vertexBuffer.Reset(); + m_indexBuffer.Reset(); + if (m_videoFrameAvailToken.Value) + { + if (AppView::GetMediaPlayer() != nullptr) + { + AppView::GetMediaPlayer()->VideoFrameAvailable -= m_videoFrameAvailToken; + } + } +} + +void VideoRenderer::ComputeSphere(unsigned short tessellation, bool invertn) +{ + if (tessellation < 3) + throw std::out_of_range("tesselation parameter out of range"); + + unsigned short verticalSegments = tessellation; + unsigned short horizontalSegments = tessellation * 2; + const unsigned short vertCount = (verticalSegments + 1) * (horizontalSegments + 1); + unsigned short indexCount = (verticalSegments) * (horizontalSegments + 1) * 6; + + float radius = 0.5f; // Diameter of the default Sphere will always be 1 to stay aligned + + std::vector sphereVertices; + + for (unsigned short i = 0; i <= verticalSegments; i++) + { + float v = 1 - (float)i / verticalSegments; + + float latitude = (i * XM_PI / verticalSegments) - XM_PIDIV2; + float dy, dxz; + + XMScalarSinCos(&dy, &dxz, latitude); + + // Create a single ring of vertices at this latitude. + for (unsigned short j = 0; j <= horizontalSegments; j++) + { + float u = (float)j / horizontalSegments; + + float longitude = j * XM_2PI / horizontalSegments; + float dx, dz; + + XMScalarSinCos(&dx, &dz, longitude); + + dx *= dxz; + dz *= dxz; + + XMVECTOR normal = XMVectorSet(dx, dy, dz, 0) * radius; + XMFLOAT3 normalFloat3; + XMStoreFloat3(&normalFloat3, normal); + VertexPositionTexture vert; + vert.position = normalFloat3; + + vert.textureCoordinate = XMFLOAT2(1.0f - u, v); + + sphereVertices.push_back(vert); + } + } + + + std::vector sphereIndices; + + // Fill the index buffer with triangles joining each pair of latitude rings. + unsigned short stride = horizontalSegments + 1; + for (unsigned short i = 0; i < verticalSegments; i++) + { + for (unsigned short j = 0; j <= horizontalSegments; j++) + { + unsigned short nextI = i + 1; + unsigned short nextJ = (j + 1) % stride; + if (!invertn) + { + sphereIndices.push_back(i * stride + j); + sphereIndices.push_back(nextI * stride + j); + sphereIndices.push_back(i * stride + nextJ); + + sphereIndices.push_back(i * stride + nextJ); + sphereIndices.push_back(nextI * stride + j); + sphereIndices.push_back(nextI * stride + nextJ); + } + else + { + sphereIndices.push_back(nextI * stride + j); + sphereIndices.push_back(i * stride + j); + sphereIndices.push_back(i * stride + nextJ); + + sphereIndices.push_back(nextI * stride + j); + sphereIndices.push_back(i * stride + nextJ); + sphereIndices.push_back(nextI * stride + nextJ); + } + } + } + + D3D11_SUBRESOURCE_DATA vertexBufferData = { 0 }; + vertexBufferData.pSysMem = sphereVertices.data(); + vertexBufferData.SysMemPitch = 0; + vertexBufferData.SysMemSlicePitch = 0; + const CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(VertexPositionTexture) * vertCount, D3D11_BIND_VERTEX_BUFFER); + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateBuffer( + &vertexBufferDesc, + &vertexBufferData, + &m_vertexBuffer + ) + ); + + m_indexCount = indexCount; + + D3D11_SUBRESOURCE_DATA indexBufferData = { 0 }; + indexBufferData.pSysMem = sphereIndices.data(); + indexBufferData.SysMemPitch = 0; + indexBufferData.SysMemSlicePitch = 0; + CD3D11_BUFFER_DESC indexBufferDesc(sizeof(unsigned short) * indexCount, D3D11_BIND_INDEX_BUFFER); + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateBuffer( + &indexBufferDesc, + &indexBufferData, + &m_indexBuffer + ) + ); +} + +void VideoRenderer::CreateD3D11Surface() +{ + Microsoft::WRL::ComPtr spDXGIInterfaceAccess; + DX::ThrowIfFailed(m_texture->QueryInterface(IID_PPV_ARGS(&spDXGIInterfaceAccess))); + m_surface = CreateDirect3DSurface(spDXGIInterfaceAccess.Get()); + m_videoFrameAvailToken = + AppView::GetMediaPlayer()->VideoFrameAvailable += + ref new TypedEventHandler( + std::bind(&VideoRenderer::OnVideoFrameAvailable, this)); + AppView::GetMediaPlayer()->Play(); +} + +void VideoRenderer::OnVideoFrameAvailable() +{ + critical_section::scoped_lock lock(m_critical); + AppView::GetMediaPlayer()->CopyFrameToVideoSurface(m_surface); +} + diff --git a/Samples/360VideoPlayback/cpp/Content/VideoRenderer.h b/Samples/360VideoPlayback/cpp/Content/VideoRenderer.h new file mode 100644 index 0000000000..37b58c3544 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Content/VideoRenderer.h @@ -0,0 +1,55 @@ +#pragma once + +#include "..\Common\DeviceResources.h" +#include "..\Common\StepTimer.h" +#include "ShaderStructures.h" +#include + +namespace _360VideoPlayback +{ + // This sample renderer instantiates a basic rendering pipeline. + class VideoRenderer + { + public: + VideoRenderer(); + void CreateDeviceDependentResources(); + void ReleaseDeviceDependentResources(); + void Update(const DX::StepTimer& timer); + void Render(); + void ComputeSphere(unsigned short tessellation, bool invertn); + void LoadShaders(); + void CreateD3D11Surface(); + private: + // Cached pointer to device resources. + std::shared_ptr m_deviceResources; + + // Direct3D resources for cube geometry. + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_geometryShader; + Microsoft::WRL::ComPtr m_pixelShader; + Microsoft::WRL::ComPtr m_modelConstantBuffer; + + // System resources for cube geometry. + ModelConstantBuffer m_modelConstantBufferData; + uint32 m_indexCount = 0; + + // Variables used with the rendering loop. + bool m_loadingComplete = false; + float m_degreesPerSecond = 45.f; + + // If the current D3D Device supports VPRT, we can avoid using a geometry +// shader just to set the render target array index. + bool m_usingVprtShaders = false; + + Microsoft::WRL::ComPtr m_texture; + Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface^ m_surface; + Microsoft::WRL::ComPtr m_textureView; + Microsoft::WRL::ComPtr m_quadTextureSamplerState; + void OnVideoFrameAvailable(); + Windows::Foundation::EventRegistrationToken m_videoFrameAvailToken; + Concurrency::critical_section m_critical; + }; +} diff --git a/Samples/360VideoPlayback/cpp/MainPage.xaml.cpp b/Samples/360VideoPlayback/cpp/MainPage.xaml.cpp new file mode 100644 index 0000000000..5ff6171f39 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/MainPage.xaml.cpp @@ -0,0 +1,32 @@ +// +// MainPage.xaml.cpp +// Implementation of the MainPage class +// + +#include "pch.h" +#include "MainPage.xaml.h" +#include "VideoGallery.xaml.h" + +using namespace _360VideoPlayback; + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::UI::Core; +using namespace Windows::UI::Xaml::Interop; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +MainPage::MainPage() +{ + InitializeComponent(); + SystemNavigationManager::GetForCurrentView()->BackRequested += ref new EventHandler(this, &MainPage::OnBackRequested); + this->contentFrame->Navigate(TypeName(VideoGallery::typeid)); +} + +void MainPage::OnBackRequested(Object^ sender, BackRequestedEventArgs^ args) +{ + if (this->contentFrame->CanGoBack) + { + this->contentFrame->GoBack(); + } +} diff --git a/Samples/360VideoPlayback/cpp/MainPage.xaml.h b/Samples/360VideoPlayback/cpp/MainPage.xaml.h new file mode 100644 index 0000000000..95d928df39 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/MainPage.xaml.h @@ -0,0 +1,23 @@ +// +// MainPage.xaml.h +// Declaration of the MainPage class +// + +#pragma once + +#include "MainPage.g.h" +#include "VideoGallery.xaml.h" + +namespace _360VideoPlayback +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public ref class MainPage sealed + { + public: + MainPage(); + private: + void OnBackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ args); + }; +} diff --git a/Samples/360VideoPlayback/cpp/Package.appxmanifest b/Samples/360VideoPlayback/cpp/Package.appxmanifest new file mode 100644 index 0000000000..23c455a1b2 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/Package.appxmanifest @@ -0,0 +1,44 @@ + + + + + + 360 Video Playback C++ Sample + Microsoft Corporation + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/360VideoPlayback/cpp/PlaybackPage.xaml.cpp b/Samples/360VideoPlayback/cpp/PlaybackPage.xaml.cpp new file mode 100644 index 0000000000..9ff76f55ac --- /dev/null +++ b/Samples/360VideoPlayback/cpp/PlaybackPage.xaml.cpp @@ -0,0 +1,396 @@ +// +// PlaybackPage.xaml.cpp +// Implementation of the PlaybackPage class +// + +#include "pch.h" +#include "PlaybackPage.xaml.h" +#include "VideoGallery.xaml.h" + +using namespace _360VideoPlayback; +using namespace DirectX; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Numerics; +using namespace Windows::Gaming::Input; +using namespace Windows::Media::Core; +using namespace Windows::Media::Playback; +using namespace Windows::System; +using namespace Windows::System::Threading; +using namespace Windows::UI::Core; +using namespace Windows::UI::Popups; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Input; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Navigation; + +const double THUMBSTICK_DEADZONE = 0.25f; +const int scrollStep = 2; +const int mouseWheelData = 120; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +quaternion CreateFromHeadingPitchRoll(double flHeading, double flPitch, double flRoll) +{ + // Here we are creating the quaternion assuming Tait–Bryan angles and applying the + // angles in order of yaw, pitch, roll. + // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles + quaternion result; + + const float headingPart = (XMConvertToRadians((float)flHeading) * 0.5f); // clockwise + const float sin1 = sin(headingPart); + const float cos1 = cos(headingPart); + + const float pitchPart = (XMConvertToRadians(-(float)flPitch) * 0.5f); // counterclockwise + const float sin2 = sin(pitchPart); + const float cos2 = cos(pitchPart); + + const float rollPart = (XMConvertToRadians((float)flRoll) * 0.5f); // clockwise + const float sin3 = sin(rollPart); + const float cos3 = cos(rollPart); + + result.w = cos1 * cos2 * cos3 - sin1 * sin2 * sin3; + result.x = cos1 * cos2 * sin3 + sin1 * sin2 * cos3; + result.y = sin1 * cos2 * cos3 + cos1 * sin2 * sin3; + result.z = cos1 * sin2 * cos3 - sin1 * cos2 * sin3; + + return result; +} + +PlaybackPage::PlaybackPage() +{ + m_centerX = 0; + m_centerY = 0; + m_pitch = 0; + m_heading = 0; + m_rotationdelta = 1.8f; + InitializeComponent(); + OnLayoutUpdatedToken = + this->LayoutUpdated += ref new EventHandler(this, &PlaybackPage::OnLayoutUpdated); +} + +void PlaybackPage::OnLayoutUpdated(Object^ sender, Object^ args) +{ + m_centerX = this->VideoElement->ActualWidth / 2; + m_centerY = this->VideoElement->ActualHeight / 2; + if (this->m_mtcGrid == nullptr) + { + FrameworkElement^ transportControlsTemplateRoot = (FrameworkElement^)(VisualTreeHelper::GetChild(this->VideoElement->TransportControls, 0)); + if (transportControlsTemplateRoot != nullptr) + { + this->m_mtcGrid = (Grid^)transportControlsTemplateRoot->FindName("ControlPanelGrid"); + OnMTCPointerPressedToken = + this->m_mtcGrid->PointerPressed += ref new PointerEventHandler(this, &PlaybackPage::OnPointerPressed); + OnMTCPointerReleasedToken = + this->m_mtcGrid->PointerReleased += ref new PointerEventHandler(this, &PlaybackPage::OnPointerReleased); + OnMTCPointerWheelChangedToken = + this->m_mtcGrid->PointerWheelChanged += ref new PointerEventHandler(this, &PlaybackPage::OnPointerWheelChanged); + OnPointerPressedToken = + this->VideoElement->PointerPressed += ref new PointerEventHandler(this, &PlaybackPage::OnPointerPressed); + OnPointerReleasedToken = + this->VideoElement->PointerReleased += ref new PointerEventHandler(this, &PlaybackPage::OnPointerReleased); + OnPointerMovedToken = + this->VideoElement->PointerMoved += ref new PointerEventHandler(this, &PlaybackPage::OnPointerMoved); + OnPointerWheelChangedToken = + this->VideoElement->PointerWheelChanged += ref new PointerEventHandler(this, &PlaybackPage::OnPointerWheelChanged); + OnKeyDownToken = + Window::Current->CoreWindow->KeyDown += ref new TypedEventHandler(this, &PlaybackPage::OnKeyDown); + } + } +} + +void PlaybackPage::OnPointerPressed(Object^ sender, PointerRoutedEventArgs^ e) +{ + if (e->OriginalSource != m_mtcGrid && IsMediaAlreadyOpened()) + { + m_isPointerPress = true; + } + e->Handled = true; +} + + +void PlaybackPage::OnPointerReleased(Object^ sender, PointerRoutedEventArgs^ e) +{ + ResetState(); + e->Handled = true; +} + + +void PlaybackPage::OnPointerWheelChanged(Object^ sender, PointerRoutedEventArgs^ e) +{ + if (e->OriginalSource != m_mtcGrid) + { + double value = videoProjection->HorizontalFieldOfViewInDegrees + + (scrollStep * e->GetCurrentPoint(VideoElement)->Properties->MouseWheelDelta / mouseWheelData); + if (value > 0 && value <= 180) + { + videoProjection->HorizontalFieldOfViewInDegrees = value; + } + } + e->Handled = true; +} + + +void PlaybackPage::OnPointerMoved(Object^ sender, PointerRoutedEventArgs^ e) +{ + if (e->OriginalSource != m_mtcGrid && m_isPointerPress) + { + double ChangeX = e->GetCurrentPoint(this->VideoElement)->Position.X - m_centerX; + double ChangeY = m_centerY - (e->GetCurrentPoint(VideoElement)->Position.Y); + this->videoProjection->ViewOrientation = CreateFromHeadingPitchRoll(ChangeX, ChangeY, 0); + } + e->Handled = true; +} + + +void PlaybackPage::OnKeyDown(CoreWindow^ sender, KeyEventArgs^ args) +{ + if (IsMediaAlreadyOpened()) + { + bool isMTCEnabled = this->VideoElement->AreTransportControlsEnabled; + + if (args->VirtualKey == VirtualKey::Up) + { + m_pitch = m_pitch + 0.5; + videoProjection->ViewOrientation = CreateFromHeadingPitchRoll(m_heading, m_pitch, 0); + } + if (args->VirtualKey == VirtualKey::Down) + { + m_pitch = m_pitch - 0.5; + videoProjection->ViewOrientation = CreateFromHeadingPitchRoll(m_heading, m_pitch, 0); + } + if (args->VirtualKey == VirtualKey::Right) + { + m_heading = m_heading + 0.5; + videoProjection->ViewOrientation = CreateFromHeadingPitchRoll(m_heading, m_pitch, 0); + } + if (args->VirtualKey == VirtualKey::Left) + { + m_heading = m_heading - 0.5; + videoProjection->ViewOrientation = CreateFromHeadingPitchRoll(m_heading, m_pitch, 0); + } + if (args->VirtualKey == VirtualKey::GamepadA) + { + if (!isMTCEnabled) + { + this->VideoElement->AreTransportControlsEnabled = true; + m_inputLoopWorker->Cancel(); + args->Handled = true; + } + + } + if (args->VirtualKey == VirtualKey::GamepadB) + { + if (isMTCEnabled) + { + this->VideoElement->AreTransportControlsEnabled = false; + StartInputLoop(); + args->Handled = true; + } + } + if (args->VirtualKey == VirtualKey::GamepadLeftTrigger) + { + double value = videoProjection->HorizontalFieldOfViewInDegrees + 2; + + if (value <= 180) + { + videoProjection->HorizontalFieldOfViewInDegrees = value; + } + args->Handled = true; + } + if (args->VirtualKey == VirtualKey::GamepadRightTrigger) + { + double value = videoProjection->HorizontalFieldOfViewInDegrees - 2; + + if (value > 0) + { + videoProjection->HorizontalFieldOfViewInDegrees = value; + } + args->Handled = true; + } + } +} + +void PlaybackPage::OnNavigatedTo(NavigationEventArgs^ e) +{ + SystemNavigationManager::GetForCurrentView()->AppViewBackButtonVisibility = AppViewBackButtonVisibility::Visible; + + Uri^ sourceUri = safe_cast(e->Parameter); + if (sourceUri != nullptr) + { + this->m_player = ref new MediaPlayer(); + MediaSource^ source = MediaSource::CreateFromUri(sourceUri); + m_player->Source = source; + OnMediaOpenedToken = + m_player->MediaOpened += ref new TypedEventHandler(this, &PlaybackPage::OnMediaOpened); + this->VideoElement->SetMediaPlayer(m_player); + } +} + + +bool PlaybackPage::IsMediaAlreadyOpened() +{ + if (m_player != nullptr && videoProjection != nullptr && + m_player->PlaybackSession->PlaybackState != MediaPlaybackState::Opening && + m_player->PlaybackSession->PlaybackState != MediaPlaybackState::None) + { + return true; + } + return false; +} + + +void PlaybackPage::ResetState() +{ + m_isPointerPress = false; + m_pitch = 0; + m_heading = 0; +} + +void PlaybackPage::OnMediaOpened(MediaPlayer^ sender, Object^ args) +{ + videoProjection = m_player->PlaybackSession->SphericalVideoProjection; + Windows::Media::MediaProperties::SphericalVideoFrameFormat videoFormat = videoProjection->FrameFormat; + // Some times Content metadata doesn't provided correct format. Try to force the equirectangular format, if doesn't match + if (videoFormat != Windows::Media::MediaProperties::SphericalVideoFrameFormat::Equirectangular) + { + videoProjection->FrameFormat = Windows::Media::MediaProperties::SphericalVideoFrameFormat::Equirectangular; + } + videoProjection->IsEnabled = true; + videoProjection->HorizontalFieldOfViewInDegrees = 120; + OnPlaybackStateChangedToken = + m_player->PlaybackSession->PlaybackStateChanged += ref new TypedEventHandler(this, &PlaybackPage::OnPlaybackStateChanged); + + StartInputLoop(); +} + + +void PlaybackPage::OnPlaybackStateChanged(MediaPlaybackSession^ sender, Object^ args) +{ + if (m_player->PlaybackSession->PlaybackState == MediaPlaybackState::Playing) + { + m_rotationdelta = 1.8f; + } + else + { + m_rotationdelta = 0.25f; + } +} + +void PlaybackPage::OnNavigatedFrom(NavigationEventArgs^ e) +{ + if (m_player != nullptr) + { + if (OnPlaybackStateChangedToken.Value) + { + m_player->PlaybackSession->PlaybackStateChanged -= OnPlaybackStateChangedToken; + } + if (OnMediaOpenedToken.Value) + { + m_player->MediaOpened -= OnMediaOpenedToken; + } + m_player->Source = nullptr; + } + + if (m_mtcGrid != nullptr) + { + this->m_mtcGrid->PointerPressed -= OnMTCPointerPressedToken; + this->m_mtcGrid->PointerReleased -= OnMTCPointerReleasedToken; + this->m_mtcGrid->PointerWheelChanged -= OnMTCPointerWheelChangedToken; + } + + if (this->VideoElement != nullptr) + { + this->VideoElement->PointerPressed -= OnPointerPressedToken; + this->VideoElement->PointerReleased -= OnPointerReleasedToken; + this->VideoElement->PointerMoved -= OnPointerMovedToken; + this->VideoElement->PointerWheelChanged -= OnPointerWheelChangedToken; + } + + if (Window::Current != nullptr) + { + Window::Current->CoreWindow->KeyDown -= OnKeyDownToken; + } + + this->LayoutUpdated -= OnLayoutUpdatedToken; + + SystemNavigationManager::GetForCurrentView()->AppViewBackButtonVisibility = AppViewBackButtonVisibility::Collapsed; + this->VideoElement->SetMediaPlayer(nullptr); + m_player = nullptr; +} + +void PlaybackPage::StartInputLoop() +{ + if (this->m_inputLoopWorker != nullptr) + { + if (m_inputLoopWorker->Status == AsyncStatus::Started) + { + return; + } + else + { + m_inputLoopWorker->Close(); + } + } + + auto workItem = ref new WorkItemHandler( + [this](IAsyncAction^ workItem) + { + while (workItem->Status == AsyncStatus::Started) + { + if (this->m_activeGamePad == nullptr) + { + auto gamepads = Gamepad::Gamepads; + if (gamepads->Size > 0) + { + // Get the Zero based first Gamepad + m_activeGamePad = gamepads->GetAt(0); + } + } + + if (this->m_activeGamePad != nullptr) + { + m_timer.Tick([this]() + { + // Put time-based updates here. By default this code will run once per frame, + // but if you change the StepTimer to use a fixed time step this code will + // run as many times as needed to get to the current step. + // + + GamepadReading reading = m_activeGamePad->GetCurrentReading(); + double deltax; + if (reading.LeftThumbstickX > THUMBSTICK_DEADZONE || reading.LeftThumbstickX < -THUMBSTICK_DEADZONE) + { + deltax = reading.LeftThumbstickX * reading.LeftThumbstickX * reading.LeftThumbstickX; + } + else + { + deltax = 0.0f; + } + double deltay; + if (reading.LeftThumbstickY > THUMBSTICK_DEADZONE || reading.LeftThumbstickY < -THUMBSTICK_DEADZONE) + { + deltay = reading.LeftThumbstickY * reading.LeftThumbstickY * reading.LeftThumbstickY; + } + else + { + deltay = 0.0f; + } + + double rotationX = deltax * m_rotationdelta; + double rotationY = deltay * m_rotationdelta; + + m_pitch += rotationY; + m_heading += rotationX; + + // Limit pitch to straight up or straight down. + this->videoProjection->ViewOrientation = CreateFromHeadingPitchRoll(m_heading, m_pitch, 0); + }); + } + } + }); + + auto asyncAction = ThreadPool::RunAsync(workItem); + m_inputLoopWorker = asyncAction; +} diff --git a/Samples/360VideoPlayback/cpp/PlaybackPage.xaml.h b/Samples/360VideoPlayback/cpp/PlaybackPage.xaml.h new file mode 100644 index 0000000000..1d500ef363 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/PlaybackPage.xaml.h @@ -0,0 +1,67 @@ +// +// PlaybackPage.xaml.h +// Declaration of the PlaybackPage class +// + +#pragma once + +#include "PlaybackPage.g.h" +#include "Common\StepTimer.h" + +namespace _360VideoPlayback +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public ref class PlaybackPage sealed + { + public: + PlaybackPage(); + + protected: + void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; + void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; + + private: + + Windows::Media::Playback::MediaPlayer^ m_player; + // positions hold the center of the window + double m_centerX = 0, m_centerY = 0; + // MTC grid to ignore mouse event on the MTC Panel + Windows::UI::Xaml::Controls::Grid^ m_mtcGrid; + double m_pitch; + double m_heading; + // Framebased timer. + DX::StepTimer m_timer; + + Windows::Media::Playback::MediaPlaybackSphericalVideoProjection^ videoProjection; + bool m_isPointerPress = false; + Windows::Foundation::IAsyncAction^ m_inputLoopWorker; + Windows::Gaming::Input::Gamepad^ m_activeGamePad; + double m_rotationdelta; + Windows::Foundation::EventRegistrationToken OnLayoutUpdatedToken; + void OnLayoutUpdated(Platform::Object^ sender, Platform::Object^ args); + bool IsMediaAlreadyOpened(); + void ResetState(); + void StartInputLoop(); + + void OnPointerPressed(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e); + Windows::Foundation::EventRegistrationToken OnPointerPressedToken; + Windows::Foundation::EventRegistrationToken OnMTCPointerPressedToken; + void OnPointerReleased(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e); + Windows::Foundation::EventRegistrationToken OnPointerReleasedToken; + Windows::Foundation::EventRegistrationToken OnMTCPointerReleasedToken; + void OnPointerWheelChanged(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e); + Windows::Foundation::EventRegistrationToken OnPointerWheelChangedToken; + Windows::Foundation::EventRegistrationToken OnMTCPointerWheelChangedToken; + void OnPointerMoved(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e); + Windows::Foundation::EventRegistrationToken OnPointerMovedToken; + Windows::Foundation::EventRegistrationToken OnMTCPointerMovedToken; + void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args); + Windows::Foundation::EventRegistrationToken OnKeyDownToken; + void OnMediaOpened(Windows::Media::Playback::MediaPlayer^ sender, Platform::Object^ args); + Windows::Foundation::EventRegistrationToken OnMediaOpenedToken; + void OnPlaybackStateChanged(Windows::Media::Playback::MediaPlaybackSession^ sender, Platform::Object^ args); + Windows::Foundation::EventRegistrationToken OnPlaybackStateChangedToken; + }; +} diff --git a/Samples/360VideoPlayback/cpp/VideoGallery.xaml.cpp b/Samples/360VideoPlayback/cpp/VideoGallery.xaml.cpp new file mode 100644 index 0000000000..0efaca6547 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/VideoGallery.xaml.cpp @@ -0,0 +1,90 @@ +// +// VideoGallery.xaml.cpp +// Implementation of the VideoGallery class +// + +#include "pch.h" +#include "VideoGallery.xaml.h" +#include "PlaybackPage.xaml.h" +#include "AppView.h" + +using namespace _360VideoPlayback; +using namespace Platform; +using namespace Platform::Collections; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::Graphics::Holographic; +using namespace Windows::Perception::Spatial::Surfaces; +using namespace Windows::UI::Core; +using namespace Windows::UI::ViewManagement; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Interop; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +int _360VideoPlayback::VideoGallery::mainviewId = 0; + +VideoGallery::VideoGallery() +{ + InitializeComponent(); + mainviewId = ApplicationView::GetForCurrentView()->Id; + this->Loaded += ref new RoutedEventHandler(this, &_360VideoPlayback::VideoGallery::OnLoaded); +} + + +void _360VideoPlayback::VideoGallery::GalleryGridView_ItemClick(Object^ sender, ItemClickEventArgs^ e) +{ + if (e->ClickedItem != nullptr) + { + VideoItem^ selectedVideoItem = safe_cast(e->ClickedItem); + + if ((HolographicSpace::IsSupported && HolographicSpace::IsAvailable) + || SpatialSurfaceObserver::IsSupported()) + { + // If VR or Hololens(or emulator) all attached to then it will play in immersive mode. + // Make sure enable Mixed Reality portal on the PC + auto appViewSource = ref new AppViewSource(selectedVideoItem->SourceUri); + auto appView = CoreApplication::CreateNewView(appViewSource); + appView->Dispatcher->RunAsync( + CoreDispatcherPriority::Normal, + ref new DispatchedHandler([this]() + { + int appviewId = ApplicationView::GetForCurrentView()->Id; + ApplicationViewSwitcher::TryShowAsStandaloneAsync( + appviewId, ViewSizePreference::Default, mainviewId, ViewSizePreference::Default); + })); + } + else + { + Frame->Navigate(TypeName(PlaybackPage::typeid), selectedVideoItem->SourceUri); + } + } +} + +struct VideoItemInfo +{ + const wchar_t* title; + const wchar_t* source; +}; + +const VideoItemInfo sampleVideos[] = { + // You can add more sample videos here. + { + L"Sample Video", + L"https://mediaplatstorage1.blob.core.windows.net/windows-universal-samples-media/SampleVideo.mp4", + } +}; + +void _360VideoPlayback::VideoGallery::OnLoaded(Object^ sender, RoutedEventArgs^ e) +{ + auto videoItemList = ref new Vector(); + for (auto const& info : sampleVideos) + { + auto videoItem = ref new VideoItem(ref new String(info.title), ref new Uri(ref new String(info.source))); + videoItemList->Append(videoItem); + } + + this->GalleryGridView->ItemsSource = videoItemList; +} diff --git a/Samples/360VideoPlayback/cpp/VideoGallery.xaml.h b/Samples/360VideoPlayback/cpp/VideoGallery.xaml.h new file mode 100644 index 0000000000..8ff79028ff --- /dev/null +++ b/Samples/360VideoPlayback/cpp/VideoGallery.xaml.h @@ -0,0 +1,27 @@ +// +// VideoGallery.xaml.h +// Declaration of the VideoGallery class +// + +#pragma once + +#include "VideoGallery.g.h" +#include "VideoItem.h" + +namespace _360VideoPlayback +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public ref class VideoGallery sealed + { + public: + VideoGallery(); + static int GetMainViewId() { return mainviewId; } + + private: + void GalleryGridView_ItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ e); + void OnLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + static int mainviewId; + }; +} diff --git a/Samples/360VideoPlayback/cpp/VideoItem.h b/Samples/360VideoPlayback/cpp/VideoItem.h new file mode 100644 index 0000000000..bccd3111b9 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/VideoItem.h @@ -0,0 +1,39 @@ +#pragma once +namespace _360VideoPlayback +{ + [Windows::UI::Xaml::Data::Bindable] + [Windows::Foundation::Metadata::WebHostHidden] + public ref class VideoItem sealed + { + public: + + VideoItem(Platform::String^ title, Windows::Foundation::Uri^ sourceUri) + : m_title(title), m_sourceUri(sourceUri) + { + } + + property Platform::String^ Title + { + Platform::String^ get() + { + return m_title; + } + } + + property Windows::Foundation::Uri^ SourceUri + { + Windows::Foundation::Uri^ get() + { + return m_sourceUri; + } + } + + private: + Platform::String^ m_title; + Windows::Foundation::Uri^ m_sourceUri; + + }; + + +} + diff --git a/Samples/360VideoPlayback/cpp/pch.cpp b/Samples/360VideoPlayback/cpp/pch.cpp new file mode 100644 index 0000000000..01484ff5aa --- /dev/null +++ b/Samples/360VideoPlayback/cpp/pch.cpp @@ -0,0 +1,6 @@ +// +// pch.cpp +// Include the standard header and generate the precompiled header. +// + +#include "pch.h" diff --git a/Samples/360VideoPlayback/cpp/pch.h b/Samples/360VideoPlayback/cpp/pch.h new file mode 100644 index 0000000000..b6de2ef538 --- /dev/null +++ b/Samples/360VideoPlayback/cpp/pch.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "App.xaml.h" +#include + diff --git a/Samples/360VideoPlayback/cs/360VideoPlayback.csproj b/Samples/360VideoPlayback/cs/360VideoPlayback.csproj new file mode 100644 index 0000000000..e2afdc5952 --- /dev/null +++ b/Samples/360VideoPlayback/cs/360VideoPlayback.csproj @@ -0,0 +1,179 @@ + + + + + Debug + x86 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7} + AppContainerExe + Properties + _360VideoPlayback + 360VideoPlayback + en-US + UAP + 10.0.15063.0 + 10.0.15063.0 + 15 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + pdbonly + x86 + false + prompt + true + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + full + x64 + false + prompt + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + pdbonly + x64 + false + prompt + true + + + + + + + + App.xaml + + + + + + + + + + + + + + + + Properties\AssemblyInfo.cs + + + MainPage.xaml + + + PlaybackPage.xaml + + + VideoGallery.xaml + + + + + + Designer + + + + + Properties\Default.rd.xml + + + Assets\windows-sdk.png + + + Properties\Default.rd.xml + + + Assets\microsoft-sdk.png + + + Assets\smallTile-sdk.png + + + Assets\splash-sdk.png + + + Assets\squareTile-sdk.png + + + Assets\storeLogo-sdk.png + + + Assets\tile-sdk.png + + + + + + + + + + + 14.0 + + + + App.xaml + MSBuild:Compile + Designer + + + MainPage.xaml + MSBuild:Compile + Designer + + + PlaybackPage.xaml + Designer + MSBuild:Compile + + + VideoGallery.xaml + Designer + MSBuild:Compile + + + + + + + This project references NuGet package(s). NuGet Package Restore will attempt to automatically find or download them when you build this project in Visual Studio. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. + + + + + + true + + \ No newline at end of file diff --git a/Samples/360VideoPlayback/cs/360VideoPlayback.sln b/Samples/360VideoPlayback/cs/360VideoPlayback.sln new file mode 100644 index 0000000000..5b6ef7254c --- /dev/null +++ b/Samples/360VideoPlayback/cs/360VideoPlayback.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26403.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "360VideoPlayback", "360VideoPlayback.csproj", "{4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Debug|x64.ActiveCfg = Debug|x64 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Debug|x64.Build.0 = Debug|x64 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Debug|x64.Deploy.0 = Debug|x64 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Debug|x86.ActiveCfg = Debug|x86 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Debug|x86.Build.0 = Debug|x86 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Debug|x86.Deploy.0 = Debug|x86 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Release|x64.ActiveCfg = Release|x64 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Release|x64.Build.0 = Release|x64 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Release|x64.Deploy.0 = Release|x64 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Release|x86.ActiveCfg = Release|x86 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Release|x86.Build.0 = Release|x86 + {4CAA11AB-CA90-4BCF-87DD-40AF5C0337A7}.Release|x86.Deploy.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/360VideoPlayback/cs/App.xaml.cs b/Samples/360VideoPlayback/cs/App.xaml.cs new file mode 100644 index 0000000000..c2efcad9ba --- /dev/null +++ b/Samples/360VideoPlayback/cs/App.xaml.cs @@ -0,0 +1,98 @@ +using System; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; + +namespace _360VideoPlayback +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App : Application + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + this.Suspending += OnSuspending; + Application.Current.RequiresPointerMode = ApplicationRequiresPointerMode.WhenRequested; + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs e) + { +#if DEBUG + if (System.Diagnostics.Debugger.IsAttached) + { + this.DebugSettings.EnableFrameRateCounter = false; + } +#endif + + Frame rootFrame = Window.Current.Content as Frame; + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == null) + { + // Create a Frame to act as the navigation context and navigate to the first page + rootFrame = new Frame(); + + rootFrame.NavigationFailed += OnNavigationFailed; + + if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + //TODO: Load state from previously suspended application + } + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + } + + if (e.PrelaunchActivated == false) + { + if (rootFrame.Content == null) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame.Navigate(typeof(MainPage), e.Arguments); + } + // Ensure the current window is active + Window.Current.Activate(); + } + } + + /// + /// Invoked when Navigation to a certain page fails + /// + /// The Frame which failed navigation + /// Details about the navigation failure + void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + } + + /// + /// Invoked when application execution is being suspended. Application state is saved + /// without knowing whether the application will be terminated or resumed with the contents + /// of memory still intact. + /// + /// The source of the suspend request. + /// Details about the suspend request. + private void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + //TODO: Save application state and stop any background activity + deferral.Complete(); + } + } +} diff --git a/Samples/360VideoPlayback/cs/AppView.cs b/Samples/360VideoPlayback/cs/AppView.cs new file mode 100644 index 0000000000..60786d0c55 --- /dev/null +++ b/Samples/360VideoPlayback/cs/AppView.cs @@ -0,0 +1,305 @@ +using _360VideoPlayback.Common; +using System; +using System.Threading.Tasks; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.ApplicationModel.Core; +using Windows.Graphics.Holographic; +using Windows.Media.Core; +using Windows.Media.Playback; +using Windows.UI.Core; +using Windows.UI.ViewManagement; + +namespace _360VideoPlayback +{ + /// + /// The IFrameworkView connects the app with Windows and handles application lifecycle events. + /// + internal class AppView : IFrameworkView, IDisposable + { + private _360VideoPlaybackMain main; + + private DeviceResources deviceResources; + private bool windowClosed = false; + private bool windowVisible = true; + private bool createShaders = false; + private bool createdShaders = false; + + // The holographic space the app will use for rendering. + private HolographicSpace holographicSpace = null; + bool appViewConsolidated = false; + bool mainWindowReactivated = false; + + static public MediaPlayer mediaPlayer = null; + private Uri sourceUri; + + public AppView(Uri sourceUri) + { + windowVisible = true; + mediaPlayer = new MediaPlayer(); + this.sourceUri = sourceUri; + } + + private void MediaPlayer_MediaOpened(MediaPlayer sender, object args) + { + createShaders = true; + } + + public void Dispose() + { + if (deviceResources != null) + { + deviceResources.Dispose(); + deviceResources = null; + } + + if (main != null) + { + main.Dispose(); + main = null; + } + + if (mediaPlayer != null) + { + mediaPlayer.Dispose(); + mediaPlayer = null; + } + } + + #region IFrameworkView Members + + /// + /// The first method called when the IFrameworkView is being created. + /// Use this method to subscribe for Windows shell events and to initialize your app. + /// + public void Initialize(CoreApplicationView applicationView) + { + CoreWindow window = CoreWindow.GetForCurrentThread(); + if (window != null) + { + window.Activated += OnmainWindowActivated; + } + applicationView.Activated += this.OnViewActivated; + } + + private void OnmainWindowActivated(CoreWindow sender, WindowActivatedEventArgs args) + { + mainWindowReactivated = true; + windowClosed = true; + TryCloseWindow(); + } + + /// + /// Called when the CoreWindow object is created (or re-created). + /// + public void SetWindow(CoreWindow window) + { + ApplicationView.GetForCurrentView().Consolidated += AppView_Consolidated; + + // Register event handlers for app lifecycle. + CoreApplication.Suspending += this.OnSuspending; + CoreApplication.Resuming += this.OnResuming; + + // Register for keypress notifications. + window.KeyDown += this.OnKeyPressed; + + // Register for notification that the app window is being closed. + window.Closed += this.OnWindowClosed; + + // Register for notifications that the app window is losing focus. + window.VisibilityChanged += this.OnVisibilityChanged; + + // At this point we have access to the device and we can create device-dependent + // resources. + deviceResources = new DeviceResources(); + + main = new _360VideoPlaybackMain(deviceResources); + + // Create a holographic space for the core window for the current view. + // Presenting holographic frames that are created by this holographic space will put + // the app into exclusive mode. + holographicSpace = HolographicSpace.CreateForCoreWindow(window); + + // The DeviceResources class uses the preferred DXGI adapter ID from the holographic + // space (when available) to create a Direct3D device. The HolographicSpace + // uses this ID3D11Device to create and manage device-based resources such as + // swap chains. + deviceResources.SetHolographicSpace(holographicSpace); + + // The main class uses the holographic space for updates and rendering. + main.SetHolographicSpace(holographicSpace); + + MediaSource source = MediaSource.CreateFromUri(sourceUri); + mediaPlayer.MediaOpened += MediaPlayer_MediaOpened; + mediaPlayer.Source = source;// Windows.Media.Core.MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/video.mp4")); + + mediaPlayer.IsVideoFrameServerEnabled = true; + mediaPlayer.IsLoopingEnabled = true; + } + + private void AppView_Consolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args) + { + appViewConsolidated = true; + windowClosed = true; + TryCloseWindow(); + Dispose(); + } + + private void TryCloseWindow() + { + CoreWindow window = CoreWindow.GetForCurrentThread(); + window?.Close(); + } + + /// + /// The Load method can be used to initialize scene resources or to load a + /// previously saved app state. + /// + public void Load(string entryPoint) + { + } + + /// + /// This method is called after the window becomes active. It oversees the + /// update, draw, and present loop, and also oversees window message processing. + /// + public void Run() + { + CoreWindow window = CoreWindow.GetForCurrentThread(); + window.Activate(); + while (!windowClosed) + { + if (createShaders) + { + if (!createdShaders) + { + main.CreateVideoShaders(); + createdShaders = true; + } + } + else + { + window.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessOneAndAllPending); + continue; + } + + if (appViewConsolidated || mainWindowReactivated) + { + TryCloseWindow(); + windowClosed = true; + + } + else + { + window.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessAllIfPresent); + if (windowVisible && (null != holographicSpace)) + { + HolographicFrame frame = main.Update(); + + if (main.Render(ref frame)) + { + deviceResources.Present(ref frame); + } + } + } + } + } + + /// + /// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView + /// class is torn down while the app is in the foreground. + // This method is not often used, but IFrameworkView requires it and it will be called for + // holographic apps. + /// + public void Uninitialize() + { + } + + #endregion + + #region Application lifecycle event handlers + + /// + /// Called when the app view is activated. Activates the app's CoreWindow. + /// + private void OnViewActivated(CoreApplicationView sender, IActivatedEventArgs args) + { + // Run() won't start until the CoreWindow is activated. + sender.CoreWindow.Activate(); + } + + private void OnSuspending(object sender, SuspendingEventArgs args) + { + // Save app state asynchronously after requesting a deferral. Holding a deferral + // indicates that the application is busy performing suspending operations. Be + // aware that a deferral may not be held indefinitely; after about five seconds, + // the app will be forced to exit. + var deferral = args.SuspendingOperation.GetDeferral(); + + Task.Run(() => + { + deviceResources.Trim(); + + if (null != main) + { + main.SaveAppState(); + } + + // + // TODO: Insert code here to save your app state. + // + + deferral.Complete(); + }); + } + + private void OnResuming(object sender, object args) + { + // Restore any data or state that was unloaded on suspend. By default, data + // and state are persisted when resuming from suspend. Note that this event + // does not occur if the app was previously terminated. + + if (null != main) + { + main.LoadAppState(); + } + + // + // TODO: Insert code here to load your app state. + // + } + + #endregion; + + #region Window event handlers + + private void OnVisibilityChanged(CoreWindow sender, VisibilityChangedEventArgs args) + { + windowVisible = args.Visible; + } + + private void OnWindowClosed(CoreWindow sender, CoreWindowEventArgs arg) + { + windowClosed = true; + } + + #endregion + + #region Input event handlers + + private async void OnKeyPressed(CoreWindow sender, KeyEventArgs args) + { + if (args.VirtualKey == Windows.System.VirtualKey.Escape) + { + await ApplicationViewSwitcher.SwitchAsync(VideoGallery.mainviewId, ApplicationView.GetForCurrentView().Id, ApplicationViewSwitchingOptions.ConsolidateViews); + } + // + // TODO: Bluetooth keyboards are supported by HoloLens. You can use this method for + // keyboard input if you want to support it as an optional input method for + // your holographic app. + // + } + + #endregion + } +} diff --git a/Samples/360VideoPlayback/cs/AppViewSource.cs b/Samples/360VideoPlayback/cs/AppViewSource.cs new file mode 100644 index 0000000000..aa5879bc2b --- /dev/null +++ b/Samples/360VideoPlayback/cs/AppViewSource.cs @@ -0,0 +1,21 @@ +using Windows.ApplicationModel.Core; +using System; + +namespace _360VideoPlayback +{ + // The entry point for the app. + internal class AppViewSource : IFrameworkViewSource + { + public AppViewSource(Uri sourceUri) + { + this.sourceUri = sourceUri; + } + + public IFrameworkView CreateView() + { + return new AppView(sourceUri); + } + + private Uri sourceUri; + } +} diff --git a/Samples/360VideoPlayback/cs/Assets/360Logo.png b/Samples/360VideoPlayback/cs/Assets/360Logo.png new file mode 100644 index 0000000000..f92a667812 Binary files /dev/null and b/Samples/360VideoPlayback/cs/Assets/360Logo.png differ diff --git a/Samples/360VideoPlayback/cs/Common/CameraResources.cs b/Samples/360VideoPlayback/cs/Common/CameraResources.cs new file mode 100644 index 0000000000..3405dcb2c4 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Common/CameraResources.cs @@ -0,0 +1,299 @@ +using SharpDX.Direct3D11; +using SharpDX.Mathematics.Interop; +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using Windows.Foundation; +using Windows.Graphics.DirectX.Direct3D11; +using Windows.Graphics.Holographic; +using Windows.Perception.Spatial; + +namespace _360VideoPlayback.Common +{ + /// + /// Constant buffer used to send hologram position transform to the shader pipeline. + /// + internal struct ViewProjectionConstantBuffer + { + public Matrix4x4 viewProjectionLeft; + public Matrix4x4 viewProjectionRight; + } + + // Manages DirectX device resources that are specific to a holographic camera, such as the + // back buffer, ViewProjection constant buffer, and viewport. + class CameraResources : Disposer + { + // Direct3D rendering objects. Required for 3D. + RenderTargetView d3dRenderTargetView; + DepthStencilView d3dDepthStencilView; + Texture2D d3dBackBuffer; + + // Device resource to store view and projection matrices. + SharpDX.Direct3D11.Buffer viewProjectionConstantBuffer; + + // Direct3D rendering properties. + SharpDX.DXGI.Format dxgiFormat; + RawViewportF d3dViewport; + Size d3dRenderTargetSize; + + // Indicates whether the camera supports stereoscopic rendering. + bool isStereo = false; + + // Indicates whether this camera has a pending frame. + bool framePending = false; + + // Pointer to the holographic camera these resources are for. + HolographicCamera holographicCamera = null; + + public CameraResources(HolographicCamera holographicCamera) + { + this.holographicCamera = holographicCamera; + isStereo = holographicCamera.IsStereo; + d3dRenderTargetSize = holographicCamera.RenderTargetSize; + + d3dViewport.Height = (float)d3dRenderTargetSize.Height; + d3dViewport.Width = (float)d3dRenderTargetSize.Width; + d3dViewport.X = 0; + d3dViewport.Y = 0; + d3dViewport.MinDepth = 0; + d3dViewport.MaxDepth = 1; + } + + /// + /// Updates resources associated with a holographic camera's swap chain. + /// The app does not access the swap chain directly, but it does create + /// resource views for the back buffer. + /// + public void CreateResourcesForBackBuffer( + DeviceResources deviceResources, + HolographicCameraRenderingParameters cameraParameters + ) + { + var device = deviceResources.D3DDevice; + + // Get the WinRT object representing the holographic camera's back buffer. + IDirect3DSurface surface = cameraParameters.Direct3D11BackBuffer; + + // Get a DXGI interface for the holographic camera's back buffer. + // Holographic cameras do not provide the DXGI swap chain, which is owned + // by the system. The Direct3D back buffer resource is provided using WinRT + // interop APIs. + InteropStatics.IDirect3DDxgiInterfaceAccess surfaceDxgiInterfaceAccess = surface as InteropStatics.IDirect3DDxgiInterfaceAccess; + IntPtr pResource = surfaceDxgiInterfaceAccess.GetInterface(InteropStatics.ID3D11Resource); + SharpDX.Direct3D11.Resource resource = SharpDX.Direct3D11.Resource.FromPointer(pResource); + Marshal.Release(pResource); + + // Get a Direct3D interface for the holographic camera's back buffer. + Texture2D cameraBackBuffer = resource.QueryInterface(); + + // Determine if the back buffer has changed. If so, ensure that the render target view + // is for the current back buffer. + if ((null == d3dBackBuffer) || (d3dBackBuffer.NativePointer != cameraBackBuffer.NativePointer)) + { + // This can change every frame as the system moves to the next buffer in the + // swap chain. This mode of operation will occur when certain rendering modes + // are activated. + d3dBackBuffer = cameraBackBuffer; + + // Create a render target view of the back buffer. + // Creating this resource is inexpensive, and is better than keeping track of + // the back buffers in order to pre-allocate render target views for each one. + d3dRenderTargetView = this.ToDispose(new RenderTargetView(device, BackBufferTexture2D)); + + // Get the DXGI format for the back buffer. + // This information can be accessed by the app using CameraResources::GetBackBufferDXGIFormat(). + Texture2DDescription backBufferDesc = BackBufferTexture2D.Description; + dxgiFormat = backBufferDesc.Format; + + // Check for render target size changes. + Size currentSize = holographicCamera.RenderTargetSize; + if (d3dRenderTargetSize != currentSize) + { + // Set render target size. + d3dRenderTargetSize = HolographicCamera.RenderTargetSize; + + // A new depth stencil view is also needed. + this.RemoveAndDispose(ref d3dDepthStencilView); + } + } + + // Refresh depth stencil resources, if needed. + if (null == DepthStencilView) + { + // Create a depth stencil view for use with 3D rendering if needed. + var depthStencilDesc = new Texture2DDescription + { + Format = SharpDX.DXGI.Format.D16_UNorm, + Width = (int)RenderTargetSize.Width, + Height = (int)RenderTargetSize.Height, + ArraySize = IsRenderingStereoscopic ? 2 : 1, // Create two textures when rendering in stereo. + MipLevels = 1, // Use a single mipmap level. + BindFlags = BindFlags.DepthStencil, + SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0) + }; + + using (var depthStencil = new Texture2D(device, depthStencilDesc)) + { + var depthStencilViewDesc = new DepthStencilViewDescription(); + depthStencilViewDesc.Dimension = IsRenderingStereoscopic ? DepthStencilViewDimension.Texture2DArray : DepthStencilViewDimension.Texture2D; + depthStencilViewDesc.Texture2DArray.ArraySize = IsRenderingStereoscopic ? 2 : 0; + d3dDepthStencilView = this.ToDispose(new DepthStencilView(device, depthStencil, depthStencilViewDesc)); + } + } + + // Create the constant buffer, if needed. + if (null == viewProjectionConstantBuffer) + { + // Create a constant buffer to store view and projection matrices for the camera. + ViewProjectionConstantBuffer viewProjectionConstantBufferData = new ViewProjectionConstantBuffer(); + viewProjectionConstantBuffer = this.ToDispose(SharpDX.Direct3D11.Buffer.Create( + device, + BindFlags.ConstantBuffer, + ref viewProjectionConstantBufferData)); + } + } + + /// + /// Releases resources associated with a holographic display back buffer. + /// + public void ReleaseResourcesForBackBuffer(DeviceResources deviceResources) + { + var context = deviceResources.D3DDeviceContext; + + this.RemoveAndDispose(ref d3dBackBuffer); + this.RemoveAndDispose(ref d3dRenderTargetView); + this.RemoveAndDispose(ref d3dDepthStencilView); + + const int D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT = 8; + RenderTargetView[] nullViews = new RenderTargetView[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; + + // Ensure system references to the back buffer are released by clearing the render + // target from the graphics pipeline state, and then flushing the Direct3D context. + context.OutputMerger.SetRenderTargets(null, nullViews); + context.Flush(); + } + + public void ReleaseAllDeviceResources(DeviceResources deviceResources) + { + ReleaseResourcesForBackBuffer(deviceResources); + this.RemoveAndDispose(ref viewProjectionConstantBuffer); + } + + /// + /// Updates the constant buffer for the display with view and projection + /// matrices for the current frame. + /// + public void UpdateViewProjectionBuffer( + DeviceResources deviceResources, + HolographicCameraPose cameraPose, + SpatialCoordinateSystem coordinateSystem + ) + { + // The system changes the viewport on a per-frame basis for system optimizations. + d3dViewport.X = (float)cameraPose.Viewport.Left; + d3dViewport.Y = (float)cameraPose.Viewport.Top; + d3dViewport.Width = (float)cameraPose.Viewport.Width; + d3dViewport.Height = (float)cameraPose.Viewport.Height; + d3dViewport.MinDepth = 0; + d3dViewport.MaxDepth = 1; + + // The projection transform for each frame is provided by the HolographicCameraPose. + HolographicStereoTransform cameraProjectionTransform = cameraPose.ProjectionTransform; + + // Get a container object with the view and projection matrices for the given + // pose in the given coordinate system. + HolographicStereoTransform? viewTransformContainer = cameraPose.TryGetViewTransform(coordinateSystem); + + // If TryGetViewTransform returns null, that means the pose and coordinate system + // cannot be understood relative to one another; content cannot be rendered in this + // coordinate system for the duration of the current frame. + // This usually means that positional tracking is not active for the current frame, in + // which case it is possible to use a SpatialLocatorAttachedFrameOfReference to render + // content that is not world-locked instead. + ViewProjectionConstantBuffer viewProjectionConstantBufferData = new ViewProjectionConstantBuffer(); + bool viewTransformAcquired = viewTransformContainer.HasValue; + if (viewTransformAcquired) + { + // Otherwise, the set of view transforms can be retrieved. + HolographicStereoTransform viewCoordinateSystemTransform = viewTransformContainer.Value; + + // Update the view matrices. Holographic cameras (such as Microsoft HoloLens) are + // constantly moving relative to the world. The view matrices need to be updated + // every frame. + viewProjectionConstantBufferData.viewProjectionLeft = Matrix4x4.Transpose( + viewCoordinateSystemTransform.Left * cameraProjectionTransform.Left + ); + viewProjectionConstantBufferData.viewProjectionRight = Matrix4x4.Transpose( + viewCoordinateSystemTransform.Right * cameraProjectionTransform.Right + ); + } + + // Use the D3D device context to update Direct3D device-based resources. + var context = deviceResources.D3DDeviceContext; + + // Loading is asynchronous. Resources must be created before they can be updated. + if (context == null || viewProjectionConstantBuffer == null || !viewTransformAcquired) + { + framePending = false; + } + else + { + // Update the view and projection matrices. + context.UpdateSubresource(ref viewProjectionConstantBufferData, viewProjectionConstantBuffer); + + framePending = true; + } + } + + /// + /// Gets the view-projection constant buffer for the display, and attaches it + /// to the shader pipeline. + /// + public bool AttachViewProjectionBuffer(DeviceResources deviceResources) + { + // This method uses Direct3D device-based resources. + var context = deviceResources.D3DDeviceContext; + + // Loading is asynchronous. Resources must be created before they can be updated. + // Cameras can also be added asynchronously, in which case they must be initialized + // before they can be used. + if (context == null || viewProjectionConstantBuffer == null || !framePending) + { + return false; + } + + // Set the viewport for this camera. + context.Rasterizer.SetViewport(Viewport); + + // Send the constant buffer to the vertex shader. + context.VertexShader.SetConstantBuffers(1, viewProjectionConstantBuffer); + + // The template includes a pass-through geometry shader that is used by + // default on systems that don't support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer extension. The shader + // will be enabled at run-time on systems that require it. + // If your app will also use the geometry shader for other tasks and those + // tasks require the view/projection matrix, uncomment the following line + // of code to send the constant buffer to the geometry shader as well. + //context.GeometryShader.SetConstantBuffers(1, viewProjectionConstantBuffer); + + framePending = false; + + return true; + } + + // Direct3D device resources. + public RenderTargetView BackBufferRenderTargetView => d3dRenderTargetView; + public DepthStencilView DepthStencilView => d3dDepthStencilView; + public Texture2D BackBufferTexture2D => d3dBackBuffer; + + // Render target properties. + public RawViewportF Viewport => d3dViewport; + public SharpDX.DXGI.Format BackBufferDxgiFormat => dxgiFormat; + public Size RenderTargetSize => d3dRenderTargetSize; + public bool IsRenderingStereoscopic => isStereo; + + // Associated objects. + public HolographicCamera HolographicCamera => holographicCamera; + } +} diff --git a/Samples/360VideoPlayback/cs/Common/DeviceResources.cs b/Samples/360VideoPlayback/cs/Common/DeviceResources.cs new file mode 100644 index 0000000000..6edbd91011 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Common/DeviceResources.cs @@ -0,0 +1,447 @@ +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Windows.Graphics.DirectX.Direct3D11; +using Windows.Graphics.Holographic; + +namespace _360VideoPlayback.Common +{ + /// + /// Controls all the DirectX device resources. + /// + internal class DeviceResources : Disposer + { + // Notifies the application that owns DeviceResources when the Direct3D device is lost. + public event EventHandler DeviceLost; + + // Notifies the application that owns DeviceResources when the Direct3D device is restored. + public event EventHandler DeviceRestored; + + // Direct3D objects. + private Device3 d3dDevice; + private DeviceContext3 d3dContext; + private SharpDX.DXGI.Adapter3 dxgiAdapter; + + // Direct3D interop objects. + private IDirect3DDevice d3dInteropDevice; + + // Direct2D factories. + private SharpDX.Direct2D1.Factory2 d2dFactory; + private SharpDX.DirectWrite.Factory1 dwriteFactory; + private SharpDX.WIC.ImagingFactory2 wicFactory; + + // The holographic space provides a preferred DXGI adapter ID. + private HolographicSpace holographicSpace = null; + + // Properties of the Direct3D device currently in use. + private FeatureLevel d3dFeatureLevel = FeatureLevel.Level_10_0; + + // Whether or not the current Direct3D device supports the optional feature + // for setting the render target array index from the vertex shader stage. + bool d3dDeviceSupportsVprt = false; + + // Back buffer resources, etc. for attached holographic cameras. + private Dictionary cameraResourcesDictionary = new Dictionary(); + private Object cameraResourcesLock = new Object(); + + /// + /// Constructor for DeviceResources. + /// + public DeviceResources() + { + CreateDeviceIndependentResources(); + } + + /// + /// Configures resources that don't depend on the Direct3D device. + /// + private void CreateDeviceIndependentResources() + { + // Dispose previous references and set to null + this.RemoveAndDispose(ref d2dFactory); + this.RemoveAndDispose(ref dwriteFactory); + this.RemoveAndDispose(ref wicFactory); + + // Initialize Direct2D resources. + var debugLevel = SharpDX.Direct2D1.DebugLevel.None; + //#if DEBUG + if (DirectXHelper.SdkLayersAvailable()) + { + debugLevel = SharpDX.Direct2D1.DebugLevel.Information; + } + //#endif + + // Initialize the Direct2D Factory. + d2dFactory = this.ToDispose( + new SharpDX.Direct2D1.Factory2( + SharpDX.Direct2D1.FactoryType.SingleThreaded, + debugLevel + ) + ); + + // Initialize the DirectWrite Factory. + dwriteFactory = this.ToDispose( + new SharpDX.DirectWrite.Factory1(SharpDX.DirectWrite.FactoryType.Shared) + ); + + // Initialize the Windows Imaging Component (WIC) Factory. + wicFactory = this.ToDispose( + new SharpDX.WIC.ImagingFactory2() + ); + } + + public void SetHolographicSpace(HolographicSpace holographicSpace) + { + // Cache the holographic space. Used to re-initalize during device-lost scenarios. + this.holographicSpace = holographicSpace; + + InitializeUsingHolographicSpace(); + } + + public void InitializeUsingHolographicSpace() + { + // The holographic space might need to determine which adapter supports + // holograms, in which case it will specify a non-zero PrimaryAdapterId. + int shiftPos = sizeof(uint); + ulong id = (ulong)holographicSpace.PrimaryAdapterId.LowPart | (((ulong)holographicSpace.PrimaryAdapterId.HighPart) << shiftPos); + + // When a primary adapter ID is given to the app, the app should find + // the corresponding DXGI adapter and use it to create Direct3D devices + // and device contexts. Otherwise, there is no restriction on the DXGI + // adapter the app can use. + if (id != 0) + { + // Create the DXGI factory. + using (var dxgiFactory4 = new SharpDX.DXGI.Factory4()) + { + // Retrieve the adapter specified by the holographic space. + IntPtr adapterPtr; + dxgiFactory4.EnumAdapterByLuid((long)id, InteropStatics.IDXGIAdapter3, out adapterPtr); + + if (adapterPtr != IntPtr.Zero) + { + dxgiAdapter = new SharpDX.DXGI.Adapter3(adapterPtr); + } + } + } + else + { + this.RemoveAndDispose(ref dxgiAdapter); + } + + CreateDeviceResources(); + + holographicSpace.SetDirect3D11Device(d3dInteropDevice); + } + + + /// + /// Configures the Direct3D device, and stores handles to it and the device context. + /// + private void CreateDeviceResources() + { + DisposeDeviceAndContext(); + + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + DeviceCreationFlags creationFlags = DeviceCreationFlags.BgraSupport; + creationFlags |= DeviceCreationFlags.VideoSupport; + +#if DEBUG + if (DirectXHelper.SdkLayersAvailable()) + { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= DeviceCreationFlags.Debug; + } +#endif + + // This array defines the set of DirectX hardware feature levels this app will support. + // Note the ordering should be preserved. + // Note that HoloLens supports feature level 11.1. The HoloLens emulator is also capable + // of running on graphics cards starting with feature level 10.0. + FeatureLevel[] featureLevels = + { + FeatureLevel.Level_12_1, + FeatureLevel.Level_12_0, + FeatureLevel.Level_11_1, + FeatureLevel.Level_11_0, + FeatureLevel.Level_10_1, + FeatureLevel.Level_10_0 + }; + RasterizerStateDescription rasterDesc = new RasterizerStateDescription() + { + FillMode = FillMode.Solid, + CullMode = CullMode.Back, + IsFrontCounterClockwise = false, + DepthBias = 0, + SlopeScaledDepthBias = 0, + DepthBiasClamp = 0, + IsDepthClipEnabled = true, + IsScissorEnabled = false, + IsMultisampleEnabled = true, + IsAntialiasedLineEnabled = true + }; + + // Create the Direct3D 11 API device object and a corresponding context. + try + { + if (null != dxgiAdapter) + { + using (var device = new Device(dxgiAdapter, creationFlags, featureLevels)) + { + // Store pointers to the Direct3D 11.1 API device. + d3dDevice = this.ToDispose(device.QueryInterface()); + } + } + else + { + using (var device = new Device(DriverType.Hardware, creationFlags, featureLevels)) + { + // Store a pointer to the Direct3D device. + d3dDevice = this.ToDispose(device.QueryInterface()); + } + } + } + catch + { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + using (var device = new Device(DriverType.Warp, creationFlags, featureLevels)) + { + d3dDevice = this.ToDispose(device.QueryInterface()); + } + } + + // Cache the feature level of the device that was created. + d3dFeatureLevel = d3dDevice.FeatureLevel; + + // Store a pointer to the Direct3D immediate context. + d3dContext = this.ToDispose(d3dDevice.ImmediateContext3); + + // Acquire the DXGI interface for the Direct3D device. + using (var dxgiDevice = d3dDevice.QueryInterface()) + { + // Wrap the native device using a WinRT interop object. + IntPtr pUnknown; + UInt32 hr = InteropStatics.CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.NativePointer, out pUnknown); + if (hr == 0) + { + d3dInteropDevice = (IDirect3DDevice)Marshal.GetObjectForIUnknown(pUnknown); + Marshal.Release(pUnknown); + } + + // Store a pointer to the DXGI adapter. + // This is for the case of no preferred DXGI adapter, or fallback to WARP. + dxgiAdapter = this.ToDispose(dxgiDevice.Adapter.QueryInterface()); + } + + // Check for device support for the optional feature that allows setting the render target array index from the vertex shader stage. + var options = d3dDevice.CheckD3D113Features3(); + if (options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer) + { + d3dDeviceSupportsVprt = true; + } + + RasterizerState rsState = new RasterizerState(d3dDevice, rasterDesc); + d3dContext.Rasterizer.State = rsState; + // Need to multithread for video Playback MF threads + DeviceMultithread mt = d3dDevice.QueryInterface(); + mt.SetMultithreadProtected(true); + } + + /// + /// Disposes of a device-based resources. + /// + private void DisposeDeviceAndContext() + { + // Dispose existing references to Direct3D 11 device and contxt, and set to null. + this.RemoveAndDispose(ref d3dDevice); + this.RemoveAndDispose(ref d3dContext); + this.RemoveAndDispose(ref dxgiAdapter); + + // Release the interop device. + d3dInteropDevice = null; + } + + /// + /// Validates the back buffer for each HolographicCamera and recreates + /// resources for back buffers that have changed. + /// Locks the set of holographic camera resources until the function exits. + /// + public void EnsureCameraResources(HolographicFrame frame, HolographicFramePrediction prediction) + { + UseHolographicCameraResources((Dictionary cameraResourcesDictionary) => + { + foreach (var pose in prediction.CameraPoses) + { + var renderingParameters = frame.GetRenderingParameters(pose); + var cameraResources = cameraResourcesDictionary[pose.HolographicCamera.Id]; + + cameraResources.CreateResourcesForBackBuffer(this, renderingParameters); + } + }); + } + + /// + /// Prepares to allocate resources and adds resource views for a camera. + /// Locks the set of holographic camera resources until the function exits. + /// + public void AddHolographicCamera(HolographicCamera camera) + { + UseHolographicCameraResources((Dictionary cameraResourcesDictionary) => + { + cameraResourcesDictionary.Add(camera.Id, new CameraResources(camera)); + }); + } + + // Deallocates resources for a camera and removes the camera from the set. + // Locks the set of holographic camera resources until the function exits. + public void RemoveHolographicCamera(HolographicCamera camera) + { + UseHolographicCameraResources((Dictionary cameraResourcesDictionary) => + { + CameraResources cameraResources = cameraResourcesDictionary[camera.Id]; + + if (null != cameraResources) + { + cameraResources.ReleaseResourcesForBackBuffer(this); + cameraResourcesDictionary.Remove(camera.Id); + } + }); + } + + /// + /// Recreate all device resources and set them back to the current state. + /// Locks the set of holographic camera resources until the function exits. + /// + public void HandleDeviceLost() + { + DeviceLost.Invoke(this, null); + + UseHolographicCameraResources((Dictionary cameraResourcesDictionary) => + { + foreach (var pair in cameraResourcesDictionary) + { + CameraResources cameraResources = pair.Value; + cameraResources.ReleaseAllDeviceResources(this); + } + }); + + InitializeUsingHolographicSpace(); + + DeviceRestored.Invoke(this, null); + } + + /// + /// Call this method when the app suspends. It provides a hint to the driver that the app + /// is entering an idle state and that temporary buffers can be reclaimed for use by other apps. + /// + public void Trim() + { + d3dContext.ClearState(); + + using (var dxgiDevice = d3dDevice.QueryInterface()) + { + dxgiDevice.Trim(); + } + } + + /// + /// Present the contents of the swap chain to the screen. + /// Locks the set of holographic camera resources until the function exits. + /// + public void Present(ref HolographicFrame frame) + { + // By default, this API waits for the frame to finish before it returns. + // Holographic apps should wait for the previous frame to finish before + // starting work on a new frame. This allows for better results from + // holographic frame predictions. + var presentResult = frame.PresentUsingCurrentPrediction( + HolographicFramePresentWaitBehavior.WaitForFrameToFinish + ); + + HolographicFramePrediction prediction = frame.CurrentPrediction; + UseHolographicCameraResources((Dictionary cameraResourcesDictionary) => + { + foreach (var cameraPose in prediction.CameraPoses) + { + // This represents the device-based resources for a HolographicCamera. + CameraResources cameraResources = cameraResourcesDictionary[cameraPose.HolographicCamera.Id]; + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be + // entirely overwritten. If dirty or scroll rects are used, this call + // should be removed. + d3dContext.DiscardView(cameraResources.BackBufferRenderTargetView); + + // Discard the contents of the depth stencil. + d3dContext.DiscardView(cameraResources.DepthStencilView); + } + }); + + // The PresentUsingCurrentPrediction API will detect when the graphics device + // changes or becomes invalid. When this happens, it is considered a Direct3D + // device lost scenario. + if (presentResult == HolographicFramePresentResult.DeviceRemoved) + { + // The Direct3D device, context, and resources should be recreated. + HandleDeviceLost(); + } + } + + public delegate void SwapChainAction(Dictionary cameraResourcesDictionary); + public delegate bool SwapChainActionWithResult(Dictionary cameraResourcesDictionary); + + /// + /// Device-based resources for holographic cameras are stored in a std::map. Access this list by providing a + /// callback to this function, and the std::map will be guarded from add and remove + /// events until the callback returns. The callback is processed immediately and must + /// not contain any nested calls to UseHolographicCameraResources. + /// The callback takes a parameter of type Dictionary cameraResourcesDictionary + /// through which the list of cameras will be accessed. + /// The callback also returns a boolean result. + /// + public bool UseHolographicCameraResources(SwapChainActionWithResult callback) + { + bool success = false; + lock (cameraResourcesLock) + { + success = callback(cameraResourcesDictionary); + } + return success; + } + + /// + /// Device-based resources for holographic cameras are stored in a std::map. Access this list by providing a + /// callback to this function, and the std::map will be guarded from add and remove + /// events until the callback returns. The callback is processed immediately and must + /// not contain any nested calls to UseHolographicCameraResources. + /// The callback takes a parameter of type Dictionary cameraResourcesDictionary + /// through which the list of cameras will be accessed. + /// + public void UseHolographicCameraResources(SwapChainAction callback) + { + lock (cameraResourcesLock) + { + callback(cameraResourcesDictionary); + } + } + + #region Property accessors + + public Device3 D3DDevice => d3dDevice; + public DeviceContext3 D3DDeviceContext => d3dContext; + public SharpDX.DXGI.Adapter3 DxgiAdapter => dxgiAdapter; + public IDirect3DDevice D3DInteropDevice => d3dInteropDevice; + public SharpDX.Direct2D1.Factory2 D2DFactory => d2dFactory; + public SharpDX.DirectWrite.Factory1 DWriteFactory => dwriteFactory; + public SharpDX.WIC.ImagingFactory2 WicImagingFactory => wicFactory; + public SharpDX.Direct3D.FeatureLevel D3DDeviceFeatureLevel => d3dFeatureLevel; + public bool D3DDeviceSupportsVprt => d3dDeviceSupportsVprt; + + #endregion + } +} diff --git a/Samples/360VideoPlayback/cs/Common/DirectXHelper.cs b/Samples/360VideoPlayback/cs/Common/DirectXHelper.cs new file mode 100644 index 0000000000..99e6881ef3 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Common/DirectXHelper.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Windows.Storage; + +namespace _360VideoPlayback.Common +{ + internal static class DirectXHelper + { + /// + /// Function that reads from a binary file asynchronously. + /// + internal static async Task ReadDataAsync(StorageFile file) + { + using (var stream = await file.OpenStreamForReadAsync()) + { + byte[] buffer = new byte[stream.Length]; + await stream.ReadAsync(buffer, 0, buffer.Length); + return buffer; + } + } + + private const float DipsPerInch = 96.0f; + + /// + /// Converts a length in device-independent pixels (DIPs) to a length in physical pixels. + /// + internal static double ConvertDipsToPixels(double dips, double dpi) + { + return Math.Floor(dips * dpi / DipsPerInch + 0.5f); // Round to nearest integer. + } + +#if DEBUG + /// + /// Check for SDK Layer support. + /// + internal static bool SdkLayersAvailable() + { + try + { + using (var device = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Null, SharpDX.Direct3D11.DeviceCreationFlags.Debug)) + { + return true; + } + } + catch + { + return false; + } + } +#endif + } +} diff --git a/Samples/360VideoPlayback/cs/Common/Disposer.cs b/Samples/360VideoPlayback/cs/Common/Disposer.cs new file mode 100644 index 0000000000..0e0f6ad4e8 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Common/Disposer.cs @@ -0,0 +1,103 @@ +using System; + +namespace _360VideoPlayback.Common +{ + // A base class that tracks resources allocated by native code. This class is + // used to release COM references to DirectX resources. + public abstract class Disposer : IDisposable + { + #region Public methods + + // Releases resources allocated by native code (unmanaged resources). + // All disposable objects that were added to the collection will be disposed of + // when this method is called. + public void Dispose() + { + if (!IsDisposed) + { + Dispose(true); + IsDisposed = true; + } + } + + #endregion + + #region Protected methods and properties + + protected internal Disposer() + { + } + + // Indicates whether this instance is already disposed. + protected internal bool IsDisposed { get; private set; } + + // Disposes all IDisposable object resources in the collection of disposable + // objects. + // + // NOTE: Since this class exists to dispose of unmanaged resources, the + // disposeManagedResources parameter is ignored. + protected virtual void Dispose(bool disposeManagedResources) + { + // If the DisposeCollector exists, have it dispose of all COM objects. + if (!IsDisposed && DisposeCollector != null) + { + DisposeCollector.Dispose(); + } + + // The DisposeCollector is done, and can be discarded. + DisposeCollector = null; + } + + // Adds an IDisposable object to the collection of disposable objects. + protected internal T ToDispose(T objectToDispose) + { + // If objectToDispose is not null, add it to the collection. + if (!ReferenceEquals(objectToDispose, null)) + { + // Create DisposeCollector if it doesn't already exist. + if (DisposeCollector == null) + { + DisposeCollector = new SharpDX.DisposeCollector(); + IsDisposed = false; + } + + return DisposeCollector.Collect(objectToDispose); + } + + // Otherwise, return a default instance of type T. + return default(T); + } + + // Disposes of an IDisposable object immediately and also removes the object from the + // collection of disposable objects. + protected internal void RemoveAndDispose(ref T objectToDispose) + { + // If objectToDispose is not null, and if the DisposeCollector is available, have + // the DisposeCollector get rid of objectToDispose. + if (!ReferenceEquals(objectToDispose, null) && (DisposeCollector != null)) + { + DisposeCollector.RemoveAndDispose(ref objectToDispose); + } + } + + // Removes an IDisposable object from the collection of disposable objects. Does not + // dispose of the object before removing it. + protected internal void RemoveToDispose(T objectToRemove) + { + // If objectToRemove is not null, have the DisposeCollector forget about it. + if (!ReferenceEquals(objectToRemove, null) && (DisposeCollector != null)) + { + DisposeCollector.Remove(objectToRemove); + } + } + + #endregion + + #region Private properties + + // The collection of disposable objects. + private SharpDX.DisposeCollector DisposeCollector { get; set; } + + #endregion + } +} diff --git a/Samples/360VideoPlayback/cs/Common/InteropStatics.cs b/Samples/360VideoPlayback/cs/Common/InteropStatics.cs new file mode 100644 index 0000000000..f89ecee7e6 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Common/InteropStatics.cs @@ -0,0 +1,41 @@ +using System; +using System.Runtime.InteropServices; + +namespace _360VideoPlayback.Common +{ + public static class InteropStatics + { + public static Guid IInspectable = new Guid("AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90"); + public static Guid ID3D11Resource = new Guid("dc8e63f3-d12b-4952-b47b-5e45026a862d"); + public static Guid IDXGIAdapter3 = new Guid("645967A4-1392-4310-A798-8053CE3E93FD"); + + [DllImport( + "d3d11.dll", + EntryPoint = "CreateDirect3D11DeviceFromDXGIDevice", + SetLastError = true, + CharSet = CharSet.Unicode, + ExactSpelling = true, + CallingConvention = CallingConvention.StdCall + )] + public static extern UInt32 CreateDirect3D11DeviceFromDXGIDevice(IntPtr dxgiDevice, out IntPtr graphicsDevice); + + [DllImport( + "d3d11.dll", + EntryPoint = "CreateDirect3D11SurfaceFromDXGISurface", + SetLastError = true, + CharSet = CharSet.Unicode, + ExactSpelling = true, + CallingConvention = CallingConvention.StdCall + )] + public static extern UInt32 CreateDirect3D11SurfaceFromDXGISurface(IntPtr dxgiSurface, out IntPtr graphicsSurface); + + [ComImport] + [Guid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComVisible(true)] + public interface IDirect3DDxgiInterfaceAccess + { + IntPtr GetInterface([In] ref Guid iid); + }; + } +} diff --git a/Samples/360VideoPlayback/cs/Common/StepTimer.cs b/Samples/360VideoPlayback/cs/Common/StepTimer.cs new file mode 100644 index 0000000000..fe714635e4 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Common/StepTimer.cs @@ -0,0 +1,187 @@ +using System; +using System.Diagnostics; + +namespace _360VideoPlayback.Common +{ + /// + /// Helper class for animation and simulation timing. + /// + internal class StepTimer + { + // Integer format represents time using 10,000,000 ticks per second. + private const long TicksPerSecond = 10000000; + + // Source timing data uses QPC units. + private long qpcFrequency; + private long qpcLastTime; + private long qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + private long leftOverTicks = 0; + + // Members for tracking the framerate. + private int framesThisSecond = 0; + private long qpcSecondCounter = 0; + + public StepTimer() + { + qpcFrequency = Stopwatch.Frequency; + qpcLastTime = Stopwatch.GetTimestamp(); + + // Initialize max delta to 1/10 of a second. + qpcMaxDelta = qpcFrequency / 10; + } + + /// + /// After an intentional timing discontinuity (for instance a blocking IO operation) + /// call this to avoid having the fixed timestep logic attempt a set of catch-up + /// Update calls. + /// + public void ResetElapsedTime() + { + qpcLastTime = Stopwatch.GetTimestamp(); + + leftOverTicks = 0; + FramesPerSecond = 0; + framesThisSecond = 0; + qpcSecondCounter = 0; + } + + /// + /// Get elapsed time since the previous Update call. + /// + public long ElapsedTicks { get; private set; } = 0; + + /// + /// Get elapsed time since the previous Update call. + /// + public double ElapsedSeconds => TicksToSeconds(ElapsedTicks); + + /// + /// Get total time since the start of the program. + /// + public long TotalTicks { get; private set; } = 0; + + /// + /// Get total time since the start of the program. + /// + public double TotalSeconds => TicksToSeconds(TotalTicks); + + /// + /// Get total number of updates since start of the program. + /// + public int FrameCount { get; private set; } = 0; + + /// + /// Get the current framerate. + /// + public int FramesPerSecond { get; private set; } = 0; + + /// + /// Get/Set whether to use fixed or variable timestep mode. + /// + public bool IsFixedTimeStep { get; set; } = false; + + /// + /// Get/Set how often to call Update when in fixed timestep mode. + /// + public long TargetElapsedTicks { get; set; } = TicksPerSecond / 60; + + /// + /// Get/Set how often to call Update when in fixed timestep mode. + /// + public double TargetElapsedSeconds + { + get { return TicksToSeconds(TargetElapsedTicks); } + set { TargetElapsedTicks = SecondsToTicks(value); } + } + + /// + /// // Update timer state, calling the specified Update function the appropriate number of times. + /// + public void Tick(Action update) + { + // Query the current time. + long currentTime = Stopwatch.GetTimestamp(); + + long timeDelta = currentTime - qpcLastTime; + + qpcLastTime = currentTime; + qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > qpcMaxDelta) + { + timeDelta = qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= qpcFrequency; + + long lastFrameCount = FrameCount; + + if (IsFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (Math.Abs(timeDelta - TargetElapsedTicks) < (TicksPerSecond / 4000)) + { + timeDelta = TargetElapsedTicks; + } + + leftOverTicks += timeDelta; + + while (leftOverTicks >= TargetElapsedTicks) + { + ElapsedTicks = TargetElapsedTicks; + TotalTicks += TargetElapsedTicks; + leftOverTicks -= TargetElapsedTicks; + FrameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + ElapsedTicks = timeDelta; + TotalTicks += timeDelta; + leftOverTicks = 0; + FrameCount++; + + update(); + } + + // Track the current framerate. + if (FrameCount != lastFrameCount) + { + framesThisSecond++; + } + + if (qpcSecondCounter >= qpcFrequency) + { + FramesPerSecond = framesThisSecond; + framesThisSecond = 0; + qpcSecondCounter %= qpcFrequency; + } + } + + private static double TicksToSeconds(long ticks) + { + return (double)ticks / TicksPerSecond; + } + + private static long SecondsToTicks(double seconds) + { + return (long)(seconds * TicksPerSecond); + } + } +} diff --git a/Samples/360VideoPlayback/cs/Content/ShaderStructures.cs b/Samples/360VideoPlayback/cs/Content/ShaderStructures.cs new file mode 100644 index 0000000000..66e3d37e82 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Content/ShaderStructures.cs @@ -0,0 +1,39 @@ +using System.Numerics; + +namespace _360VideoPlayback.Content +{ + /// + /// Constant buffer used to send hologram position transform to the shader pipeline. + /// + internal struct ModelConstantBuffer + { + public Matrix4x4 model; + } + + /// + /// Used to send per-vertex data to the vertex shader. + /// + internal struct VertexPositionColor + { + public VertexPositionColor(Vector3 pos, Vector3 color) + { + this.pos = pos; + this.color = color; + } + + public Vector3 pos; + public Vector3 color; + }; + + internal struct VertexPositionTexture + { + public VertexPositionTexture(Vector3 pos, Vector2 texture) + { + this.pos = pos; + this.texture = texture; + } + + public Vector3 pos; + public Vector2 texture; + }; +} diff --git a/Samples/360VideoPlayback/cs/Content/Shaders/GeometryShader.hlsl b/Samples/360VideoPlayback/cs/Content/Shaders/GeometryShader.hlsl new file mode 100644 index 0000000000..4065a36e62 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Content/Shaders/GeometryShader.hlsl @@ -0,0 +1,31 @@ +// Per-vertex data from the vertex shader. +struct GeometryShaderInput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint instId : TEXCOORD0; +}; + +// Per-vertex data passed to the rasterizer. +struct GeometryShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint rtvId : SV_RenderTargetArrayIndex; +}; + +// This geometry shader is a pass-through that leaves the geometry unmodified +// and sets the render target array index. +[maxvertexcount(3)] +void main(triangle GeometryShaderInput input[3], inout TriangleStream outStream) +{ + GeometryShaderOutput output; + [unroll(3)] + for (int i = 0; i < 3; ++i) + { + output.pos = input[i].pos; + output.tex = input[i].tex; + output.rtvId = input[i].instId; + outStream.Append(output); + } +} diff --git a/Samples/360VideoPlayback/cs/Content/Shaders/PixelShader.hlsl b/Samples/360VideoPlayback/cs/Content/Shaders/PixelShader.hlsl new file mode 100644 index 0000000000..8779fb1cd0 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Content/Shaders/PixelShader.hlsl @@ -0,0 +1,26 @@ +Texture2D objectTexture: t0; +SamplerState samp: s0; + +// Per-pixel color data passed through the pixel shader. +struct PixelShaderInput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; +}; + +// NOTE: This should be created in .cpp but this is just simpler for now +SamplerState basicLinearWrap +{ + Filter = MIN_MAG_MIP_LINEAR; + AddressU = WRAP; + AddressV = WRAP; +}; + + +// The pixel shader passes through the color data. The color data from +// is interpolated and assigned to a pixel at the rasterization step. +min16float4 main(PixelShaderInput input) : SV_TARGET +{ + min16float4 output = min16float4(objectTexture.Sample(samp, input.tex)); + return output; +} diff --git a/Samples/360VideoPlayback/cs/Content/Shaders/VPRTVertexShader.hlsl b/Samples/360VideoPlayback/cs/Content/Shaders/VPRTVertexShader.hlsl new file mode 100644 index 0000000000..56dd228107 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Content/Shaders/VPRTVertexShader.hlsl @@ -0,0 +1,58 @@ +// A constant buffer that stores the model transform. +cbuffer ModelConstantBuffer : register(b0) +{ + float4x4 model; +}; + +// A constant buffer that stores each set of view and projection matrices in column-major format. +cbuffer ViewProjectionConstantBuffer : register(b1) +{ + float4x4 viewProjection[2]; +}; + +// Per-vertex data used as input to the vertex shader. +struct VertexShaderInput +{ + min16float3 pos : POSITION; + min16float2 tex : TEXCOORD1; + uint instId : SV_InstanceID; +}; + +// Per-vertex data passed to the geometry shader. +// Note that the render target array index will be set by the geometry shader +// using the value of viewId. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint viewId : SV_RenderTargetArrayIndex; // SV_InstanceID % 2 +}; + + +// Simple shader to do vertex processing on the GPU. +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Note which view this vertex has been sent to. Used for matrix lookup. + // Taking the modulo of the instance ID allows geometry instancing to be used + // along with stereo instanced drawing; in that case, two copies of each + // instance would be drawn, one for left and one for right. + int idx = input.instId % 2; + + // Transform the vertex position into world space. + pos = mul(pos, model); + + // Correct for perspective and project the vertex position onto the screen. + pos = mul(pos, viewProjection[idx]); + output.pos = (min16float4)pos; + + // Pass the color through without modification. + output.tex = input.tex; + + // Set the render target array index. + output.viewId = idx; + + return output; +} diff --git a/Samples/360VideoPlayback/cs/Content/Shaders/VertexShader.hlsl b/Samples/360VideoPlayback/cs/Content/Shaders/VertexShader.hlsl new file mode 100644 index 0000000000..76b2a63b30 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Content/Shaders/VertexShader.hlsl @@ -0,0 +1,58 @@ +// A constant buffer that stores the model transform. +cbuffer ModelConstantBuffer : register(b0) +{ + float4x4 model; +}; + +// A constant buffer that stores each set of view and projection matrices in column-major format. +cbuffer ViewProjectionConstantBuffer : register(b1) +{ + float4x4 viewProjection[2]; +}; + +// Per-vertex data used as input to the vertex shader. +struct VertexShaderInput +{ + min16float3 pos : POSITION; + min16float2 tex : TEXCOORD1; + uint instId : SV_InstanceID; +}; + +// Per-vertex data passed to the geometry shader. +// Note that the render target array index will be set by the geometry shader +// using the value of viewId. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float2 tex : TEXCOORD1; + uint viewId : TEXCOORD0; // SV_InstanceID % 2 +}; + +// Simple shader to do vertex processing on the GPU. +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Note which view this vertex has been sent to. Used for matrix lookup. + // Taking the modulo of the instance ID allows geometry instancing to be used + // along with stereo instanced drawing; in that case, two copies of each + // instance would be drawn, one for left and one for right. + int idx = input.instId % 2; + + // Transform the vertex position into world space. + pos = mul(pos, model); + + // Correct for perspective and project the vertex position onto the screen. + pos = mul(pos, viewProjection[idx]); + output.pos = (min16float4)pos; + + // Pass the text through without modification. + output.tex = input.tex; + + // Set the instance ID. The pass-through geometry shader will set the + // render target array index to whatever value is set here. + output.viewId = idx; + + return output; +} diff --git a/Samples/360VideoPlayback/cs/Content/SpatialInputHandler.cs b/Samples/360VideoPlayback/cs/Content/SpatialInputHandler.cs new file mode 100644 index 0000000000..11aa1526f6 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Content/SpatialInputHandler.cs @@ -0,0 +1,51 @@ +using Windows.UI.Input.Spatial; + +namespace _360VideoPlayback.Common +{ + // Sample gesture handler. + // Hooks up events to recognize a tap gesture, and keeps track of input using a boolean value. + public class SpatialInputHandler + { + // API objects used to process gesture input, and generate gesture events. + private SpatialInteractionManager interactionManager; + + // Used to indicate that a Pressed input event was received this frame. + private SpatialInteractionSourceState sourceState; + + // Creates and initializes a GestureRecognizer that listens to a Person. + public SpatialInputHandler() + { + // The interaction manager provides an event that informs the app when + // spatial interactions are detected. + interactionManager = SpatialInteractionManager.GetForCurrentView(); + + // Bind a handler to the SourcePressed event. + interactionManager.SourcePressed += this.OnSourcePressed; + + // + // TODO: Expand this class to use other gesture-based input events as applicable to + // your app. + // + } + + // Checks if the user performed an input gesture since the last call to this method. + // Allows the main update loop to check for asynchronous changes to the user + // input state. + public SpatialInteractionSourceState CheckForInput() + { + SpatialInteractionSourceState sourceState = this.sourceState; + this.sourceState = null; + return sourceState; + } + + public void OnSourcePressed(SpatialInteractionManager sender, SpatialInteractionSourceEventArgs args) + { + sourceState = args.State; + + // + // TODO: In your app or game engine, rewrite this method to queue + // input events in your input class or event handler. + // + } + } +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/cs/Content/VideoRenderer.cs b/Samples/360VideoPlayback/cs/Content/VideoRenderer.cs new file mode 100644 index 0000000000..3788b5bcfa --- /dev/null +++ b/Samples/360VideoPlayback/cs/Content/VideoRenderer.cs @@ -0,0 +1,427 @@ +using _360VideoPlayback.Common; +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using Windows.Graphics.DirectX.Direct3D11; +using Windows.Media.Playback; + +namespace _360VideoPlayback.Content +{ + /// + /// This sample renderer instantiates a basic rendering pipeline. + /// + internal class VideoRenderer : Disposer + { + // Cached reference to device resources. + private DeviceResources deviceResources; + + // Direct3D resources for cube geometry. + private SharpDX.Direct3D11.InputLayout inputLayout; + private SharpDX.Direct3D11.Buffer vertexBuffer; + private SharpDX.Direct3D11.Buffer indexBuffer; + private SharpDX.Direct3D11.VertexShader vertexShader; + private SharpDX.Direct3D11.GeometryShader geometryShader; + private SharpDX.Direct3D11.PixelShader pixelShader; + private SharpDX.Direct3D11.Buffer modelConstantBuffer; + + private SharpDX.Direct3D11.Texture2D m_texture; + private SharpDX.Direct3D11.ShaderResourceView m_textureView; + private SharpDX.Direct3D11.SamplerState m_quadTextureSamplerState; + private IDirect3DSurface d3dInteropSurface; + + // System resources for cube geometry. + private ModelConstantBuffer modelConstantBufferData; + private int indexCount = 0; + + // Variables used with the rendering loop. + private bool loadingComplete = false; + + // If the current D3D Device supports VPRT, we can avoid using a geometry + // shader just to set the render target array index. + private bool usingVprtShaders = false; + + private MediaPlayer m_mediaPlayer; + private Object thisLock = new Object(); + + /// + /// Loads vertex and pixel shaders from files and instantiates the cube geometry. + /// + public VideoRenderer(DeviceResources deviceResources) + { + this.deviceResources = deviceResources; + m_mediaPlayer = AppView.mediaPlayer; + + } + + /// + /// Called once per frame, rotates the cube and calculates the model and view matrices. + /// + public void Update(StepTimer timer) + { + Vector3 scale = new Vector3(10.0f); + Matrix4x4 modelscale = Matrix4x4.CreateScale(scale); + + // Here, we provide the model transform for the sample hologram. The model transform + // matrix is transposed to prepare it for the shader. + this.modelConstantBufferData.model = Matrix4x4.Transpose(modelscale); + // Loading is asynchronous. Resources must be created before they can be updated. + if (!loadingComplete) + { + return; + } + + // Use the D3D device context to update Direct3D device-based resources. + var context = this.deviceResources.D3DDeviceContext; + + // Update the model transform buffer for the hologram. + context.UpdateSubresource(ref this.modelConstantBufferData, this.modelConstantBuffer); + } + + /// + /// Renders one frame using the vertex and pixel shaders. + /// On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3:: + /// VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature, + /// a pass-through geometry shader is also used to set the render + /// target array index. + /// + public void Render() + { + // Loading is asynchronous. Resources must be created before drawing can occur. + if (!this.loadingComplete) + { + return; + } + + var context = this.deviceResources.D3DDeviceContext; + + // Each vertex is one instance of the VertexPositionColor struct. + int stride = SharpDX.Utilities.SizeOf(); + int offset = 0; + var bufferBinding = new SharpDX.Direct3D11.VertexBufferBinding(this.vertexBuffer, stride, offset); + context.InputAssembler.SetVertexBuffers(0, bufferBinding); + context.InputAssembler.SetIndexBuffer( + this.indexBuffer, + SharpDX.DXGI.Format.R32_UInt, // Each index is one 16-bit unsigned integer (short). + 0); + context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; + context.InputAssembler.InputLayout = this.inputLayout; + + // Attach the vertex shader. + context.VertexShader.SetShader(this.vertexShader, null, 0); + // Apply the model constant buffer to the vertex shader. + context.VertexShader.SetConstantBuffers(0, this.modelConstantBuffer); + + if (!this.usingVprtShaders) + { + // On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature, + // a pass-through geometry shader is used to set the render target + // array index. + context.GeometryShader.SetShader(this.geometryShader, null, 0); + } + + // Attach the pixel shader. + context.PixelShader.SetShader(this.pixelShader, null, 0); + + lock (thisLock) + { + + context.PixelShader.SetShaderResources(0, 1, m_textureView); + + context.PixelShader.SetSamplers(0, 1, m_quadTextureSamplerState); + + // Draw the objects. + context.DrawIndexedInstanced( + indexCount, // Index count per instance. + 2, // Instance count. + 0, // Start index location. + 0, // Base vertex location. + 0 // Start instance location. + ); + } + } + + /// + /// Creates device-based resources to store a constant buffer, cube + /// geometry, and vertex and pixel shaders. In some cases this will also + /// store a geometry shader. + /// + public void CreateDeviceDependentResourcesAsync() + { + ReleaseDeviceDependentResources(); + + // Create a constant buffer to store the model matrix. + modelConstantBuffer = this.ToDispose(SharpDX.Direct3D11.Buffer.Create( + deviceResources.D3DDevice, + SharpDX.Direct3D11.BindFlags.ConstantBuffer, + ref modelConstantBufferData)); + + // Create the Texture, ShaderResource and Sampler state + lock (thisLock) + { + m_texture = this.ToDispose(new SharpDX.Direct3D11.Texture2D(deviceResources.D3DDevice, new SharpDX.Direct3D11.Texture2DDescription() + { + Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm, + Width = (int)m_mediaPlayer.PlaybackSession.NaturalVideoWidth,//Width + Height = (int)m_mediaPlayer.PlaybackSession.NaturalVideoHeight,//Height + MipLevels = 1, + ArraySize = 1, + BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource | SharpDX.Direct3D11.BindFlags.RenderTarget, + Usage = SharpDX.Direct3D11.ResourceUsage.Default, + CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None, + SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), + OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None + })); + + m_textureView = this.ToDispose(new SharpDX.Direct3D11.ShaderResourceView(deviceResources.D3DDevice, m_texture)); + } + + m_quadTextureSamplerState = this.ToDispose(new SharpDX.Direct3D11.SamplerState(deviceResources.D3DDevice, new SharpDX.Direct3D11.SamplerStateDescription() + { + Filter = SharpDX.Direct3D11.Filter.Anisotropic, + AddressU = SharpDX.Direct3D11.TextureAddressMode.Clamp, + AddressV = SharpDX.Direct3D11.TextureAddressMode.Clamp, + AddressW = SharpDX.Direct3D11.TextureAddressMode.Clamp, + MaximumAnisotropy = 3, + MinimumLod = 0, + MaximumLod = 3, + MipLodBias = 0, + BorderColor = new SharpDX.Mathematics.Interop.RawColor4(0, 0, 0, 0), + ComparisonFunction = SharpDX.Direct3D11.Comparison.Never + })); + + CreateD3D11Surface(); + LoadShaders(); + } + + + private async void LoadShaders() + { + usingVprtShaders = deviceResources.D3DDeviceSupportsVprt; + // On devices that do support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature + // we can avoid using a pass-through geometry shader to set the render + // target array index, thus avoiding any overhead that would be + // incurred by setting the geometry shader stage. + var vertexShaderFileName = usingVprtShaders ? "Content\\Shaders\\VPRTVertexShader.cso" : "Content\\Shaders\\VertexShader.cso"; + var folder = Windows.ApplicationModel.Package.Current.InstalledLocation; + // Load the compiled vertex shader. + var vertexShaderByteCode = await DirectXHelper.ReadDataAsync(await folder.GetFileAsync(vertexShaderFileName)); + + // After the vertex shader file is loaded, create the shader and input layout. + vertexShader = this.ToDispose(new SharpDX.Direct3D11.VertexShader( + deviceResources.D3DDevice, + vertexShaderByteCode)); + + SharpDX.Direct3D11.InputElement[] vertexDesc = + { + new SharpDX.Direct3D11.InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0, 0, SharpDX.Direct3D11.InputClassification.PerVertexData, 0), + new SharpDX.Direct3D11.InputElement("TEXCOORD", 1, SharpDX.DXGI.Format.R32G32_Float, 12, 0, SharpDX.Direct3D11.InputClassification.PerVertexData, 0), + }; + + + inputLayout = this.ToDispose(new SharpDX.Direct3D11.InputLayout( + deviceResources.D3DDevice, + vertexShaderByteCode, + vertexDesc)); + + + if (!usingVprtShaders) + { + // Load the compiled pass-through geometry shader. + var geometryShaderByteCode = await DirectXHelper.ReadDataAsync(await folder.GetFileAsync("Content\\Shaders\\GeometryShader.cso")); + + // After the pass-through geometry shader file is loaded, create the shader. + geometryShader = this.ToDispose(new SharpDX.Direct3D11.GeometryShader( + deviceResources.D3DDevice, + geometryShaderByteCode)); + } + + // Load the compiled pixel shader. + var pixelShaderByteCode = await DirectXHelper.ReadDataAsync(await folder.GetFileAsync("Content\\Shaders\\PixelShader.cso")); + + // After the pixel shader file is loaded, create the shader. + pixelShader = this.ToDispose(new SharpDX.Direct3D11.PixelShader( + deviceResources.D3DDevice, + pixelShaderByteCode)); + + ComputeSphere(16, true); + // Once the cube is loaded, the object is ready to be rendered. + loadingComplete = true; + } + + /// + /// Releases device-based resources. + /// + public void ReleaseDeviceDependentResources() + { + loadingComplete = false; + usingVprtShaders = false; + this.RemoveAndDispose(ref vertexShader); + this.RemoveAndDispose(ref inputLayout); + this.RemoveAndDispose(ref pixelShader); + this.RemoveAndDispose(ref geometryShader); + this.RemoveAndDispose(ref modelConstantBuffer); + this.RemoveAndDispose(ref vertexBuffer); + this.RemoveAndDispose(ref indexBuffer); + this.RemoveAndDispose(ref m_texture); + this.RemoveAndDispose(ref m_textureView); + this.RemoveAndDispose(ref m_quadTextureSamplerState); + } + + private void CreateD3D11Surface() + { + SharpDX.DXGI.Surface2 surface = m_texture.QueryInterface(); + IntPtr pUnknown; + UInt32 hr = InteropStatics.CreateDirect3D11SurfaceFromDXGISurface(surface.NativePointer, out pUnknown); + + if (hr == 0) + { + d3dInteropSurface = (IDirect3DSurface)Marshal.GetObjectForIUnknown(pUnknown); + Marshal.Release(pUnknown); + } + + m_mediaPlayer.VideoFrameAvailable += M_mediaPlayer_VideoFrameAvailable; + m_mediaPlayer.Play(); + } + + private void M_mediaPlayer_VideoFrameAvailable(MediaPlayer sender, object args) + { + lock (thisLock) + { + m_mediaPlayer.CopyFrameToVideoSurface(d3dInteropSurface); + } + } + + private void ComputeSphere(int tessellation, bool invertn) + { + if (tessellation < 3) + { + new Exception("tesselation parameter out of range"); + } + + int verticalSegments = tessellation; + int horizontalSegments = tessellation * 2; + int vertCount = (verticalSegments + 1) * (horizontalSegments + 1); + int idxCount = (verticalSegments) * (horizontalSegments + 1) * 6; + + float radius = 0.5f; // Diameter of the default Sphere will always be 1 to stay aligned + + + VertexPositionTexture[] sphereVertArray = new VertexPositionTexture[vertCount]; + int[] cubeIndices = new int[idxCount]; + + int writePos = 0; + + for (int i = 0; i <= verticalSegments; i++) + { + float v = 1 - (float)i / verticalSegments; + + float latitude = (float)(i * SharpDX.MathUtil.Pi / + verticalSegments) - SharpDX.MathUtil.PiOverTwo; + + var dy = (float)Math.Sin(latitude); + var dxz = (float)Math.Cos(latitude); + + // Create a single ring of vertices at this latitude. + for (ushort j = 0; j <= horizontalSegments; j++) + { + float u = (float)j / horizontalSegments; + + float longitude = (float)(j * SharpDX.MathUtil.TwoPi / horizontalSegments); + float dx = (float)Math.Cos(longitude); + float dz = (float)Math.Sin(longitude); + dx *= dxz; + dz *= dxz; + + Vector3 vect3 = new Vector3(dx, dy, dz); + VertexPositionTexture vert; + vert.pos = vect3 * radius; + vert.texture = new Vector2(u, v); + + sphereVertArray[writePos] = vert; + writePos++; + } + } + + // Fill the index buffer with triangles joining each pair of latitude rings. + int stride = horizontalSegments + 1; + writePos = 0; + for (int i = 0; i < verticalSegments; i++) + { + for (int j = 0; j <= horizontalSegments; j++) + { + int nextI = i + 1; + int nextJ = (j + 1) % stride; + + cubeIndices[writePos] = i * stride + j; + cubeIndices[++writePos] = nextI * stride + j; + cubeIndices[++writePos] = i * stride + nextJ; + + cubeIndices[++writePos] = i * stride + nextJ; + cubeIndices[++writePos] = nextI * stride + j; + cubeIndices[++writePos] = nextI * stride + nextJ; + writePos++; + } + } + + vertexBuffer = this.ToDispose(SharpDX.Direct3D11.Buffer.Create( + deviceResources.D3DDevice, + SharpDX.Direct3D11.BindFlags.VertexBuffer, + sphereVertArray)); + + indexCount = idxCount; + + indexBuffer = this.ToDispose(SharpDX.Direct3D11.Buffer.Create( + deviceResources.D3DDevice, + SharpDX.Direct3D11.BindFlags.IndexBuffer, + cubeIndices)); + } + + private void XMScalarSinCos(ref float Sin, ref float Cos, float Value) + { + const float XM1div2PI = 0.159154943f; + // Map Value to y in [-pi,pi], x = 2*pi*quotient + remainder. + float quotient = XM1div2PI * Value; + if (Value >= 0.0f) + { + quotient = (float)((int)(quotient + 0.5f)); + } + else + { + quotient = (float)((int)(quotient - 0.5f)); + } + float y = Value - SharpDX.MathUtil.TwoPi * quotient; + + // Map y to [-pi/2,pi/2] with sin(y) = sin(Value). + float sign; + if (y > SharpDX.MathUtil.PiOverTwo) + { + y = SharpDX.MathUtil.Pi - y; + sign = -1.0f; + } + else if (y < -(SharpDX.MathUtil.PiOverTwo)) + { + y = -(SharpDX.MathUtil.Pi) - y; + sign = -1.0f; + } + else + { + sign = +1.0f; + } + + float y2 = y * y; + + // 11-degree minimax approximation + Sin = (((((-2.3889859e-08f * y2 + 2.7525562e-06f) * y2 - 0.00019840874f) * y2 + 0.0083333310f) * y2 - 0.16666667f) * y2 + 1.0f) * y; + + // 10-degree minimax approximation + float p = (float)((float)((((-2.6051615e-07f * y2 + 2.4760495e-05f) * y2 - 0.0013888378f) * y2 + 0.041666638f) * y2 - 0.5f) * y2 + 1.0f); + + Cos = sign * p; + } + + } +} + + diff --git a/Samples/360VideoPlayback/cs/FxCompile.cs b/Samples/360VideoPlayback/cs/FxCompile.cs new file mode 100644 index 0000000000..83c8ff8968 --- /dev/null +++ b/Samples/360VideoPlayback/cs/FxCompile.cs @@ -0,0 +1,366 @@ +//----------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- + +using Microsoft.Build.Framework; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Build.Utilities; + +namespace Microsoft.Build.Tasks +{ + /// + /// Task to support Fxc.exe + /// + public class FxCompile : ToolTask + { + /// + /// Constructor + /// + public FxCompile() + { + // Because FxCop wants it this way. + } + + #region Inputs + + /// + /// Sources to be compiled. + /// + /// Required for task to run. + [Required] + public virtual ITaskItem[] Source + { + get { return (ITaskItem[])Bag["Sources"]; } + set { Bag["Sources"] = value; } + } + + /// + /// Gets the collection of parameters used by the derived task class. + /// + /// Parameter bag. + protected internal Hashtable Bag + { + get + { + return bag; + } + } + + private Hashtable bag = new Hashtable(); + + /// + /// ShaderType, requires ShaderModel + /// Specifies the type of shader. (/T [type]_[model]) + /// + /// Consider using one of these: "NotSet", "Effect", "Vertex", "Pixel", "Geometry", "Hull", "Domain", "Compute", or "Texture". + public virtual string ShaderType + { + get + { + return (string)Bag["ShaderType"]; + } + + set + { + string result = String.Empty; + switch (value.ToLowerInvariant()) + { + case "notset": + result = ""; + break; + case "effect": + result = "/T fx"; + break; + case "vertex": + result = "/T vs"; + break; + case "pixel": + result = "/T ps"; + break; + case "geometry": + result = "/T gs"; + break; + case "hull": + result = "/T hs"; + break; + case "domain": + result = "/T ds"; + break; + case "compute": + result = "/T cs"; + break; + case "texture": + result = "/T tx"; + break; + default: + throw new ArgumentException("ShaderType of " + value + @" is an invalid. Consider using one of these: ""NotSet"", ""Effect"", ""Vertex"", ""Pixel"", ""Geometry"", ""Hull"", ""Domain"", ""Compute"", or ""Texture""."); + } + + Bag["ShaderType"] = result; + } + } + + /// + /// ShaderModel, requires ShaderType + /// Specifies the shader model. Some shader types can only be used with recent shader models (/T [type]_[model]) + /// + public virtual string ShaderModel + { + get { return (string)Bag["ShaderModel"]; } + set { Bag["ShaderModel"] = value; } + } + + /// + /// AssemblerOutput, requires AssemblerOutputFile + /// Specifies the contents of assembly language output file. (/Fc, /Fx) + /// + /// Consider using one of these: "Assembly Code" or "Assembly Code and Hex". + public virtual string AssemblerOutput + { + get + { + return (string)Bag["AssemblerOutput"]; + } + + set + { + string result = String.Empty; + switch (value.ToLowerInvariant()) + { + case "Assembly Code": + result = "/Fc"; + break; + case "Assembly Code and Hex": + result = "/Fx"; + break; + default: + throw new ArgumentException("AssemblerOutput of " + value + @" is an invalid. Consider using one of these: ""Assembly Code"" or ""Assembly Code and Hex""."); + } + + Bag["AssemblerOutput"] = value; + } + } + + /// + /// AssemblerOutputFile, requires AssemblerOutput + /// Specifies file name for assembly code listing file + /// + public virtual string AssemblerOutputFile + { + get { return (string)Bag["AssemblerOutputFile"]; } + set { Bag["AssemblerOutputFile"] = value; } + } + + /// + /// Specifies a name for the variable name in the header file (/Vn [name]) + /// + public virtual string VariableName + { + get { return (string)Bag["VariableName"]; } + set { Bag["VariableName"] = value; } + } + + /// + /// Specifies a name for header file containing object code. (/Fh [name]) + /// + public virtual string HeaderFileOutput + { + get { return (string)Bag["HeaderFileOutput"]; } + set { Bag["HeaderFileOutput"] = value; } + } + + /// + /// Specifies a name for object file. (/Fo [name]) + /// + public virtual string ObjectFileOutput + { + get { return (string)Bag["ObjectFileOutput"]; } + set { Bag["ObjectFileOutput"] = value; } + } + + /// + /// Defines preprocessing symbols for your source file. + /// + public virtual string[] PreprocessorDefinitions + { + get { return (string[])Bag["PreprocessorDefinitions"]; } + set { Bag["PreprocessorDefinitions"] = value; } + } + + /// + /// Specifies one or more directories to add to the include path; separate with semi-colons if more than one. (/I[path]) + /// + public virtual string[] AdditionalIncludeDirectories + { + get { return (string[])Bag["AdditionalIncludeDirectories"]; } + set { Bag["AdditionalIncludeDirectories"] = value; } + } + + /// + /// Suppresses the display of the startup banner and information message. (/nologo) + /// + public virtual bool SuppressStartupBanner + { + get { return GetBoolParameterWithDefault("SuppressStartupBanner", false); } + set { Bag["SuppressStartupBanner"] = value; } + } + + /// + /// Specifies the name of the entry point for the shader (/E[name]) + /// + public virtual string EntryPointName + { + get { return (string)Bag["EntryPointName"]; } + set { Bag["EntryPointName"] = value; } + } + + /// + /// Treats all compiler warnings as errors. For a new project, it may be best to use /WX in all compilations; resolving all warnings will ensure the fewest possible hard-to-find code defects. + /// + public virtual bool TreatWarningAsError + { + get { return GetBoolParameterWithDefault("TreatWarningAsError", false); } + set { Bag["TreatWarningAsError"] = value; } + } + + /// + /// Disable optimizations. /Od implies /Gfp though output may not be identical to /Od /Gfp. + /// + public virtual bool DisableOptimizations + { + get { return GetBoolParameterWithDefault("DisableOptimizations", false); } + set { Bag["DisableOptimizations"] = value; } + } + + /// + /// Enable debugging information. + /// + public virtual bool EnableDebuggingInformation + { + get { return GetBoolParameterWithDefault("EnableDebuggingInformation", false); } + set { Bag["EnableDebuggingInformation"] = value; } + } + + /// + /// Path to Windows SDK + /// + public string SdkToolsPath + { + get { return (string)Bag["SdkToolsPath"]; } + set { Bag["SdkToolsPath"] = value; } + } + + /// + /// Name to Fxc.exe + /// + protected override string ToolName + { + get { return "Fxc.exe"; } + } + + #endregion + + /// + /// Returns a string with those switches and other information that can't go into a response file and + /// must go directly onto the command line. + /// Called after ValidateParameters and SkipTaskExecution + /// + /// + override protected string GenerateCommandLineCommands() + { + CommandLineBuilderExtension commandLineBuilder = new CommandLineBuilderExtension(); + AddCommandLineCommands(commandLineBuilder); + return commandLineBuilder.ToString(); + } + + /// + /// Returns the command line switch used by the tool executable to specify the response file + /// Will only be called if the task returned a non empty string from GetResponseFileCommands + /// Called after ValidateParameters, SkipTaskExecution and GetResponseFileCommands + /// + /// full path to the temporarily created response file + /// + override protected string GenerateResponseFileCommands() + { + CommandLineBuilderExtension commandLineBuilder = new CommandLineBuilderExtension(); + AddResponseFileCommands(commandLineBuilder); + return commandLineBuilder.ToString(); + } + + /// + /// Fills the provided CommandLineBuilderExtension with those switches and other information that can go into a response file. + /// + /// + protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtension commandLine) + { + } + + /// + /// Add Command Line Commands + /// + /// CommandLineBuilderExtension + protected internal void AddCommandLineCommands(CommandLineBuilderExtension commandLine) + { + //// Order of these affect the order of the command line + + commandLine.AppendSwitchIfNotNull("/I ", AdditionalIncludeDirectories, ""); + commandLine.AppendSwitch(SuppressStartupBanner ? "/nologo" : String.Empty); + commandLine.AppendSwitchIfNotNull("/E", EntryPointName); + commandLine.AppendSwitch(TreatWarningAsError ? "/WX" : String.Empty); + + // Switch cannot be null + if (ShaderType != null && ShaderModel != null) + { + // shader Model and Type are one switch + commandLine.AppendSwitch(ShaderType + "_" + ShaderModel); + } + + commandLine.AppendSwitchIfNotNull("/D ", PreprocessorDefinitions, ""); + commandLine.AppendSwitchIfNotNull("/Fh ", HeaderFileOutput); + commandLine.AppendSwitchIfNotNull("/Fo ", ObjectFileOutput); + + // Switch cannot be null + if (AssemblerOutput != null) + { + commandLine.AppendSwitchIfNotNull(AssemblerOutput, AssemblerOutputFile); + } + + commandLine.AppendSwitchIfNotNull("/Vn ", VariableName); + commandLine.AppendSwitch(DisableOptimizations ? "/Od" : String.Empty); + commandLine.AppendSwitch(EnableDebuggingInformation ? "/Zi" : String.Empty); + + commandLine.AppendSwitchIfNotNull("", Source, " "); + } + + /// + /// Fullpath to the fxc.exe + /// + /// Fullpath to fxc.exe, if found. Otherwise empty or null. + protected override string GenerateFullPathToTool() + { + return System.IO.Path.Combine(SdkToolsPath, ToolName); + } + + /// + /// Get a bool parameter and return a default if its not present + /// in the hash table. + /// + /// + /// + /// + /// + /// JomoF + protected internal bool GetBoolParameterWithDefault(string parameterName, bool defaultValue) + { + object obj = bag[parameterName]; + return (obj == null) ? defaultValue : (bool) obj; + } + } +} diff --git a/Samples/360VideoPlayback/cs/Helpers.cs b/Samples/360VideoPlayback/cs/Helpers.cs new file mode 100644 index 0000000000..0c81c9a003 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Helpers.cs @@ -0,0 +1,36 @@ +using System.Numerics; + +namespace _360VideoPlayback +{ + class Helpers + { + static public Quaternion CreateFromHeadingPitchRoll(double heading, double pitch, double roll) + { + Quaternion result; + double headingPart = DegreetoRadians(heading) * 0.5; + double sin1 = System.Math.Sin(headingPart); + double cos1 = System.Math.Cos(headingPart); + + double pitchPart = DegreetoRadians(-pitch) * 0.5; + double sin2 = System.Math.Sin(pitchPart); + double cos2 = System.Math.Cos(pitchPart); + + double rollPart = DegreetoRadians(roll) * 0.5; + double sin3 = System.Math.Sin(rollPart); + double cos3 = System.Math.Cos(rollPart); + + result.W = (float)(cos1 * cos2 * cos3 - sin1 * sin2 * sin3); + result.X = (float)(cos1 * cos2 * sin3 + sin1 * sin2 * cos3); + result.Y = (float)(sin1 * cos2 * cos3 + cos1 * sin2 * sin3); + result.Z = (float)(cos1 * sin2 * cos3 - sin1 * cos2 * sin3); + + return result; + } + + static private double DegreetoRadians(double degree) + { + return degree * System.Math.PI / 180.0; + } + + } +} diff --git a/Samples/360VideoPlayback/cs/HolographicApp1Main.cs b/Samples/360VideoPlayback/cs/HolographicApp1Main.cs new file mode 100644 index 0000000000..b068e3e59e --- /dev/null +++ b/Samples/360VideoPlayback/cs/HolographicApp1Main.cs @@ -0,0 +1,471 @@ +// +// Comment out this preprocessor definition to disable all of the +// sample content. +// +// To remove the content after disabling it: +// * Remove the unused code from this file. +// * Delete the Content folder provided with this template. +// +#define DRAW_SAMPLE_CONTENT + +using System; +using System.Numerics; +using System.Diagnostics; +using Windows.Graphics.Holographic; +using Windows.Perception.Spatial; +using Windows.UI.Input.Spatial; + +using HolographicApp2.Common; +using System.Threading.Tasks; +using Windows.Foundation; +using System.Collections.Generic; + +#if DRAW_SAMPLE_CONTENT +using HolographicApp2.Content; +#endif + +namespace HolographicApp2 +{ + /// + /// Updates, renders, and presents holographic content using Direct3D. + /// + internal class HolographicApp1Main : IDisposable + { + +#if DRAW_SAMPLE_CONTENT + // Renders a colorful holographic cube that's 20 centimeters wide. This sample content + // is used to demonstrate world-locked rendering. + private SpinningCubeRenderer spinningCubeRenderer; + + private SpatialInputHandler spatialInputHandler; +#endif + + // Cached reference to device resources. + private DeviceResources deviceResources; + + // Render loop timer. + private StepTimer timer = new StepTimer(); + + // Represents the holographic space around the user. + HolographicSpace holographicSpace; + + // SpatialLocator that is attached to the primary camera. + SpatialLocator locator; + + // A reference frame attached to the holographic camera. + SpatialStationaryFrameOfReference referenceFrame; + + SpatialLocatorAttachedFrameOfReference attachreferenceFrame; + + /// + /// Loads and initializes application assets when the application is loaded. + /// + /// + public HolographicApp1Main(DeviceResources deviceResources) + { + this.deviceResources = deviceResources; + + // Register to be notified if the Direct3D device is lost. + this.deviceResources.DeviceLost += this.OnDeviceLost; + this.deviceResources.DeviceRestored += this.OnDeviceRestored; + } + + public void SetHolographicSpace(HolographicSpace holographicSpace) + { + this.holographicSpace = holographicSpace; + + // + // TODO: Add code here to initialize your content. + // + +#if DRAW_SAMPLE_CONTENT + // Initialize the sample hologram. + spinningCubeRenderer = new SpinningCubeRenderer(deviceResources); + + spatialInputHandler = new SpatialInputHandler(); +#endif + + // Use the default SpatialLocator to track the motion of the device. + locator = SpatialLocator.GetDefault(); + + // Be able to respond to changes in the positional tracking state. + locator.LocatabilityChanged += this.OnLocatabilityChanged; + + // Respond to camera added events by creating any resources that are specific + // to that camera, such as the back buffer render target view. + // When we add an event handler for CameraAdded, the API layer will avoid putting + // the new camera in new HolographicFrames until we complete the deferral we created + // for that handler, or return from the handler without creating a deferral. This + // allows the app to take more than one frame to finish creating resources and + // loading assets for the new holographic camera. + // This function should be registered before the app creates any HolographicFrames. + holographicSpace.CameraAdded += this.OnCameraAdded; + + // Respond to camera removed events by releasing resources that were created for that + // camera. + // When the app receives a CameraRemoved event, it releases all references to the back + // buffer right away. This includes render target views, Direct2D target bitmaps, and so on. + // The app must also ensure that the back buffer is not attached as a render target, as + // shown in DeviceResources.ReleaseResourcesForBackBuffer. + holographicSpace.CameraRemoved += this.OnCameraRemoved; + + // The simplest way to render world-locked holograms is to create a stationary reference frame + // when the app is launched. This is roughly analogous to creating a "world" coordinate system + // with the origin placed at the device's position as the app is launched. + referenceFrame = locator.CreateStationaryFrameOfReferenceAtCurrentLocation(); + attachreferenceFrame = locator.CreateAttachedFrameOfReferenceAtCurrentHeading(); + + // Notes on spatial tracking APIs: + // * Stationary reference frames are designed to provide a best-fit position relative to the + // overall space. Individual positions within that reference frame are allowed to drift slightly + // as the device learns more about the environment. + // * When precise placement of individual holograms is required, a SpatialAnchor should be used to + // anchor the individual hologram to a position in the real world - for example, a point the user + // indicates to be of special interest. Anchor positions do not drift, but can be corrected; the + // anchor will use the corrected position starting in the next frame after the correction has + // occurred. + } + + public void Dispose() + { +#if DRAW_SAMPLE_CONTENT + if (spinningCubeRenderer != null) + { + spinningCubeRenderer.ReleaseDeviceDependentResources(); + spinningCubeRenderer.Dispose(); + spinningCubeRenderer = null; + } +#endif + } + + /// + /// Updates the application state once per frame. + /// + public HolographicFrame Update() + { + // Before doing the timer update, there is some work to do per-frame + // to maintain holographic rendering. First, we will get information + // about the current frame. + + // The HolographicFrame has information that the app needs in order + // to update and render the current frame. The app begins each new + // frame by calling CreateNextFrame. + HolographicFrame holographicFrame = holographicSpace.CreateNextFrame(); + + // Get a prediction of where holographic cameras will be when this frame + // is presented. + HolographicFramePrediction prediction = holographicFrame.CurrentPrediction; + + // Back buffers can change from frame to frame. Validate each buffer, and recreate + // resource views and depth buffers as needed. + deviceResources.EnsureCameraResources(holographicFrame, prediction); + + // Next, we get a coordinate system from the attached frame of reference that is + // associated with the current frame. Later, this coordinate system is used for + // for creating the stereo view matrices when rendering the sample content. + SpatialCoordinateSystem currentCoordinateSystem = attachreferenceFrame.GetStationaryCoordinateSystemAtTimestamp(prediction.Timestamp);//referenceFrame.CoordinateSystem; + + +#if DRAW_SAMPLE_CONTENT + + // Check for new input state since the last frame. + SpatialInteractionSourceState pointerState = spatialInputHandler.CheckForInput(); + if (null != pointerState) + { + // When a Pressed gesture is detected, the sample hologram will be repositioned + // two meters in front of the user. + spinningCubeRenderer.PositionHologram( + // pointerState.TryGetPointerPose(currentCoordinateSystem) + SpatialPointerPose.TryGetAtTimestamp(currentCoordinateSystem, prediction.Timestamp) + ); + } + + //var downstate = Windows.UI.Core.CoreVirtualKeyStates.Down; + //bool rightclick = (Windows.UI.Core.CoreWindow.GetForCurrentThread().GetKeyState(Windows.System.VirtualKey.Escape) & downstate) == downstate; + //System.Diagnostics.Debug.WriteLine("Windows.System.VirtualKey.Escape " + Windows.UI.Core.CoreWindow.GetForCurrentThread().GetKeyState(Windows.System.VirtualKey.Escape).ToString() + " downstate" + downstate); + //System.Diagnostics.Debug.WriteLine("Windows.System.VirtualKey.A " + Windows.UI.Core.CoreWindow.GetForCurrentThread().GetKeyState(Windows.System.VirtualKey.A).ToString() + " downstate" + downstate); + //if (rightclick) + //{ + // Windows.UI.ViewManagement.ApplicationViewSwitcher.SwitchAsync(VideoGallery.mainId, VideoGallery.appId, Windows.UI.ViewManagement.ApplicationViewSwitchingOptions.ConsolidateViews); + //} +#endif + + + + timer.Tick(() => + { + // + // TODO: Update scene objects. + // + // Put time-based updates here. By default this code will run once per frame, + // but if you change the StepTimer to use a fixed time step this code will + // run as many times as needed to get to the current step. + // + +#if DRAW_SAMPLE_CONTENT + spinningCubeRenderer.Update(timer); +#endif + }); + + // We complete the frame update by using information about our content positioning + // to set the focus point. + foreach (var cameraPose in prediction.CameraPoses) + { +#if DRAW_SAMPLE_CONTENT + // The HolographicCameraRenderingParameters class provides access to set + // the image stabilization parameters. + HolographicCameraRenderingParameters renderingParameters = holographicFrame.GetRenderingParameters(cameraPose); + + // SetFocusPoint informs the system about a specific point in your scene to + // prioritize for image stabilization. The focus point is set independently + // for each holographic camera. + // You should set the focus point near the content that the user is looking at. + // In this example, we put the focus point at the center of the sample hologram, + // since that is the only hologram available for the user to focus on. + // You can also set the relative velocity and facing of that content; the sample + // hologram is at a fixed point so we only need to indicate its position. + Vector3 position = new Vector3(0.0f, 0.0f, -3.0f); + renderingParameters.SetFocusPoint( + currentCoordinateSystem, position + /*spinningCubeRenderer.Position*/ + ); +#endif + } + + // The holographic frame will be used to get up-to-date view and projection matrices and + // to present the swap chain. + return holographicFrame; + } + + /// + /// Renders the current frame to each holographic display, according to the + /// current application and spatial positioning state. Returns true if the + /// frame was rendered to at least one display. + /// + public bool Render(ref HolographicFrame holographicFrame) + { + // Don't try to render anything before the first Update. + if (timer.FrameCount == 0) + { + return false; + } + + // + // TODO: Add code for pre-pass rendering here. + // + // Take care of any tasks that are not specific to an individual holographic + // camera. This includes anything that doesn't need the final view or projection + // matrix, such as lighting maps. + // + + // Up-to-date frame predictions enhance the effectiveness of image stablization and + // allow more accurate positioning of holograms. + holographicFrame.UpdateCurrentPrediction(); + HolographicFramePrediction prediction = holographicFrame.CurrentPrediction; + + // Lock the set of holographic camera resources, then draw to each camera + // in this frame. + return deviceResources.UseHolographicCameraResources( + (Dictionary cameraResourceDictionary) => + { + bool atLeastOneCameraRendered = false; + + foreach (var cameraPose in prediction.CameraPoses) + { + // This represents the device-based resources for a HolographicCamera. + CameraResources cameraResources = cameraResourceDictionary[cameraPose.HolographicCamera.Id]; + + // Get the device context. + var context = deviceResources.D3DDeviceContext; + var renderTargetView = cameraResources.BackBufferRenderTargetView; + var depthStencilView = cameraResources.DepthStencilView; + + // Set render targets to the current holographic camera. + context.OutputMerger.SetRenderTargets(depthStencilView, renderTargetView); + + // Clear the back buffer and depth stencil view. + SharpDX.Mathematics.Interop.RawColor4 transparent = new SharpDX.Mathematics.Interop.RawColor4(0.0f, 0.0f, 0.0f, 0.0f); + context.ClearRenderTargetView(renderTargetView, transparent); + context.ClearDepthStencilView( + depthStencilView, + SharpDX.Direct3D11.DepthStencilClearFlags.Depth | SharpDX.Direct3D11.DepthStencilClearFlags.Stencil, + 1.0f, + 0); + + // + // TODO: Replace the sample content with your own content. + // + // Notes regarding holographic content: + // * For drawing, remember that you have the potential to fill twice as many pixels + // in a stereoscopic render target as compared to a non-stereoscopic render target + // of the same resolution. Avoid unnecessary or repeated writes to the same pixel, + // and only draw holograms that the user can see. + // * To help occlude hologram geometry, you can create a depth map using geometry + // data obtained via the surface mapping APIs. You can use this depth map to avoid + // rendering holograms that are intended to be hidden behind tables, walls, + // monitors, and so on. + // * Black pixels will appear transparent to the user wearing the device, but you + // should still use alpha blending to draw semitransparent holograms. You should + // also clear the screen to Transparent as shown above. + // + + + // The view and projection matrices for each holographic camera will change + // every frame. This function refreshes the data in the constant buffer for + // the holographic camera indicated by cameraPose. + cameraResources.UpdateViewProjectionBuffer(deviceResources, cameraPose, attachreferenceFrame.GetStationaryCoordinateSystemAtTimestamp(prediction.Timestamp)/*referenceFrame.CoordinateSystem*/); + + // Attach the view/projection constant buffer for this camera to the graphics pipeline. + bool cameraActive = cameraResources.AttachViewProjectionBuffer(deviceResources); + +#if DRAW_SAMPLE_CONTENT + // Only render world-locked content when positional tracking is active. + if (cameraActive) + { + // Draw the sample hologram. + spinningCubeRenderer.Render(); + } +#endif + atLeastOneCameraRendered = true; + } + + return atLeastOneCameraRendered; + }); + } + + public void SaveAppState() + { + // + // TODO: Insert code here to save your app state. + // This method is called when the app is about to suspend. + // + // For example, store information in the SpatialAnchorStore. + // + } + + public void LoadAppState() + { + // + // TODO: Insert code here to load your app state. + // This method is called when the app resumes. + // + // For example, load information from the SpatialAnchorStore. + // + } + + + /// + /// Notifies renderers that device resources need to be released. + /// + public void OnDeviceLost(Object sender, EventArgs e) + { + +#if DRAW_SAMPLE_CONTENT + spinningCubeRenderer.ReleaseDeviceDependentResources(); +#endif + + } + + /// + /// Notifies renderers that device resources may now be recreated. + /// + public void OnDeviceRestored(Object sender, EventArgs e) + { +#if DRAW_SAMPLE_CONTENT + spinningCubeRenderer.CreateDeviceDependentResourcesAsync(); +#endif + } + + void OnLocatabilityChanged(SpatialLocator sender, Object args) + { + switch (sender.Locatability) + { + case SpatialLocatability.Unavailable: + // Holograms cannot be rendered. + { + String message = "Warning! Positional tracking is " + sender.Locatability + "."; + Debug.WriteLine(message); + } + break; + + // In the following three cases, it is still possible to place holograms using a + // SpatialLocatorAttachedFrameOfReference. + case SpatialLocatability.PositionalTrackingActivating: + // The system is preparing to use positional tracking. + + case SpatialLocatability.OrientationOnly: + // Positional tracking has not been activated. + + case SpatialLocatability.PositionalTrackingInhibited: + // Positional tracking is temporarily inhibited. User action may be required + // in order to restore positional tracking. + break; + + case SpatialLocatability.PositionalTrackingActive: + // Positional tracking is active. World-locked content can be rendered. + break; + } + } + + public void OnCameraAdded( + HolographicSpace sender, + HolographicSpaceCameraAddedEventArgs args + ) + { + Deferral deferral = args.GetDeferral(); + HolographicCamera holographicCamera = args.Camera; + + Task task1 = new Task(() => + { + // + // TODO: Allocate resources for the new camera and load any content specific to + // that camera. Note that the render target size (in pixels) is a property + // of the HolographicCamera object, and can be used to create off-screen + // render targets that match the resolution of the HolographicCamera. + // + + // Create device-based resources for the holographic camera and add it to the list of + // cameras used for updates and rendering. Notes: + // * Since this function may be called at any time, the AddHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // adding the new camera. At 60 frames per second this wait should not take long. + // * A subsequent Update will take the back buffer from the RenderingParameters of this + // camera's CameraPose and use it to create the ID3D11RenderTargetView for this camera. + // Content can then be rendered for the HolographicCamera. + deviceResources.AddHolographicCamera(holographicCamera); + + // Holographic frame predictions will not include any information about this camera until + // the deferral is completed. + deferral.Complete(); + }); + task1.Start(); + } + + public void OnCameraRemoved( + HolographicSpace sender, + HolographicSpaceCameraRemovedEventArgs args + ) + { + Task task2 = new Task(() => + { + // + // TODO: Asynchronously unload or deactivate content resources (not back buffer + // resources) that are specific only to the camera that was removed. + // + }); + task2.Start(); + + // Before letting this callback return, ensure that all references to the back buffer + // are released. + // Since this function may be called at any time, the RemoveHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // deallocating resources for this camera. At 60 frames per second this wait should + // not take long. + deviceResources.RemoveHolographicCamera(args.Camera); + } + public void CreateVideoShaders() + { + spinningCubeRenderer.CreateDeviceDependentResourcesAsync(); + } + } +} diff --git a/Samples/360VideoPlayback/cs/MainPage.xaml.cs b/Samples/360VideoPlayback/cs/MainPage.xaml.cs new file mode 100644 index 0000000000..58b1aecdf0 --- /dev/null +++ b/Samples/360VideoPlayback/cs/MainPage.xaml.cs @@ -0,0 +1,34 @@ +using Windows.UI.Core; +using Windows.UI.Xaml.Controls; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 + +namespace _360VideoPlayback +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainPage : Page + { + public MainPage() + { + this.InitializeComponent(); + SystemNavigationManager.GetForCurrentView().BackRequested += MainPage_BackRequested; + this.contentFrame.Navigate(typeof(VideoGallery)); + } + + private void MainPage_BackRequested(object sender, BackRequestedEventArgs e) + { + goBack(null, e); + } + + private void goBack(object sender, BackRequestedEventArgs e) + { + if (this.contentFrame.CanGoBack) + { + this.contentFrame.GoBack(); + e.Handled = true; + } + } + } +} diff --git a/Samples/360VideoPlayback/cs/Package.appxmanifest b/Samples/360VideoPlayback/cs/Package.appxmanifest new file mode 100644 index 0000000000..ff8c275c82 --- /dev/null +++ b/Samples/360VideoPlayback/cs/Package.appxmanifest @@ -0,0 +1,44 @@ + + + + + + 360 Video Playback C# Sample + Microsoft Corporation + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/360VideoPlayback/cs/PlaybackPage.xaml.cs b/Samples/360VideoPlayback/cs/PlaybackPage.xaml.cs new file mode 100644 index 0000000000..cbdde5a345 --- /dev/null +++ b/Samples/360VideoPlayback/cs/PlaybackPage.xaml.cs @@ -0,0 +1,331 @@ +using _360VideoPlayback.Common; +using System; +using Windows.Foundation; +using Windows.Gaming.Input; +using Windows.Media.Core; +using Windows.Media.Playback; +using Windows.System; +using Windows.System.Threading; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace _360VideoPlayback +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class PlaybackPage : Page + { + private MediaPlayer mediaPlayer; + // positions hold the center of the window + private double centerX = 0, centerY = 0; + // MTC grid to ignore mouse event on the MTC Panel + Grid mtcGrid = null; + private double pitch = 0, heading = 0; + private MediaPlaybackSphericalVideoProjection videoProjection; + private bool isPointerPress = false; + IAsyncAction m_inputLoopWorker = null; + Gamepad activeGamePad = null; + WorkItemHandler workItemHandler; + const double THUMBSTICK_DEADZONE = 0.25f; + //Frame Timer + private StepTimer timer = new StepTimer(); + double rotationdelta = 1.8f; + const int scrollStep = 2; + const int mouseWheelData = 120; + + public PlaybackPage() + { + this.InitializeComponent(); + this.LayoutUpdated += PlaybackPage_LayoutUpdated; + } + + private void PlaybackPage_LayoutUpdated(object sender, object e) + { + centerX = VideoElement.ActualWidth / 2; + centerY = VideoElement.ActualHeight / 2; + if (mtcGrid == null) + { + FrameworkElement transportControlsTemplateRoot = (FrameworkElement)VisualTreeHelper.GetChild(VideoElement.TransportControls, 0); + if (transportControlsTemplateRoot != null) + { + mtcGrid = (Grid)transportControlsTemplateRoot.FindName("ControlPanelGrid"); + mtcGrid.PointerPressed += OnPointerPressed; + mtcGrid.PointerReleased += OnPointerReleased; + mtcGrid.PointerWheelChanged += OnPointerWheelChanged; + VideoElement.PointerPressed += OnPointerPressed; + VideoElement.PointerReleased += OnPointerReleased; + VideoElement.PointerMoved += OnPointerMoved; + VideoElement.PointerWheelChanged += OnPointerWheelChanged; + Window.Current.CoreWindow.KeyDown += OnKeyDown; + } + } + } + + private void OnPointerWheelChanged(object sender, PointerRoutedEventArgs e) + { + if (e.OriginalSource != mtcGrid) + { + double value = videoProjection.HorizontalFieldOfViewInDegrees + + (scrollStep * e.GetCurrentPoint(VideoElement).Properties.MouseWheelDelta / mouseWheelData); + if (value > 0 && value <= 180) + { + videoProjection.HorizontalFieldOfViewInDegrees = value; + } + } + e.Handled = true; + } + + private void OnKeyDown(CoreWindow sender, KeyEventArgs args) + { + if (IsMediaAlreadyOpened()) + { + bool isMTCEnabled = VideoElement.AreTransportControlsEnabled; + + if (args.VirtualKey == VirtualKey.Up) + { + pitch = pitch + 0.5; + videoProjection.ViewOrientation = Helpers.CreateFromHeadingPitchRoll(heading, pitch, 0); + } + if (args.VirtualKey == VirtualKey.Down) + { + pitch = pitch - 0.5; + videoProjection.ViewOrientation = Helpers.CreateFromHeadingPitchRoll(heading, pitch, 0); + } + if (args.VirtualKey == VirtualKey.Right) + { + heading = heading + 0.5; + videoProjection.ViewOrientation = Helpers.CreateFromHeadingPitchRoll(heading, pitch, 0); + } + if (args.VirtualKey == VirtualKey.Left) + { + heading = heading - 0.5; + videoProjection.ViewOrientation = Helpers.CreateFromHeadingPitchRoll(heading, pitch, 0); + } + if (args.VirtualKey == VirtualKey.GamepadA) + { + if (!isMTCEnabled) + { + VideoElement.AreTransportControlsEnabled = true; + m_inputLoopWorker.Cancel(); + args.Handled = true; + } + + } + if (args.VirtualKey == VirtualKey.GamepadB) + { + if (isMTCEnabled) + { + VideoElement.AreTransportControlsEnabled = false; + StartInputLoop(); + args.Handled = true; + } + } + if (args.VirtualKey == VirtualKey.GamepadLeftTrigger) + { + double value = videoProjection.HorizontalFieldOfViewInDegrees + 2; + + if (value <= 180) + { + videoProjection.HorizontalFieldOfViewInDegrees = value; + } + args.Handled = true; + } + if (args.VirtualKey == VirtualKey.GamepadRightTrigger) + { + double value = videoProjection.HorizontalFieldOfViewInDegrees - 2; + + if (value > 0) + { + videoProjection.HorizontalFieldOfViewInDegrees = value; + } + args.Handled = true; + } + } + } + + private void OnPointerMoved(object sender, PointerRoutedEventArgs e) + { + if (e.OriginalSource != mtcGrid && isPointerPress) + { + double ChangeX = e.GetCurrentPoint(VideoElement).Position.X - centerX; + double ChangeY = centerY - e.GetCurrentPoint(VideoElement).Position.Y; + videoProjection.ViewOrientation = Helpers.CreateFromHeadingPitchRoll(ChangeX, ChangeY, 0); + } + e.Handled = true; + } + + private void OnPointerReleased(object sender, PointerRoutedEventArgs e) + { + ResetState(); + e.Handled = true; + } + + private void OnPointerPressed(object sender, PointerRoutedEventArgs e) + { + if (e.OriginalSource != mtcGrid && IsMediaAlreadyOpened()) + { + isPointerPress = true; + } + e.Handled = true; + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible; + + Uri sourceUri = (Uri)e.Parameter; + if (sourceUri != null) + { + mediaPlayer = new MediaPlayer(); + MediaSource source = MediaSource.CreateFromUri(sourceUri); + mediaPlayer.Source = source; + mediaPlayer.MediaOpened += MediaPlayer_MediaOpened; + VideoElement.SetMediaPlayer(mediaPlayer); + } + } + + private void MediaPlayer_MediaOpened(MediaPlayer sender, object args) + { + videoProjection = mediaPlayer.PlaybackSession.SphericalVideoProjection; + Windows.Media.MediaProperties.SphericalVideoFrameFormat videoFormat = videoProjection.FrameFormat; + // Some times Content metadata doesn't provided correct format. Try to force the equirectangular format, if doesn't match + if (videoFormat != Windows.Media.MediaProperties.SphericalVideoFrameFormat.Equirectangular) + { + videoProjection.FrameFormat = Windows.Media.MediaProperties.SphericalVideoFrameFormat.Equirectangular; + } + videoProjection.IsEnabled = true; + videoProjection.HorizontalFieldOfViewInDegrees = 120; + mediaPlayer.PlaybackSession.PlaybackStateChanged += PlaybackSession_PlaybackStateChanged; + + StartInputLoop(); + } + + private void PlaybackSession_PlaybackStateChanged(MediaPlaybackSession sender, object args) + { + if (mediaPlayer.PlaybackSession.PlaybackState == MediaPlaybackState.Playing) + { + rotationdelta = 1.8f; + } + else + { + rotationdelta = 0.25f; + } + } + + private bool IsMediaAlreadyOpened() + { + if (mediaPlayer != null && videoProjection != null && + mediaPlayer.PlaybackSession.PlaybackState != MediaPlaybackState.Opening && + mediaPlayer.PlaybackSession.PlaybackState != MediaPlaybackState.None) + { + return true; + } + return false; + } + + private void ResetState() + { + isPointerPress = false; + pitch = 0; + heading = 0; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + if (mediaPlayer != null) + { + mediaPlayer.PlaybackSession.PlaybackStateChanged -= PlaybackSession_PlaybackStateChanged; + mediaPlayer.MediaOpened -= MediaPlayer_MediaOpened; + } + if (mtcGrid != null) + { + mtcGrid.PointerPressed -= OnPointerPressed; + mtcGrid.PointerReleased -= OnPointerReleased; + mtcGrid.PointerWheelChanged -= OnPointerWheelChanged; + VideoElement.PointerPressed -= OnPointerPressed; + VideoElement.PointerReleased -= OnPointerReleased; + VideoElement.PointerMoved -= OnPointerMoved; + VideoElement.PointerWheelChanged -= OnPointerWheelChanged; + Window.Current.CoreWindow.KeyDown -= OnKeyDown; + } + + SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed; + mediaPlayer.Source = null; + VideoElement.SetMediaPlayer(null); + mediaPlayer = null; + } + + void StartInputLoop() + { + // If the animation render loop is already running then do not start another thread. + if (m_inputLoopWorker != null) + { + if (m_inputLoopWorker.Status == AsyncStatus.Started) + { + return; + } + else + { + m_inputLoopWorker.Close(); + } + } + + workItemHandler = new WorkItemHandler((IAsyncAction action) => + { + while (action.Status == AsyncStatus.Started) + { + var gamepads = Gamepad.Gamepads; + if (gamepads.Count > 0 && activeGamePad == null) + { + // Get the Zero based first Gamepad + activeGamePad = gamepads[0]; + } + + if (activeGamePad != null) + { + timer.Tick(() => + { + GamepadReading reading = activeGamePad.GetCurrentReading(); + double deltax; + if (reading.LeftThumbstickX > THUMBSTICK_DEADZONE || reading.LeftThumbstickX < -THUMBSTICK_DEADZONE) + { + deltax = reading.LeftThumbstickX * reading.LeftThumbstickX * reading.LeftThumbstickX; + } + else + { + deltax = 0.0f; + } + double deltay; + if (reading.LeftThumbstickY > THUMBSTICK_DEADZONE || reading.LeftThumbstickY < -THUMBSTICK_DEADZONE) + { + deltay = reading.LeftThumbstickY * reading.LeftThumbstickY * reading.LeftThumbstickY; + } + else + { + deltay = 0.0f; + } + + double rotationX = deltax * rotationdelta; + double rotationY = deltay * rotationdelta; + + pitch += rotationY; + heading += rotationX; + + // Limit pitch to straight up or straight down. + videoProjection.ViewOrientation = Helpers.CreateFromHeadingPitchRoll(heading, pitch, 0); + }); + } + } + }); + + m_inputLoopWorker = ThreadPool.RunAsync(workItemHandler, WorkItemPriority.High, WorkItemOptions.None); + } + } +} diff --git a/Samples/360VideoPlayback/cs/Program.cs b/Samples/360VideoPlayback/cs/Program.cs new file mode 100644 index 0000000000..b1b03fb29e --- /dev/null +++ b/Samples/360VideoPlayback/cs/Program.cs @@ -0,0 +1,21 @@ +using System; +using Windows.ApplicationModel.Core; + +namespace _360VideoPlayback +{ + /// + /// Windows Holographic application using SharpDX. + /// + internal class Program + { + /// + /// Defines the entry point of the application. + /// + [MTAThread] + private static void Main() + { + var exclusiveViewApplicationSource = new AppViewSource(); + CoreApplication.Run(exclusiveViewApplicationSource); + } + } +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/cs/VideoGallery.xaml.cs b/Samples/360VideoPlayback/cs/VideoGallery.xaml.cs new file mode 100644 index 0000000000..8723589e43 --- /dev/null +++ b/Samples/360VideoPlayback/cs/VideoGallery.xaml.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.ObjectModel; +using Windows.ApplicationModel.Core; +using Windows.Graphics.Holographic; +using Windows.Perception.Spatial.Surfaces; +using Windows.UI.Core; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace _360VideoPlayback +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class VideoGallery : Page + { + static public int mainviewId = 0; + + public VideoGallery() + { + this.InitializeComponent(); + mainviewId = ApplicationView.GetForCurrentView().Id; + this.Loaded += VideoGallery_Loaded; + } + + async private void GalleryGridView_ItemClick(object sender, ItemClickEventArgs e) + { + VideoItem selectedVideo = (VideoItem)e.ClickedItem; + if (selectedVideo != null) + { + if ((HolographicSpace.IsSupported && HolographicSpace.IsAvailable) + || SpatialSurfaceObserver.IsSupported()) + { + var appViewSource = new AppViewSource(selectedVideo.SourceUri); + var appView = CoreApplication.CreateNewView(appViewSource); + await appView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => + { + int appviewId = ApplicationView.GetForCurrentView().Id; + bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(appviewId, ViewSizePreference.Default, mainviewId, ViewSizePreference.Default); + System.Diagnostics.Debug.Assert(viewShown); + }); + } + else + { + Frame.Navigate(typeof(PlaybackPage), selectedVideo.SourceUri); + } + } + } + + private class VideoItemInfo + { + public string Title; + public string Source; + } + + static VideoItemInfo[] sampleVideos = + { + // You can add more sample videos here. + new VideoItemInfo { Title = "Sample Video", Source = "https://mediaplatstorage1.blob.core.windows.net/windows-universal-samples-media/SampleVideo.mp4" } + }; + + private void VideoGallery_Loaded(object sender, RoutedEventArgs e) + { + ObservableCollection videoList = new ObservableCollection(); + foreach (var info in sampleVideos) + { + videoList.Add(new VideoItem(info.Title, new Uri(info.Source))); + } + + GalleryGridView.ItemsSource = videoList; + } + } +} diff --git a/Samples/360VideoPlayback/cs/VideoItem.cs b/Samples/360VideoPlayback/cs/VideoItem.cs new file mode 100644 index 0000000000..a72c712708 --- /dev/null +++ b/Samples/360VideoPlayback/cs/VideoItem.cs @@ -0,0 +1,15 @@ +using System; + +namespace _360VideoPlayback +{ + public class VideoItem + { + public VideoItem(string title, Uri sourceUri) + { + Title = title; + SourceUri = sourceUri; + } + public string Title { get; private set; } + public Uri SourceUri { get; private set; } + } +} diff --git a/Samples/360VideoPlayback/cs/_360VideoPlaybackMain.cs b/Samples/360VideoPlayback/cs/_360VideoPlaybackMain.cs new file mode 100644 index 0000000000..e8364ac182 --- /dev/null +++ b/Samples/360VideoPlayback/cs/_360VideoPlaybackMain.cs @@ -0,0 +1,432 @@ +// +// Comment out this preprocessor definition to disable all of the +// sample content. +// +// To remove the content after disabling it: +// * Remove the unused code from this file. +// * Delete the Content folder provided with this template. +// +#define DRAW_SAMPLE_CONTENT + +using System; +using System.Numerics; +using System.Diagnostics; +using Windows.Graphics.Holographic; +using Windows.Perception.Spatial; +using Windows.UI.Input.Spatial; + +using _360VideoPlayback.Common; +using System.Threading.Tasks; +using Windows.Foundation; +using System.Collections.Generic; + +#if DRAW_SAMPLE_CONTENT +using _360VideoPlayback.Content; +#endif + +namespace _360VideoPlayback +{ + /// + /// Updates, renders, and presents holographic content using Direct3D. + /// + internal class _360VideoPlaybackMain : IDisposable + { + +#if DRAW_SAMPLE_CONTENT + // Renders a SPherical Video Playback . This sample content + // is used to demonstrate world-locked rendering. + private VideoRenderer videoRenderer; + + private SpatialInputHandler spatialInputHandler; +#endif + + // Cached reference to device resources. + private DeviceResources deviceResources; + + // Render loop timer. + private StepTimer timer = new StepTimer(); + + // Represents the holographic space around the user. + HolographicSpace holographicSpace; + + // SpatialLocator that is attached to the primary camera. + SpatialLocator locator; + + // A reference frame attached to the holographic camera. + SpatialLocatorAttachedFrameOfReference attachreferenceFrame; + + /// + /// Loads and initializes application assets when the application is loaded. + /// + /// + public _360VideoPlaybackMain(DeviceResources deviceResources) + { + this.deviceResources = deviceResources; + + // Register to be notified if the Direct3D device is lost. + this.deviceResources.DeviceLost += this.OnDeviceLost; + this.deviceResources.DeviceRestored += this.OnDeviceRestored; + } + + public void SetHolographicSpace(HolographicSpace holographicSpace) + { + this.holographicSpace = holographicSpace; + + // + // TODO: Add code here to initialize your content. + // + +#if DRAW_SAMPLE_CONTENT + // Initialize the sample hologram. + videoRenderer = new VideoRenderer(deviceResources); + + spatialInputHandler = new SpatialInputHandler(); +#endif + + // Use the default SpatialLocator to track the motion of the device. + locator = SpatialLocator.GetDefault(); + + // Be able to respond to changes in the positional tracking state. + locator.LocatabilityChanged += this.OnLocatabilityChanged; + + // Respond to camera added events by creating any resources that are specific + // to that camera, such as the back buffer render target view. + // When we add an event handler for CameraAdded, the API layer will avoid putting + // the new camera in new HolographicFrames until we complete the deferral we created + // for that handler, or return from the handler without creating a deferral. This + // allows the app to take more than one frame to finish creating resources and + // loading assets for the new holographic camera. + // This function should be registered before the app creates any HolographicFrames. + holographicSpace.CameraAdded += this.OnCameraAdded; + + // Respond to camera removed events by releasing resources that were created for that + // camera. + // When the app receives a CameraRemoved event, it releases all references to the back + // buffer right away. This includes render target views, Direct2D target bitmaps, and so on. + // The app must also ensure that the back buffer is not attached as a render target, as + // shown in DeviceResources.ReleaseResourcesForBackBuffer. + holographicSpace.CameraRemoved += this.OnCameraRemoved; + + // The simplest way to render video Frame is to create a stationary reference frame + // when the app is launched. This is roughly analogous to creating a "world" coordinate system + // with the origin placed at the device's position as the app is launched. + attachreferenceFrame = locator.CreateAttachedFrameOfReferenceAtCurrentHeading(); + + // Notes on spatial tracking APIs: + // * Stationary reference frames are designed to provide a best-fit position relative to the + // overall space. Individual positions within that reference frame are allowed to drift slightly + // as the device learns more about the environment. + // * When precise placement of individual holograms is required, a SpatialAnchor should be used to + // anchor the individual hologram to a position in the real world - for example, a point the user + // indicates to be of special interest. Anchor positions do not drift, but can be corrected; the + // anchor will use the corrected position starting in the next frame after the correction has + // occurred. + } + + public void Dispose() + { +#if DRAW_SAMPLE_CONTENT + if (videoRenderer != null) + { + videoRenderer.ReleaseDeviceDependentResources(); + videoRenderer.Dispose(); + videoRenderer = null; + } +#endif + } + + /// + /// Updates the application state once per frame. + /// + public HolographicFrame Update() + { + // Before doing the timer update, there is some work to do per-frame + // to maintain holographic rendering. First, we will get information + // about the current frame. + + // The HolographicFrame has information that the app needs in order + // to update and render the current frame. The app begins each new + // frame by calling CreateNextFrame. + HolographicFrame holographicFrame = holographicSpace.CreateNextFrame(); + + // Get a prediction of where holographic cameras will be when this frame + // is presented. + HolographicFramePrediction prediction = holographicFrame.CurrentPrediction; + + // Back buffers can change from frame to frame. Validate each buffer, and recreate + // resource views and depth buffers as needed. + deviceResources.EnsureCameraResources(holographicFrame, prediction); + + // Next, we get a coordinate system from the attached frame of reference that is + // associated with the current frame. Later, this coordinate system is used for + // for creating the stereo view matrices when rendering the sample content. + SpatialCoordinateSystem currentCoordinateSystem = attachreferenceFrame.GetStationaryCoordinateSystemAtTimestamp(prediction.Timestamp);//referenceFrame.CoordinateSystem; + + timer.Tick(() => + { + // + // TODO: Update scene objects. + // + // Put time-based updates here. By default this code will run once per frame, + // but if you change the StepTimer to use a fixed time step this code will + // run as many times as needed to get to the current step. + // + +#if DRAW_SAMPLE_CONTENT + videoRenderer.Update(timer); +#endif + }); + + // We complete the frame update by using information about our content positioning + // to set the focus point. + foreach (var cameraPose in prediction.CameraPoses) + { +#if DRAW_SAMPLE_CONTENT + // The HolographicCameraRenderingParameters class provides access to set + // the image stabilization parameters. + HolographicCameraRenderingParameters renderingParameters = holographicFrame.GetRenderingParameters(cameraPose); + + // SetFocusPoint informs the system about a specific point in your scene to + // prioritize for image stabilization. The focus point is set independently + // for each holographic camera. + // You should set the focus point near the content that the user is looking at. + // In this example, we put the focus point at the center of the sample hologram, + // since that is the only hologram available for the user to focus on. + // You can also set the relative velocity and facing of that content; the sample + // hologram is at a fixed point so we only need to indicate its position. + Vector3 position = new Vector3(0.0f, 0.0f, 0.0f); + renderingParameters.SetFocusPoint( + currentCoordinateSystem, position + ); +#endif + } + + // The holographic frame will be used to get up-to-date view and projection matrices and + // to present the swap chain. + return holographicFrame; + } + + /// + /// Renders the current frame to each holographic display, according to the + /// current application and spatial positioning state. Returns true if the + /// frame was rendered to at least one display. + /// + public bool Render(ref HolographicFrame holographicFrame) + { + // Don't try to render anything before the first Update. + if (timer.FrameCount == 0) + { + return false; + } + + // Up-to-date frame predictions enhance the effectiveness of image stablization and + // allow more accurate positioning of holograms. + holographicFrame.UpdateCurrentPrediction(); + HolographicFramePrediction prediction = holographicFrame.CurrentPrediction; + + // Lock the set of holographic camera resources, then draw to each camera + // in this frame. + return deviceResources.UseHolographicCameraResources( + (Dictionary cameraResourceDictionary) => + { + bool atLeastOneCameraRendered = false; + + foreach (var cameraPose in prediction.CameraPoses) + { + // This represents the device-based resources for a HolographicCamera. + CameraResources cameraResources = cameraResourceDictionary[cameraPose.HolographicCamera.Id]; + + // Get the device context. + var context = deviceResources.D3DDeviceContext; + var renderTargetView = cameraResources.BackBufferRenderTargetView; + var depthStencilView = cameraResources.DepthStencilView; + + // Set render targets to the current holographic camera. + context.OutputMerger.SetRenderTargets(depthStencilView, renderTargetView); + + // Clear the back buffer and depth stencil view. + SharpDX.Mathematics.Interop.RawColor4 transparent = new SharpDX.Mathematics.Interop.RawColor4(0.0f, 0.0f, 0.0f, 0.0f); + context.ClearRenderTargetView(renderTargetView, transparent); + context.ClearDepthStencilView( + depthStencilView, + SharpDX.Direct3D11.DepthStencilClearFlags.Depth | SharpDX.Direct3D11.DepthStencilClearFlags.Stencil, + 1.0f, + 0); + + // + // TODO: Replace the sample content with your own content. + // + // Notes regarding holographic content: + // * For drawing, remember that you have the potential to fill twice as many pixels + // in a stereoscopic render target as compared to a non-stereoscopic render target + // of the same resolution. Avoid unnecessary or repeated writes to the same pixel, + // and only draw holograms that the user can see. + // * To help occlude hologram geometry, you can create a depth map using geometry + // data obtained via the surface mapping APIs. You can use this depth map to avoid + // rendering holograms that are intended to be hidden behind tables, walls, + // monitors, and so on. + // * Black pixels will appear transparent to the user wearing the device, but you + // should still use alpha blending to draw semitransparent holograms. You should + // also clear the screen to Transparent as shown above. + // + + + // The view and projection matrices for each holographic camera will change + // every frame. This function refreshes the data in the constant buffer for + // the holographic camera indicated by cameraPose. + cameraResources.UpdateViewProjectionBuffer(deviceResources, cameraPose, attachreferenceFrame.GetStationaryCoordinateSystemAtTimestamp(prediction.Timestamp)/*referenceFrame.CoordinateSystem*/); + + // Attach the view/projection constant buffer for this camera to the graphics pipeline. + bool cameraActive = cameraResources.AttachViewProjectionBuffer(deviceResources); + +#if DRAW_SAMPLE_CONTENT + // Only render world-locked content when positional tracking is active. + if (cameraActive) + { + // Draw the sample hologram. + videoRenderer.Render(); + } +#endif + atLeastOneCameraRendered = true; + } + + return atLeastOneCameraRendered; + }); + } + + public void SaveAppState() + { + // + // TODO: Insert code here to save your app state. + // This method is called when the app is about to suspend. + // + // For example, store information in the SpatialAnchorStore. + // + } + + public void LoadAppState() + { + // + // TODO: Insert code here to load your app state. + // This method is called when the app resumes. + // + // For example, load information from the SpatialAnchorStore. + // + } + + + /// + /// Notifies renderers that device resources need to be released. + /// + public void OnDeviceLost(Object sender, EventArgs e) + { + +#if DRAW_SAMPLE_CONTENT + videoRenderer.ReleaseDeviceDependentResources(); +#endif + + } + + /// + /// Notifies renderers that device resources may now be recreated. + /// + public void OnDeviceRestored(Object sender, EventArgs e) + { +#if DRAW_SAMPLE_CONTENT + videoRenderer.CreateDeviceDependentResourcesAsync(); +#endif + } + + void OnLocatabilityChanged(SpatialLocator sender, Object args) + { + switch (sender.Locatability) + { + case SpatialLocatability.Unavailable: + // Holograms cannot be rendered. + { + String message = "Warning! Positional tracking is " + sender.Locatability + "."; + Debug.WriteLine(message); + } + break; + + // In the following three cases, it is still possible to place holograms using a + // SpatialLocatorAttachedFrameOfReference. + case SpatialLocatability.PositionalTrackingActivating: + // The system is preparing to use positional tracking. + + case SpatialLocatability.OrientationOnly: + // Positional tracking has not been activated. + + case SpatialLocatability.PositionalTrackingInhibited: + // Positional tracking is temporarily inhibited. User action may be required + // in order to restore positional tracking. + break; + + case SpatialLocatability.PositionalTrackingActive: + // Positional tracking is active. World-locked content can be rendered. + break; + } + } + + public void OnCameraAdded( + HolographicSpace sender, + HolographicSpaceCameraAddedEventArgs args + ) + { + Deferral deferral = args.GetDeferral(); + HolographicCamera holographicCamera = args.Camera; + + Task task1 = new Task(() => + { + // + // TODO: Allocate resources for the new camera and load any content specific to + // that camera. Note that the render target size (in pixels) is a property + // of the HolographicCamera object, and can be used to create off-screen + // render targets that match the resolution of the HolographicCamera. + // + + // Create device-based resources for the holographic camera and add it to the list of + // cameras used for updates and rendering. Notes: + // * Since this function may be called at any time, the AddHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // adding the new camera. At 60 frames per second this wait should not take long. + // * A subsequent Update will take the back buffer from the RenderingParameters of this + // camera's CameraPose and use it to create the ID3D11RenderTargetView for this camera. + // Content can then be rendered for the HolographicCamera. + deviceResources.AddHolographicCamera(holographicCamera); + + // Holographic frame predictions will not include any information about this camera until + // the deferral is completed. + deferral.Complete(); + }); + task1.Start(); + } + + public void OnCameraRemoved( + HolographicSpace sender, + HolographicSpaceCameraRemovedEventArgs args + ) + { + Task task2 = new Task(() => + { + // + // TODO: Asynchronously unload or deactivate content resources (not back buffer + // resources) that are specific only to the camera that was removed. + // + }); + task2.Start(); + + // Before letting this callback return, ensure that all references to the back buffer + // are released. + // Since this function may be called at any time, the RemoveHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // deallocating resources for this camera. At 60 frames per second this wait should + // not take long. + deviceResources.RemoveHolographicCamera(args.Camera); + } + public void CreateVideoShaders() + { + videoRenderer.CreateDeviceDependentResourcesAsync(); + } + } +} diff --git a/Samples/360VideoPlayback/cs/ms.fxcompile.targets b/Samples/360VideoPlayback/cs/ms.fxcompile.targets new file mode 100644 index 0000000000..1b2bc1c8b1 --- /dev/null +++ b/Samples/360VideoPlayback/cs/ms.fxcompile.targets @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(PrepareResourcesDependsOn); + FxCompile; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_FxCompile Include="@(_EffectShaderWithTargetPath)"> + Effect + 5_0 + + <_FxCompile Include="@(_VertexShaderWithTargetPath)"> + Vertex + 5_0 + + <_FxCompile Include="@(_PixelShaderWithTargetPath)"> + Pixel + 5_0 + + <_FxCompile Include="@(_GeometryShaderWithTargetPath)"> + Geometry + 5_0 + + <_FxCompile Include="@(_HullShaderWithTargetPath)"> + Hull + 5_0 + + <_FxCompile Include="@(_DomainShaderWithTargetPath)"> + Domain + 5_0 + + <_FxCompile Include="@(_ComputeShaderWithTargetPath)"> + Compute + 5_0 + + <_FxCompile Include="@(_TextureShaderWithTargetPath)"> + Texture + 5_0 + + + + + <_FxCompile> + true + $([System.IO.Path]::GetDirectoryName(%(_FxCompile.TargetPath))) + $(IntermediateOutputPath)$([System.IO.Path]::ChangeExtension(%(_FxCompile.TargetPath), '.cso')) + main + true + $(ShaderModel) + + + + + + %(_FxCompile.TargetDirectory)\ + + + + + $(MSBuildProgramFiles32)\Windows Kits\10\bin\x86 + + + + + + + + $(FxCompileDependsOn);AssignItemsFxCompile; + $(AssignTargetPathsDependsOn);AssignItemsFxCompile + + + + + + + + + + + + + + + diff --git a/Samples/360VideoPlayback/cs/project.json b/Samples/360VideoPlayback/cs/project.json new file mode 100644 index 0000000000..8eedafbdfa --- /dev/null +++ b/Samples/360VideoPlayback/cs/project.json @@ -0,0 +1,18 @@ +{ + "dependencies": { + "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", + "SharpDX": "3.0.2", + "SharpDX.Direct2D1": "3.0.2", + "SharpDX.Direct3D11": "3.0.2", + "SharpDX.Mathematics": "3.0.2" + }, + "frameworks": { + "uap10.0": {} + }, + "runtimes": { + "win10-x64": {}, + "win10-x64-aot": {}, + "win10-x86": {}, + "win10-x86-aot": {} + } +} \ No newline at end of file diff --git a/Samples/360VideoPlayback/shared/App.xaml b/Samples/360VideoPlayback/shared/App.xaml new file mode 100644 index 0000000000..8bc1764ec8 --- /dev/null +++ b/Samples/360VideoPlayback/shared/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/Samples/360VideoPlayback/shared/MainPage.xaml b/Samples/360VideoPlayback/shared/MainPage.xaml new file mode 100644 index 0000000000..ef3bccbd1c --- /dev/null +++ b/Samples/360VideoPlayback/shared/MainPage.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/Samples/360VideoPlayback/shared/PlaybackPage.xaml b/Samples/360VideoPlayback/shared/PlaybackPage.xaml new file mode 100644 index 0000000000..1f44c18b08 --- /dev/null +++ b/Samples/360VideoPlayback/shared/PlaybackPage.xaml @@ -0,0 +1,15 @@ + + + + + + diff --git a/Samples/360VideoPlayback/shared/VideoGallery.xaml b/Samples/360VideoPlayback/shared/VideoGallery.xaml new file mode 100644 index 0000000000..bee1a8939b --- /dev/null +++ b/Samples/360VideoPlayback/shared/VideoGallery.xaml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/3DPrinting/cs/3DPrinting.sln b/Samples/3DPrinting/cs/3DPrinting.sln index dfafb49601..94d1f2a708 100644 --- a/Samples/3DPrinting/cs/3DPrinting.sln +++ b/Samples/3DPrinting/cs/3DPrinting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3DPrinting", "3DPrinting.csproj", "{46EF1408-F615-57D4-B4E4-A18A4902E4FC}" EndProject diff --git a/Samples/Accelerometer/cpp/Accelerometer.sln b/Samples/Accelerometer/cpp/Accelerometer.sln index d3bbd271a7..cd88001269 100644 --- a/Samples/Accelerometer/cpp/Accelerometer.sln +++ b/Samples/Accelerometer/cpp/Accelerometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Accelerometer", "Accelerometer.vcxproj", "{0B2CC0F5-B383-5005-A85B-D0021AA6A6DC}" EndProject diff --git a/Samples/Accelerometer/cs/Accelerometer.sln b/Samples/Accelerometer/cs/Accelerometer.sln index dfaeb6e726..b858a97ac1 100644 --- a/Samples/Accelerometer/cs/Accelerometer.sln +++ b/Samples/Accelerometer/cs/Accelerometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22820.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accelerometer", "Accelerometer.csproj", "{8ECB1F8D-8B5C-541C-8DF6-3F9EC6085379}" EndProject diff --git a/Samples/Accelerometer/js/Accelerometer.sln b/Samples/Accelerometer/js/Accelerometer.sln index bc715c7475..f28eb9882b 100644 --- a/Samples/Accelerometer/js/Accelerometer.sln +++ b/Samples/Accelerometer/js/Accelerometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Accelerometer", "Accelerometer.jsproj", "{51751A3D-1A3A-5A43-BCB9-FF9D3BDD3F7D}" EndProject diff --git a/Samples/Accelerometer/vb/Accelerometer.sln b/Samples/Accelerometer/vb/Accelerometer.sln index 7ed25f1ec4..be6054865e 100644 --- a/Samples/Accelerometer/vb/Accelerometer.sln +++ b/Samples/Accelerometer/vb/Accelerometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22820.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Accelerometer", "Accelerometer.vbproj", "{191D8346-2FBB-5AB3-8F4D-9D948657D1CE}" EndProject diff --git a/Samples/ActivitySensor/cpp/ActivitySensor.sln b/Samples/ActivitySensor/cpp/ActivitySensor.sln index ff85064f29..6e6266ccd4 100644 --- a/Samples/ActivitySensor/cpp/ActivitySensor.sln +++ b/Samples/ActivitySensor/cpp/ActivitySensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ActivitySensor", "ActivitySensor.vcxproj", "{F101CE4D-1834-5D51-99AE-9DE715E49FB2}" EndProject diff --git a/Samples/ActivitySensor/cs/ActivitySensor.sln b/Samples/ActivitySensor/cs/ActivitySensor.sln index 0182f0a3ca..cf8076e5e4 100644 --- a/Samples/ActivitySensor/cs/ActivitySensor.sln +++ b/Samples/ActivitySensor/cs/ActivitySensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActivitySensor", "ActivitySensor.csproj", "{4E03DFF6-DA5F-5DB1-B134-59B251464C32}" EndProject diff --git a/Samples/ActivitySensor/js/ActivitySensor.sln b/Samples/ActivitySensor/js/ActivitySensor.sln index afe54613f3..29dcb34885 100644 --- a/Samples/ActivitySensor/js/ActivitySensor.sln +++ b/Samples/ActivitySensor/js/ActivitySensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "ActivitySensor", "ActivitySensor.jsproj", "{BEBFC2A7-1CC2-571C-A562-FCB5B7A2D0E1}" EndProject diff --git a/Samples/ActivitySensor/vb/ActivitySensor.sln b/Samples/ActivitySensor/vb/ActivitySensor.sln index c0a0fd2800..2743d4d411 100644 --- a/Samples/ActivitySensor/vb/ActivitySensor.sln +++ b/Samples/ActivitySensor/vb/ActivitySensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ActivitySensor", "ActivitySensor.vbproj", "{A19F2DFD-754C-5CF7-AA76-5311E0E19742}" EndProject diff --git a/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.sln b/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.sln index b23cb87602..81c5520c2c 100644 --- a/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.sln +++ b/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdaptiveStreaming", "AdaptiveStreaming.csproj", "{AC0C3055-DBD6-5101-A538-0D42DF50F376}" EndProject diff --git a/Samples/AdvancedCasting/cs/AdvancedCasting.sln b/Samples/AdvancedCasting/cs/AdvancedCasting.sln index f0554ad9e6..b761b24871 100644 --- a/Samples/AdvancedCasting/cs/AdvancedCasting.sln +++ b/Samples/AdvancedCasting/cs/AdvancedCasting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedCasting", "AdvancedCasting.csproj", "{EBA0BDC8-F665-52CD-9C92-CFB6C1668433}" EndProject diff --git a/Samples/AdvancedCasting/vb/AdvancedCasting.sln b/Samples/AdvancedCasting/vb/AdvancedCasting.sln index 1018e8187f..38750ea1d1 100644 --- a/Samples/AdvancedCasting/vb/AdvancedCasting.sln +++ b/Samples/AdvancedCasting/vb/AdvancedCasting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AdvancedCasting", "AdvancedCasting.vbproj", "{10422D7F-BAB9-5607-8F82-27CDA41DD0CF}" EndProject diff --git a/Samples/Advertising/cpp/Advertising.sln b/Samples/Advertising/cpp/Advertising.sln index aea6f42f69..17bdc973d7 100644 --- a/Samples/Advertising/cpp/Advertising.sln +++ b/Samples/Advertising/cpp/Advertising.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Advertising", "Advertising.vcxproj", "{F2CC05F2-B8CA-52CC-B875-C6978FA68852}" EndProject diff --git a/Samples/Advertising/cs/Advertising.sln b/Samples/Advertising/cs/Advertising.sln index af2a6bbde0..222c5a47e4 100644 --- a/Samples/Advertising/cs/Advertising.sln +++ b/Samples/Advertising/cs/Advertising.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Advertising", "Advertising.csproj", "{C2CA4DF6-9483-548C-BD20-1493C6B0B247}" EndProject diff --git a/Samples/Advertising/js/Advertising.sln b/Samples/Advertising/js/Advertising.sln index 937c6ed096..d4c3d98ce9 100644 --- a/Samples/Advertising/js/Advertising.sln +++ b/Samples/Advertising/js/Advertising.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Advertising", "Advertising.jsproj", "{796AA01F-A852-574A-A3A6-43BD8941582D}" EndProject diff --git a/Samples/AllJoyn/ConsumerExperiences/cs/AllJoynConsumerExperiences.sln b/Samples/AllJoyn/ConsumerExperiences/cs/AllJoynConsumerExperiences.sln index 4e9f49fa5f..5774ee544c 100644 --- a/Samples/AllJoyn/ConsumerExperiences/cs/AllJoynConsumerExperiences.sln +++ b/Samples/AllJoyn/ConsumerExperiences/cs/AllJoynConsumerExperiences.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AllJoynConsumerExperiences", "AllJoynConsumerExperiences.csproj", "{B14CC9CB-BA89-5D3D-AB03-A9B818C6036A}" EndProject diff --git a/Samples/AllJoyn/ConsumerExperiences/js/AllJoynConsumerExperiences.sln b/Samples/AllJoyn/ConsumerExperiences/js/AllJoynConsumerExperiences.sln index a520715c9d..893ef5d2a3 100644 --- a/Samples/AllJoyn/ConsumerExperiences/js/AllJoynConsumerExperiences.sln +++ b/Samples/AllJoyn/ConsumerExperiences/js/AllJoynConsumerExperiences.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AllJoynConsumerExperiences", "AllJoynConsumerExperiences.jsproj", "{CACAE149-136D-5C4A-983B-D63F7181B57F}" EndProject diff --git a/Samples/AllJoyn/ProducerExperiences/cs/AllJoynProducerExperiences.sln b/Samples/AllJoyn/ProducerExperiences/cs/AllJoynProducerExperiences.sln index c4f48b7fcc..b8ff4a7873 100644 --- a/Samples/AllJoyn/ProducerExperiences/cs/AllJoynProducerExperiences.sln +++ b/Samples/AllJoyn/ProducerExperiences/cs/AllJoynProducerExperiences.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AllJoynProducerExperiences", "AllJoynProducerExperiences.csproj", "{2140E48F-111B-5B85-A76B-42073A20F370}" EndProject diff --git a/Samples/AllJoyn/ProducerExperiences/js/AllJoynProducerExperiences.sln b/Samples/AllJoyn/ProducerExperiences/js/AllJoynProducerExperiences.sln index d13a86066f..6ccea6627e 100644 --- a/Samples/AllJoyn/ProducerExperiences/js/AllJoynProducerExperiences.sln +++ b/Samples/AllJoyn/ProducerExperiences/js/AllJoynProducerExperiences.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AllJoynProducerExperiences", "AllJoynProducerExperiences.jsproj", "{B78B2582-8FE6-5AEB-B831-45C6E5B06CDA}" EndProject diff --git a/Samples/Altimeter/cpp/Altimeter.sln b/Samples/Altimeter/cpp/Altimeter.sln index b3cc76a6cd..3abaf42816 100644 --- a/Samples/Altimeter/cpp/Altimeter.sln +++ b/Samples/Altimeter/cpp/Altimeter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Altimeter", "Altimeter.vcxproj", "{506AC0D6-5149-5A38-A840-D6DA58DC3B22}" EndProject diff --git a/Samples/Altimeter/cs/Altimeter.sln b/Samples/Altimeter/cs/Altimeter.sln index aa6ed656d7..f1cf2a8439 100644 --- a/Samples/Altimeter/cs/Altimeter.sln +++ b/Samples/Altimeter/cs/Altimeter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altimeter", "Altimeter.csproj", "{C858FC3C-6478-5405-8494-9EEBBA4AA9C9}" EndProject diff --git a/Samples/Altimeter/js/Altimeter.sln b/Samples/Altimeter/js/Altimeter.sln index 0af88db6d6..7447407de2 100644 --- a/Samples/Altimeter/js/Altimeter.sln +++ b/Samples/Altimeter/js/Altimeter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Altimeter", "Altimeter.jsproj", "{3ECE7ED7-B5D6-5D89-B523-EE91F94894C5}" EndProject diff --git a/Samples/Altimeter/vb/Altimeter.sln b/Samples/Altimeter/vb/Altimeter.sln index 313bb01015..42cef74b67 100644 --- a/Samples/Altimeter/vb/Altimeter.sln +++ b/Samples/Altimeter/vb/Altimeter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Altimeter", "Altimeter.vbproj", "{1BF860DF-80D2-5016-942F-D359842550E2}" EndProject diff --git a/Samples/AnimationLibrary/js/AnimationLibrary.sln b/Samples/AnimationLibrary/js/AnimationLibrary.sln index 99196f93bc..22607e12ad 100644 --- a/Samples/AnimationLibrary/js/AnimationLibrary.sln +++ b/Samples/AnimationLibrary/js/AnimationLibrary.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AnimationLibrary", "AnimationLibrary.jsproj", "{DCECAF61-53C3-50E8-897C-FF7A6086FDC1}" EndProject diff --git a/Samples/AnimationMetrics/cpp/AnimationMetrics.sln b/Samples/AnimationMetrics/cpp/AnimationMetrics.sln index dd6a8a43eb..4685412d40 100644 --- a/Samples/AnimationMetrics/cpp/AnimationMetrics.sln +++ b/Samples/AnimationMetrics/cpp/AnimationMetrics.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AnimationMetrics", "AnimationMetrics.vcxproj", "{5DF675EE-50A1-5C3B-B193-0DF9CB1B1B8D}" EndProject diff --git a/Samples/AnimationMetrics/cs/AnimationMetrics.sln b/Samples/AnimationMetrics/cs/AnimationMetrics.sln index e94cff0a0d..54f802eaa1 100644 --- a/Samples/AnimationMetrics/cs/AnimationMetrics.sln +++ b/Samples/AnimationMetrics/cs/AnimationMetrics.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnimationMetrics", "AnimationMetrics.csproj", "{E18B5F10-4167-5FF2-831D-B2AA62DACF22}" EndProject diff --git a/Samples/AnimationMetrics/js/AnimationMetrics.sln b/Samples/AnimationMetrics/js/AnimationMetrics.sln index 1f31553314..446a8e33fd 100644 --- a/Samples/AnimationMetrics/js/AnimationMetrics.sln +++ b/Samples/AnimationMetrics/js/AnimationMetrics.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AnimationMetrics", "AnimationMetrics.jsproj", "{C2DA5972-5BEF-5B9E-9988-049EE8BD390E}" EndProject diff --git a/Samples/AnimationMetrics/vb/AnimationMetrics.sln b/Samples/AnimationMetrics/vb/AnimationMetrics.sln index e3676c35c0..2cca90bb9c 100644 --- a/Samples/AnimationMetrics/vb/AnimationMetrics.sln +++ b/Samples/AnimationMetrics/vb/AnimationMetrics.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AnimationMetrics", "AnimationMetrics.vbproj", "{FEE8B568-6D43-59ED-965E-769514E5FED9}" EndProject diff --git a/Samples/AppServices/cs/AppServices.sln b/Samples/AppServices/cs/AppServices.sln index 0b356bd9f1..5aad3409a1 100644 --- a/Samples/AppServices/cs/AppServices.sln +++ b/Samples/AppServices/cs/AppServices.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppServicesClient", "AppServicesClient\AppServicesClient.csproj", "{1A6B6734-6036-5DDD-97B7-704E5F598901}" EndProject diff --git a/Samples/AppServices/cs/RandomNumberService/RandomNumberGeneratorTask.cs b/Samples/AppServices/cs/RandomNumberService/RandomNumberGeneratorTask.cs index b40f577e3e..ea75985ec3 100644 --- a/Samples/AppServices/cs/RandomNumberService/RandomNumberGeneratorTask.cs +++ b/Samples/AppServices/cs/RandomNumberService/RandomNumberGeneratorTask.cs @@ -36,6 +36,12 @@ private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancel serviceDeferral.Complete(); serviceDeferral = null; } + + if (connection != null) + { + connection.Dispose(); + connection = null; + } } async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) diff --git a/Samples/AppServices/vb/AppServices.sln b/Samples/AppServices/vb/AppServices.sln index 8cd046ed27..5d42a312e3 100644 --- a/Samples/AppServices/vb/AppServices.sln +++ b/Samples/AppServices/vb/AppServices.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AppServicesClient", "AppServicesClient\AppServicesClient.vbproj", "{AA7CB8AF-1AF8-5D3E-AF73-1E3D3ABECEFB}" EndProject diff --git a/Samples/AppServices/vb/RandomNumberService/RandomNumberGeneratorTask.vb b/Samples/AppServices/vb/RandomNumberService/RandomNumberGeneratorTask.vb index 62f34362a5..68eb340236 100644 --- a/Samples/AppServices/vb/RandomNumberService/RandomNumberGeneratorTask.vb +++ b/Samples/AppServices/vb/RandomNumberService/RandomNumberGeneratorTask.vb @@ -28,6 +28,10 @@ Namespace Global.RandomNumberService serviceDeferral.Complete() serviceDeferral = Nothing End If + If connection IsNot Nothing Then + connection.Dispose() + connection = Nothing + End If End Sub Async Sub OnRequestReceived(sender As AppServiceConnection, args As AppServiceRequestReceivedEventArgs) diff --git a/Samples/ApplicationData/cs/ApplicationData.sln b/Samples/ApplicationData/cs/ApplicationData.sln index da52722c71..6ed128fc19 100644 --- a/Samples/ApplicationData/cs/ApplicationData.sln +++ b/Samples/ApplicationData/cs/ApplicationData.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationData", "ApplicationData.csproj", "{0457EC4A-5221-5EB8-BC0A-D5AE2DAEA054}" EndProject diff --git a/Samples/ApplicationData/vb/ApplicationData.sln b/Samples/ApplicationData/vb/ApplicationData.sln index 296f2a1cc9..72dd991e7b 100644 --- a/Samples/ApplicationData/vb/ApplicationData.sln +++ b/Samples/ApplicationData/vb/ApplicationData.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ApplicationData", "ApplicationData.vbproj", "{2CA6F7E7-A28D-5462-B722-86EC657EB911}" EndProject diff --git a/Samples/ApplicationResources/cpp/ApplicationResources.sln b/Samples/ApplicationResources/cpp/ApplicationResources.sln index e0d7ec6341..845ad4f2ab 100644 --- a/Samples/ApplicationResources/cpp/ApplicationResources.sln +++ b/Samples/ApplicationResources/cpp/ApplicationResources.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ApplicationResources", "ApplicationResources.vcxproj", "{C156003D-844F-5C69-8D99-C6D5712DC0E0}" EndProject diff --git a/Samples/ApplicationResources/cs/ApplicationResources.sln b/Samples/ApplicationResources/cs/ApplicationResources.sln index 5fe680c38b..136f359429 100644 --- a/Samples/ApplicationResources/cs/ApplicationResources.sln +++ b/Samples/ApplicationResources/cs/ApplicationResources.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationResources", "ApplicationResources.csproj", "{EC4D069F-F68B-57BF-B3F5-B51520FF4415}" EndProject diff --git a/Samples/ApplicationResources/js/ApplicationResources.sln b/Samples/ApplicationResources/js/ApplicationResources.sln index 7bf10debe4..63b7e66d29 100644 --- a/Samples/ApplicationResources/js/ApplicationResources.sln +++ b/Samples/ApplicationResources/js/ApplicationResources.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "ApplicationResources", "ApplicationResources.jsproj", "{854C4830-4CBC-5862-A20A-7AD8CBF8F348}" EndProject diff --git a/Samples/ApplicationResources/vb/ApplicationResources.sln b/Samples/ApplicationResources/vb/ApplicationResources.sln index f992324324..3e21d1a16c 100644 --- a/Samples/ApplicationResources/vb/ApplicationResources.sln +++ b/Samples/ApplicationResources/vb/ApplicationResources.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ApplicationResources", "ApplicationResources.vbproj", "{90B0BC8D-D777-58BF-A7AF-1CE991C6C38C}" EndProject diff --git a/Samples/Appointments/cs/Appointments.sln b/Samples/Appointments/cs/Appointments.sln index 0f750a0eee..9de26064d6 100644 --- a/Samples/Appointments/cs/Appointments.sln +++ b/Samples/Appointments/cs/Appointments.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Appointments", "Appointments.csproj", "{E1B9AAF2-2E6F-59A7-8291-CF02D513357C}" EndProject diff --git a/Samples/Appointments/vb/Appointments.sln b/Samples/Appointments/vb/Appointments.sln index 05220dd96b..6bbfa85d15 100644 --- a/Samples/Appointments/vb/Appointments.sln +++ b/Samples/Appointments/vb/Appointments.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Appointments", "Appointments.vbproj", "{A32DB859-C4E2-57F2-B7B0-10B0C2EC4AA7}" EndProject diff --git a/Samples/AssociationLaunching/cs/AssociationLaunching.sln b/Samples/AssociationLaunching/cs/AssociationLaunching.sln index ed50447c0f..b9cc8319dd 100644 --- a/Samples/AssociationLaunching/cs/AssociationLaunching.sln +++ b/Samples/AssociationLaunching/cs/AssociationLaunching.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssociationLaunching", "AssociationLaunching.csproj", "{38658848-7E28-50B3-AD89-027E558F5E80}" EndProject diff --git a/Samples/AssociationLaunching/vb/AssociationLaunching.sln b/Samples/AssociationLaunching/vb/AssociationLaunching.sln index d4a16848c3..cfb7d8f12f 100644 --- a/Samples/AssociationLaunching/vb/AssociationLaunching.sln +++ b/Samples/AssociationLaunching/vb/AssociationLaunching.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AssociationLaunching", "AssociationLaunching.vbproj", "{AD921393-B8FC-50F3-8FE8-48873A043A91}" EndProject diff --git a/Samples/AudioCategory/cs/AudioCategory/AudioCategory.sln b/Samples/AudioCategory/cs/AudioCategory/AudioCategory.sln index 2839cbfc54..bcddc99769 100644 --- a/Samples/AudioCategory/cs/AudioCategory/AudioCategory.sln +++ b/Samples/AudioCategory/cs/AudioCategory/AudioCategory.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioCategory", "AudioCategory.csproj", "{7E155C04-AF4D-5F4C-B44A-D81DEE4FD8B5}" EndProject diff --git a/Samples/AudioCategory/cs/AudioCategoryCompanion/AudioCategoryCompanion.sln b/Samples/AudioCategory/cs/AudioCategoryCompanion/AudioCategoryCompanion.sln index b0b1380b51..16529fe936 100644 --- a/Samples/AudioCategory/cs/AudioCategoryCompanion/AudioCategoryCompanion.sln +++ b/Samples/AudioCategory/cs/AudioCategoryCompanion/AudioCategoryCompanion.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioCategoryCompanion", "AudioCategoryCompanion.csproj", "{EEF4E054-5F0B-5E55-B1F9-C9E50608E753}" EndProject diff --git a/Samples/AudioCategory/js/AudioCategory/AudioCategory.sln b/Samples/AudioCategory/js/AudioCategory/AudioCategory.sln index 7fda0cf9bb..c6ad87af1e 100644 --- a/Samples/AudioCategory/js/AudioCategory/AudioCategory.sln +++ b/Samples/AudioCategory/js/AudioCategory/AudioCategory.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AudioCategory", "AudioCategory.jsproj", "{FFB9405E-CB55-51FF-BF04-BF6B33811B95}" EndProject diff --git a/Samples/AudioCategory/js/AudioCategoryCompanion/AudioCategoryCompanion.sln b/Samples/AudioCategory/js/AudioCategoryCompanion/AudioCategoryCompanion.sln index bbfecfe172..2a7bf583f9 100644 --- a/Samples/AudioCategory/js/AudioCategoryCompanion/AudioCategoryCompanion.sln +++ b/Samples/AudioCategory/js/AudioCategoryCompanion/AudioCategoryCompanion.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AudioCategoryCompanion", "AudioCategoryCompanion.jsproj", "{2A8DC2F8-67A3-5C1E-B875-C9771AD3C404}" EndProject diff --git a/Samples/AudioCategory/vb/AudioCategory/AudioCategory.sln b/Samples/AudioCategory/vb/AudioCategory/AudioCategory.sln index eaffbd6766..5807b25cb0 100644 --- a/Samples/AudioCategory/vb/AudioCategory/AudioCategory.sln +++ b/Samples/AudioCategory/vb/AudioCategory/AudioCategory.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AudioCategory", "AudioCategory.vbproj", "{FBFF029F-AEEB-5B86-878C-EE85162A5B5A}" EndProject diff --git a/Samples/AudioCategory/vb/AudioCategoryCompanion/AudioCategoryCompanion.sln b/Samples/AudioCategory/vb/AudioCategoryCompanion/AudioCategoryCompanion.sln index 5d5594fefc..b994f21e25 100644 --- a/Samples/AudioCategory/vb/AudioCategoryCompanion/AudioCategoryCompanion.sln +++ b/Samples/AudioCategory/vb/AudioCategoryCompanion/AudioCategoryCompanion.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AudioCategoryCompanion", "AudioCategoryCompanion.vbproj", "{875FB74A-5754-5FC0-A996-E2F2146E9C4A}" EndProject diff --git a/Samples/AudioCreation/cs/AudioCreation.sln b/Samples/AudioCreation/cs/AudioCreation.sln index ebba9efaf5..0d467431d4 100644 --- a/Samples/AudioCreation/cs/AudioCreation.sln +++ b/Samples/AudioCreation/cs/AudioCreation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22822.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioCreation", "AudioCreation\AudioCreation.csproj", "{D52CB6A5-8B63-50DE-AF50-1B39D4DB5EB2}" EndProject diff --git a/Samples/BackButton/cpp/SystemBack.sln b/Samples/BackButton/cpp/SystemBack.sln index 105fa51c76..40732ef9b0 100644 --- a/Samples/BackButton/cpp/SystemBack.sln +++ b/Samples/BackButton/cpp/SystemBack.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SystemBack", "SystemBack.vcxproj", "{41E184D6-562C-5C4B-AB61-17F3DD5A9C18}" EndProject diff --git a/Samples/BackButton/cs/SystemBack.sln b/Samples/BackButton/cs/SystemBack.sln index d60adb3e95..0829bf22fe 100644 --- a/Samples/BackButton/cs/SystemBack.sln +++ b/Samples/BackButton/cs/SystemBack.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23023.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemBack", "SystemBack.csproj", "{F744E470-561E-5A58-8ED3-224C5570B3E1}" EndProject diff --git a/Samples/BackButton/vb/SystemBack.sln b/Samples/BackButton/vb/SystemBack.sln index 968b5371d6..9dc214b53f 100644 --- a/Samples/BackButton/vb/SystemBack.sln +++ b/Samples/BackButton/vb/SystemBack.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23023.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SystemBack", "SystemBack.vbproj", "{39F19D13-ED35-5678-862D-C098976781C2}" EndProject diff --git a/Samples/BackgroundActivation/cpp/BackgroundActivation.sln b/Samples/BackgroundActivation/cpp/BackgroundActivation.sln index 20bce2ff1b..1e169ea17f 100644 --- a/Samples/BackgroundActivation/cpp/BackgroundActivation.sln +++ b/Samples/BackgroundActivation/cpp/BackgroundActivation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackgroundActivation", "BackgroundActivation.vcxproj", "{6FE60016-AF86-5119-9F73-87A8627AA0C3}" EndProject diff --git a/Samples/BackgroundActivation/cs/BackgroundActivation.sln b/Samples/BackgroundActivation/cs/BackgroundActivation.sln index 3c58b50d51..bed3bce944 100644 --- a/Samples/BackgroundActivation/cs/BackgroundActivation.sln +++ b/Samples/BackgroundActivation/cs/BackgroundActivation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundActivation", "BackgroundActivation.csproj", "{C65E0AF4-32AA-5865-BA26-38F00C594790}" EndProject diff --git a/Samples/BackgroundActivation/vb/BackgroundActivation.sln b/Samples/BackgroundActivation/vb/BackgroundActivation.sln index ae3a130f1c..60475a96cc 100644 --- a/Samples/BackgroundActivation/vb/BackgroundActivation.sln +++ b/Samples/BackgroundActivation/vb/BackgroundActivation.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BackgroundActivation", "BackgroundActivation.vbproj", "{19B318B2-B22C-528B-B258-409C888F86C8}" EndProject diff --git a/Samples/BackgroundMediaPlayback/cs/BackgroundMediaPlayback.sln b/Samples/BackgroundMediaPlayback/cs/BackgroundMediaPlayback.sln index 406149c695..6593e56ee8 100644 --- a/Samples/BackgroundMediaPlayback/cs/BackgroundMediaPlayback.sln +++ b/Samples/BackgroundMediaPlayback/cs/BackgroundMediaPlayback.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundMediaPlayback", "BackgroundMediaPlayback.csproj", "{42B98426-8502-5F5D-B108-75940BA71909}" EndProject diff --git a/Samples/BackgroundMediaPlayback/js/BackgroundMediaPlayback.sln b/Samples/BackgroundMediaPlayback/js/BackgroundMediaPlayback.sln index a2b6eebaec..12b1e671b9 100644 --- a/Samples/BackgroundMediaPlayback/js/BackgroundMediaPlayback.sln +++ b/Samples/BackgroundMediaPlayback/js/BackgroundMediaPlayback.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "BackgroundMediaPlayback", "BackgroundMediaPlayback.jsproj", "{699ACD45-16AD-5E54-BA6F-53079F3828D2}" EndProject diff --git a/Samples/BackgroundSensors/cpp/BackgroundSensors.sln b/Samples/BackgroundSensors/cpp/BackgroundSensors.sln index b6335221d0..ff086412dd 100644 --- a/Samples/BackgroundSensors/cpp/BackgroundSensors.sln +++ b/Samples/BackgroundSensors/cpp/BackgroundSensors.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackgroundSensors", "BackgroundSensors.vcxproj", "{901649E8-0E02-5A6F-8198-E8053FBCDD25}" EndProject diff --git a/Samples/BackgroundSensors/cs/BackgroundSensors.sln b/Samples/BackgroundSensors/cs/BackgroundSensors.sln index 8afba4bb5e..dc00297e9b 100644 --- a/Samples/BackgroundSensors/cs/BackgroundSensors.sln +++ b/Samples/BackgroundSensors/cs/BackgroundSensors.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22820.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundSensors", "BackgroundSensors.csproj", "{ADB5EE04-4D4F-5977-AD5F-0988C8633D37}" EndProject diff --git a/Samples/BackgroundSensors/vb/BackgroundSensors.sln b/Samples/BackgroundSensors/vb/BackgroundSensors.sln index e77409eb44..e059dca2e6 100644 --- a/Samples/BackgroundSensors/vb/BackgroundSensors.sln +++ b/Samples/BackgroundSensors/vb/BackgroundSensors.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22820.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BackgroundSensors", "BackgroundSensors.vbproj", "{916C3541-4671-5330-B057-1A00B93381C4}" EndProject diff --git a/Samples/BackgroundTask/README.md b/Samples/BackgroundTask/README.md index 5ecb86b0be..dc7dac9d27 100644 --- a/Samples/BackgroundTask/README.md +++ b/Samples/BackgroundTask/README.md @@ -28,6 +28,7 @@ This sample demonstrates the following: - Using a deferral object to include asynchronous code in your background task. - Handling the cancellation of a background task, and ensuring the task is cancelled when required conditions are no longer met. - Initializing background task progress and completion handlers when the app is launched. +- Registering a background task in a Background Task Registration Group. To obtain an evaluation copy of Windows 8.1, go to [Windows 8.1](http://go.microsoft.com/fwlink/p/?linkid=301696). diff --git a/Samples/BackgroundTask/cpp/BackgroundTask.sln b/Samples/BackgroundTask/cpp/BackgroundTask.sln index 98db90d8bf..d6c43302f6 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask.sln +++ b/Samples/BackgroundTask/cpp/BackgroundTask.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackgroundTask", "BackgroundTask\BackgroundTask.vcxproj", "{F285F4B9-B84B-5293-908A-3865213C2849}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj b/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj index f27f0df527..37ed9e8f81 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj +++ b/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj @@ -162,6 +162,9 @@ ..\..\shared\Scenario5_ApplicationTriggerTask.xaml + + ..\..\shared\Scenario6_GroupedTask.xaml + @@ -175,6 +178,7 @@ + Styles\Styles.xaml @@ -215,6 +219,9 @@ ..\..\shared\Scenario5_ApplicationTriggerTask.xaml + + ..\..\shared\Scenario6_GroupedTask.xaml + diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj.filters b/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj.filters index a609b35fdf..fa45996ee7 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj.filters +++ b/Samples/BackgroundTask/cpp/BackgroundTask/BackgroundTask.vcxproj.filters @@ -21,6 +21,8 @@ + + @@ -31,6 +33,8 @@ + + @@ -44,6 +48,8 @@ + + @@ -61,5 +67,11 @@ Assets + + Assets + + + Assets + \ No newline at end of file diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp index df8a0fb668..28bea457ba 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp +++ b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp @@ -30,6 +30,9 @@ String^ BackgroundTaskSample::ApplicationTriggerTaskProgress = ""; bool BackgroundTaskSample::ApplicationTriggerTaskRegistered = false; String^ BackgroundTaskSample::ApplicationTriggerTaskResult = ""; +String^ BackgroundTaskSample::GroupedBackgroundTaskProgress = ""; +bool BackgroundTaskSample::GroupedBackgroundTaskRegistered = false; + Array^ MainPage::scenariosInner = ref new Array { // The format here is the following: @@ -38,7 +41,8 @@ Array^ MainPage::scenariosInner = ref new Array { "Background task with a condition", "SDKTemplate.SampleBackgroundTaskWithCondition" }, { "Servicing complete task", "SDKTemplate.ServicingCompleteTask" }, { "Background task with time trigger", "SDKTemplate.TimeTriggeredTask" }, - { "Background task with application trigger", "SDKTemplate.ApplicationTriggerTask" } + { "Background task with application trigger", "SDKTemplate.ApplicationTriggerTask" }, + { "Grouped background task", "SDKTemplate.GroupedBackgroundTask" }, }; String^ BackgroundTaskSample::GetBackgroundTaskStatus(String^ name) @@ -64,6 +68,10 @@ String^ BackgroundTaskSample::GetBackgroundTaskStatus(String^ name) { registered = BackgroundTaskSample::ApplicationTriggerTaskRegistered; } + else if (name == GroupedBackgroundTaskName) + { + registered = BackgroundTaskSample::GroupedBackgroundTaskRegistered; + } String^ status = registered ? "Registered" : "Unregistered"; @@ -76,7 +84,7 @@ String^ BackgroundTaskSample::GetBackgroundTaskStatus(String^ name) return status; } -BackgroundTaskRegistration^ BackgroundTaskSample::RegisterBackgroundTask(String^ taskEntryPoint, String^ name, IBackgroundTrigger^ trigger, IBackgroundCondition^ condition) +BackgroundTaskRegistration^ BackgroundTaskSample::RegisterBackgroundTask(String^ taskEntryPoint, String^ name, IBackgroundTrigger^ trigger, IBackgroundCondition^ condition, BackgroundTaskRegistrationGroup^ group) { if (TaskRequiresBackgroundAccess(name)) { @@ -100,6 +108,11 @@ BackgroundTaskRegistration^ BackgroundTaskSample::RegisterBackgroundTask(String^ builder->CancelOnConditionLoss = true; } + if (group != nullptr) + { + builder->TaskGroup = group; + } + auto task = builder->Register(); UpdateBackgroundTaskRegistrationStatus(name, true); @@ -115,9 +128,6 @@ BackgroundTaskRegistration^ BackgroundTaskSample::RegisterBackgroundTask(String^ bool BackgroundTaskSample::TaskRequiresBackgroundAccess(String^ name) { -#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP - return true; -#else if ((name == TimeTriggeredTaskName) || (name == ApplicationTriggerTaskName)) { @@ -127,29 +137,53 @@ bool BackgroundTaskSample::TaskRequiresBackgroundAccess(String^ name) { return false; } -#endif } -void BackgroundTaskSample::UnregisterBackgroundTasks(String^ name) +void BackgroundTaskSample::UnregisterBackgroundTasks(String^ name, BackgroundTaskRegistrationGroup^ group) { // - // Loop through all background tasks and unregister any that have a name that matches - // the name passed into this function. + // If the given task group is registered then loop through all background tasks associated with it + // and unregister any with the name passed into this function. // - auto iter = BackgroundTaskRegistration::AllTasks->First(); - auto hascur = iter->HasCurrent; - while (hascur) + if (group != nullptr) { - auto cur = iter->Current->Value; - - if (cur->Name == name) + for (auto pair : group->AllTasks) { - cur->Unregister(true); - UpdateBackgroundTaskRegistrationStatus(name, false); + auto task = pair->Value; + if (task->Name == name) + { + task->Unregister(true); + } } + } + else + { + // + // Loop through all ungrouped background tasks and unregister any with the name passed into this function. + // + for (auto pair : BackgroundTaskRegistration::AllTasks) + { + auto task = pair->Value; + if (task->Name == name) + { + task->Unregister(true); + } + } + } - hascur = iter->MoveNext(); + UpdateBackgroundTaskRegistrationStatus(name, false); +} + +BackgroundTaskRegistrationGroup^ BackgroundTaskSample::GetTaskGroup(String^ id, String^ groupName) +{ + auto group = BackgroundTaskRegistration::GetTaskGroup(id); + + if (group == nullptr) + { + group = ref new BackgroundTaskRegistrationGroup(id, groupName); } + + return group; } void BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(String^ name, bool registered) @@ -174,4 +208,8 @@ void BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(String^ name, { BackgroundTaskSample::ApplicationTriggerTaskRegistered = registered; } + else if (name == GroupedBackgroundTaskName) + { + BackgroundTaskSample::GroupedBackgroundTaskRegistered = registered; + } } diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h index b53e43482a..51bbb4ac2b 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h +++ b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h @@ -23,6 +23,9 @@ using namespace Windows::Storage; #define ServicingCompleteTaskName "ServicingCompleteTask" #define TimeTriggeredTaskName "TimeTriggeredTask" #define ApplicationTriggerTaskName "ApplicationTriggerTask" +#define GroupedBackgroundTaskName "GroupedBackgroundTask" +#define BackgroundTaskGroupId "3F2504E0-5F89-41D3-9A0C-0405E82C3333" +#define BackgroundTaskGroupFriendlyName "Background Task Group" namespace SDKTemplate { @@ -58,9 +61,10 @@ namespace SDKTemplate { public: static String^ GetBackgroundTaskStatus(String^ name); - static BackgroundTaskRegistration^ RegisterBackgroundTask(String^ taskEntryPoint, String^ name, IBackgroundTrigger^ trigger, IBackgroundCondition^ condition); + static BackgroundTaskRegistration^ RegisterBackgroundTask(String^ taskEntryPoint, String^ name, IBackgroundTrigger^ trigger, IBackgroundCondition^ condition, BackgroundTaskRegistrationGroup^ group = nullptr); static bool TaskRequiresBackgroundAccess(String^ name); - static void UnregisterBackgroundTasks(String^ name); + static void UnregisterBackgroundTasks(String^ name, BackgroundTaskRegistrationGroup^ group = nullptr); + static BackgroundTaskRegistrationGroup^ GetTaskGroup(String^ id, String^ groupName); static void UpdateBackgroundTaskRegistrationStatus(String^ name, bool registered); static String^ SampleBackgroundTaskProgress; @@ -78,6 +82,9 @@ namespace SDKTemplate static String^ ApplicationTriggerTaskProgress; static bool ApplicationTriggerTaskRegistered; static String^ ApplicationTriggerTaskResult; + + static String^ GroupedBackgroundTaskProgress; + static bool GroupedBackgroundTaskRegistered; }; } diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario6_GroupedTask.xaml.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario6_GroupedTask.xaml.cpp new file mode 100644 index 0000000000..7e48f59195 --- /dev/null +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario6_GroupedTask.xaml.cpp @@ -0,0 +1,155 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +// +// Scenario6_GroupedTask.xaml.cpp +// Implementation of the GroupedBackgroundTask class +// + +#include "pch.h" +#include "Scenario6_GroupedTask.xaml.h" +#include "SampleConfiguration.h" + +using namespace SDKTemplate; +using namespace concurrency; +using namespace Windows::ApplicationModel::Background; +using namespace Windows::UI::Core; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Navigation; + +GroupedBackgroundTask::GroupedBackgroundTask() +{ + InitializeComponent(); +} + +/// +/// Invoked when this page is about to be displayed in a Frame. +/// +/// Event data that describes how this page was reached. The Parameter +/// property is typically used to configure the page. +void GroupedBackgroundTask::OnNavigatedTo(NavigationEventArgs^ e) +{ + // A pointer back to the main page. This is needed if you want to call methods in MainPage such + // as NotifyUser() + rootPage = MainPage::Current; + + group = BackgroundTaskSample::GetTaskGroup(BackgroundTaskGroupId, BackgroundTaskGroupFriendlyName); + + // + // Attach progress and completed handlers to any existing tasks. + // + for (auto pair : group->AllTasks) + { + auto task = pair->Value; + if (task->Name == GroupedBackgroundTaskName) + { + BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(task->Name, true); + AttachProgressAndCompletedHandlers(task); + break; + } + } + + UpdateUI(); +} + +/// +/// Attach progress and completed handers to a background task. +/// +/// The task to attach progress and completed handlers to. +void GroupedBackgroundTask::AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration^ task) +{ + task->Progress += ref new BackgroundTaskProgressEventHandler(this, &GroupedBackgroundTask::OnProgress); + task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &GroupedBackgroundTask::OnCompleted); +} + +/// +/// Register a Grouped Background Task. +/// +/// +/// +void GroupedBackgroundTask::RegisterGroupedBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + auto task = BackgroundTaskSample::RegisterBackgroundTask(SampleBackgroundTaskEntryPoint, + GroupedBackgroundTaskName, + ref new SystemTrigger(SystemTriggerType::TimeZoneChange, false), + nullptr, + group); + AttachProgressAndCompletedHandlers(task); + UpdateUI(); +} + +/// +/// Unregister a Grouped Background Task. +/// +/// +/// +void GroupedBackgroundTask::UnregisterGroupedTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + BackgroundTaskSample::UnregisterBackgroundTasks(GroupedBackgroundTaskName, group); + UpdateUI(); +} + +/// +/// Unregister all Background Tasks that are not grouped. +/// +/// +/// +void GroupedBackgroundTask::UnregisterUngroupedTasks(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + for (auto pair : BackgroundTaskRegistration::AllTasks) + { + auto task = pair->Value; + task->Unregister(true); + BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(task->Name, false); + } +} + +/// +/// Handle background task progress. +/// +/// The task that is reporting progress. +/// Arguments of the progress report. +void GroupedBackgroundTask::OnProgress(BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) +{ + Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args]() + { + auto progress = "Progress: " + args->Progress + "%"; + BackgroundTaskSample::GroupedBackgroundTaskProgress = progress; + UpdateUI(); + })); +} + +/// +/// Handle background task completion. +/// +/// The task that is reporting completion. +/// Arguments of the completion report. +void GroupedBackgroundTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) +{ + UpdateUI(); +} + +/// +/// Update the scenario UI. +/// +void GroupedBackgroundTask::UpdateUI() +{ + auto uiDelegate = [this]() + { + RegisterButton->IsEnabled = !BackgroundTaskSample::GroupedBackgroundTaskRegistered; + UnregisterGroupedButton->IsEnabled = BackgroundTaskSample::GroupedBackgroundTaskRegistered; + Progress->Text = BackgroundTaskSample::GroupedBackgroundTaskProgress; + Status->Text = BackgroundTaskSample::GetBackgroundTaskStatus(GroupedBackgroundTaskName); + }; + auto handler = ref new Windows::UI::Core::DispatchedHandler(uiDelegate, Platform::CallbackContext::Any); + + Dispatcher->RunAsync(CoreDispatcherPriority::Normal, handler); +} diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario6_GroupedTask.xaml.h b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario6_GroupedTask.xaml.h new file mode 100644 index 0000000000..4f639635a1 --- /dev/null +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario6_GroupedTask.xaml.h @@ -0,0 +1,48 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +// +// Scenario5_GroupedTask.xaml.h +// Declaration of the GroupedBackgroundTask class +// + +#pragma once + +#include +#include "pch.h" +#include "Scenario6_GroupedTask.g.h" +#include "MainPage.xaml.h" + +namespace SDKTemplate +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + [Windows::Foundation::Metadata::WebHostHidden] + public ref class GroupedBackgroundTask sealed + { + public: + GroupedBackgroundTask(); + + protected: + virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; + private: + SDKTemplate::MainPage^ rootPage; + BackgroundTaskRegistrationGroup^ group = nullptr; + + void AttachProgressAndCompletedHandlers(Windows::ApplicationModel::Background::IBackgroundTaskRegistration^ task); + void RegisterGroupedBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void UnregisterGroupedTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void UnregisterUngroupedTasks(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void OnProgress(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskProgressEventArgs^ args); + void OnCompleted(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs^ args); + void UpdateUI(); + }; +} diff --git a/Samples/BackgroundTask/cs/BackgroundTask.sln b/Samples/BackgroundTask/cs/BackgroundTask.sln index 14cdb33528..4191ac3ef8 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask.sln +++ b/Samples/BackgroundTask/cs/BackgroundTask.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundTask", "BackgroundTask\BackgroundTask.csproj", "{EDDAF946-4577-5703-84CE-1756BEE56F6D}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/BackgroundTask/cs/BackgroundTask/BackgroundTask.csproj b/Samples/BackgroundTask/cs/BackgroundTask/BackgroundTask.csproj index 05c03925dc..1ad96a071c 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/BackgroundTask.csproj +++ b/Samples/BackgroundTask/cs/BackgroundTask/BackgroundTask.csproj @@ -118,6 +118,9 @@ Scenario3_ServicingCompleteTask.xaml + + Scenario6_GroupedTask.xaml + @@ -164,6 +167,12 @@ + + Scenario6_GroupedTask.xaml + MSBuild:Compile + + + Styles\Styles.xaml MSBuild:Compile diff --git a/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs b/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs index 09bc8d3d46..353bfcdd72 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs +++ b/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs @@ -28,7 +28,8 @@ public partial class MainPage : Page new Scenario() { Title="Background Task with Condition", ClassType=typeof(SampleBackgroundTaskWithCondition)}, new Scenario() { Title="Servicing Complete Task", ClassType=typeof(ServicingCompleteTask)}, new Scenario() { Title="Background Task with Time Trigger", ClassType=typeof(TimeTriggeredTask) }, - new Scenario() { Title="Background Task with Application Trigger", ClassType=typeof(ApplicationTriggerTask) } + new Scenario() { Title="Background Task with Application Trigger", ClassType=typeof(ApplicationTriggerTask) }, + new Scenario() { Title="Grouped Background Task", ClassType=typeof(GroupedBackgroundTask) }, }; } @@ -66,6 +67,12 @@ class BackgroundTaskSample public static string ApplicationTriggerTaskResult = ""; public static bool ApplicationTriggerTaskRegistered = false; + public const string GroupedBackgroundTaskName = "GroupedBackgroundTask"; + public const string BackgroundTaskGroupId = "3F2504E0-5F89-41D3-9A0C-0405E82C3333"; + public const string BackgroundTaskGroupFriendlyName = "Background Task Group"; + public static string GroupedBackgroundTaskProgress = ""; + public static bool GroupedBackgroundTaskRegistered = false; + /// /// Register a background task with the specified taskEntryPoint, name, trigger, /// and condition (optional). @@ -74,7 +81,7 @@ class BackgroundTaskSample /// A name for the background task. /// The trigger for the background task. /// An optional conditional event that must be true for the task to fire. - public static BackgroundTaskRegistration RegisterBackgroundTask(String taskEntryPoint, String name, IBackgroundTrigger trigger, IBackgroundCondition condition) + public static BackgroundTaskRegistration RegisterBackgroundTask(String taskEntryPoint, String name, IBackgroundTrigger trigger, IBackgroundCondition condition, BackgroundTaskRegistrationGroup group = null) { if (TaskRequiresBackgroundAccess(name)) { @@ -99,6 +106,11 @@ public static BackgroundTaskRegistration RegisterBackgroundTask(String taskEntry builder.CancelOnConditionLoss = true; } + if (group != null) + { + builder.TaskGroup = group; + } + BackgroundTaskRegistration task = builder.Register(); UpdateBackgroundTaskRegistrationStatus(name, true); @@ -116,23 +128,56 @@ public static BackgroundTaskRegistration RegisterBackgroundTask(String taskEntry /// Unregister background tasks with specified name. /// /// Name of the background task to unregister. - public static void UnregisterBackgroundTasks(String name) + public static void UnregisterBackgroundTasks(String name, BackgroundTaskRegistrationGroup group = null) { // - // Loop through all background tasks and unregister any with SampleBackgroundTaskName or - // SampleBackgroundTaskWithConditionName. + // If the given task group is registered then loop through all background tasks associated with it + // and unregister any with the given name. // - foreach (var cur in BackgroundTaskRegistration.AllTasks) + if (group != null) { - if (cur.Value.Name == name) + foreach (var cur in group.AllTasks) + { + if (cur.Value.Name == name) + { + cur.Value.Unregister(true); + } + } + } + else + { + // + // Loop through all ungrouped background tasks and unregister any with the given name. + // + foreach (var cur in BackgroundTaskRegistration.AllTasks) { - cur.Value.Unregister(true); + if (cur.Value.Name == name) + { + cur.Value.Unregister(true); + } } } UpdateBackgroundTaskRegistrationStatus(name, false); } + /// + /// Retrieve a registered background task group. If no group is registered with the given id, + /// then create a new one and return it. + /// + /// The task group associated with the given id + public static BackgroundTaskRegistrationGroup GetTaskGroup(string id, string groupName) + { + var group = BackgroundTaskRegistration.GetTaskGroup(id); + + if (group == null) + { + group = new BackgroundTaskRegistrationGroup(id, groupName); + } + + return group; + } + /// /// Store the registration status of a background task with a given name. /// @@ -157,6 +202,9 @@ public static void UpdateBackgroundTaskRegistrationStatus(String name, bool regi case ApplicationTriggerTaskName: ApplicationTriggerTaskRegistered = registered; break; + case GroupedBackgroundTaskName: + GroupedBackgroundTaskRegistered = registered; + break; } } @@ -185,6 +233,9 @@ public static String GetBackgroundTaskStatus(String name) case ApplicationTriggerTaskName: registered = ApplicationTriggerTaskRegistered; break; + case GroupedBackgroundTaskName: + registered = GroupedBackgroundTaskRegistered; + break; } var status = registered ? "Registered" : "Unregistered"; diff --git a/Samples/BackgroundTask/cs/BackgroundTask/Scenario6_GroupedTask.xaml.cs b/Samples/BackgroundTask/cs/BackgroundTask/Scenario6_GroupedTask.xaml.cs new file mode 100644 index 0000000000..8886a938b1 --- /dev/null +++ b/Samples/BackgroundTask/cs/BackgroundTask/Scenario6_GroupedTask.xaml.cs @@ -0,0 +1,156 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +using System; +using SDKTemplate; +using Windows.ApplicationModel.Background; +using Windows.Storage; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +namespace SDKTemplate +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class GroupedBackgroundTask : Page + { + // A pointer back to the main page. This is needed if you want to call methods in MainPage such + // as NotifyUser() + MainPage rootPage = MainPage.Current; + + public GroupedBackgroundTask() + { + this.InitializeComponent(); + } + + BackgroundTaskRegistrationGroup group; + + /// + /// Invoked when this page is about to be displayed in a Frame. + /// + /// Event data that describes how this page was reached. The Parameter + /// property is typically used to configure the page. + protected override void OnNavigatedTo(NavigationEventArgs e) + { + group = BackgroundTaskSample.GetTaskGroup(BackgroundTaskSample.BackgroundTaskGroupId, BackgroundTaskSample.BackgroundTaskGroupFriendlyName); + + foreach (var task in group.AllTasks) + { + if (task.Value.Name == BackgroundTaskSample.GroupedBackgroundTaskName) + { + AttachProgressAndCompletedHandlers(task.Value); + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.GroupedBackgroundTaskName, true); + break; + } + } + + UpdateUI(); + } + + /// + /// Register a Grouped Background Task. + /// + /// + /// + private void RegisterGroupedBackgroundTask(object sender, RoutedEventArgs e) + { + var task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, + BackgroundTaskSample.GroupedBackgroundTaskName, + new SystemTrigger(SystemTriggerType.TimeZoneChange, false), + null, + group); + AttachProgressAndCompletedHandlers(task); + UpdateUI(); + } + + + /// + /// Unregister a Grouped Background Task. + /// + /// + /// + private void UnregisterGroupedTask(object sender, RoutedEventArgs e) + { + BackgroundTaskSample.UnregisterBackgroundTasks(BackgroundTaskSample.GroupedBackgroundTaskName, group); + UpdateUI(); + } + + /// + /// Unregisters all Background Tasks that are not in groups. + /// This will not impact tasks registered with groups. + /// + /// + /// + private void UnregisterUngroupedTasks(object sender, RoutedEventArgs e) + { + foreach(var cur in BackgroundTaskRegistration.AllTasks) + { + cur.Value.Unregister(true); + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(cur.Value.Name, false); + } + } + + /// + /// Attach progress and completed handers to a background task. + /// + /// The task to attach progress and completed handlers to. + private void AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration task) + { + task.Progress += new BackgroundTaskProgressEventHandler(OnProgress); + task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted); + } + + /// + /// Handle background task progress. + /// + /// The task that is reporting progress. + /// Arguments of the progress report. + private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args) + { + var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + var progress = "Progress: " + args.Progress + "%"; + BackgroundTaskSample.GroupedBackgroundTaskProgress = progress; + UpdateUI(); + }); + } + + /// + /// Handle background task completion. + /// + /// The task that is reporting completion. + /// Arguments of the completion report. + private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args) + { + UpdateUI(); + } + + /// + /// Update the scenario UI. + /// + private async void UpdateUI() + { + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, + () => + { + RegisterButton.IsEnabled = !BackgroundTaskSample.GroupedBackgroundTaskRegistered; + UnregisterGroupedButton.IsEnabled = BackgroundTaskSample.GroupedBackgroundTaskRegistered; + Progress.Text = BackgroundTaskSample.GroupedBackgroundTaskProgress; + Status.Text = BackgroundTaskSample.GetBackgroundTaskStatus(BackgroundTaskSample.GroupedBackgroundTaskName); + }); + } + } +} diff --git a/Samples/BackgroundTask/shared/Scenario6_GroupedTask.xaml b/Samples/BackgroundTask/shared/Scenario6_GroupedTask.xaml new file mode 100644 index 0000000000..6eb418ce61 --- /dev/null +++ b/Samples/BackgroundTask/shared/Scenario6_GroupedTask.xaml @@ -0,0 +1,49 @@ + + + + + + + + + + Registers a background task for a Time zone change trigger event with a background task + registration group. Registering with a group enables the task registration to remain active + when all ungrouped tasks are unregistered. + + + + + + + + + + + + + diff --git a/Samples/BackgroundTask/vb/BackgroundTask.sln b/Samples/BackgroundTask/vb/BackgroundTask.sln index 5f9dd65cd1..5005cd93f5 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask.sln +++ b/Samples/BackgroundTask/vb/BackgroundTask.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BackgroundTask", "BackgroundTask\BackgroundTask.vbproj", "{4322EB18-632F-585B-8167-541E5D55D293}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/BackgroundTask/vb/BackgroundTask/BackgroundTask.vbproj b/Samples/BackgroundTask/vb/BackgroundTask/BackgroundTask.vbproj index b1392cc85c..121879a755 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/BackgroundTask.vbproj +++ b/Samples/BackgroundTask/vb/BackgroundTask/BackgroundTask.vbproj @@ -122,6 +122,9 @@ Scenario3_ServicingCompleteTask.xaml + + Scenario6_GroupedTask.xaml + @@ -164,6 +167,11 @@ MSBuild:Compile + + Scenario6_GroupedTask.xaml + MSBuild:Compile + + Styles\Styles.xaml MSBuild:Compile diff --git a/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb b/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb index 0fa21b4e4c..355328cd93 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb +++ b/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb @@ -22,7 +22,7 @@ Namespace Global.SDKTemplate Public Const FEATURE_NAME As String = "Background tasks" - Public ReadOnly Property scenarios As New List(Of Scenario) From {New Scenario() With {.Title = "Background Task", .ClassType = GetType(SampleBackgroundTask)}, New Scenario() With {.Title = "Background Task with Condition", .ClassType = GetType(SampleBackgroundTaskWithCondition)}, New Scenario() With {.Title = "Servicing Complete Task", .ClassType = GetType(ServicingCompleteTask)}, New Scenario() With {.Title = "Background Task with Time Trigger", .ClassType = GetType(TimeTriggeredTask)}, New Scenario() With {.Title = "Background Task with Application Trigger", .ClassType = GetType(ApplicationTriggerTask)}} + Public ReadOnly Property scenarios As New List(Of Scenario) From {New Scenario() With {.Title = "Background Task", .ClassType = GetType(SampleBackgroundTask)}, New Scenario() With {.Title = "Background Task with Condition", .ClassType = GetType(SampleBackgroundTaskWithCondition)}, New Scenario() With {.Title = "Servicing Complete Task", .ClassType = GetType(ServicingCompleteTask)}, New Scenario() With {.Title = "Background Task with Time Trigger", .ClassType = GetType(TimeTriggeredTask)}, New Scenario() With {.Title = "Background Task with Application Trigger", .ClassType = GetType(ApplicationTriggerTask)}, New Scenario() With {.Title = "Grouped Background Task", .ClassType = GetType(GroupedBackgroundTask)}} End Class Public Class Scenario @@ -73,6 +73,16 @@ Namespace Global.SDKTemplate Public Shared ApplicationTriggerTaskRegistered As Boolean = False + Public Const GroupedBackgroundTaskName As String = "GroupedBackgroundTask" + + Public Const BackgroundTaskGroupId As String = "3F2504E0-5F89-41D3-9A0C-0405E82C3333" + + Public Const BackgroundTaskGroupFriendlyName As String = "Background Task Group" + + Public Shared GroupedBackgroundTaskProgress As String = "" + + Public Shared GroupedBackgroundTaskRegistered As Boolean = False + ''' ''' Register a background task with the specified taskEntryPoint, name, trigger, ''' and condition (optional). @@ -81,7 +91,7 @@ Namespace Global.SDKTemplate ''' A name for the background task. ''' The trigger for the background task. ''' An optional conditional event that must be true for the task to fire. - Public Shared Function RegisterBackgroundTask(taskEntryPoint As String, name As String, trigger As IBackgroundTrigger, condition As IBackgroundCondition) As BackgroundTaskRegistration + Public Shared Function RegisterBackgroundTask(taskEntryPoint As String, name As String, trigger As IBackgroundTrigger, condition As IBackgroundCondition, Optional group As BackgroundTaskRegistrationGroup = Nothing) As BackgroundTaskRegistration If TaskRequiresBackgroundAccess(name) Then ' If the user denies access, the task will not run. Dim requestTask = BackgroundExecutionManager.RequestAccessAsync() @@ -96,6 +106,10 @@ Namespace Global.SDKTemplate builder.CancelOnConditionLoss = True End If + If group IsNot Nothing Then + builder.TaskGroup = group + End If + Dim task As BackgroundTaskRegistration = builder.Register() UpdateBackgroundTaskRegistrationStatus(name, True) ' @@ -110,16 +124,42 @@ Namespace Global.SDKTemplate ''' Unregister background tasks with specified name. ''' ''' Name of the background task to unregister. - Public Shared Sub UnregisterBackgroundTasks(name As String) - For Each cur In BackgroundTaskRegistration.AllTasks - If cur.Value.Name = name Then - cur.Value.Unregister(True) - End If - Next + Public Shared Sub UnregisterBackgroundTasks(name As String, Optional group As BackgroundTaskRegistrationGroup = Nothing) + + If group IsNot Nothing Then + For Each cur In group.AllTasks + If cur.Value.Name = name Then + cur.Value.Unregister(True) + End If + Next + Else + For Each cur In BackgroundTaskRegistration.AllTasks + If cur.Value.Name = name Then + cur.Value.Unregister(True) + End If + Next + End If UpdateBackgroundTaskRegistrationStatus(name, False) End Sub + ''' + ''' Retrieve a registered background task group. If no group is registered with the given id, + ''' then create a new one and return it. + ''' + ''' + ''' + ''' The task group associated with the given id + Public Shared Function GetTaskGroup(id As String, groupName As String) As BackgroundTaskRegistrationGroup + Dim group = BackgroundTaskRegistration.GetTaskGroup(id) + + If group Is Nothing Then + group = New BackgroundTaskRegistrationGroup(id, groupName) + End If + + Return group + End Function + ''' ''' Store the registration status of a background task with a given name. ''' @@ -137,7 +177,9 @@ Namespace Global.SDKTemplate TimeTriggeredTaskRegistered = registered Case ApplicationTriggerTaskName ApplicationTriggerTaskRegistered = registered - End Select + Case GroupedBackgroundTaskName + GroupedBackgroundTaskRegistered = registered + End Select End Sub ''' @@ -158,7 +200,9 @@ Namespace Global.SDKTemplate registered = TimeTriggeredTaskRegistered Case ApplicationTriggerTaskName registered = ApplicationTriggerTaskRegistered - End Select + Case GroupedBackgroundTaskName + registered = GroupedBackgroundTaskRegistered + End Select Dim status = If(registered, "Registered", "Unregistered") Dim taskStatus As Object = Nothing diff --git a/Samples/BackgroundTask/vb/BackgroundTask/Scenario6_GroupedTask.xaml.vb b/Samples/BackgroundTask/vb/BackgroundTask/Scenario6_GroupedTask.xaml.vb new file mode 100644 index 0000000000..5c51e1137e --- /dev/null +++ b/Samples/BackgroundTask/vb/BackgroundTask/Scenario6_GroupedTask.xaml.vb @@ -0,0 +1,133 @@ +'********************************************************* +' +' Copyright (c) Microsoft. All rights reserved. +' This code is licensed under the MIT License (MIT). +' THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +' ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +' IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +' PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +' +'********************************************************* +Imports System +Imports SDKTemplate +Imports Windows.ApplicationModel.Background +Imports Windows.Storage +Imports Windows.UI.Core +Imports Windows.UI.Xaml +Imports Windows.UI.Xaml.Controls +Imports Windows.UI.Xaml.Navigation + +Namespace Global.SDKTemplate + + ''' + ''' An empty page that can be used on its own or navigated to within a Frame. + ''' + Partial Public NotInheritable Class GroupedBackgroundTask + Inherits Page + + Dim rootPage As MainPage = MainPage.Current + + Dim group As BackgroundTaskRegistrationGroup = Nothing + + Public Sub New() + Me.InitializeComponent() + End Sub + + ''' + ''' Invoked when this page is about to be displayed in a Frame. + ''' + ''' Event data that describes how this page was reached. The Parameter + ''' property is typically used to configure the page. + Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs) + + group = BackgroundTaskSample.GetTaskGroup(BackgroundTaskSample.BackgroundTaskGroupId, BackgroundTaskSample.BackgroundTaskGroupFriendlyName) + + For Each task In group.AllTasks + If task.Value.Name = BackgroundTaskSample.GroupedBackgroundTaskName Then + AttachProgressAndCompletedHandlers(task.Value) + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.GroupedBackgroundTaskName, True) + Exit For + End If + Next + + UpdateUI() + End Sub + + ''' + ''' Register a Grouped Background Task. + ''' + ''' + ''' + Private Sub RegisterGroupedBackgroundTask(sender As Object, e As RoutedEventArgs) + Dim task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.GroupedBackgroundTaskName, New SystemTrigger(SystemTriggerType.TimeZoneChange, False), Nothing, group) + AttachProgressAndCompletedHandlers(task) + UpdateUI() + End Sub + + ''' + ''' Unregister a Grouped Background Task. + ''' + ''' + ''' + Private Sub UnregisterGroupedTask(sender As Object, e As RoutedEventArgs) + BackgroundTaskSample.UnregisterBackgroundTasks(BackgroundTaskSample.GroupedBackgroundTaskName, group) + UpdateUI() + End Sub + + ''' + ''' Unregister all Background Tasks that are not in groups. + ''' This will not impact tasks registered with groups. + ''' + ''' + ''' + Private Sub UnregisterUngroupedTasks(sender As Object, e As RoutedEventArgs) + For Each cur In BackgroundTaskRegistration.AllTasks + cur.Value.Unregister(True) + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(cur.Value.Name, False) + Next + End Sub + + ''' + ''' Attach progress and completed handers to a background task. + ''' + ''' The task to attach progress and completed handlers to. + Private Sub AttachProgressAndCompletedHandlers(task As IBackgroundTaskRegistration) + AddHandler task.Progress, New BackgroundTaskProgressEventHandler(AddressOf OnProgress) + AddHandler task.Completed, New BackgroundTaskCompletedEventHandler(AddressOf OnCompleted) + End Sub + + ''' + ''' Handle background task progress. + ''' + ''' The task that is reporting progress. + ''' Arguments of the progress report. + Private Sub OnProgress(task As IBackgroundTaskRegistration, args As BackgroundTaskProgressEventArgs) + Dim ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() + Dim progress = "Progress: " & args.Progress & "%" + BackgroundTaskSample.GroupedBackgroundTaskProgress = progress + UpdateUI() + End Sub) + End Sub + + ''' + ''' Handle background task completion. + ''' + ''' The task that is reporting completion. + ''' Arguments of the completion report. + Private Sub OnCompleted(task As IBackgroundTaskRegistration, args As BackgroundTaskCompletedEventArgs) + UpdateUI() + End Sub + + ''' + ''' Update the scenario UI. + ''' + Private Async Sub UpdateUI() + Await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() + RegisterButton.IsEnabled = Not BackgroundTaskSample.GroupedBackgroundTaskRegistered + UnregisterGroupedButton.IsEnabled = BackgroundTaskSample.GroupedBackgroundTaskRegistered + Progress.Text = BackgroundTaskSample.GroupedBackgroundTaskProgress + Status.Text = BackgroundTaskSample.GetBackgroundTaskStatus(BackgroundTaskSample.GroupedBackgroundTaskName) + End Sub) + End Sub + End Class +End Namespace diff --git a/Samples/BackgroundTransfer/cpp/BackgroundTransfer.sln b/Samples/BackgroundTransfer/cpp/BackgroundTransfer.sln index 173c4fc1c1..3817cff7b5 100644 --- a/Samples/BackgroundTransfer/cpp/BackgroundTransfer.sln +++ b/Samples/BackgroundTransfer/cpp/BackgroundTransfer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackgroundTransfer", "BackgroundTransfer\BackgroundTransfer.vcxproj", "{D8C2D505-8ACC-5986-A26A-E36FB2D6ABA6}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/BackgroundTransfer/cs/BackgroundTransfer.sln b/Samples/BackgroundTransfer/cs/BackgroundTransfer.sln index 14228e2e3f..0a03bd2704 100644 --- a/Samples/BackgroundTransfer/cs/BackgroundTransfer.sln +++ b/Samples/BackgroundTransfer/cs/BackgroundTransfer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundTransfer", "BackgroundTransfer\BackgroundTransfer.csproj", "{12E2E221-37A9-5A37-84A9-9D2B396366E7}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/BackgroundTransfer/js/BackgroundTransfer.sln b/Samples/BackgroundTransfer/js/BackgroundTransfer.sln index f9f6e423b7..149cea8887 100644 --- a/Samples/BackgroundTransfer/js/BackgroundTransfer.sln +++ b/Samples/BackgroundTransfer/js/BackgroundTransfer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "BackgroundTransfer", "BackgroundTransfer.jsproj", "{8B4EF842-15AE-5F4E-BA13-5B6799D7FBE5}" EndProject diff --git a/Samples/BackgroundTransfer/vb/BackgroundTransfer.sln b/Samples/BackgroundTransfer/vb/BackgroundTransfer.sln index 745211d6d4..ed5d56f953 100644 --- a/Samples/BackgroundTransfer/vb/BackgroundTransfer.sln +++ b/Samples/BackgroundTransfer/vb/BackgroundTransfer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BackgroundTransfer", "BackgroundTransfer\BackgroundTransfer.vbproj", "{2078B9B3-6A72-5A79-AF38-707F2DDBADDE}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/BarcodeScanner/cpp/BarcodeScanner.sln b/Samples/BarcodeScanner/cpp/BarcodeScanner.sln index dad5afdd89..759fdef552 100644 --- a/Samples/BarcodeScanner/cpp/BarcodeScanner.sln +++ b/Samples/BarcodeScanner/cpp/BarcodeScanner.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BarcodeScanner", "BarcodeScanner.vcxproj", "{9056786E-8B85-5EF6-8CED-2D299FC93CEA}" EndProject diff --git a/Samples/BarcodeScanner/cs/BarcodeScanner.sln b/Samples/BarcodeScanner/cs/BarcodeScanner.sln index d9071e5287..dbf0262d60 100644 --- a/Samples/BarcodeScanner/cs/BarcodeScanner.sln +++ b/Samples/BarcodeScanner/cs/BarcodeScanner.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BarcodeScanner", "BarcodeScanner.csproj", "{676FCC42-46A5-5156-9CD9-95C8A68EF3EA}" EndProject diff --git a/Samples/BarcodeScanner/js/BarcodeScanner.sln b/Samples/BarcodeScanner/js/BarcodeScanner.sln index 85d36ac399..8b97daf064 100644 --- a/Samples/BarcodeScanner/js/BarcodeScanner.sln +++ b/Samples/BarcodeScanner/js/BarcodeScanner.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "BarcodeScanner", "BarcodeScanner.jsproj", "{76A91647-0B7F-595B-8871-3964B35ADB3B}" EndProject diff --git a/Samples/BarcodeScanner/vb/BarcodeScanner.sln b/Samples/BarcodeScanner/vb/BarcodeScanner.sln index 31dea13830..3fef91fc58 100644 --- a/Samples/BarcodeScanner/vb/BarcodeScanner.sln +++ b/Samples/BarcodeScanner/vb/BarcodeScanner.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BarcodeScanner", "BarcodeScanner.vbproj", "{DC7419D5-0E8B-5431-85A9-C21F81D86F5A}" EndProject diff --git a/Samples/Barometer/cpp/Barometer.sln b/Samples/Barometer/cpp/Barometer.sln index 68a6baa283..725e1f2775 100644 --- a/Samples/Barometer/cpp/Barometer.sln +++ b/Samples/Barometer/cpp/Barometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Barometer", "Barometer.vcxproj", "{B2495D2E-F647-5877-AC83-09F4A7D0F5CE}" EndProject diff --git a/Samples/Barometer/cs/Barometer.sln b/Samples/Barometer/cs/Barometer.sln index d605927ae2..2a4fb7a7c5 100644 --- a/Samples/Barometer/cs/Barometer.sln +++ b/Samples/Barometer/cs/Barometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Barometer", "Barometer.csproj", "{7B59078D-4B3C-52E5-A10D-32BE2939894A}" EndProject diff --git a/Samples/Barometer/js/Barometer.sln b/Samples/Barometer/js/Barometer.sln index e71dd29eb6..30109f3e38 100644 --- a/Samples/Barometer/js/Barometer.sln +++ b/Samples/Barometer/js/Barometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Barometer", "Barometer.jsproj", "{7E663E90-22FD-5EE5-A031-DFA6A420C8F1}" EndProject diff --git a/Samples/Barometer/vb/Barometer.sln b/Samples/Barometer/vb/Barometer.sln index a7be935c16..0597701842 100644 --- a/Samples/Barometer/vb/Barometer.sln +++ b/Samples/Barometer/vb/Barometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Barometer", "Barometer.vbproj", "{9064D869-ED19-5CE5-B91F-8739E05575D4}" EndProject diff --git a/Samples/BasicFaceDetection/cpp/BasicFaceDetection.sln b/Samples/BasicFaceDetection/cpp/BasicFaceDetection.sln index e8b92929de..9731ade174 100644 --- a/Samples/BasicFaceDetection/cpp/BasicFaceDetection.sln +++ b/Samples/BasicFaceDetection/cpp/BasicFaceDetection.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicFaceDetection", "BasicFaceDetection.vcxproj", "{D5439AD9-935A-5CD7-8CCE-CF7F351B6D68}" EndProject diff --git a/Samples/BasicFaceDetection/cs/BasicFaceDetection.sln b/Samples/BasicFaceDetection/cs/BasicFaceDetection.sln index 6163334990..ad46c18787 100644 --- a/Samples/BasicFaceDetection/cs/BasicFaceDetection.sln +++ b/Samples/BasicFaceDetection/cs/BasicFaceDetection.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicFaceDetection", "BasicFaceDetection.csproj", "{B32722A2-7498-5C4E-8D1E-F72EFD788BBA}" EndProject diff --git a/Samples/BasicFaceDetection/vb/BasicFaceDetection.sln b/Samples/BasicFaceDetection/vb/BasicFaceDetection.sln index f232c4279a..ab1d7748fc 100644 --- a/Samples/BasicFaceDetection/vb/BasicFaceDetection.sln +++ b/Samples/BasicFaceDetection/vb/BasicFaceDetection.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicFaceDetection", "BasicFaceDetection.vbproj", "{3DD607F7-F461-53D8-9C12-E13C45752B5F}" EndProject diff --git a/Samples/BasicFaceTracking/cpp/BasicFaceTracking.sln b/Samples/BasicFaceTracking/cpp/BasicFaceTracking.sln index d78be4a7b4..5e9ae06312 100644 --- a/Samples/BasicFaceTracking/cpp/BasicFaceTracking.sln +++ b/Samples/BasicFaceTracking/cpp/BasicFaceTracking.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicFaceTracking", "BasicFaceTracking.vcxproj", "{756A46DC-B917-5914-A1D0-CC30CC27E385}" EndProject diff --git a/Samples/BasicFaceTracking/cs/BasicFaceTracking.sln b/Samples/BasicFaceTracking/cs/BasicFaceTracking.sln index 720bd06ed9..4daad5d6c2 100644 --- a/Samples/BasicFaceTracking/cs/BasicFaceTracking.sln +++ b/Samples/BasicFaceTracking/cs/BasicFaceTracking.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicFaceTracking", "BasicFaceTracking.csproj", "{0E7DBC61-4B7B-57C2-9576-3A9B5DA4ACCE}" EndProject diff --git a/Samples/BasicFaceTracking/vb/BasicFaceTracking.sln b/Samples/BasicFaceTracking/vb/BasicFaceTracking.sln index 7b03d3c3f3..98cd4061de 100644 --- a/Samples/BasicFaceTracking/vb/BasicFaceTracking.sln +++ b/Samples/BasicFaceTracking/vb/BasicFaceTracking.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicFaceTracking", "BasicFaceTracking.vbproj", "{1F120EA7-1849-5ACC-BD9E-38FF91B554BD}" EndProject diff --git a/Samples/BasicInput/cpp/BasicInput.sln b/Samples/BasicInput/cpp/BasicInput.sln index e439d81cd1..0adb5d56ab 100644 --- a/Samples/BasicInput/cpp/BasicInput.sln +++ b/Samples/BasicInput/cpp/BasicInput.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicInput", "BasicInput.vcxproj", "{C0C8E9AF-EB8E-5700-AD5E-6267DE9BA16E}" EndProject diff --git a/Samples/BasicInput/cs/BasicInput.sln b/Samples/BasicInput/cs/BasicInput.sln index 004764af97..47fdcb8b05 100644 --- a/Samples/BasicInput/cs/BasicInput.sln +++ b/Samples/BasicInput/cs/BasicInput.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicInput", "BasicInput.csproj", "{6A7AAE08-7019-5799-81C9-E61460ACDC25}" EndProject diff --git a/Samples/BasicInput/vb/BasicInput.sln b/Samples/BasicInput/vb/BasicInput.sln index 1c548ffdf8..c1ecedc01f 100644 --- a/Samples/BasicInput/vb/BasicInput.sln +++ b/Samples/BasicInput/vb/BasicInput.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicInput", "BasicInput.vbproj", "{FE2E6267-3E68-538D-9F60-CCA3CCE8F581}" EndProject diff --git a/Samples/BasicMediaCasting/cs/BasicMediaCasting.sln b/Samples/BasicMediaCasting/cs/BasicMediaCasting.sln index ad7e7f965b..9ea8bb7d93 100644 --- a/Samples/BasicMediaCasting/cs/BasicMediaCasting.sln +++ b/Samples/BasicMediaCasting/cs/BasicMediaCasting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicMediaCasting", "BasicMediaCasting.csproj", "{8ECE56F9-F434-5CA9-ADA0-1F75F7019FA6}" EndProject diff --git a/Samples/BasicMediaCasting/vb/BasicMediaCasting.sln b/Samples/BasicMediaCasting/vb/BasicMediaCasting.sln index 3518c44f7a..8111fbd624 100644 --- a/Samples/BasicMediaCasting/vb/BasicMediaCasting.sln +++ b/Samples/BasicMediaCasting/vb/BasicMediaCasting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicMediaCasting", "BasicMediaCasting.vbproj", "{512872FF-2C46-5E56-8865-C8318A6006AE}" EndProject diff --git a/Samples/BasicSuspension/cs/BasicSuspension.sln b/Samples/BasicSuspension/cs/BasicSuspension.sln index b1ab26fb4a..116f166013 100644 --- a/Samples/BasicSuspension/cs/BasicSuspension.sln +++ b/Samples/BasicSuspension/cs/BasicSuspension.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BasicSuspension", "BasicSuspension.csproj", "{71214BF4-0491-563E-9CC8-5ACDECF6E39F}" EndProject diff --git a/Samples/BluetoothAdvertisement/cs/BluetoothAdvertisement.sln b/Samples/BluetoothAdvertisement/cs/BluetoothAdvertisement.sln index 11f8236313..51a890e945 100644 --- a/Samples/BluetoothAdvertisement/cs/BluetoothAdvertisement.sln +++ b/Samples/BluetoothAdvertisement/cs/BluetoothAdvertisement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bluetoothadvertisement", "bluetoothadvertisement.csproj", "{C95D065E-F1F0-58AD-A385-C19FA9C5F8C6}" EndProject diff --git a/Samples/BluetoothAdvertisement/js/BluetoothAdvertisement.sln b/Samples/BluetoothAdvertisement/js/BluetoothAdvertisement.sln index 9b8a667c79..8df113e212 100644 --- a/Samples/BluetoothAdvertisement/js/BluetoothAdvertisement.sln +++ b/Samples/BluetoothAdvertisement/js/BluetoothAdvertisement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "BluetoothAdvertisement", "BluetoothAdvertisement.jsproj", "{7563C15D-3F5E-58EF-B24B-831257B486F1}" EndProject diff --git a/Samples/BluetoothAdvertisement/vb/BluetoothAdvertisement.sln b/Samples/BluetoothAdvertisement/vb/BluetoothAdvertisement.sln index 865ef6636c..c69824058d 100644 --- a/Samples/BluetoothAdvertisement/vb/BluetoothAdvertisement.sln +++ b/Samples/BluetoothAdvertisement/vb/BluetoothAdvertisement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "bluetoothadvertisement", "bluetoothadvertisement.vbproj", "{A2F55623-BD3F-582E-9B5B-1DEFBCCE5084}" EndProject diff --git a/Samples/BluetoothLEClient/cs/BluetoothLEClient.sln b/Samples/BluetoothLEClient/cs/BluetoothLEClient.sln index 16f0dedf67..ff3a1e3cb7 100644 --- a/Samples/BluetoothLEClient/cs/BluetoothLEClient.sln +++ b/Samples/BluetoothLEClient/cs/BluetoothLEClient.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BluetoothLEClient", "BluetoothLEClient.csproj", "{4F601390-640F-5066-BF31-C45A23884F94}" EndProject diff --git a/Samples/BluetoothRfcommChat/cs/RfcommChat.sln b/Samples/BluetoothRfcommChat/cs/RfcommChat.sln index 1c28501cab..b73c772ab4 100644 --- a/Samples/BluetoothRfcommChat/cs/RfcommChat.sln +++ b/Samples/BluetoothRfcommChat/cs/RfcommChat.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RfcommChat", "RfcommChat.csproj", "{970A2AF6-A1AC-5A1D-AD88-CB43D639CB7C}" EndProject diff --git a/Samples/Calendar/cpp/Calendar.sln b/Samples/Calendar/cpp/Calendar.sln index eed2cd98a5..5c3f2ae32a 100644 --- a/Samples/Calendar/cpp/Calendar.sln +++ b/Samples/Calendar/cpp/Calendar.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Calendar", "Calendar.vcxproj", "{632095B8-2309-544E-9AE4-055F74FB3C6F}" EndProject diff --git a/Samples/Calendar/cs/Calendar.sln b/Samples/Calendar/cs/Calendar.sln index bf4cf02d49..d732fea47a 100644 --- a/Samples/Calendar/cs/Calendar.sln +++ b/Samples/Calendar/cs/Calendar.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calendar", "Calendar.csproj", "{C2C37FBD-E36A-5548-9022-11D1E0FF9072}" EndProject diff --git a/Samples/Calendar/js/Calendar.sln b/Samples/Calendar/js/Calendar.sln index 146aa88f10..40d654127a 100644 --- a/Samples/Calendar/js/Calendar.sln +++ b/Samples/Calendar/js/Calendar.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Calendar", "Calendar.jsproj", "{3D399424-4C96-55C9-ACAD-140F995A142F}" EndProject diff --git a/Samples/Calendar/vb/Calendar.sln b/Samples/Calendar/vb/Calendar.sln index ce7f4675c3..75cc5d62d2 100644 --- a/Samples/Calendar/vb/Calendar.sln +++ b/Samples/Calendar/vb/Calendar.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Calendar", "Calendar.vbproj", "{7949D831-1877-5DC8-85AF-E7000893A73B}" EndProject diff --git a/Samples/CallerID/cs/CallerID.sln b/Samples/CallerID/cs/CallerID.sln index da2c1d9d9a..b81a30e4f3 100644 --- a/Samples/CallerID/cs/CallerID.sln +++ b/Samples/CallerID/cs/CallerID.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CallerID", "CallerID.csproj", "{9C1A8440-C577-5734-B4F9-7B2F096AA65B}" EndProject diff --git a/Samples/CameraAdvancedCapture/cpp/CameraAdvancedCapture.sln b/Samples/CameraAdvancedCapture/cpp/CameraAdvancedCapture.sln index 3c68390cd3..ce777fe852 100644 --- a/Samples/CameraAdvancedCapture/cpp/CameraAdvancedCapture.sln +++ b/Samples/CameraAdvancedCapture/cpp/CameraAdvancedCapture.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraAdvancedCapture", "CameraAdvancedCapture.vcxproj", "{F571EC0B-2FF7-52A6-87AA-9224BA6856C2}" EndProject diff --git a/Samples/CameraAdvancedCapture/cs/CameraAdvancedCapture.sln b/Samples/CameraAdvancedCapture/cs/CameraAdvancedCapture.sln index e7c7bad6b1..cfde471451 100644 --- a/Samples/CameraAdvancedCapture/cs/CameraAdvancedCapture.sln +++ b/Samples/CameraAdvancedCapture/cs/CameraAdvancedCapture.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraAdvancedCapture", "CameraAdvancedCapture.csproj", "{8E8D3103-B448-54FA-BD16-89665201BD4F}" EndProject diff --git a/Samples/CameraAdvancedCapture/js/CameraAdvancedCapture.sln b/Samples/CameraAdvancedCapture/js/CameraAdvancedCapture.sln index 872f8c1daf..8950dc4144 100644 --- a/Samples/CameraAdvancedCapture/js/CameraAdvancedCapture.sln +++ b/Samples/CameraAdvancedCapture/js/CameraAdvancedCapture.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{89201536-2F87-4126-8592-2DE4CEFACA7E}") = "CameraAdvancedCapture", "CameraAdvancedCapture.jsproj", "{479DFEA6-5106-5E08-A135-FE45391C9A5A}" EndProject diff --git a/Samples/CameraAdvancedCapture/vb/CameraAdvancedCapture.sln b/Samples/CameraAdvancedCapture/vb/CameraAdvancedCapture.sln index 664dc64c15..bbdae9209e 100644 --- a/Samples/CameraAdvancedCapture/vb/CameraAdvancedCapture.sln +++ b/Samples/CameraAdvancedCapture/vb/CameraAdvancedCapture.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CameraAdvancedCapture", "CameraAdvancedCapture.vbproj", "{1FD5A815-BF04-505D-BC37-06C49C4420E7}" EndProject diff --git a/Samples/CameraFaceDetection/cpp/CameraFaceDetection.sln b/Samples/CameraFaceDetection/cpp/CameraFaceDetection.sln index bb4679c252..68661bf48e 100644 --- a/Samples/CameraFaceDetection/cpp/CameraFaceDetection.sln +++ b/Samples/CameraFaceDetection/cpp/CameraFaceDetection.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22815.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraFaceDetection", "CameraFaceDetection.vcxproj", "{B09647D8-72A5-5595-ADF7-3A8B4F27D930}" EndProject diff --git a/Samples/CameraFaceDetection/cs/CameraFaceDetection.sln b/Samples/CameraFaceDetection/cs/CameraFaceDetection.sln index b260145609..5308f8c297 100644 --- a/Samples/CameraFaceDetection/cs/CameraFaceDetection.sln +++ b/Samples/CameraFaceDetection/cs/CameraFaceDetection.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraFaceDetection", "CameraFaceDetection.csproj", "{1D8F7B18-04C9-5B15-9C71-347F9F363A8B}" EndProject diff --git a/Samples/CameraFaceDetection/js/CameraFaceDetection.sln b/Samples/CameraFaceDetection/js/CameraFaceDetection.sln index 7c721f2590..0adad96ef4 100644 --- a/Samples/CameraFaceDetection/js/CameraFaceDetection.sln +++ b/Samples/CameraFaceDetection/js/CameraFaceDetection.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CameraFaceDetection", "CameraFaceDetection.jsproj", "{0B484CD0-D6AF-5DCB-9AC3-A64BDE0BCA8C}" EndProject diff --git a/Samples/CameraFaceDetection/vb/CameraFaceDetection.sln b/Samples/CameraFaceDetection/vb/CameraFaceDetection.sln index 35e82fa26c..89062fa9cc 100644 --- a/Samples/CameraFaceDetection/vb/CameraFaceDetection.sln +++ b/Samples/CameraFaceDetection/vb/CameraFaceDetection.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CameraFaceDetection", "CameraFaceDetection.vbproj", "{42FC4695-4898-5A25-9A7D-5E4BAE9F0068}" EndProject diff --git a/Samples/CameraFrames/cpp/CameraFrames.sln b/Samples/CameraFrames/cpp/CameraFrames.sln index d22aa5ccb3..de0699d9ed 100644 --- a/Samples/CameraFrames/cpp/CameraFrames.sln +++ b/Samples/CameraFrames/cpp/CameraFrames.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraFrames", "CameraFrames.vcxproj", "{F6E08808-9C86-5321-8262-9D7E6026AB7D}" EndProject diff --git a/Samples/CameraFrames/cs/CameraFrames.sln b/Samples/CameraFrames/cs/CameraFrames.sln index d494f59254..0e7a1ee7ed 100644 --- a/Samples/CameraFrames/cs/CameraFrames.sln +++ b/Samples/CameraFrames/cs/CameraFrames.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraFrames", "CameraFrames.csproj", "{1C9C1B0C-DC7A-5F05-AD85-94DBBFEDDB69}" EndProject diff --git a/Samples/CameraGetPreviewFrame/cpp/CameraGetPreviewFrame.sln b/Samples/CameraGetPreviewFrame/cpp/CameraGetPreviewFrame.sln index a2a2b11be3..0fd363384a 100644 --- a/Samples/CameraGetPreviewFrame/cpp/CameraGetPreviewFrame.sln +++ b/Samples/CameraGetPreviewFrame/cpp/CameraGetPreviewFrame.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraGetPreviewFrame", "CameraGetPreviewFrame.vcxproj", "{426E63C8-FE61-54C3-BFF0-2C157F31B555}" EndProject diff --git a/Samples/CameraGetPreviewFrame/cs/CameraGetPreviewFrame.sln b/Samples/CameraGetPreviewFrame/cs/CameraGetPreviewFrame.sln index 827573c201..6f0e9144d2 100644 --- a/Samples/CameraGetPreviewFrame/cs/CameraGetPreviewFrame.sln +++ b/Samples/CameraGetPreviewFrame/cs/CameraGetPreviewFrame.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraGetPreviewFrame", "CameraGetPreviewFrame.csproj", "{4CD240E5-9276-5FDA-BA33-AF2F6C39367A}" EndProject diff --git a/Samples/CameraGetPreviewFrame/js/CameraGetPreviewFrame.sln b/Samples/CameraGetPreviewFrame/js/CameraGetPreviewFrame.sln index 5e03a90496..896665c3bb 100644 --- a/Samples/CameraGetPreviewFrame/js/CameraGetPreviewFrame.sln +++ b/Samples/CameraGetPreviewFrame/js/CameraGetPreviewFrame.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CameraGetPreviewFrame", "CameraGetPreviewFrame.jsproj", "{2F094DF8-AA3B-5FA6-89CA-4F88D9692271}" EndProject diff --git a/Samples/CameraManualControls/cs/CameraManualControls.sln b/Samples/CameraManualControls/cs/CameraManualControls.sln index da11919289..b31ca644f0 100644 --- a/Samples/CameraManualControls/cs/CameraManualControls.sln +++ b/Samples/CameraManualControls/cs/CameraManualControls.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraManualControls", "CameraManualControls.csproj", "{5898961F-02D7-5876-A6D3-3B3F80E6DFDF}" EndProject diff --git a/Samples/CameraOpenCV/README.md b/Samples/CameraOpenCV/README.md new file mode 100644 index 0000000000..d87a9e607e --- /dev/null +++ b/Samples/CameraOpenCV/README.md @@ -0,0 +1,54 @@ + + +# Camera frames + OpenCV sample + +Shows how to operate on individual frames with OpenCV. + +Specifically, this sample shows how to: + +- Obtain the data pointer to an image in a frame +- One way to use 3rd party libraries such as OpenCV + +**Note** The Windows universal samples require Visual Studio 2017 with Windows SDK version 15063 or above to build and Windows 10 to execute. + +To obtain information about Windows 10 development, go to the [Windows Dev Center](http://go.microsoft.com/fwlink/?LinkID=532421) + +To obtain information about Microsoft Visual Studio and the tools for developing Windows apps, go to [Visual Studio](http://go.microsoft.com/fwlink/?LinkID=532422) + +### Samples + +[CameraFrames](/Samples/CameraFrames) + +### Reference + +### Conceptual + +[Using MediaFrameReader](https://docs.microsoft.com/windows/uwp/audio-video-camera/process-media-frames-with-mediaframereader) + +## System requirements + +**Client:** Windows 10 + +**Phone:** Windows 10 + +## Build the sample + +1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build. +2. Start Microsoft Visual Studio 2017 and select **File** \> **Open** \> **Project/Solution**. +3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then the subfolder for your preferred language (C++, C#, or JavaScript). Double-click the Visual Studio Solution (.sln) file. +4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**. + +## Run the sample + +The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it. + +### Deploying the sample + +- Select Build > Deploy Solution. + +### Deploying and running the sample + +- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging. diff --git a/Samples/CameraOpenCV/cs/CameraOpenCV.csproj b/Samples/CameraOpenCV/cs/CameraOpenCV.csproj new file mode 100644 index 0000000000..2cd3dfa0aa --- /dev/null +++ b/Samples/CameraOpenCV/cs/CameraOpenCV.csproj @@ -0,0 +1,190 @@ + + + + + Debug + x86 + {610027E9-719D-5879-9A8E-23CD07DE0278} + AppContainerExe + Properties + SDKTemplate + CameraOpenCV + en-US + UAP + 10.0.15063.0 + 10.0.15063.0 + 14 + true + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + true + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + true + true + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + true + true + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + true + true + true + + + true + bin\x86\Debug\ + TRACE;DEBUG;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS;CODE_ANALYSIS + ;2008 + full + x86 + false + prompt + true + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + true + true + true + + + + App.xaml.cs + App.xaml + + + MainPage.xaml.cs + MainPage.xaml + + + Properties\AssemblyInfo.cs + + + + + Scenario1_ExampleOperations.xaml + + + + + Designer + + + + + App.xaml + MSBuild:Compile + Designer + + + MainPage.xaml + MSBuild:Compile + Designer + + + Scenario1_ExampleOperations.xaml + MSBuild:Compile + Designer + + + Styles\Styles.xaml + MSBuild:Compile + Designer + + + + + Properties\Default.rd.xml + + + Assets\microsoft-sdk.png + + + Assets\smallTile-sdk.png + + + Assets\splash-sdk.png + + + Assets\squareTile-sdk.png + + + Assets\storeLogo-sdk.png + + + Assets\tile-sdk.png + + + Assets\windows-sdk.png + + + + + {19bf707c-e068-49bc-8df4-0ac5218ebdb8} + OpenCVBridge + + + + + 5.0.0 + + + + 14.0 + + + + \ No newline at end of file diff --git a/Samples/CameraOpenCV/cs/CameraOpenCV.sln b/Samples/CameraOpenCV/cs/CameraOpenCV.sln new file mode 100644 index 0000000000..8fb19847fc --- /dev/null +++ b/Samples/CameraOpenCV/cs/CameraOpenCV.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraOpenCV", "CameraOpenCV.csproj", "{610027E9-719D-5879-9A8E-23CD07DE0278}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenCVBridge", "..\shared\OpenCVBridge\OpenCVBridge.vcxproj", "{B8653F83-E68A-54E6-86B8-D2D1122BF2BB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|ARM.ActiveCfg = Debug|ARM + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|ARM.Build.0 = Debug|ARM + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|ARM.Deploy.0 = Debug|ARM + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|x64.ActiveCfg = Debug|x64 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|x64.Build.0 = Debug|x64 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|x64.Deploy.0 = Debug|x64 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|x86.ActiveCfg = Debug|x86 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|x86.Build.0 = Debug|x86 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Debug|x86.Deploy.0 = Debug|x86 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|ARM.ActiveCfg = Release|ARM + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|ARM.Build.0 = Release|ARM + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|ARM.Deploy.0 = Release|ARM + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|x64.ActiveCfg = Release|x64 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|x64.Build.0 = Release|x64 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|x64.Deploy.0 = Release|x64 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|x86.ActiveCfg = Release|x86 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|x86.Build.0 = Release|x86 + {610027E9-719D-5879-9A8E-23CD07DE0278}.Release|x86.Deploy.0 = Release|x86 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Debug|ARM.ActiveCfg = Debug|ARM + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Debug|ARM.Build.0 = Debug|ARM + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Debug|x64.ActiveCfg = Debug|x64 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Debug|x64.Build.0 = Debug|x64 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Debug|x86.ActiveCfg = Debug|Win32 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Debug|x86.Build.0 = Debug|Win32 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Release|ARM.ActiveCfg = Release|ARM + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Release|ARM.Build.0 = Release|ARM + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Release|x64.ActiveCfg = Release|x64 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Release|x64.Build.0 = Release|x64 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Release|x86.ActiveCfg = Release|Win32 + {B8653F83-E68A-54E6-86B8-D2D1122BF2BB}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/CameraOpenCV/cs/Package.appxmanifest b/Samples/CameraOpenCV/cs/Package.appxmanifest new file mode 100644 index 0000000000..83da07cbb7 --- /dev/null +++ b/Samples/CameraOpenCV/cs/Package.appxmanifest @@ -0,0 +1,43 @@ + + + + + + CameraOpenCV C# Sample + Microsoft Corporation + Assets\StoreLogo-sdk.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CameraOpenCV/cs/SampleConfiguration.cs b/Samples/CameraOpenCV/cs/SampleConfiguration.cs new file mode 100644 index 0000000000..8b2938ef48 --- /dev/null +++ b/Samples/CameraOpenCV/cs/SampleConfiguration.cs @@ -0,0 +1,33 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +using System; +using System.Collections.Generic; +using Windows.UI.Xaml.Controls; + +namespace SDKTemplate +{ + public partial class MainPage : Page + { + public const string FEATURE_NAME = "CameraOpenCV C# Sample"; + + List scenarios = new List + { + new Scenario() { Title="Example Operations", ClassType=typeof(Scenario1_ExampleOperations)}, + }; + } + + public class Scenario + { + public string Title { get; set; } + public Type ClassType { get; set; } + } +} diff --git a/Samples/CameraOpenCV/cs/Scenario1_ExampleOperations.xaml.cs b/Samples/CameraOpenCV/cs/Scenario1_ExampleOperations.xaml.cs new file mode 100644 index 0000000000..4eddcc4f13 --- /dev/null +++ b/Samples/CameraOpenCV/cs/Scenario1_ExampleOperations.xaml.cs @@ -0,0 +1,250 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +using OpenCVBridge; +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Windows.Graphics.Imaging; +using Windows.Media.Capture; +using Windows.Media.Capture.Frames; +using Windows.Media.MediaProperties; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; + +namespace SDKTemplate +{ + /// + /// Scenario that illustrates using OpenCV along with camera frames. + /// + public sealed partial class Scenario1_ExampleOperations : Page + { + private MainPage rootPage; + + private MediaCapture _mediaCapture = null; + private MediaFrameReader _reader = null; + private FrameRenderer _previewRenderer = null; + private FrameRenderer _outputRenderer = null; + + private int _frameCount = 0; + + private const int IMAGE_ROWS = 480; + private const int IMAGE_COLS = 640; + + private OpenCVHelper _helper; + + private DispatcherTimer _FPSTimer = null; + + enum OperationType + { + Blur = 0, + HoughLines, + Contours, + Histogram, + MotionDetector + } + OperationType currentOperation; + + public Scenario1_ExampleOperations() + { + this.InitializeComponent(); + _previewRenderer = new FrameRenderer(PreviewImage); + _outputRenderer = new FrameRenderer(OutputImage); + + _helper = new OpenCVHelper(); + + _FPSTimer = new DispatcherTimer() + { + Interval = TimeSpan.FromSeconds(1) + }; + _FPSTimer.Tick += UpdateFPS; + } + + /// + /// Initializes the MediaCapture object with the given source group. + /// + /// SourceGroup with which to initialize. + private async Task InitializeMediaCaptureAsync(MediaFrameSourceGroup sourceGroup) + { + if (_mediaCapture != null) + { + return; + } + + _mediaCapture = new MediaCapture(); + var settings = new MediaCaptureInitializationSettings() + { + SourceGroup = sourceGroup, + SharingMode = MediaCaptureSharingMode.ExclusiveControl, + StreamingCaptureMode = StreamingCaptureMode.Video, + MemoryPreference = MediaCaptureMemoryPreference.Cpu + }; + await _mediaCapture.InitializeAsync(settings); + } + + /// + /// Unregisters FrameArrived event handlers, stops and disposes frame readers + /// and disposes the MediaCapture object. + /// + private async Task CleanupMediaCaptureAsync() + { + if (_mediaCapture != null) + { + await _reader.StopAsync(); + _reader.FrameArrived -= ColorFrameReader_FrameArrivedAsync; + _reader.Dispose(); + _mediaCapture = null; + } + } + + private void UpdateFPS(object sender, object e) + { + var frameCount = Interlocked.Exchange(ref _frameCount, 0); + this.FPSMonitor.Text = "FPS: " + frameCount; + } + + protected override async void OnNavigatedTo(NavigationEventArgs e) + { + rootPage = MainPage.Current; + + // setting up the combobox, and default operation + OperationComboBox.ItemsSource = Enum.GetValues(typeof(OperationType)); + OperationComboBox.SelectedIndex = 0; + currentOperation = OperationType.Blur; + + // Find the sources + var allGroups = await MediaFrameSourceGroup.FindAllAsync(); + var sourceGroups = allGroups.Select(g => new + { + Group = g, + SourceInfo = g.SourceInfos.FirstOrDefault(i => i.SourceKind == MediaFrameSourceKind.Color) + }).Where(g => g.SourceInfo != null).ToList(); + + if (sourceGroups.Count == 0) + { + // No camera sources found + return; + } + var selectedSource = sourceGroups.FirstOrDefault(); + + // Initialize MediaCapture + try + { + await InitializeMediaCaptureAsync(selectedSource.Group); + } + catch (Exception exception) + { + Debug.WriteLine("MediaCapture initialization error: " + exception.Message); + await CleanupMediaCaptureAsync(); + return; + } + + // Create the frame reader + MediaFrameSource frameSource = _mediaCapture.FrameSources[selectedSource.SourceInfo.Id]; + BitmapSize size = new BitmapSize() // Choose a lower resolution to make the image processing more performant + { + Height = IMAGE_ROWS, + Width = IMAGE_COLS + }; + _reader = await _mediaCapture.CreateFrameReaderAsync(frameSource, MediaEncodingSubtypes.Bgra8, size); + _reader.FrameArrived += ColorFrameReader_FrameArrivedAsync; + await _reader.StartAsync(); + + _FPSTimer.Start(); + } + + protected override async void OnNavigatedFrom(NavigationEventArgs args) + { + _FPSTimer.Stop(); + await CleanupMediaCaptureAsync(); + } + + /// + /// Handles a frame arrived event and renders the frame to the screen. + /// + private void ColorFrameReader_FrameArrivedAsync(MediaFrameReader sender, MediaFrameArrivedEventArgs args) + { + var frame = sender.TryAcquireLatestFrame(); + if (frame != null) + { + SoftwareBitmap originalBitmap = null; + var inputBitmap = frame.VideoMediaFrame?.SoftwareBitmap; + if (inputBitmap != null) + { + // The XAML Image control can only display images in BRGA8 format with premultiplied or no alpha + // The frame reader as configured in this sample gives BGRA8 with straight alpha, so need to convert it + originalBitmap = SoftwareBitmap.Convert(inputBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); + + SoftwareBitmap outputBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, originalBitmap.PixelWidth, originalBitmap.PixelHeight, BitmapAlphaMode.Premultiplied); + + // Operate on the image in the manner chosen by the user. + if (currentOperation == OperationType.Blur) + { + _helper.Blur(originalBitmap, outputBitmap); + } + else if (currentOperation == OperationType.HoughLines) + { + _helper.HoughLines(originalBitmap, outputBitmap); + } + else if (currentOperation == OperationType.Contours) + { + _helper.Contours(originalBitmap, outputBitmap); + } + else if (currentOperation == OperationType.Histogram) + { + _helper.Histogram(originalBitmap, outputBitmap); + } + else if (currentOperation == OperationType.MotionDetector) + { + _helper.MotionDetector(originalBitmap, outputBitmap); + } + + // Display both the original bitmap and the processed bitmap. + _previewRenderer.RenderFrame(originalBitmap); + _outputRenderer.RenderFrame(outputBitmap); + } + + Interlocked.Increment(ref _frameCount); + } + } + + private void OperationComboBox_SelectionChanged(object sender, RoutedEventArgs e) + { + currentOperation = (OperationType)((sender as ComboBox).SelectedItem); + if (OperationType.Blur == currentOperation) + { + this.CurrentOperationTextBlock.Text = "Current: Blur"; + } + else if (OperationType.Contours == currentOperation) + { + this.CurrentOperationTextBlock.Text = "Current: Contours"; + } + else if (OperationType.Histogram == currentOperation) + { + this.CurrentOperationTextBlock.Text = "Current: Histogram of RGB channels"; + } + else if (OperationType.HoughLines == currentOperation) + { + this.CurrentOperationTextBlock.Text = "Current: Line detection"; + } + else if (OperationType.MotionDetector == currentOperation) + { + this.CurrentOperationTextBlock.Text = "Current: Motion detection"; + } + else + { + this.CurrentOperationTextBlock.Text = string.Empty; + } + } + } +} diff --git a/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVBridge.vcxproj b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVBridge.vcxproj new file mode 100644 index 0000000000..ff14ea5527 --- /dev/null +++ b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVBridge.vcxproj @@ -0,0 +1,240 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {13e80ce8-eec1-5369-b63e-e2162a79347f} + WindowsRuntimeComponent + OpenCVBridge + en-US + 14.0 + true + Windows Store + 10.0.15063.0 + 10.0.15063.0 + 10.0 + + + + DynamicLibrary + true + v141 + + + DynamicLibrary + true + v141 + + + DynamicLibrary + true + v141 + + + DynamicLibrary + false + true + v141 + + + DynamicLibrary + false + true + v141 + + + DynamicLibrary + false + true + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + false + + + false + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + + + Console + false + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + + + Console + false + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + + + Console + false + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVBridge.vcxproj.filters b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVBridge.vcxproj.filters new file mode 100644 index 0000000000..1f5baadb93 --- /dev/null +++ b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVBridge.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + 49d7baab-0f46-4431-b9fc-4351a4fb4ef5 + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVHelper.cpp b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVHelper.cpp new file mode 100644 index 0000000000..31dbf2c7c5 --- /dev/null +++ b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVHelper.cpp @@ -0,0 +1,186 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +// OpenCVHelper.cpp + +#include "pch.h" +#include "OpenCVHelper.h" +#include "MemoryBuffer.h" +#include +using namespace Microsoft::WRL; + +using namespace OpenCVBridge; +using namespace Platform; +using namespace Windows::Graphics::Imaging; +using namespace Windows::Storage::Streams; +using namespace Windows::Foundation; + +using namespace cv; + +OpenCVHelper::OpenCVHelper() +{ + pMOG2 = createBackgroundSubtractorMOG2(); +} + +void OpenCVHelper::Blur(SoftwareBitmap^ input, SoftwareBitmap^ output) +{ + Mat inputMat, outputMat; + if (!(TryConvert(input, inputMat) && TryConvert(output, outputMat))) + { + return; + } + + blur(inputMat, outputMat, cv::Size(5, 5)); +} + +void OpenCVHelper::MotionDetector(SoftwareBitmap^ input, SoftwareBitmap^ output) +{ + Mat inputMat, outputMat; + if (!(TryConvert(input, inputMat) && TryConvert(output, outputMat))) + { + return; + } + + pMOG2->apply(inputMat, fgMaskMOG2); + int type = fgMaskMOG2.type(); + Mat temp; + cvtColor(fgMaskMOG2, temp, CV_GRAY2BGRA); + + Mat element = getStructuringElement(MORPH_RECT, cv::Size(3, 3)); + erode(temp, temp, element); + temp.copyTo(outputMat); +} + +void OpenCVHelper::Histogram(SoftwareBitmap^ input, SoftwareBitmap^ output) +{ + Mat inputMat, outputMat; + if (!(TryConvert(input, inputMat) && TryConvert(output, outputMat))) + { + return; + } + + std::vector bgr_planes; + split(inputMat, bgr_planes); + int histSize = 256; + float range[] = { 0, 256 }; + const float* histRange = { range }; + bool uniform = true; bool accumulate = false; + + Mat b_hist, g_hist, r_hist; + calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate); + calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate); + calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate); + int hist_w = outputMat.cols; int hist_h = outputMat.rows; + double bin_w = (double)outputMat.cols / histSize; + + normalize(b_hist, b_hist, 0, outputMat.rows, NORM_MINMAX, -1, Mat()); + normalize(g_hist, g_hist, 0, outputMat.rows, NORM_MINMAX, -1, Mat()); + normalize(r_hist, r_hist, 0, outputMat.rows, NORM_MINMAX, -1, Mat()); + for (int i = 1; i < histSize; i++) + { + int x1 = cvRound(bin_w * (i - 1)); + int x2 = cvRound(bin_w * i); + line(outputMat, cv::Point(x1, hist_h - cvRound(b_hist.at(i - 1))), + cv::Point(x2, hist_h - cvRound(b_hist.at(i))), + Scalar(255, 0, 0, 255), 2, 8, 0); + line(outputMat, cv::Point(x1, hist_h - cvRound(g_hist.at(i - 1))), + cv::Point(x2, hist_h - cvRound(g_hist.at(i))), + Scalar(0, 255, 0, 255), 2, 8, 0); + line(outputMat, cv::Point(x1, hist_h - cvRound(r_hist.at(i - 1))), + cv::Point(x2, hist_h - cvRound(r_hist.at(i))), + Scalar(0, 0, 255, 255), 2, 8, 0); + } +} + +void OpenCVHelper::Contours(SoftwareBitmap^ input, SoftwareBitmap^ output) +{ + Mat inputMat, outputMat; + if (!(TryConvert(input, inputMat) && TryConvert(output, outputMat))) + { + return; + } + + Mat src_gray; + Mat canny_output; + int thresh = 50; + int max_thresh = 255; + std::vector > contours; + std::vector hierarchy; + + cvtColor(inputMat, src_gray, CV_BGRA2GRAY); + blur(src_gray, src_gray, cv::Size(3, 3)); + Canny(src_gray, canny_output, thresh, thresh * 3, 3); + findContours(canny_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0)); + + for (int i = 0; i < contours.size(); i++) + { + drawContours(outputMat, contours, i, Scalar(255, 0, 0, 255), 2, 8, hierarchy, 0); + } +} + +void OpenCVHelper::HoughLines(SoftwareBitmap^ input, SoftwareBitmap^ output) +{ + Mat inputMat, outputMat; + if (!(TryConvert(input, inputMat) && TryConvert(output, outputMat))) + { + return; + } + + inputMat.copyTo(outputMat); + + Mat edges, cdst, src_gray; + cvtColor(inputMat, src_gray, CV_BGRA2GRAY); + Canny(src_gray, edges, 100, 200, 3); + std::vector lines; + HoughLinesP(edges, lines, 1, CV_PI / 180, 50, input->PixelWidth / 4, 10); + for (size_t i = 0; i < lines.size(); i++) + { + Vec4i l = lines[i]; + line(outputMat, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), Scalar(0, 255, 0, 255), 3, CV_AA); + } +} + +bool OpenCVHelper::TryConvert(SoftwareBitmap^ from, Mat& convertedMat) +{ + unsigned char* pPixels = nullptr; + unsigned int capacity = 0; + if (!GetPointerToPixelData(from, &pPixels, &capacity)) + { + return false; + } + + Mat mat(from->PixelHeight, + from->PixelWidth, + CV_8UC4, // assume input SoftwareBitmap is BGRA8 + (void*)pPixels); + + // shallow copy because we want convertedMat.data = pPixels + // don't use .copyTo or .clone + convertedMat = mat; + return true; +} + +bool OpenCVHelper::GetPointerToPixelData(SoftwareBitmap^ bitmap, unsigned char** pPixelData, unsigned int* capacity) +{ + BitmapBuffer^ bmpBuffer = bitmap->LockBuffer(BitmapBufferAccessMode::ReadWrite); + IMemoryBufferReference^ reference = bmpBuffer->CreateReference(); + + ComPtr pBufferByteAccess; + if ((reinterpret_cast(reference)->QueryInterface(IID_PPV_ARGS(&pBufferByteAccess))) != S_OK) + { + return false; + } + + if (pBufferByteAccess->GetBuffer(pPixelData, capacity) != S_OK) + { + return false; + } + return true; +} \ No newline at end of file diff --git a/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVHelper.h b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVHelper.h new file mode 100644 index 0000000000..0c32e8ba60 --- /dev/null +++ b/Samples/CameraOpenCV/shared/OpenCVBridge/OpenCVHelper.h @@ -0,0 +1,52 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* +// OpenCVHelper.h + +#pragma once +#include +#include +#include + +namespace OpenCVBridge +{ + public ref class OpenCVHelper sealed + { + public: + OpenCVHelper(); + + // Image processing operators + void Blur( + Windows::Graphics::Imaging::SoftwareBitmap^ input, + Windows::Graphics::Imaging::SoftwareBitmap^ output); + void HoughLines( + Windows::Graphics::Imaging::SoftwareBitmap^ input, + Windows::Graphics::Imaging::SoftwareBitmap^ output); + void Contours( + Windows::Graphics::Imaging::SoftwareBitmap^ input, + Windows::Graphics::Imaging::SoftwareBitmap^ output); + void Histogram( + Windows::Graphics::Imaging::SoftwareBitmap^ input, + Windows::Graphics::Imaging::SoftwareBitmap^ output); + void MotionDetector( + Windows::Graphics::Imaging::SoftwareBitmap^ input, + Windows::Graphics::Imaging::SoftwareBitmap^ output); + private: + // used only for the background subtraction operation + cv::Mat fgMaskMOG2; + cv::Ptr pMOG2; + + // helper functions for getting a cv::Mat from SoftwareBitmap + bool GetPointerToPixelData(Windows::Graphics::Imaging::SoftwareBitmap^ bitmap, + unsigned char** pPixelData, unsigned int* capacity); + + bool TryConvert(Windows::Graphics::Imaging::SoftwareBitmap^ from, cv::Mat& convertedMat); + }; +} diff --git a/Samples/CameraOpenCV/shared/OpenCVBridge/packages.config b/Samples/CameraOpenCV/shared/OpenCVBridge/packages.config new file mode 100644 index 0000000000..fb219ce385 --- /dev/null +++ b/Samples/CameraOpenCV/shared/OpenCVBridge/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Samples/CameraOpenCV/shared/OpenCVBridge/pch.cpp b/Samples/CameraOpenCV/shared/OpenCVBridge/pch.cpp new file mode 100644 index 0000000000..bcb5590be1 --- /dev/null +++ b/Samples/CameraOpenCV/shared/OpenCVBridge/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/Samples/CameraOpenCV/shared/OpenCVBridge/pch.h b/Samples/CameraOpenCV/shared/OpenCVBridge/pch.h new file mode 100644 index 0000000000..10fe677c72 --- /dev/null +++ b/Samples/CameraOpenCV/shared/OpenCVBridge/pch.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include diff --git a/Samples/CameraOpenCV/shared/Scenario1_ExampleOperations.xaml b/Samples/CameraOpenCV/shared/Scenario1_ExampleOperations.xaml new file mode 100644 index 0000000000..9265937670 --- /dev/null +++ b/Samples/CameraOpenCV/shared/Scenario1_ExampleOperations.xaml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + Shows the output of various OpenCV operations + + Current: Blur + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CameraProfile/cpp/CameraProfile.sln b/Samples/CameraProfile/cpp/CameraProfile.sln index 9df3fd597a..5c6fe81f77 100644 --- a/Samples/CameraProfile/cpp/CameraProfile.sln +++ b/Samples/CameraProfile/cpp/CameraProfile.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraProfile", "CameraProfile.vcxproj", "{4F09DC87-8032-5DE1-9719-AAFC2AE588A7}" EndProject diff --git a/Samples/CameraProfile/cs/CameraProfile.sln b/Samples/CameraProfile/cs/CameraProfile.sln index 447662bb83..3dd3339604 100644 --- a/Samples/CameraProfile/cs/CameraProfile.sln +++ b/Samples/CameraProfile/cs/CameraProfile.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraProfile", "CameraProfile.csproj", "{1A48FCD6-D232-5980-9F91-B02F5ED0E4F8}" EndProject diff --git a/Samples/CameraProfile/js/CameraProfile.sln b/Samples/CameraProfile/js/CameraProfile.sln index 540ec3c90f..eb873fd0cd 100644 --- a/Samples/CameraProfile/js/CameraProfile.sln +++ b/Samples/CameraProfile/js/CameraProfile.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22821.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CameraProfile", "CameraProfile.jsproj", "{D585FB63-963A-50E6-A876-651C0C09CF0D}" EndProject diff --git a/Samples/CameraResolution/cpp/CameraResolution.sln b/Samples/CameraResolution/cpp/CameraResolution.sln index ab006ec5f6..c1fc99953e 100644 --- a/Samples/CameraResolution/cpp/CameraResolution.sln +++ b/Samples/CameraResolution/cpp/CameraResolution.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{65CFCD43-DEE5-43F7-833F-CE9BDCDE5471}") = "CameraResolution", "CameraResolution.vcxproj", "{1F8637EE-0143-5348-9DB9-D79ACB323394}" EndProject diff --git a/Samples/CameraResolution/cs/CameraResolution.sln b/Samples/CameraResolution/cs/CameraResolution.sln index 4daddf188b..d3f881869e 100644 --- a/Samples/CameraResolution/cs/CameraResolution.sln +++ b/Samples/CameraResolution/cs/CameraResolution.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22529.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraResolution", "CameraResolution.csproj", "{3D191E1E-1898-5730-9350-5072CAAF9DA0}" EndProject diff --git a/Samples/CameraResolution/js/CameraResolution.sln b/Samples/CameraResolution/js/CameraResolution.sln index feb0b71d85..baef42cfd8 100644 --- a/Samples/CameraResolution/js/CameraResolution.sln +++ b/Samples/CameraResolution/js/CameraResolution.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22821.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{09235B5C-7164-4BDA-8171-273D49B8B291}") = "CameraResolution", "CameraResolution.jsproj", "{708D9710-567E-5B80-A1DA-427DC8E6CA07}" EndProject diff --git a/Samples/CameraStarterKit/cpp/CameraStarterKit.sln b/Samples/CameraStarterKit/cpp/CameraStarterKit.sln index 7d87d147c9..0c6659ec1e 100644 --- a/Samples/CameraStarterKit/cpp/CameraStarterKit.sln +++ b/Samples/CameraStarterKit/cpp/CameraStarterKit.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraStarterKit", "CameraStarterKit.vcxproj", "{F0310BBC-5644-534E-AAD5-C72E5C2C384B}" EndProject diff --git a/Samples/CameraStarterKit/cs/CameraStarterKit.sln b/Samples/CameraStarterKit/cs/CameraStarterKit.sln index 2f5f3db5ff..8086ed5a81 100644 --- a/Samples/CameraStarterKit/cs/CameraStarterKit.sln +++ b/Samples/CameraStarterKit/cs/CameraStarterKit.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraStarterKit", "CameraStarterKit.csproj", "{E9E935F5-8157-5080-8368-F5EEF8E2E28F}" EndProject diff --git a/Samples/CameraStarterKit/js/CameraStarterKit.sln b/Samples/CameraStarterKit/js/CameraStarterKit.sln index a351a8e233..b11b874d90 100644 --- a/Samples/CameraStarterKit/js/CameraStarterKit.sln +++ b/Samples/CameraStarterKit/js/CameraStarterKit.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CameraStarterKit", "CameraStarterKit.jsproj", "{C610D8B4-DC54-535A-A3DA-A6A8036DC1DA}" EndProject diff --git a/Samples/CameraStarterKit/vb/CameraStarterKit.sln b/Samples/CameraStarterKit/vb/CameraStarterKit.sln index de4b8a9092..39683e7021 100644 --- a/Samples/CameraStarterKit/vb/CameraStarterKit.sln +++ b/Samples/CameraStarterKit/vb/CameraStarterKit.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CameraStarterKit", "CameraStarterKit.vbproj", "{0F42FC13-AC57-5F1F-A378-7FD3E872ACE5}" EndProject diff --git a/Samples/CameraStreamCorrelation/cpp/CameraStreamCorrelation.sln b/Samples/CameraStreamCorrelation/cpp/CameraStreamCorrelation.sln index f46da95216..19735c13b2 100644 --- a/Samples/CameraStreamCorrelation/cpp/CameraStreamCorrelation.sln +++ b/Samples/CameraStreamCorrelation/cpp/CameraStreamCorrelation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraStreamCorrelation", "CameraStreamCorrelation.vcxproj", "{5D0B26EA-0EAA-5F30-B4D5-2C7516C66FFB}" EndProject diff --git a/Samples/CameraVideoStabilization/cpp/CameraVideoStabilization.sln b/Samples/CameraVideoStabilization/cpp/CameraVideoStabilization.sln index 73b928ad1f..f399ac0a5c 100644 --- a/Samples/CameraVideoStabilization/cpp/CameraVideoStabilization.sln +++ b/Samples/CameraVideoStabilization/cpp/CameraVideoStabilization.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraVideoStabilization", "CameraVideoStabilization.vcxproj", "{9949119A-40C4-5D55-91D2-D4050DCC9596}" EndProject diff --git a/Samples/CameraVideoStabilization/cs/CameraVideoStabilization.sln b/Samples/CameraVideoStabilization/cs/CameraVideoStabilization.sln index fd7ac943aa..de9dc3352a 100644 --- a/Samples/CameraVideoStabilization/cs/CameraVideoStabilization.sln +++ b/Samples/CameraVideoStabilization/cs/CameraVideoStabilization.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraVideoStabilization", "CameraVideoStabilization.csproj", "{1624A976-E79B-50D9-AD87-61952C3BC114}" EndProject diff --git a/Samples/CameraVideoStabilization/js/CameraVideoStabilization.sln b/Samples/CameraVideoStabilization/js/CameraVideoStabilization.sln index e097b0b3e5..6ced9e43ad 100644 --- a/Samples/CameraVideoStabilization/js/CameraVideoStabilization.sln +++ b/Samples/CameraVideoStabilization/js/CameraVideoStabilization.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CameraVideoStabilization", "CameraVideoStabilization.jsproj", "{2B71C1C1-D8DE-54CF-B4BA-578E01881BDC}" EndProject diff --git a/Samples/CameraVideoStabilization/vb/CameraVideoStabilization.sln b/Samples/CameraVideoStabilization/vb/CameraVideoStabilization.sln index 3613b43d63..26862bddfe 100644 --- a/Samples/CameraVideoStabilization/vb/CameraVideoStabilization.sln +++ b/Samples/CameraVideoStabilization/vb/CameraVideoStabilization.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CameraVideoStabilization", "CameraVideoStabilization.vbproj", "{E31E6A6C-BC3B-5E5A-8E7A-D5ADC5E65B8C}" EndProject diff --git a/Samples/CashDrawer/cpp/CashDrawer.sln b/Samples/CashDrawer/cpp/CashDrawer.sln index d57f63f415..95091b198f 100644 --- a/Samples/CashDrawer/cpp/CashDrawer.sln +++ b/Samples/CashDrawer/cpp/CashDrawer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CashDrawer", "CashDrawer.vcxproj", "{2D18D3D3-DCFF-5E42-817B-1AD0E5D3ED40}" EndProject diff --git a/Samples/CashDrawer/cs/CashDrawer.sln b/Samples/CashDrawer/cs/CashDrawer.sln index 6718f234ba..d5a4228f49 100644 --- a/Samples/CashDrawer/cs/CashDrawer.sln +++ b/Samples/CashDrawer/cs/CashDrawer.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CashDrawer", "CashDrawer.csproj", "{64C5F129-24C9-5920-B23B-AFABE7F18C42}" EndProject diff --git a/Samples/CashDrawer/js/CashDrawer.sln b/Samples/CashDrawer/js/CashDrawer.sln index 6ff0195d79..abf3ede48e 100644 --- a/Samples/CashDrawer/js/CashDrawer.sln +++ b/Samples/CashDrawer/js/CashDrawer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CashDrawer", "CashDrawer.jsproj", "{CA8B4106-159C-576A-8BB7-8BE24D59AACC}" EndProject diff --git a/Samples/CashDrawer/vb/CashDrawer.sln b/Samples/CashDrawer/vb/CashDrawer.sln index 85c93f5c83..2559f7fda8 100644 --- a/Samples/CashDrawer/vb/CashDrawer.sln +++ b/Samples/CashDrawer/vb/CashDrawer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CashDrawer", "CashDrawer.vbproj", "{97683790-3CA5-5EB5-A54F-4704C8A12131}" EndProject diff --git a/Samples/ClientDeviceInformation/cpp/ClientDeviceInformation.sln b/Samples/ClientDeviceInformation/cpp/ClientDeviceInformation.sln index dbb4c69f99..404ad0cebe 100644 --- a/Samples/ClientDeviceInformation/cpp/ClientDeviceInformation.sln +++ b/Samples/ClientDeviceInformation/cpp/ClientDeviceInformation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClientDeviceInformation", "ClientDeviceInformation.vcxproj", "{6D11B565-6AC3-5291-B8A9-44AC109D96E5}" EndProject diff --git a/Samples/ClientDeviceInformation/cs/ClientDeviceInformation.sln b/Samples/ClientDeviceInformation/cs/ClientDeviceInformation.sln index 1542ae39b8..df54233717 100644 --- a/Samples/ClientDeviceInformation/cs/ClientDeviceInformation.sln +++ b/Samples/ClientDeviceInformation/cs/ClientDeviceInformation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientDeviceInformation", "ClientDeviceInformation.csproj", "{702D3687-9CF4-5B6F-BC94-7AA0183288A6}" EndProject diff --git a/Samples/ClientDeviceInformation/js/ClientDeviceInformation.sln b/Samples/ClientDeviceInformation/js/ClientDeviceInformation.sln index 898caa3af5..e89f891839 100644 --- a/Samples/ClientDeviceInformation/js/ClientDeviceInformation.sln +++ b/Samples/ClientDeviceInformation/js/ClientDeviceInformation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "ClientDeviceInformation", "ClientDeviceInformation.jsproj", "{530D6147-C136-56B2-953C-F69637C2DE77}" EndProject diff --git a/Samples/Clipboard/cpp/Clipboard.sln b/Samples/Clipboard/cpp/Clipboard.sln index be7c9336c7..b5cac5bb30 100644 --- a/Samples/Clipboard/cpp/Clipboard.sln +++ b/Samples/Clipboard/cpp/Clipboard.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Clipboard", "Clipboard.vcxproj", "{949A5CE3-96E7-51C4-8545-E90E353DF8FB}" EndProject diff --git a/Samples/Clipboard/cs/Clipboard.sln b/Samples/Clipboard/cs/Clipboard.sln index d2a8eac982..7113a2a129 100644 --- a/Samples/Clipboard/cs/Clipboard.sln +++ b/Samples/Clipboard/cs/Clipboard.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Clipboard", "Clipboard.csproj", "{494AC2A2-5BF6-557F-A65C-313757132904}" EndProject diff --git a/Samples/Clipboard/js/Clipboard.sln b/Samples/Clipboard/js/Clipboard.sln index b7aed31fe8..6fb79597e9 100644 --- a/Samples/Clipboard/js/Clipboard.sln +++ b/Samples/Clipboard/js/Clipboard.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Clipboard", "Clipboard.jsproj", "{C2CF8C83-8718-5332-ABC6-D70DD14A47BC}" EndProject diff --git a/Samples/Clipboard/vb/Clipboard.sln b/Samples/Clipboard/vb/Clipboard.sln index 61a731f403..d292585a3f 100644 --- a/Samples/Clipboard/vb/Clipboard.sln +++ b/Samples/Clipboard/vb/Clipboard.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Clipboard", "Clipboard.vbproj", "{C4D0495E-5160-5926-A30A-74261669CD84}" EndProject diff --git a/Samples/CommunicationBlockAndFilter/cs/BlockAndFilter.sln b/Samples/CommunicationBlockAndFilter/cs/BlockAndFilter.sln index 03376d14d5..17afe1e0e3 100755 --- a/Samples/CommunicationBlockAndFilter/cs/BlockAndFilter.sln +++ b/Samples/CommunicationBlockAndFilter/cs/BlockAndFilter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlockAndFilter", "BlockAndFilter.csproj", "{139C5776-4BBF-5A31-9200-68E0ED67B186}" EndProject diff --git a/Samples/Compass/cpp/Compass.sln b/Samples/Compass/cpp/Compass.sln index 2dc7885759..58963b8641 100644 --- a/Samples/Compass/cpp/Compass.sln +++ b/Samples/Compass/cpp/Compass.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Compass", "Compass.vcxproj", "{AED7E536-5F80-5FDD-A5BD-15186212FDB8}" EndProject diff --git a/Samples/Compass/cs/Compass.sln b/Samples/Compass/cs/Compass.sln index 8585cfaa9c..d3837e3026 100644 --- a/Samples/Compass/cs/Compass.sln +++ b/Samples/Compass/cs/Compass.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compass", "Compass.csproj", "{1A4C9183-A064-55A3-AFE2-208AD51A4196}" EndProject diff --git a/Samples/Compass/js/Compass.sln b/Samples/Compass/js/Compass.sln index 20aea31c3a..ecefa1b66a 100644 --- a/Samples/Compass/js/Compass.sln +++ b/Samples/Compass/js/Compass.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Compass", "Compass.jsproj", "{35A9BDE3-7E12-5AC6-B414-B7203829A4E5}" EndProject diff --git a/Samples/Compass/vb/Compass.sln b/Samples/Compass/vb/Compass.sln index d4cafc54fe..9163a15307 100644 --- a/Samples/Compass/vb/Compass.sln +++ b/Samples/Compass/vb/Compass.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Compass", "Compass.vbproj", "{085F07D5-531E-5D79-AE2C-C7A662F824F5}" EndProject diff --git a/Samples/ComplexInk/cpp/ComplexInk.sln b/Samples/ComplexInk/cpp/ComplexInk.sln index 00eb897504..3e284a8d69 100644 --- a/Samples/ComplexInk/cpp/ComplexInk.sln +++ b/Samples/ComplexInk/cpp/ComplexInk.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ComplexInk", "ComplexInk.vcxproj", "{3EEAD6BB-34BC-5991-9772-ED3BF3991F53}" EndProject diff --git a/Samples/CompositionVisual/cpp/CompositionVisual.sln b/Samples/CompositionVisual/cpp/CompositionVisual.sln index d38e1e4251..13f13d3d2d 100644 --- a/Samples/CompositionVisual/cpp/CompositionVisual.sln +++ b/Samples/CompositionVisual/cpp/CompositionVisual.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CompositionVisual", "CompositionVisual.vcxproj", "{F2F381E5-A8FC-5730-9A16-44C284D44417}" EndProject diff --git a/Samples/CompositionVisual/cs/CompositionVisual.sln b/Samples/CompositionVisual/cs/CompositionVisual.sln index 31f6419821..7e5942f53a 100644 --- a/Samples/CompositionVisual/cs/CompositionVisual.sln +++ b/Samples/CompositionVisual/cs/CompositionVisual.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompositionVisual", "CompositionVisual.csproj", "{14AB7E5E-B6D6-555B-8A09-70F7A8DD8A8F}" EndProject diff --git a/Samples/CompositionVisual/vb/CompositionVisual.sln b/Samples/CompositionVisual/vb/CompositionVisual.sln index 35cb411538..389c2b04e6 100644 --- a/Samples/CompositionVisual/vb/CompositionVisual.sln +++ b/Samples/CompositionVisual/vb/CompositionVisual.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "CompositionVisual", "CompositionVisual.vbproj", "{F2F32BA6-AB3D-5513-A554-BBA14A695AE6}" EndProject diff --git a/Samples/Compression/cpp/Compression.sln b/Samples/Compression/cpp/Compression.sln index 30a14193c7..14d4b541d5 100644 --- a/Samples/Compression/cpp/Compression.sln +++ b/Samples/Compression/cpp/Compression.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.2222512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Compression", "Compression.vcxproj", "{5B81B719-41E2-5A7A-A8D8-7A4FA06FF5FC}" EndProject diff --git a/Samples/Compression/cs/Compression.sln b/Samples/Compression/cs/Compression.sln index f1fbc78e13..e12c51008a 100644 --- a/Samples/Compression/cs/Compression.sln +++ b/Samples/Compression/cs/Compression.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compression", "Compression.csproj", "{0F1BA47D-5DF9-5158-9832-1C9F0BF675BA}" EndProject diff --git a/Samples/Compression/js/Compression.sln b/Samples/Compression/js/Compression.sln index f0641a508a..5cf72f2cde 100644 --- a/Samples/Compression/js/Compression.sln +++ b/Samples/Compression/js/Compression.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Compression", "Compression.jsproj", "{9A300D5E-C3D3-5320-9E10-F1E31B1B9E74}" EndProject diff --git a/Samples/ContactCardIntegration/cs/ContactCardIntegration.sln b/Samples/ContactCardIntegration/cs/ContactCardIntegration.sln index 8094e4462a..01f099eaa2 100644 --- a/Samples/ContactCardIntegration/cs/ContactCardIntegration.sln +++ b/Samples/ContactCardIntegration/cs/ContactCardIntegration.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContactCardIntegration", "ContactCardIntegration.csproj", "{D0C712ED-C9D1-507D-8BC6-08780692E86E}" EndProject diff --git a/Samples/ContactCards/cpp/ContactCards.sln b/Samples/ContactCards/cpp/ContactCards.sln index 62de5791c8..1bed80faa5 100644 --- a/Samples/ContactCards/cpp/ContactCards.sln +++ b/Samples/ContactCards/cpp/ContactCards.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ContactCards", "ContactCards.vcxproj", "{31A6B3E6-F89E-517C-B835-155B65AD0900}" EndProject diff --git a/Samples/ContactCards/cs/ContactCards.sln b/Samples/ContactCards/cs/ContactCards.sln index e0a43e1b49..e88a41442f 100644 --- a/Samples/ContactCards/cs/ContactCards.sln +++ b/Samples/ContactCards/cs/ContactCards.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContactCards", "ContactCards.csproj", "{16BF4EF9-4C5B-5835-A66C-9824047A5563}" EndProject diff --git a/Samples/ContactCards/js/ContactCards.sln b/Samples/ContactCards/js/ContactCards.sln index e5270ff064..d267294ec8 100644 --- a/Samples/ContactCards/js/ContactCards.sln +++ b/Samples/ContactCards/js/ContactCards.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "ContactCards", "ContactCards.jsproj", "{C295AE04-562F-5877-BC27-A4D0B7A4FEE0}" EndProject diff --git a/Samples/ContactPicker/cpp/ContactPicker.sln b/Samples/ContactPicker/cpp/ContactPicker.sln index 6429eafe89..26b889f25a 100644 --- a/Samples/ContactPicker/cpp/ContactPicker.sln +++ b/Samples/ContactPicker/cpp/ContactPicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ContactPicker", "ContactPicker.vcxproj", "{EA350320-71F1-54C7-8E80-3FF4D6D979A5}" EndProject diff --git a/Samples/ContactPicker/cs/ContactPicker.sln b/Samples/ContactPicker/cs/ContactPicker.sln index c047ccf5ac..68919320c2 100644 --- a/Samples/ContactPicker/cs/ContactPicker.sln +++ b/Samples/ContactPicker/cs/ContactPicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContactPicker", "ContactPicker.csproj", "{0261D0DD-EBAB-5CC5-B015-57887AE78917}" EndProject diff --git a/Samples/ContactPicker/js/ContactPicker.sln b/Samples/ContactPicker/js/ContactPicker.sln index 9cc6a13329..9a71c7cd88 100644 --- a/Samples/ContactPicker/js/ContactPicker.sln +++ b/Samples/ContactPicker/js/ContactPicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "ContactPicker", "ContactPicker.jsproj", "{46312DFC-E223-5A22-837E-DDE8D66E56D6}" EndProject diff --git a/Samples/ContentIndexer/cpp/ContentIndexer.sln b/Samples/ContentIndexer/cpp/ContentIndexer.sln index 96d796a2b7..3c7c56a03d 100644 --- a/Samples/ContentIndexer/cpp/ContentIndexer.sln +++ b/Samples/ContentIndexer/cpp/ContentIndexer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ContentIndexer", "ContentIndexer.vcxproj", "{E931FFCE-D7B3-589B-84E3-0863E15ECBD8}" EndProject diff --git a/Samples/ContentIndexer/cs/ContentIndexer.sln b/Samples/ContentIndexer/cs/ContentIndexer.sln index 7ea6974905..6a5de63a77 100644 --- a/Samples/ContentIndexer/cs/ContentIndexer.sln +++ b/Samples/ContentIndexer/cs/ContentIndexer.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContentIndexer", "ContentIndexer.csproj", "{55A577C0-3EF8-5FA1-AF88-6E6A3E86F3F8}" EndProject diff --git a/Samples/ContentIndexer/js/ContentIndexer.sln b/Samples/ContentIndexer/js/ContentIndexer.sln index ce41532a9d..b5b25a5377 100644 --- a/Samples/ContentIndexer/js/ContentIndexer.sln +++ b/Samples/ContentIndexer/js/ContentIndexer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "ContentIndexer", "ContentIndexer.jsproj", "{E8C5C6E5-6659-54C5-8F4C-7011B619A516}" EndProject diff --git a/Samples/ContextMenu/cpp/ContextMenu.sln b/Samples/ContextMenu/cpp/ContextMenu.sln index a99924e675..4ca3b269b5 100644 --- a/Samples/ContextMenu/cpp/ContextMenu.sln +++ b/Samples/ContextMenu/cpp/ContextMenu.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ContextMenu", "ContextMenu.vcxproj", "{08F00C68-282C-563E-825A-431098D9620B}" EndProject diff --git a/Samples/ContextMenu/cs/ContextMenu.sln b/Samples/ContextMenu/cs/ContextMenu.sln index 68fa8d7d98..6ce636f6ae 100644 --- a/Samples/ContextMenu/cs/ContextMenu.sln +++ b/Samples/ContextMenu/cs/ContextMenu.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContextMenu", "ContextMenu.csproj", "{BA3E55CA-24BC-5620-AE60-27917B77A88A}" EndProject diff --git a/Samples/ContextMenu/js/ContextMenu.sln b/Samples/ContextMenu/js/ContextMenu.sln index b33e340b49..3066719d49 100644 --- a/Samples/ContextMenu/js/ContextMenu.sln +++ b/Samples/ContextMenu/js/ContextMenu.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "ContextMenu", "ContextMenu.jsproj", "{EFA928B0-5A1F-546F-8397-68FD9CB5A95E}" EndProject diff --git a/Samples/CortanaVoiceCommand/cpp/AdventureWorks.sln b/Samples/CortanaVoiceCommand/cpp/AdventureWorks.sln index ad334d4a19..ef77a0a9b4 100644 --- a/Samples/CortanaVoiceCommand/cpp/AdventureWorks.sln +++ b/Samples/CortanaVoiceCommand/cpp/AdventureWorks.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdventureWorks", "AdventureWorks\AdventureWorks.vcxproj", "{D4E12206-D88F-5D12-B352-CFFF6675E8EA}" EndProject diff --git a/Samples/CortanaVoiceCommand/cs/AdventureWorks.sln b/Samples/CortanaVoiceCommand/cs/AdventureWorks.sln index f8c740b162..58ed12e818 100644 --- a/Samples/CortanaVoiceCommand/cs/AdventureWorks.sln +++ b/Samples/CortanaVoiceCommand/cs/AdventureWorks.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdventureWorks", "AdventureWorks\AdventureWorks.csproj", "{5CC88409-4AC4-5214-9210-8CA5D414B54F}" EndProject diff --git a/Samples/CortanaVoiceCommand/js/AdventureWorks.sln b/Samples/CortanaVoiceCommand/js/AdventureWorks.sln index 53e7070e40..f6a36b3dbf 100644 --- a/Samples/CortanaVoiceCommand/js/AdventureWorks.sln +++ b/Samples/CortanaVoiceCommand/js/AdventureWorks.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23020.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AdventureWorks", "AdventureWorks\AdventureWorks.jsproj", "{2B6EE8D2-DE75-5030-A4E8-D795DBC159A2}" EndProject diff --git a/Samples/CredentialPicker/cpp/CredentialPicker.sln b/Samples/CredentialPicker/cpp/CredentialPicker.sln index 5c6948291a..bc62c9a712 100644 --- a/Samples/CredentialPicker/cpp/CredentialPicker.sln +++ b/Samples/CredentialPicker/cpp/CredentialPicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CredentialPicker", "CredentialPicker.vcxproj", "{6554A04C-2C72-51DF-ABF6-450840030918}" EndProject diff --git a/Samples/CredentialPicker/cs/CredentialPicker.sln b/Samples/CredentialPicker/cs/CredentialPicker.sln index e66b71ee9f..cb7575f703 100644 --- a/Samples/CredentialPicker/cs/CredentialPicker.sln +++ b/Samples/CredentialPicker/cs/CredentialPicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CredentialPicker", "CredentialPicker.csproj", "{FB1D85E7-AC0E-5479-8FF1-7ACEF7CE9346}" EndProject diff --git a/Samples/CredentialPicker/js/CredentialPicker.sln b/Samples/CredentialPicker/js/CredentialPicker.sln index bb61f88e83..8e501ecbf1 100644 --- a/Samples/CredentialPicker/js/CredentialPicker.sln +++ b/Samples/CredentialPicker/js/CredentialPicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CredentialPicker", "CredentialPicker.jsproj", "{BAC4CD2A-72BE-5A01-8AAE-2D3DBA2EB627}" EndProject diff --git a/Samples/CustomEditControl/cs/CustomEditControl.sln b/Samples/CustomEditControl/cs/CustomEditControl.sln index 8807038ee0..66f63b089b 100644 --- a/Samples/CustomEditControl/cs/CustomEditControl.sln +++ b/Samples/CustomEditControl/cs/CustomEditControl.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomEditControl", "CustomEditControl.csproj", "{F627CD06-9B7F-564B-AAE5-26CE53EF53F2}" EndProject diff --git a/Samples/CustomHidDeviceAccess/cpp/CustomHidDeviceAccess.sln b/Samples/CustomHidDeviceAccess/cpp/CustomHidDeviceAccess.sln index b3e50d9dc7..73015facbd 100644 --- a/Samples/CustomHidDeviceAccess/cpp/CustomHidDeviceAccess.sln +++ b/Samples/CustomHidDeviceAccess/cpp/CustomHidDeviceAccess.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomHidDeviceAccess", "CustomHidDeviceAccess.vcxproj", "{377CB2B0-A886-5991-86B8-6453B15B922F}" EndProject diff --git a/Samples/CustomHidDeviceAccess/cs/CustomHidDeviceAccess.sln b/Samples/CustomHidDeviceAccess/cs/CustomHidDeviceAccess.sln index d00e6309d4..2c0e4df07b 100644 --- a/Samples/CustomHidDeviceAccess/cs/CustomHidDeviceAccess.sln +++ b/Samples/CustomHidDeviceAccess/cs/CustomHidDeviceAccess.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomHidDeviceAccess", "CustomHidDeviceAccess.csproj", "{48E35013-BF77-5753-89B0-CB23CF7062E5}" EndProject diff --git a/Samples/CustomSensors/cpp/CustomSensors.sln b/Samples/CustomSensors/cpp/CustomSensors.sln index f24b9842cd..5178b72be6 100644 --- a/Samples/CustomSensors/cpp/CustomSensors.sln +++ b/Samples/CustomSensors/cpp/CustomSensors.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomSensors", "CustomSensors.vcxproj", "{7D2C0D78-4FD1-550C-BE02-BB2AEC23891F}" EndProject diff --git a/Samples/CustomSensors/cs/CustomSensors.sln b/Samples/CustomSensors/cs/CustomSensors.sln index e5dfa4b16f..8f848c3729 100644 --- a/Samples/CustomSensors/cs/CustomSensors.sln +++ b/Samples/CustomSensors/cs/CustomSensors.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSensors", "CustomSensors.csproj", "{AF3C3182-556C-5BA0-8B4D-7870ECC61FEB}" EndProject diff --git a/Samples/CustomSensors/js/CustomSensor.sln b/Samples/CustomSensors/js/CustomSensor.sln index 57541c90a6..36f26b7c88 100644 --- a/Samples/CustomSensors/js/CustomSensor.sln +++ b/Samples/CustomSensors/js/CustomSensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CustomSensor", "CustomSensor.jsproj", "{48A6EB55-703E-56AF-8570-8EA67EB19F0B}" EndProject diff --git a/Samples/CustomSerialDeviceAccess/cs/CustomSerialDeviceAccess.sln b/Samples/CustomSerialDeviceAccess/cs/CustomSerialDeviceAccess.sln index 258eb750ef..1e48d4049e 100644 --- a/Samples/CustomSerialDeviceAccess/cs/CustomSerialDeviceAccess.sln +++ b/Samples/CustomSerialDeviceAccess/cs/CustomSerialDeviceAccess.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSerialDeviceAccess", "CustomSerialDeviceAccess.csproj", "{AFD4120E-2ECE-5323-B8D8-675419D9A052}" EndProject diff --git a/Samples/CustomSerialDeviceAccess/js/CustomSerialDeviceAccess.sln b/Samples/CustomSerialDeviceAccess/js/CustomSerialDeviceAccess.sln index e7adeb8bab..176f27f36f 100644 --- a/Samples/CustomSerialDeviceAccess/js/CustomSerialDeviceAccess.sln +++ b/Samples/CustomSerialDeviceAccess/js/CustomSerialDeviceAccess.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22724.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CustomSerialDeviceAccess", "CustomSerialDeviceAccess.jsproj", "{75054C62-9AE8-5AE1-A395-38D8BF3DFCD7}" EndProject diff --git a/Samples/CustomUsbDeviceAccess/cs/CustomUsbDeviceAccess.sln b/Samples/CustomUsbDeviceAccess/cs/CustomUsbDeviceAccess.sln index cfcb1fd121..36d296389d 100644 --- a/Samples/CustomUsbDeviceAccess/cs/CustomUsbDeviceAccess.sln +++ b/Samples/CustomUsbDeviceAccess/cs/CustomUsbDeviceAccess.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22724.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomUsbDeviceAccess", "CustomUsbDeviceAccess.csproj", "{B9983D44-E19A-5CD5-B7BF-930BDF99E7F9}" EndProject diff --git a/Samples/CustomUsbDeviceAccess/js/CustomUsbDeviceAccess.sln b/Samples/CustomUsbDeviceAccess/js/CustomUsbDeviceAccess.sln index 1b073f4b34..45156c0b2c 100644 --- a/Samples/CustomUsbDeviceAccess/js/CustomUsbDeviceAccess.sln +++ b/Samples/CustomUsbDeviceAccess/js/CustomUsbDeviceAccess.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22724.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "CustomUsbDeviceAccess", "CustomUsbDeviceAccess.jsproj", "{87B99672-D20B-5504-8EBA-EBDFE669C75E}" EndProject diff --git a/Samples/D2DAdvancedColorImages/README.md b/Samples/D2DAdvancedColorImages/README.md new file mode 100644 index 0000000000..d4c7c21671 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/README.md @@ -0,0 +1,112 @@ + + +# Direct2D advanced color image rendering sample + +Shows how to use [Direct2D](http://msdn.microsoft.com/library/windows/desktop/dd370990) to load and draw advanced color images. + +> **Note:** This sample is part of a large collection of UWP feature samples. +> If you are unfamiliar with Git and GitHub, you can download the entire collection as a +> [ZIP file](https://github.com/Microsoft/Windows-universal-samples/archive/master.zip), but be +> sure to unzip everything to access shared dependencies. For more info on working with the ZIP file, +> the samples collection, and GitHub, see [Get the UWP samples from GitHub](https://aka.ms/ovu2uq). +> For more samples, see the [Samples portal](https://aka.ms/winsamples) on the Windows Dev Center. + +Specifically, this sample shows how to: + +- Create and configure an advanced color (FP16) DirectX render pipeline. +- Load a JPEG XR containing extended-range floating point data from the disk and decode it with WIC. +- Use Direct2D's effect pipeline to correctly handle an attached ICC profile. +- Implement a custom Direct2D image effect to perform HDR-to-SDR tone mapping, so that HDR images can be rendered in higher quality on SDR displays. +- Use DXGI to retrieve display color capabilities and determine whether tone mapping should be applied. + +## Sample project files + +The sample's project files fall into the following categories. + +### Sample-specific files +The following files form the main educational content of the sample: + +- **DirectXPage.xaml/.cpp/.h/:** Implements a XAML-based UI to drive the app. Hosts the DirectX content in a SwapChainPanel. +- **App.xaml/.cpp/.h:** The app's main entry point. +- **D2DAdvancedColorImagesRenderer.cpp/.h:** The core implementation of the Direct2D scene. + +### DirectX SDK sample common files +The following files provide common functionality needed by DirectX SDK samples: + +- **DeviceResources.cpp/.h:** Manages creation and lifetime of the core Direct3D and Direct2D device-dependent resources. Handles cases such as device lost and window size and orientation changes. +- **DirectXHelper.h:** Common inline helper functions, including ThrowIfFailed which converts HRESULT-based APIs into an exception model. + +All DirectX SDK samples and the Visual Studio template DirectX projects contain a version of these files. These common files demonstrate important best practices for DirectX UWP apps, and you are encouraged to use them in your own projects. + +### C++ UWP common files +Variants of the following files are found in every UWP app written in C++: + +- Package.appxmanifest +- pch.cpp/.h +- D2DAdvancedColorImagesRenderer.vcxproj +- D2DAdvancedColorImagesRenderer.vcxproj.filters +- D2DAdvancedColorImagesRenderer.sln + +## Related topics + +### Feature areas + +[Direct2D](http://msdn.microsoft.com/library/windows/desktop/dd370990): used to render images, primitives, and text. +[XAML overview](https://msdn.microsoft.com/library/windows/apps/mt185595): technology for building user interfaces in managed and C++ code. + +### Reference + +Direct2D APIs: + +[Color management effect](https://msdn.microsoft.com/en-us/library/windows/desktop/hh706318) +[ID2D1DeviceContext2::CreateImageSourceFromWic method](https://msdn.microsoft.com/en-us/library/windows/desktop/dn890793) + +DXGI APIs: + +IDXGIOutput6 + +Related APIs: + +[SwapChainPanel](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.swapchainpanel) + +## System requirements + +**Client:** Windows 10 + +**Server:** Windows Server 2016 Technical Preview + +**Phone:** Windows 10 + +## Build the sample + +1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build. +2. Start Microsoft Visual Studio 2017 and select **File** \> **Open** \> **Project/Solution**. +3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then the subfolder for your preferred language (C++, C#, or JavaScript). Double-click the Visual Studio 2017 Solution (.sln) file. +4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**. + +## Run the sample + +The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it. + +### Deploying the sample + +- Select Build > Deploy Solution. + +### Deploying and running the sample + +- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging. + +## Run the sample + +The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it. + +### Deploying the sample + +- Select Build > Deploy Solution. + +### Deploying and running the sample + +- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging. \ No newline at end of file diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages.sln b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages.sln new file mode 100644 index 0000000000..d2c25e4618 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.22919.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D2DAdvancedColorImages", "D2DAdvancedColorImages\D2DAdvancedColorImages.vcxproj", "{E680BD3C-51E4-524B-A709-B472289A5BEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x86 = Debug|x86 + Debug|x64 = Debug|x64 + Release|ARM = Release|ARM + Release|x86 = Release|x86 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|ARM.ActiveCfg = Debug|ARM + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|ARM.Build.0 = Debug|ARM + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|ARM.Deploy.0 = Debug|ARM + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|x86.ActiveCfg = Debug|Win32 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|x86.Build.0 = Debug|Win32 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|x86.Deploy.0 = Debug|Win32 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|x64.ActiveCfg = Debug|x64 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|x64.Build.0 = Debug|x64 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Debug|x64.Deploy.0 = Debug|x64 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|ARM.ActiveCfg = Release|ARM + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|ARM.Build.0 = Release|ARM + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|ARM.Deploy.0 = Release|ARM + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|x86.ActiveCfg = Release|Win32 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|x86.Build.0 = Release|Win32 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|x86.Deploy.0 = Release|Win32 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|x64.ActiveCfg = Release|x64 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|x64.Build.0 = Release|x64 + {E680BD3C-51E4-524B-A709-B472289A5BEC}.Release|x64.Deploy.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml new file mode 100644 index 0000000000..a3d51599d2 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml @@ -0,0 +1,20 @@ + + + + diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml.cpp b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml.cpp new file mode 100644 index 0000000000..757793e91c --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml.cpp @@ -0,0 +1,120 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "App.xaml.h" + +using namespace SDKTemplate; + +using namespace Platform; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::Storage; +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::Interop; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Navigation; + +/// +/// Initializes the singleton application object. This is the first line of authored code +/// executed, and as such is the logical equivalent of main() or WinMain(). +/// +App::App() +{ + InitializeComponent(); + Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); + Resuming += ref new EventHandler(this, &App::OnResuming); +} + +/// +/// Invoked when the application is launched normally by the end user. Other entry points +/// will be used when the application is launched to open a specific file, to display +/// search results, and so forth. +/// +/// Details about the launch request and process. +void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) +{ + if (m_directXPage == nullptr) + { + m_directXPage = ref new DirectXPage(); + } + + if (e->PreviousExecutionState == ApplicationExecutionState::Terminated) + { + m_directXPage->LoadInternalState(ApplicationData::Current->LocalSettings->Values); + } + + m_directXPage->LoadDefaultImage(); + + // Place the page in the current window and ensure that it is active. + Window::Current->Content = m_directXPage; + Window::Current->Activate(); +} + +// Invoked when the app is launched via the file type association for which the app has registered. +void App::OnFileActivated(Windows::ApplicationModel::Activation::FileActivatedEventArgs ^ e) +{ + if (m_directXPage == nullptr) + { + m_directXPage = ref new DirectXPage(); + } + + if (e->PreviousExecutionState == ApplicationExecutionState::Terminated) + { + m_directXPage->LoadInternalState(ApplicationData::Current->LocalSettings->Values); + } + + int numFiles = e->Files->Size; + + if (numFiles == 1) + { + IStorageItem^ storageItem = e->Files->GetAt(0); + StorageFile^ storageFile = (StorageFile^)storageItem; + + m_directXPage->LoadImage(storageFile); + } + else + { + throw ref new Platform::FailureException(L"Activated with incorrect number of files."); + } + + // Place the page in the current window and ensure that it is active. + Window::Current->Content = m_directXPage; + Window::Current->Activate(); +} + +/// +/// Invoked when application execution is being suspended. Application state is saved +/// without knowing whether the application will be terminated or resumed with the contents +/// of memory still intact. +/// +/// The source of the suspend request. +/// Details about the suspend request. +void App::OnSuspending(Object^, SuspendingEventArgs^) +{ + m_directXPage->SaveInternalState(ApplicationData::Current->LocalSettings->Values); +} + +/// +/// Invoked when application execution is being resumed. +/// +/// The source of the resume request. +/// Details about the resume request. +void App::OnResuming(Object^, Object^) +{ + m_directXPage->LoadInternalState(ApplicationData::Current->LocalSettings->Values); +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml.h new file mode 100644 index 0000000000..bc363fcbc4 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/App.xaml.h @@ -0,0 +1,34 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +#include "App.g.h" +#include "DirectXPage.xaml.h" + +namespace SDKTemplate +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + ref class App sealed + { + public: + App(); + virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override; + virtual void OnFileActivated(Windows::ApplicationModel::Activation::FileActivatedEventArgs^ e) override; + + private: + void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e); + void OnResuming(Platform::Object ^sender, Platform::Object ^args); + DirectXPage^ m_directXPage; + }; +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/BasicReaderWriter.cpp b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/BasicReaderWriter.cpp new file mode 100644 index 0000000000..ea7b76097f --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/BasicReaderWriter.cpp @@ -0,0 +1,171 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "BasicReaderWriter.h" + +using namespace Microsoft::WRL; +using namespace Windows::Storage; +using namespace Windows::Storage::FileProperties; +using namespace Windows::Storage::Streams; +using namespace Windows::Foundation; +using namespace Windows::ApplicationModel; +using namespace concurrency; + +BasicReaderWriter::BasicReaderWriter() +{ + m_location = Package::Current->InstalledLocation; +} + +BasicReaderWriter::BasicReaderWriter( + _In_ Windows::Storage::StorageFolder^ folder + ) +{ + m_location = folder; + Platform::String^ path = m_location->Path; + if (path->Length() == 0) + { + // Applications are not permitted to access certain + // folders, such as the Documents folder, using this + // code path. In such cases, the Path property for + // the folder will be an empty string. + throw ref new Platform::FailureException(); + } +} + +Platform::Array^ BasicReaderWriter::ReadData( + _In_ Platform::String^ filename + ) +{ + CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0}; + extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN; + extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extendedParams.lpSecurityAttributes = nullptr; + extendedParams.hTemplateFile = nullptr; + + Wrappers::FileHandle file( + CreateFile2( + filename->Data(), + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + &extendedParams + ) + ); + if (file.Get() == INVALID_HANDLE_VALUE) + { + throw ref new Platform::FailureException(); + } + + FILE_STANDARD_INFO fileInfo = {0}; + if (!GetFileInformationByHandleEx( + file.Get(), + FileStandardInfo, + &fileInfo, + sizeof(fileInfo) + )) + { + throw ref new Platform::FailureException(); + } + + if (fileInfo.EndOfFile.HighPart != 0) + { + throw ref new Platform::OutOfMemoryException(); + } + + Platform::Array^ fileData = ref new Platform::Array(fileInfo.EndOfFile.LowPart); + + if (!ReadFile( + file.Get(), + fileData->Data, + fileData->Length, + nullptr, + nullptr + )) + { + throw ref new Platform::FailureException(); + } + + return fileData; +} + +task^> BasicReaderWriter::ReadDataAsync( + _In_ Platform::String^ filename + ) +{ + return task(m_location->GetFileAsync(filename)).then([=](StorageFile^ file) + { + return FileIO::ReadBufferAsync(file); + }).then([=](IBuffer^ buffer) + { + auto fileData = ref new Platform::Array(buffer->Length); + DataReader::FromBuffer(buffer)->ReadBytes(fileData); + return fileData; + }); +} + +uint32 BasicReaderWriter::WriteData( + _In_ Platform::String^ filename, + _In_ const Platform::Array^ fileData + ) +{ + CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0}; + extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN; + extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extendedParams.lpSecurityAttributes = nullptr; + extendedParams.hTemplateFile = nullptr; + + Wrappers::FileHandle file( + CreateFile2( + filename->Data(), + GENERIC_WRITE, + 0, + CREATE_ALWAYS, + &extendedParams + ) + ); + if (file.Get() == INVALID_HANDLE_VALUE) + { + throw ref new Platform::FailureException(); + } + + DWORD numBytesWritten; + if ( + !WriteFile( + file.Get(), + fileData->Data, + fileData->Length, + &numBytesWritten, + nullptr + ) || + numBytesWritten != fileData->Length + ) + { + throw ref new Platform::FailureException(); + } + + return numBytesWritten; +} + +task BasicReaderWriter::WriteDataAsync( + _In_ Platform::String^ filename, + _In_ const Platform::Array^ fileData + ) +{ + return task(m_location->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting)).then([=](StorageFile^ file) + { + FileIO::WriteBytesAsync(file, fileData); + }); +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/BasicReaderWriter.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/BasicReaderWriter.h new file mode 100644 index 0000000000..4dd9bfa8ba --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/BasicReaderWriter.h @@ -0,0 +1,46 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +#include + +// A simple reader/writer class that provides support for reading and writing +// files on disk. Provides synchronous and asynchronous methods. +ref class BasicReaderWriter +{ +private: + Windows::Storage::StorageFolder^ m_location; + +internal: + BasicReaderWriter(); + BasicReaderWriter( + _In_ Windows::Storage::StorageFolder^ folder + ); + + Platform::Array^ ReadData( + _In_ Platform::String^ filename + ); + + concurrency::task^> ReadDataAsync( + _In_ Platform::String^ filename + ); + + uint32 WriteData( + _In_ Platform::String^ filename, + _In_ const Platform::Array^ fileData + ); + + concurrency::task WriteDataAsync( + _In_ Platform::String^ filename, + _In_ const Platform::Array^ fileData + ); +}; diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImages.vcxproj b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImages.vcxproj new file mode 100644 index 0000000000..4f595b5446 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImages.vcxproj @@ -0,0 +1,407 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + + {e680bd3c-51e4-524b-a709-b472289a5bec} + SDKTemplate + en-US + 14.0 + true + Windows Store + 10.0 + true + 10.0.15063.0 + 10.0.15063.0 + D2DAdvancedColorImages + + + + Application + true + v141 + + + Application + true + v141 + + + Application + true + v141 + + + Application + false + true + v141 + true + + + Application + false + true + v141 + true + + + Application + false + true + v141 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + ClCompile + + + ClCompile + + + ClCompile + + + ClCompile + + + ClCompile + + + ClCompile + + + + d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; dxguid.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + _DEBUG;%(PreprocessorDefinitions) + + + :: fxc.exe needs the path to d2d1effecthelpers.hlsli (/I parameter). +:: Parse the Visual Studio macro into a form usable by fxc.exe. +set INCLUDEPATHS="$(WindowsSDK_IncludePath)" +set INCLUDEPATHS=%INCLUDEPATHS:;=" /I "% +fxc /T lib_4_0_level_9_1_ps_only ToneMapEffect.hlsl /D D2D_FUNCTION /D D2D_ENTRY=main /Fl "$(ProjectDir)ToneMapEffect.fxlib" /nologo /I %INCLUDEPATHS% +fxc /T ps_4_0_level_9_1 ToneMapEffect.hlsl /D D2D_FULL_SHADER /D D2D_ENTRY=main /E main /setprivate "$(ProjectDir)ToneMapEffect.fxlib" /Fo "$(OutDir)ToneMapEffect.cso" /Fh "$(OutDir)ToneMapEffectShader.h" /nologo /I %INCLUDEPATHS% + + + Generate a linking compatible pixel shader + + + $(OutDir)ToneMapEffect.cso;$(OutDir)ToneMapEffectShader.h + + + ToneMapEffect.hlsl + + + true + + + + + d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; dxguid.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + NDEBUG;%(PreprocessorDefinitions) + + + :: fxc.exe needs the path to d2d1effecthelpers.hlsli (/I parameter). +:: Parse the Visual Studio macro into a form usable by fxc.exe. +set INCLUDEPATHS="$(WindowsSDK_IncludePath)" +set INCLUDEPATHS=%INCLUDEPATHS:;=" /I "% +fxc /T lib_4_0_level_9_1_ps_only ToneMapEffect.hlsl /D D2D_FUNCTION /D D2D_ENTRY=main /Fl "$(ProjectDir)ToneMapEffect.fxlib" /nologo /I %INCLUDEPATHS% +fxc /T ps_4_0_level_9_1 ToneMapEffect.hlsl /D D2D_FULL_SHADER /D D2D_ENTRY=main /E main /setprivate "$(ProjectDir)ToneMapEffect.fxlib" /Fo "$(OutDir)ToneMapEffect.cso" /Fh "$(OutDir)ToneMapEffectShader.h" /nologo /I %INCLUDEPATHS% + + + Generate a linking compatible pixel shader + + + $(OutDir)ToneMapEffect.cso;$(OutDir)ToneMapEffectShader.h + + + ToneMapEffect.hlsl + + + true + + + + + d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; dxguid.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + _DEBUG;%(PreprocessorDefinitions) + + + :: fxc.exe needs the path to d2d1effecthelpers.hlsli (/I parameter). +:: Parse the Visual Studio macro into a form usable by fxc.exe. +set INCLUDEPATHS="$(WindowsSDK_IncludePath)" +set INCLUDEPATHS=%INCLUDEPATHS:;=" /I "% +fxc /T lib_4_0_level_9_1_ps_only ToneMapEffect.hlsl /D D2D_FUNCTION /D D2D_ENTRY=main /Fl "$(ProjectDir)ToneMapEffect.fxlib" /nologo /I %INCLUDEPATHS% +fxc /T ps_4_0_level_9_1 ToneMapEffect.hlsl /D D2D_FULL_SHADER /D D2D_ENTRY=main /E main /setprivate "$(ProjectDir)ToneMapEffect.fxlib" /Fo "$(OutDir)ToneMapEffect.cso" /Fh "$(OutDir)ToneMapEffectShader.h" /nologo /I %INCLUDEPATHS% + + + Generate a linking compatible pixel shader + + + $(OutDir)ToneMapEffect.cso;$(OutDir)ToneMapEffectShader.h + + + ToneMapEffect.hlsl + + + true + + + + + d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; dxguid.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + NDEBUG;%(PreprocessorDefinitions) + + + :: fxc.exe needs the path to d2d1effecthelpers.hlsli (/I parameter). +:: Parse the Visual Studio macro into a form usable by fxc.exe. +set INCLUDEPATHS="$(WindowsSDK_IncludePath)" +set INCLUDEPATHS=%INCLUDEPATHS:;=" /I "% +fxc /T lib_4_0_level_9_1_ps_only ToneMapEffect.hlsl /D D2D_FUNCTION /D D2D_ENTRY=main /Fl "$(ProjectDir)ToneMapEffect.fxlib" /nologo /I %INCLUDEPATHS% +fxc /T ps_4_0_level_9_1 ToneMapEffect.hlsl /D D2D_FULL_SHADER /D D2D_ENTRY=main /E main /setprivate "$(ProjectDir)ToneMapEffect.fxlib" /Fo "$(OutDir)ToneMapEffect.cso" /Fh "$(OutDir)ToneMapEffectShader.h" /nologo /I %INCLUDEPATHS% + + + Generate a linking compatible pixel shader + + + $(OutDir)ToneMapEffect.cso;$(OutDir)ToneMapEffectShader.h + + + ToneMapEffect.hlsl + + + true + + + + + d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; dxguid.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + _DEBUG;%(PreprocessorDefinitions) + + + :: fxc.exe needs the path to d2d1effecthelpers.hlsli (/I parameter). +:: Parse the Visual Studio macro into a form usable by fxc.exe. +set INCLUDEPATHS="$(WindowsSDK_IncludePath)" +set INCLUDEPATHS=%INCLUDEPATHS:;=" /I "% +fxc /T lib_4_0_level_9_1_ps_only ToneMapEffect.hlsl /D D2D_FUNCTION /D D2D_ENTRY=main /Fl "$(ProjectDir)ToneMapEffect.fxlib" /nologo /I %INCLUDEPATHS% +fxc /T ps_4_0_level_9_1 ToneMapEffect.hlsl /D D2D_FULL_SHADER /D D2D_ENTRY=main /E main /setprivate "$(ProjectDir)ToneMapEffect.fxlib" /Fo "$(OutDir)ToneMapEffect.cso" /Fh "$(OutDir)ToneMapEffectShader.h" /nologo /I %INCLUDEPATHS% + + + Generate a linking compatible pixel shader + + + $(OutDir)ToneMapEffect.cso;$(OutDir)ToneMapEffectShader.h + + + ToneMapEffect.hlsl + + + true + + + + + d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; dxguid.lib; %(AdditionalDependencies) + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + 4453;28204 + NDEBUG;%(PreprocessorDefinitions) + + + :: fxc.exe needs the path to d2d1effecthelpers.hlsli (/I parameter). +:: Parse the Visual Studio macro into a form usable by fxc.exe. +set INCLUDEPATHS="$(WindowsSDK_IncludePath)" +set INCLUDEPATHS=%INCLUDEPATHS:;=" /I "% +fxc /T lib_4_0_level_9_1_ps_only ToneMapEffect.hlsl /D D2D_FUNCTION /D D2D_ENTRY=main /Fl "$(ProjectDir)ToneMapEffect.fxlib" /nologo /I %INCLUDEPATHS% +fxc /T ps_4_0_level_9_1 ToneMapEffect.hlsl /D D2D_FULL_SHADER /D D2D_ENTRY=main /E main /setprivate "$(ProjectDir)ToneMapEffect.fxlib" /Fo "$(OutDir)ToneMapEffect.cso" /Fh "$(OutDir)ToneMapEffectShader.h" /nologo /I %INCLUDEPATHS% + + + Generate a linking compatible pixel shader + + + $(OutDir)ToneMapEffect.cso;$(OutDir)ToneMapEffectShader.h + + + ToneMapEffect.hlsl + + + true + + + + + Assets\smalltile-sdk.png + + + Assets\splash-sdk.png + + + Assets\squaretile-sdk.png + + + Assets\storelogo-sdk.png + + + Assets\tile-sdk.png + + + + + App.xaml + + + + + + DirectXPage.xaml + + + + + + + + App.xaml + + + + + DirectXPage.xaml + + + Create + Create + Create + Create + Create + Create + + + + + + + Designer + + + + + Designer + + + Designer + + + + + true + Document + true + true + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImages.vcxproj.filters b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImages.vcxproj.filters new file mode 100644 index 0000000000..59cb100614 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImages.vcxproj.filters @@ -0,0 +1,70 @@ + + + + + d6d27eff-6efd-4cdf-9154-377ac3856a6b + bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + {a6fce137-2822-4f7a-8593-eff13050174b} + + + + + + + + + + + + Common + + + Common + + + + + + + + + + Common + + + Common + + + Common + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + \ No newline at end of file diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImagesRenderer.cpp b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImagesRenderer.cpp new file mode 100644 index 0000000000..e658ef5320 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImagesRenderer.cpp @@ -0,0 +1,398 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "D2DAdvancedColorImagesRenderer.h" +#include "DirectXPage.xaml.h" +#include "DirectXHelper.h" + +using namespace SDKTemplate; + +using namespace concurrency; +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace Platform; +using namespace std; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::Graphics::Display; +using namespace Windows::Storage; +using namespace Windows::Storage::Streams; +using namespace Windows::UI::Input; +using namespace Windows::UI::Xaml; + +D2DAdvancedColorImages::D2DAdvancedColorImages(const std::shared_ptr& deviceResources) : + m_deviceResources(deviceResources), + m_imageSize(), + m_useToneMapping(true), + m_numberOfProfiles(0), + m_zoom(1.0f), + m_offset() +{ + // Register to be notified if the GPU device is lost or recreated. + m_deviceResources->RegisterDeviceNotify(this); + + CreateDeviceIndependentResources(); + CreateDeviceDependentResources(); + CreateWindowSizeDependentResources(); +} + +D2DAdvancedColorImages::~D2DAdvancedColorImages() +{ + // Deregister device notification. + m_deviceResources->RegisterDeviceNotify(nullptr); +} + +void D2DAdvancedColorImages::CreateDeviceIndependentResources() +{ + // Register the custom effect. + DX::ThrowIfFailed( + ToneMapEffect::Register(m_deviceResources->GetD2DFactory()) + ); +} + +void D2DAdvancedColorImages::CreateDeviceDependentResources() +{ + // All this app's device-dependent resources also depend on + // the loaded image, so they are all created in + // CreateImageDependentResources. +} + +void D2DAdvancedColorImages::ReleaseDeviceDependentResources() +{ +} + +// Whenever the app window is resized or changes displays, this method is used +// to update the app's sizing and advanced color state. +void D2DAdvancedColorImages::CreateWindowSizeDependentResources() +{ + UpdateAdvancedColorState(); + + // In case the window size changed, update the app's image scaling values. + FitImageToWindow(); +} + +// Reads the provided data stream and decodes a JPEG XR image from it. Retrieves the +// ICC color profile attached to that image, if any. These resources are device- +// independent. +void D2DAdvancedColorImages::LoadImage(IStream* imageStream) +{ + auto wicFactory = m_deviceResources->GetWicImagingFactory(); + + // First, decode the provided image. + + ComPtr decoder; + DX::ThrowIfFailed( + wicFactory->CreateDecoderFromStream( + imageStream, + nullptr, + WICDecodeMetadataCacheOnDemand, + &decoder + ) + ); + + ComPtr frame; + DX::ThrowIfFailed( + decoder->GetFrame(0, &frame) + ); + + // Check that the image data is in a floating-point format. This app + // only supports JPEG XR images containing scRGB content, expressed + // in an extended-range, floating-point format. + + WICPixelFormatGUID pixelFormat; + DX::ThrowIfFailed( + frame->GetPixelFormat(&pixelFormat) + ); + + ComPtr componentInfo; + DX::ThrowIfFailed( + wicFactory->CreateComponentInfo( + pixelFormat, + &componentInfo + ) + ); + + ComPtr pixelFormatInfo; + DX::ThrowIfFailed( + componentInfo.As(&pixelFormatInfo) + ); + + WICPixelFormatNumericRepresentation formatNumber; + DX::ThrowIfFailed( + pixelFormatInfo->GetNumericRepresentation(&formatNumber) + ); + + if (formatNumber != WICPixelFormatNumericRepresentationFloat) + { + // Terminate image loading if the image is not in a floating-point format. + return; + } + + // Convert the image to a pixel format supported by Direct2D. Note that WIC + // performs an implicit gamma conversion when converting between a fixed-point/ + // integer pixel format (sRGB gamma) and a float-point pixel format (linear gamma). + // In this case, no gamma adjustment is performed since the source content + // is already in a floating-point format. Gamma adjustment, if specified by + // the ICC profile, will be performed by the color management effect. + + DX::ThrowIfFailed( + wicFactory->CreateFormatConverter(&m_formatConvert) + ); + + DX::ThrowIfFailed( + m_formatConvert->Initialize( + frame.Get(), + GUID_WICPixelFormat64bppPRGBAHalf, // Equivalent to DXGI_FORMAT_R16G16B16A16_FLOAT. + WICBitmapDitherTypeNone, + nullptr, + 0.0f, + WICBitmapPaletteTypeCustom + ) + ); + + UINT width; + UINT height; + DX::ThrowIfFailed( + m_formatConvert->GetSize(&width, &height) + ); + m_imageSize = Size(static_cast(width), static_cast(height)); + + // Attempt to read the embedded color profile from the image. + DX::ThrowIfFailed( + wicFactory->CreateColorContext(&m_wicColorContext) + ); + DX::ThrowIfFailed( + frame->GetColorContexts( + 1, + m_wicColorContext.GetAddressOf(), + &m_numberOfProfiles + ) + ); +} + +// Configures a Direct2D image source, a color management effect, and a +// tone mapping effect, based on the loaded image. +void D2DAdvancedColorImages::CreateImageDependentResources() +{ + auto d2dFactory = m_deviceResources->GetD2DFactory(); + auto context = m_deviceResources->GetD2DDeviceContext(); + + // Load the image from WIC using ID2D1ImageSource. + DX::ThrowIfFailed( + m_deviceResources->GetD2DDeviceContext()->CreateImageSourceFromWic( + m_formatConvert.Get(), + &m_imageSource + ) + ); + + // Next, configure the app's effect pipeline, consisting of a color management effect + // followed by a tone mapping effect. + + DX::ThrowIfFailed( + context->CreateEffect(CLSID_D2D1ColorManagement, &m_colorManagementEffect) + ); + + DX::ThrowIfFailed( + m_colorManagementEffect->SetValue( + D2D1_COLORMANAGEMENT_PROP_QUALITY, + D2D1_COLORMANAGEMENT_QUALITY_BEST // Required for floating point and DXGI color space support. + ) + ); + + // The color management effect takes a source color space and a destination color space, + // and performs the appropriate math to convert images between them. Color contexts can be + // "hard-coded" (by providing a set of color primaries and a white point), but in this case + // we will use the color context attached to the image. This color context, if it exists, + // was retrieved by WIC in the LoadImage method. If it doesn't exist, default to scRGB. + + ComPtr sourceColorContext; + if (m_numberOfProfiles >= 1) + { + DX::ThrowIfFailed( + context->CreateColorContextFromWicColorContext( + m_wicColorContext.Get(), + &sourceColorContext + ) + ); + } + else + { + DX::ThrowIfFailed( + context->CreateColorContext( + D2D1_COLOR_SPACE_SCRGB, + nullptr, + 0, + &sourceColorContext + ) + ); + } + + DX::ThrowIfFailed( + m_colorManagementEffect->SetValue( + D2D1_COLORMANAGEMENT_PROP_SOURCE_COLOR_CONTEXT, + sourceColorContext.Get() + ) + ); + + // For the destination color space, we will use scRGB. This is appropriate for this app's + // choice of swap chain pixel format. + ComPtr destColorContext; + DX::ThrowIfFailed( + context->CreateColorContextFromDxgiColorSpace( + DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, + &destColorContext + ) + ); + + DX::ThrowIfFailed( + m_colorManagementEffect->SetValue( + D2D1_COLORMANAGEMENT_PROP_DESTINATION_COLOR_CONTEXT, + destColorContext.Get() + ) + ); + + // Instantiate and configure the tone mapping effect, which is a custom Direct2D effect + // implemented in ToneMapEffect.cpp and ToneMapEffect.hlsl. It performs a very basic + // HDR-to-SDR tone mapping operation. + DX::ThrowIfFailed( + context->CreateEffect(CLSID_CustomToneMapEffect, &m_toneMapEffect) + ); + + m_toneMapEffect->SetInputEffect(0, m_colorManagementEffect.Get()); +} + +void D2DAdvancedColorImages::ReleaseImageDependentResources() +{ + m_imageSource.Reset(); + m_scaledImage.Reset(); + m_colorManagementEffect.Reset(); + m_toneMapEffect.Reset(); +} + +// Update zoom state to keep the image fit to the app window. +void D2DAdvancedColorImages::FitImageToWindow() +{ + if (m_imageSource) + { + Size panelSize = m_deviceResources->GetLogicalSize(); + + // Letterbox but never exceed max scale. + m_zoom = min( + min( + panelSize.Width / m_imageSize.Width, + panelSize.Height / m_imageSize.Height + ), + 1.0f + ); + + // Center the image. + m_offset = D2D1::Point2F( + (panelSize.Width - (m_imageSize.Width * m_zoom)) / 2.0f, + (panelSize.Height - (m_imageSize.Height * m_zoom)) / 2.0f + ); + + // When using ID2D1ImageSource, the recommend method of scaling is to use + // ID2D1TransformedImageSource. It is inexpensive to recreate this object. + D2D1_TRANSFORMED_IMAGE_SOURCE_PROPERTIES props = + { + D2D1_ORIENTATION_DEFAULT, + m_zoom, + m_zoom, + D2D1_INTERPOLATION_MODE_LINEAR, // This is ignored when using DrawImage. + D2D1_TRANSFORMED_IMAGE_SOURCE_OPTIONS_NONE + }; + + DX::ThrowIfFailed( + m_deviceResources->GetD2DDeviceContext()->CreateTransformedImageSource( + m_imageSource.Get(), + &props, + &m_scaledImage + ) + ); + + // Set the new image as the new source to the effect pipeline. + m_colorManagementEffect->SetInput(0, m_scaledImage.Get()); + } +} + +// Uses DXGI APIs to query the capabilities of the app's current display, and +// enables HDR-to-SDR tone mapping if the display does not meet a particular +// brightness threshold or is not in advanced color mode. +void D2DAdvancedColorImages::UpdateAdvancedColorState() +{ + DXGI_OUTPUT_DESC1 outputDesc = m_deviceResources->GetCurrentOutputDesc1(); + + // Decide whether or not the app needs to apply tone mapping, based on the brightness + // capabilities of the display (maximum luminance at least 300) and the mode of the display. + if ((outputDesc.MaxLuminance >= 300.0f) && (outputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)) + { + m_useToneMapping = false; + } + else + { + m_useToneMapping = true; + } +} + +// Renders the loaded JPEG XR image, optionally applying HDR-to-SDR tone mapping, +// if appropriate. +void D2DAdvancedColorImages::Draw() +{ + auto d2dContext = m_deviceResources->GetD2DDeviceContext(); + + d2dContext->BeginDraw(); + + d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::Black)); + + d2dContext->SetTransform(m_deviceResources->GetOrientationTransform2D()); + + if (m_scaledImage) + { + if (m_useToneMapping) + { + // Draw the full effect pipeline, which includes the tone mapping effect. + d2dContext->DrawImage(m_toneMapEffect.Get(), m_offset); + } + else + { + // Omit the tone mapping effect and just draw the color-managed image. + d2dContext->DrawImage(m_colorManagementEffect.Get(), m_offset); + } + } + + // We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device + // is lost. It will be handled during the next call to Present. + HRESULT hr = d2dContext->EndDraw(); + if (hr != D2DERR_RECREATE_TARGET) + { + DX::ThrowIfFailed(hr); + } + + m_deviceResources->Present(); +} + +// Notifies renderers that device resources need to be released. +void D2DAdvancedColorImages::OnDeviceLost() +{ + ReleaseImageDependentResources(); + ReleaseDeviceDependentResources(); +} + +// Notifies renderers that device resources may now be recreated. +void D2DAdvancedColorImages::OnDeviceRestored() +{ + CreateDeviceDependentResources(); + CreateImageDependentResources(); + CreateWindowSizeDependentResources(); + + Draw(); +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImagesRenderer.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImagesRenderer.h new file mode 100644 index 0000000000..d5dd9a1de6 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/D2DAdvancedColorImagesRenderer.h @@ -0,0 +1,61 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +#include "DeviceResources.h" +#include "ToneMapEffect.h" + +namespace SDKTemplate +{ + class D2DAdvancedColorImages : public DX::IDeviceNotify + { + public: + D2DAdvancedColorImages(const std::shared_ptr& deviceResources); + ~D2DAdvancedColorImages(); + + void CreateDeviceIndependentResources(); + void CreateDeviceDependentResources(); + void CreateWindowSizeDependentResources(); + void ReleaseDeviceDependentResources(); + void Draw(); + + void LoadImage(IStream* imageStream); + void CreateImageDependentResources(); + void ReleaseImageDependentResources(); + void FitImageToWindow(); + + void UpdateAdvancedColorState(); + + // IDeviceNotify methods handle device lost and restored. + virtual void OnDeviceLost(); + virtual void OnDeviceRestored(); + + private: + // Cached pointer to device resources. + std::shared_ptr m_deviceResources; + + // WIC and Direct2D resources. + Microsoft::WRL::ComPtr m_formatConvert; + Microsoft::WRL::ComPtr m_wicColorContext; + Microsoft::WRL::ComPtr m_imageSource; + Microsoft::WRL::ComPtr m_scaledImage; + Microsoft::WRL::ComPtr m_colorManagementEffect; + Microsoft::WRL::ComPtr m_toneMapEffect; + + // Other renderer members. + bool m_useToneMapping; + Windows::Foundation::Size m_imageSize; + unsigned int m_numberOfProfiles; + float m_zoom; + D2D1_POINT_2F m_offset; + }; +} \ No newline at end of file diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DeviceResources.cpp b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DeviceResources.cpp new file mode 100644 index 0000000000..eb1d288ec1 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DeviceResources.cpp @@ -0,0 +1,805 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" +#include + +using namespace D2D1; +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Display; +using namespace Windows::UI::Core; +using namespace Windows::UI::Xaml::Controls; +using namespace Platform; + +// Instead of the typical 8 bits-per-channel, UNORM pixel format, this app will use the +// 16 bits-per-channel, floating-point format. This format should be used for swap chains +// and intermediate surfaces that will be representing content in the scRGB color space. +// Direct3D and Direct2D natively support rendering to this pixel format. +static const DXGI_FORMAT sc_swapChainFormat = DXGI_FORMAT_R16G16B16A16_FLOAT; + +// Constants used to calculate screen rotations +namespace ScreenRotation +{ + // 0-degree Z-rotation + static const XMFLOAT4X4 Rotation0( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 90-degree Z-rotation + static const XMFLOAT4X4 Rotation90( + 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 180-degree Z-rotation + static const XMFLOAT4X4 Rotation180( + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + + // 270-degree Z-rotation + static const XMFLOAT4X4 Rotation270( + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); +}; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources() : + m_screenViewport(), + m_d3dFeatureLevel(D3D_FEATURE_LEVEL_9_1), + m_d3dRenderTargetSize(), + m_outputSize(), + m_logicalSize(), + m_nativeOrientation(DisplayOrientations::None), + m_currentOrientation(DisplayOrientations::None), + m_dpi(-1.0f), + m_compositionScaleX(1.0f), + m_compositionScaleY(1.0f), + m_deviceNotify(nullptr) +{ + CreateDeviceIndependentResources(); + CreateDeviceResources(); +} + +// Configures resources that don't depend on the Direct3D device. +void DX::DeviceResources::CreateDeviceIndependentResources() +{ + // Initialize Direct2D resources. + D2D1_FACTORY_OPTIONS options; + ZeroMemory(&options, sizeof(options)); + +#if defined(_DEBUG) + // If the project is in a debug build, enable Direct2D debugging via SDK Layers. + options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; +#endif + + // Initialize the Direct2D Factory. + DX::ThrowIfFailed( + D2D1CreateFactory( + D2D1_FACTORY_TYPE_SINGLE_THREADED, + __uuidof(ID2D1Factory6), + &options, + &m_d2dFactory + ) + ); + + // Initialize the DirectWrite Factory. + DX::ThrowIfFailed( + DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory2), + &m_dwriteFactory + ) + ); + + // Initialize the Windows Imaging Component (WIC) Factory. + DX::ThrowIfFailed( + CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&m_wicFactory) + ) + ); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#if defined(_DEBUG) + if (DX::SdkLayersAvailable()) + { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } +#endif + + // This array defines the set of DirectX hardware feature levels this app will support. + // Note the ordering should be preserved. + // Don't forget to declare your application's minimum required feature level in its + // description. All applications are assumed to support 9.1 unless otherwise stated. + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + HRESULT hr = D3D11CreateDevice( + nullptr, // Specify nullptr to use the default adapter. + D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver. + 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. + creationFlags, // Set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), // Size of the list above. + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + &device, // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + &context // Returns the device immediate context. + ); + + if (FAILED(hr)) + { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + DX::ThrowIfFailed( + D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. + 0, + creationFlags, + featureLevels, + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, + &device, + &m_d3dFeatureLevel, + &context + ) + ); + } + + // Store pointers to the Direct3D 11.1 API device and immediate context. + DX::ThrowIfFailed( + device.As(&m_d3dDevice) + ); + + DX::ThrowIfFailed( + context.As(&m_d3dContext) + ); + + // Create the Direct2D device object and a corresponding context. + ComPtr dxgiDevice; + DX::ThrowIfFailed( + m_d3dDevice.As(&dxgiDevice) + ); + + DX::ThrowIfFailed( + m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice) + ); + + DX::ThrowIfFailed( + m_d2dDevice->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, + &m_d2dContext + ) + ); +} + +// These resources need to be recreated every time the window size is changed. +void DX::DeviceResources::CreateWindowSizeDependentResources() +{ + // Clear the previous window size specific context. + ID3D11RenderTargetView* nullViews[] = {nullptr}; + m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); + m_d3dRenderTargetView = nullptr; + m_d2dContext->SetTarget(nullptr); + m_d2dTargetBitmap = nullptr; + m_d3dDepthStencilView = nullptr; + m_d3dContext->Flush(); + + // Calculate the necessary swap chain and render target size in pixels. + m_outputSize.Width = m_logicalSize.Width * m_compositionScaleX; + m_outputSize.Height = m_logicalSize.Height * m_compositionScaleY; + + // Prevent zero size DirectX content from being created. + m_outputSize.Width = max(m_outputSize.Width, 1); + m_outputSize.Height = max(m_outputSize.Height, 1); + + // The width and height of the swap chain must be based on the window's + // natively-oriented width and height. If the window is not in the native + // orientation, the dimensions must be reversed. + DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation(); + + bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270; + m_d3dRenderTargetSize.Width = swapDimensions ? m_outputSize.Height : m_outputSize.Width; + m_d3dRenderTargetSize.Height = swapDimensions ? m_outputSize.Width : m_outputSize.Height; + + if (m_swapChain != nullptr) + { + // If the swap chain already exists, resize it. + HRESULT hr = m_swapChain->ResizeBuffers( + 2, // Double-buffered swap chain. + lround(m_d3dRenderTargetSize.Width), + lround(m_d3dRenderTargetSize.Height), + sc_swapChainFormat, + 0 + ); + + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { + // If the device was removed for any reason, a new device and swap chain will need to be created. + HandleDeviceLost(); + + // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method + // and correctly set up the new device. + return; + } + else + { + DX::ThrowIfFailed(hr); + } + } + else + { + // Otherwise, create a new one using the same adapter as the existing Direct3D device. + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + + swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Match the size of the window. + swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height); + swapChainDesc.Format = sc_swapChainFormat; + swapChainDesc.Stereo = false; + swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling. + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency. + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect. + swapChainDesc.Flags = 0; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + // This sequence obtains the DXGI factory that was used to create the Direct3D device above. + ComPtr dxgiDevice; + DX::ThrowIfFailed( + m_d3dDevice.As(&dxgiDevice) + ); + + ComPtr dxgiAdapter; + DX::ThrowIfFailed( + dxgiDevice->GetAdapter(&dxgiAdapter) + ); + + DX::ThrowIfFailed( + dxgiAdapter->GetParent(IID_PPV_ARGS(&m_dxgiFactory)) + ); + + // When using XAML interop, the swap chain must be created for composition. + ComPtr swapChain; + + DX::ThrowIfFailed( + m_dxgiFactory->CreateSwapChainForComposition( + m_d3dDevice.Get(), + &swapChainDesc, + nullptr, + &swapChain + ) + ); + + DX::ThrowIfFailed( + swapChain.As(&m_swapChain) + ); + + // Check the swap chain's color space support. This app needs to use the scRGB color space. + UINT colorSpaceSupport; + DX::ThrowIfFailed( + m_swapChain->CheckColorSpaceSupport(DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, &colorSpaceSupport) + ); + + if ((colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) + { + // Set the swap chain's color space to scRGB. + DX::ThrowIfFailed( + m_swapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709) + ); + } + else + { + // This sample app does not handle the unsupported case. + throw ref new NotImplementedException(); + } + + // Associate the swap chain with SwapChainPanel. + // UI changes will need to be dispatched back to the UI thread. + m_swapChainPanel->Dispatcher->RunAsync(CoreDispatcherPriority::High, ref new DispatchedHandler([=]() + { + // Get backing native interface for SwapChainPanel. + ComPtr panelNative; + DX::ThrowIfFailed( + reinterpret_cast(m_swapChainPanel)->QueryInterface(IID_PPV_ARGS(&panelNative)) + ); + + DX::ThrowIfFailed( + panelNative->SetSwapChain(m_swapChain.Get()) + ); + }, CallbackContext::Any)); + + // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and + // ensures that the application will only render after each VSync, minimizing power consumption. + DX::ThrowIfFailed( + dxgiDevice->SetMaximumFrameLatency(1) + ); + } + + // Set the proper orientation for the swap chain, and generate 2D and + // 3D matrix transformations for rendering to the rotated swap chain. + // Note the rotation angle for the 2D and 3D transforms are different. + // This is due to the difference in coordinate spaces. Additionally, + // the 3D matrix is specified explicitly to avoid rounding errors. + + switch (displayRotation) + { + case DXGI_MODE_ROTATION_IDENTITY: + m_orientationTransform2D = Matrix3x2F::Identity(); + m_orientationTransform3D = ScreenRotation::Rotation0; + break; + + case DXGI_MODE_ROTATION_ROTATE90: + m_orientationTransform2D = + Matrix3x2F::Rotation(90.0f) * + Matrix3x2F::Translation(m_logicalSize.Height, 0.0f); + m_orientationTransform3D = ScreenRotation::Rotation270; + break; + + case DXGI_MODE_ROTATION_ROTATE180: + m_orientationTransform2D = + Matrix3x2F::Rotation(180.0f) * + Matrix3x2F::Translation(m_logicalSize.Width, m_logicalSize.Height); + m_orientationTransform3D = ScreenRotation::Rotation180; + break; + + case DXGI_MODE_ROTATION_ROTATE270: + m_orientationTransform2D = + Matrix3x2F::Rotation(270.0f) * + Matrix3x2F::Translation(0.0f, m_logicalSize.Width); + m_orientationTransform3D = ScreenRotation::Rotation90; + break; + + default: + throw ref new FailureException(); + } + + DX::ThrowIfFailed( + m_swapChain->SetRotation(displayRotation) + ); + + // Set an inverse scale on the swap chain. + DXGI_MATRIX_3X2_F inverseScale = { 0 }; + inverseScale._11 = 1.0f / m_compositionScaleX; + inverseScale._22 = 1.0f / m_compositionScaleY; + ComPtr spSwapChain2; + DX::ThrowIfFailed( + m_swapChain.As(&spSwapChain2) + ); + + DX::ThrowIfFailed( + spSwapChain2->SetMatrixTransform(&inverseScale) + ); + + + // Create a render target view of the swap chain back buffer. + ComPtr backBuffer; + DX::ThrowIfFailed( + m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)) + ); + + DX::ThrowIfFailed( + m_d3dDevice->CreateRenderTargetView( + backBuffer.Get(), + nullptr, + &m_d3dRenderTargetView + ) + ); + + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + DXGI_FORMAT_D24_UNORM_S8_UINT, + lround(m_d3dRenderTargetSize.Width), + lround(m_d3dRenderTargetSize.Height), + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + ComPtr depthStencil; + DX::ThrowIfFailed( + m_d3dDevice->CreateTexture2D( + &depthStencilDesc, + nullptr, + &depthStencil + ) + ); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); + DX::ThrowIfFailed( + m_d3dDevice->CreateDepthStencilView( + depthStencil.Get(), + &depthStencilViewDesc, + &m_d3dDepthStencilView + ) + ); + + // Set the 3D rendering viewport to target the entire window. + m_screenViewport = CD3D11_VIEWPORT( + 0.0f, + 0.0f, + m_d3dRenderTargetSize.Width, + m_d3dRenderTargetSize.Height + ); + + m_d3dContext->RSSetViewports(1, &m_screenViewport); + + // Create a Direct2D target bitmap associated with the + // swap chain back buffer and set it as the current target. + D2D1_BITMAP_PROPERTIES1 bitmapProperties = + D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat(sc_swapChainFormat, D2D1_ALPHA_MODE_PREMULTIPLIED), + m_dpi, + m_dpi + ); + + ComPtr dxgiBackBuffer; + DX::ThrowIfFailed( + m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer)) + ); + + DX::ThrowIfFailed( + m_d2dContext->CreateBitmapFromDxgiSurface( + dxgiBackBuffer.Get(), + &bitmapProperties, + &m_d2dTargetBitmap + ) + ); + + m_d2dContext->SetTarget(m_d2dTargetBitmap.Get()); + + // Grayscale text anti-aliasing is recommended for all Windows Store apps. + m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); +} + +// This method is called when the XAML control is created (or re-created). +void DX::DeviceResources::SetSwapChainPanel(SwapChainPanel^ panel) +{ + DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + m_swapChainPanel = panel; + m_logicalSize = Windows::Foundation::Size(static_cast(panel->ActualWidth), static_cast(panel->ActualHeight)); + m_nativeOrientation = currentDisplayInformation->NativeOrientation; + m_currentOrientation = currentDisplayInformation->CurrentOrientation; + m_compositionScaleX = panel->CompositionScaleX; + m_compositionScaleY = panel->CompositionScaleY; + m_dpi = currentDisplayInformation->LogicalDpi; + m_d2dContext->SetDpi(m_dpi, m_dpi); + + CreateWindowSizeDependentResources(); +} + +// This method is called in the event handler for the SizeChanged event. +void DX::DeviceResources::SetLogicalSize(Windows::Foundation::Size logicalSize) +{ + if (m_logicalSize != logicalSize) + { + m_logicalSize = logicalSize; + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the DpiChanged event. +void DX::DeviceResources::SetDpi(float dpi) +{ + if (dpi != m_dpi) + { + m_dpi = dpi; + + m_d2dContext->SetDpi(m_dpi, m_dpi); + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the OrientationChanged event. +void DX::DeviceResources::SetCurrentOrientation(DisplayOrientations currentOrientation) +{ + if (m_currentOrientation != currentOrientation) + { + m_currentOrientation = currentOrientation; + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the CompositionScaleChanged event. +void DX::DeviceResources::SetCompositionScale(float compositionScaleX, float compositionScaleY) +{ + if (m_compositionScaleX != compositionScaleX || + m_compositionScaleY != compositionScaleY) + { + m_compositionScaleX = compositionScaleX; + m_compositionScaleY = compositionScaleY; + CreateWindowSizeDependentResources(); + } +} + +// This method is called in the event handler for the DisplayContentsInvalidated event. +void DX::DeviceResources::ValidateDevice() +{ + // The D3D Device is no longer valid if the default adapter changed since the device + // was created or if the device has been removed. + + // First, get the information for the default adapter from when the device was created. + + ComPtr previousDefaultAdapter; + DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter)); + + DXGI_ADAPTER_DESC previousDesc; + DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); + + // Next, get the information for the current default adapter. + + ComPtr currentFactory; + DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(¤tFactory))); + + ComPtr currentDefaultAdapter; + DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, ¤tDefaultAdapter)); + + DXGI_ADAPTER_DESC currentDesc; + DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); + + // If the adapter LUIDs don't match, or if the device reports that it has been removed, + // a new D3D device must be created. + + if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart || + previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart || + FAILED(m_d3dDevice->GetDeviceRemovedReason())) + { + // Release references to resources related to the old device. + m_dxgiFactory = nullptr; + previousDefaultAdapter = nullptr; + + // Create a new device and swap chain. + HandleDeviceLost(); + } +} + +// Recreate all device resources and set them back to the current state. +void DX::DeviceResources::HandleDeviceLost() +{ + m_swapChain = nullptr; + + if (m_deviceNotify != nullptr) + { + m_deviceNotify->OnDeviceLost(); + } + + CreateDeviceResources(); + m_d2dContext->SetDpi(m_dpi, m_dpi); + CreateWindowSizeDependentResources(); + + if (m_deviceNotify != nullptr) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Register our DeviceNotify to be informed on device lost and creation. +void DX::DeviceResources::RegisterDeviceNotify(DX::IDeviceNotify* deviceNotify) +{ + m_deviceNotify = deviceNotify; +} + +// Call this method when the app suspends. It provides a hint to the driver that the app +// is entering an idle state and that temporary buffers can be reclaimed for use by other apps. +void DX::DeviceResources::Trim() +{ + ComPtr dxgiDevice; + m_d3dDevice.As(&dxgiDevice); + + dxgiDevice->Trim(); +} + +// Present the contents of the swap chain to the screen. +void DX::DeviceResources::Present() +{ + // The first argument instructs DXGI to block until VSync, putting the application + // to sleep until the next VSync. This ensures we don't waste any cycles rendering + // frames that will never be displayed to the screen. + HRESULT hr = m_swapChain->Present(1, 0); + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be entirely + // overwritten. If dirty or scroll rects are used, this call should be removed. + m_d3dContext->DiscardView(m_d3dRenderTargetView.Get()); + + // Discard the contents of the depth stencil. + m_d3dContext->DiscardView(m_d3dDepthStencilView.Get()); + + // If the device was removed either by a disconnection or a driver upgrade, we + // must recreate all device resources. + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { + HandleDeviceLost(); + } + else + { + DX::ThrowIfFailed(hr); + } +} + +// This method determines the rotation between the display device's native Orientation and the +// current display orientation. +DXGI_MODE_ROTATION DX::DeviceResources::ComputeDisplayRotation() +{ + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + + // Note: NativeOrientation can only be Landscape or Portrait even though + // the DisplayOrientations enum has other values. + switch (m_nativeOrientation) + { + case DisplayOrientations::Landscape: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + } + break; + + case DisplayOrientations::Portrait: + switch (m_currentOrientation) + { + case DisplayOrientations::Landscape: + rotation = DXGI_MODE_ROTATION_ROTATE90; + break; + + case DisplayOrientations::Portrait: + rotation = DXGI_MODE_ROTATION_IDENTITY; + break; + + case DisplayOrientations::LandscapeFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE270; + break; + + case DisplayOrientations::PortraitFlipped: + rotation = DXGI_MODE_ROTATION_ROTATE180; + break; + } + break; + } + return rotation; +} + +// This method determines the primary DXGI output associated with the app at this +// point in time (using window/display intersection) and returns the display +// capabilities of that particular output. +DXGI_OUTPUT_DESC1 DX::DeviceResources::GetCurrentOutputDesc1() +{ + // If the display's advanced color state has changed, then this app's DXGI + // factory is invalidated and must be created anew in order to retrieve + // up-to-date display information. + if (m_dxgiFactory->IsCurrent() == false) + { + DX::ThrowIfFailed( + CreateDXGIFactory2(0, IID_PPV_ARGS(&m_dxgiFactory)) + ); + } + + // First, the method must determine the app's current display. Swap chains created + // with CreateSwapChainForComposition do not support the + // IDXGISwapChain::GetContainingOutput method, so the app must determine its current + // display. For swap chains created with CreateSwapChainForCoreWindow, the + // IDXGISwapChain::GetContainingOutput method can replace the following logic. + + // Compute the DPI-adjusted window bounds. + Windows::Foundation::Rect windowBounds = Windows::UI::Xaml::Window::Current->CoreWindow->Bounds; + windowBounds = Windows::Foundation::Rect( + DX::ConvertDipsToPixels(windowBounds.X, m_dpi), + DX::ConvertDipsToPixels(windowBounds.Y, m_dpi), + DX::ConvertDipsToPixels(windowBounds.Width, m_dpi), + DX::ConvertDipsToPixels(windowBounds.Height, m_dpi) + ); + + // Retrieve the current default adapter. + ComPtr dxgiAdapter; + DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &dxgiAdapter)); + + // Iterate through the DXGI outputs associated with the DXGI adapter, + // and find the output whose bounds have the greatest overlap with the + // app window (i.e. the output for which the intersection area is the + // greatest). + UINT i = 0; + ComPtr currentOutput; + ComPtr bestOutput; + float bestIntersectArea = -1; + while (dxgiAdapter->EnumOutputs(i, ¤tOutput) != DXGI_ERROR_NOT_FOUND) + { + DXGI_OUTPUT_DESC desc; + DX::ThrowIfFailed(currentOutput->GetDesc(&desc)); + RECT r = desc.DesktopCoordinates; + Windows::Foundation::Rect outputBounds = Windows::Foundation::Rect( + (float)r.left, + (float)r.top, + (float)(r.right - r.left), + (float)(r.bottom - r.top) + ); + + if (windowBounds.IntersectsWith(outputBounds)) + { + Windows::Foundation::Rect intersectBounds = windowBounds; + intersectBounds.Intersect(outputBounds); + + float intersectArea = intersectBounds.Width * intersectBounds.Height; + + if (intersectArea > bestIntersectArea) + { + bestOutput = currentOutput; + bestIntersectArea = intersectArea; + } + } + + i++; + } + + // Having determined the output (display) upon which the app is primarily being + // rendered, retrieve the capabilities of that display and return them. + ComPtr output6; + DX::ThrowIfFailed(bestOutput.As(&output6)); + + DXGI_OUTPUT_DESC1 desc1; + DX::ThrowIfFailed(output6->GetDesc1(&desc1)); + + return desc1; +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DeviceResources.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DeviceResources.h new file mode 100644 index 0000000000..7c0b65a42f --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DeviceResources.h @@ -0,0 +1,115 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Controls all the DirectX device resources. + class DeviceResources + { + public: + DeviceResources(); + void SetSwapChainPanel(Windows::UI::Xaml::Controls::SwapChainPanel^ panel); + void SetLogicalSize(Windows::Foundation::Size logicalSize); + void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation); + void SetDpi(float dpi); + void SetCompositionScale(float compositionScaleX, float compositionScaleY); + void ValidateDevice(); + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify); + void Trim(); + void Present(); + + // Device Accessors. + Windows::Foundation::Size GetOutputSize() const { return m_outputSize; } + Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; } + float GetDpi() const { return m_dpi; } + + // D3D Accessors. + ID3D11Device2* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContext3* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + ID3D11RenderTargetView* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } + DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } + + // D2D Accessors. + ID2D1Factory6* GetD2DFactory() const { return m_d2dFactory.Get(); } + ID2D1Device5* GetD2DDevice() const { return m_d2dDevice.Get(); } + ID2D1DeviceContext5* GetD2DDeviceContext() const { return m_d2dContext.Get(); } + ID2D1Bitmap1* GetD2DTargetBitmap() const { return m_d2dTargetBitmap.Get(); } + IDWriteFactory2* GetDWriteFactory() const { return m_dwriteFactory.Get(); } + IWICImagingFactory2* GetWicImagingFactory() const { return m_wicFactory.Get(); } + D2D1::Matrix3x2F GetOrientationTransform2D() const { return m_orientationTransform2D; } + + // Helper methods for DXGI functionality. + DXGI_OUTPUT_DESC1 GetCurrentOutputDesc1(); + + private: + void CreateDeviceIndependentResources(); + void CreateDeviceResources(); + void CreateWindowSizeDependentResources(); + DXGI_MODE_ROTATION ComputeDisplayRotation(); + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_dxgiFactory; + Microsoft::WRL::ComPtr m_swapChain; + + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + D3D11_VIEWPORT m_screenViewport; + + // Direct2D drawing components. + Microsoft::WRL::ComPtr m_d2dFactory; + Microsoft::WRL::ComPtr m_d2dDevice; + Microsoft::WRL::ComPtr m_d2dContext; + Microsoft::WRL::ComPtr m_d2dTargetBitmap; + + // DirectWrite drawing components. + Microsoft::WRL::ComPtr m_dwriteFactory; + Microsoft::WRL::ComPtr m_wicFactory; + + // Cached reference to the XAML panel. + Windows::UI::Xaml::Controls::SwapChainPanel^ m_swapChainPanel; + + // Cached device properties. + D3D_FEATURE_LEVEL m_d3dFeatureLevel; + Windows::Foundation::Size m_d3dRenderTargetSize; + Windows::Foundation::Size m_outputSize; + Windows::Foundation::Size m_logicalSize; + Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; + Windows::Graphics::Display::DisplayOrientations m_currentOrientation; + float m_dpi; + float m_compositionScaleX; + float m_compositionScaleY; + + + // Transforms used for display orientation. + D2D1::Matrix3x2F m_orientationTransform2D; + DirectX::XMFLOAT4X4 m_orientationTransform3D; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify; + }; +} \ No newline at end of file diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXHelper.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXHelper.h new file mode 100644 index 0000000000..52328ad017 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXHelper.h @@ -0,0 +1,89 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +#include + +namespace DX +{ + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + // Set a breakpoint on this line to catch Win32 API errors. + throw Platform::Exception::CreateException(hr); + } + } + + // Function that reads from a binary file asynchronously. + inline Concurrency::task> ReadDataAsync(const std::wstring& filename) + { + using namespace Windows::Storage; + using namespace Concurrency; + + auto folder = Windows::ApplicationModel::Package::Current->InstalledLocation; + + return create_task(folder->GetFileAsync(Platform::StringReference(filename.c_str()))).then([] (StorageFile^ file) + { + return FileIO::ReadBufferAsync(file); + }).then([] (Streams::IBuffer^ fileBuffer) -> std::vector + { + std::vector returnBuffer; + returnBuffer.resize(fileBuffer->Length); + Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference(returnBuffer.data(), fileBuffer->Length)); + return returnBuffer; + }); + } + + // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. + inline float ConvertDipsToPixels(float dips, float dpi) + { + static const float dipsPerInch = 96.0f; + return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. + } + + // Converts a length in physical pixels to a length in device-independent pixels (DIPs). + inline float ConvertPixelsToDips(float pixels) + { + static const float dipsPerInch = 96.0f; + return pixels * dipsPerInch / Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->LogicalDpi; // Do not round. + } + + // Converts a length in physical pixels to a length in device-independent pixels (DIPs) using the provided DPI. This removes the need + // to call this function from a thread associated with a CoreWindow, which is required by DisplayInformation::GetForCurrentView(). + inline float ConvertPixelsToDips(float pixels, float dpi) + { + static const float dipsPerInch = 96.0f; + return pixels * dipsPerInch / dpi; // Do not round. + } + +#if defined(_DEBUG) + // Check for SDK Layer support. + inline bool SdkLayersAvailable() + { + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + + return SUCCEEDED(hr); + } +#endif +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml new file mode 100644 index 0000000000..363a0089c7 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml.cpp b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml.cpp new file mode 100644 index 0000000000..f57c8ba503 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml.cpp @@ -0,0 +1,191 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "DirectXPage.xaml.h" +#include "DirectXHelper.h" + +using namespace SDKTemplate; + +using namespace concurrency; +using namespace Microsoft::WRL; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::Graphics::Display; +using namespace Windows::Storage; +using namespace Windows::Storage::Pickers; +using namespace Windows::Storage::Streams; +using namespace Windows::System::Threading; +using namespace Windows::UI::Core; +using namespace Windows::UI::Input; +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::Media; +using namespace Windows::UI::Xaml::Navigation; + +DirectXPage::DirectXPage() : + m_isWindowVisible(true) +{ + InitializeComponent(); + + // Register event handlers for page lifecycle. + CoreWindow^ window = Window::Current->CoreWindow; + + window->VisibilityChanged += + ref new TypedEventHandler(this, &DirectXPage::OnVisibilityChanged); + + DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); + + currentDisplayInformation->DpiChanged += + ref new TypedEventHandler(this, &DirectXPage::OnDpiChanged); + + currentDisplayInformation->OrientationChanged += + ref new TypedEventHandler(this, &DirectXPage::OnOrientationChanged); + + DisplayInformation::DisplayContentsInvalidated += + ref new TypedEventHandler(this, &DirectXPage::OnDisplayContentsInvalidated); + + swapChainPanel->CompositionScaleChanged += + ref new TypedEventHandler(this, &DirectXPage::OnCompositionScaleChanged); + + swapChainPanel->SizeChanged += + ref new SizeChangedEventHandler(this, &DirectXPage::OnSwapChainPanelSizeChanged); + + // At this point we have access to the device and + // can create the device-dependent resources. + m_deviceResources = std::make_shared(); + m_deviceResources->SetSwapChainPanel(swapChainPanel); + + m_renderer = std::unique_ptr(new D2DAdvancedColorImages(m_deviceResources)); +} + +DirectXPage::~DirectXPage() +{ +} + +void DirectXPage::LoadDefaultImage() +{ + Uri^ uri = ref new Uri("https://mediaplatstorage1.blob.core.windows.net/windows-universal-samples-media/image-scrgb-icc.jxr"); + create_task(StorageFile::CreateStreamedFileFromUriAsync(L"image-scRGB-ICC.jxr", uri, nullptr)).then([=](StorageFile^ imageFile) + { + LoadImage(imageFile); + }); +} + +void DirectXPage::LoadImage(StorageFile^ imageFile) +{ + create_task(imageFile->OpenAsync(FileAccessMode::Read)).then([=](task previousTask) { + IRandomAccessStream^ ras; + try + { + ras = previousTask.get(); + } + catch (...) + { + // If the file cannot be opened, then do nothing. + return; + } + + ComPtr iStream; + DX::ThrowIfFailed(CreateStreamOverRandomAccessStream(ras, IID_PPV_ARGS(&iStream))); + + m_renderer->LoadImage(iStream.Get()); + m_renderer->CreateImageDependentResources(); + m_renderer->FitImageToWindow(); + m_renderer->Draw(); + }); +} + +// UI element event handlers. + +void DirectXPage::LoadImageButtonClick(Object^ sender, RoutedEventArgs^ e) +{ + FileOpenPicker^ picker = ref new FileOpenPicker(); + picker->SuggestedStartLocation = PickerLocationId::Desktop; + picker->FileTypeFilter->Append(L".jxr"); + + create_task(picker->PickSingleFileAsync()).then([=](StorageFile^ pickedFile) { + if (pickedFile != nullptr) + { + LoadImage(pickedFile); + } + }); +} + +void DirectXPage::ResetButtonClick(Object^ sender, RoutedEventArgs^ e) +{ + LoadDefaultImage(); +} + +// Saves the current state of the app for suspend and terminate events. +void DirectXPage::SaveInternalState(_In_ IPropertySet^ state) +{ + m_deviceResources->Trim(); +} + +// Loads the current state of the app for resume events. +void DirectXPage::LoadInternalState(_In_ IPropertySet^ state) +{ +} + +// Window event handlers. + +void DirectXPage::OnVisibilityChanged(_In_ CoreWindow^ sender, _In_ VisibilityChangedEventArgs^ args) +{ + m_isWindowVisible = args->Visible; + if (m_isWindowVisible) + { + m_renderer->Draw(); + } +} + +// DisplayInformation event handlers. + +void DirectXPage::OnDpiChanged(_In_ DisplayInformation^ sender, _In_ Object^ args) +{ + m_deviceResources->SetDpi(sender->LogicalDpi); + m_renderer->CreateWindowSizeDependentResources(); + m_renderer->Draw(); +} + +void DirectXPage::OnOrientationChanged(_In_ DisplayInformation^ sender, _In_ Object^ args) +{ + m_deviceResources->SetCurrentOrientation(sender->CurrentOrientation); + m_renderer->CreateWindowSizeDependentResources(); + m_renderer->Draw(); +} + +void DirectXPage::OnDisplayContentsInvalidated(_In_ DisplayInformation^ sender, _In_ Object^ args) +{ + m_deviceResources->ValidateDevice(); + m_renderer->CreateWindowSizeDependentResources(); + m_renderer->Draw(); +} + +// Other event handlers. + +void DirectXPage::OnCompositionScaleChanged(_In_ SwapChainPanel^ sender, _In_ Object^ args) +{ + m_deviceResources->SetCompositionScale(sender->CompositionScaleX, sender->CompositionScaleY); + m_renderer->CreateWindowSizeDependentResources(); + m_renderer->Draw(); +} + +void DirectXPage::OnSwapChainPanelSizeChanged(_In_ Object^ sender, _In_ SizeChangedEventArgs^ e) +{ + m_deviceResources->SetLogicalSize(e->NewSize); + m_renderer->CreateWindowSizeDependentResources(); + m_renderer->Draw(); +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml.h new file mode 100644 index 0000000000..21a056ceba --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/DirectXPage.xaml.h @@ -0,0 +1,62 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +#include "DirectXPage.g.h" + +#include "DeviceResources.h" +#include "D2DAdvancedColorImagesRenderer.h" + +namespace SDKTemplate +{ + /// + /// A page that hosts the Direct2D app in a SwapChainPanel, and app UI in XAML. + /// + public ref class DirectXPage sealed + { + public: + DirectXPage(); + virtual ~DirectXPage(); + + void SaveInternalState(_In_ Windows::Foundation::Collections::IPropertySet^ state); + void LoadInternalState(_In_ Windows::Foundation::Collections::IPropertySet^ state); + + void LoadDefaultImage(); + void LoadImage(Windows::Storage::StorageFile^ imageFile); + + private: + // UI element event handlers. + void LoadImageButtonClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void ResetButtonClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + + // XAML low-level rendering event handler. + void OnRendering(_In_ Platform::Object^ sender, _In_ Platform::Object^ args); + + // Window event handlers. + void OnVisibilityChanged(_In_ Windows::UI::Core::CoreWindow^ sender, _In_ Windows::UI::Core::VisibilityChangedEventArgs^ args); + + // DisplayInformation event handlers. + void OnDpiChanged(_In_ Windows::Graphics::Display::DisplayInformation^ sender, _In_ Platform::Object^ args); + void OnOrientationChanged(_In_ Windows::Graphics::Display::DisplayInformation^ sender, _In_ Platform::Object^ args); + void OnDisplayContentsInvalidated(_In_ Windows::Graphics::Display::DisplayInformation^ sender, _In_ Platform::Object^ args); + + // Other event handlers. + void OnCompositionScaleChanged(_In_ Windows::UI::Xaml::Controls::SwapChainPanel^ sender, _In_ Object^ args); + void OnSwapChainPanelSizeChanged(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::SizeChangedEventArgs^ e); + + // Resources used to draw the DirectX content in the XAML page. + std::shared_ptr m_deviceResources; + std::unique_ptr m_renderer; + bool m_isWindowVisible; + }; +} + diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/Package.appxmanifest b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/Package.appxmanifest new file mode 100644 index 0000000000..4f79a899dd --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/Package.appxmanifest @@ -0,0 +1,53 @@ + + + + + + Direct2D Advanced Color Images C++ Sample + Microsoft Corporation + Assets\StoreLogo-sdk.png + + + + + + + + + + + + + + + + + + + + + + JPEG XR File + + .jxr + + + + + + + + + + diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.cpp b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.cpp new file mode 100644 index 0000000000..ee47216a5b --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.cpp @@ -0,0 +1,257 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include +#include "ToneMapEffect.h" +#include "BasicReaderWriter.h" + +#define XML(X) TEXT(#X) + +ToneMapEffect::ToneMapEffect() : + m_refCount(1) +{ +} + +HRESULT __stdcall ToneMapEffect::CreateToneMapImpl(_Outptr_ IUnknown** ppEffectImpl) +{ + // Since the object's refcount is initialized to 1, we don't need to AddRef here. + *ppEffectImpl = static_cast(new (std::nothrow) ToneMapEffect()); + + if (*ppEffectImpl == nullptr) + { + return E_OUTOFMEMORY; + } + else + { + return S_OK; + } +} + +HRESULT ToneMapEffect::Register(_In_ ID2D1Factory1* pFactory) +{ + // The inspectable metadata of an effect is defined in XML. This can be passed in from an external source + // as well, however for simplicity we just inline the XML. + PCWSTR pszXml = + XML( + + + + + + + + + + + + + ); + + // This registers the effect with the factory, which will make the effect + // instantiatable. + return pFactory->RegisterEffectFromString( + CLSID_CustomToneMapEffect, + pszXml, + nullptr, + 0, + CreateToneMapImpl + ); +} + +IFACEMETHODIMP ToneMapEffect::Initialize( + _In_ ID2D1EffectContext* pEffectContext, + _In_ ID2D1TransformGraph* pTransformGraph + ) +{ + BasicReaderWriter^ reader = ref new BasicReaderWriter(); + Platform::Array^ data; + + try + { + data = reader->ReadData("ToneMapEffect.cso"); + } + catch (Platform::Exception^ e) + { + // Return error if file can not be read. + return e->HResult; + } + + HRESULT hr = pEffectContext->LoadPixelShader(GUID_ToneMapPixelShader, data->Data, data->Length); + + // This loads the shader into the Direct2D image effects system and associates it with the GUID passed in. + // If this method is called more than once (say by other instances of the effect) with the same GUID, + // the system will simply do nothing, ensuring that only one instance of a shader is stored regardless of how + // many time it is used. + if (SUCCEEDED(hr)) + { + // The graph consists of a single transform. In fact, this class is the transform, + // reducing the complexity of implementing an effect when all we need to + // do is use a single pixel shader. + hr = pTransformGraph->SetSingleTransformNode(this); + } + + return hr; +} + +IFACEMETHODIMP ToneMapEffect::PrepareForRender(D2D1_CHANGE_TYPE changeType) +{ + return S_OK; +} + +// SetGraph is only called when the number of inputs changes. This never happens as we publish this effect +// as a single input effect. +IFACEMETHODIMP ToneMapEffect::SetGraph(_In_ ID2D1TransformGraph* pGraph) +{ + return E_NOTIMPL; +} + +// Called to assign a new render info class, which is used to inform D2D on +// how to set the state of the GPU. +IFACEMETHODIMP ToneMapEffect::SetDrawInfo(_In_ ID2D1DrawInfo* pDrawInfo) +{ + m_drawInfo = pDrawInfo; + + return m_drawInfo->SetPixelShader(GUID_ToneMapPixelShader); +} + +// Calculates the mapping between the output and input rects. +IFACEMETHODIMP ToneMapEffect::MapOutputRectToInputRects( + _In_ const D2D1_RECT_L* pOutputRect, + _Out_writes_(inputRectCount) D2D1_RECT_L* pInputRects, + UINT32 inputRectCount + ) const +{ + // This effect has exactly one input, so if there is more than one input rect, + // something is wrong. + if (inputRectCount != 1) + { + return E_INVALIDARG; + } + + pInputRects[0].left = pOutputRect->left; + pInputRects[0].top = pOutputRect->top; + pInputRects[0].right = pOutputRect->right; + pInputRects[0].bottom = pOutputRect->bottom; + + return S_OK; +} + +IFACEMETHODIMP ToneMapEffect::MapInputRectsToOutputRect( + _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputRects, + _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputOpaqueSubRects, + UINT32 inputRectCount, + _Out_ D2D1_RECT_L* pOutputRect, + _Out_ D2D1_RECT_L* pOutputOpaqueSubRect + ) +{ + // This effect has exactly one input, so if there is more than one input rect, + // something is wrong. + if (inputRectCount != 1) + { + return E_INVALIDARG; + } + + *pOutputRect = pInputRects[0]; + m_inputRect = pInputRects[0]; + + // Indicate that entire output might contain transparency. + ZeroMemory(pOutputOpaqueSubRect, sizeof(*pOutputOpaqueSubRect)); + + return S_OK; +} + +IFACEMETHODIMP ToneMapEffect::MapInvalidRect( + UINT32 inputIndex, + D2D1_RECT_L invalidInputRect, + _Out_ D2D1_RECT_L* pInvalidOutputRect + ) const +{ + HRESULT hr = S_OK; + + // Indicate that the entire output may be invalid. + *pInvalidOutputRect = m_inputRect; + + return hr; +} + +IFACEMETHODIMP_(UINT32) ToneMapEffect::GetInputCount() const +{ + return 1; +} + +// D2D ensures that that effects are only referenced from one thread at a time. +// To improve performance, we simply increment/decrement our reference count +// rather than use atomic InterlockedIncrement()/InterlockedDecrement() functions. +IFACEMETHODIMP_(ULONG) ToneMapEffect::AddRef() +{ + m_refCount++; + return m_refCount; +} + +IFACEMETHODIMP_(ULONG) ToneMapEffect::Release() +{ + m_refCount--; + + if (m_refCount == 0) + { + delete this; + return 0; + } + else + { + return m_refCount; + } +} + +// This enables the stack of parent interfaces to be queried. In the instance +// of the ToneMap interface, this method simply enables the developer +// to cast a ToneMap instance to an ID2D1EffectImpl or IUnknown instance. +IFACEMETHODIMP ToneMapEffect::QueryInterface( + _In_ REFIID riid, + _Outptr_ void** ppOutput + ) +{ + *ppOutput = nullptr; + HRESULT hr = S_OK; + + if (riid == __uuidof(ID2D1EffectImpl)) + { + *ppOutput = reinterpret_cast(this); + } + else if (riid == __uuidof(ID2D1DrawTransform)) + { + *ppOutput = static_cast(this); + } + else if (riid == __uuidof(ID2D1Transform)) + { + *ppOutput = static_cast(this); + } + else if (riid == __uuidof(ID2D1TransformNode)) + { + *ppOutput = static_cast(this); + } + else if (riid == __uuidof(IUnknown)) + { + *ppOutput = this; + } + else + { + hr = E_NOINTERFACE; + } + + if (*ppOutput != nullptr) + { + AddRef(); + } + + return hr; +} diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.h new file mode 100644 index 0000000000..3d1bad1b03 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.h @@ -0,0 +1,97 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +DEFINE_GUID(GUID_ToneMapPixelShader, 0x6716FB29, 0x06A0, 0x460F, 0xAA, 0x9C, 0x8B, 0x8F, 0xF0, 0x33, 0x5E, 0xA6); +DEFINE_GUID(CLSID_CustomToneMapEffect, 0xB7B36C92, 0x3498, 0x4A94, 0x9E, 0x95, 0x9F, 0x24, 0x6F, 0x92, 0x45, 0xBF); + +// Our effect contains one transform, which is simply a wrapper around a pixel shader. As such, +// we can simply make the effect itself act as the transform. +class ToneMapEffect : public ID2D1EffectImpl, public ID2D1DrawTransform +{ +public: + // Declare effect registration methods. + static HRESULT Register(_In_ ID2D1Factory1* pFactory); + + static HRESULT __stdcall CreateToneMapImpl(_Outptr_ IUnknown** ppEffectImpl); + + // Declare ID2D1EffectImpl implementation methods. + IFACEMETHODIMP Initialize( + _In_ ID2D1EffectContext* pContextInternal, + _In_ ID2D1TransformGraph* pTransformGraph + ); + + IFACEMETHODIMP PrepareForRender(D2D1_CHANGE_TYPE changeType); + + IFACEMETHODIMP SetGraph(_In_ ID2D1TransformGraph* pGraph); + + // Declare ID2D1DrawTransform implementation methods. + IFACEMETHODIMP SetDrawInfo(_In_ ID2D1DrawInfo* pRenderInfo); + + // Declare ID2D1Transform implementation methods. + IFACEMETHODIMP MapOutputRectToInputRects( + _In_ const D2D1_RECT_L* pOutputRect, + _Out_writes_(inputRectCount) D2D1_RECT_L* pInputRects, + UINT32 inputRectCount + ) const; + + IFACEMETHODIMP MapInputRectsToOutputRect( + _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputRects, + _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputOpaqueSubRects, + UINT32 inputRectCount, + _Out_ D2D1_RECT_L* pOutputRect, + _Out_ D2D1_RECT_L* pOutputOpaqueSubRect + ); + + IFACEMETHODIMP MapInvalidRect( + UINT32 inputIndex, + D2D1_RECT_L invalidInputRect, + _Out_ D2D1_RECT_L* pInvalidOutputRect + ) const; + + // Declare ID2D1TransformNode implementation methods. + IFACEMETHODIMP_(UINT32) GetInputCount() const; + + // Declare IUnknown implementation methods. + IFACEMETHODIMP_(ULONG) AddRef(); + IFACEMETHODIMP_(ULONG) Release(); + IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void** ppOutput); + +private: + ToneMapEffect(); + HRESULT UpdateConstants(); + + inline static float Clamp(float v, float low, float high) + { + return (v < low) ? low : (v > high) ? high : v; + } + + inline static float Round(float v) + { + return floor(v + 0.5f); + } + + // Prevents over/underflows when adding longs. + inline static long SafeAdd(long base, long valueToAdd) + { + if (valueToAdd >= 0) + { + return ((base + valueToAdd) >= base) ? (base + valueToAdd) : LONG_MAX; + } + else + { + return ((base + valueToAdd) <= base) ? (base + valueToAdd) : LONG_MIN; + } + } + + Microsoft::WRL::ComPtr m_drawInfo; + ULONG m_refCount; + D2D1_RECT_L m_inputRect; +}; diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.hlsl b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.hlsl new file mode 100644 index 0000000000..b95fa80d02 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/ToneMapEffect.hlsl @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +// Custom effects using pixel shaders should use HLSL helper functions defined in +// d2d1effecthelpers.hlsli to make use of effect shader linking. +#define D2D_INPUT_COUNT 1 // The pixel shader takes 1 input texture. +#define D2D_INPUT0_SIMPLE + +// Note that the custom build step must provide the correct path to find d2d1effecthelpers.hlsli when calling fxc.exe. +#include "d2d1effecthelpers.hlsli" + +// Implements an extremely rudimentary HDR-to-SDR tone mapping effect. This is a +// simplified version of the Reinhard tone mapping algorithm, applied directly +// to the RGB channels. It successfully maps any content into the SDR range +// (i.e. 0.0f - 1.0f), but highlights will tend to be compressed, and color +// shifting can occur. +D2D_PS_ENTRY(main) +{ + // Basic formula: for each color value x of each pixel, return (x / (x+1)). + float4 color = D2DGetInput(0); + return (color / (color + 1.0f)); +} \ No newline at end of file diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/pch.cpp b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/pch.cpp new file mode 100644 index 0000000000..14ef4dbcf3 --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/pch.cpp @@ -0,0 +1,12 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" diff --git a/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/pch.h b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/pch.h new file mode 100644 index 0000000000..3ae8b0a5fe --- /dev/null +++ b/Samples/D2DAdvancedColorImages/cpp/D2DAdvancedColorImages/pch.h @@ -0,0 +1,30 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include \ No newline at end of file diff --git a/Samples/D2DCustomEffects/cpp/D2DCustomEffects.sln b/Samples/D2DCustomEffects/cpp/D2DCustomEffects.sln index 9fe2cfe2ea..7e20d01bfa 100644 --- a/Samples/D2DCustomEffects/cpp/D2DCustomEffects.sln +++ b/Samples/D2DCustomEffects/cpp/D2DCustomEffects.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomVertexShader", "VertexShader\CustomVertexShader.vcxproj", "{A11F5806-3EDC-5CA8-B43F-E28ABA9BA19F}" EndProject diff --git a/Samples/D2DGradientMesh/cpp/D2DGradientMesh.sln b/Samples/D2DGradientMesh/cpp/D2DGradientMesh.sln index 6e5ad750ad..300553ce2c 100644 --- a/Samples/D2DGradientMesh/cpp/D2DGradientMesh.sln +++ b/Samples/D2DGradientMesh/cpp/D2DGradientMesh.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 for Windows -VisualStudioVersion = 12.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D2DGradientMesh", "D2DGradientMesh.vcxproj", "{120D27DA-64D3-5996-A34A-4FE5202283A2}" EndProject diff --git a/Samples/D2DPhotoAdjustment/cpp/D2DPhotoAdjustment.sln b/Samples/D2DPhotoAdjustment/cpp/D2DPhotoAdjustment.sln index 379b8465f7..785fd16098 100644 --- a/Samples/D2DPhotoAdjustment/cpp/D2DPhotoAdjustment.sln +++ b/Samples/D2DPhotoAdjustment/cpp/D2DPhotoAdjustment.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22919.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D2DPhotoAdjustment", "D2DPhotoAdjustment.vcxproj", "{ADFDDC2F-F8C9-58A6-AB25-A9E504709139}" EndProject diff --git a/Samples/D2DSvgImage/cpp/D2DSvgImage.sln b/Samples/D2DSvgImage/cpp/D2DSvgImage.sln index a7137dc3f6..40350de1f5 100644 --- a/Samples/D2DSvgImage/cpp/D2DSvgImage.sln +++ b/Samples/D2DSvgImage/cpp/D2DSvgImage.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22919.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D2DSvgImage", "D2DSvgImage.vcxproj", "{709D89E0-15F3-5237-9284-BB434D0C174E}" EndProject diff --git a/Samples/DWriteColorGlyph/cpp/DWriteColorTextRenderer.sln b/Samples/DWriteColorGlyph/cpp/DWriteColorTextRenderer.sln index 297b443201..3808a8f93b 100644 --- a/Samples/DWriteColorGlyph/cpp/DWriteColorTextRenderer.sln +++ b/Samples/DWriteColorGlyph/cpp/DWriteColorTextRenderer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 for Windows -VisualStudioVersion = 12.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DWriteColorTextRenderer", "DWriteColorTextRenderer.vcxproj", "{4A6477C6-9928-5705-B8EF-1ACE17EF988C}" EndProject diff --git a/Samples/DWriteLineSpacingModes/cpp/DWriteLineSpacingModes.sln b/Samples/DWriteLineSpacingModes/cpp/DWriteLineSpacingModes.sln index 3f9cda8020..4b7475f6b0 100644 --- a/Samples/DWriteLineSpacingModes/cpp/DWriteLineSpacingModes.sln +++ b/Samples/DWriteLineSpacingModes/cpp/DWriteLineSpacingModes.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DWriteLineSpacingModes", "DWriteLineSpacingModes\DWriteLineSpacingModes.vcxproj", "{4F77839D-B622-53CF-8A81-18DC6B69F53A}" EndProject diff --git a/Samples/DWriteTextLayoutCloudFont/cpp/DWriteTextLayoutCloudFont.sln b/Samples/DWriteTextLayoutCloudFont/cpp/DWriteTextLayoutCloudFont.sln index 2ef4921210..00bc955de1 100644 --- a/Samples/DWriteTextLayoutCloudFont/cpp/DWriteTextLayoutCloudFont.sln +++ b/Samples/DWriteTextLayoutCloudFont/cpp/DWriteTextLayoutCloudFont.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DWriteTextLayoutCloudFont", "DWriteTextLayoutCloudFont\DWriteTextLayoutCloudFont.vcxproj", "{722C35E5-AC26-5234-AEB8-A6A6A892BAE1}" EndProject diff --git a/Samples/DataReaderWriter/cpp/DataReaderWriter.sln b/Samples/DataReaderWriter/cpp/DataReaderWriter.sln index af20e0efcd..91116048ab 100644 --- a/Samples/DataReaderWriter/cpp/DataReaderWriter.sln +++ b/Samples/DataReaderWriter/cpp/DataReaderWriter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DataReaderWriter", "DataReaderWriter.vcxproj", "{1ADD77AD-ECA6-5777-8B2A-E4AFEBFE5C79}" EndProject diff --git a/Samples/DataReaderWriter/cs/DataReaderWriter.sln b/Samples/DataReaderWriter/cs/DataReaderWriter.sln index 0a3d92e777..21edcca7ed 100644 --- a/Samples/DataReaderWriter/cs/DataReaderWriter.sln +++ b/Samples/DataReaderWriter/cs/DataReaderWriter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataReaderWriter", "DataReaderWriter.csproj", "{1E2C8C98-AF93-59A6-8B9C-B5549C0F8DF0}" EndProject diff --git a/Samples/DataReaderWriter/js/DataReaderWriter.sln b/Samples/DataReaderWriter/js/DataReaderWriter.sln index bfec532379..b7061f0f67 100644 --- a/Samples/DataReaderWriter/js/DataReaderWriter.sln +++ b/Samples/DataReaderWriter/js/DataReaderWriter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "DataReaderWriter", "DataReaderWriter.jsproj", "{1AF09AE8-6572-5277-81D8-58FF2C6A4CC0}" EndProject diff --git a/Samples/DatagramSocket/cpp/DatagramSocket.sln b/Samples/DatagramSocket/cpp/DatagramSocket.sln index dbf9cf549f..a14423f9cc 100644 --- a/Samples/DatagramSocket/cpp/DatagramSocket.sln +++ b/Samples/DatagramSocket/cpp/DatagramSocket.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DatagramSocket", "DatagramSocket.vcxproj", "{A7451945-8E82-54EA-B15A-DA734014A2DF}" EndProject diff --git a/Samples/DatagramSocket/cs/DatagramSocket.sln b/Samples/DatagramSocket/cs/DatagramSocket.sln index dd979f79fb..f743c9cd07 100644 --- a/Samples/DatagramSocket/cs/DatagramSocket.sln +++ b/Samples/DatagramSocket/cs/DatagramSocket.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatagramSocket", "DatagramSocket.csproj", "{F9EA67D4-792F-57A8-999C-A957752789BB}" EndProject diff --git a/Samples/DatagramSocket/js/DatagramSocket.sln b/Samples/DatagramSocket/js/DatagramSocket.sln index 7ee2aeea86..bd72ac97bc 100644 --- a/Samples/DatagramSocket/js/DatagramSocket.sln +++ b/Samples/DatagramSocket/js/DatagramSocket.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "DatagramSocket", "DatagramSocket.jsproj", "{95BBA096-3567-58FA-8005-091DBD9E8B4E}" EndProject diff --git a/Samples/DateTimeFormatting/cpp/DateTimeFormatting.sln b/Samples/DateTimeFormatting/cpp/DateTimeFormatting.sln index 10e86f5683..2b99903822 100644 --- a/Samples/DateTimeFormatting/cpp/DateTimeFormatting.sln +++ b/Samples/DateTimeFormatting/cpp/DateTimeFormatting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DateTimeFormatting", "DateTimeFormatting.vcxproj", "{61B9ED3B-28D0-5A0F-9209-A6C9D5D7E11B}" EndProject diff --git a/Samples/DateTimeFormatting/cs/DateTimeFormatting.sln b/Samples/DateTimeFormatting/cs/DateTimeFormatting.sln index 090f46f1a9..76ff8f86e4 100644 --- a/Samples/DateTimeFormatting/cs/DateTimeFormatting.sln +++ b/Samples/DateTimeFormatting/cs/DateTimeFormatting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DateTimeFormatting", "DateTimeFormatting.csproj", "{0CADC458-5949-5EC6-AF80-28935DA66EAD}" EndProject diff --git a/Samples/DateTimeFormatting/js/DateTimeFormatting.sln b/Samples/DateTimeFormatting/js/DateTimeFormatting.sln index 098482bc21..9e367150e8 100644 --- a/Samples/DateTimeFormatting/js/DateTimeFormatting.sln +++ b/Samples/DateTimeFormatting/js/DateTimeFormatting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "DateTimeFormatting", "DateTimeFormatting.jsproj", "{823C52C3-8346-5E74-B766-0297E332D181}" EndProject diff --git a/Samples/DeviceEnumerationAndPairing/cpp/DeviceEnumeration.sln b/Samples/DeviceEnumerationAndPairing/cpp/DeviceEnumeration.sln index c36c8c2c9f..28745d36b8 100644 --- a/Samples/DeviceEnumerationAndPairing/cpp/DeviceEnumeration.sln +++ b/Samples/DeviceEnumerationAndPairing/cpp/DeviceEnumeration.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeviceEnumeration", "DeviceEnumeration.vcxproj", "{F23BD31A-138D-5C35-B1FC-52B6D76BB4F2}" EndProject diff --git a/Samples/DeviceEnumerationAndPairing/cs/DeviceEnumeration.sln b/Samples/DeviceEnumerationAndPairing/cs/DeviceEnumeration.sln index f30d66b8d2..adafe90269 100644 --- a/Samples/DeviceEnumerationAndPairing/cs/DeviceEnumeration.sln +++ b/Samples/DeviceEnumerationAndPairing/cs/DeviceEnumeration.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceEnumeration", "DeviceEnumeration.csproj", "{6986B83D-0A00-5E76-9EAA-3D63090573BC}" EndProject diff --git a/Samples/DeviceEnumerationAndPairing/js/DeviceEnumeration.sln b/Samples/DeviceEnumerationAndPairing/js/DeviceEnumeration.sln index 8afbeb2035..78367ce3fe 100644 --- a/Samples/DeviceEnumerationAndPairing/js/DeviceEnumeration.sln +++ b/Samples/DeviceEnumerationAndPairing/js/DeviceEnumeration.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22810.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "DeviceEnumeration", "DeviceEnumeration.jsproj", "{360AC149-73E7-59E6-ABAD-7FC15F3F0706}" EndProject diff --git a/Samples/DeviceLockdownAzureLogin/cs/DeviceLockdownAzureLogin.sln b/Samples/DeviceLockdownAzureLogin/cs/DeviceLockdownAzureLogin.sln index 9bef86d6ad..b9b274fbf6 100644 --- a/Samples/DeviceLockdownAzureLogin/cs/DeviceLockdownAzureLogin.sln +++ b/Samples/DeviceLockdownAzureLogin/cs/DeviceLockdownAzureLogin.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceLockdownAzureLogin", "DeviceLockdownAzureLogin.csproj", "{8F466084-8AAC-5855-BE98-C81AAB4859A2}" EndProject diff --git a/Samples/DisablingScreenCapture/cpp/DisablingScreenCapture.sln b/Samples/DisablingScreenCapture/cpp/DisablingScreenCapture.sln index 14bc0d138c..c5b34fc819 100644 --- a/Samples/DisablingScreenCapture/cpp/DisablingScreenCapture.sln +++ b/Samples/DisablingScreenCapture/cpp/DisablingScreenCapture.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DisablingScreenCapture", "DisablingScreenCapture.vcxproj", "{222364B2-69A1-53C1-A7CD-25215937D32C}" EndProject diff --git a/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.sln b/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.sln index 346bef17ba..faa6d4f607 100644 --- a/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.sln +++ b/Samples/DisablingScreenCapture/cs/DisablingScreenCapture.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DisablingScreenCapture", "DisablingScreenCapture.csproj", "{0B9BA47E-BE34-5C9E-8885-A5FDD167C3DC}" EndProject diff --git a/Samples/DisablingScreenCapture/js/DisablingScreenCapture.sln b/Samples/DisablingScreenCapture/js/DisablingScreenCapture.sln index 3174ee22b3..c6af362338 100644 --- a/Samples/DisablingScreenCapture/js/DisablingScreenCapture.sln +++ b/Samples/DisablingScreenCapture/js/DisablingScreenCapture.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "DisablingScreenCapture", "DisablingScreenCapture.jsproj", "{124AB1BE-40C4-52DB-82FC-35CC26154100}" EndProject diff --git a/Samples/DisplayOrientation/cpp/DisplayOrientation.sln b/Samples/DisplayOrientation/cpp/DisplayOrientation.sln index 187ccfde59..fd6c102904 100644 --- a/Samples/DisplayOrientation/cpp/DisplayOrientation.sln +++ b/Samples/DisplayOrientation/cpp/DisplayOrientation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DisplayOrientation", "DisplayOrientation.vcxproj", "{739861F5-40E8-5876-BCEA-26097F74D665}" EndProject diff --git a/Samples/DisplayOrientation/cs/DisplayOrientation.sln b/Samples/DisplayOrientation/cs/DisplayOrientation.sln index 4b9e46fadd..184d864fbb 100644 --- a/Samples/DisplayOrientation/cs/DisplayOrientation.sln +++ b/Samples/DisplayOrientation/cs/DisplayOrientation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DisplayOrientation", "DisplayOrientation.csproj", "{82FDFFEA-B069-589E-A5A5-BED9E5FB069A}" EndProject diff --git a/Samples/DisplayOrientation/js/DisplayOrientation.sln b/Samples/DisplayOrientation/js/DisplayOrientation.sln index 8508756c98..2e2cfef78d 100644 --- a/Samples/DisplayOrientation/js/DisplayOrientation.sln +++ b/Samples/DisplayOrientation/js/DisplayOrientation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "DisplayOrientation", "DisplayOrientation.jsproj", "{05619A22-114C-5E97-AF32-288F85B664E8}" EndProject diff --git a/Samples/DpiScaling/cpp/DpiScaling.sln b/Samples/DpiScaling/cpp/DpiScaling.sln index 32dd005944..7959d1fed7 100644 --- a/Samples/DpiScaling/cpp/DpiScaling.sln +++ b/Samples/DpiScaling/cpp/DpiScaling.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DpiScaling", "DpiScaling.vcxproj", "{22274EC0-6160-508B-BF85-DDE53B83D512}" EndProject diff --git a/Samples/DpiScaling/cs/DpiScaling.sln b/Samples/DpiScaling/cs/DpiScaling.sln index 7ccb1fbebf..1ad5a890b7 100644 --- a/Samples/DpiScaling/cs/DpiScaling.sln +++ b/Samples/DpiScaling/cs/DpiScaling.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DpiScaling", "DpiScaling.csproj", "{6346FF86-4BBF-5459-8864-DF2186EBE58E}" EndProject diff --git a/Samples/DpiScaling/js/DpiScaling.sln b/Samples/DpiScaling/js/DpiScaling.sln index 868ab09c3d..1725407cb0 100644 --- a/Samples/DpiScaling/js/DpiScaling.sln +++ b/Samples/DpiScaling/js/DpiScaling.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "DpiScaling", "DpiScaling.jsproj", "{3F0B0EBD-D1D0-5583-861D-AAD0CEEB95F8}" EndProject diff --git a/Samples/EfficientAnimations/js/EfficientAnimations.sln b/Samples/EfficientAnimations/js/EfficientAnimations.sln index 5c7b0750de..f5ea959467 100644 --- a/Samples/EfficientAnimations/js/EfficientAnimations.sln +++ b/Samples/EfficientAnimations/js/EfficientAnimations.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "EfficientAnimations", "EfficientAnimations.jsproj", "{E68B216F-D4C8-57A2-AEE3-60E887F1BFAF}" EndProject diff --git a/Samples/EnterpriseDataProtection/cs/EnterpriseDataProtection.sln b/Samples/EnterpriseDataProtection/cs/EnterpriseDataProtection.sln index a92a40798b..6f2a8433be 100644 --- a/Samples/EnterpriseDataProtection/cs/EnterpriseDataProtection.sln +++ b/Samples/EnterpriseDataProtection/cs/EnterpriseDataProtection.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnterpriseDataProtection", "EnterpriseDataProtection.csproj", "{A19A9412-4A58-54FF-B42C-D60EC5FABB48}" EndProject diff --git a/Samples/ExtendedExecution/cpp/ExtendedExecution.sln b/Samples/ExtendedExecution/cpp/ExtendedExecution.sln index 1f35bec090..c067d18de2 100644 --- a/Samples/ExtendedExecution/cpp/ExtendedExecution.sln +++ b/Samples/ExtendedExecution/cpp/ExtendedExecution.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExtendedExecution", "ExtendedExecution.vcxproj", "{E8E4655E-EC7D-5878-B4AA-CDC13769CB8D}" EndProject diff --git a/Samples/ExtendedExecution/cpp/SampleConfiguration.h b/Samples/ExtendedExecution/cpp/SampleConfiguration.h index bc42fe9be3..2275e3152f 100644 --- a/Samples/ExtendedExecution/cpp/SampleConfiguration.h +++ b/Samples/ExtendedExecution/cpp/SampleConfiguration.h @@ -23,7 +23,7 @@ namespace SDKTemplate { Platform::String^ get() { - return "Resize app view"; + return "Extended Execution"; } } diff --git a/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.cpp b/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.cpp index 3c85b04f55..bbb6d67298 100644 --- a/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.cpp +++ b/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.cpp @@ -42,7 +42,7 @@ void SavingDataReason::OnNavigatingFrom(NavigatingCancelEventArgs^ e) void SavingDataReason::OnSuspending(Object^ sender, SuspendingEventArgs^ args) { - SuspendingDeferral^ suspendDeferral = args->SuspendingOperation->GetDeferral(); + suspendDeferral = args->SuspendingOperation->GetDeferral(); rootPage->NotifyUser("", NotifyType::StatusMessage); @@ -91,11 +91,15 @@ void SavingDataReason::OnSuspending(Object^ sender, SuspendingEventArgs^ args) }); break; } - }).then([this, session, revokedToken, suspendDeferral]() + }).then([this, session, revokedToken]() { session->Revoked -= revokedToken; delete session; - suspendDeferral->Complete(); + if (suspendDeferral != nullptr) + { + suspendDeferral->Complete(); + suspendDeferral = nullptr; + } }); } @@ -119,5 +123,11 @@ void SavingDataReason::ExtendedExecutionSessionRevoked(Object^ sender, ExtendedE rootPage->NotifyUser("Extended execution revoked due to system policy.", NotifyType::StatusMessage); break; } + + if (suspendDeferral != nullptr) + { + suspendDeferral->Complete(); + suspendDeferral = nullptr; + } })); } diff --git a/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.h b/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.h index 44fcd09ad9..5f8672addc 100644 --- a/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.h +++ b/Samples/ExtendedExecution/cpp/Scenario2_SavingDataReason.xaml.h @@ -33,6 +33,7 @@ namespace SDKTemplate MainPage^ rootPage = MainPage::Current; Concurrency::cancellation_token_source cancellationTokenSource; Windows::Foundation::EventRegistrationToken suspendingToken; + Windows::ApplicationModel::SuspendingDeferral^ suspendDeferral = nullptr; void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args); void ExtendedExecutionSessionRevoked(Platform::Object^ sender, Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionRevokedEventArgs^ args); diff --git a/Samples/ExtendedExecution/cs/ExtendedExecution.sln b/Samples/ExtendedExecution/cs/ExtendedExecution.sln index f438f12a66..555cbff904 100644 --- a/Samples/ExtendedExecution/cs/ExtendedExecution.sln +++ b/Samples/ExtendedExecution/cs/ExtendedExecution.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtendedExecution", "ExtendedExecution.csproj", "{0F6ED68B-4C24-57AE-9340-56A0DB0CDFEE}" EndProject diff --git a/Samples/ExtendedExecution/cs/Scenario2_SavingDataReason.xaml.cs b/Samples/ExtendedExecution/cs/Scenario2_SavingDataReason.xaml.cs index f8cd8f7fc2..8723e7baf2 100644 --- a/Samples/ExtendedExecution/cs/Scenario2_SavingDataReason.xaml.cs +++ b/Samples/ExtendedExecution/cs/Scenario2_SavingDataReason.xaml.cs @@ -30,6 +30,7 @@ public sealed partial class SavingDataReason : Page private MainPage rootPage = MainPage.Current; private CancellationTokenSource cancellationTokenSource; + private SuspendingDeferral suspendDeferral; public SavingDataReason() { @@ -49,7 +50,7 @@ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) private async void OnSuspending(object sender, SuspendingEventArgs args) { - SuspendingDeferral suspendDeferral = args.SuspendingOperation.GetDeferral(); + suspendDeferral = args.SuspendingOperation.GetDeferral(); rootPage.NotifyUser("", NotifyType.StatusMessage); @@ -87,7 +88,8 @@ private async void OnSuspending(object sender, SuspendingEventArgs args) session.Revoked -= ExtendedExecutionSessionRevoked; } - suspendDeferral.Complete(); + suspendDeferral?.Complete(); + suspendDeferral = null; } private async void ExtendedExecutionSessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args) @@ -110,6 +112,9 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => rootPage.NotifyUser("Extended execution revoked due to system policy.", NotifyType.StatusMessage); break; } + + suspendDeferral?.Complete(); + suspendDeferral = null; }); } } diff --git a/Samples/FeedReader/js/FeedReader.sln b/Samples/FeedReader/js/FeedReader.sln index 49289cbc3a..3eb739006a 100644 --- a/Samples/FeedReader/js/FeedReader.sln +++ b/Samples/FeedReader/js/FeedReader.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "FeedReader", "FeedReader.jsproj", "{BF23EFA9-34DB-556B-B6BD-87664A5C79E0}" EndProject diff --git a/Samples/FileAccess/cpp/FileAccess.sln b/Samples/FileAccess/cpp/FileAccess.sln index bd886f6548..c10741b33f 100644 --- a/Samples/FileAccess/cpp/FileAccess.sln +++ b/Samples/FileAccess/cpp/FileAccess.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileAccess", "FileAccess.vcxproj", "{AF58FC68-630E-543A-A2ED-E7B94E190BC4}" EndProject diff --git a/Samples/FileAccess/cs/FileAccess.sln b/Samples/FileAccess/cs/FileAccess.sln index dd326742c0..548cd8af9e 100644 --- a/Samples/FileAccess/cs/FileAccess.sln +++ b/Samples/FileAccess/cs/FileAccess.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileAccess", "FileAccess.csproj", "{EADFCFC5-D1A0-5C8B-BA40-3922AE772303}" EndProject diff --git a/Samples/FileAccess/js/FileAccess.sln b/Samples/FileAccess/js/FileAccess.sln index 0f550bbc17..ba8b88d6e8 100644 --- a/Samples/FileAccess/js/FileAccess.sln +++ b/Samples/FileAccess/js/FileAccess.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "FileAccess", "FileAccess.jsproj", "{BBEC713F-14F7-5DFE-AC68-28B2AC3E97BD}" EndProject diff --git a/Samples/FilePicker/cpp/FilePicker.sln b/Samples/FilePicker/cpp/FilePicker.sln index 17b1721032..f7d072849b 100644 --- a/Samples/FilePicker/cpp/FilePicker.sln +++ b/Samples/FilePicker/cpp/FilePicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FilePicker", "FilePicker.vcxproj", "{AFBE3775-ED39-59EC-8159-AB5ADD9662C1}" EndProject diff --git a/Samples/FilePicker/cs/FilePicker.sln b/Samples/FilePicker/cs/FilePicker.sln index 673ad8fe89..9471c41ecb 100644 --- a/Samples/FilePicker/cs/FilePicker.sln +++ b/Samples/FilePicker/cs/FilePicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FilePicker", "FilePicker.csproj", "{314C397F-9301-5E7D-A6D0-8631702D610D}" EndProject diff --git a/Samples/FilePicker/js/FilePicker.sln b/Samples/FilePicker/js/FilePicker.sln index a57ab9a6c9..7f272f0c08 100644 --- a/Samples/FilePicker/js/FilePicker.sln +++ b/Samples/FilePicker/js/FilePicker.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "FilePicker", "FilePicker.jsproj", "{3FAEFBB7-151C-57C1-84B1-39B766D332A7}" EndProject diff --git a/Samples/FilePickerContracts/cs/FilePickerContracts.sln b/Samples/FilePickerContracts/cs/FilePickerContracts.sln index 05a1050bc3..b524892564 100644 --- a/Samples/FilePickerContracts/cs/FilePickerContracts.sln +++ b/Samples/FilePickerContracts/cs/FilePickerContracts.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FilePickerContracts", "FilePickerContracts.csproj", "{B3E8B6D5-E89E-5AF2-A079-5F1001C71A6B}" EndProject diff --git a/Samples/FileSearch/cpp/FileSearch.sln b/Samples/FileSearch/cpp/FileSearch.sln index 8667842992..1bd39b867f 100644 --- a/Samples/FileSearch/cpp/FileSearch.sln +++ b/Samples/FileSearch/cpp/FileSearch.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileSearch", "FileSearch.vcxproj", "{ED285012-A37D-5FB3-91A6-D6796FCFEC8A}" EndProject diff --git a/Samples/FileSearch/cs/FileSearch.sln b/Samples/FileSearch/cs/FileSearch.sln index 143c8806b5..1728cc4ba4 100644 --- a/Samples/FileSearch/cs/FileSearch.sln +++ b/Samples/FileSearch/cs/FileSearch.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileSearch", "FileSearch.csproj", "{C043CA94-CAD8-5EDD-91DD-67E206744A29}" EndProject diff --git a/Samples/FileSearch/js/FileSearch.sln b/Samples/FileSearch/js/FileSearch.sln index 883868d9aa..22ee1f4495 100644 --- a/Samples/FileSearch/js/FileSearch.sln +++ b/Samples/FileSearch/js/FileSearch.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "FileSearch", "FileSearch.jsproj", "{01F9BB7A-8A3E-5A6F-A5B6-E8A705F196E0}" EndProject diff --git a/Samples/FileThumbnails/cpp/FileThumbnails.sln b/Samples/FileThumbnails/cpp/FileThumbnails.sln index 54da42ae98..ec29a46f42 100644 --- a/Samples/FileThumbnails/cpp/FileThumbnails.sln +++ b/Samples/FileThumbnails/cpp/FileThumbnails.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileThumbnails", "FileThumbnails.vcxproj", "{4569C622-57A0-52E1-BCB3-FD6FDBF54760}" EndProject diff --git a/Samples/FileThumbnails/cs/FileThumbnails.sln b/Samples/FileThumbnails/cs/FileThumbnails.sln index b465875c59..7aa5c60ed2 100644 --- a/Samples/FileThumbnails/cs/FileThumbnails.sln +++ b/Samples/FileThumbnails/cs/FileThumbnails.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileThumbnails", "FileThumbnails.csproj", "{087772FC-C57F-51DB-A5F7-68E5AA93071B}" EndProject diff --git a/Samples/FileThumbnails/js/FileThumbnails.sln b/Samples/FileThumbnails/js/FileThumbnails.sln index 5aeb0fb025..05d890a010 100644 --- a/Samples/FileThumbnails/js/FileThumbnails.sln +++ b/Samples/FileThumbnails/js/FileThumbnails.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "FileThumbnails", "FileThumbnails.jsproj", "{A6A28378-D4FC-5D18-8A58-B1C51E06FFAC}" EndProject diff --git a/Samples/FolderEnumeration/cpp/FolderEnumeration.sln b/Samples/FolderEnumeration/cpp/FolderEnumeration.sln index 33d7c910c7..30e68b0bf7 100644 --- a/Samples/FolderEnumeration/cpp/FolderEnumeration.sln +++ b/Samples/FolderEnumeration/cpp/FolderEnumeration.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FolderEnumeration", "FolderEnumeration.vcxproj", "{6F5138EC-C144-5DAF-A9BB-586CDF90AAE0}" EndProject diff --git a/Samples/FolderEnumeration/cs/FolderEnumeration.sln b/Samples/FolderEnumeration/cs/FolderEnumeration.sln index a92f9e194f..b6d84ccdce 100644 --- a/Samples/FolderEnumeration/cs/FolderEnumeration.sln +++ b/Samples/FolderEnumeration/cs/FolderEnumeration.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FolderEnumeration", "FolderEnumeration.csproj", "{964DAE41-3C1A-5AEC-A9E3-20DE15881C67}" EndProject diff --git a/Samples/FolderEnumeration/js/FolderEnumeration.sln b/Samples/FolderEnumeration/js/FolderEnumeration.sln index 5033707511..12140a71de 100644 --- a/Samples/FolderEnumeration/js/FolderEnumeration.sln +++ b/Samples/FolderEnumeration/js/FolderEnumeration.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "FolderEnumeration", "FolderEnumeration.jsproj", "{9266FCCF-9457-579D-A7F9-EEEB608ECCBD}" EndProject diff --git a/Samples/FullScreenMode/cpp/FullScreenMode.sln b/Samples/FullScreenMode/cpp/FullScreenMode.sln index 9a93ed8c08..15b609dc31 100644 --- a/Samples/FullScreenMode/cpp/FullScreenMode.sln +++ b/Samples/FullScreenMode/cpp/FullScreenMode.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FullScreenMode", "FullScreenMode.vcxproj", "{04C03225-0218-5AE6-AB5D-662566A5A7FE}" EndProject diff --git a/Samples/FullScreenMode/cs/FullScreenMode.sln b/Samples/FullScreenMode/cs/FullScreenMode.sln index f7cadc4644..e35acc7cb4 100644 --- a/Samples/FullScreenMode/cs/FullScreenMode.sln +++ b/Samples/FullScreenMode/cs/FullScreenMode.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FullScreenMode", "FullScreenMode.csproj", "{B8B87B9B-C92C-54DF-BC95-36F1796B702D}" EndProject diff --git a/Samples/FullScreenMode/js/FullScreenMode.sln b/Samples/FullScreenMode/js/FullScreenMode.sln index d44e35b15e..8173bebbd1 100644 --- a/Samples/FullScreenMode/js/FullScreenMode.sln +++ b/Samples/FullScreenMode/js/FullScreenMode.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "FullScreenMode", "FullScreenMode.jsproj", "{A72DA1E0-B878-527C-8CC0-EC26B69E6AE4}" EndProject diff --git a/Samples/Geolocation/cpp/Geolocation.sln b/Samples/Geolocation/cpp/Geolocation.sln index 2e7d4fc1e8..bdbebaa537 100644 --- a/Samples/Geolocation/cpp/Geolocation.sln +++ b/Samples/Geolocation/cpp/Geolocation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Geolocation", "GeolocationCPP\Geolocation.vcxproj", "{15943193-1461-5929-BCD9-340DE06EDDE5}" EndProject diff --git a/Samples/Geolocation/cs/Geolocation.sln b/Samples/Geolocation/cs/Geolocation.sln index b3445101c6..6dcc686074 100644 --- a/Samples/Geolocation/cs/Geolocation.sln +++ b/Samples/Geolocation/cs/Geolocation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geolocation", "GeolocationCS\Geolocation.csproj", "{1B0B25E2-948B-510D-9AD1-B382A4C0CD4C}" EndProject diff --git a/Samples/Geolocation/js/Geolocation.sln b/Samples/Geolocation/js/Geolocation.sln index a8c438a5f9..252e22f452 100644 --- a/Samples/Geolocation/js/Geolocation.sln +++ b/Samples/Geolocation/js/Geolocation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Geolocation", "GeolocationJS\Geolocation.jsproj", "{6FD2E595-C898-5CB5-9B4B-9429773C444E}" EndProject diff --git a/Samples/Geotag/cpp/Geotag.sln b/Samples/Geotag/cpp/Geotag.sln index e4c2c86d5b..fc555b4ecf 100644 --- a/Samples/Geotag/cpp/Geotag.sln +++ b/Samples/Geotag/cpp/Geotag.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Geotag", "Geotag.vcxproj", "{697A8FA5-2D78-5D46-843E-7D33BA37CA90}" EndProject diff --git a/Samples/Geotag/cs/Geotag.sln b/Samples/Geotag/cs/Geotag.sln index f986fa5373..a550e211f2 100644 --- a/Samples/Geotag/cs/Geotag.sln +++ b/Samples/Geotag/cs/Geotag.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geotag", "Geotag.csproj", "{B2FCFE7D-1F6D-5DBE-9333-DF7DF28A9D4C}" EndProject diff --git a/Samples/Geotag/js/Geotag.sln b/Samples/Geotag/js/Geotag.sln index a28cf2369d..5693441873 100644 --- a/Samples/Geotag/js/Geotag.sln +++ b/Samples/Geotag/js/Geotag.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Geotag", "Geotag.jsproj", "{016C9311-004B-504D-9ADC-1D87645DD260}" EndProject diff --git a/Samples/GlobalizationPreferences/cpp/GlobalizationPreferences.sln b/Samples/GlobalizationPreferences/cpp/GlobalizationPreferences.sln index 19dc60bc87..1f4ade09db 100644 --- a/Samples/GlobalizationPreferences/cpp/GlobalizationPreferences.sln +++ b/Samples/GlobalizationPreferences/cpp/GlobalizationPreferences.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GlobalizationPreferences", "GlobalizationPreferences.vcxproj", "{7B110251-61BA-5AB5-98B3-FEC9F292A684}" EndProject diff --git a/Samples/GlobalizationPreferences/cs/GlobalizationPreferences.sln b/Samples/GlobalizationPreferences/cs/GlobalizationPreferences.sln index 8429d3773c..7150597f61 100644 --- a/Samples/GlobalizationPreferences/cs/GlobalizationPreferences.sln +++ b/Samples/GlobalizationPreferences/cs/GlobalizationPreferences.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalizationPreferences", "GlobalizationPreferences.csproj", "{70C8C7FB-5D0A-548E-B03C-211CDF274DDD}" EndProject diff --git a/Samples/GlobalizationPreferences/js/GlobalizationPreferences.sln b/Samples/GlobalizationPreferences/js/GlobalizationPreferences.sln index 26bd05e372..3b98d39ec4 100644 --- a/Samples/GlobalizationPreferences/js/GlobalizationPreferences.sln +++ b/Samples/GlobalizationPreferences/js/GlobalizationPreferences.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "GlobalizationPreferences", "GlobalizationPreferences.jsproj", "{80A7F7F1-243D-522A-8F3E-6DBC6BC203BD}" EndProject diff --git a/Samples/Gyrometer/cpp/Gyrometer.sln b/Samples/Gyrometer/cpp/Gyrometer.sln index 803a58219f..04376d0e0b 100644 --- a/Samples/Gyrometer/cpp/Gyrometer.sln +++ b/Samples/Gyrometer/cpp/Gyrometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Gyrometer", "Gyrometer.vcxproj", "{D80D93A6-6F4D-5837-8E7E-6CCAD6267A89}" EndProject diff --git a/Samples/Gyrometer/cs/Gyrometer.sln b/Samples/Gyrometer/cs/Gyrometer.sln index e4de329904..08dfe5af29 100644 --- a/Samples/Gyrometer/cs/Gyrometer.sln +++ b/Samples/Gyrometer/cs/Gyrometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gyrometer", "Gyrometer.csproj", "{F71D9306-E966-5F09-B7FA-C7BEA25C43DF}" EndProject diff --git a/Samples/Gyrometer/js/Gyrometer.sln b/Samples/Gyrometer/js/Gyrometer.sln index f142a4bd07..b46e52ec4d 100644 --- a/Samples/Gyrometer/js/Gyrometer.sln +++ b/Samples/Gyrometer/js/Gyrometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Gyrometer", "Gyrometer.jsproj", "{72A3ABFA-071D-511E-9ACE-6C6ADFA93793}" EndProject diff --git a/Samples/HolographicDepthBasedImageStabilization/cpp/HolographicDepthBasedImageStabilization.sln b/Samples/HolographicDepthBasedImageStabilization/cpp/HolographicDepthBasedImageStabilization.sln index 8f5ebb61b9..7f256af44b 100644 --- a/Samples/HolographicDepthBasedImageStabilization/cpp/HolographicDepthBasedImageStabilization.sln +++ b/Samples/HolographicDepthBasedImageStabilization/cpp/HolographicDepthBasedImageStabilization.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HolographicDepthBasedImageStabilization", "HolographicDepthBasedImageStabilization.vcxproj", "{3014BFCA-84B0-5217-B2D8-9A99AECB1C5F}" EndProject diff --git a/Samples/HolographicFaceTracking/cpp/HolographicFaceTracking.sln b/Samples/HolographicFaceTracking/cpp/HolographicFaceTracking.sln index be43479b41..9b03c7758d 100644 --- a/Samples/HolographicFaceTracking/cpp/HolographicFaceTracking.sln +++ b/Samples/HolographicFaceTracking/cpp/HolographicFaceTracking.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HolographicFaceTracking", "HolographicFaceTracking.vcxproj", "{C9105102-9091-500A-8A5B-F9965BD1FDC1}" EndProject diff --git a/Samples/HolographicMixedRealityCapture/cpp/HolographicMRCapture.sln b/Samples/HolographicMixedRealityCapture/cpp/HolographicMRCapture.sln index e34451f3e4..d172f4c645 100644 --- a/Samples/HolographicMixedRealityCapture/cpp/HolographicMRCapture.sln +++ b/Samples/HolographicMixedRealityCapture/cpp/HolographicMRCapture.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HolographicMRCapture", "HolographicMRCapture.vcxproj", "{B1A3A140-2E76-53DA-8221-CBBC1A930C5E}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/HolographicSpatialMapping/cpp/HolographicSpatialMapping.sln b/Samples/HolographicSpatialMapping/cpp/HolographicSpatialMapping.sln index 3d9af9d3ea..79e32fe6bd 100644 --- a/Samples/HolographicSpatialMapping/cpp/HolographicSpatialMapping.sln +++ b/Samples/HolographicSpatialMapping/cpp/HolographicSpatialMapping.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HolographicSpatialMapping", "HolographicSpatialMapping.vcxproj", "{0DC64F01-3FC5-5DE9-9D11-ACA907A5C530}" EndProject diff --git a/Samples/HolographicSpatialStage/README.md b/Samples/HolographicSpatialStage/README.md new file mode 100644 index 0000000000..62f8ab1d4f --- /dev/null +++ b/Samples/HolographicSpatialStage/README.md @@ -0,0 +1,103 @@ + + +# Holographic spatial stage sample + +Shows how to acquire a SpatialStage, and make use of its coordinate system and properties. + +> **Note:** This sample is part of a large collection of UWP feature samples. +> If you are unfamiliar with Git and GitHub, you can download the entire collection as a +> [ZIP file](https://github.com/Microsoft/Windows-universal-samples/archive/master.zip), but be +> sure to unzip everything to access shared dependencies. For more info on working with the ZIP file, +> the samples collection, and GitHub, see [Get the UWP samples from GitHub](https://aka.ms/ovu2uq). +> For more samples, see the [Samples portal](https://aka.ms/winsamples) on the Windows Dev Center. + +Specifically, this sample obtains a spatial stage, inspects the properties of the stage, and renders +a visualization of the stage based on its properties. + +The spatial stage includes a 2D bounding shape indicating the area where the user can walk around. This +sample acquires that shape, and uses it to draw the spatial stage with the walkable area on it. This +sample also draws an indicator for the look direction range. + + +### Additional remarks + +**Note** The Windows universal samples for Windows Mixed Reality require Visual Studio 2017 +to build, and a Windows Holographic device to execute. Windows Mixed Reality devices include the +Microsoft HoloLens, the Microsoft HoloLens Emulator, and PCs with immersive headset devices attached. + +To obtain information about Windows 10 development, go to the [Windows Dev Center](http://go.microsoft.com/fwlink/?LinkID=532421). + +To obtain information about the tools used for Windows Mixed Reality development, including +Microsoft Visual Studio 2017 and the Microsoft HoloLens Emulator, go to +[Install the tools](https://developer.microsoft.com/windows/holographic/install_the_tools). + +## Reference + +The following APIs are used in this code sample: + +* [Windows.Perception namespace](https://msdn.microsoft.com/library/windows/apps/windows.perception.aspx) +* [Windows.Perception.Spatial namespace](https://msdn.microsoft.com/library/windows/apps/windows.perception.spatial.aspx) + * [SpatialStageFrameOfReference class](https://msdn.microsoft.com/library/windows/apps/windows.perception.spatial.SpatialStageFrameOfReference.aspx) + +## System requirements + +**Client:** Windows 10 Holographic or Windows Mixed Reality + +**Phone:** Not supported + +## Build the sample + +1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with + the sample you want to build. +2. Start Microsoft Visual Studio 2017 and select **File** \> **Open** \> **Project/Solution**. +3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the + subfolder for this specific sample, then the subfolder for your preferred language (C++, C#, or + JavaScript). Double-click the Visual Studio 2017 Solution (.sln) file. +4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**. + +## Run the sample + +The next steps depend on whether you just want to deploy the sample or you want to both deploy and +run it. + +### Deploying the sample + +- If your Windows Mixed Reality target device is separate from your development machine, click the debug target drop-down + and select the appropriate target. If needed, use the properties panel of the project to set the remote computer IP and + authentication method. +- Select **Build** \> **Deploy** Solution. + +### Deploying the sample to a Microsoft HoloLens + +- Developer unlock your Microsoft HoloLens. For instructions, go to [Enable your device for development] + (https://msdn.microsoft.com/windows/uwp/get-started/enable-your-device-for-development#enable-your-windows-10-devices). +- Find the IP address of your Microsoft HoloLens. The IP address can be found in **Settings** + \> **Network & Internet** \> **Wi-Fi** \> **Advanced options**. Or, you can ask Cortana for this + information by saying: "Hey Cortana, what's my IP address?" +- Right-click on your project in Visual Studio, and then select **Properties**. +- In the Debugging pane, click the drop-down and select **Remote Machine**. +- Enter the IP address of your Microsoft HoloLens into the field labelled **Machine Name**. +- Click **OK**. +- Select **Build** \> **Deploy** Solution. + +### Pairing your developer-unlocked Microsoft HoloLens with Visual Studio + +The first time you deploy from your development PC to your developer-unlocked Microsoft HoloLens, +you will need to use a PIN to pair your PC with the Microsoft HoloLens. +- When you select **Build** \> **Deploy Solution**, a dialog box will appear for Visual Studio to + accept the PIN. +- On your Microsoft HoloLens, go to **Settings** \> **Update** \> **For developers**, and click on + **Pair**. +- Type the PIN displayed by your Microsoft HoloLens into the Visual Studio dialog box and click + **OK**. +- On your Microsoft HoloLens, select **Done** to accept the pairing. +- The solution will then start to deploy. + +### Deploying and running the sample + +- To debug the sample and then run it, follow the steps listed above to connect your + developer-unlocked Microsoft HoloLens, then press F5 or select **Debug** \> **Start Debugging**. + To run the sample without debugging, press Ctrl+F5 or select **Debug** \> **Start Without Debugging**. diff --git a/Samples/HolographicSpatialStage/cpp/AppView.cpp b/Samples/HolographicSpatialStage/cpp/AppView.cpp new file mode 100644 index 0000000000..57263dffe4 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/AppView.cpp @@ -0,0 +1,180 @@ +#include "pch.h" +#include "AppView.h" + +#include + +using namespace HolographicSpatialStage; + +using namespace concurrency; +using namespace Windows::ApplicationModel; +using namespace Windows::ApplicationModel::Activation; +using namespace Windows::ApplicationModel::Core; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Holographic; +using namespace Windows::UI::Core; + +// The main function is only used to initialize our IFrameworkView class. +// Under most circumstances, you should not need to modify this function. +[Platform::MTAThread] +int main(Platform::Array^) +{ + AppViewSource^ appViewSource = ref new ::AppViewSource(); + CoreApplication::Run(appViewSource); + return 0; +} + +IFrameworkView^ AppViewSource::CreateView() +{ + return ref new AppView(); +} + +AppView::AppView() +{ +} + + +// IFrameworkView methods + +// The first method called when the IFrameworkView is being created. +// Use this method to subscribe for Windows shell events and to initialize your app. +void AppView::Initialize(CoreApplicationView^ applicationView) +{ + applicationView->Activated += + ref new TypedEventHandler(this, &AppView::OnViewActivated); + + // Register event handlers for app lifecycle. + CoreApplication::Suspending += + ref new EventHandler(this, &AppView::OnSuspending); + + CoreApplication::Resuming += + ref new EventHandler(this, &AppView::OnResuming); + + // At this point we have access to the device and we can create device-dependent + // resources. + m_deviceResources = std::make_shared(); + + m_main = std::make_unique(m_deviceResources); +} + +// Called when the CoreWindow object is created (or re-created). +void AppView::SetWindow(CoreWindow^ window) +{ + // Register for notification that the app window is being closed. + window->Closed += + ref new TypedEventHandler(this, &AppView::OnWindowClosed); + + // Register for notifications that the app window is losing focus. + window->VisibilityChanged += + ref new TypedEventHandler(this, &AppView::OnVisibilityChanged); + + // Create a holographic space for the core window for the current view. + // Presenting holographic frames that are created by this holographic space will put + // the app into exclusive mode. + m_holographicSpace = HolographicSpace::CreateForCoreWindow(window); + + // The DeviceResources class uses the preferred DXGI adapter ID from the holographic + // space (when available) to create a Direct3D device. The HolographicSpace + // uses this ID3D11Device to create and manage device-based resources such as + // swap chains. + m_deviceResources->SetHolographicSpace(m_holographicSpace); + + // The main class uses the holographic space for updates and rendering. + m_main->SetHolographicSpace(m_holographicSpace); +} + +// The Load method can be used to initialize scene resources or to load a +// previously saved app state. +void AppView::Load(Platform::String^ entryPoint) +{ +} + +// This method is called after the window becomes active. It oversees the +// update, draw, and present loop, and it also oversees window message processing. +void AppView::Run() +{ + while (!m_windowClosed) + { + if (m_windowVisible && (m_holographicSpace != nullptr)) + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); + + HolographicFrame^ holographicFrame = m_main->Update(); + + if (m_main->Render(holographicFrame)) + { + // The holographic frame has an API that presents the swap chain for each + // holographic camera. + m_deviceResources->Present(holographicFrame); + } + } + else + { + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); + } + } +} + +// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView +// class is torn down while the app is in the foreground. +// This method is not often used, but IFrameworkView requires it and it will be called for +// holographic apps. +void AppView::Uninitialize() +{ + +} + + +// Application lifecycle event handlers + +// Called when the app is prelaunched. Use this method to load resources ahead of time +// and enable faster launch times. +void AppView::OnLaunched(LaunchActivatedEventArgs^ args) +{ + if (args->PrelaunchActivated) + { + return; + } +} + +// Called when the app view is activated. Activates the app's CoreWindow. +void AppView::OnViewActivated(CoreApplicationView^ sender, IActivatedEventArgs^ args) +{ + // Run() won't start until the CoreWindow is activated. + sender->CoreWindow->Activate(); +} + +void AppView::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) +{ + // Save app state asynchronously after requesting a deferral. Holding a deferral + // indicates that the application is busy performing suspending operations. Be + // aware that a deferral may not be held indefinitely; after about five seconds, + // the app will be forced to exit. + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); + + create_task([this, deferral] () + { + m_deviceResources->Trim(); + + deferral->Complete(); + }); +} + +void AppView::OnResuming(Platform::Object^ sender, Platform::Object^ args) +{ + // Restore any data or state that was unloaded on suspend. By default, data + // and state are persisted when resuming from suspend. Note that this event + // does not occur if the app was previously terminated. +} + + +// Window event handlers + +void AppView::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) +{ + m_windowVisible = args->Visible; +} + +void AppView::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) +{ + m_windowClosed = true; +} diff --git a/Samples/HolographicSpatialStage/cpp/AppView.h b/Samples/HolographicSpatialStage/cpp/AppView.h new file mode 100644 index 0000000000..7e9271925d --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/AppView.h @@ -0,0 +1,49 @@ +#pragma once + +#include "Common\DeviceResources.h" +#include "HolographicSpatialStageMain.h" + +namespace HolographicSpatialStage +{ + // IFrameworkView class. Connects the app with the Windows shell and handles application lifecycle events. + ref class AppView sealed : public Windows::ApplicationModel::Core::IFrameworkView + { + public: + AppView(); + + // IFrameworkView methods. + virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView); + virtual void SetWindow(Windows::UI::Core::CoreWindow^ window); + virtual void Load(Platform::String^ entryPoint); + virtual void Run(); + virtual void Uninitialize(); + + protected: + // Application lifecycle event handlers. + void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ args); + void OnViewActivated(Windows::ApplicationModel::Core::CoreApplicationView^ sender, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args); + void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args); + void OnResuming(Platform::Object^ sender, Platform::Object^ args); + + // Window event handlers. + void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); + void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args); + + private: + std::unique_ptr m_main; + + std::shared_ptr m_deviceResources; + bool m_windowClosed = false; + bool m_windowVisible = true; + + // The holographic space the app will use for rendering. + Windows::Graphics::Holographic::HolographicSpace^ m_holographicSpace = nullptr; + }; + + // The entry point for the app. + ref class AppViewSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource + { + public: + virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView(); + }; +} diff --git a/Samples/HolographicSpatialStage/cpp/Common/CameraResources.cpp b/Samples/HolographicSpatialStage/cpp/Common/CameraResources.cpp new file mode 100644 index 0000000000..bff077e20c --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Common/CameraResources.cpp @@ -0,0 +1,262 @@ +#include "pch.h" + +#include "CameraResources.h" +#include "Common\DirectXHelper.h" +#include "DeviceResources.h" +#include + +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace Windows::Graphics::DirectX::Direct3D11; +using namespace Windows::Graphics::Holographic; +using namespace Windows::Perception::Spatial; + +DX::CameraResources::CameraResources(HolographicCamera^ camera) : + m_holographicCamera(camera), + m_isStereo(camera->IsStereo), + m_d3dRenderTargetSize(camera->RenderTargetSize) +{ + m_d3dViewport = CD3D11_VIEWPORT( + 0.f, 0.f, + m_d3dRenderTargetSize.Width, + m_d3dRenderTargetSize.Height + ); +}; + +// Updates resources associated with a holographic camera's swap chain. +// The app does not access the swap chain directly, but it does create +// resource views for the back buffer. +void DX::CameraResources::CreateResourcesForBackBuffer( + DX::DeviceResources* pDeviceResources, + HolographicCameraRenderingParameters^ cameraParameters + ) +{ + const auto device = pDeviceResources->GetD3DDevice(); + + // Get the WinRT object representing the holographic camera's back buffer. + IDirect3DSurface^ surface = cameraParameters->Direct3D11BackBuffer; + + // Get a DXGI interface for the holographic camera's back buffer. + // Holographic cameras do not provide the DXGI swap chain, which is owned + // by the system. The Direct3D back buffer resource is provided using WinRT + // interop APIs. + ComPtr resource; + ThrowIfFailed( + GetDXGIInterfaceFromObject(surface, IID_PPV_ARGS(&resource)) + ); + + // Get a Direct3D interface for the holographic camera's back buffer. + ComPtr cameraBackBuffer; + ThrowIfFailed( + resource.As(&cameraBackBuffer) + ); + + // Determine if the back buffer has changed. If so, ensure that the render target view + // is for the current back buffer. + if (m_d3dBackBuffer.Get() != cameraBackBuffer.Get()) + { + // This can change every frame as the system moves to the next buffer in the + // swap chain. This mode of operation will occur when certain rendering modes + // are activated. + m_d3dBackBuffer = cameraBackBuffer; + + // Create a render target view of the back buffer. + // Creating this resource is inexpensive, and is better than keeping track of + // the back buffers in order to pre-allocate render target views for each one. + DX::ThrowIfFailed( + device->CreateRenderTargetView( + m_d3dBackBuffer.Get(), + nullptr, + &m_d3dRenderTargetView + ) + ); + + // Get the DXGI format for the back buffer. + // This information can be accessed by the app using CameraResources::GetBackBufferDXGIFormat(). + D3D11_TEXTURE2D_DESC backBufferDesc; + m_d3dBackBuffer->GetDesc(&backBufferDesc); + m_dxgiFormat = backBufferDesc.Format; + + // Check for render target size changes. + Windows::Foundation::Size currentSize = m_holographicCamera->RenderTargetSize; + if (m_d3dRenderTargetSize != currentSize) + { + // Set render target size. + m_d3dRenderTargetSize = currentSize; + + // A new depth stencil view is also needed. + m_d3dDepthStencilView.Reset(); + } + } + + // Refresh depth stencil resources, if needed. + if (m_d3dDepthStencilView == nullptr) + { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + DXGI_FORMAT_R16_TYPELESS, + static_cast(m_d3dRenderTargetSize.Width), + static_cast(m_d3dRenderTargetSize.Height), + m_isStereo ? 2 : 1, // Create two textures when rendering in stereo. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE + ); + + DX::ThrowIfFailed( + device->CreateTexture2D( + &depthStencilDesc, + nullptr, + &m_d3dDepthBuffer + ) + ); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc( + m_isStereo ? D3D11_DSV_DIMENSION_TEXTURE2DARRAY : D3D11_DSV_DIMENSION_TEXTURE2D, + DXGI_FORMAT_D16_UNORM + ); + DX::ThrowIfFailed( + device->CreateDepthStencilView( + m_d3dDepthBuffer.Get(), + &depthStencilViewDesc, + &m_d3dDepthStencilView + ) + ); + } + + // Create the constant buffer, if needed. + if (m_viewProjectionConstantBuffer == nullptr) + { + // Create a constant buffer to store view and projection matrices for the camera. + CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); + DX::ThrowIfFailed( + device->CreateBuffer( + &constantBufferDesc, + nullptr, + &m_viewProjectionConstantBuffer + ) + ); + } +} + +// Releases resources associated with a back buffer. +void DX::CameraResources::ReleaseResourcesForBackBuffer(DX::DeviceResources* pDeviceResources) +{ + const auto context = pDeviceResources->GetD3DDeviceContext(); + + // Release camera-specific resources. + m_d3dBackBuffer.Reset(); + m_d3dDepthBuffer.Reset(); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_viewProjectionConstantBuffer.Reset(); + + // Ensure system references to the back buffer are released by clearing the render + // target from the graphics pipeline state, and then flushing the Direct3D context. + ID3D11RenderTargetView* nullViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = { nullptr }; + context->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); + context->Flush(); +} + +// Updates the view/projection constant buffer for a holographic camera. +void DX::CameraResources::UpdateViewProjectionBuffer( + std::shared_ptr deviceResources, + HolographicCameraPose^ cameraPose, + SpatialCoordinateSystem^ coordinateSystem + ) +{ + // The system changes the viewport on a per-frame basis for system optimizations. + m_d3dViewport = CD3D11_VIEWPORT( + cameraPose->Viewport.Left, + cameraPose->Viewport.Top, + cameraPose->Viewport.Width, + cameraPose->Viewport.Height + ); + + // The projection transform for each frame is provided by the HolographicCameraPose. + HolographicStereoTransform cameraProjectionTransform = cameraPose->ProjectionTransform; + + // Get a container object with the view and projection matrices for the given + // pose in the given coordinate system. + Platform::IBox^ viewTransformContainer = cameraPose->TryGetViewTransform(coordinateSystem); + + // If TryGetViewTransform returns a null pointer, that means the pose and coordinate + // system cannot be understood relative to one another; content cannot be rendered + // in this coordinate system for the duration of the current frame. + // This usually means that positional tracking is not active for the current frame, in + // which case it is possible to use a SpatialLocatorAttachedFrameOfReference to render + // content that is not world-locked instead. + DX::ViewProjectionConstantBuffer viewProjectionConstantBufferData; + bool viewTransformAcquired = viewTransformContainer != nullptr; + if (viewTransformAcquired) + { + // Otherwise, the set of view transforms can be retrieved. + HolographicStereoTransform viewCoordinateSystemTransform = viewTransformContainer->Value; + + // Update the view matrices. Holographic cameras (such as Microsoft HoloLens) are + // constantly moving relative to the world. The view matrices need to be updated + // every frame. + XMStoreFloat4x4( + &viewProjectionConstantBufferData.viewProjection[0], + XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Left) * XMLoadFloat4x4(&cameraProjectionTransform.Left)) + ); + XMStoreFloat4x4( + &viewProjectionConstantBufferData.viewProjection[1], + XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Right) * XMLoadFloat4x4(&cameraProjectionTransform.Right)) + ); + } + + // Use the D3D device context to update Direct3D device-based resources. + const auto context = deviceResources->GetD3DDeviceContext(); + + // Loading is asynchronous. Resources must be created before they can be updated. + if (context == nullptr || m_viewProjectionConstantBuffer == nullptr || !viewTransformAcquired) + { + m_framePending = false; + } + else + { + // Update the view and projection matrices. + context->UpdateSubresource( + m_viewProjectionConstantBuffer.Get(), + 0, + nullptr, + &viewProjectionConstantBufferData, + 0, + 0 + ); + + m_framePending = true; + } +} + +// Gets the view-projection constant buffer for the HolographicCamera and attaches it +// to the shader pipeline. +bool DX::CameraResources::AttachViewProjectionBuffer( + std::shared_ptr deviceResources + ) +{ + // This method uses Direct3D device-based resources. + const auto context = deviceResources->GetD3DDeviceContext(); + + // Loading is asynchronous. Resources must be created before they can be updated. + // Cameras can also be added asynchronously, in which case they must be initialized + // before they can be used. + if (context == nullptr || m_viewProjectionConstantBuffer == nullptr || m_framePending == false) + { + return false; + } + + // Set the viewport for this camera. + context->RSSetViewports(1, &m_d3dViewport); + + // Send the constant buffer to the vertex shader. + context->VSSetConstantBuffers( + 1, + 1, + m_viewProjectionConstantBuffer.GetAddressOf() + ); + + m_framePending = false; + + return true; +} diff --git a/Samples/HolographicSpatialStage/cpp/Common/CameraResources.h b/Samples/HolographicSpatialStage/cpp/Common/CameraResources.h new file mode 100644 index 0000000000..3468557560 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Common/CameraResources.h @@ -0,0 +1,78 @@ +#pragma once + +namespace DX +{ + class DeviceResources; + + // Constant buffer used to send the view-projection matrices to the shader pipeline. + struct ViewProjectionConstantBuffer + { + DirectX::XMFLOAT4X4 viewProjection[2]; + }; + + // Assert that the constant buffer remains 16-byte aligned (best practice). + static_assert((sizeof(ViewProjectionConstantBuffer) % (sizeof(float) * 4)) == 0, "ViewProjection constant buffer size must be 16-byte aligned (16 bytes is the length of four floats)."); + + // Manages DirectX device resources that are specific to a holographic camera, such as the + // back buffer, ViewProjection constant buffer, and viewport. + class CameraResources + { + public: + CameraResources(Windows::Graphics::Holographic::HolographicCamera^ holographicCamera); + + void CreateResourcesForBackBuffer( + DX::DeviceResources* pDeviceResources, + Windows::Graphics::Holographic::HolographicCameraRenderingParameters^ cameraParameters + ); + void ReleaseResourcesForBackBuffer( + DX::DeviceResources* pDeviceResources + ); + + void UpdateViewProjectionBuffer( + std::shared_ptr deviceResources, + Windows::Graphics::Holographic::HolographicCameraPose^ cameraPose, + Windows::Perception::Spatial::SpatialCoordinateSystem^ coordinateSystem); + + bool AttachViewProjectionBuffer( + std::shared_ptr deviceResources); + + // Direct3D device resources. + ID3D11RenderTargetView* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.Get(); } + ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } + ID3D11Texture2D* GetDepthBufferTexture2D() const { return m_d3dDepthBuffer.Get(); } + ID3D11Texture2D* GetBackBufferTexture2D() const { return m_d3dBackBuffer.Get(); } + D3D11_VIEWPORT GetViewport() const { return m_d3dViewport; } + DXGI_FORMAT GetBackBufferDXGIFormat() const { return m_dxgiFormat; } + + // Render target properties. + Windows::Foundation::Size GetRenderTargetSize() const { return m_d3dRenderTargetSize; } + bool IsRenderingStereoscopic() const { return m_isStereo; } + + // The holographic camera these resources are for. + Windows::Graphics::Holographic::HolographicCamera^ GetHolographicCamera() const { return m_holographicCamera; } + + private: + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr m_d3dRenderTargetView; + Microsoft::WRL::ComPtr m_d3dDepthStencilView; + Microsoft::WRL::ComPtr m_d3dBackBuffer; + Microsoft::WRL::ComPtr m_d3dDepthBuffer; + + // Device resource to store view and projection matrices. + Microsoft::WRL::ComPtr m_viewProjectionConstantBuffer; + + // Direct3D rendering properties. + DXGI_FORMAT m_dxgiFormat; + Windows::Foundation::Size m_d3dRenderTargetSize; + D3D11_VIEWPORT m_d3dViewport; + + // Indicates whether the camera supports stereoscopic rendering. + bool m_isStereo = false; + + // Indicates whether this camera has a pending frame. + bool m_framePending = false; + + // Pointer to the holographic camera these resources are for. + Windows::Graphics::Holographic::HolographicCamera^ m_holographicCamera = nullptr; + }; +} diff --git a/Samples/HolographicSpatialStage/cpp/Common/DeviceResources.cpp b/Samples/HolographicSpatialStage/cpp/Common/DeviceResources.cpp new file mode 100644 index 0000000000..74e43525ee --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Common/DeviceResources.cpp @@ -0,0 +1,352 @@ + +#include "pch.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" + +#include +#include + +using namespace D2D1; +using namespace Microsoft::WRL; +using namespace Windows::Graphics::DirectX::Direct3D11; +using namespace Windows::Graphics::Display; +using namespace Windows::Graphics::Holographic; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources() +{ + CreateDeviceIndependentResources(); +} + +// Configures resources that don't depend on the Direct3D device. +void DX::DeviceResources::CreateDeviceIndependentResources() +{ + // Initialize Direct2D resources. + D2D1_FACTORY_OPTIONS options {}; + +#if defined(_DEBUG) + // If the project is in a debug build, enable Direct2D debugging via SDK Layers. + options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; +#endif + + // Initialize the Direct2D Factory. + DX::ThrowIfFailed( + D2D1CreateFactory( + D2D1_FACTORY_TYPE_SINGLE_THREADED, + __uuidof(ID2D1Factory2), + &options, + &m_d2dFactory + ) + ); + + // Initialize the DirectWrite Factory. + DX::ThrowIfFailed( + DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(IDWriteFactory2), + &m_dwriteFactory + ) + ); + + // Initialize the Windows Imaging Component (WIC) Factory. + DX::ThrowIfFailed( + CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&m_wicFactory) + ) + ); +} + +void DX::DeviceResources::SetHolographicSpace(HolographicSpace^ holographicSpace) +{ + // Cache the holographic space. Used to re-initalize during device-lost scenarios. + m_holographicSpace = holographicSpace; + + InitializeUsingHolographicSpace(); +} + +void DX::DeviceResources::InitializeUsingHolographicSpace() +{ + // The holographic space might need to determine which adapter supports + // holograms, in which case it will specify a non-zero PrimaryAdapterId. + LUID id = + { + m_holographicSpace->PrimaryAdapterId.LowPart, + m_holographicSpace->PrimaryAdapterId.HighPart + }; + + // When a primary adapter ID is given to the app, the app should find + // the corresponding DXGI adapter and use it to create Direct3D devices + // and device contexts. Otherwise, there is no restriction on the DXGI + // adapter the app can use. + if ((id.HighPart != 0) || (id.LowPart != 0)) + { + UINT createFlags = 0; +#ifdef DEBUG + if (DX::SdkLayersAvailable()) + { + createFlags |= DXGI_CREATE_FACTORY_DEBUG; + } +#endif + // Create the DXGI factory. + ComPtr dxgiFactory; + DX::ThrowIfFailed( + CreateDXGIFactory2( + createFlags, + IID_PPV_ARGS(&dxgiFactory) + ) + ); + ComPtr dxgiFactory4; + DX::ThrowIfFailed(dxgiFactory.As(&dxgiFactory4)); + + // Retrieve the adapter specified by the holographic space. + DX::ThrowIfFailed( + dxgiFactory4->EnumAdapterByLuid( + id, + IID_PPV_ARGS(&m_dxgiAdapter) + ) + ); + } + else + { + m_dxgiAdapter.Reset(); + } + + CreateDeviceResources(); + + m_holographicSpace->SetDirect3D11Device(m_d3dInteropDevice); +} + +// Configures the Direct3D device, and stores handles to it and the device context. +void DX::DeviceResources::CreateDeviceResources() +{ + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#if defined(_DEBUG) + if (DX::SdkLayersAvailable()) + { + // If the project is in a debug build, enable debugging via SDK Layers with this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } +#endif + + // This array defines the set of DirectX hardware feature levels this app will support. + // Note the ordering should be preserved. + // Note that HoloLens supports feature level 11.1. The HoloLens emulator is also capable + // of running on graphics cards starting with feature level 10.0. + D3D_FEATURE_LEVEL featureLevels [] = + { + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0 + }; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr device; + ComPtr context; + + const D3D_DRIVER_TYPE driverType = m_dxgiAdapter == nullptr ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN; + const HRESULT hr = D3D11CreateDevice( + m_dxgiAdapter.Get(), // Either nullptr, or the primary adapter determined by Windows Holographic. + driverType, // Create a device using the hardware graphics driver. + 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. + creationFlags, // Set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), // Size of the list above. + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + &device, // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + &context // Returns the device immediate context. + ); + + if (FAILED(hr)) + { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + DX::ThrowIfFailed( + D3D11CreateDevice( + nullptr, // Use the default DXGI adapter for WARP. + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. + 0, + creationFlags, + featureLevels, + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, + &device, + &m_d3dFeatureLevel, + &context + ) + ); + } + + // Store pointers to the Direct3D device and immediate context. + DX::ThrowIfFailed( + device.As(&m_d3dDevice) + ); + + DX::ThrowIfFailed( + context.As(&m_d3dContext) + ); + + // Acquire the DXGI interface for the Direct3D device. + ComPtr dxgiDevice; + DX::ThrowIfFailed( + m_d3dDevice.As(&dxgiDevice) + ); + + // Wrap the native device using a WinRT interop object. + m_d3dInteropDevice = CreateDirect3DDevice(dxgiDevice.Get()); + + // Cache the DXGI adapter. + // This is for the case of no preferred DXGI adapter, or fallback to WARP. + ComPtr dxgiAdapter; + DX::ThrowIfFailed( + dxgiDevice->GetAdapter(&dxgiAdapter) + ); + DX::ThrowIfFailed( + dxgiAdapter.As(&m_dxgiAdapter) + ); + + // Check for device support for the optional feature that allows setting the render target array index from the vertex shader stage. + D3D11_FEATURE_DATA_D3D11_OPTIONS3 options; + m_d3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &options, sizeof(options)); + if (options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer) + { + m_supportsVprt = true; + } +} + +// Validates the back buffer for each HolographicCamera and recreates +// resources for back buffers that have changed. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::EnsureCameraResources( + HolographicFrame^ frame, + HolographicFramePrediction^ prediction) +{ + UseHolographicCameraResources([this, frame, prediction](std::map>& cameraResourceMap) + { + for (HolographicCameraPose^ pose : prediction->CameraPoses) + { + HolographicCameraRenderingParameters^ renderingParameters = frame->GetRenderingParameters(pose); + CameraResources* pCameraResources = cameraResourceMap[pose->HolographicCamera->Id].get(); + + pCameraResources->CreateResourcesForBackBuffer(this, renderingParameters); + } + }); +} + +// Prepares to allocate resources and adds resource views for a camera. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::AddHolographicCamera(HolographicCamera^ camera) +{ + UseHolographicCameraResources([this, camera](std::map>& cameraResourceMap) + { + cameraResourceMap[camera->Id] = std::make_unique(camera); + }); +} + +// Deallocates resources for a camera and removes the camera from the set. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::RemoveHolographicCamera(HolographicCamera^ camera) +{ + UseHolographicCameraResources([this, camera](std::map>& cameraResourceMap) + { + CameraResources* pCameraResources = cameraResourceMap[camera->Id].get(); + + if (pCameraResources != nullptr) + { + pCameraResources->ReleaseResourcesForBackBuffer(this); + cameraResourceMap.erase(camera->Id); + } + }); +} + +// Recreate all device resources and set them back to the current state. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::HandleDeviceLost() +{ + if (m_deviceNotify != nullptr) + { + m_deviceNotify->OnDeviceLost(); + } + + UseHolographicCameraResources([this](std::map>& cameraResourceMap) + { + for (auto& pair : cameraResourceMap) + { + CameraResources* pCameraResources = pair.second.get(); + pCameraResources->ReleaseResourcesForBackBuffer(this); + } + }); + + InitializeUsingHolographicSpace(); + + if (m_deviceNotify != nullptr) + { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Register our DeviceNotify to be informed on device lost and creation. +void DX::DeviceResources::RegisterDeviceNotify(DX::IDeviceNotify* deviceNotify) +{ + m_deviceNotify = deviceNotify; +} + +// Call this method when the app suspends. It provides a hint to the driver that the app +// is entering an idle state and that temporary buffers can be reclaimed for use by other apps. +void DX::DeviceResources::Trim() +{ + m_d3dContext->ClearState(); + + ComPtr dxgiDevice; + DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); + dxgiDevice->Trim(); +} + +// Present the contents of the swap chain to the screen. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::Present(HolographicFrame^ frame) +{ + // By default, this API waits for the frame to finish before it returns. + // Holographic apps should wait for the previous frame to finish before + // starting work on a new frame. This allows for better results from + // holographic frame predictions. + HolographicFramePresentResult presentResult = frame->PresentUsingCurrentPrediction(); + + HolographicFramePrediction^ prediction = frame->CurrentPrediction; + UseHolographicCameraResources([this, prediction](std::map>& cameraResourceMap) + { + for (auto cameraPose : prediction->CameraPoses) + { + // This represents the device-based resources for a HolographicCamera. + DX::CameraResources* pCameraResources = cameraResourceMap[cameraPose->HolographicCamera->Id].get(); + + // Discard the contents of the render target. + // This is a valid operation only when the existing contents will be + // entirely overwritten. If dirty or scroll rects are used, this call + // should be removed. + m_d3dContext->DiscardView(pCameraResources->GetBackBufferRenderTargetView()); + + // Discard the contents of the depth stencil. + m_d3dContext->DiscardView(pCameraResources->GetDepthStencilView()); + } + }); + + // The PresentUsingCurrentPrediction API will detect when the graphics device + // changes or becomes invalid. When this happens, it is considered a Direct3D + // device lost scenario. + if (presentResult == HolographicFramePresentResult::DeviceRemoved) + { + // The Direct3D device, context, and resources should be recreated. + HandleDeviceLost(); + } +} diff --git a/Samples/HolographicSpatialStage/cpp/Common/DeviceResources.h b/Samples/HolographicSpatialStage/cpp/Common/DeviceResources.h new file mode 100644 index 0000000000..65dc82c4d6 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Common/DeviceResources.h @@ -0,0 +1,107 @@ + +#pragma once + +#include "CameraResources.h" + +namespace DX +{ + // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. + interface IDeviceNotify + { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; + }; + + // Creates and manages a Direct3D device and immediate context, Direct2D device and context (for debug), and the holographic swap chain. + class DeviceResources + { + public: + DeviceResources(); + + // Public methods related to Direct3D devices. + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify* deviceNotify); + void Trim(); + void Present(Windows::Graphics::Holographic::HolographicFrame^ frame); + + // Public methods related to holographic devices. + void SetHolographicSpace(Windows::Graphics::Holographic::HolographicSpace^ space); + void EnsureCameraResources( + Windows::Graphics::Holographic::HolographicFrame^ frame, + Windows::Graphics::Holographic::HolographicFramePrediction^ prediction); + + void AddHolographicCamera(Windows::Graphics::Holographic::HolographicCamera^ camera); + void RemoveHolographicCamera(Windows::Graphics::Holographic::HolographicCamera^ camera); + + // Holographic accessors. + template + RetType UseHolographicCameraResources(const LCallback& callback); + + Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice^ + GetD3DInteropDevice() const { return m_d3dInteropDevice; } + + // D3D accessors. + ID3D11Device4* GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContext3* GetD3DDeviceContext() const { return m_d3dContext.Get(); } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + bool GetDeviceSupportsVprt() const { return m_supportsVprt; } + + // DXGI acessors. + IDXGIAdapter3* GetDXGIAdapter() const { return m_dxgiAdapter.Get(); } + + // D2D accessors. + ID2D1Factory2* GetD2DFactory() const { return m_d2dFactory.Get(); } + IDWriteFactory2* GetDWriteFactory() const { return m_dwriteFactory.Get(); } + IWICImagingFactory2* GetWicImagingFactory() const { return m_wicFactory.Get(); } + + private: + // Private methods related to the Direct3D device, and resources based on that device. + void CreateDeviceIndependentResources(); + void InitializeUsingHolographicSpace(); + void CreateDeviceResources(); + + // Direct3D objects. + Microsoft::WRL::ComPtr m_d3dDevice; + Microsoft::WRL::ComPtr m_d3dContext; + Microsoft::WRL::ComPtr m_dxgiAdapter; + + // Direct3D interop objects. + Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice^ m_d3dInteropDevice; + + // Direct2D factories. + Microsoft::WRL::ComPtr m_d2dFactory; + Microsoft::WRL::ComPtr m_dwriteFactory; + Microsoft::WRL::ComPtr m_wicFactory; + + // The holographic space provides a preferred DXGI adapter ID. + Windows::Graphics::Holographic::HolographicSpace^ m_holographicSpace = nullptr; + + // Properties of the Direct3D device currently in use. + D3D_FEATURE_LEVEL m_d3dFeatureLevel = D3D_FEATURE_LEVEL_10_0; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify* m_deviceNotify = nullptr; + + // Whether or not the current Direct3D device supports the optional feature + // for setting the render target array index from the vertex shader stage. + bool m_supportsVprt = false; + + // Back buffer resources, etc. for attached holographic cameras. + std::map> m_cameraResources; + std::mutex m_cameraResourcesLock; + }; +} + +// Device-based resources for holographic cameras are stored in a std::map. Access this list by providing a +// callback to this function, and the std::map will be guarded from add and remove +// events until the callback returns. The callback is processed immediately and must +// not contain any nested calls to UseHolographicCameraResources. +// The callback takes a parameter of type std::map>& +// through which the list of cameras will be accessed. +template +RetType DX::DeviceResources::UseHolographicCameraResources(const LCallback& callback) +{ + std::lock_guard guard(m_cameraResourcesLock); + return callback(m_cameraResources); +} + diff --git a/Samples/HolographicSpatialStage/cpp/Common/DirectXHelper.h b/Samples/HolographicSpatialStage/cpp/Common/DirectXHelper.h new file mode 100644 index 0000000000..f73985f6e3 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Common/DirectXHelper.h @@ -0,0 +1,59 @@ +#pragma once + +#include // For create_task + +namespace DX +{ + inline void ThrowIfFailed(HRESULT hr) + { + if (FAILED(hr)) + { + // Set a breakpoint on this line to catch Win32 API errors. + throw Platform::Exception::CreateException(hr); + } + } + + // Function that reads from a binary file asynchronously. + inline Concurrency::task> ReadDataAsync(const std::wstring& filename) + { + using namespace Windows::Storage; + using namespace Concurrency; + + return create_task(PathIO::ReadBufferAsync(Platform::StringReference(filename.c_str()))).then( + [] (Streams::IBuffer^ fileBuffer) -> std::vector + { + std::vector returnBuffer; + returnBuffer.resize(fileBuffer->Length); + Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference(returnBuffer.data(), static_cast(returnBuffer.size()))); + return returnBuffer; + }); + } + + // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. + inline float ConvertDipsToPixels(float dips, float dpi) + { + constexpr float dipsPerInch = 96.0f; + return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. + } + +#if defined(_DEBUG) + // Check for SDK Layer support. + inline bool SdkLayersAvailable() + { + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps. + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + + return SUCCEEDED(hr); + } +#endif +} diff --git a/Samples/HolographicSpatialStage/cpp/Common/StepTimer.h b/Samples/HolographicSpatialStage/cpp/Common/StepTimer.h new file mode 100644 index 0000000000..eb9f8f6d72 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Common/StepTimer.h @@ -0,0 +1,189 @@ +#pragma once + +namespace DX +{ + // Helper class for animation and simulation timing. + class StepTimer + { + public: + StepTimer() : + m_elapsedTicks(0), + m_totalTicks(0), + m_leftOverTicks(0), + m_frameCount(0), + m_framesPerSecond(0), + m_framesThisSecond(0), + m_qpcSecondCounter(0), + m_isFixedTimeStep(false), + m_targetElapsedTicks(TicksPerSecond / 60) + { + m_qpcFrequency = GetPerformanceFrequency(); + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency / 10; + } + + // Get elapsed time since the previous Update call. + uint64 GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64 GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32 GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32 GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64 targetElapsed) { m_targetElapsedTicks = targetElapsed; } + void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64 TicksPerSecond = 10'000'000; + + static double TicksToSeconds(uint64 ticks) { return static_cast(ticks) / TicksPerSecond; } + static uint64 SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } + + // Convenient wrapper for QueryPerformanceFrequency. Throws an exception if + // the call to QueryPerformanceFrequency fails. + static inline uint64 GetPerformanceFrequency() + { + LARGE_INTEGER freq; + if (!QueryPerformanceFrequency(&freq)) + { + throw ref new Platform::FailureException(); + } + return freq.QuadPart; + } + + // Gets the current number of ticks from QueryPerformanceCounter. Throws an + // exception if the call to QueryPerformanceCounter fails. + static inline int64 GetTicks() + { + LARGE_INTEGER ticks; + if (!QueryPerformanceCounter(&ticks)) + { + throw ref new Platform::FailureException(); + } + return ticks.QuadPart; + } + + // After an intentional timing discontinuity (for instance a blocking IO operation) + // call this to avoid having the fixed timestep logic attempt a set of catch-up + // Update calls. + + void ResetElapsedTime() + { + m_qpcLastTime = GetTicks(); + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate number of times. + template + void Tick(const TUpdate& update) + { + // Query the current time. + uint64 currentTime = GetTicks(); + uint64 timeDelta = currentTime - m_qpcLastTime; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) + { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency; + + uint32 lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) + { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp + // the clock to exactly match the target value. This prevents tiny and irrelevant errors + // from accumulating over time. Without this clamping, a game that requested a 60 fps + // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually + // accumulate enough tiny errors that it would drop a frame. It is better to just round + // small deviations down to zero to leave things running smoothly. + + if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) + { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) + { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } + else + { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) + { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast(m_qpcFrequency)) + { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency; + } + } + + private: + + // Source timing data uses QPC units. + uint64 m_qpcFrequency; + uint64 m_qpcLastTime; + uint64 m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64 m_elapsedTicks; + uint64 m_totalTicks; + uint64 m_leftOverTicks; + + // Members for tracking the framerate. + uint32 m_frameCount; + uint32 m_framesPerSecond; + uint32 m_framesThisSecond; + uint64 m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64 m_targetElapsedTicks; + }; +} diff --git a/Samples/HolographicSpatialStage/cpp/Content/GeometryShader.hlsl b/Samples/HolographicSpatialStage/cpp/Content/GeometryShader.hlsl new file mode 100644 index 0000000000..b966621d48 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/GeometryShader.hlsl @@ -0,0 +1,31 @@ +// Per-vertex data from the vertex shader. +struct GeometryShaderInput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + uint instId : TEXCOORD0; +}; + +// Per-vertex data passed to the rasterizer. +struct GeometryShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + uint rtvId : SV_RenderTargetArrayIndex; +}; + +// This geometry shader is a pass-through that leaves the geometry unmodified +// and sets the render target array index. +[maxvertexcount(3)] +void main(triangle GeometryShaderInput input[3], inout TriangleStream outStream) +{ + GeometryShaderOutput output; + [unroll(3)] + for (int i = 0; i < 3; ++i) + { + output.pos = input[i].pos; + output.color = input[i].color; + output.rtvId = input[i].instId; + outStream.Append(output); + } +} diff --git a/Samples/HolographicSpatialStage/cpp/Content/PixelShader.hlsl b/Samples/HolographicSpatialStage/cpp/Content/PixelShader.hlsl new file mode 100644 index 0000000000..fd857896f5 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/PixelShader.hlsl @@ -0,0 +1,13 @@ +// Per-pixel color data passed through the pixel shader. +struct PixelShaderInput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; +}; + +// The pixel shader passes through the color data. The color data from +// is interpolated and assigned to a pixel at the rasterization step. +min16float4 main(PixelShaderInput input) : SV_TARGET +{ + return min16float4(input.color, 1.0f); +} diff --git a/Samples/HolographicSpatialStage/cpp/Content/SceneController.cpp b/Samples/HolographicSpatialStage/cpp/Content/SceneController.cpp new file mode 100644 index 0000000000..2a5a4ffd5f --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/SceneController.cpp @@ -0,0 +1,45 @@ +#include "pch.h" + +#include "SceneController.h" +#include "Common\DirectXHelper.h" + +using namespace HolographicSpatialStage; +using namespace Windows::Perception::Spatial; + +SceneController::SceneController(const std::shared_ptr& deviceResources) : + m_deviceResources(deviceResources) +{ +} + +void SceneController::Update(const DX::StepTimer& timer, SpatialCoordinateSystem^ viewCoords) +{ + for (auto& object : m_sceneObjects) + { + object->Update(timer, viewCoords); + } +} + +void SceneController::Render() +{ + for (auto& object : m_sceneObjects) + { + object->Render(); + } +} + +void SceneController::CreateDeviceDependentResources() +{ + for (auto& object : m_sceneObjects) + { + object->CreateDeviceDependentResources(); + } +} + +void SceneController::ReleaseDeviceDependentResources() +{ + for (auto& object : m_sceneObjects) + { + object->ReleaseDeviceDependentResources(); + } +} + diff --git a/Samples/HolographicSpatialStage/cpp/Content/SceneController.h b/Samples/HolographicSpatialStage/cpp/Content/SceneController.h new file mode 100644 index 0000000000..b95f58924a --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/SceneController.h @@ -0,0 +1,28 @@ +#pragma once + +#include "..\Common\DeviceResources.h" +#include "..\Common\StepTimer.h" +#include "ShaderStructures.h" +#include "SceneObject.h" + +namespace HolographicSpatialStage +{ + // This sample renderer instantiates a basic rendering pipeline. + class SceneController + { + public: + SceneController(const std::shared_ptr& deviceResources); + void CreateDeviceDependentResources(); + void ReleaseDeviceDependentResources(); + void Update(const DX::StepTimer& timer, Windows::Perception::Spatial::SpatialCoordinateSystem^ viewCoords); + void Render(); + + void AddSceneObject(std::shared_ptr& newObject) { m_sceneObjects.push_back(newObject); } + void ClearSceneObjects() { m_sceneObjects.clear(); } + + private: + // Cached pointer to device resources. + std::shared_ptr m_deviceResources; + std::vector> m_sceneObjects; + }; +} diff --git a/Samples/HolographicSpatialStage/cpp/Content/SceneObject.cpp b/Samples/HolographicSpatialStage/cpp/Content/SceneObject.cpp new file mode 100644 index 0000000000..50d7875c9f --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/SceneObject.cpp @@ -0,0 +1,329 @@ +#include "pch.h" +#include "SceneObject.h" + +#include "Common\DirectXHelper.h" + +#include + +using namespace HolographicSpatialStage; + +using namespace Concurrency; +using namespace DirectX; +using namespace Windows::Perception::Spatial; + + +SceneObject::SceneObject( + const std::shared_ptr& deviceResources, + DirectX::XMFLOAT3 const& color, + SpatialCoordinateSystem^ coordinateSystem) + : SceneObject(deviceResources, c_cubeVertices, color, coordinateSystem) +{ +} + +SceneObject::SceneObject( + const std::shared_ptr& deviceResources, + std::vector const& vertices, + DirectX::XMFLOAT3 const& color, + SpatialCoordinateSystem^ coordinateSystem) + : SceneObject(deviceResources, vertices, c_cubeIndices, color, coordinateSystem) +{ +} + +SceneObject::SceneObject( + const std::shared_ptr& deviceResources, + std::vector const& vertices, + std::vector const& indices, + DirectX::XMFLOAT3 const& color, + Windows::Perception::Spatial::SpatialCoordinateSystem^ coordinateSystem) +{ + m_coordinateSystem = coordinateSystem; + m_deviceResources = deviceResources; + + m_vertices.resize(vertices.size()); + for (size_t i = 0; i < vertices.size(); ++i) + { + m_vertices[i].pos = vertices[i]; + m_vertices[i].color = color; + } + + m_indices = indices; + m_indexCount = unsigned int(m_indices.size()); + + CreateDeviceDependentResources(); +} + +void SceneObject::Update(const DX::StepTimer& timer, Windows::Perception::Spatial::SpatialCoordinateSystem^ viewCoords) +{ + if (viewCoords == nullptr) + { + return; + } + + // Try to get transform. + auto transformContainer = m_coordinateSystem->TryGetTransformTo(viewCoords); + if (m_canRenderThisFrame = (transformContainer != nullptr)) + { + const XMMATRIX modelTransform = XMLoadFloat4x4(&transformContainer->Value); + XMStoreFloat4x4(&m_modelConstantBufferData.model, XMMatrixTranspose(modelTransform)); + } + + // Loading is asynchronous. Resources must be created before they can be updated. + if (!m_loadingComplete || !m_canRenderThisFrame) + { + return; + } + + // Use the D3D device context to update Direct3D device-based resources. + const auto context = m_deviceResources->GetD3DDeviceContext(); + + // Update the model transform buffer for the hologram. + context->UpdateSubresource( + m_modelConstantBuffer.Get(), + 0, + nullptr, + &m_modelConstantBufferData, + 0, + 0 + ); +} + +void SceneObject::Render() +{ + // Loading is asynchronous. Resources must be created before drawing can occur. + // Our coordinate system must also be locatable. + if (!m_loadingComplete || !m_canRenderThisFrame) + { + return; + } + + const auto context = m_deviceResources->GetD3DDeviceContext(); + + // Each vertex is one instance of the VertexPositionColor struct. + const UINT stride = sizeof(VertexPositionColor); + const UINT offset = 0; + context->IASetVertexBuffers( + 0, + 1, + m_vertexBuffer.GetAddressOf(), + &stride, + &offset + ); + context->IASetIndexBuffer( + m_indexBuffer.Get(), + DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short). + 0 + ); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->IASetInputLayout(m_inputLayout.Get()); + + if (m_useWireframe) + { + // Use a wireframe rasterizer state. + m_deviceResources->GetD3DDeviceContext()->RSSetState(m_wireframeRasterizerState.Get()); + } + else + { + // Use the default rasterizer state. + m_deviceResources->GetD3DDeviceContext()->RSSetState(m_defaultRasterizerState.Get()); + } + + // Attach the vertex shader. + context->VSSetShader( + m_vertexShader.Get(), + nullptr, + 0 + ); + // Apply the model constant buffer to the vertex shader. + context->VSSetConstantBuffers( + 0, + 1, + m_modelConstantBuffer.GetAddressOf() + ); + + if (!m_usingVprtShaders) + { + // On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature, + // a pass-through geometry shader is used to set the render target + // array index. + context->GSSetShader( + m_geometryShader.Get(), + nullptr, + 0 + ); + } + + // Attach the pixel shader. + context->PSSetShader( + m_pixelShader.Get(), + nullptr, + 0 + ); + + // Draw the objects. + context->DrawIndexedInstanced( + m_indexCount, // Index count per instance. + 2, // Instance count. + 0, // Start index location. + 0, // Base vertex location. + 0 // Start instance location. + ); +} + +void SceneObject::CreateDeviceDependentResources() +{ + m_usingVprtShaders = m_deviceResources->GetDeviceSupportsVprt(); + + // On devices that do support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature + // we can avoid using a pass-through geometry shader to set the render + // target array index, thus avoiding any overhead that would be + // incurred by setting the geometry shader stage. + std::wstring vertexShaderFileName = m_usingVprtShaders ? L"ms-appx:///VprtVertexShader.cso" : L"ms-appx:///VertexShader.cso"; + + // Load shaders asynchronously. + task> loadVSTask = DX::ReadDataAsync(vertexShaderFileName); + task> loadPSTask = DX::ReadDataAsync(L"ms-appx:///PixelShader.cso"); + + task> loadGSTask; + if (!m_usingVprtShaders) + { + // Load the pass-through geometry shader. + loadGSTask = DX::ReadDataAsync(L"ms-appx:///GeometryShader.cso"); + } + + // After the vertex shader file is loaded, create the shader and input layout. + task createVSTask = loadVSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateVertexShader( + fileData.data(), + fileData.size(), + nullptr, + &m_vertexShader + ) + ); + + constexpr std::array vertexDesc = + { { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + } }; + + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateInputLayout( + vertexDesc.data(), + static_cast(vertexDesc.size()), + fileData.data(), + static_cast(fileData.size()), + &m_inputLayout + ) + ); + }); + + // After the pixel shader file is loaded, create the shader and constant buffer. + task createPSTask = loadPSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreatePixelShader( + fileData.data(), + fileData.size(), + nullptr, + &m_pixelShader + ) + ); + + const CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateBuffer( + &constantBufferDesc, + nullptr, + &m_modelConstantBuffer + ) + ); + }); + + task createGSTask; + if (!m_usingVprtShaders) + { + // After the pass-through geometry shader file is loaded, create the shader. + createGSTask = loadGSTask.then([this](const std::vector& fileData) + { + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateGeometryShader( + fileData.data(), + fileData.size(), + nullptr, + &m_geometryShader + ) + ); + }); + } + + // Once all shaders are loaded, create the mesh. + task shaderTaskGroup = m_usingVprtShaders ? (createPSTask && createVSTask) : (createPSTask && createVSTask && createGSTask); + task createGeometryTask = shaderTaskGroup.then([this]() + { + // Load mesh vertices. Each vertex has a position and a color. + D3D11_SUBRESOURCE_DATA vertexBufferData = { 0 }; + vertexBufferData.pSysMem = m_vertices.data(); + vertexBufferData.SysMemPitch = 0; + vertexBufferData.SysMemSlicePitch = 0; + const CD3D11_BUFFER_DESC vertexBufferDesc( + sizeof(VertexPositionColor) * static_cast(m_vertices.size()), + D3D11_BIND_VERTEX_BUFFER); + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateBuffer( + &vertexBufferDesc, + &vertexBufferData, + &m_vertexBuffer + ) + ); + + D3D11_SUBRESOURCE_DATA indexBufferData = { 0 }; + indexBufferData.pSysMem = m_indices.data(); + indexBufferData.SysMemPitch = 0; + indexBufferData.SysMemSlicePitch = 0; + CD3D11_BUFFER_DESC indexBufferDesc( + sizeof(unsigned short) * static_cast(m_indices.size()), + D3D11_BIND_INDEX_BUFFER); + DX::ThrowIfFailed( + m_deviceResources->GetD3DDevice()->CreateBuffer( + &indexBufferDesc, + &indexBufferData, + &m_indexBuffer + ) + ); + }); + + // Once the geometry is loaded, the object is ready to be rendered. + createGeometryTask.then([this]() + { + // Create the default rasterizer state. + D3D11_RASTERIZER_DESC rasterizerDesc = CD3D11_RASTERIZER_DESC(D3D11_DEFAULT); + m_deviceResources->GetD3DDevice()->CreateRasterizerState(&rasterizerDesc, m_defaultRasterizerState.GetAddressOf()); + + // Create a wireframe rasterizer state. + rasterizerDesc.AntialiasedLineEnable = true; + rasterizerDesc.CullMode = D3D11_CULL_NONE; + rasterizerDesc.FillMode = D3D11_FILL_WIREFRAME; + m_deviceResources->GetD3DDevice()->CreateRasterizerState(&rasterizerDesc, m_wireframeRasterizerState.GetAddressOf()); + + m_loadingComplete = true; + }); +} + +void SceneObject::ReleaseDeviceDependentResources() +{ + m_loadingComplete = false; + m_usingVprtShaders = false; + m_vertexShader.Reset(); + m_inputLayout.Reset(); + m_pixelShader.Reset(); + m_geometryShader.Reset(); + m_modelConstantBuffer.Reset(); + m_vertexBuffer.Reset(); + m_indexBuffer.Reset(); + m_defaultRasterizerState.Reset(); + m_wireframeRasterizerState.Reset(); +} diff --git a/Samples/HolographicSpatialStage/cpp/Content/SceneObject.h b/Samples/HolographicSpatialStage/cpp/Content/SceneObject.h new file mode 100644 index 0000000000..8da6501f3f --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/SceneObject.h @@ -0,0 +1,106 @@ +#pragma once + +#include "Common\DeviceResources.h" +#include "Common\StepTimer.h" +#include "Content\ShaderStructures.h" + +namespace HolographicSpatialStage +{ + class SceneObject + { + public: + SceneObject( + const std::shared_ptr& deviceResources, + DirectX::XMFLOAT3 const& color, + Windows::Perception::Spatial::SpatialCoordinateSystem^ coordinateSystem); + + SceneObject( + const std::shared_ptr& deviceResources, + std::vector const& vertices, + DirectX::XMFLOAT3 const& color, + Windows::Perception::Spatial::SpatialCoordinateSystem^ coordinateSystem); + + SceneObject( + const std::shared_ptr& deviceResources, + std::vector const& vertices, + std::vector const& indices, + DirectX::XMFLOAT3 const& color, + Windows::Perception::Spatial::SpatialCoordinateSystem^ coordinateSystem); + + void CreateDeviceDependentResources(); + void ReleaseDeviceDependentResources(); + void Update(const DX::StepTimer& timer, Windows::Perception::Spatial::SpatialCoordinateSystem^ viewCoords); + void Render(); + + void EnableWireframe() { m_useWireframe = true; } + + private: + // Cached pointer to device resources. + std::shared_ptr m_deviceResources; + + // Direct3D resources. + Microsoft::WRL::ComPtr m_inputLayout; + Microsoft::WRL::ComPtr m_vertexBuffer; + Microsoft::WRL::ComPtr m_indexBuffer; + Microsoft::WRL::ComPtr m_vertexShader; + Microsoft::WRL::ComPtr m_geometryShader; + Microsoft::WRL::ComPtr m_pixelShader; + Microsoft::WRL::ComPtr m_modelConstantBuffer; + + // Rasterizer states, for different rendering modes. + Microsoft::WRL::ComPtr m_defaultRasterizerState; + Microsoft::WRL::ComPtr m_wireframeRasterizerState; + + // System resources. + ModelConstantBuffer m_modelConstantBufferData; + std::vector m_vertices; + std::vector m_indices; + unsigned int m_indexCount; + + Windows::Perception::Spatial::SpatialCoordinateSystem^ m_coordinateSystem; + + // Variables used with the rendering loop. + bool m_loadingComplete = false; + bool m_canRenderThisFrame = false; + bool m_useWireframe = false; + + // If the current D3D Device supports VPRT, we can avoid using a geometry + // shader just to set the render target array index. + bool m_usingVprtShaders = false; + + // Vertices for a cube. + const std::vector c_cubeVertices = + { { + { DirectX::XMFLOAT3(-0.01f, -0.01f, -0.01f) }, + { DirectX::XMFLOAT3(-0.01f, -0.01f, 0.01f) }, + { DirectX::XMFLOAT3(-0.01f, 0.01f, -0.01f) }, + { DirectX::XMFLOAT3(-0.01f, 0.01f, 0.01f) }, + { DirectX::XMFLOAT3( 0.01f, -0.01f, -0.01f) }, + { DirectX::XMFLOAT3( 0.01f, -0.01f, 0.01f) }, + { DirectX::XMFLOAT3( 0.01f, 0.01f, -0.01f) }, + { DirectX::XMFLOAT3( 0.01f, 0.01f, 0.01f) }, + } }; + + // Indices for a six-sided shape. + const std::vector c_cubeIndices = + { { + 2,1,0, // -x + 2,3,1, + + 6,4,5, // +x + 6,5,7, + + 0,1,5, // -y + 0,5,4, + + 2,6,7, // +y + 2,7,3, + + 0,4,6, // -z + 0,6,2, + + 1,3,7, // +z + 1,7,5, + } }; + }; +} diff --git a/Samples/HolographicSpatialStage/cpp/Content/ShaderStructures.h b/Samples/HolographicSpatialStage/cpp/Content/ShaderStructures.h new file mode 100644 index 0000000000..c7820b651b --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/ShaderStructures.h @@ -0,0 +1,21 @@ +#pragma once + +namespace HolographicSpatialStage +{ + // Constant buffer used to send hologram position transform to the shader pipeline. + struct ModelConstantBuffer + { + DirectX::XMFLOAT4X4 model; + }; + + // Assert that the constant buffer remains 16-byte aligned (best practice). + static_assert((sizeof(ModelConstantBuffer) % (sizeof(float) * 4)) == 0, "Model constant buffer size must be 16-byte aligned (16 bytes is the length of four floats)."); + + + // Used to send per-vertex data to the vertex shader. + struct VertexPositionColor + { + DirectX::XMFLOAT3 pos; + DirectX::XMFLOAT3 color; + }; +} \ No newline at end of file diff --git a/Samples/HolographicSpatialStage/cpp/Content/VPRTVertexShader.hlsl b/Samples/HolographicSpatialStage/cpp/Content/VPRTVertexShader.hlsl new file mode 100644 index 0000000000..8b6dd6c742 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/VPRTVertexShader.hlsl @@ -0,0 +1,11 @@ +// Per-vertex data passed to the geometry shader. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + + // The render target array index is set here in the vertex shader. + uint viewId : SV_RenderTargetArrayIndex; +}; + +#include "VertexShaderShared.hlsl" diff --git a/Samples/HolographicSpatialStage/cpp/Content/VertexShader.hlsl b/Samples/HolographicSpatialStage/cpp/Content/VertexShader.hlsl new file mode 100644 index 0000000000..f8ae0e1492 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/VertexShader.hlsl @@ -0,0 +1,11 @@ +// Per-vertex data passed to the geometry shader. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + + // The render target array index will be set by the geometry shader. + uint viewId : TEXCOORD0; +}; + +#include "VertexShaderShared.hlsl" diff --git a/Samples/HolographicSpatialStage/cpp/Content/VertexShaderShared.hlsl b/Samples/HolographicSpatialStage/cpp/Content/VertexShaderShared.hlsl new file mode 100644 index 0000000000..7a49de6fab --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Content/VertexShaderShared.hlsl @@ -0,0 +1,47 @@ +// A constant buffer that stores the model transform. +cbuffer ModelConstantBuffer : register(b0) +{ + float4x4 model; +}; + +// A constant buffer that stores each set of view and projection matrices in column-major format. +cbuffer ViewProjectionConstantBuffer : register(b1) +{ + float4x4 viewProjection[2]; +}; + +// Per-vertex data used as input to the vertex shader. +struct VertexShaderInput +{ + min16float3 pos : POSITION; + min16float3 color : COLOR0; + uint instId : SV_InstanceID; +}; + +// Simple shader to do vertex processing on the GPU. +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Note which view this vertex has been sent to. Used for matrix lookup. + // Taking the modulo of the instance ID allows geometry instancing to be used + // along with stereo instanced drawing; in that case, two copies of each + // instance would be drawn, one for left and one for right. + int idx = input.instId % 2; + + // Transform the vertex position into world space. + pos = mul(pos, model); + + // Correct for perspective and project the vertex position onto the screen. + pos = mul(pos, viewProjection[idx]); + output.pos = (min16float4)pos; + + // Pass the color through without modification. + output.color = input.color; + + // Set the render target array index. + output.viewId = idx; + + return output; +} diff --git a/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.sln b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.sln new file mode 100644 index 0000000000..baa4b8a21b --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.10 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HolographicSpatialStage", "HolographicSpatialStage.vcxproj", "{4F81929A-5A25-536F-ABCF-185339C2D784}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4F81929A-5A25-536F-ABCF-185339C2D784}.Debug|x64.ActiveCfg = Debug|x64 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Debug|x64.Build.0 = Debug|x64 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Debug|x64.Deploy.0 = Debug|x64 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Debug|x86.ActiveCfg = Debug|Win32 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Debug|x86.Build.0 = Debug|Win32 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Debug|x86.Deploy.0 = Debug|Win32 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Release|x64.ActiveCfg = Release|x64 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Release|x64.Build.0 = Release|x64 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Release|x64.Deploy.0 = Release|x64 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Release|x86.ActiveCfg = Release|Win32 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Release|x86.Build.0 = Release|Win32 + {4F81929A-5A25-536F-ABCF-185339C2D784}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.vcxproj b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.vcxproj new file mode 100644 index 0000000000..0f27431fb0 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.vcxproj @@ -0,0 +1,213 @@ + + + + {4f81929a-5a25-536f-abcf-185339c2d784} + HolographicApp + HolographicSpatialStage + en-US + 15.0 + true + Windows Store + 10.0.15044.0 + 10.0.10586.0 + 10.0 + true + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + Application + true + v141 + + + Application + false + true + v141 + + + Application + true + v141 + + + Application + false + true + v141 + + + + + + + + + + + + + + + + + + + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + _DEBUG;%(PreprocessorDefinitions) + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + _DEBUG;%(PreprocessorDefinitions) + + + + + d2d1.lib; d3d11.lib; dxgi.lib; dwrite.lib; windowscodecs.lib; %(AdditionalDependencies); + %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 + mincore.lib;kernel32.lib;ole32.lib;%(IgnoreSpecificDefaultLibraries) + + + pch.h + $(IntDir)pch.pch + $(ProjectDir);$(IntermediateOutputPath);%(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + NDEBUG;%(PreprocessorDefinitions) + + + + + Assets\microsoft-sdk.png + + + Assets\smallTile-sdk.png + + + Assets\splash-sdk.png + + + Assets\squareTile-sdk.png + + + Assets\storeLogo-sdk.png + + + Assets\tile-sdk.png + + + Assets\windows-sdk.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + Designer + + + + + Pixel + 5.0 + + + + Vertex + 5.0 + + + Vertex + 5.0 + + + Geometry + 5.0 + + + + + + + + + \ No newline at end of file diff --git a/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.vcxproj.filters b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.vcxproj.filters new file mode 100644 index 0000000000..66bbb771b0 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStage.vcxproj.filters @@ -0,0 +1,107 @@ + + + + + 4b4eb4bc-8cc1-4f65-8d1e-50aa6da51de3 + + + 15bd3c0c-31dd-42d0-a256-5cc4d429d4e6 + bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png + + + d7d66920-a448-4440-ab09-235b6e5ae41c + + + ca2f9fcc-8362-4702-b699-306b1ee93659 + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + + + + + + Content + + + + Content + + + + + + + Content + + + + Content + + + + Content + + + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + Content\Shaders + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + \ No newline at end of file diff --git a/Samples/HolographicSpatialStage/cpp/HolographicSpatialStageMain.cpp b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStageMain.cpp new file mode 100644 index 0000000000..9e4b04bb37 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStageMain.cpp @@ -0,0 +1,328 @@ +#include "pch.h" +#include "HolographicSpatialStageMain.h" +#include "Common\DirectXHelper.h" + +#include +#include + + +using namespace HolographicSpatialStage; + +using namespace concurrency; +using namespace Platform; +using namespace Microsoft::WRL; +using namespace Windows::Graphics::DirectX::Direct3D11; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Numerics; +using namespace Windows::Gaming::Input; +using namespace Windows::Graphics::Holographic; +using namespace Windows::Perception::Spatial; +using namespace Windows::UI::Input::Spatial; +using namespace std::placeholders; + +// Loads and initializes application assets when the application is loaded. +HolographicSpatialStageMain::HolographicSpatialStageMain(const std::shared_ptr& deviceResources) : + m_deviceResources(deviceResources) +{ + // Register to be notified if the device is lost or recreated. + m_deviceResources->RegisterDeviceNotify(this); +} + +void HolographicSpatialStageMain::SetHolographicSpace(HolographicSpace^ holographicSpace) +{ + UnregisterHolographicEventHandlers(); + + m_holographicSpace = holographicSpace; + + // Initialize the sample. + m_sceneController = std::make_shared(m_deviceResources); + + // Set up spatial stage. + m_spatialStageManager = std::make_shared(m_deviceResources, m_sceneController); + + // Use the default SpatialLocator to track the motion of the device. + auto locator = SpatialLocator::GetDefault(); + + // Be able to respond to changes in the positional tracking state. + if (locator != nullptr) + { + m_locatabilityChangedToken = + locator->LocatabilityChanged += + ref new Windows::Foundation::TypedEventHandler( + std::bind(&HolographicSpatialStageMain::OnLocatabilityChanged, this, _1, _2) + ); + } + + // Respond to camera added events by creating any resources that are specific + // to that camera, such as the back buffer render target view. + // When we add an event handler for CameraAdded, the API layer will avoid putting + // the new camera in new HolographicFrames until we complete the deferral we created + // for that handler, or return from the handler without creating a deferral. This + // allows the app to take more than one frame to finish creating resources and + // loading assets for the new holographic camera. + // This function should be registered before the app creates any HolographicFrames. + m_cameraAddedToken = + m_holographicSpace->CameraAdded += + ref new Windows::Foundation::TypedEventHandler( + std::bind(&HolographicSpatialStageMain::OnCameraAdded, this, _1, _2) + ); + + // Respond to camera removed events by releasing resources that were created for that + // camera. + // When the app receives a CameraRemoved event, it releases all references to the back + // buffer right away. This includes render target views, Direct2D target bitmaps, and so on. + // The app must also ensure that the back buffer is not attached as a render target, as + // shown in DeviceResources::ReleaseResourcesForBackBuffer. + m_cameraRemovedToken = + m_holographicSpace->CameraRemoved += + ref new Windows::Foundation::TypedEventHandler( + std::bind(&HolographicSpatialStageMain::OnCameraRemoved, this, _1, _2) + ); +} + +void HolographicSpatialStageMain::UnregisterHolographicEventHandlers() +{ + if (m_holographicSpace != nullptr) + { + // Clear previous event registrations. + + if (m_cameraAddedToken.Value != 0) + { + m_holographicSpace->CameraAdded -= m_cameraAddedToken; + m_cameraAddedToken.Value = 0; + } + + if (m_cameraRemovedToken.Value != 0) + { + m_holographicSpace->CameraRemoved -= m_cameraRemovedToken; + m_cameraRemovedToken.Value = 0; + } + } + + auto locator = SpatialLocator::GetDefault(); + if (locator != nullptr) + { + locator->LocatabilityChanged -= m_locatabilityChangedToken; + } +} + +HolographicSpatialStageMain::~HolographicSpatialStageMain() +{ + // Deregister device notification. + m_deviceResources->RegisterDeviceNotify(nullptr); + + UnregisterHolographicEventHandlers(); +} + +// Updates the application state once per frame. +HolographicFrame^ HolographicSpatialStageMain::Update() +{ + // Before doing the timer update, there is some work to do per-frame + // to maintain holographic rendering. First, we will get information + // about the current frame. + + // The HolographicFrame has information that the app needs in order + // to update and render the current frame. The app begins each new + // frame by calling CreateNextFrame. + HolographicFrame^ holographicFrame = m_holographicSpace->CreateNextFrame(); + + // Get a prediction of where holographic cameras will be when this frame + // is presented. + HolographicFramePrediction^ prediction = holographicFrame->CurrentPrediction; + + // Back buffers can change from frame to frame. Validate each buffer, and recreate + // resource views and depth buffers as needed. + m_deviceResources->EnsureCameraResources(holographicFrame, prediction); + + // Next, we get a coordinate system from the attached frame of reference that is + // associated with the current frame. Later, this coordinate system is used for + // for creating the stereo view matrices when rendering the sample content. + SpatialCoordinateSystem^ currentCoordinateSystem = m_spatialStageManager->GetCoordinateSystemForCurrentStage(); + + m_timer.Tick([&]() + { + m_sceneController->Update(m_timer, currentCoordinateSystem); + }); + + // The holographic frame will be used to get up-to-date view and projection matrices and + // to present the swap chain. + return holographicFrame; +} + +// Renders the current frame to each holographic camera, according to the +// current application and spatial positioning state. Returns true if the +// frame was rendered to at least one camera. +bool HolographicSpatialStageMain::Render(Windows::Graphics::Holographic::HolographicFrame^ holographicFrame) +{ + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return false; + } + + // Lock the set of holographic camera resources, then draw to each camera + // in this frame. + return m_deviceResources->UseHolographicCameraResources( + [this, holographicFrame](std::map>& cameraResourceMap) + { + // Up-to-date frame predictions enhance the effectiveness of image stablization and + // allow more accurate positioning of holograms. + holographicFrame->UpdateCurrentPrediction(); + HolographicFramePrediction^ prediction = holographicFrame->CurrentPrediction; + + bool atLeastOneCameraRendered = false; + for (auto cameraPose : prediction->CameraPoses) + { + // This represents the device-based resources for a HolographicCamera. + DX::CameraResources* pCameraResources = cameraResourceMap[cameraPose->HolographicCamera->Id].get(); + + // Get the device context. + const auto context = m_deviceResources->GetD3DDeviceContext(); + const auto depthStencilView = pCameraResources->GetDepthStencilView(); + + // Set render targets to the current holographic camera. + ID3D11RenderTargetView *const targets[1] = { pCameraResources->GetBackBufferRenderTargetView() }; + context->OMSetRenderTargets(1, targets, depthStencilView); + + // Clear the back buffer and depth stencil view. + context->ClearRenderTargetView(targets[0], DirectX::Colors::Transparent); + context->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + // The view and projection matrices for each holographic camera will change + // every frame. This function refreshes the data in the constant buffer for + // the holographic camera indicated by cameraPose. + SpatialCoordinateSystem^ currentCoordinateSystem = m_spatialStageManager->GetCoordinateSystemForCurrentStage(); + if (currentCoordinateSystem != nullptr) + { + pCameraResources->UpdateViewProjectionBuffer(m_deviceResources, cameraPose, currentCoordinateSystem); + } + + // Attach the view/projection constant buffer for this camera to the graphics pipeline. + bool cameraActive = pCameraResources->AttachViewProjectionBuffer(m_deviceResources); + + // Only render world-locked content when positional tracking is active. + if (cameraActive) + { + // Draw the sample hologram. + m_sceneController->Render(); + + // We complete the frame by using the depth buffer to optimize image stabilization. + ComPtr depthBuffer = cameraResourceMap.at(cameraPose->HolographicCamera->Id)->GetDepthBufferTexture2D(); + + // The depth buffer might be stereo, so we take the first subresource. + // This should also work for mono cameras. + ComPtr depthStencilResource; + HRESULT hr = depthBuffer.As(&depthStencilResource); + ComPtr depthDxgiSurface; + if (SUCCEEDED(hr)) + { + hr = depthStencilResource->CreateSubresourceSurface(0, &depthDxgiSurface); + } + + if (SUCCEEDED(hr)) + { + IDirect3DSurface^ depthD3DSurface = CreateDirect3DSurface(depthDxgiSurface.Get()); + auto renderingParameters = holographicFrame->GetRenderingParameters(cameraPose); + try + { + // Provide the depth buffer. + renderingParameters->CommitDirect3D11DepthBuffer(depthD3DSurface); + } + catch (Platform::InvalidArgumentException^ ex) + { + OutputDebugStringA("Unsupported depth buffer format, invalid properties, or incorrect D3D device.\n"); + } + } + + atLeastOneCameraRendered = true; + } + } + + return atLeastOneCameraRendered; + }); +} + +// Notifies classes that use Direct3D device resources that the device resources +// need to be released before this method returns. +void HolographicSpatialStageMain::OnDeviceLost() +{ + m_sceneController->ReleaseDeviceDependentResources(); +} + +// Notifies classes that use Direct3D device resources that the device resources +// may now be recreated. +void HolographicSpatialStageMain::OnDeviceRestored() +{ + m_sceneController->CreateDeviceDependentResources(); +} + +void HolographicSpatialStageMain::OnLocatabilityChanged(SpatialLocator^ sender, Object^ args) +{ + switch (sender->Locatability) + { + case SpatialLocatability::Unavailable: + // Holograms cannot be rendered. + { + String^ message = L"Warning! Positional tracking is " + + sender->Locatability.ToString() + L".\n"; + OutputDebugStringW(message->Data()); + } + break; + + // In the following three cases, it is still possible to place holograms using a + // SpatialLocatorAttachedFrameOfReference. + case SpatialLocatability::PositionalTrackingActivating: + // The system is preparing to use positional tracking. + + case SpatialLocatability::OrientationOnly: + // Positional tracking has not been activated. + + case SpatialLocatability::PositionalTrackingInhibited: + // Positional tracking is temporarily inhibited. User action may be required + // in order to restore positional tracking. + break; + + case SpatialLocatability::PositionalTrackingActive: + // Positional tracking is active. World-locked content can be rendered. + break; + } +} + +void HolographicSpatialStageMain::OnCameraAdded( + HolographicSpace^ sender, + HolographicSpaceCameraAddedEventArgs^ args + ) +{ + Deferral^ deferral = args->GetDeferral(); + HolographicCamera^ holographicCamera = args->Camera; + create_task([this, deferral, holographicCamera] () + { + // Create device-based resources for the holographic camera and add it to the list of + // cameras used for updates and rendering. Notes: + // * Since this function may be called at any time, the AddHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // adding the new camera. At 60 frames per second this wait should not take long. + // * A subsequent Update will take the back buffer from the RenderingParameters of this + // camera's CameraPose and use it to create the ID3D11RenderTargetView for this camera. + // Content can then be rendered for the HolographicCamera. + m_deviceResources->AddHolographicCamera(holographicCamera); + + // Holographic frame predictions will not include any information about this camera until + // the deferral is completed. + deferral->Complete(); + }); +} + +void HolographicSpatialStageMain::OnCameraRemoved( + HolographicSpace^ sender, + HolographicSpaceCameraRemovedEventArgs^ args + ) +{ + // Before letting this callback return, ensure that all references to the back buffer + // are released. + // Since this function may be called at any time, the RemoveHolographicCamera function + // waits until it can get a lock on the set of holographic camera resources before + // deallocating resources for this camera. At 60 frames per second this wait should + // not take long. + m_deviceResources->RemoveHolographicCamera(args->Camera); +} diff --git a/Samples/HolographicSpatialStage/cpp/HolographicSpatialStageMain.h b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStageMain.h new file mode 100644 index 0000000000..b009e7653f --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/HolographicSpatialStageMain.h @@ -0,0 +1,73 @@ +#pragma once + +#include "Common\DeviceResources.h" +#include "Common\StepTimer.h" + +#include "Content\SceneController.h" +#include "SpatialStageManager.h" + +// Updates, renders, and presents holographic content using Direct3D. +namespace HolographicSpatialStage +{ + class HolographicSpatialStageMain : public DX::IDeviceNotify + { + public: + HolographicSpatialStageMain(const std::shared_ptr& deviceResources); + ~HolographicSpatialStageMain(); + + // Sets the holographic space. This is our closest analogue to setting a new window + // for the app. + void SetHolographicSpace(Windows::Graphics::Holographic::HolographicSpace^ holographicSpace); + + // Starts the holographic frame and updates the content. + Windows::Graphics::Holographic::HolographicFrame^ Update(); + + // Renders holograms, including world-locked content. + bool Render(Windows::Graphics::Holographic::HolographicFrame^ holographicFrame); + + // IDeviceNotify + virtual void OnDeviceLost(); + virtual void OnDeviceRestored(); + + private: + // Asynchronously creates resources for new holographic cameras. + void OnCameraAdded( + Windows::Graphics::Holographic::HolographicSpace^ sender, + Windows::Graphics::Holographic::HolographicSpaceCameraAddedEventArgs^ args); + + // Synchronously releases resources for holographic cameras that are no longer + // attached to the system. + void OnCameraRemoved( + Windows::Graphics::Holographic::HolographicSpace^ sender, + Windows::Graphics::Holographic::HolographicSpaceCameraRemovedEventArgs^ args); + + // Used to notify the app when the positional tracking state changes. + void OnLocatabilityChanged( + Windows::Perception::Spatial::SpatialLocator^ sender, + Platform::Object^ args); + + // Clears event registration state. Used when changing to a new HolographicSpace + // and when tearing down AppMain. + void UnregisterHolographicEventHandlers(); + + std::shared_ptr m_sceneController; + + // Cached pointer to device resources. + std::shared_ptr m_deviceResources; + + std::shared_ptr m_spatialStageManager; + + // Render loop timer. + DX::StepTimer m_timer; + + // Represents the holographic space around the user. + Windows::Graphics::Holographic::HolographicSpace^ m_holographicSpace; + + // Event registration tokens. + Windows::Foundation::EventRegistrationToken m_cameraAddedToken; + Windows::Foundation::EventRegistrationToken m_cameraRemovedToken; + Windows::Foundation::EventRegistrationToken m_locatabilityChangedToken; + Windows::Foundation::EventRegistrationToken m_gamepadAddedEventToken; + Windows::Foundation::EventRegistrationToken m_gamepadRemovedEventToken; + }; +} diff --git a/Samples/HolographicSpatialStage/cpp/Package.appxmanifest b/Samples/HolographicSpatialStage/cpp/Package.appxmanifest new file mode 100644 index 0000000000..991055fdf0 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/Package.appxmanifest @@ -0,0 +1,39 @@ + + + + + + Holographic Spatial Stage C++ Sample + Microsoft Corporation + Assets\StoreLogo-sdk.png + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/HolographicSpatialStage/cpp/SpatialStageManager.cpp b/Samples/HolographicSpatialStage/cpp/SpatialStageManager.cpp new file mode 100644 index 0000000000..4826c9ddfc --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/SpatialStageManager.cpp @@ -0,0 +1,255 @@ +#include "pch.h" +#include "SpatialStageManager.h" + +using namespace HolographicSpatialStage; + +using namespace DirectX; +using namespace Platform; +using namespace std::placeholders; +using namespace Windows::Foundation; +using namespace Windows::Perception::Spatial; +using namespace Windows::Foundation::Numerics; + +SpatialStageManager::SpatialStageManager( + const std::shared_ptr& deviceResources, + const std::shared_ptr& sceneController) + : m_deviceResources(deviceResources), m_sceneController(sceneController) +{ + // Get notified when the stage is updated. + m_spatialStageChangedEventToken = SpatialStageFrameOfReference::CurrentChanged += + ref new EventHandler(std::bind(&SpatialStageManager::OnCurrentChanged, this, _1)); + + // Make sure to get the current spatial stage. + OnCurrentChanged(nullptr); +} + +SpatialStageManager::~SpatialStageManager() +{ + SpatialStageFrameOfReference::CurrentChanged -= m_spatialStageChangedEventToken; +} + +void SpatialStageManager::OnCurrentChanged(Object^ /*o*/) +{ + // The event notifies us that a new stage is available. + // Get the current stage. + m_currentStage = SpatialStageFrameOfReference::Current; + m_currentCoordinateSystem = nullptr; + m_stationaryFrameOfReference = nullptr; + + // Clear previous content. + m_sceneController->ClearSceneObjects(); + + XMFLOAT3 visibleAreaColor; + std::vector visibleAreaIndicatorVertices; + + if (m_currentStage != nullptr) + { + // Obtain stage geometry. + m_currentCoordinateSystem = m_currentStage->CoordinateSystem; + auto boundsVertexArray = m_currentStage->TryGetMovementBounds(m_currentCoordinateSystem); + if (boundsVertexArray->Length > 0) + { + // Visualize the area where the user can move around. + std::vector boundsVertices; + boundsVertices.resize(boundsVertexArray->Length); + memcpy(boundsVertices.data(), boundsVertexArray->Data, boundsVertexArray->Length * sizeof(float3)); + std::vector indices = TriangulatePoints(boundsVertices); + m_stageBoundsShape = + std::make_shared( + m_deviceResources, + reinterpret_cast&>(boundsVertices), + indices, + XMFLOAT3(DirectX::Colors::SeaGreen), + m_currentCoordinateSystem); + m_sceneController->AddSceneObject(m_stageBoundsShape); + } + + // In this sample, we draw a visual indicator for some spatial stage properties. + // If the view is forward-only, the indicator is a half circle pointing forward - otherwise, it + // is a full circle. + // If the user can walk around, the indicator is blue. If the user is seated, it is red. + + // The indicator is rendered at the origin - which is where the user declared the center of the + // stage to be during setup - above the plane of the stage bounds object. + float3 visibleAreaCenter = float3(0.f, 0.001f, 0.f); + + // Its shape depends on the look direction range. + if (m_currentStage->LookDirectionRange == SpatialLookDirectionRange::ForwardOnly) + { + // Half circle for forward-only look direction range. + visibleAreaIndicatorVertices = CreateCircle(visibleAreaCenter, 0.25f, 9, XM_PI); + } + else + { + // Full circle for omnidirectional look direction range. + visibleAreaIndicatorVertices = CreateCircle(visibleAreaCenter, 0.25f, 16, XM_2PI); + } + + // Its color depends on the movement range. + if (m_currentStage->MovementRange == SpatialMovementRange::NoMovement) + { + visibleAreaColor = XMFLOAT3(DirectX::Colors::OrangeRed); + } + else + { + visibleAreaColor = XMFLOAT3(DirectX::Colors::Aqua); + } + } + else + { + // No spatial stage was found. + // Fall back to a stationary coordinate system. + auto locator = SpatialLocator::GetDefault(); + if (locator) + { + m_stationaryFrameOfReference = locator->CreateStationaryFrameOfReferenceAtCurrentLocation(float3(0.f, -0.5f, 0.f)); + if (m_stationaryFrameOfReference) + { + m_currentCoordinateSystem = m_stationaryFrameOfReference->CoordinateSystem; + + // Render an indicator, so that we know we fell back to a mode without a stage. + visibleAreaIndicatorVertices = CreateCircle(float3(0.f), 0.125f, 16, XM_2PI); + visibleAreaColor = XMFLOAT3(DirectX::Colors::LightSlateGray); + } + } + } + + if (m_currentCoordinateSystem != nullptr) + { + std::vector visibleAreaIndicatorIndices = TriangulatePoints(visibleAreaIndicatorVertices); + m_stageVisibleAreaIndicatorShape = + std::make_shared( + m_deviceResources, + reinterpret_cast&>(visibleAreaIndicatorVertices), + visibleAreaIndicatorIndices, + visibleAreaColor, + m_currentCoordinateSystem); + m_sceneController->AddSceneObject(m_stageVisibleAreaIndicatorShape); + } +} + +SpatialCoordinateSystem^ SpatialStageManager::GetCoordinateSystemForCurrentStage() +{ + return m_currentCoordinateSystem; +} + +// Creates a 2D circle in the x-z plane, with the specified properties. +std::vector SpatialStageManager::CreateCircle(float3 center, float radius, int divisions, float radians) +{ + std::vector vertices(divisions); + + for (int i = 0; i < divisions; ++i) + { + float radiansThisIteration = radians * float(i) / float(divisions); + vertices[i] = + { + center.x + (radius * -cos(radiansThisIteration)), + center.y, + center.z + (radius * -sin(radiansThisIteration)) + }; + } + + return vertices; +} + +// Triangulates a 2D shape, such as the spatial stage movement bounds. +// This function expects a set of vertices that define the boundaries of a shape, in +// clockwise order. +std::vector SpatialStageManager::TriangulatePoints(std::vector const& vertices) +{ + size_t const& vertexCount = vertices.size(); + + // Segments of the shape are removed as they are triangularized. + std::vector vertexRemoved; + vertexRemoved.resize(vertexCount, false); + unsigned int vertexRemovedCount = 0; + + // Indices are used to define triangles. + std::vector indices; + + // Decompose into convex segments. + unsigned short currentVertex = 0; + while (vertexRemovedCount < (vertexCount - 2)) + { + // Get next triangle: + // Start with the current vertex. + unsigned short index1 = currentVertex; + + // Get the next available vertex. + unsigned short index2 = index1 + 1; + + // This cycles to the next available index. + auto CycleIndex = [=](unsigned short indexToCycle, unsigned short stopIndex) + { + // Make sure the index does not exceed bounds. + if (indexToCycle >= unsigned short(vertexCount)) + { + indexToCycle -= unsigned short(vertexCount); + } + + while (vertexRemoved[indexToCycle]) + { + // If the vertex is removed, go to the next available one. + ++indexToCycle; + + // Make sure the index does not exceed bounds. + if (indexToCycle >= unsigned short(vertexCount)) + { + indexToCycle -= unsigned short(vertexCount); + } + + // Prevent cycling all the way around. + // Should not be needed, as we limit with the vertex count. + if (indexToCycle == stopIndex) + { + break; + } + } + + return indexToCycle; + }; + index2 = CycleIndex(index2, index1); + + // Get the next available vertex after that. + unsigned short index3 = index2 + 1; + index3 = CycleIndex(index3, index1); + + // Vertices that may define a triangle inside the 2D shape. + auto& v1 = vertices[index1]; + auto& v2 = vertices[index2]; + auto& v3 = vertices[index3]; + + // If the projection of the first segment (in clockwise order) onto the second segment is + // positive, we know that the clockwise angle is less than 180 degrees, which tells us + // that the triangle formed by the two segments is contained within the bounding shape. + auto v2ToV1 = v1 - v2; + auto v2ToV3 = v3 - v2; + float3 normalToV2ToV3 = { -v2ToV3.z, 0.f, v2ToV3.x }; + float projectionOntoNormal = dot(v2ToV1, normalToV2ToV3); + if (projectionOntoNormal >= 0) + { + // Triangle is contained within the 2D shape. + + // Remove peak vertex from the list. + vertexRemoved[index2] = true; + ++vertexRemovedCount; + + // Create the triangle. + indices.push_back(index1); + indices.push_back(index2); + indices.push_back(index3); + + // Continue on to the next outer triangle. + currentVertex = index3; + } + else + { + // Triangle is a cavity in the 2D shape. + // The next triangle starts at the inside corner. + currentVertex = index2; + } + } + + indices.shrink_to_fit(); + return indices; +} diff --git a/Samples/HolographicSpatialStage/cpp/SpatialStageManager.h b/Samples/HolographicSpatialStage/cpp/SpatialStageManager.h new file mode 100644 index 0000000000..b8ca88d382 --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/SpatialStageManager.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Common\DeviceResources.h" +#include "Content\SceneController.h" + +namespace HolographicSpatialStage +{ + class SpatialStageManager + { + public: + SpatialStageManager(std::shared_ptr const& deviceResources, std::shared_ptr const& sceneController); + SpatialStageManager(const SpatialStageManager&) = delete; + SpatialStageManager(SpatialStageManager&&) = default; + ~SpatialStageManager(); + + Windows::Perception::Spatial::SpatialCoordinateSystem^ GetCoordinateSystemForCurrentStage(); + + private: + void OnCurrentChanged(Platform::Object^ /*o*/); + + std::vector CreateCircle(Windows::Foundation::Numerics::float3 center, float radius, int divisions, float radians); + std::vector TriangulatePoints(std::vector const& vertices); + + std::shared_ptr m_deviceResources; + std::shared_ptr m_sceneController; + + Windows::Foundation::EventRegistrationToken m_spatialStageChangedEventToken; + + std::shared_ptr m_stageBoundsShape; + std::shared_ptr m_stageVisibleAreaIndicatorShape; + + Windows::Perception::Spatial::SpatialCoordinateSystem^ m_currentCoordinateSystem; + Windows::Perception::Spatial::SpatialStageFrameOfReference^ m_currentStage; + Windows::Perception::Spatial::SpatialStationaryFrameOfReference^ m_stationaryFrameOfReference; + }; +} \ No newline at end of file diff --git a/Samples/HolographicSpatialStage/cpp/pch.cpp b/Samples/HolographicSpatialStage/cpp/pch.cpp new file mode 100644 index 0000000000..01484ff5aa --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/pch.cpp @@ -0,0 +1,6 @@ +// +// pch.cpp +// Include the standard header and generate the precompiled header. +// + +#include "pch.h" diff --git a/Samples/HolographicSpatialStage/cpp/pch.h b/Samples/HolographicSpatialStage/cpp/pch.h new file mode 100644 index 0000000000..283f07da9a --- /dev/null +++ b/Samples/HolographicSpatialStage/cpp/pch.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + diff --git a/Samples/HolographicTagAlong/cpp/HolographicTagAlong.sln b/Samples/HolographicTagAlong/cpp/HolographicTagAlong.sln index 9ecfb70303..2977ced601 100644 --- a/Samples/HolographicTagAlong/cpp/HolographicTagAlong.sln +++ b/Samples/HolographicTagAlong/cpp/HolographicTagAlong.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HolographicTagAlong", "HolographicTagAlong.vcxproj", "{D545BF65-B882-5785-89DC-ACF2182592EA}" EndProject diff --git a/Samples/HolographicVoiceInput/cpp/HolographicVoiceInput.sln b/Samples/HolographicVoiceInput/cpp/HolographicVoiceInput.sln index bff1e9cf4d..060db14940 100644 --- a/Samples/HolographicVoiceInput/cpp/HolographicVoiceInput.sln +++ b/Samples/HolographicVoiceInput/cpp/HolographicVoiceInput.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HolographicVoiceInput", "HolographicVoiceInput.vcxproj", "{CFD41A63-8FFA-57DB-B04F-5F89EE2AC7ED}" EndProject diff --git a/Samples/HomeGroup/cpp/HomeGroup.sln b/Samples/HomeGroup/cpp/HomeGroup.sln index dc0be70b57..a0ada68ffe 100644 --- a/Samples/HomeGroup/cpp/HomeGroup.sln +++ b/Samples/HomeGroup/cpp/HomeGroup.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HomeGroup", "HomeGroup.vcxproj", "{D3FA6269-F5BB-58EA-83B8-81DB89E50057}" EndProject diff --git a/Samples/HomeGroup/cs/HomeGroup.sln b/Samples/HomeGroup/cs/HomeGroup.sln index 7db295a442..c795638e19 100644 --- a/Samples/HomeGroup/cs/HomeGroup.sln +++ b/Samples/HomeGroup/cs/HomeGroup.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HomeGroup", "HomeGroup.csproj", "{3F628743-870A-5763-A428-5F224B9239B2}" EndProject diff --git a/Samples/HomeGroup/js/HomeGroup.sln b/Samples/HomeGroup/js/HomeGroup.sln index fbc5bae1a9..200816a68f 100644 --- a/Samples/HomeGroup/js/HomeGroup.sln +++ b/Samples/HomeGroup/js/HomeGroup.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "HomeGroup", "HomeGroup.jsproj", "{5EE2DDBB-B4C1-54A8-81D5-CC09E32DFDEA}" EndProject diff --git a/Samples/HtmlFormValidation/js/HtmlFormValidation.sln b/Samples/HtmlFormValidation/js/HtmlFormValidation.sln index de5fcac516..5638e78363 100644 --- a/Samples/HtmlFormValidation/js/HtmlFormValidation.sln +++ b/Samples/HtmlFormValidation/js/HtmlFormValidation.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "HtmlFormValidation", "HtmlFormValidation.jsproj", "{B53BB7A2-16EB-5320-948E-8C6006D69D68}" EndProject diff --git a/Samples/HttpClient/cpp/HttpClient.sln b/Samples/HttpClient/cpp/HttpClient.sln index add2cc2fb6..36f3971c66 100644 --- a/Samples/HttpClient/cpp/HttpClient.sln +++ b/Samples/HttpClient/cpp/HttpClient.sln @@ -1,11 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpClient", "HttpClient.vcxproj", "{4AB0D3B9-5AE2-5755-9D94-00EF178BC6D6}" + ProjectSection(ProjectDependencies) = postProject + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE} = {DC7DFD34-63DC-5B78-914B-4435A2A87EAE} + EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpFilters", "..\HttpFilters\HttpFilters.vcxproj", "{682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HttpFilters", "..\HttpFilters\HttpFilters.vcxproj", "{DC7DFD34-63DC-5B78-914B-4435A2A87EAE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -35,18 +38,18 @@ Global {4AB0D3B9-5AE2-5755-9D94-00EF178BC6D6}.Release|x86.ActiveCfg = Release|Win32 {4AB0D3B9-5AE2-5755-9D94-00EF178BC6D6}.Release|x86.Build.0 = Release|Win32 {4AB0D3B9-5AE2-5755-9D94-00EF178BC6D6}.Release|x86.Deploy.0 = Release|Win32 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Debug|ARM.ActiveCfg = Debug|ARM - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Debug|ARM.Build.0 = Debug|ARM - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Debug|x64.ActiveCfg = Debug|x64 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Debug|x64.Build.0 = Debug|x64 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Debug|x86.ActiveCfg = Debug|Win32 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Debug|x86.Build.0 = Debug|Win32 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Release|ARM.ActiveCfg = Release|ARM - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Release|ARM.Build.0 = Release|ARM - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Release|x64.ActiveCfg = Release|x64 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Release|x64.Build.0 = Release|x64 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Release|x86.ActiveCfg = Release|Win32 - {682DF16E-DEB3-5F7E-851E-F45DDAEBBC09}.Release|x86.Build.0 = Release|Win32 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Debug|ARM.ActiveCfg = Debug|ARM + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Debug|ARM.Build.0 = Debug|ARM + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Debug|x64.ActiveCfg = Debug|x64 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Debug|x64.Build.0 = Debug|x64 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Debug|x86.ActiveCfg = Debug|Win32 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Debug|x86.Build.0 = Debug|Win32 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Release|ARM.ActiveCfg = Release|ARM + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Release|ARM.Build.0 = Release|ARM + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Release|x64.ActiveCfg = Release|x64 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Release|x64.Build.0 = Release|x64 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Release|x86.ActiveCfg = Release|Win32 + {DC7DFD34-63DC-5B78-914B-4435A2A87EAE}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Samples/HttpClient/cs/HttpClient.sln b/Samples/HttpClient/cs/HttpClient.sln index 70d7d62629..3cf95180ac 100644 --- a/Samples/HttpClient/cs/HttpClient.sln +++ b/Samples/HttpClient/cs/HttpClient.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpClient", "HttpClient.csproj", "{291DE7E0-1E5C-5538-B41E-C2171A93F588}" EndProject diff --git a/Samples/Inclinometer/cpp/Inclinometer.sln b/Samples/Inclinometer/cpp/Inclinometer.sln index cebb84b9ff..334376c4b1 100644 --- a/Samples/Inclinometer/cpp/Inclinometer.sln +++ b/Samples/Inclinometer/cpp/Inclinometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Inclinometer", "Inclinometer.vcxproj", "{4FD94690-9CE5-5D99-8CBE-098ABB4E5A4A}" EndProject diff --git a/Samples/Inclinometer/cs/Inclinometer.sln b/Samples/Inclinometer/cs/Inclinometer.sln index bb36fe7d61..0fb4ac2d4c 100644 --- a/Samples/Inclinometer/cs/Inclinometer.sln +++ b/Samples/Inclinometer/cs/Inclinometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Inclinometer", "Inclinometer.csproj", "{7D741028-33EF-5F0A-9FD9-8A7EEA4D7178}" EndProject diff --git a/Samples/Inclinometer/js/Inclinometer.sln b/Samples/Inclinometer/js/Inclinometer.sln index 35dda01eee..27db7808fd 100644 --- a/Samples/Inclinometer/js/Inclinometer.sln +++ b/Samples/Inclinometer/js/Inclinometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Inclinometer", "Inclinometer.jsproj", "{AE30D41B-F418-520E-97CC-3FE5A5C4DBFE}" EndProject diff --git a/Samples/IndexedDB/js/IndexedDB.sln b/Samples/IndexedDB/js/IndexedDB.sln index f9705dcbfd..935f2bcf0d 100644 --- a/Samples/IndexedDB/js/IndexedDB.sln +++ b/Samples/IndexedDB/js/IndexedDB.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "IndexedDB", "IndexedDB.jsproj", "{55F761EF-E592-5723-A67B-37BCC80FD55D}" EndProject diff --git a/Samples/Ink/js/Ink.sln b/Samples/Ink/js/Ink.sln index 42d873dd62..30e95892a3 100644 --- a/Samples/Ink/js/Ink.sln +++ b/Samples/Ink/js/Ink.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Ink", "Ink.jsproj", "{69DA4B66-6FE2-5E58-B3AF-4058E2964F50}" EndProject diff --git a/Samples/InkAnalysis/cs/InkAnalysis.sln b/Samples/InkAnalysis/cs/InkAnalysis.sln index 4c3cc79e21..0a13bc0839 100644 --- a/Samples/InkAnalysis/cs/InkAnalysis.sln +++ b/Samples/InkAnalysis/cs/InkAnalysis.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InkAnalysis", "InkAnalysis.csproj", "{DF99970C-FA6A-57CA-9F94-42DDCA43DEFA}" EndProject diff --git a/Samples/IoT-GPIO/cpp/Gpio.sln b/Samples/IoT-GPIO/cpp/Gpio.sln index 59bc871d28..b2c3a05a0c 100644 --- a/Samples/IoT-GPIO/cpp/Gpio.sln +++ b/Samples/IoT-GPIO/cpp/Gpio.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Gpio", "Gpio.vcxproj", "{A2602819-9290-56CD-A95A-5AD8A5EF02A9}" EndProject diff --git a/Samples/IoT-GPIO/cs/Gpio.sln b/Samples/IoT-GPIO/cs/Gpio.sln index b18a4ae107..0e14de9da9 100644 --- a/Samples/IoT-GPIO/cs/Gpio.sln +++ b/Samples/IoT-GPIO/cs/Gpio.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gpio", "Gpio.csproj", "{E465792C-14DB-56D6-AB52-605D98CF429F}" EndProject diff --git a/Samples/IoT-GPIO/js/Gpio.sln b/Samples/IoT-GPIO/js/Gpio.sln index d2d84d1d36..c9cc396a09 100644 --- a/Samples/IoT-GPIO/js/Gpio.sln +++ b/Samples/IoT-GPIO/js/Gpio.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Gpio", "Gpio.jsproj", "{BA10FA82-2732-5E22-B8A1-A9E2CC793B4A}" EndProject diff --git a/Samples/IoT-I2C/cpp/I2C.sln b/Samples/IoT-I2C/cpp/I2C.sln index 0baa9039b8..807d03c5c0 100644 --- a/Samples/IoT-I2C/cpp/I2C.sln +++ b/Samples/IoT-I2C/cpp/I2C.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "I2C", "I2C.vcxproj", "{95CF1DEF-37FB-5490-B526-B2530735DC64}" EndProject diff --git a/Samples/IoT-I2C/cs/I2C.sln b/Samples/IoT-I2C/cs/I2C.sln index 193620f433..bf698fbc4f 100644 --- a/Samples/IoT-I2C/cs/I2C.sln +++ b/Samples/IoT-I2C/cs/I2C.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "I2C", "I2C.csproj", "{6EB3429E-8903-5E3E-B0FF-92689D816769}" EndProject diff --git a/Samples/IoT-I2C/js/I2C.sln b/Samples/IoT-I2C/js/I2C.sln index 1eb83d70e2..4b6bc224b5 100644 --- a/Samples/IoT-I2C/js/I2C.sln +++ b/Samples/IoT-I2C/js/I2C.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "I2C", "I2C.jsproj", "{43FDFDD1-7E8D-5984-841D-F532359FF733}" EndProject diff --git a/Samples/IoT-SPI/cpp/SPI.sln b/Samples/IoT-SPI/cpp/SPI.sln index b7bbc0b54e..b27a27eaf2 100644 --- a/Samples/IoT-SPI/cpp/SPI.sln +++ b/Samples/IoT-SPI/cpp/SPI.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPI", "SPI.vcxproj", "{C9975317-A7B3-5110-845A-0E96575CE4E9}" EndProject diff --git a/Samples/IoT-SPI/cs/SPI.sln b/Samples/IoT-SPI/cs/SPI.sln index 4d5438a631..d438836db8 100644 --- a/Samples/IoT-SPI/cs/SPI.sln +++ b/Samples/IoT-SPI/cs/SPI.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPI", "SPI.csproj", "{BCDC4A2A-B429-5E41-AA41-62C3C9141701}" EndProject diff --git a/Samples/IoT-SPI/js/SPI.sln b/Samples/IoT-SPI/js/SPI.sln index 513760613d..3125df9459 100644 --- a/Samples/IoT-SPI/js/SPI.sln +++ b/Samples/IoT-SPI/js/SPI.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "SPI", "SPI.jsproj", "{D80FE894-2C47-5E67-80E3-C577D35A1D7A}" EndProject diff --git a/Samples/JapanesePhoneticAnalysis/cpp/JapanesePhoneticAnalysis.sln b/Samples/JapanesePhoneticAnalysis/cpp/JapanesePhoneticAnalysis.sln index a155142229..0f91266bac 100644 --- a/Samples/JapanesePhoneticAnalysis/cpp/JapanesePhoneticAnalysis.sln +++ b/Samples/JapanesePhoneticAnalysis/cpp/JapanesePhoneticAnalysis.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JapanesePhoneticAnalysis", "JapanesePhoneticAnalysis.vcxproj", "{31A2CBB6-D33B-5559-B386-6642EB3F9E14}" EndProject diff --git a/Samples/JapanesePhoneticAnalysis/cs/JapanesePhoneticAnalysis.sln b/Samples/JapanesePhoneticAnalysis/cs/JapanesePhoneticAnalysis.sln index a1e8fd7bb5..90e04cbb8b 100644 --- a/Samples/JapanesePhoneticAnalysis/cs/JapanesePhoneticAnalysis.sln +++ b/Samples/JapanesePhoneticAnalysis/cs/JapanesePhoneticAnalysis.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JapanesePhoneticAnalysis", "JapanesePhoneticAnalysis.csproj", "{FDFC4DA0-DAB7-59BF-A4D8-D77118874C9A}" EndProject diff --git a/Samples/JapanesePhoneticAnalysis/js/JapanesePhoneticAnalysis.sln b/Samples/JapanesePhoneticAnalysis/js/JapanesePhoneticAnalysis.sln index 0b36b20468..0155c52181 100644 --- a/Samples/JapanesePhoneticAnalysis/js/JapanesePhoneticAnalysis.sln +++ b/Samples/JapanesePhoneticAnalysis/js/JapanesePhoneticAnalysis.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "JapanesePhoneticAnalysis", "JapanesePhoneticAnalysis.jsproj", "{5F192767-953A-50BC-A962-3E23E1926A05}" EndProject diff --git a/Samples/Json/cs/Json.sln b/Samples/Json/cs/Json.sln index 52008f7480..960e2fbe77 100644 --- a/Samples/Json/cs/Json.sln +++ b/Samples/Json/cs/Json.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Json", "Json.csproj", "{D8CB8BF0-E43D-52D7-98F4-61315DE95032}" EndProject diff --git a/Samples/JumpList/cpp/JumpList.sln b/Samples/JumpList/cpp/JumpList.sln index 9f622dbd26..8c013cc718 100644 --- a/Samples/JumpList/cpp/JumpList.sln +++ b/Samples/JumpList/cpp/JumpList.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JumpList", "JumpList.vcxproj", "{C9313C33-C23B-5160-8E2A-19AECECA5E50}" EndProject diff --git a/Samples/JumpList/cs/JumpList.sln b/Samples/JumpList/cs/JumpList.sln index 9788d9c06b..8a265a5637 100644 --- a/Samples/JumpList/cs/JumpList.sln +++ b/Samples/JumpList/cs/JumpList.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpList", "JumpList.csproj", "{3AA8454C-C484-5139-A42D-5700A9A89D06}" EndProject diff --git a/Samples/JumpList/js/JumpList.sln b/Samples/JumpList/js/JumpList.sln index 53f5d13e0b..592e3c1db0 100644 --- a/Samples/JumpList/js/JumpList.sln +++ b/Samples/JumpList/js/JumpList.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "JumpList", "JumpList.jsproj", "{1293A54B-71E1-509B-AC69-96543209FED2}" EndProject diff --git a/Samples/KeyCredentialManager/cpp/KeyCredentialManager.sln b/Samples/KeyCredentialManager/cpp/KeyCredentialManager.sln index 406384b536..d93cd4952e 100644 --- a/Samples/KeyCredentialManager/cpp/KeyCredentialManager.sln +++ b/Samples/KeyCredentialManager/cpp/KeyCredentialManager.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyCredentialManager", "KeyCredentialManager.vcxproj", "{DE1E59AD-B6C8-5EDA-A207-7D904C15C5CC}" EndProject diff --git a/Samples/KeyCredentialManager/cs/KeyCredentialManager.sln b/Samples/KeyCredentialManager/cs/KeyCredentialManager.sln index 98b9870ea9..058115c18b 100644 --- a/Samples/KeyCredentialManager/cs/KeyCredentialManager.sln +++ b/Samples/KeyCredentialManager/cs/KeyCredentialManager.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22822.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyCredentialManager", "KeyCredentialManager.csproj", "{39E73422-AE91-5E6B-88F0-ABEF0D65F67F}" EndProject diff --git a/Samples/LampDevice/cpp/LampDevice.sln b/Samples/LampDevice/cpp/LampDevice.sln index 001ddf63a4..f147ebe3d8 100644 --- a/Samples/LampDevice/cpp/LampDevice.sln +++ b/Samples/LampDevice/cpp/LampDevice.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LampDevice", "LampDevice.vcxproj", "{8E063DBE-EEC3-5D2A-BF28-D1A57D83012A}" EndProject diff --git a/Samples/LampDevice/cs/LampDevice.sln b/Samples/LampDevice/cs/LampDevice.sln index 1aea56723c..485e71f9c5 100644 --- a/Samples/LampDevice/cs/LampDevice.sln +++ b/Samples/LampDevice/cs/LampDevice.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22529.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LampDevice", "LampDevice.csproj", "{C9501E38-7594-5F9B-9463-4DEA46FBE878}" EndProject diff --git a/Samples/LampDevice/js/LampDevice.sln b/Samples/LampDevice/js/LampDevice.sln index 0fbaf8b363..0907adc4e7 100644 --- a/Samples/LampDevice/js/LampDevice.sln +++ b/Samples/LampDevice/js/LampDevice.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22821.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "LampDevice", "LampDevice.jsproj", "{B3B09A08-B49F-5B03-93CC-FE5425FEDC97}" EndProject diff --git a/Samples/LanguageFont/cpp/LanguageFont.sln b/Samples/LanguageFont/cpp/LanguageFont.sln index 9e58e9cd46..397e357f06 100644 --- a/Samples/LanguageFont/cpp/LanguageFont.sln +++ b/Samples/LanguageFont/cpp/LanguageFont.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LanguageFont", "LanguageFont.vcxproj", "{29216955-75F1-5AD0-BC5E-0D6D2F0D7228}" EndProject diff --git a/Samples/LanguageFont/cs/LanguageFont.sln b/Samples/LanguageFont/cs/LanguageFont.sln index 295ea40997..d244c37f96 100644 --- a/Samples/LanguageFont/cs/LanguageFont.sln +++ b/Samples/LanguageFont/cs/LanguageFont.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LanguageFont", "LanguageFont.csproj", "{94AD3010-0264-5612-8990-72CA1A837219}" EndProject diff --git a/Samples/LanguageFont/js/LanguageFont.sln b/Samples/LanguageFont/js/LanguageFont.sln index 2deaa42607..2e2deabc5e 100644 --- a/Samples/LanguageFont/js/LanguageFont.sln +++ b/Samples/LanguageFont/js/LanguageFont.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "LanguageFont", "LanguageFont.jsproj", "{CBB6E66F-D16B-547C-8ACE-64859F656F37}" EndProject diff --git a/Samples/LibraryManagement/cpp/LibraryManagement.sln b/Samples/LibraryManagement/cpp/LibraryManagement.sln index fea2221af4..560fa7ddc0 100644 --- a/Samples/LibraryManagement/cpp/LibraryManagement.sln +++ b/Samples/LibraryManagement/cpp/LibraryManagement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibraryManagement", "LibraryManagement.vcxproj", "{A269AD4D-7F99-5DDF-9B18-E6EB7AE8E9F7}" EndProject diff --git a/Samples/LibraryManagement/cs/LibraryManagement.sln b/Samples/LibraryManagement/cs/LibraryManagement.sln index 3519ce41f9..dead1ebdc4 100644 --- a/Samples/LibraryManagement/cs/LibraryManagement.sln +++ b/Samples/LibraryManagement/cs/LibraryManagement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibraryManagement", "LibraryManagement.csproj", "{6B987721-4BD6-5015-B641-A237757D12B1}" EndProject diff --git a/Samples/LibraryManagement/js/LibraryManagement.sln b/Samples/LibraryManagement/js/LibraryManagement.sln index 492165915c..d585cfa60a 100644 --- a/Samples/LibraryManagement/js/LibraryManagement.sln +++ b/Samples/LibraryManagement/js/LibraryManagement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "LibraryManagement", "LibraryManagement.jsproj", "{CBBAB6E7-3723-50AC-883C-6A0B14C73D29}" EndProject diff --git a/Samples/LightSensor/cpp/LightSensor.sln b/Samples/LightSensor/cpp/LightSensor.sln index 940edfd5c1..080c48bb30 100644 --- a/Samples/LightSensor/cpp/LightSensor.sln +++ b/Samples/LightSensor/cpp/LightSensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LightSensor", "LightSensor.vcxproj", "{917B9F7A-0096-5512-96D1-BEC4E7D9297C}" EndProject diff --git a/Samples/LightSensor/cs/LightSensor.sln b/Samples/LightSensor/cs/LightSensor.sln index f80a87c57f..2e406d79b0 100644 --- a/Samples/LightSensor/cs/LightSensor.sln +++ b/Samples/LightSensor/cs/LightSensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LightSensor", "LightSensor.csproj", "{5B4B7177-8DFE-5F88-8EC9-93DFC50CA70B}" EndProject diff --git a/Samples/LightSensor/js/LightSensor.sln b/Samples/LightSensor/js/LightSensor.sln index 0a77445eb0..acadb21987 100644 --- a/Samples/LightSensor/js/LightSensor.sln +++ b/Samples/LightSensor/js/LightSensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "LightSensor", "LightSensor.jsproj", "{B88C652A-2807-5BBA-9956-E512C5D3DC3C}" EndProject diff --git a/Samples/LineDisplay/README.md b/Samples/LineDisplay/README.md index 565b44f21b..b5c8f329d2 100644 --- a/Samples/LineDisplay/README.md +++ b/Samples/LineDisplay/README.md @@ -1,6 +1,6 @@ # Line display sample diff --git a/Samples/LinguisticServices/cpp/LinguisticServices.sln b/Samples/LinguisticServices/cpp/LinguisticServices.sln index d8fcefe21e..651444aab5 100644 --- a/Samples/LinguisticServices/cpp/LinguisticServices.sln +++ b/Samples/LinguisticServices/cpp/LinguisticServices.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinguisticServices", "LinguisticServices.vcxproj", "{4BD59264-56A8-5BFF-949F-A85516B3D3E1}" EndProject diff --git a/Samples/LiveDash/cs/LiveDash.sln b/Samples/LiveDash/cs/LiveDash.sln index bff7756057..be0e4170a5 100644 --- a/Samples/LiveDash/cs/LiveDash.sln +++ b/Samples/LiveDash/cs/LiveDash.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveDashApp", "LiveDashApp\LiveDashApp.csproj", "{9B84853B-A984-5A1E-90CC-4F786FBCC870}" EndProject diff --git a/Samples/LockScreenApps/cs/LockScreenApps.sln b/Samples/LockScreenApps/cs/LockScreenApps.sln index 9a60341e64..82ee9a8918 100644 --- a/Samples/LockScreenApps/cs/LockScreenApps.sln +++ b/Samples/LockScreenApps/cs/LockScreenApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LockScreenApps", "LockScreenApps.csproj", "{4A1DE537-20B0-5EB4-AD22-F4EFA23EC49A}" EndProject diff --git a/Samples/Logging/cpp/Logging.sln b/Samples/Logging/cpp/Logging.sln index ac0ff6c6ad..e24ee43080 100644 --- a/Samples/Logging/cpp/Logging.sln +++ b/Samples/Logging/cpp/Logging.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Logging", "Logging.vcxproj", "{57C6476D-5D71-5E0B-9618-C674F48B5316}" EndProject diff --git a/Samples/Logging/cs/Logging.sln b/Samples/Logging/cs/Logging.sln index 47a8aae6c2..9df6aec154 100644 --- a/Samples/Logging/cs/Logging.sln +++ b/Samples/Logging/cs/Logging.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logging", "Logging.csproj", "{4DB51D8A-D9A3-5133-840F-8808D43B8110}" EndProject diff --git a/Samples/Logging/js/Logging.sln b/Samples/Logging/js/Logging.sln index 0bc150e7d7..67fbd24171 100644 --- a/Samples/Logging/js/Logging.sln +++ b/Samples/Logging/js/Logging.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Logging", "Logging.jsproj", "{14A6FCC0-921C-5384-A874-383641311190}" EndProject diff --git a/Samples/LowLatencyInput/cpp/LowLatencyInput.sln b/Samples/LowLatencyInput/cpp/LowLatencyInput.sln index 3cee104505..ff9c9ac8d3 100644 --- a/Samples/LowLatencyInput/cpp/LowLatencyInput.sln +++ b/Samples/LowLatencyInput/cpp/LowLatencyInput.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23023.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LowLatencyInput", "LowLatencyInput.vcxproj", "{022490CC-2F8A-510B-88F9-3F01DAACE3C8}" EndProject diff --git a/Samples/MIDI/cs/MIDI.sln b/Samples/MIDI/cs/MIDI.sln index 0c430bca84..0a385ca3b3 100644 --- a/Samples/MIDI/cs/MIDI.sln +++ b/Samples/MIDI/cs/MIDI.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22822.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MIDI", "MIDI.csproj", "{90B742E6-4EA7-500A-9618-4FB549B0B5FB}" EndProject diff --git a/Samples/MagneticStripeReader/cpp/MagneticStripeReader.sln b/Samples/MagneticStripeReader/cpp/MagneticStripeReader.sln index 2e5450b39e..10e1288833 100644 --- a/Samples/MagneticStripeReader/cpp/MagneticStripeReader.sln +++ b/Samples/MagneticStripeReader/cpp/MagneticStripeReader.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MagneticStripeReader", "MagneticStripeReader.vcxproj", "{C624FB3E-9791-5728-B955-2F607A23B9B6}" EndProject diff --git a/Samples/MagneticStripeReader/cs/MagneticStripeReader.sln b/Samples/MagneticStripeReader/cs/MagneticStripeReader.sln index f3ea20ca4f..cdaad5735d 100644 --- a/Samples/MagneticStripeReader/cs/MagneticStripeReader.sln +++ b/Samples/MagneticStripeReader/cs/MagneticStripeReader.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagneticStripeReader", "MagneticStripeReader.csproj", "{20251B5B-2AC3-5844-A6B6-CA1F69561E04}" EndProject diff --git a/Samples/MagneticStripeReader/js/MagneticStripeReader.sln b/Samples/MagneticStripeReader/js/MagneticStripeReader.sln index 1651950dad..4718749f7c 100644 --- a/Samples/MagneticStripeReader/js/MagneticStripeReader.sln +++ b/Samples/MagneticStripeReader/js/MagneticStripeReader.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "MagneticStripeReader", "MagneticStripeReader.jsproj", "{67DF5395-DCBB-50A2-B628-5F24A7BFF8D7}" EndProject diff --git a/Samples/MapControl/cpp/MapControl.sln b/Samples/MapControl/cpp/MapControl.sln index 5651ec5027..0ebce79ba9 100644 --- a/Samples/MapControl/cpp/MapControl.sln +++ b/Samples/MapControl/cpp/MapControl.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MapControl", "MapControl.vcxproj", "{C81A4FF6-3CF5-5404-B714-AE584959BF43}" EndProject diff --git a/Samples/MapControl/cs/MapControl.sln b/Samples/MapControl/cs/MapControl.sln index 79e8449d3b..a3d829ce9e 100644 --- a/Samples/MapControl/cs/MapControl.sln +++ b/Samples/MapControl/cs/MapControl.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl", "MapControl.csproj", "{804C73B9-0248-5337-9289-0CEFFA987B6E}" EndProject diff --git a/Samples/MediaEditing/cpp/MediaEditing.sln b/Samples/MediaEditing/cpp/MediaEditing.sln index e4cfb27871..3bdf4d1f11 100644 --- a/Samples/MediaEditing/cpp/MediaEditing.sln +++ b/Samples/MediaEditing/cpp/MediaEditing.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MediaEditing", "MediaEditing.vcxproj", "{2816507F-2121-57B9-9CCE-ED48E002EF8C}" EndProject diff --git a/Samples/MediaEditing/cs/MediaEditing.sln b/Samples/MediaEditing/cs/MediaEditing.sln index d8de38ff1e..069b914591 100644 --- a/Samples/MediaEditing/cs/MediaEditing.sln +++ b/Samples/MediaEditing/cs/MediaEditing.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaEditing", "MediaEditing.csproj", "{5EC07BF3-F09D-56DA-BC86-65F864801299}" EndProject diff --git a/Samples/MediaEditing/js/MediaEditing.sln b/Samples/MediaEditing/js/MediaEditing.sln index 2262d9e19f..6aa9e0972f 100644 --- a/Samples/MediaEditing/js/MediaEditing.sln +++ b/Samples/MediaEditing/js/MediaEditing.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "MediaEditing", "MediaEditing.jsproj", "{3026355C-9226-5E43-83AC-1457788FAC43}" EndProject diff --git a/Samples/MediaImport/cs/Import.sln b/Samples/MediaImport/cs/Import.sln index f5629ada4b..558c935742 100644 --- a/Samples/MediaImport/cs/Import.sln +++ b/Samples/MediaImport/cs/Import.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23102.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Import", "Import.csproj", "{430BF2F9-BB86-5CC2-8B51-726F28A0BA35}" EndProject diff --git a/Samples/MediaTranscoding/cpp/MediaTranscoding.sln b/Samples/MediaTranscoding/cpp/MediaTranscoding.sln index 46fc7ccf18..f9a2a3d75f 100644 --- a/Samples/MediaTranscoding/cpp/MediaTranscoding.sln +++ b/Samples/MediaTranscoding/cpp/MediaTranscoding.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MediaTranscoding", "MediaTranscoding.vcxproj", "{B577097F-3D98-53E1-9A22-5AD7B91EC5FD}" EndProject diff --git a/Samples/MediaTranscoding/cs/MediaTranscoding.sln b/Samples/MediaTranscoding/cs/MediaTranscoding.sln index 2a36b7928a..234d91108f 100644 --- a/Samples/MediaTranscoding/cs/MediaTranscoding.sln +++ b/Samples/MediaTranscoding/cs/MediaTranscoding.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaTranscoding", "MediaTranscoding.csproj", "{56F59854-DD2C-5B1C-9627-123866B0E7E0}" EndProject diff --git a/Samples/MediaTranscoding/js/MediaTranscoding.sln b/Samples/MediaTranscoding/js/MediaTranscoding.sln index 23bd7456db..a2e2363dcd 100644 --- a/Samples/MediaTranscoding/js/MediaTranscoding.sln +++ b/Samples/MediaTranscoding/js/MediaTranscoding.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "MediaTranscoding", "MediaTranscoding.jsproj", "{D969DD3C-5EF1-5259-A56E-FBE53262A22A}" EndProject diff --git a/Samples/MessageDialog/cpp/MessageDialogSample.sln b/Samples/MessageDialog/cpp/MessageDialogSample.sln index c8c63615d7..117d8997e7 100644 --- a/Samples/MessageDialog/cpp/MessageDialogSample.sln +++ b/Samples/MessageDialog/cpp/MessageDialogSample.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessageDialogSample", "MessageDialogSample.vcxproj", "{86CB50E3-6A2D-56F4-9357-3CECC9722054}" EndProject diff --git a/Samples/MessageDialog/cs/MessageDialogSample.sln b/Samples/MessageDialog/cs/MessageDialogSample.sln index b041733110..4416798f3f 100644 --- a/Samples/MessageDialog/cs/MessageDialogSample.sln +++ b/Samples/MessageDialog/cs/MessageDialogSample.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessageDialogSample", "MessageDialogSample.csproj", "{6686D35B-5414-52ED-9CF6-5163D05FC306}" EndProject diff --git a/Samples/MessageDialog/js/MessageDialogSample.sln b/Samples/MessageDialog/js/MessageDialogSample.sln index 244061a017..df7ae064b2 100644 --- a/Samples/MessageDialog/js/MessageDialogSample.sln +++ b/Samples/MessageDialog/js/MessageDialogSample.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "MessageDialogSample", "MessageDialogSample.jsproj", "{AE42A124-73F0-5C15-8998-F8A3840E6FF1}" EndProject diff --git a/Samples/MicrosoftPassport/Server/MicrosoftPassport.Server.sln b/Samples/MicrosoftPassport/Server/MicrosoftPassport.Server.sln index 16d2a1599a..07dbf2e391 100644 --- a/Samples/MicrosoftPassport/Server/MicrosoftPassport.Server.sln +++ b/Samples/MicrosoftPassport/Server/MicrosoftPassport.Server.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicrosoftPassport.Server", "MicrosoftPassport.Server.csproj", "{71B7CC07-E79C-5A67-BF2E-06E160E04AB1}" EndProject diff --git a/Samples/MicrosoftPassport/cs/MicrosoftPassport.sln b/Samples/MicrosoftPassport/cs/MicrosoftPassport.sln index 0f1e32e53f..095975c360 100644 --- a/Samples/MicrosoftPassport/cs/MicrosoftPassport.sln +++ b/Samples/MicrosoftPassport/cs/MicrosoftPassport.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicrosoftPassport", "MicrosoftPassport.csproj", "{44616963-834F-5296-BFA0-45685F6951E0}" EndProject diff --git a/Samples/MobileBroadband/cs/MobileBroadband.sln b/Samples/MobileBroadband/cs/MobileBroadband.sln index 893fd1db4a..b1faf51d06 100644 --- a/Samples/MobileBroadband/cs/MobileBroadband.sln +++ b/Samples/MobileBroadband/cs/MobileBroadband.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22822.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileBroadband", "MobileBroadband.csproj", "{F196E4A3-F9FE-5A5B-A6D1-233A7823FC6F}" EndProject diff --git a/Samples/MsBlobBuilder/js/MsBlobBuilder.sln b/Samples/MsBlobBuilder/js/MsBlobBuilder.sln index a3e5501894..27d9466ec4 100644 --- a/Samples/MsBlobBuilder/js/MsBlobBuilder.sln +++ b/Samples/MsBlobBuilder/js/MsBlobBuilder.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "MsBlobBuilder", "MsBlobBuilder.jsproj", "{5E3A1554-50DE-5E30-986F-661C4BF1DFF7}" EndProject diff --git a/Samples/MultipleViews/cs/MultipleViews.sln b/Samples/MultipleViews/cs/MultipleViews.sln index 243095afba..95243e7732 100644 --- a/Samples/MultipleViews/cs/MultipleViews.sln +++ b/Samples/MultipleViews/cs/MultipleViews.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultipleViews", "MultipleViews.csproj", "{115142A9-488C-5A45-9A24-413B7CE8A754}" EndProject diff --git a/Samples/Nfc/Nfc.sln b/Samples/Nfc/Nfc.sln index 39428026a3..aa32bcab02 100644 --- a/Samples/Nfc/Nfc.sln +++ b/Samples/Nfc/Nfc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22808.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nfc", "Nfc\Nfc.csproj", "{268889BC-42C4-5D16-8DDE-5EB2CD4C9AF6}" ProjectSection(ProjectDependencies) = postProject diff --git a/Samples/NfcProvisioner/cs/NfcProvisioner.sln b/Samples/NfcProvisioner/cs/NfcProvisioner.sln index ea1ab6a314..65367ecec1 100644 --- a/Samples/NfcProvisioner/cs/NfcProvisioner.sln +++ b/Samples/NfcProvisioner/cs/NfcProvisioner.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22821.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NfcProvisioner", "NfcProvisioner.csproj", "{C41AAF2F-5BC0-58F4-A5A4-391FF0BED521}" EndProject diff --git a/Samples/Notifications/cs/Notifications.sln b/Samples/Notifications/cs/Notifications.sln index 7b744af6aa..12949ad45b 100644 --- a/Samples/Notifications/cs/Notifications.sln +++ b/Samples/Notifications/cs/Notifications.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Notifications", "Notifications\Notifications.csproj", "{A716433F-9652-5713-A516-40BA3EC47E47}" EndProject diff --git a/Samples/Notifications/js/Notifications.sln b/Samples/Notifications/js/Notifications.sln index 4c194ae7f5..3233f2ad4a 100644 --- a/Samples/Notifications/js/Notifications.sln +++ b/Samples/Notifications/js/Notifications.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Notifications", "Notifications\Notifications.jsproj", "{A27C42A8-6BE1-5E9B-BF82-42FFA43EF4E6}" EndProject diff --git a/Samples/NumberFormatting/cpp/NumberFormatting.sln b/Samples/NumberFormatting/cpp/NumberFormatting.sln index 84b948f9cb..fe373325a5 100644 --- a/Samples/NumberFormatting/cpp/NumberFormatting.sln +++ b/Samples/NumberFormatting/cpp/NumberFormatting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NumberFormatting", "NumberFormatting.vcxproj", "{D10012DD-1F9B-5993-BF21-61D972A697A8}" EndProject diff --git a/Samples/NumberFormatting/cs/NumberFormatting.sln b/Samples/NumberFormatting/cs/NumberFormatting.sln index 5906eff4c8..189d91ba7e 100644 --- a/Samples/NumberFormatting/cs/NumberFormatting.sln +++ b/Samples/NumberFormatting/cs/NumberFormatting.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NumberFormatting", "NumberFormatting.csproj", "{0C5A650F-157E-57E3-9CCC-3B444F440954}" EndProject diff --git a/Samples/NumberFormatting/js/NumberFormattingSample.sln b/Samples/NumberFormatting/js/NumberFormattingSample.sln index 1e34d9958b..1ca095316b 100644 --- a/Samples/NumberFormatting/js/NumberFormattingSample.sln +++ b/Samples/NumberFormatting/js/NumberFormattingSample.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "NumberFormattingSample", "NumberFormattingSample.jsproj", "{5DA637F0-39A4-571A-A68E-9850849D6A8D}" EndProject diff --git a/Samples/OCR/cpp/OCR.sln b/Samples/OCR/cpp/OCR.sln index 41fb694de3..108ee9b17e 100644 --- a/Samples/OCR/cpp/OCR.sln +++ b/Samples/OCR/cpp/OCR.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCR", "OCR.vcxproj", "{4A556C24-4202-520B-9998-25D7C33C5D77}" EndProject diff --git a/Samples/OCR/cs/OCR.sln b/Samples/OCR/cs/OCR.sln index 207842d522..5e8bb21cae 100644 --- a/Samples/OCR/cs/OCR.sln +++ b/Samples/OCR/cs/OCR.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OCR", "OCR.csproj", "{0712B45A-664E-5DFA-A805-45E396207962}" EndProject diff --git a/Samples/OCR/js/OCR.sln b/Samples/OCR/js/OCR.sln index 4aa8a191b0..b9323440aa 100644 --- a/Samples/OCR/js/OCR.sln +++ b/Samples/OCR/js/OCR.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "OCR", "OCR.jsproj", "{D5066730-00DF-5217-8994-418F438060D1}" EndProject diff --git a/Samples/OrientationSensor/cpp/OrientationSensor.sln b/Samples/OrientationSensor/cpp/OrientationSensor.sln index e9e08c25e3..79f7e97cfa 100644 --- a/Samples/OrientationSensor/cpp/OrientationSensor.sln +++ b/Samples/OrientationSensor/cpp/OrientationSensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OrientationSensor", "OrientationSensor.vcxproj", "{06E8F30A-928F-5A4F-99F3-ED134EF1E022}" EndProject diff --git a/Samples/OrientationSensor/cs/OrientationSensor.sln b/Samples/OrientationSensor/cs/OrientationSensor.sln index bd860a3978..2ac25de7b7 100644 --- a/Samples/OrientationSensor/cs/OrientationSensor.sln +++ b/Samples/OrientationSensor/cs/OrientationSensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrientationSensor", "OrientationSensor.csproj", "{592374E6-39A3-5DE3-9DCB-EFFAA92F0A61}" EndProject diff --git a/Samples/OrientationSensor/js/OrientationSensor.sln b/Samples/OrientationSensor/js/OrientationSensor.sln index bc5db13b40..360fd00be4 100644 --- a/Samples/OrientationSensor/js/OrientationSensor.sln +++ b/Samples/OrientationSensor/js/OrientationSensor.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "OrientationSensor", "OrientationSensor.jsproj", "{1F7DB676-E913-5281-8517-34AB9B3DCCA9}" EndProject diff --git a/Samples/Package/cpp/PackageSample.sln b/Samples/Package/cpp/PackageSample.sln index 9f2f9d0d54..513c71fc60 100644 --- a/Samples/Package/cpp/PackageSample.sln +++ b/Samples/Package/cpp/PackageSample.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageSample", "PackageSample.vcxproj", "{3CCEB005-8A90-5038-A276-A8934777BF99}" EndProject diff --git a/Samples/Package/cs/PackageSample.sln b/Samples/Package/cs/PackageSample.sln index a3c77fbb31..f68f0e5b01 100644 --- a/Samples/Package/cs/PackageSample.sln +++ b/Samples/Package/cs/PackageSample.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PackageSample", "PackageSample.csproj", "{76D0D202-5937-51B1-BC4A-EFC789FB5391}" EndProject diff --git a/Samples/Package/js/PackageSample.sln b/Samples/Package/js/PackageSample.sln index a08769840d..4330978ab4 100644 --- a/Samples/Package/js/PackageSample.sln +++ b/Samples/Package/js/PackageSample.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "PackageSample", "PackageSample.jsproj", "{91E83590-D2F4-5170-951B-25F8D4F08363}" EndProject diff --git a/Samples/PackagedContent/js/PackagedContent.sln b/Samples/PackagedContent/js/PackagedContent.sln index f81f7cbb9e..c3fb8565c2 100644 --- a/Samples/PackagedContent/js/PackagedContent.sln +++ b/Samples/PackagedContent/js/PackagedContent.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "PackagedContent", "PackagedContent.jsproj", "{33440A19-8404-5EB0-94EB-C004BB253572}" EndProject diff --git a/Samples/PasswordVault/cpp/PasswordVault.sln b/Samples/PasswordVault/cpp/PasswordVault.sln index d3b6a54716..65205a6461 100644 --- a/Samples/PasswordVault/cpp/PasswordVault.sln +++ b/Samples/PasswordVault/cpp/PasswordVault.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PasswordVault", "PasswordVault.vcxproj", "{D6A0503E-2053-50BA-9D6C-84549AAA7BC2}" EndProject diff --git a/Samples/PasswordVault/cs/PasswordVault.sln b/Samples/PasswordVault/cs/PasswordVault.sln index 2fac027148..58e894e022 100644 --- a/Samples/PasswordVault/cs/PasswordVault.sln +++ b/Samples/PasswordVault/cs/PasswordVault.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PasswordVault", "PasswordVault.csproj", "{49B24274-6F96-5A3E-AC23-99DD28A27A53}" EndProject diff --git a/Samples/PasswordVault/js/PasswordVault.sln b/Samples/PasswordVault/js/PasswordVault.sln index 222212b1ac..194a848d2a 100644 --- a/Samples/PasswordVault/js/PasswordVault.sln +++ b/Samples/PasswordVault/js/PasswordVault.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "PasswordVault", "PasswordVault.jsproj", "{74F319CB-6BA9-555F-902F-F8AA3D148AC6}" EndProject diff --git a/Samples/PdfDocument/cpp/PdfDocument.sln b/Samples/PdfDocument/cpp/PdfDocument.sln index 499b7dd884..e71a8224a2 100644 --- a/Samples/PdfDocument/cpp/PdfDocument.sln +++ b/Samples/PdfDocument/cpp/PdfDocument.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PdfDocument", "PdfDocument.vcxproj", "{FD56EB1A-C787-537B-BC50-C5F0EB9F4859}" EndProject diff --git a/Samples/PdfDocument/cs/PdfDocument.sln b/Samples/PdfDocument/cs/PdfDocument.sln index 7b30153280..55ceb8fa9a 100644 --- a/Samples/PdfDocument/cs/PdfDocument.sln +++ b/Samples/PdfDocument/cs/PdfDocument.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdfDocument", "PdfDocument.csproj", "{EAECE865-E171-5DEF-B7C1-3AF0D6DADF0E}" EndProject diff --git a/Samples/PdfDocument/js/PdfDocument.sln b/Samples/PdfDocument/js/PdfDocument.sln index ddcd9864e9..febcc381e1 100644 --- a/Samples/PdfDocument/js/PdfDocument.sln +++ b/Samples/PdfDocument/js/PdfDocument.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "PdfDocument", "PdfDocument.jsproj", "{84B711EA-2E9A-5696-A3B0-3BA6403B8203}" EndProject diff --git a/Samples/Pedometer/cpp/Pedometer.sln b/Samples/Pedometer/cpp/Pedometer.sln index 73bea98146..652b562012 100644 --- a/Samples/Pedometer/cpp/Pedometer.sln +++ b/Samples/Pedometer/cpp/Pedometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pedometer", "Pedometer.vcxproj", "{64996060-EB91-55A5-8B80-F85ED7A48415}" EndProject diff --git a/Samples/Pedometer/cs/Pedometer.sln b/Samples/Pedometer/cs/Pedometer.sln index 807d9c9b15..43d13cbe81 100644 --- a/Samples/Pedometer/cs/Pedometer.sln +++ b/Samples/Pedometer/cs/Pedometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pedometer", "Pedometer.csproj", "{0541B353-300E-5558-9447-97E2C1A71B43}" EndProject diff --git a/Samples/Pedometer/js/Pedometer.sln b/Samples/Pedometer/js/Pedometer.sln index 0d5e1efcf2..ed33ea3340 100644 --- a/Samples/Pedometer/js/Pedometer.sln +++ b/Samples/Pedometer/js/Pedometer.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Pedometer", "Pedometer.jsproj", "{DD7FAE58-B1A8-5E2E-8BFE-2251884FF567}" EndProject diff --git a/Samples/Personalization/cpp/Personalization.sln b/Samples/Personalization/cpp/Personalization.sln index ac82b34877..a09fd848cf 100644 --- a/Samples/Personalization/cpp/Personalization.sln +++ b/Samples/Personalization/cpp/Personalization.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Personalization", "Personalization.vcxproj", "{BB75573C-FF1F-55EB-88CF-4AEDD8A9D7A5}" EndProject diff --git a/Samples/Personalization/cs/Personalization.sln b/Samples/Personalization/cs/Personalization.sln index 2487cd5160..ea6e7ee5f0 100644 --- a/Samples/Personalization/cs/Personalization.sln +++ b/Samples/Personalization/cs/Personalization.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Personalization", "Personalization.csproj", "{DB0262C5-91ED-5A75-B538-8EE88C89864C}" EndProject diff --git a/Samples/Personalization/js/Personalization.sln b/Samples/Personalization/js/Personalization.sln index b2ef55f56f..e316d3c2a3 100644 --- a/Samples/Personalization/js/Personalization.sln +++ b/Samples/Personalization/js/Personalization.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22609.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Personalization", "Personalization.jsproj", "{9B328927-A0CA-567E-BEEA-E19FA222FE5A}" EndProject diff --git a/Samples/PhoneCall/cs/PhoneCall.sln b/Samples/PhoneCall/cs/PhoneCall.sln index f825c53b61..a226717fb5 100644 --- a/Samples/PhoneCall/cs/PhoneCall.sln +++ b/Samples/PhoneCall/cs/PhoneCall.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23103.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneCall", "PhoneCall.csproj", "{CD6DB80A-CD90-58CF-9BC5-E68860B4D7B9}" EndProject diff --git a/Samples/PlayReady/cs/PlayReady.sln b/Samples/PlayReady/cs/PlayReady.sln index d9b85c6423..47d78a9933 100644 --- a/Samples/PlayReady/cs/PlayReady.sln +++ b/Samples/PlayReady/cs/PlayReady.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlayReady", "PlayReady.csproj", "{1FBA39A3-D643-5620-AF91-497045D71641}" EndProject diff --git a/Samples/PlayReady/js/PlayReady.sln b/Samples/PlayReady/js/PlayReady.sln index a2ba421006..b22d1eba2b 100644 --- a/Samples/PlayReady/js/PlayReady.sln +++ b/Samples/PlayReady/js/PlayReady.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "PlayReady", "PlayReady.jsproj", "{56F093EF-1956-518A-A1D1-48C0D1664C1A}" EndProject diff --git a/Samples/Playlists/cpp/Playlists.sln b/Samples/Playlists/cpp/Playlists.sln index 9ed8841cf2..f312aa9bed 100644 --- a/Samples/Playlists/cpp/Playlists.sln +++ b/Samples/Playlists/cpp/Playlists.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Playlists", "Playlists.vcxproj", "{78105785-45D2-5F11-B96D-56E2524D8D92}" EndProject diff --git a/Samples/Playlists/cs/Playlists.sln b/Samples/Playlists/cs/Playlists.sln index e3abfdb430..2d5be7cd61 100644 --- a/Samples/Playlists/cs/Playlists.sln +++ b/Samples/Playlists/cs/Playlists.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Playlists", "Playlists.csproj", "{D4709CFC-12C5-5BD4-BABD-8B1C7234C159}" EndProject diff --git a/Samples/Playlists/js/Playlists.sln b/Samples/Playlists/js/Playlists.sln index 91bc6f0b20..9c25badeef 100644 --- a/Samples/Playlists/js/Playlists.sln +++ b/Samples/Playlists/js/Playlists.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Playlists", "Playlists.jsproj", "{43B2E240-969D-5F23-A8D5-69A9BAE441D9}" EndProject diff --git a/Samples/PosPrinter/cpp/PosPrinter.sln b/Samples/PosPrinter/cpp/PosPrinter.sln index 2c9021e58c..188acccbb6 100644 --- a/Samples/PosPrinter/cpp/PosPrinter.sln +++ b/Samples/PosPrinter/cpp/PosPrinter.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22512.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PosPrinter", "PosPrinter.vcxproj", "{72EA7C4D-F210-5BB1-9FE4-15765144F091}" EndProject diff --git a/Samples/PosPrinter/cpp/PosPrinter.vcxproj b/Samples/PosPrinter/cpp/PosPrinter.vcxproj index 6d9fe5f506..b06c692c74 100644 --- a/Samples/PosPrinter/cpp/PosPrinter.vcxproj +++ b/Samples/PosPrinter/cpp/PosPrinter.vcxproj @@ -147,13 +147,16 @@ - Scenario1_ReceiptPrinter.xaml + ..\shared\Scenario1_ReceiptPrinter.xaml - Scenario2_ErrorHandling.xaml + ..\shared\Scenario2_ErrorHandling.xaml - Scenario3_MultipleReceipt.xaml + ..\shared\Scenario3_MultipleReceipt.xaml + + + ..\shared\Scenario4_BitmapReceipt.xaml @@ -163,12 +166,13 @@ Designer - - - + + + Styles\Styles.xaml + @@ -192,16 +196,22 @@ - Scenario1_ReceiptPrinter.xaml + ..\shared\Scenario1_ReceiptPrinter.xaml - Scenario2_ErrorHandling.xaml + ..\shared\Scenario2_ErrorHandling.xaml - Scenario3_MultipleReceipt.xaml + ..\shared\Scenario3_MultipleReceipt.xaml + + + ..\shared\Scenario4_BitmapReceipt.xaml + + Assets\coffee-logo.png + Assets\microsoft-sdk.png diff --git a/Samples/PosPrinter/cpp/PosPrinter.vcxproj.filters b/Samples/PosPrinter/cpp/PosPrinter.vcxproj.filters index 2bc20850b4..bd3c4b4809 100644 --- a/Samples/PosPrinter/cpp/PosPrinter.vcxproj.filters +++ b/Samples/PosPrinter/cpp/PosPrinter.vcxproj.filters @@ -39,11 +39,14 @@ Styles - - - + + + + + Assets + Assets diff --git a/Samples/PosPrinter/cpp/SampleConfiguration.cpp b/Samples/PosPrinter/cpp/SampleConfiguration.cpp index 34453fd67f..760f5595c8 100644 --- a/Samples/PosPrinter/cpp/SampleConfiguration.cpp +++ b/Samples/PosPrinter/cpp/SampleConfiguration.cpp @@ -24,7 +24,8 @@ Platform::Array^ MainPage::scenariosInner = ref new Platform::Array DeviceHelpers::GetFirstReceiptPrinterAsync(PosConnectionTypes connectionTypes) diff --git a/Samples/PosPrinter/cpp/Scenario1_ReceiptPrinter.xaml.h b/Samples/PosPrinter/cpp/Scenario1_ReceiptPrinter.xaml.h index bb57fce4a1..a611488265 100644 --- a/Samples/PosPrinter/cpp/Scenario1_ReceiptPrinter.xaml.h +++ b/Samples/PosPrinter/cpp/Scenario1_ReceiptPrinter.xaml.h @@ -49,9 +49,9 @@ namespace SDKTemplate void EndScenario_Click(Platform::Object^ sender, RoutedEventArgs e); void ResetTheScenarioState(); - ReceiptPrintJob^ GetMerchantFooter(ClaimedPosPrinter^ claimedInstance); - ReceiptPrintJob^ GetCustomerFooter(ClaimedPosPrinter^ claimedInstance); - void LineFeedAndCutPaper(ReceiptPrintJob^ job); + Platform::String^ GetMerchantFooter(); + Platform::String^ GetCustomerFooter(); + void PrintLineFeedAndCutPaper(ReceiptPrintJob^ job, Platform::String^ receipt); task ClaimPrinter(); task EnableAsync(); diff --git a/Samples/PosPrinter/cpp/Scenario4_BitmapReceipt.xaml.cpp b/Samples/PosPrinter/cpp/Scenario4_BitmapReceipt.xaml.cpp new file mode 100644 index 0000000000..221fbf8b3b --- /dev/null +++ b/Samples/PosPrinter/cpp/Scenario4_BitmapReceipt.xaml.cpp @@ -0,0 +1,254 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#include "pch.h" +#include "Scenario4_BitmapReceipt.xaml.h" + +using namespace SDKTemplate; + +using namespace Concurrency; +using namespace Platform; +using namespace Windows::Devices::Enumeration; +using namespace Windows::Devices::PointOfService; +using namespace Windows::Foundation::Collections; +using namespace Windows::Foundation; +using namespace Windows::Graphics::Imaging; +using namespace Windows::Storage; +using namespace Windows::Storage::Streams; +using namespace Windows::UI::Core; +using namespace Windows::UI::Xaml::Controls::Primitives; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Data; +using namespace Windows::UI::Xaml::Input; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Navigation; +using namespace Windows::UI::Xaml; + +// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 + +Scenario4_BitmapReceipt::Scenario4_BitmapReceipt() : rootPage(MainPage::Current) +{ + InitializeComponent(); + ResetTheScenarioState(); +} + +void Scenario4_BitmapReceipt::PrintBitmap_Click(Platform::Object ^sender, RoutedEventArgs^ e) +{ + rootPage->NotifyUser("Trying to Print Receipt", NotifyType::StatusMessage); + PrintBitmap(); +} + +// +//Creates multiple tasks, first to find a receipt printer, then to claim the printer and then to enable and add releasedevicerequested event handler. +// +void Scenario4_BitmapReceipt::FindClaimEnable_Click(Platform::Object^ sender, RoutedEventArgs^ e) +{ + FindReceiptPrinter().then([this]() + { + if (printer != nullptr) + { + ClaimPrinter().then([this]() + { + if (claimedPrinter) + { + EnableAsync().then([this]() + { + releaseDeviceRequestedToken = claimedPrinter->ReleaseDeviceRequested += + ref new TypedEventHandler(this, &Scenario4_BitmapReceipt::ClaimedPrinter_ReleaseDeviceRequested); + }); + } + }); + } + }); +} + +void Scenario4_BitmapReceipt::IsImportantTransaction_Click(Object^ sender, RoutedEventArgs^ e) +{ + auto checkBox = safe_cast(sender); + IsAnImportantTransaction = checkBox->IsChecked->Value; +} + +// +//Default checkbox selection makes it an important transaction, hence we do not release claim when we get a release devicerequested event. +// +void Scenario4_BitmapReceipt::ClaimedPrinter_ReleaseDeviceRequested(ClaimedPosPrinter ^claimedInstance, PosPrinterReleaseDeviceRequestedEventArgs ^args) +{ + if (IsAnImportantTransaction) + { + create_task(claimedInstance->RetainDeviceAsync()).then([this](bool success) + { + if (success) + { + rootPage->NotifyUser("Retained Device", NotifyType::StatusMessage); + } + else + { + rootPage->NotifyUser("Could not retain device.", NotifyType::ErrorMessage); + } + }); + } + else + { + ResetTheScenarioState(); + } +} + + +void Scenario4_BitmapReceipt::EndScenario_Click(Platform::Object ^sender, RoutedEventArgs^ e) +{ + ResetTheScenarioState(); + rootPage->NotifyUser("Disconnected Printer", NotifyType::StatusMessage); +} + +// +//Actual claim method task that claims the printer asynchronously +// +task Scenario4_BitmapReceipt::ClaimPrinter() +{ + if (claimedPrinter == nullptr) + { + return create_task(printer->ClaimPrinterAsync()).then([this](ClaimedPosPrinter^ _claimedPrinter) + { + this->claimedPrinter = _claimedPrinter; + if (claimedPrinter != nullptr) + { + rootPage->NotifyUser("Claimed Printer", NotifyType::StatusMessage); + } + else + { + rootPage->NotifyUser("Claim Printer failed", NotifyType::ErrorMessage); + } + }); + } + + return task_from_result(); +} + +task Scenario4_BitmapReceipt::EnableAsync() +{ + if (claimedPrinter) + { + return create_task(claimedPrinter->EnableAsync()).then([this](bool) + { + rootPage->NotifyUser("Enabled printer.", NotifyType::StatusMessage); + }); + } + else + { + rootPage->NotifyUser("Error: Printer not claimed anymore to enable.", NotifyType::ErrorMessage); + return task_from_result(); + } +} + +// +//Prints a sample receipt. +// +void Scenario4_BitmapReceipt::PrintBitmap() +{ + if (printer != nullptr && claimedPrinter != nullptr) + { + LoadLogoBitmapAsync().then([this](BitmapFrame^ logoFrame) + { + ReceiptPrintJob^ job = claimedPrinter->Receipt->CreateJob(); + claimedPrinter->Receipt->IsLetterQuality = true; + job->PrintBitmap(logoFrame, PosPrinterAlignment::Center); + return create_task(job->ExecuteAsync()); + }).then([this](bool success) + { + if (success) + { + rootPage->NotifyUser("Bitmap printed successfully", NotifyType::StatusMessage); + } + else + { + rootPage->NotifyUser("Was not able to print bitmap", NotifyType::ErrorMessage); + } + }); + } + else + { + rootPage->NotifyUser("Must find and claim printer before printing.", NotifyType::ErrorMessage); + } +} + +task Scenario4_BitmapReceipt::LoadLogoBitmapAsync() +{ + Uri^ uri = ref new Uri("ms-appx:///Assets/coffee-logo.png"); + return create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).then([](StorageFile^ file) + { + return create_task(file->OpenReadAsync()); + }).then([](IRandomAccessStream^ readStream) + { + return create_task(BitmapDecoder::CreateAsync(readStream)); + }).then([](BitmapDecoder^ decoder) + { + return create_task(decoder->GetFrameAsync(0)); + }); +} + +task Scenario4_BitmapReceipt::FindReceiptPrinter() +{ + if (printer == nullptr) + { + rootPage->NotifyUser("Finding printer", NotifyType::StatusMessage); + return DeviceHelpers::GetFirstReceiptPrinterAsync().then([this](PosPrinter^ _printer) + { + printer = _printer; + if (printer != nullptr) + { + rootPage->NotifyUser("Got Printer with Device Id : " + printer->DeviceId, NotifyType::StatusMessage); + } + else + { + rootPage->NotifyUser("Could not get printer.", NotifyType::ErrorMessage); + } + }); + } + return task_from_result(); +} + +// +//Remove event handler and delete claimed instance. +// +void Scenario4_BitmapReceipt::ResetTheScenarioState() +{ + if (claimedPrinter != nullptr) + { + claimedPrinter->ReleaseDeviceRequested -= releaseDeviceRequestedToken; + delete claimedPrinter; + claimedPrinter = nullptr; + } + + if (printer != nullptr) + { + delete printer; + printer = nullptr; + } +} + +/// +/// Invoked when this page is about to be displayed in a Frame. +/// +/// Event data that describes how this page was reached. The Parameter +/// property is typically used to configure the page. +void Scenario4_BitmapReceipt::OnNavigatedTo(NavigationEventArgs^ e) +{ + ResetTheScenarioState(); +} + +/// +/// Invoked when this page is no longer displayed. +/// +/// +void Scenario4_BitmapReceipt::OnNavigatedFrom(NavigationEventArgs^ e) +{ + ResetTheScenarioState(); +} diff --git a/Samples/PosPrinter/cpp/Scenario4_BitmapReceipt.xaml.h b/Samples/PosPrinter/cpp/Scenario4_BitmapReceipt.xaml.h new file mode 100644 index 0000000000..3675394017 --- /dev/null +++ b/Samples/PosPrinter/cpp/Scenario4_BitmapReceipt.xaml.h @@ -0,0 +1,56 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +#pragma once + +#include "Scenario4_BitmapReceipt.g.h" +#include "MainPage.xaml.h" + +namespace SDKTemplate +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + [Windows::Foundation::Metadata::WebHostHidden] + public ref class Scenario4_BitmapReceipt sealed + { + public: + Scenario4_BitmapReceipt(); + + protected: + virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; + virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; + + private: + MainPage^ rootPage; + Windows::Devices::PointOfService::PosPrinter^ printer; + Windows::Devices::PointOfService::ClaimedPosPrinter^ claimedPrinter; + bool IsAnImportantTransaction = true; + Windows::Foundation::EventRegistrationToken releaseDeviceRequestedToken; + + Concurrency::task FindReceiptPrinter(); + void ClaimedPrinter_ReleaseDeviceRequested(Windows::Devices::PointOfService::ClaimedPosPrinter^ claimedInstance, Windows::Devices::PointOfService::PosPrinterReleaseDeviceRequestedEventArgs^ args); + + void FindClaimEnable_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void IsImportantTransaction_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void PrintBitmap_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void EndScenario_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + + void ResetTheScenarioState(); +// void PrintLineFeedAndCutPaper(Windows::Devices::PointOfService::ReceiptPrintJob^ job, Platform::String^ receipt); + + Concurrency::task ClaimPrinter(); + Concurrency::task EnableAsync(); + Concurrency::task LoadLogoBitmapAsync(); + void PrintBitmap(); + + }; +} diff --git a/Samples/PosPrinter/cs/PosPrinter.csproj b/Samples/PosPrinter/cs/PosPrinter.csproj index 5db07a15bc..4dee51f156 100644 --- a/Samples/PosPrinter/cs/PosPrinter.csproj +++ b/Samples/PosPrinter/cs/PosPrinter.csproj @@ -7,7 +7,7 @@ {D22D4718-85D7-59F5-812D-0BF7349309E3} AppContainerExe Properties - PosPrinterSample + SDKTemplate PosPrinter en-US UAP @@ -100,6 +100,9 @@ DeviceHelpers.cs + + Scenario4_BitmapReceipt.xaml + Scenario1_ReceiptPrinter.xaml @@ -126,15 +129,23 @@ MSBuild:Compile Designer - + + Scenario4_BitmapReceipt.xaml MSBuild:Compile Designer - + + Scenario1_ReceiptPrinter.xaml MSBuild:Compile Designer - + + Scenario2_ErrorHandling.xaml + MSBuild:Compile + Designer + + + Scenario3_MultipleReceipt.xaml MSBuild:Compile Designer @@ -145,6 +156,9 @@ + + Assets\coffee-logo.png + Properties\Default.rd.xml diff --git a/Samples/PosPrinter/cs/PosPrinter.sln b/Samples/PosPrinter/cs/PosPrinter.sln index 3ecb5de4e8..2519a46bcf 100644 --- a/Samples/PosPrinter/cs/PosPrinter.sln +++ b/Samples/PosPrinter/cs/PosPrinter.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.22418.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PosPrinter", "PosPrinter.csproj", "{D22D4718-85D7-59F5-812D-0BF7349309E3}" EndProject diff --git a/Samples/PosPrinter/cs/SampleConfiguration.cs b/Samples/PosPrinter/cs/SampleConfiguration.cs index 1c807ba5f7..0d2ccc4f4f 100644 --- a/Samples/PosPrinter/cs/SampleConfiguration.cs +++ b/Samples/PosPrinter/cs/SampleConfiguration.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; using Windows.Devices.PointOfService; using Windows.UI.Xaml.Controls; -using PosPrinterSample; +using SDKTemplate; namespace SDKTemplate { @@ -26,7 +26,8 @@ public partial class MainPage : Page { new Scenario() { Title="Receipt Printer", ClassType=typeof(Scenario1_ReceiptPrinter)}, new Scenario() { Title="Receipt Printer Error Handling", ClassType=typeof(Scenario2_ErrorHandling)}, - new Scenario() { Title="Multiple Receipt Printers", ClassType=typeof(Scenario3_MultipleReceipt)} + new Scenario() { Title="Multiple Receipt Printers", ClassType=typeof(Scenario3_MultipleReceipt)}, + new Scenario() { Title="Bitmap Receipt", ClassType=typeof(Scenario4_BitmapReceipt), } }; } diff --git a/Samples/PosPrinter/cs/Scenario1_ReceiptPrinter.xaml b/Samples/PosPrinter/cs/Scenario1_ReceiptPrinter.xaml deleted file mode 100644 index 942eebd54d..0000000000 --- a/Samples/PosPrinter/cs/Scenario1_ReceiptPrinter.xaml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - Find, claim, and enable a receipt printer, and then perform a test print with the printer object. - - - - - - +
+ +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/Samples/PosPrinter/js/js/Scenario4_BitmapReceipt.js b/Samples/PosPrinter/js/js/Scenario4_BitmapReceipt.js new file mode 100644 index 0000000000..2edd8ab5a6 --- /dev/null +++ b/Samples/PosPrinter/js/js/Scenario4_BitmapReceipt.js @@ -0,0 +1,141 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +(function () { + "use strict"; + var page = WinJS.UI.Pages.define("/html/Scenario4_BitmapReceipt.html", { + + ready: function (element, options) { + + WinJS.log("Find and claim the printer to begin.", "sample", "status"); + + document.getElementById("findClaimEnableButton").addEventListener("click", findClaimEnable, false); + document.getElementById("isImportantTransactionCheckBox").addEventListener("click", toggleIsImportant, false); + document.getElementById("scenarioEndButton").addEventListener("click", endScenario, false); + document.getElementById("printBitmapButton").addEventListener("click", printBitmap, false); + }, + + unload: function () { + if (_claimedPrinter !== null) { + _claimedPrinter.close(); + _claimedPrinter = null; + } + + if (_printer !== null) { + _printer.close(); + _printer = null; + } + } + }); + + var _printer = null; + var _claimedPrinter = null; + var _isImportantTransaction = true; + + // + //Creates multiple tasks, first to find a receipt printer, then to claim the printer and then to enable and add releasedevicerequested event handler. + // + function findClaimEnable() { + + WinJS.log("Finding printer...", "sample", "status"); + + if (_printer == null) { + + SdkSample.getFirstReceiptPrinterAsync().then(function (printer) { + + if (printer != null) { + _printer = printer; + + //Claim + _printer.claimPrinterAsync().done(function (claimedPrinter) { + + if (claimedPrinter !== null) { + + _claimedPrinter = claimedPrinter; + + //Enable printer + _claimedPrinter.enableAsync().done(function (success) { + + if (success) { + WinJS.log("Enabled printer. Device ID: " + _claimedPrinter.deviceId, "sample", "status"); + + document.getElementById("findClaimEnableButton").disabled = true; + document.getElementById("printBitmapButton").disabled = false; + document.getElementById("scenarioEndButton").disabled = false; + } + else { + WinJS.log("Could not enable printer.", "sample", "error"); + } + }); + } else { + WinJS.log("Could not claim the printer.", "sample", "error"); + } + }); + } else { + WinJS.log("No printer found", "sample", "error"); + } + }); + } + } + + function toggleIsImportant(e) { + _isImportantTransaction = e.target.checked; + } + + function endScenario() { + + if (_claimedPrinter !== null) { + _claimedPrinter.close(); + _claimedPrinter = null; + } + + if (_printer !== null) { + _printer.close(); + _printer = null; + } + + WinJS.log("Scenario ended.", "sample", "status"); + + document.getElementById("findClaimEnableButton").disabled = false; + document.getElementById("printBitmapButton").disabled = true; + document.getElementById("scenarioEndButton").disabled = true; + } + + // + //Prints the logo bitmap. + // + function printBitmap() { + + if (_claimedPrinter == null) { + WinJS.log("Claimed printer instance is null. Cannot print.", "sample", "error"); + } else { + var uri = new Windows.Foundation.Uri("ms-appx:///images/coffee-logo.png"); + Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) { + return file.openReadAsync(); + }).then(function (readStream) { + return Windows.Graphics.Imaging.BitmapDecoder.createAsync(readStream); + }).then(function (decoder) { + return decoder.getFrameAsync(0); + }).then(function (bitmapFrame) { + _claimedPrinter.receipt.isLetterQuality = true; + var job = _claimedPrinter.receipt.createJob(); + job.printBitmap(bitmapFrame, Windows.Devices.PointOfService.PosPrinterAlignment.Center, 500); + return job.executeAsync(); + }).done(function (success) { + if (success) { + WinJS.log("Was not able to print bitmap.", "sample", "error"); + } else { + WinJS.log("Printed Bitmap.", "sample", "status"); + } + }); + } + } +})(); diff --git a/Samples/PosPrinter/js/js/sample-configuration.js b/Samples/PosPrinter/js/js/sample-configuration.js index 6ceb3c2937..00fd406f1b 100644 --- a/Samples/PosPrinter/js/js/sample-configuration.js +++ b/Samples/PosPrinter/js/js/sample-configuration.js @@ -17,7 +17,8 @@ var scenarios = [ { url: "/html/Scenario1_ReceiptPrinter.html", title: "Receipt Printer" }, { url: "/html/Scenario2_ErrorHandling.html", title: "Error Handling" }, - { url: "/html/Scenario3_MultipleReceipt.html", title: "Multiple Receipt Printers" } + { url: "/html/Scenario3_MultipleReceipt.html", title: "Multiple Receipt Printers" }, + { url: "/html/Scenario4_BitmapReceipt.html", title: "Bitmap Receipt" }, ]; var PosPrinter = Windows.Devices.PointOfService.PosPrinter; diff --git a/Samples/PosPrinter/cpp/Scenario1_ReceiptPrinter.xaml b/Samples/PosPrinter/shared/Scenario1_ReceiptPrinter.xaml similarity index 100% rename from Samples/PosPrinter/cpp/Scenario1_ReceiptPrinter.xaml rename to Samples/PosPrinter/shared/Scenario1_ReceiptPrinter.xaml diff --git a/Samples/PosPrinter/cpp/Scenario2_ErrorHandling.xaml b/Samples/PosPrinter/shared/Scenario2_ErrorHandling.xaml similarity index 100% rename from Samples/PosPrinter/cpp/Scenario2_ErrorHandling.xaml rename to Samples/PosPrinter/shared/Scenario2_ErrorHandling.xaml index ced512bb83..60e18a7089 100644 --- a/Samples/PosPrinter/cpp/Scenario2_ErrorHandling.xaml +++ b/Samples/PosPrinter/shared/Scenario2_ErrorHandling.xaml @@ -36,8 +36,8 @@