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

namespace Oculus.Platform.Samples.VrVoiceChat
{
using UnityEngine;
using System;
using System.Collections.Generic;
using Oculus.Platform;
using Oculus.Platform.Models;
// Helper class to manage Room creation, membership and invites.
// Rooms are a mechanism to help Oculus users create a shared experience.
// Users can only be in one Room at a time. If the Owner of a room
// leaves, then ownership is transferred to some other member.
// Here we use rooms to create the notion of a 'call' to help us
// invite a Friend and establish a VOIP and P2P connection.
public class RoomManager
{
// the ID of the Room that I'm in
private ulong m_roomID;
// the other User in the Room
private User m_remoteUser;
// how often I should poll for invites
private static readonly float INVITE_POLL_FREQ_SECONDS = 5.0f;
// the next time I should poll Oculus Platform for valid Room Invite requests
private float m_nextPollTime;
public struct Invite
{
public readonly ulong RoomID;
public readonly string OwnerID;
public Invite(ulong roomID, string owner)
{
this.RoomID = roomID;
this.OwnerID = owner;
}
}
// cached list of rooms that I've been invited to and I'm waiting
// for more information about
private HashSet<ulong> m_pendingRoomRequests;
// accumulation list of room invites and the room owner
private List<Invite> m_invites;
public RoomManager()
{
Rooms.SetRoomInviteAcceptedNotificationCallback(LaunchedFromAcceptingInviteCallback);
Rooms.SetUpdateNotificationCallback(RoomUpdateCallback);
}
public ulong RemoteUserID
{
get
{
return m_remoteUser != null ? m_remoteUser.ID : 0;
}
}
public String RemoteOculusID
{
get
{
return m_remoteUser != null ? m_remoteUser.OculusID : String.Empty;
}
}
#region Launched Application from Accepting Invite
// Callback to check whether the User accepted the invite as
// a notification which caused the Application to launch. If so, then
// we know we need to try to join that room.
void LaunchedFromAcceptingInviteCallback(Message<string> msg)
{
if (msg.IsError)
{
PlatformManager.TerminateWithError(msg);
return;
}
Debug.Log("Launched Invite to join Room: " + msg.Data);
m_roomID = Convert.ToUInt64(msg.GetString());
}
// Check to see if the App was launched by accepting the Notication from the main Oculus app.
// If so, we can directly join that room. (If it's still available.)
public bool CheckForLaunchInvite()
{
if (m_roomID != 0)
{
JoinExistingRoom(m_roomID);
return true;
}
else
{
return false;
}
}
#endregion
#region Create a Room and Invite Friend(s) from the Oculus Universal Menu
public void CreateRoomAndLaunchInviteMenu()
{
Rooms.CreateAndJoinPrivate(RoomJoinPolicy.InvitedUsers, 2, true)
.OnComplete(CreateAndJoinPrivateRoomCallback);
}
void CreateAndJoinPrivateRoomCallback(Message<Room> msg)
{
if (msg.IsError)
{
PlatformManager.TerminateWithError(msg);
return;
}
m_roomID = msg.Data.ID;
m_remoteUser = null;
PlatformManager.TransitionToState(PlatformManager.State.WAITING_FOR_ANSWER);
// launch the Room Invite workflow in the Oculus Univeral Menu
Rooms.LaunchInvitableUserFlow(m_roomID).OnComplete(OnLaunchInviteWorkflowComplete);
}
void OnLaunchInviteWorkflowComplete(Message msg)
{
if (msg.IsError)
{
PlatformManager.TerminateWithError(msg);
return;
}
}
#endregion
#region Polling for Invites
public bool ShouldPollInviteList
{
get
{
return m_pendingRoomRequests == null && Time.time >= m_nextPollTime;
}
}
public void UpdateActiveInvitesList()
{
m_nextPollTime = Time.time + INVITE_POLL_FREQ_SECONDS;
m_pendingRoomRequests = new HashSet<ulong>();
m_invites = new List<Invite>();
Notifications.GetRoomInviteNotifications().OnComplete(GetRoomInviteNotificationsCallback);
}
// task 13572454: add the type to callback definition
void GetRoomInviteNotificationsCallback(Message msg_untyped)
{
Message<RoomInviteNotificationList> msg = (Message<RoomInviteNotificationList>)msg_untyped;
if (msg.IsError)
{
PlatformManager.TerminateWithError(msg);
return;
}
// loop over all the rooms we're invited to and request more info
foreach (RoomInviteNotification invite in msg.Data)
{
m_pendingRoomRequests.Add(invite.RoomID);
Rooms.Get(invite.RoomID).OnComplete(GetRoomInfoCallback);
}
if (msg.Data.Count == 0)
{
m_pendingRoomRequests = null;
PlatformManager.SetActiveInvites(m_invites);
}
}
void GetRoomInfoCallback(Message<Room> msg)
{
if (msg.IsError)
{
PlatformManager.TerminateWithError(msg);
return;
}
if (msg.Data.OwnerOptional != null)
{
Invite invite = new Invite(msg.Data.ID, msg.Data.OwnerOptional.OculusID);
m_pendingRoomRequests.Remove(invite.RoomID);
// make sure the room still looks usable
// (e.g. they aren't currently talking to someone)
if (msg.Data.UsersOptional != null && msg.Data.UsersOptional.Count == 1)
{
m_invites.Add(invite);
}
}
// once we're received all the room info, let the platform update
// its display
if (m_pendingRoomRequests.Count == 0)
{
m_pendingRoomRequests = null;
PlatformManager.SetActiveInvites(m_invites);
}
}
#endregion
#region Accept Invite
public void JoinExistingRoom(ulong roomID)
{
Rooms.Join(roomID, true).OnComplete(JoinRoomCallback);
}
void JoinRoomCallback(Message<Room> msg)
{
if (msg.IsError)
{
// is reasonable if caller called more than 1 person, and I didn't answer first
return;
}
string oculusOwnerID = msg.Data.OwnerOptional != null ? msg.Data.OwnerOptional.OculusID : "";
int numUsers = msg.Data.UsersOptional != null ? msg.Data.UsersOptional.Count : 0;
Debug.LogFormat("Joined room: {0} owner: {1} count: ",
msg.Data.ID, oculusOwnerID, numUsers);
m_roomID = msg.Data.ID;
// if the caller left while I was in the process of joining, just hangup
if (msg.Data.UsersOptional == null || msg.Data.UsersOptional.Count != 2)
{
PlatformManager.TransitionToState(PlatformManager.State.HANGUP);
}
else
{
foreach (User user in msg.Data.UsersOptional)
{
if (user.ID != PlatformManager.MyID)
{
m_remoteUser = user;
}
}
PlatformManager.TransitionToState(PlatformManager.State.CONNECTED_IN_A_ROOM);
}
// update the invite list sooner
m_nextPollTime = Time.time;
}
#endregion
#region Room Updates
void RoomUpdateCallback(Message<Room> msg)
{
if (msg.IsError)
{
PlatformManager.TerminateWithError(msg);
return;
}
string oculusOwnerID = msg.Data.OwnerOptional != null ? msg.Data.OwnerOptional.OculusID : "";
int numUsers = msg.Data.UsersOptional != null ? msg.Data.UsersOptional.Count : 0;
Debug.LogFormat("Room {0} Update: {1} owner: {2} count: ",
msg.Data.ID, oculusOwnerID, numUsers);
// if the Room count is not 2 then the other party has left.
// We'll just hangup the connection here.
// If the other User created then room, ownership would switch to me.
if (msg.Data.UsersOptional == null || msg.Data.UsersOptional.Count != 2)
{
PlatformManager.TransitionToState(PlatformManager.State.HANGUP);
}
else
{
foreach (User user in msg.Data.UsersOptional)
{
if (user.ID != PlatformManager.MyID)
{
m_remoteUser = user;
}
}
PlatformManager.TransitionToState(PlatformManager.State.CONNECTED_IN_A_ROOM);
}
}
#endregion
#region Room Exit
public void LeaveCurrentRoom()
{
if (m_roomID != 0)
{
Rooms.Leave(m_roomID);
m_roomID = 0;
m_remoteUser = null;
}
PlatformManager.TransitionToState(PlatformManager.State.WAITING_TO_CALL_OR_ANSWER);
}
#endregion
}
}