1

I am maintaining a C# WPF application, and I want to add Windows Mixed Reality support to it.

Porting the app to UWP is probably not a very good idea, as the app supports a lot of other APIs that do not have their UWP variants. For example Oculus, OSVR and OpenVR(Vive) support. I do not have enough UWP experience to sure, though.

So, any idea if it's even possible to use Mixed Reality UWP APIs in a non-UWP application? Or perhaps porting middleware API to UWP is not so scary after all?

Krzysztof Bociurko
  • 4,575
  • 2
  • 26
  • 44

3 Answers3

2

You can also implement the interface in c# if you want to access it from your WPF/winforms projects. To use the code below, add a reference to the Microsoft.Windows.SDK.Contracts nuget package, eg: https://www.nuget.org/packages/Microsoft.Windows.SDK.Contracts/10.0.18362.2002-preview

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using Windows.UI.Input.Spatial;

namespace UWPInterop
{
    //MIDL_INTERFACE("5C4EE536-6A98-4B86-A170-587013D6FD4B")
    //ISpatialInteractionManagerInterop : public IInspectable
    //{
    //public:
    //    virtual HRESULT STDMETHODCALLTYPE GetForWindow(
    //        /* [in] */ __RPC__in HWND window,
    //        /* [in] */ __RPC__in REFIID riid,
    //        /* [iid_is][retval][out] */ __RPC__deref_out_opt void** spatialInteractionManager) = 0;

    //};
    [System.Runtime.InteropServices.Guid("5C4EE536-6A98-4B86-A170-587013D6FD4B")]
    [System.Runtime.InteropServices.InterfaceType(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIInspectable)]
    interface ISpatialInteractionManagerInterop
    {
        SpatialInteractionManager GetForWindow(IntPtr Window, [System.Runtime.InteropServices.In] ref Guid riid);
    }

    //Helper to initialize SpatialInteractionManager
    public static class SpatialInteractionManagerInterop
    {
        public static SpatialInteractionManager GetForWindow(IntPtr hWnd)
        {
            ISpatialInteractionManagerInterop spatialInteractionManagerInterop = (ISpatialInteractionManagerInterop)WindowsRuntimeMarshal.GetActivationFactory(typeof(SpatialInteractionManager));
            Guid guid = typeof(SpatialInteractionManager).GUID;

            return spatialInteractionManagerInterop.GetForWindow(hWnd, ref guid);
        }
    }
}
1

Sadly not, The Mixed Reality API's are all built in to the UWP platform, to run MR it needs to be in a UWP app. The only other way is to build a project as a Steam VR app, but I don't think that's compatible with what you are trying to achieve.

My best advice would be to try and make your project as cross-platform as possible. Putting all your logic in a Netcore / PCL project and having two different UI layers for WPF and UWP in separate projects.

Darkside
  • 1,722
  • 14
  • 19
  • Well, all I wanted was a "windows-mixed-reality" checkbox next to the "oculus", "openvr/steamvr" and "osvr" ones. Having someone to install a dedicated player just for that is not the best user experience. Developing the quite big WPF user interface from scratch in UWP is very bad developer experience. Maybe I could launch a slave UWP ap that gets a video texture and some other communication from the main app and only renders to the headset? – Krzysztof Bociurko Apr 05 '18 at 17:32
1

Yes, it's possible to use UWP API in any non-UWP app because all UWP API is actually COM. I usually prefer to use C++/WinRT, but it has the limitation in C++17 language.

If the limitation is unacceptable for you, you might use the classic COM like

    Microsoft::WRL::ComPtr<ABI::Windows::UI::Input::Spatial::ISpatialInteractionManagerStatics> interactionManagerStatic;
    Windows::Foundation::GetActivationFactory(
        Microsoft::WRL::Wrappers::HStringReference(InterfaceName_Windows_UI_Input_Spatial_ISpatialInteractionManagerStatics).Get(),
        &interactionManagerStatic);

    Microsoft::WRL::ComPtr<ABI::Windows::UI::Input::Spatial::ISpatialInteractionManager> interactionManager;
    if (FAILED(interactionManagerStatic->GetForCurrentView(interactionManager.GetAddressOf())))
    {
        return -1;
    }
Tania Chistyakova
  • 3,928
  • 6
  • 13
  • Thanks, will look into that. I'm currently working on C++/WinRT with another project but somehow didn't make the connection. Perhaps I might even do a C++ project with a proper IDL wrapper for this. – Krzysztof Bociurko Apr 25 '19 at 14:06