Implementar inicializadores de aplicativos 3D (aplicativos Win32)

Observação

Esse recurso só está disponível para computadores que executam os voos mais recentes do Windows Insider (RS5), build 17704 e mais recente.

A casa Windows Mixed Reality é o ponto de partida em que os usuários chegam antes de iniciar aplicativos. Por padrão, você precisa iniciar aplicativos e jogos win32 VR imersivos de fora do fone de ouvido e não aparecerá na lista "Todos os aplicativos" no menu Iniciar Windows Mixed Reality. Se você seguir as instruções neste artigo para implementar um inicializador de aplicativos 3D, sua experiência imersiva do Win32 VR poderá ser iniciada de dentro do menu Iniciar Windows Mixed Reality e do ambiente inicial.

Isso só vale para experiências imersivas do Win32 VR distribuídas fora do Steam. Para experiências vr distribuídas por meio do Steam, atualizamos o Windows Mixed Reality para SteamVR Beta juntamente com os voos mais recentes do Windows Insider RS5 para que os títulos do SteamVR apareçam no menu iniciar Windows Mixed Reality na lista "Todos os aplicativos" automaticamente usando um inicializador padrão. Em outras palavras, o método descrito neste artigo é desnecessário para títulos do SteamVR e será substituído pelo Windows Mixed Reality para a funcionalidade do SteamVR Beta.

Processo de criação do inicializador de aplicativos 3D

Há três etapas para criar um inicializador de aplicativos 3D:

  1. Design e conceitos
  2. Modelagem e exportação
  3. Integrando-o ao seu aplicativo (este artigo)

Os ativos 3D a serem usados como inicializadores para seu aplicativo devem ser criados usando as diretrizes de criação do Windows Mixed Reality para garantir a compatibilidade. Os ativos que não atenderem a essa especificação de criação não serão renderizados na Windows Mixed Reality página inicial.

Configurando o inicializador 3D

Os aplicativos Win32 aparecerão na lista "Todos os aplicativos" no menu Iniciar Windows Mixed Reality se você criar um inicializador de aplicativos 3D para eles. Para fazer isso, crie um arquivo XML de Manifesto de Elementos Visuais referenciando o Inicializador de Aplicativos 3D seguindo estas etapas:

  1. Crie um arquivo GLB de ativo do Inicializador de Aplicativos 3D (consulte Modelagem e exportação).
  2. Crie um manifesto de elementos visuais para seu aplicativo.
    1. Você pode começar com o exemplo abaixo. Consulte a documentação completa do Manifesto de Elementos Visuais para obter mais detalhes.
    2. Atualize Square150x150Logo e Square70x70Logo com um PNG/JPG/GIF para seu aplicativo.
      • Eles serão usados para o logotipo 2D do aplicativo na lista Windows Mixed Reality Todos os Aplicativos e para o Menu Iniciar na área de trabalho.
      • O caminho do arquivo é baseado na pasta que contém o Manifesto de Elementos Visuais.
      • Você ainda precisa fornecer um ícone do Menu Iniciar da área de trabalho para seu aplicativo por meio dos mecanismos padrão. Isso pode estar diretamente no executável ou no atalho que você criar. Por exemplo, por meio de IShellLink::SetIconLocation.
      • Opcional: Você pode usar um arquivo resources.pri se desejar que o MRT forneça vários tamanhos de ativo para diferentes escalas de resolução e temas de alto contraste.
    3. Atualizar o Caminho MixedRealityModel para apontar para o GLB para o inicializador de aplicativos 3D
    4. Salve o arquivo com o mesmo nome que o arquivo executável, com uma extensão ".VisualElementsManifest.xml" e salve-o no mesmo diretório. Por exemplo, para o arquivo executável "contoso.exe", o arquivo XML que acompanha é chamado de "contoso.visualelementsmanifest.xml".
  3. Adicione um atalho ao seu aplicativo ao Menu Iniciar do Windows da área de trabalho. Consulte o exemplo abaixo para obter um exemplo de implementação do C++.
    • Crie-o em %ALLUSERSPROFILE%\Microsoft\Windows\Menu Iniciar\Programas (computador) ou %APPDATA%\Microsoft\Windows\Menu Iniciar\Programas (usuário)
    • Se uma atualização alterar o manifesto dos elementos visuais ou os ativos referenciados por ele, o atualizador ou instalador deverá atualizar o atalho de modo que o manifesto seja reparsado e os ativos armazenados em cache sejam atualizados.
  4. Opcional: Se o atalho da área de trabalho não apontar diretamente para o EXE do aplicativo (por exemplo, se ele invocar um manipulador de protocolo personalizado como "myapp://"), o Menu Iniciar não encontrará automaticamente o arquivo VisualElementsManifest.xml do aplicativo. Para resolve isso, o atalho deve especificar o caminho do arquivo do Manifesto de Elementos Visuais usando System.AppUserModel.VisualElementsManifestHintPath (). Isso pode ser definido no atalho usando as mesmas técnicas que System.AppUserModel.ID. Você não precisa usar System.AppUserModel.ID, mas pode fazê-lo se desejar que o atalho corresponda à ID explícita do modelo de usuário do aplicativo se um for usado. Consulte a seção de criação de atalho do inicializador de aplicativos de exemplo abaixo para obter um exemplo de C++.

Exemplo de manifesto de elementos visuais

<Application xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <VisualElements
    ShowNameOnSquare150x150Logo="on"
    Square150x150Logo="YOUR_APP_LOGO_150X150.png"
    Square70x70Logo=" YOUR_APP_LOGO_70X70.png"
    ForegroundText="light"
    BackgroundColor="#000000">
    <MixedRealityModel Path="YOUR_3D_APP_LAUNCHER_ASSET.glb">
        <SpatialBoundingBox Center="0,0,0" Extents="Auto" />
    </MixedRealityModel>
  </VisualElements>
</Application>

Criação de atalho de inicializador de aplicativo de exemplo

O código de exemplo abaixo mostra como você pode criar um atalho no C++, incluindo substituir o caminho para o arquivo XML manifesto de elementos visuais. Observe que a substituição só é necessária nos casos em que o atalho não aponta diretamente para o EXE associado ao manifesto (por exemplo, o atalho usa um manipulador de protocolo personalizado como "myapp://").

Amostra. Criação de atalho LNK (C++)

#include <windows.h>
#include <propkey.h>
#include <shlobj_core.h>
#include <shlwapi.h>
#include <propvarutil.h>
#include <wrl.h>

#include <memory>

using namespace Microsoft::WRL;

#define RETURN_IF_FAILED(x) do { HRESULT hr = x; if (FAILED(hr)) { return hr; } } while(0)
#define RETURN_IF_WIN32_BOOL_FALSE(x) do { DWORD res = x; if (res == 0) { return HRESULT_FROM_WIN32(GetLastError()); } } while(0)

int wmain()
{
    RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED));

    ComPtr<IShellLink> shellLink;
    RETURN_IF_FAILED(CoCreateInstance(__uuidof(ShellLink), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)));
    RETURN_IF_FAILED(shellLink->SetPath(L"MyLauncher://launch/app-identifier"));

    // It is also possible to use an icon file in another location. For example, "C:\Program Files (x86)\MyLauncher\assets\app-identifier.ico".
    RETURN_IF_FAILED(shellLink->SetIconLocation(L"C:\\Program Files (x86)\\MyLauncher\\apps\\app-identifier\\game.exe", 0 /*iIcon*/));

    ComPtr<IPropertyStore> propStore;
    RETURN_IF_FAILED(shellLink.As(&propStore));

    {
        // Optional: If the application has an explict Application User Model ID, then you should usually specify it in the shortcut.
        PROPVARIANT propVar;
        RETURN_IF_FAILED(InitPropVariantFromString(L"ExplicitAppUserModelID", &propVar));
        RETURN_IF_FAILED(propStore->SetValue(PKEY_AppUserModel_ID, propVar));
        PropVariantClear(&propVar);
    }

    {
        // A hint path to the manifest is only necessary if the target path of the shortcut is not a file path to the executable.
        // By convention the manifest is named <executable name>.VisualElementsManifest.xml and is in the same folder as the executable
        // (and resources.pri if applicable). Assets referenced by the manifest are relative to the folder containing the manifest.

        //
        // PropKey.h
        //
        //  Name:     System.AppUserModel.VisualElementsManifestHintPath -- PKEY_AppUserModel_VisualElementsManifestHintPath
        //  Type:     String -- VT_LPWSTR  (For variants: VT_BSTR)
        //  FormatID: {9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 31
        //  
        //  Suggests where to look for the VisualElementsManifest for a Win32 app
        //
        // DEFINE_PROPERTYKEY(PKEY_AppUserModel_VisualElementsManifestHintPath, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 31);
        // #define INIT_PKEY_AppUserModel_VisualElementsManifestHintPath { { 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 }, 31 }

        PROPVARIANT propVar;
        RETURN_IF_FAILED(InitPropVariantFromString(L"C:\\Program Files (x86)\\MyLauncher\\apps\\app-identifier\\game.visualelementsmanifest.xml", &propVar));
        RETURN_IF_FAILED(propStore->SetValue(PKEY_AppUserModel_VisualElementsManifestHintPath, propVar));
        PropVariantClear(&propVar);
    }

    constexpr PCWSTR shortcutPath = L"%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\game.lnk";
    const DWORD requiredBufferLength = ExpandEnvironmentStrings(shortcutPath, nullptr, 0);
    RETURN_IF_WIN32_BOOL_FALSE(requiredBufferLength);

    const auto expandedShortcutPath = std::make_unique<wchar_t[]>(requiredBufferLength);
    RETURN_IF_WIN32_BOOL_FALSE(ExpandEnvironmentStrings(shortcutPath, expandedShortcutPath.get(), requiredBufferLength));

    ComPtr<IPersistFile> persistFile;
    RETURN_IF_FAILED(shellLink.As(&persistFile));
    RETURN_IF_FAILED(persistFile->Save(expandedShortcutPath.get(), FALSE));

    return 0;
}

Amostra. Atalho do inicializador de URL

[{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}]
Prop31=C:\Program Files (x86)\MyLauncher\apps\app-identifier\game.visualelementsmanifest.xml
Prop5=ExplicitAppUserModelID

[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,0

[InternetShortcut]
IDList=
URL=MyLauncher://launch/app-identifier
IconFile=C:\Program Files (x86)\MyLauncher\apps\app-identifier\game.exe
IconIndex=0

Confira também