Share via


HoloLens (1ère génération) et Azure 311 - Microsoft Graph

Notes

Les tutoriels Mixed Reality Academy ont été conçus pour les appareils HoloLens (1re génération) et les casques immersifs de réalité mixte. Nous estimons qu’il est important de laisser ces tutoriels à la disposition des développeurs qui recherchent encore des conseils pour développer des applications sur ces appareils. Notez que ces tutoriels ne sont pas mis à jour avec les derniers ensembles d’outils ou interactions utilisés pour HoloLens 2. Ils sont fournis dans le but de fonctionner sur les appareils pris en charge. Il y aura une nouvelle série de tutoriels qui seront publiés à l’avenir et qui montreront comment développer pour HoloLens 2. Cet avis sera mis à jour avec un lien vers ces tutoriels lorsqu’ils seront publiés.

Dans ce cours, vous allez apprendre à utiliser Microsoft Graph pour vous connecter à votre compte Microsoft à l’aide de l’authentification sécurisée au sein d’une application de réalité mixte. Vous allez ensuite récupérer et afficher vos réunions planifiées dans l’interface de l’application.

Capture d’écran montrant les réunions planifiées dans l’interface de l’application.

Microsoft Graph est un ensemble d’API conçues pour permettre l’accès à de nombreux services de Microsoft. Microsoft décrit Microsoft Graph comme une matrice de ressources connectées par des relations, ce qui signifie qu’il permet à une application d’accéder à toutes sortes de données utilisateur connectées. Pour plus d’informations, consultez la page Microsoft Graph.

Le développement inclut la création d’une application dans laquelle l’utilisateur est invité à regarder, puis à appuyer sur une sphère, ce qui invite l’utilisateur à se connecter en toute sécurité à un compte Microsoft. Une fois connecté à son compte, l’utilisateur peut voir la liste des réunions planifiées pour la journée.

Après avoir terminé ce cours, vous disposerez d’une application HoloLens de réalité mixte, qui sera en mesure d’effectuer les opérations suivantes :

  1. À l’aide du mouvement Appuyez sur un objet, qui invite l’utilisateur à se connecter à un compte Microsoft (en sortant de l’application pour se connecter, puis à nouveau dans l’application).
  2. Affichez la liste des réunions planifiées pour la journée.

Dans votre application, il vous appartient de savoir comment intégrer les résultats à votre conception. Ce cours est conçu pour vous apprendre à intégrer un service Azure à votre projet Unity. C’est votre travail d’utiliser les connaissances que vous obtenez de ce cours pour améliorer votre application de réalité mixte.

Prise en charge des appareils

Cours HoloLens Casques immersifs
Réalité mixte - Azure - Cours 311 : Microsoft Graph ✔️

Prérequis

Notes

Ce tutoriel est conçu pour les développeurs qui ont une expérience de base avec Unity et C#. Notez également que les prérequis et les instructions écrites dans ce document représentent ce qui a été testé et vérifié au moment de la rédaction (juillet 2018). Vous êtes libre d’utiliser les logiciels les plus récents, comme indiqué dans l’article installer les outils , bien qu’il ne soit pas supposé que les informations de ce cours correspondront parfaitement à ce que vous trouverez dans les logiciels plus récents que ce qui est listé ci-dessous.

Nous vous recommandons d’utiliser le matériel et les logiciels suivants pour ce cours :

Avant de commencer

  1. Pour éviter de rencontrer des problèmes lors de la création de ce projet, il est fortement recommandé de créer le projet mentionné dans ce didacticiel dans un dossier racine ou proche de la racine (les chemins de dossier longs peuvent entraîner des problèmes au moment de la génération).
  2. Configurez et testez votre HoloLens. Si vous avez besoin de support pour configurer votre HoloLens, consultez l’article sur la configuration de HoloLens.
  3. Il est judicieux d’effectuer l’étalonnage et le réglage des capteurs lorsque vous commencez à développer une nouvelle application HoloLens (il peut parfois être utile d’effectuer ces tâches pour chaque utilisateur).

Pour obtenir de l’aide sur l’étalonnage, suivez ce lien vers l’article Étalonnage HoloLens.

Pour obtenir de l’aide sur le réglage des capteurs, suivez ce lien vers l’article Paramétrage du capteur HoloLens.

Chapitre 1 : Créer votre application dans le portail d’inscription des applications

Pour commencer, vous devez créer et inscrire votre application dans le portail d’inscription des applications.

Dans ce chapitre, vous trouverez également la clé de service qui vous permettra d’effectuer des appels à Microsoft Graph pour accéder au contenu de votre compte.

  1. Accédez au portail d’inscription des applications Microsoft et connectez-vous avec votre compte Microsoft. Une fois connecté, vous êtes redirigé vers le portail d’inscription des applications.

  2. Dans la section Mes applications , cliquez sur le bouton Ajouter une application.

    Capture d’écran montrant où sélectionner Ajouter une application.

    Important

    Le portail d’inscription des applications peut être différent, selon que vous avez déjà travaillé avec Microsoft Graph. Les captures d’écran ci-dessous affichent ces différentes versions.

  3. Ajoutez un nom pour votre application, puis cliquez sur Créer.

    Capture d’écran montrant où ajouter un nom pour votre application.

  4. Une fois l’application créée, vous êtes redirigé vers la page main de l’application. Copiez l’ID d’application et veillez à noter cette valeur à un endroit sûr, vous l’utiliserez bientôt dans votre code.

    Capture d’écran montrant où afficher l’ID d’application.

  5. Dans la section Plateformes , vérifiez que l’application native est affichée. Si ce n’est pas le cas, cliquez sur Ajouter une plateforme et sélectionnez Application native.

    Capture d’écran mettant en évidence la section Application native.

  6. Faites défiler vers le bas dans la même page et dans la section intitulée Autorisations Microsoft Graph , vous devez ajouter des autorisations supplémentaires pour l’application. Cliquez sur Ajouter en regard de Autorisations déléguées.

    Capture d’écran montrant où sélectionner Ajouter en regard de Autorisations déléguées.

  7. Étant donné que vous souhaitez que votre application accède au calendrier de l’utilisateur, case activée la zone appelée Calendars.Read et cliquez sur OK.

    Capture d’écran montrant la case Calendars.Read.

  8. Faites défiler jusqu’au bas, puis cliquez sur le bouton Enregistrer .

    Capture d’écran montrant où sélectionner Enregistrer.

  9. Votre enregistrement sera confirmé et vous pourrez vous déconnecter du portail d’inscription des applications.

Chapitre 2 - Configurer le projet Unity

Ce qui suit est une configuration classique pour le développement avec la réalité mixte. En tant que tel, il s’agit d’un bon modèle pour d’autres projets.

  1. Ouvrez Unity , puis cliquez sur Nouveau.

    Capture d’écran montrant l’interface Unity.

  2. Vous devez fournir un nom de projet Unity. Insérez MSGraphMR. Vérifiez que le modèle de projet est défini sur 3D. Définissez l’emplacement sur un emplacement approprié pour vous (n’oubliez pas qu’il est préférable de se rapprocher des répertoires racine). Cliquez ensuite sur Créer un projet.

    Capture d’écran montrant où sélectionner Créer un projet.

  3. Une fois Unity ouvert, il est utile de vérifier que l’éditeur de script par défaut est défini sur Visual Studio. Accédez à Modifier les>préférences , puis, dans la nouvelle fenêtre, accédez à Outils externes. Remplacez Éditeur de script externe par Visual Studio 2017. Fermez la fenêtre Préférences.

    Capture d’écran montrant où définir l’Éditeur de script externe sur Visual Studio 2017.

  4. Accédez àParamètres de build de fichier> et sélectionnez plateforme Windows universelle, puis cliquez sur le bouton Changer de plateforme pour appliquer votre sélection.

    Capture d’écran montrant où sélectionner Changer de plateforme.

  5. Toujours dansParamètres de build de fichier>, assurez-vous que :

    1. L’appareil cible est défini sur HoloLens

    2. Le type de build est défini sur D3D

    3. Le KIT DE DÉVELOPPEMENT LOGICIEL (SDK) est défini sur Dernier installé

    4. La version de Visual Studio est définie sur Dernière installation

    5. Générer et exécuter est défini sur Ordinateur local

    6. Enregistrez la scène et ajoutez-la à la build.

      1. Pour ce faire, sélectionnez Ajouter des scènes ouvertes. Une fenêtre d’enregistrement s’affiche.

        Capture d’écran montrant où sélectionner Ajouter des scènes ouvertes.

      2. Créez un dossier pour cette scène et toute scène future. Sélectionnez le bouton Nouveau dossier pour créer un dossier, nommez-le Scenes.

        Capture d’écran montrant où nommer le nouveau dossier.

      3. Ouvrez votre dossier Scènes nouvellement créé, puis dans le champ Nom de fichier : champ de texte, tapez MR_ComputerVisionScene, puis cliquez sur Enregistrer.

        Capture d’écran montrant où taper le nom du fichier.

        Important

        N’oubliez pas que vous devez enregistrer vos scènes Unity dans le dossier Assets , car elles doivent être associées au projet Unity. La création du dossier scènes (et d’autres dossiers similaires) est un moyen classique de structurer un projet Unity.

    7. Les autres paramètres, dans Paramètres de build, doivent être conservés par défaut pour l’instant.

  6. Dans la fenêtre Paramètres de build, cliquez sur le bouton Paramètres du lecteur. Le panneau associé s’ouvre dans l’espace où se trouve l’inspecteur.

    Capture d’écran montrant la boîte de dialogue Paramètres du lecteur.

  7. Dans ce panneau, quelques paramètres doivent être vérifiés :

    1. Sous l’onglet Autres paramètres :

      1. La version du runtimede script doit être expérimentale (équivalent.NET 4.6), ce qui déclenche la nécessité de redémarrer l’éditeur.

      2. Le serveur principal de script doit être .NET

      3. Le niveau de compatibilité de l’API doit être .NET 4.6

        Capture d’écran montrant où case activée le niveau de compatibilité de l’API.

    2. Sous l’onglet Paramètres de publication, sous Fonctionnalités, case activée :

      • InternetClient

        Capture d’écran montrant où sélectionner l’option InternetClient.

    3. Plus loin dans le panneau, dans Paramètres XR (ci-dessous Paramètres de publication), case activée Réalité virtuelle prise en charge, vérifiez que le kit sdk Windows Mixed Reality est ajouté.

      Capture d’écran montrant où ajouter Windows Mixed Reality SDK.

  8. De retour dans les paramètres de build, Unity C# Projects n’est plus grisé ; case activée la case à cocher en regard de ceci.

  9. Fermez la fenêtre Build Settings.

  10. Enregistrez votre scène et votre projet (FILE>SAVE SCENES / FILE>SAVE PROJECT).

Chapitre 3 - Importer des bibliothèques dans Unity

Important

Si vous souhaitez ignorer le composant Unity Set up de ce cours et continuer directement dans le code, n’hésitez pas à télécharger ce package Azure-MR-311.unitypackage, à l’importer dans votre projet en tant que package personnalisé, puis à partir du chapitre 5.

Pour utiliser Microsoft Graph dans Unity, vous devez utiliser la DLL Microsoft.Identity.Client . Il est possible d’utiliser le Kit de développement logiciel (SDK) Microsoft Graph. Toutefois, il faudra ajouter un package NuGet après avoir généré le projet Unity (c’est-à-dire modifier le projet après la génération). Il est considéré comme plus simple d’importer les DLL requises directement dans Unity.

Notes

Il existe actuellement un problème connu dans Unity qui nécessite la reconfiguration des plug-ins après l’importation. Ces étapes (4 à 7 dans cette section) ne seront plus nécessaires une fois le bogue résolu.

Pour importer Microsoft Graph dans votre propre projet, téléchargez le fichier MSGraph_LabPlugins.zip. Ce package a été créé avec des versions des bibliothèques qui ont été testées.

Si vous souhaitez en savoir plus sur l’ajout de DLL personnalisées à votre projet Unity, suivez ce lien.

Pour importer le package :

  1. Ajoutez le package Unity à Unity à l’aidede l’option > de menuImporter le package>personnalisé de ressources. Sélectionnez le package que vous venez de télécharger.

  2. Dans la zone Importer un package Unity qui s’affiche, vérifiez que tout ce qui se trouve sous (et y compris) Plug-ins est sélectionné.

    Capture d’écran montrant les paramètres de configuration sélectionnés sous Plug-ins.

  3. Cliquez sur le bouton Importer pour ajouter les éléments à votre projet.

  4. Accédez au dossier MSGraph sous Plug-ins dans le panneau projet et sélectionnez le plug-in appelé Microsoft.Identity.Client.

    Capture d’écran montrant le plug-in Microsoft.Identity.Client.

  5. Une fois le plug-in sélectionné, vérifiez que n’importe quelle plateforme est décochée, puis vérifiez que WSAPlayer est également décoché, puis cliquez sur Appliquer. Il s’agit simplement de vérifier que les fichiers sont configurés correctement.

    Capture d’écran montrant où confirmer que n’importe quelle plateforme et WSAPlayer ne sont pas vérifiés.

    Notes

    Le marquage de ces plug-ins les configure pour qu’ils soient utilisés uniquement dans l’éditeur Unity. Il existe un autre ensemble de DLL dans le dossier WSA qui sera utilisé après l’exportation du projet à partir d’Unity en tant qu’application Windows universelle.

  6. Ensuite, vous devez ouvrir le dossier WSA , dans le dossier MSGraph . Vous verrez une copie du fichier que vous venez de configurer. Sélectionnez le fichier, puis dans l’inspecteur :

    • Vérifiez que n’importe quelle plateforme est décochée et que seulWSAPlayer est coché.

    • Vérifiez que le KIT de développement logiciel (SDK) est défini sur UWP et que le serveur principal de script est défini sur Dot Net

    • Vérifiez que l’option Ne pas traiter est cochée.

      Capture d’écran montrant que l’option Ne pas traiter est sélectionnée.

  7. Cliquez sur Appliquer.

Chapitre 4 - Configuration de l’appareil photo

Au cours de ce chapitre, vous allez configurer la caméra principale de votre scène :

  1. Dans le panneau Hiérarchie, sélectionnez l’appareil photo principal.

  2. Une fois sélectionné, vous pourrez voir tous les composants de la caméra principale dans le panneau Inspecteur .

    1. L’objet Camera doit être nommé Main Camera (notez l’orthographe !)

    2. La balise main camera doit être définie sur MainCamera (notez l’orthographe !)

    3. Vérifiez que la position de transformation est définie sur 0, 0, 0

    4. Définir les indicateurs clairs sur Couleur unie

    5. Définissez la couleur d’arrière-plan du composant Caméra sur Noir, Alpha 0(Code hexadécimal : #000000000)

      Capture d’écran montrant où définir la couleur d’arrière-plan.

  3. La structure d’objet finale dans le panneau de hiérarchie doit être semblable à celle illustrée dans l’image ci-dessous :

    Capture d’écran montrant la structure d’objet finale dans le panneau hiérarchie.

Chapitre 5 - Créer une classe MeetingsUI

Le premier script que vous devez créer est MeetingsUI, qui est responsable de l’hébergement et du remplissage de l’interface utilisateur de l’application (message de bienvenue, instructions et détails des réunions).

Pour créer cette classe :

  1. Cliquez avec le bouton droit sur le dossier Ressources dans le volet Projet, puis sélectionnez Créer un>dossier. Nommez le dossier Scripts.

    Capture d’écran montrant où trouver le dossier Assets.Capture d’écran montrant où créer le dossier Scripts.

  2. Ouvrez le dossier Scripts , puis, dans ce dossier, cliquez avec le bouton droit sur Créer un>script C#. Nommez le script MeetingsUI.

    Capture d’écran montrant où créer le dossier MeetingsUI.

  3. Double-cliquez sur le nouveau script MeetingsUI pour l’ouvrir avec Visual Studio.

  4. Insérez les espaces de noms suivants :

    using System;
    using UnityEngine;
    
  5. À l’intérieur de la classe, insérez les variables suivantes :

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static MeetingsUI Instance;
    
        /// <summary>
        /// The 3D text of the scene
        /// </summary>
        private TextMesh _meetingDisplayTextMesh;
    
  6. Remplacez ensuite la méthode Start() et ajoutez une méthode Awake(). Ceux-ci seront appelés lorsque la classe initialise :

        /// <summary>
        /// Called on initialization
        /// </summary>
        void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        void Start ()
        {
            // Creating the text mesh within the scene
            _meetingDisplayTextMesh = CreateMeetingsDisplay();
        }
    
  7. Ajoutez les méthodes responsables de la création de l’interface utilisateur des réunions et renseignez-la avec les réunions en cours lorsque vous y êtes invité :

        /// <summary>
        /// Set the welcome message for the user
        /// </summary>
        internal void WelcomeUser(string userName)
        {
            if(!string.IsNullOrEmpty(userName))
            {
                _meetingDisplayTextMesh.text = $"Welcome {userName}";
            }
            else 
            {
                _meetingDisplayTextMesh.text = "Welcome";
            }
        }
    
        /// <summary>
        /// Set up the parameters for the UI text
        /// </summary>
        /// <returns>Returns the 3D text in the scene</returns>
        private TextMesh CreateMeetingsDisplay()
        {
            GameObject display = new GameObject();
            display.transform.localScale = new Vector3(0.03f, 0.03f, 0.03f);
            display.transform.position = new Vector3(-3.5f, 2f, 9f);
            TextMesh textMesh = display.AddComponent<TextMesh>();
            textMesh.anchor = TextAnchor.MiddleLeft;
            textMesh.alignment = TextAlignment.Left;
            textMesh.fontSize = 80;
            textMesh.text = "Welcome! \nPlease gaze at the button" +
                "\nand use the Tap Gesture to display your meetings";
    
            return textMesh;
        }
    
        /// <summary>
        /// Adds a new Meeting in the UI by chaining the existing UI text
        /// </summary>
        internal void AddMeeting(string subject, DateTime dateTime, string location)
        {
            string newText = $"\n{_meetingDisplayTextMesh.text}\n\n Meeting,\nSubject: {subject},\nToday at {dateTime},\nLocation: {location}";
    
            _meetingDisplayTextMesh.text = newText;
        }
    
  8. Supprimez la méthode Update() et enregistrez vos modifications dans Visual Studio avant de revenir à Unity.

Chapitre 6 - Créer la classe Graph

Le script suivant à créer est le script Graph . Ce script est chargé d’effectuer les appels pour authentifier l’utilisateur et récupérer les réunions planifiées pour le jour actuel à partir du calendrier de l’utilisateur.

Pour créer cette classe :

  1. Double-cliquez sur le dossier Scripts pour l’ouvrir.

  2. Cliquez avec le bouton droit dans le dossier Scripts , puis cliquez sur Créer un>script C#. Nommez le script Graph.

  3. Double-cliquez sur le script pour l’ouvrir avec Visual Studio.

  4. Insérez les espaces de noms suivants :

    using System.Collections.Generic;
    using UnityEngine;
    using Microsoft.Identity.Client;
    using System;
    using System.Threading.Tasks;
    
    #if !UNITY_EDITOR && UNITY_WSA
    using System.Net.Http;
    using System.Net.Http.Headers;
    using Windows.Storage;
    #endif
    

    Important

    Vous remarquerez que certaines parties du code de ce script sont encapsulées autour des directives de précompile, afin d’éviter les problèmes avec les bibliothèques lors de la génération de la solution Visual Studio.

  5. Supprimez les méthodes Start() et Update(), car elles ne seront pas utilisées.

  6. En dehors de la classe Graph , insérez les objets suivants, qui sont nécessaires pour désérialiser l’objet JSON représentant les réunions planifiées quotidiennes :

    /// <summary>
    /// The object hosting the scheduled meetings
    /// </summary>
    [Serializable]
    public class Rootobject
    {
        public List<Value> value;
    }
    
    [Serializable]
    public class Value
    {
        public string subject { get; set; }
        public StartTime start { get; set; }
        public Location location { get; set; }
    }
    
    [Serializable]
    public class StartTime
    {
        public string dateTime;
    
        private DateTime? _startDateTime;
        public DateTime StartDateTime
        {
            get
            {
                if (_startDateTime != null)
                    return _startDateTime.Value;
                DateTime dt;
                DateTime.TryParse(dateTime, out dt);
                _startDateTime = dt;
                return _startDateTime.Value;
            }
        }
    }
    
    [Serializable]
    public class Location
    {
        public string displayName { get; set; }
    }
    
  7. Dans la classe Graph , ajoutez les variables suivantes :

        /// <summary>
        /// Insert your Application Id here
        /// </summary>
        private string _appId = "-- Insert your Application Id here --";
    
        /// <summary>
        /// Application scopes, determine Microsoft Graph accessibility level to user account
        /// </summary>
        private IEnumerable<string> _scopes = new List<string>() { "User.Read", "Calendars.Read" };
    
        /// <summary>
        /// Microsoft Graph API, user reference
        /// </summary>
        private PublicClientApplication _client;
    
        /// <summary>
        /// Microsoft Graph API, authentication
        /// </summary>
        private AuthenticationResult _authResult;
    
    

    Notes

    Modifiez la valeur appId pour qu’elle corresponde à l’ID d’application que vous avez noté au chapitre 1, étape 4. Cette valeur doit être identique à celle affichée dans le portail d’inscription des applications, dans la page d’inscription de votre application.

  8. Dans la classe Graph , ajoutez les méthodes SignInAsync() et AquireTokenAsync(), qui invitent l’utilisateur à insérer les informations d’identification de connexion.

        /// <summary>
        /// Begin the Sign In process using Microsoft Graph Library
        /// </summary>
        internal async void SignInAsync()
        {
    #if !UNITY_EDITOR && UNITY_WSA
            // Set up Grap user settings, determine if needs auth
            ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
            string userId = localSettings.Values["UserId"] as string;
            _client = new PublicClientApplication(_appId);
    
            // Attempt authentication
            _authResult = await AcquireTokenAsync(_client, _scopes, userId);
    
            // If authentication is successful, retrieve the meetings
            if (!string.IsNullOrEmpty(_authResult.AccessToken))
            {
                // Once Auth as been completed, find the meetings for the day
                await ListMeetingsAsync(_authResult.AccessToken);
            }
    #endif
        }
    
        /// <summary>
        /// Attempt to retrieve the Access Token by either retrieving
        /// previously stored credentials or by prompting user to Login
        /// </summary>
        private async Task<AuthenticationResult> AcquireTokenAsync(
            IPublicClientApplication app, IEnumerable<string> scopes, string userId)
        {
            IUser user = !string.IsNullOrEmpty(userId) ? app.GetUser(userId) : null;
            string userName = user != null ? user.Name : "null";
    
            // Once the User name is found, display it as a welcome message
            MeetingsUI.Instance.WelcomeUser(userName);
    
            // Attempt to Log In the user with a pre-stored token. Only happens
            // in case the user Logged In with this app on this device previously
            try
            {
                _authResult = await app.AcquireTokenSilentAsync(scopes, user);
            }
            catch (MsalUiRequiredException)
            {
                // Pre-stored token not found, prompt the user to log-in 
                try
                {
                    _authResult = await app.AcquireTokenAsync(scopes);
                }
                catch (MsalException msalex)
                {
                    Debug.Log($"Error Acquiring Token: {msalex.Message}");
                    return _authResult;
                }
            }
    
            MeetingsUI.Instance.WelcomeUser(_authResult.User.Name);
    
    #if !UNITY_EDITOR && UNITY_WSA
            ApplicationData.Current.LocalSettings.Values["UserId"] = 
            _authResult.User.Identifier;
    #endif
            return _authResult;
        }
    
  9. Ajoutez les deux méthodes suivantes :

    1. BuildTodayCalendarEndpoint(), qui génère l’URI spécifiant le jour et l’intervalle de temps dans lequel les réunions planifiées sont récupérées.

    2. ListMeetingsAsync(), qui demande les réunions planifiées à partir de Microsoft Graph.

        /// <summary>
        /// Build the endpoint to retrieve the meetings for the current day.
        /// </summary>
        /// <returns>Returns the Calendar Endpoint</returns>
        public string BuildTodayCalendarEndpoint()
        {
            DateTime startOfTheDay = DateTime.Today.AddDays(0);
            DateTime endOfTheDay = DateTime.Today.AddDays(1);
            DateTime startOfTheDayUTC = startOfTheDay.ToUniversalTime();
            DateTime endOfTheDayUTC = endOfTheDay.ToUniversalTime();
    
            string todayDate = startOfTheDayUTC.ToString("o");
            string tomorrowDate = endOfTheDayUTC.ToString("o");
            string todayCalendarEndpoint = string.Format(
                "https://graph.microsoft.com/v1.0/me/calendarview?startdatetime={0}&enddatetime={1}",
                todayDate,
                tomorrowDate);
    
            return todayCalendarEndpoint;
        }
    
        /// <summary>
        /// Request all the scheduled meetings for the current day.
        /// </summary>
        private async Task ListMeetingsAsync(string accessToken)
        {
    #if !UNITY_EDITOR && UNITY_WSA
            var http = new HttpClient();
    
            http.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await http.GetAsync(BuildTodayCalendarEndpoint());
    
            var jsonResponse = await response.Content.ReadAsStringAsync();
    
            Rootobject rootObject = new Rootobject();
            try
            {
                // Parse the JSON response.
                rootObject = JsonUtility.FromJson<Rootobject>(jsonResponse);
    
                // Sort the meeting list by starting time.
                rootObject.value.Sort((x, y) => DateTime.Compare(x.start.StartDateTime, y.start.StartDateTime));
    
                // Populate the UI with the meetings.
                for (int i = 0; i < rootObject.value.Count; i++)
                {
                    MeetingsUI.Instance.AddMeeting(rootObject.value[i].subject,
                                                rootObject.value[i].start.StartDateTime.ToLocalTime(),
                                                rootObject.value[i].location.displayName);
                }
            }
            catch (Exception ex)
            {
                Debug.Log($"Error = {ex.Message}");
                return;
            }
    #endif
        }
    
  10. Vous avez maintenant terminé le script Graph . Enregistrez vos modifications dans Visual Studio avant de revenir à Unity.

Chapitre 7 - Créer le script GazeInput

Vous allez maintenant créer l’objet GazeInput. Cette classe gère et assure le suivi du regard de l’utilisateur, à l’aide d’un Raycast provenant de la caméra principale, projetant vers l’avant.

Pour créer le script :

  1. Double-cliquez sur le dossier Scripts pour l’ouvrir.

  2. Cliquez avec le bouton droit dans le dossier Scripts , puis cliquez sur Créer un>script C#. Nommez le script GazeInput.

  3. Double-cliquez sur le script pour l’ouvrir avec Visual Studio.

  4. Modifiez le code des espaces de noms pour qu’il corresponde à celui ci-dessous, en ajoutant la balise « [System.Serializable] » au-dessus de votre classe GazeInput , afin qu’elle puisse être sérialisée :

    using UnityEngine;
    
    /// <summary>
    /// Class responsible for the User's Gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    {
    
  5. Dans la classe GazeInput , ajoutez les variables suivantes :

        [Tooltip("Used to compare whether an object is to be interacted with.")]
        internal string InteractibleTag = "SignInButton";
    
        /// <summary>
        /// Length of the gaze
        /// </summary>
        internal float GazeMaxDistance = 300;
    
        /// <summary>
        /// Object currently gazed
        /// </summary>
        internal GameObject FocusedObject { get; private set; }
    
        internal GameObject oldFocusedObject { get; private set; }
    
        internal RaycastHit HitInfo { get; private set; }
    
        /// <summary>
        /// Cursor object visible in the scene
        /// </summary>
        internal GameObject Cursor { get; private set; }
    
        internal bool Hit { get; private set; }
    
        internal Vector3 Position { get; private set; }
    
        internal Vector3 Normal { get; private set; }
    
        private Vector3 _gazeOrigin;
    
        private Vector3 _gazeDirection;
    
  6. Ajoutez la méthode CreateCursor() pour créer le curseur HoloLens dans la scène, puis appelez la méthode à partir de la méthode Start() :

        /// <summary>
        /// Start method used upon initialisation.
        /// </summary>
        internal virtual void Start()
        {
            FocusedObject = null;
            Cursor = CreateCursor();
        }
    
        /// <summary>
        /// Method to create a cursor object.
        /// </summary>
        internal GameObject CreateCursor()
        {
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            newCursor.SetActive(false);
            // Remove the collider, so it doesn't block raycast.
            Destroy(newCursor.GetComponent<SphereCollider>());
            newCursor.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f);
            Material mat = new Material(Shader.Find("Diffuse"));
            newCursor.GetComponent<MeshRenderer>().material = mat;
            mat.color = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
            newCursor.SetActive(true);
    
            return newCursor;
        }
    
  7. Les méthodes suivantes activent le regard Raycast et effectuent le suivi des objets ciblés.

    /// <summary>
    /// Called every frame
    /// </summary>
    internal virtual void Update()
    {
        _gazeOrigin = Camera.main.transform.position;
    
        _gazeDirection = Camera.main.transform.forward;
    
        UpdateRaycast();
    }
    /// <summary>
    /// Reset the old focused object, stop the gaze timer, and send data if it
    /// is greater than one.
    /// </summary>
    private void ResetFocusedObject()
    {
        // Ensure the old focused object is not null.
        if (oldFocusedObject != null)
        {
            if (oldFocusedObject.CompareTag(InteractibleTag))
            {
                // Provide the 'Gaze Exited' event.
                oldFocusedObject.SendMessage("OnGazeExited", SendMessageOptions.DontRequireReceiver);
            }
        }
    }
    
        private void UpdateRaycast()
        {
            // Set the old focused gameobject.
            oldFocusedObject = FocusedObject;
            RaycastHit hitInfo;
    
            // Initialise Raycasting.
            Hit = Physics.Raycast(_gazeOrigin,
                _gazeDirection,
                out hitInfo,
                GazeMaxDistance);
                HitInfo = hitInfo;
    
            // Check whether raycast has hit.
            if (Hit == true)
            {
                Position = hitInfo.point;
                Normal = hitInfo.normal;
    
                // Check whether the hit has a collider.
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at.
                    FocusedObject = hitInfo.collider.gameObject;
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null.
                    FocusedObject = null;
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedObject = null;
    
                // Provide default position for cursor.
                Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance);
    
                // Provide a default normal.
                Normal = _gazeDirection;
            }
    
            // Lerp the cursor to the given position, which helps to stabilize the gaze.
            Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f);
    
            // Check whether the previous focused object is this same. If so, reset the focused object.
            if (FocusedObject != oldFocusedObject)
            {
                ResetFocusedObject();
                if (FocusedObject != null)
                {
                    if (FocusedObject.CompareTag(InteractibleTag))
                    {
                        // Provide the 'Gaze Entered' event.
                        FocusedObject.SendMessage("OnGazeEntered", 
                            SendMessageOptions.DontRequireReceiver);
                    }
                }
            }
        }
    
  8. Enregistrez vos modifications dans Visual Studio avant de revenir à Unity.

Chapitre 8 - Créer la classe Interactions

Vous devez maintenant créer le script Interactions , qui est responsable des opérations suivantes :

  • Gestion de l’interaction d’appui et du regard de la caméra, ce qui permet à l’utilisateur d’interagir avec le « bouton » de connexion dans la scène.

  • Création de l’objet de connexion « button » dans la scène avec laquelle l’utilisateur peut interagir.

Pour créer le script :

  1. Double-cliquez sur le dossier Scripts pour l’ouvrir.

  2. Cliquez avec le bouton droit dans le dossier Scripts , puis cliquez sur Créer un>script C#. Nommez le script Interactions.

  3. Double-cliquez sur le script pour l’ouvrir avec Visual Studio.

  4. Insérez les espaces de noms suivants :

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Modifiez l’héritage de la classe Interaction de MonoBehaviour en GazeInput.

    interactions de classe publique : MonoBehaviour

    public class Interactions : GazeInput
    
  6. Dans la classe Interaction , insérez la variable suivante :

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Remplacez la méthode Start ; Notez qu’il s’agit d’une méthode de substitution, qui appelle la méthode de classe Gaze de base. Start() est appelé lorsque la classe s’initialise, en s’inscrivant pour la reconnaissance d’entrée et en créant le bouton de connexion dans la scène :

        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        internal override void Start()
        {
            base.Start();
    
            // Register the application to recognize HoloLens user inputs
            _gestureRecognizer = new GestureRecognizer();
            _gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap);
            _gestureRecognizer.Tapped += GestureRecognizer_Tapped;
            _gestureRecognizer.StartCapturingGestures();
    
            // Add the Graph script to this object
            gameObject.AddComponent<MeetingsUI>();
            CreateSignInButton();
        }
    
  8. Ajoutez la méthode CreateSignInButton(), qui instancie le bouton de connexion dans la scène et définit ses propriétés :

        /// <summary>
        /// Create the sign in button object in the scene
        /// and sets its properties
        /// </summary>
        void CreateSignInButton()
        {
            GameObject signInButton = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    
            Material mat = new Material(Shader.Find("Diffuse"));
            signInButton.GetComponent<Renderer>().material = mat;
            mat.color = Color.blue;
    
            signInButton.transform.position = new Vector3(3.5f, 2f, 9f);
            signInButton.tag = "SignInButton";
            signInButton.AddComponent<Graph>();
        }
    
  9. Ajoutez la méthode GestureRecognizer_Tapped(), qui doit répondre à l’événement Utilisateur Tap .

        /// <summary>
        /// Detects the User Tap Input
        /// </summary>
        private void GestureRecognizer_Tapped(TappedEventArgs obj)
        {
            if(base.FocusedObject != null)
            {
                Debug.Log($"TAP on {base.FocusedObject.name}");
                base.FocusedObject.SendMessage("SignInAsync", SendMessageOptions.RequireReceiver);
            }
        }
    
  10. Supprimez la méthode Update(), puis enregistrez vos modifications dans Visual Studio avant de revenir à Unity.

Chapitre 9 - Configurer les références de script

Dans ce chapitre, vous devez placer le script Interactions sur la caméra principale. Ce script gère ensuite le placement des autres scripts là où ils doivent l’être.

  • Dans le dossier Scripts du panneau projet, faites glisser le script Interactions vers l’objet Main Camera , comme illustré ci-dessous.

    Capture d’écran montrant où faire glisser le script Interactions.

Chapitre 10 - Configuration de la balise

Le code qui gère le regard utilise la balise SignInButton pour identifier l’objet avec lequel l’utilisateur interagira pour se connecter à Microsoft Graph.

Pour créer la balise :

  1. Dans l’éditeur Unity, cliquez sur la caméra principale dans le panneau hiérarchie.

  2. Dans le panneau Inspecteur, cliquez sur la baliseMainCamera pour ouvrir une liste déroulante. Cliquez sur Ajouter une balise...

    Capture d’écran mettant en évidence l’option Ajouter une balise... Option.

  3. Cliquez sur le bouton +.

    Capture d’écran montrant le bouton + .

  4. Écrivez le nom de la balise en tant que SignInButton , puis cliquez sur Enregistrer.

    Capture d’écran montrant où ajouter le nom de la balise SignInButton.

Chapitre 11 : Générer le projet Unity dans UWP

Tout ce qui est nécessaire pour la section Unity de ce projet est maintenant terminé. Il est donc temps de le générer à partir d’Unity.

  1. Accédez à Paramètres de build (Paramètres de buildde fichier>).

    Capture d’écran montrant la boîte de dialogue Paramètres de build.

  2. Si ce n’est pas déjà le cas, cochez Projets Unity C#.

  3. Cliquez sur Générer. Unity lance une fenêtre Explorateur de fichiers, dans laquelle vous devez créer, puis sélectionner un dossier dans lequel générer l’application. Créez ce dossier maintenant et nommez-le Application. Ensuite, avec le dossier Application sélectionné, cliquez sur Sélectionner un dossier.

  4. Unity commence à générer votre projet dans le dossier Application .

  5. Une fois la génération terminée (cela peut prendre un certain temps), Unity ouvre une fenêtre Explorateur de fichiers à l’emplacement de votre build (case activée votre barre des tâches, car elle n’apparaît peut-être pas toujours au-dessus de vos fenêtres, mais vous informe de l’ajout d’une nouvelle fenêtre).

Chapitre 12 - Déployer sur HoloLens

Pour déployer sur HoloLens :

  1. Vous aurez besoin de l’adresse IP de votre HoloLens (pour le déploiement à distance) et de vous assurer que votre HoloLens est en mode développeur. Pour ce faire :

    1. Lorsque vous portez votre HoloLens, ouvrez les Paramètres.

    2. Accédez à Network & Internet>Wi-Fi>Advanced Options

    3. Notez l’adresse IPv4 .

    4. Ensuite, revenez à Paramètres, puis à Mettre à jour & sécurité>pour les développeurs

    5. Définissez Mode développeur activé.

  2. Accédez à votre nouvelle build Unity (le dossier App ) et ouvrez le fichier solution avec Visual Studio.

  3. Dans configuration de la solution , sélectionnez Déboguer.

  4. Dans Plateforme de solution, sélectionnez x86, Ordinateur distant. Vous serez invité à insérer l’adresse IP d’un appareil distant (holoLens, dans ce cas, que vous avez noté).

    Capture d’écran montrant où sélectionner x86 et Ordinateur distant.

  5. Accédez au menu Générer et cliquez sur Déployer la solution pour charger une version test de l’application sur votre HoloLens.

  6. Votre application doit maintenant apparaître dans la liste des applications installées sur votre HoloLens, prête à être lancée !

Votre application Microsoft Graph HoloLens

Félicitations, vous avez créé une application de réalité mixte qui tire parti de Microsoft Graph pour lire et afficher les données du calendrier utilisateur.

Capture d’écran montrant l’application de réalité mixte terminée.

Exercices bonus

Exercice 1

Utiliser Microsoft Graph pour afficher d’autres informations sur l’utilisateur

  • Adresse e-mail de l’utilisateur / numéro de téléphone / image de profil

Exercice 1

Implémentez le contrôle vocal pour naviguer dans l’interface utilisateur de Microsoft Graph.