namespace Oculus.Platform.Samples.VrVoiceChat { using UnityEngine; using UnityEngine.UI; using System.Collections.Generic; using Oculus.Platform; using Oculus.Platform.Models; // This class coordinates communication with the Oculus Platform // Service running in your device. public class PlatformManager : MonoBehaviour { // the game object to build the invite list in [SerializeField] private GameObject m_invitesList = null; // Button to create for the user to answer an invite call [SerializeField] private GameObject m_invitePrefab = null; // State transition sets the background color as a visual status indication [SerializeField] private Camera m_camera = null; // GameObject that represents the Head of the remote Avatar [SerializeField] private GameObject m_remoteHead = null; private State m_currentState; private static PlatformManager s_instance = null; private RoomManager m_roomManager; private P2PManager m_p2pManager; private VoipManager m_voipManager; // my Application-scoped Oculus ID private ulong m_myID; // my Oculus user name private string m_myOculusID; void Update() { // occasionally poll for new call invites if (m_roomManager.ShouldPollInviteList) { m_roomManager.UpdateActiveInvitesList(); } // occasionally send my transform to my interlocutor if (m_p2pManager.ShouldSendHeadUpdate) { m_p2pManager.SendHeadTransform(m_camera.transform); } // estimate the remote avatar transforms from the most recent network update m_p2pManager.GetRemoteHeadTransform(m_remoteHead.transform); } #region Initialization and Shutdown void Awake() { // make sure only one instance of this manager ever exists if (s_instance != null) { Destroy(gameObject); return; } s_instance = this; DontDestroyOnLoad(gameObject); TransitionToState(State.INITIALIZING); Core.Initialize(); m_roomManager = new RoomManager(); m_p2pManager = new P2PManager(m_remoteHead.transform); m_voipManager = new VoipManager(m_remoteHead); } void Start () { // First thing we should do is perform an entitlement check to make sure // we successfully connected to the Oculus Platform Service. Entitlements.IsUserEntitledToApplication().OnComplete(IsEntitledCallback); } void IsEntitledCallback(Message msg) { if (msg.IsError) { TerminateWithError(msg); return; } // Next get the identity of the user that launched the Application. Users.GetLoggedInUser().OnComplete(GetLoggedInUserCallback); } void GetLoggedInUserCallback(Message msg) { if (msg.IsError) { TerminateWithError(msg); return; } m_myID = msg.Data.ID; m_myOculusID = msg.Data.OculusID; TransitionToState(State.WAITING_TO_CALL_OR_ANSWER); // If the user launched the app by accepting the notification, then we want to // join that room. Otherwise, start polling for invites. m_roomManager.CheckForLaunchInvite(); } void OnApplicationQuit() { m_roomManager.LeaveCurrentRoom(); m_p2pManager.Disconnect(); m_voipManager.Disconnect(); } // For most errors we terminate the Application since this example doesn't make // sense if the user is disconnected. public static void TerminateWithError(Message msg) { Debug.Log("Error: " + msg.GetError().Message); UnityEngine.Application.Quit(); } #endregion #region Properties public static State CurrentState { get { return s_instance.m_currentState; } } public static ulong MyID { get { if (s_instance != null) { return s_instance.m_myID; } else { return 0; } } } public static string MyOculusID { get { if (s_instance != null && s_instance.m_myOculusID != null) { return s_instance.m_myOculusID; } else { return string.Empty; } } } #endregion #region Button Clicks public void CallFriendOnClick() { if (CurrentState == State.WAITING_TO_CALL_OR_ANSWER) { m_roomManager.CreateRoomAndLaunchInviteMenu(); } } public void HangupOnClick() { m_roomManager.LeaveCurrentRoom(); } public void QuitOnClick() { UnityEngine.Application.Quit(); } public static void AnswerCallOnClick(ulong roomID) { if (s_instance) { s_instance.m_roomManager.JoinExistingRoom(roomID); } } #endregion #region State Management public enum State { // loading platform library, checking application entitlement, // getting the local user info INITIALIZING, // waiting on the user to invite a friend to chat, or // accept an invite sent to them WAITING_TO_CALL_OR_ANSWER, // in this state we've create a room, and hopefully // sent some invites, and we're waiting for a response WAITING_FOR_ANSWER, // we're in a room as the caller or the callee CONNECTED_IN_A_ROOM, // shutdown any connections and leave the current room HANGUP, }; public static void TransitionToState(State newState) { Debug.LogFormat("State {0} -> {1}", s_instance.m_currentState, newState); if (s_instance && s_instance.m_currentState != newState) { s_instance.m_currentState = newState; // state transition logic switch (newState) { case State.HANGUP: s_instance.m_roomManager.LeaveCurrentRoom(); s_instance.m_p2pManager.Disconnect(); s_instance.m_voipManager.Disconnect(); break; case State.WAITING_TO_CALL_OR_ANSWER: break; case State.CONNECTED_IN_A_ROOM: s_instance.m_p2pManager.ConnectTo(s_instance.m_roomManager.RemoteUserID); s_instance.m_voipManager.ConnectTo(s_instance.m_roomManager.RemoteUserID); break; } } // set the background color as a visual aid to the connection status SetBackgroundColorForState(); } public static void SetBackgroundColorForState() { switch (s_instance.m_currentState) { case State.INITIALIZING: case State.HANGUP: s_instance.m_camera.backgroundColor = Color.black; break; case State.WAITING_TO_CALL_OR_ANSWER: s_instance.m_camera.backgroundColor = new Color(0f, 0f, .3f); break; case State.WAITING_FOR_ANSWER: s_instance.m_camera.backgroundColor = new Color(0, 0, .6f); break; case State.CONNECTED_IN_A_ROOM: float red = s_instance.m_p2pManager.Connected ? 1.0f : 0; float green = s_instance.m_voipManager.Connected ? 1.0f : 0; s_instance.m_camera.backgroundColor = new Color(red, green, 1.0f); break; } } public static void SetActiveInvites(List invites) { if (s_instance && s_instance.m_invitesList && s_instance.m_invitePrefab) { // first remove all existing Invites foreach (Transform child in s_instance.m_invitesList.transform) { Destroy(child.gameObject); } foreach (var invite in invites) { GameObject button = Instantiate(s_instance.m_invitePrefab) as GameObject; button.GetComponentInChildren().text = invite.OwnerID; button.name = invite.RoomID.ToString(); button.GetComponent