Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
7.2 KiB

  1. namespace Oculus.Platform.Samples.VrVoiceChat
  2. {
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using System.Collections.Generic;
  6. using Oculus.Platform;
  7. using Oculus.Platform.Models;
  8. // This class coordinates communication with the Oculus Platform
  9. // Service running in your device.
  10. public class PlatformManager : MonoBehaviour
  11. {
  12. // the game object to build the invite list in
  13. [SerializeField] private GameObject m_invitesList = null;
  14. // Button to create for the user to answer an invite call
  15. [SerializeField] private GameObject m_invitePrefab = null;
  16. // State transition sets the background color as a visual status indication
  17. [SerializeField] private Camera m_camera = null;
  18. // GameObject that represents the Head of the remote Avatar
  19. [SerializeField] private GameObject m_remoteHead = null;
  20. private State m_currentState;
  21. private static PlatformManager s_instance = null;
  22. private RoomManager m_roomManager;
  23. private P2PManager m_p2pManager;
  24. private VoipManager m_voipManager;
  25. // my Application-scoped Oculus ID
  26. private ulong m_myID;
  27. // my Oculus user name
  28. private string m_myOculusID;
  29. void Update()
  30. {
  31. // occasionally poll for new call invites
  32. if (m_roomManager.ShouldPollInviteList)
  33. {
  34. m_roomManager.UpdateActiveInvitesList();
  35. }
  36. // occasionally send my transform to my interlocutor
  37. if (m_p2pManager.ShouldSendHeadUpdate)
  38. {
  39. m_p2pManager.SendHeadTransform(m_camera.transform);
  40. }
  41. // estimate the remote avatar transforms from the most recent network update
  42. m_p2pManager.GetRemoteHeadTransform(m_remoteHead.transform);
  43. }
  44. #region Initialization and Shutdown
  45. void Awake()
  46. {
  47. // make sure only one instance of this manager ever exists
  48. if (s_instance != null) {
  49. Destroy(gameObject);
  50. return;
  51. }
  52. s_instance = this;
  53. DontDestroyOnLoad(gameObject);
  54. TransitionToState(State.INITIALIZING);
  55. Core.Initialize();
  56. m_roomManager = new RoomManager();
  57. m_p2pManager = new P2PManager(m_remoteHead.transform);
  58. m_voipManager = new VoipManager(m_remoteHead);
  59. }
  60. void Start ()
  61. {
  62. // First thing we should do is perform an entitlement check to make sure
  63. // we successfully connected to the Oculus Platform Service.
  64. Entitlements.IsUserEntitledToApplication().OnComplete(IsEntitledCallback);
  65. }
  66. void IsEntitledCallback(Message msg)
  67. {
  68. if (msg.IsError)
  69. {
  70. TerminateWithError(msg);
  71. return;
  72. }
  73. // Next get the identity of the user that launched the Application.
  74. Users.GetLoggedInUser().OnComplete(GetLoggedInUserCallback);
  75. }
  76. void GetLoggedInUserCallback(Message<User> msg)
  77. {
  78. if (msg.IsError)
  79. {
  80. TerminateWithError(msg);
  81. return;
  82. }
  83. m_myID = msg.Data.ID;
  84. m_myOculusID = msg.Data.OculusID;
  85. TransitionToState(State.WAITING_TO_CALL_OR_ANSWER);
  86. // If the user launched the app by accepting the notification, then we want to
  87. // join that room. Otherwise, start polling for invites.
  88. m_roomManager.CheckForLaunchInvite();
  89. }
  90. void OnApplicationQuit()
  91. {
  92. m_roomManager.LeaveCurrentRoom();
  93. m_p2pManager.Disconnect();
  94. m_voipManager.Disconnect();
  95. }
  96. // For most errors we terminate the Application since this example doesn't make
  97. // sense if the user is disconnected.
  98. public static void TerminateWithError(Message msg)
  99. {
  100. Debug.Log("Error: " + msg.GetError().Message);
  101. UnityEngine.Application.Quit();
  102. }
  103. #endregion
  104. #region Properties
  105. public static State CurrentState
  106. {
  107. get
  108. {
  109. return s_instance.m_currentState;
  110. }
  111. }
  112. public static ulong MyID
  113. {
  114. get
  115. {
  116. if (s_instance != null)
  117. {
  118. return s_instance.m_myID;
  119. }
  120. else
  121. {
  122. return 0;
  123. }
  124. }
  125. }
  126. public static string MyOculusID
  127. {
  128. get
  129. {
  130. if (s_instance != null && s_instance.m_myOculusID != null)
  131. {
  132. return s_instance.m_myOculusID;
  133. }
  134. else
  135. {
  136. return string.Empty;
  137. }
  138. }
  139. }
  140. #endregion
  141. #region Button Clicks
  142. public void CallFriendOnClick()
  143. {
  144. if (CurrentState == State.WAITING_TO_CALL_OR_ANSWER)
  145. {
  146. m_roomManager.CreateRoomAndLaunchInviteMenu();
  147. }
  148. }
  149. public void HangupOnClick()
  150. {
  151. m_roomManager.LeaveCurrentRoom();
  152. }
  153. public void QuitOnClick()
  154. {
  155. UnityEngine.Application.Quit();
  156. }
  157. public static void AnswerCallOnClick(ulong roomID)
  158. {
  159. if (s_instance)
  160. {
  161. s_instance.m_roomManager.JoinExistingRoom(roomID);
  162. }
  163. }
  164. #endregion
  165. #region State Management
  166. public enum State
  167. {
  168. // loading platform library, checking application entitlement,
  169. // getting the local user info
  170. INITIALIZING,
  171. // waiting on the user to invite a friend to chat, or
  172. // accept an invite sent to them
  173. WAITING_TO_CALL_OR_ANSWER,
  174. // in this state we've create a room, and hopefully
  175. // sent some invites, and we're waiting for a response
  176. WAITING_FOR_ANSWER,
  177. // we're in a room as the caller or the callee
  178. CONNECTED_IN_A_ROOM,
  179. // shutdown any connections and leave the current room
  180. HANGUP,
  181. };
  182. public static void TransitionToState(State newState)
  183. {
  184. Debug.LogFormat("State {0} -> {1}", s_instance.m_currentState, newState);
  185. if (s_instance && s_instance.m_currentState != newState)
  186. {
  187. s_instance.m_currentState = newState;
  188. // state transition logic
  189. switch (newState)
  190. {
  191. case State.HANGUP:
  192. s_instance.m_roomManager.LeaveCurrentRoom();
  193. s_instance.m_p2pManager.Disconnect();
  194. s_instance.m_voipManager.Disconnect();
  195. break;
  196. case State.WAITING_TO_CALL_OR_ANSWER:
  197. break;
  198. case State.CONNECTED_IN_A_ROOM:
  199. s_instance.m_p2pManager.ConnectTo(s_instance.m_roomManager.RemoteUserID);
  200. s_instance.m_voipManager.ConnectTo(s_instance.m_roomManager.RemoteUserID);
  201. break;
  202. }
  203. }
  204. // set the background color as a visual aid to the connection status
  205. SetBackgroundColorForState();
  206. }
  207. public static void SetBackgroundColorForState()
  208. {
  209. switch (s_instance.m_currentState)
  210. {
  211. case State.INITIALIZING:
  212. case State.HANGUP:
  213. s_instance.m_camera.backgroundColor = Color.black;
  214. break;
  215. case State.WAITING_TO_CALL_OR_ANSWER:
  216. s_instance.m_camera.backgroundColor = new Color(0f, 0f, .3f);
  217. break;
  218. case State.WAITING_FOR_ANSWER:
  219. s_instance.m_camera.backgroundColor = new Color(0, 0, .6f);
  220. break;
  221. case State.CONNECTED_IN_A_ROOM:
  222. float red = s_instance.m_p2pManager.Connected ? 1.0f : 0;
  223. float green = s_instance.m_voipManager.Connected ? 1.0f : 0;
  224. s_instance.m_camera.backgroundColor = new Color(red, green, 1.0f);
  225. break;
  226. }
  227. }
  228. public static void SetActiveInvites(List<RoomManager.Invite> invites)
  229. {
  230. if (s_instance && s_instance.m_invitesList && s_instance.m_invitePrefab)
  231. {
  232. // first remove all existing Invites
  233. foreach (Transform child in s_instance.m_invitesList.transform)
  234. {
  235. Destroy(child.gameObject);
  236. }
  237. foreach (var invite in invites)
  238. {
  239. GameObject button = Instantiate(s_instance.m_invitePrefab) as GameObject;
  240. button.GetComponentInChildren<Text>().text = invite.OwnerID;
  241. button.name = invite.RoomID.ToString();
  242. button.GetComponent<Button>().onClick.AddListener(
  243. () => PlatformManager.AnswerCallOnClick(invite.RoomID));
  244. button.transform.SetParent(s_instance.m_invitesList.transform, false);
  245. }
  246. }
  247. }
  248. #endregion
  249. }
  250. }