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.

395 lines
11 KiB

  1. // Uncomment this if you have the Touch controller classes in your project
  2. //#define USE_OVRINPUT
  3. using Oculus.Platform;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEngine.UI;
  7. /**
  8. * This class shows a very simple way to integrate setting the Rich Presence
  9. * with a destination and how to respond to a user's app launch details that
  10. * include the destination they wish to travel to.
  11. */
  12. public class RichPresenceSample : MonoBehaviour
  13. {
  14. /**
  15. * Sets extra fields on the rich presence
  16. */
  17. // Optional message to override the deep-link message set in the developer
  18. // dashboard. This is where you can specify the ID for a room, party,
  19. // matchmaking pool or group server. There should be no whitespaces.
  20. public string DeeplinkMessageOverride;
  21. // A boolean to indicate whether the destination is joinable. You can check
  22. // the current capacity against the max capacity to determine whether the room
  23. // is joinable.
  24. public bool IsJoinable;
  25. // A boolean to indicate whether the current user is idling in the app.
  26. public bool IsIdle;
  27. // The current capacity at that destination. Used for displaying with the
  28. // extra context when it's set to RichPresenceExtraContext.CurrentCapacity
  29. public uint CurrentCapacity;
  30. // The maximum capacity of the destination. Can be used with current capacity
  31. // to see if a user can join. For example, when used with a room, set the max
  32. // capacity of the destination to the max capacity of the room.
  33. // Used for displaying with the extra context when it's set to
  34. // RichPresenceExtraContext.CurrentCapacity
  35. public uint MaxCapacity;
  36. // The time the current match starts or started. Used for displaying with the
  37. // extra context when it's set to RichPresenceExtraContext.StartedAgo
  38. public System.DateTime StartTime = System.DateTime.Now;
  39. // The time the current match ends. Used for displaying with the
  40. // extra context when it's set to RichPresenceExtraContext.EndingIn
  41. public System.DateTime EndTime = System.DateTime.Now.AddHours(2);
  42. // Extra information to set the user’s presence correctly. This should give
  43. // more insight for people to decided whether or not to join the user.
  44. public RichPresenceExtraContext ExtraContext = RichPresenceExtraContext.LookingForAMatch;
  45. public Text InVRConsole;
  46. public Text DestinationsConsole;
  47. private List<string> DestinationAPINames = new List<string>();
  48. private ulong LoggedInUserID = 0;
  49. // Start is called before the first frame update
  50. void Start()
  51. {
  52. UpdateConsole("Init Oculus Platform SDK...");
  53. Core.AsyncInitialize().OnComplete(message => {
  54. if (message.IsError)
  55. {
  56. // Init failed, nothing will work
  57. UpdateConsole(message.GetError().Message);
  58. }
  59. else
  60. {
  61. /**
  62. * Get the deeplink message when the app starts up
  63. */
  64. UpdateConsole("Init complete!\n" + GetAppLaunchDetails());
  65. /**
  66. * Get and cache the Logged in User ID for future queries
  67. */
  68. Users.GetLoggedInUser().OnComplete(OnLoggedInUser);
  69. /**
  70. * Get the list of destinations defined for this app from the developer portal
  71. */
  72. RichPresence.GetDestinations().OnComplete(OnGetDestinations);
  73. /**
  74. * Listen for future deeplink message changes that might come in
  75. */
  76. ApplicationLifecycle.SetLaunchIntentChangedNotificationCallback(OnLaunchIntentChangeNotif);
  77. }
  78. });
  79. }
  80. /**
  81. * Setting the rich presence
  82. */
  83. void SetPresence()
  84. {
  85. var options = new RichPresenceOptions();
  86. // Only Destination API Name is required
  87. options.SetApiName(DestinationAPINames[DestinationIndex]);
  88. // Override the deeplink message if you like, otherwise it will use the one found in the destination
  89. if (!string.IsNullOrEmpty(DeeplinkMessageOverride))
  90. {
  91. options.SetDeeplinkMessageOverride(DeeplinkMessageOverride);
  92. }
  93. // Set is Joinable to let other players deeplink and join this user via the presence
  94. options.SetIsJoinable(IsJoinable);
  95. // Set if the user is idle
  96. options.SetIsIdle(IsIdle);
  97. // Used when displaying the current to max capacity on the user's presence
  98. options.SetCurrentCapacity(CurrentCapacity);
  99. options.SetMaxCapacity(MaxCapacity);
  100. // Used to display how long since this start / when will this end
  101. options.SetStartTime(StartTime);
  102. options.SetEndTime(EndTime);
  103. // Used to display extra info like the capacity, start/end times, or looking for a match
  104. options.SetExtraContext(ExtraContext);
  105. UpdateConsole("Setting Rich Presence to " + DestinationAPINames[DestinationIndex] + " ...");
  106. // Here we are setting the rich presence then fetching it after we successfully set it
  107. RichPresence.Set(options).OnComplete(message => {
  108. if (message.IsError)
  109. {
  110. UpdateConsole(message.GetError().Message);
  111. }
  112. else
  113. {
  114. // Note that Users.GetLoggedInUser() does not do a server fetch and will
  115. // not get an updated presence status
  116. Users.Get(LoggedInUserID).OnComplete(message2 =>
  117. {
  118. if (message2.IsError)
  119. {
  120. UpdateConsole("Success! But rich presence is unknown!");
  121. }
  122. else
  123. {
  124. UpdateConsole("Rich Presence set to:\n" + message2.Data.Presence + "\n" + message2.Data.PresenceDeeplinkMessage + "\n" + message2.Data.PresenceDestinationApiName);
  125. }
  126. });
  127. }
  128. });
  129. }
  130. /**
  131. * Clearing the rich presence
  132. */
  133. void ClearPresence()
  134. {
  135. UpdateConsole("Clearing Rich Presence...");
  136. RichPresence.Clear().OnComplete(message => {
  137. if (message.IsError)
  138. {
  139. UpdateConsole(message.GetError().Message);
  140. }
  141. else
  142. {
  143. // Clearing the rich presence then fetching the user's presence afterwards
  144. Users.Get(LoggedInUserID).OnComplete(message2 =>
  145. {
  146. if (message2.IsError)
  147. {
  148. UpdateConsole("Rich Presence cleared! But rich presence is unknown!");
  149. }
  150. else
  151. {
  152. UpdateConsole("Rich Presence cleared!\n" + message2.Data.Presence + "\n");
  153. }
  154. });
  155. }
  156. });
  157. }
  158. /**
  159. * Getting the deeplink information off the app launch details. When a user requests
  160. * to travel to a destination from outside your app, their request will be found here
  161. * Get the info to bring the user to the expected destination.
  162. */
  163. string GetAppLaunchDetails()
  164. {
  165. var launchDetails = ApplicationLifecycle.GetLaunchDetails();
  166. // The other users this user expect to see after traveling to the destination
  167. // If there is conflicting data between the inputted users and destination,
  168. // favor using the users.
  169. // For example, if user A & destination 1 was passed in, but user A is now
  170. // in destination 2, it is better to bring the current user to destination 2
  171. // if possible.
  172. var users = launchDetails.UsersOptional;
  173. var usersCount = (users != null) ? users.Count : 0;
  174. // The deeplink message, this should give enough info on how to go the
  175. // destination in the app.
  176. var deeplinkMessage = launchDetails.DeeplinkMessage;
  177. // The API Name of the destination. You can set the user to this after
  178. // navigating to the app
  179. var destinationApiName = launchDetails.DestinationApiName;
  180. var detailsString = "-Deeplink Message:\n" + deeplinkMessage + "\n-Api Name:\n" + destinationApiName + "\n-Users:\n";
  181. if (usersCount > 0)
  182. {
  183. foreach(var user in users)
  184. {
  185. detailsString += user.OculusID + "\n";
  186. }
  187. } else
  188. {
  189. detailsString += "null\n";
  190. }
  191. detailsString += "\n";
  192. return detailsString;
  193. }
  194. // User has interacted with a deeplink outside this app
  195. void OnLaunchIntentChangeNotif(Oculus.Platform.Message<string> message)
  196. {
  197. if (message.IsError)
  198. {
  199. UpdateConsole(message.GetError().Message);
  200. } else
  201. {
  202. UpdateConsole("Updated launch details:\n" + GetAppLaunchDetails());
  203. }
  204. }
  205. void OnGetDestinations(Message<Oculus.Platform.Models.DestinationList> message)
  206. {
  207. if (message.IsError)
  208. {
  209. UpdateConsole("Could not get the list of destinations!");
  210. }
  211. else
  212. {
  213. foreach(Oculus.Platform.Models.Destination destination in message.Data)
  214. {
  215. DestinationAPINames.Add(destination.ApiName);
  216. UpdateDestinationsConsole();
  217. }
  218. }
  219. }
  220. #region Helper Functions
  221. private int DestinationIndex = 0;
  222. private bool OnlyPushUpOnce = false;
  223. // Update is called once per frame
  224. void Update()
  225. {
  226. if (PressAButton())
  227. {
  228. if (DestinationAPINames.Count > 0)
  229. {
  230. SetPresence();
  231. }
  232. else
  233. {
  234. UpdateConsole("No destinations to set to!");
  235. return;
  236. }
  237. }
  238. else if (PressBButton())
  239. {
  240. ClearPresence();
  241. }
  242. ScrollThroughDestinations();
  243. }
  244. private void ScrollThroughDestinations()
  245. {
  246. if (PressUp())
  247. {
  248. if (!OnlyPushUpOnce)
  249. {
  250. DestinationIndex--;
  251. if (DestinationIndex < 0)
  252. {
  253. DestinationIndex = DestinationAPINames.Count - 1;
  254. }
  255. OnlyPushUpOnce = true;
  256. UpdateDestinationsConsole();
  257. }
  258. }
  259. else if (PressDown())
  260. {
  261. if (!OnlyPushUpOnce)
  262. {
  263. DestinationIndex++;
  264. if (DestinationIndex >= DestinationAPINames.Count)
  265. {
  266. DestinationIndex = 0;
  267. }
  268. OnlyPushUpOnce = true;
  269. UpdateDestinationsConsole();
  270. }
  271. }
  272. else
  273. {
  274. OnlyPushUpOnce = false;
  275. }
  276. }
  277. private void UpdateDestinationsConsole()
  278. {
  279. if (DestinationAPINames.Count == 0)
  280. {
  281. DestinationsConsole.text = "Add some destinations to the developer dashboard first!";
  282. }
  283. string destinations = "Destination API Names:\n";
  284. for (int i = 0; i < DestinationAPINames.Count; i++)
  285. {
  286. if (i == DestinationIndex)
  287. {
  288. destinations += "==>";
  289. }
  290. destinations += DestinationAPINames[i] + "\n";
  291. }
  292. DestinationsConsole.text = destinations;
  293. }
  294. private void OnLoggedInUser(Message<Oculus.Platform.Models.User> message)
  295. {
  296. if (message.IsError)
  297. {
  298. Debug.LogError("Cannot get logged in user");
  299. }
  300. else
  301. {
  302. LoggedInUserID = message.Data.ID;
  303. }
  304. }
  305. private void UpdateConsole(string value)
  306. {
  307. Debug.Log(value);
  308. InVRConsole.text =
  309. "Scroll Up/Down on Right Thumbstick\n(A) - Set Rich Presence to selected\n(B) - Clear Rich Presence\n\n" + value;
  310. }
  311. #endregion
  312. #region I/O Inputs
  313. private bool PressAButton()
  314. {
  315. #if USE_OVRINPUT
  316. return OVRInput.GetUp(OVRInput.Button.One) || Input.GetKeyUp(KeyCode.A);
  317. #else
  318. return Input.GetKeyUp(KeyCode.A);
  319. #endif
  320. }
  321. private bool PressBButton()
  322. {
  323. #if USE_OVRINPUT
  324. return OVRInput.GetUp(OVRInput.Button.Two) || Input.GetKeyUp(KeyCode.B);
  325. #else
  326. return Input.GetKeyUp(KeyCode.B);
  327. #endif
  328. }
  329. private bool PressUp()
  330. {
  331. #if USE_OVRINPUT
  332. Vector2 axis = OVRInput.Get(OVRInput.Axis2D.SecondaryThumbstick);
  333. return (axis.y > 0.2 || Input.GetKeyUp(KeyCode.UpArrow));
  334. #else
  335. return Input.GetKeyUp(KeyCode.UpArrow);
  336. #endif
  337. }
  338. private bool PressDown()
  339. {
  340. #if USE_OVRINPUT
  341. Vector2 axis = OVRInput.Get(OVRInput.Axis2D.SecondaryThumbstick);
  342. return (axis.y < -0.2 || Input.GetKeyUp(KeyCode.DownArrow));
  343. #else
  344. return Input.GetKeyUp(KeyCode.DownArrow);
  345. #endif
  346. }
  347. #endregion
  348. }