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.

316 lines
7.7 KiB

  1. namespace Oculus.Platform.Samples.VrVoiceChat
  2. {
  3. using UnityEngine;
  4. using System;
  5. using System.Collections.Generic;
  6. using Oculus.Platform;
  7. using Oculus.Platform.Models;
  8. // Helper class to manage Room creation, membership and invites.
  9. // Rooms are a mechanism to help Oculus users create a shared experience.
  10. // Users can only be in one Room at a time. If the Owner of a room
  11. // leaves, then ownership is transferred to some other member.
  12. // Here we use rooms to create the notion of a 'call' to help us
  13. // invite a Friend and establish a VOIP and P2P connection.
  14. public class RoomManager
  15. {
  16. // the ID of the Room that I'm in
  17. private ulong m_roomID;
  18. // the other User in the Room
  19. private User m_remoteUser;
  20. // how often I should poll for invites
  21. private static readonly float INVITE_POLL_FREQ_SECONDS = 5.0f;
  22. // the next time I should poll Oculus Platform for valid Room Invite requests
  23. private float m_nextPollTime;
  24. public struct Invite
  25. {
  26. public readonly ulong RoomID;
  27. public readonly string OwnerID;
  28. public Invite(ulong roomID, string owner)
  29. {
  30. this.RoomID = roomID;
  31. this.OwnerID = owner;
  32. }
  33. }
  34. // cached list of rooms that I've been invited to and I'm waiting
  35. // for more information about
  36. private HashSet<ulong> m_pendingRoomRequests;
  37. // accumulation list of room invites and the room owner
  38. private List<Invite> m_invites;
  39. public RoomManager()
  40. {
  41. Rooms.SetRoomInviteAcceptedNotificationCallback(LaunchedFromAcceptingInviteCallback);
  42. Rooms.SetUpdateNotificationCallback(RoomUpdateCallback);
  43. }
  44. public ulong RemoteUserID
  45. {
  46. get
  47. {
  48. return m_remoteUser != null ? m_remoteUser.ID : 0;
  49. }
  50. }
  51. public String RemoteOculusID
  52. {
  53. get
  54. {
  55. return m_remoteUser != null ? m_remoteUser.OculusID : String.Empty;
  56. }
  57. }
  58. #region Launched Application from Accepting Invite
  59. // Callback to check whether the User accepted the invite as
  60. // a notification which caused the Application to launch. If so, then
  61. // we know we need to try to join that room.
  62. void LaunchedFromAcceptingInviteCallback(Message<string> msg)
  63. {
  64. if (msg.IsError)
  65. {
  66. PlatformManager.TerminateWithError(msg);
  67. return;
  68. }
  69. Debug.Log("Launched Invite to join Room: " + msg.Data);
  70. m_roomID = Convert.ToUInt64(msg.GetString());
  71. }
  72. // Check to see if the App was launched by accepting the Notication from the main Oculus app.
  73. // If so, we can directly join that room. (If it's still available.)
  74. public bool CheckForLaunchInvite()
  75. {
  76. if (m_roomID != 0)
  77. {
  78. JoinExistingRoom(m_roomID);
  79. return true;
  80. }
  81. else
  82. {
  83. return false;
  84. }
  85. }
  86. #endregion
  87. #region Create a Room and Invite Friend(s) from the Oculus Universal Menu
  88. public void CreateRoomAndLaunchInviteMenu()
  89. {
  90. Rooms.CreateAndJoinPrivate(RoomJoinPolicy.InvitedUsers, 2, true)
  91. .OnComplete(CreateAndJoinPrivateRoomCallback);
  92. }
  93. void CreateAndJoinPrivateRoomCallback(Message<Room> msg)
  94. {
  95. if (msg.IsError)
  96. {
  97. PlatformManager.TerminateWithError(msg);
  98. return;
  99. }
  100. m_roomID = msg.Data.ID;
  101. m_remoteUser = null;
  102. PlatformManager.TransitionToState(PlatformManager.State.WAITING_FOR_ANSWER);
  103. // launch the Room Invite workflow in the Oculus Univeral Menu
  104. Rooms.LaunchInvitableUserFlow(m_roomID).OnComplete(OnLaunchInviteWorkflowComplete);
  105. }
  106. void OnLaunchInviteWorkflowComplete(Message msg)
  107. {
  108. if (msg.IsError)
  109. {
  110. PlatformManager.TerminateWithError(msg);
  111. return;
  112. }
  113. }
  114. #endregion
  115. #region Polling for Invites
  116. public bool ShouldPollInviteList
  117. {
  118. get
  119. {
  120. return m_pendingRoomRequests == null && Time.time >= m_nextPollTime;
  121. }
  122. }
  123. public void UpdateActiveInvitesList()
  124. {
  125. m_nextPollTime = Time.time + INVITE_POLL_FREQ_SECONDS;
  126. m_pendingRoomRequests = new HashSet<ulong>();
  127. m_invites = new List<Invite>();
  128. Notifications.GetRoomInviteNotifications().OnComplete(GetRoomInviteNotificationsCallback);
  129. }
  130. // task 13572454: add the type to callback definition
  131. void GetRoomInviteNotificationsCallback(Message msg_untyped)
  132. {
  133. Message<RoomInviteNotificationList> msg = (Message<RoomInviteNotificationList>)msg_untyped;
  134. if (msg.IsError)
  135. {
  136. PlatformManager.TerminateWithError(msg);
  137. return;
  138. }
  139. // loop over all the rooms we're invited to and request more info
  140. foreach (RoomInviteNotification invite in msg.Data)
  141. {
  142. m_pendingRoomRequests.Add(invite.RoomID);
  143. Rooms.Get(invite.RoomID).OnComplete(GetRoomInfoCallback);
  144. }
  145. if (msg.Data.Count == 0)
  146. {
  147. m_pendingRoomRequests = null;
  148. PlatformManager.SetActiveInvites(m_invites);
  149. }
  150. }
  151. void GetRoomInfoCallback(Message<Room> msg)
  152. {
  153. if (msg.IsError)
  154. {
  155. PlatformManager.TerminateWithError(msg);
  156. return;
  157. }
  158. if (msg.Data.OwnerOptional != null)
  159. {
  160. Invite invite = new Invite(msg.Data.ID, msg.Data.OwnerOptional.OculusID);
  161. m_pendingRoomRequests.Remove(invite.RoomID);
  162. // make sure the room still looks usable
  163. // (e.g. they aren't currently talking to someone)
  164. if (msg.Data.UsersOptional != null && msg.Data.UsersOptional.Count == 1)
  165. {
  166. m_invites.Add(invite);
  167. }
  168. }
  169. // once we're received all the room info, let the platform update
  170. // its display
  171. if (m_pendingRoomRequests.Count == 0)
  172. {
  173. m_pendingRoomRequests = null;
  174. PlatformManager.SetActiveInvites(m_invites);
  175. }
  176. }
  177. #endregion
  178. #region Accept Invite
  179. public void JoinExistingRoom(ulong roomID)
  180. {
  181. Rooms.Join(roomID, true).OnComplete(JoinRoomCallback);
  182. }
  183. void JoinRoomCallback(Message<Room> msg)
  184. {
  185. if (msg.IsError)
  186. {
  187. // is reasonable if caller called more than 1 person, and I didn't answer first
  188. return;
  189. }
  190. string oculusOwnerID = msg.Data.OwnerOptional != null ? msg.Data.OwnerOptional.OculusID : "";
  191. int numUsers = msg.Data.UsersOptional != null ? msg.Data.UsersOptional.Count : 0;
  192. Debug.LogFormat("Joined room: {0} owner: {1} count: ",
  193. msg.Data.ID, oculusOwnerID, numUsers);
  194. m_roomID = msg.Data.ID;
  195. // if the caller left while I was in the process of joining, just hangup
  196. if (msg.Data.UsersOptional == null || msg.Data.UsersOptional.Count != 2)
  197. {
  198. PlatformManager.TransitionToState(PlatformManager.State.HANGUP);
  199. }
  200. else
  201. {
  202. foreach (User user in msg.Data.UsersOptional)
  203. {
  204. if (user.ID != PlatformManager.MyID)
  205. {
  206. m_remoteUser = user;
  207. }
  208. }
  209. PlatformManager.TransitionToState(PlatformManager.State.CONNECTED_IN_A_ROOM);
  210. }
  211. // update the invite list sooner
  212. m_nextPollTime = Time.time;
  213. }
  214. #endregion
  215. #region Room Updates
  216. void RoomUpdateCallback(Message<Room> msg)
  217. {
  218. if (msg.IsError)
  219. {
  220. PlatformManager.TerminateWithError(msg);
  221. return;
  222. }
  223. string oculusOwnerID = msg.Data.OwnerOptional != null ? msg.Data.OwnerOptional.OculusID : "";
  224. int numUsers = msg.Data.UsersOptional != null ? msg.Data.UsersOptional.Count : 0;
  225. Debug.LogFormat("Room {0} Update: {1} owner: {2} count: ",
  226. msg.Data.ID, oculusOwnerID, numUsers);
  227. // if the Room count is not 2 then the other party has left.
  228. // We'll just hangup the connection here.
  229. // If the other User created then room, ownership would switch to me.
  230. if (msg.Data.UsersOptional == null || msg.Data.UsersOptional.Count != 2)
  231. {
  232. PlatformManager.TransitionToState(PlatformManager.State.HANGUP);
  233. }
  234. else
  235. {
  236. foreach (User user in msg.Data.UsersOptional)
  237. {
  238. if (user.ID != PlatformManager.MyID)
  239. {
  240. m_remoteUser = user;
  241. }
  242. }
  243. PlatformManager.TransitionToState(PlatformManager.State.CONNECTED_IN_A_ROOM);
  244. }
  245. }
  246. #endregion
  247. #region Room Exit
  248. public void LeaveCurrentRoom()
  249. {
  250. if (m_roomID != 0)
  251. {
  252. Rooms.Leave(m_roomID);
  253. m_roomID = 0;
  254. m_remoteUser = null;
  255. }
  256. PlatformManager.TransitionToState(PlatformManager.State.WAITING_TO_CALL_OR_ANSWER);
  257. }
  258. #endregion
  259. }
  260. }