Initial commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace XRMultiplayer
|
||||
{
|
||||
public class PlayerListInitializer : MonoBehaviour
|
||||
{
|
||||
[SerializeField] PlayerListUI[] m_PlayerListUIs;
|
||||
|
||||
void Start()
|
||||
{
|
||||
foreach (var l in m_PlayerListUIs)
|
||||
{
|
||||
l.InitializeCallbacks();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bee81ae8e4186d45a1a593720a17674
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,131 @@
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XRMultiplayer
|
||||
{
|
||||
public class PlayerListUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] TMP_Text m_PlayerCountText;
|
||||
[SerializeField] Transform m_ConnectedPlayersViewportContentTransform;
|
||||
[SerializeField] GameObject m_PlayerSlotPrefab;
|
||||
|
||||
[SerializeField] bool m_AutoInitializeCallbacks = true;
|
||||
|
||||
readonly Dictionary<PlayerSlot, XRINetworkPlayer> m_PlayerDictionary = new();
|
||||
|
||||
bool m_CallbacksInitialized = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (!m_CallbacksInitialized && m_AutoInitializeCallbacks)
|
||||
InitializeCallbacks();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (XRINetworkGameManager.Connected.Value)
|
||||
{
|
||||
foreach (var kvp in m_PlayerDictionary)
|
||||
{
|
||||
kvp.Key.voiceChatFillImage.fillAmount = kvp.Value.playerVoiceAmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
XRINetworkGameManager.Instance.playerStateChanged -= ConnectedPlayerStateChange;
|
||||
XRINetworkGameManager.Connected.Unsubscribe(OnConnected);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this function to initialize the callbacks on objects that start out disabled or inactive.
|
||||
/// </summary>
|
||||
public void InitializeCallbacks()
|
||||
{
|
||||
if (m_CallbacksInitialized) return;
|
||||
m_CallbacksInitialized = true;
|
||||
|
||||
//Remove Prefab placeholders
|
||||
foreach (Transform t in m_ConnectedPlayersViewportContentTransform)
|
||||
{
|
||||
Destroy(t.gameObject);
|
||||
}
|
||||
|
||||
XRINetworkGameManager.Instance.playerStateChanged += ConnectedPlayerStateChange;
|
||||
XRINetworkGameManager.Connected.Subscribe(OnConnected);
|
||||
}
|
||||
|
||||
void OnConnected(bool connected)
|
||||
{
|
||||
if (!connected)
|
||||
{
|
||||
foreach (Transform t in m_ConnectedPlayersViewportContentTransform)
|
||||
{
|
||||
Destroy(t.gameObject);
|
||||
}
|
||||
|
||||
m_PlayerDictionary.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectedPlayerStateChange(ulong playerId, bool connected)
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
SetupPlayerSlotUI(playerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemovePlayerSlotUI(playerId);
|
||||
}
|
||||
}
|
||||
|
||||
void RemovePlayerSlotUI(ulong playerId)
|
||||
{
|
||||
PlayerSlot slotToRemove = null;
|
||||
foreach (PlayerSlot slot in m_PlayerDictionary.Keys)
|
||||
{
|
||||
if (slot.playerID == playerId)
|
||||
{
|
||||
slotToRemove = slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (slotToRemove != null)
|
||||
{
|
||||
m_PlayerDictionary.Remove(slotToRemove);
|
||||
Destroy(slotToRemove.gameObject);
|
||||
m_PlayerCountText.text = $"{m_PlayerDictionary.Keys.Count}/{XRINetworkGameManager.Instance.lobbyManager.connectedLobby.MaxPlayers}";
|
||||
}
|
||||
}
|
||||
|
||||
void SetupPlayerSlotUI(ulong playerId)
|
||||
{
|
||||
PlayerSlot slot = Instantiate(m_PlayerSlotPrefab, m_ConnectedPlayersViewportContentTransform).GetComponent<PlayerSlot>();
|
||||
slot.playerID = playerId;
|
||||
|
||||
if (XRINetworkGameManager.Instance.GetPlayerByID(playerId, out XRINetworkPlayer player))
|
||||
{
|
||||
if (m_PlayerDictionary.TryAdd(slot, player))
|
||||
{
|
||||
slot.Setup(player);
|
||||
|
||||
if (player.IsLocalPlayer)
|
||||
{
|
||||
slot.playerSlotName.text += " (You)";
|
||||
}
|
||||
slot.playerIconImage.color = player.playerColor;
|
||||
|
||||
m_PlayerCountText.text = $"{m_PlayerDictionary.Keys.Count}/{XRINetworkGameManager.Instance.lobbyManager.connectedLobby.MaxPlayers}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.Log($"Player with id {playerId} is null. This is a bug.", 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 890d351bcb11f5245838066b83e72d7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace XRMultiplayer
|
||||
{
|
||||
public class PlayerSlot : MonoBehaviour
|
||||
{
|
||||
public TMP_Text playerSlotName;
|
||||
public TMP_Text playerInitial;
|
||||
public Image playerIconImage;
|
||||
|
||||
[Header("Mic Button")]
|
||||
public Image voiceChatFillImage;
|
||||
[SerializeField] Button m_MicButton;
|
||||
[SerializeField] Image m_PlayerVoiceIcon;
|
||||
[SerializeField] Image m_SquelchedIcon;
|
||||
[SerializeField] Sprite[] micIcons;
|
||||
XRINetworkPlayer m_Player;
|
||||
internal ulong playerID = 0;
|
||||
|
||||
public void Setup(XRINetworkPlayer player)
|
||||
{
|
||||
m_Player = player;
|
||||
m_Player.onColorUpdated += UpdateColor;
|
||||
m_Player.onNameUpdated += UpdateName;
|
||||
m_Player.selfMuted.OnValueChanged += UpdateSelfMutedState;
|
||||
m_MicButton.onClick.AddListener(Squelch);
|
||||
m_Player.squelched.Subscribe(UpdateSquelchedState);
|
||||
m_SquelchedIcon.enabled = false;
|
||||
if (m_Player.IsLocalPlayer)
|
||||
{
|
||||
m_MicButton.interactable = false;
|
||||
}
|
||||
|
||||
if (m_Player.selfMuted.Value)
|
||||
{
|
||||
m_PlayerVoiceIcon.sprite = micIcons[1];
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
m_Player.onColorUpdated -= UpdateColor;
|
||||
m_Player.onNameUpdated -= UpdateName;
|
||||
m_Player.selfMuted.OnValueChanged -= UpdateSelfMutedState;
|
||||
m_MicButton.onClick.RemoveListener(Squelch);
|
||||
m_Player.squelched.Unsubscribe(UpdateSquelchedState);
|
||||
}
|
||||
|
||||
void UpdateColor(Color newColor)
|
||||
{
|
||||
playerIconImage.color = newColor;
|
||||
}
|
||||
|
||||
void UpdateName(string newName)
|
||||
{
|
||||
if (!newName.IsNullOrEmpty())
|
||||
{
|
||||
string playerName = newName;
|
||||
if (m_Player.IsLocalPlayer)
|
||||
{
|
||||
playerName += " (You)";
|
||||
}
|
||||
else if (m_Player.IsOwnedByServer)
|
||||
{
|
||||
playerName += " (Host)";
|
||||
}
|
||||
playerSlotName.text = playerName;
|
||||
playerInitial.text = newName.Substring(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#region Muting
|
||||
public void Squelch()
|
||||
{
|
||||
m_Player.ToggleSquelch();
|
||||
}
|
||||
|
||||
void UpdateSelfMutedState(bool old, bool current)
|
||||
{
|
||||
m_PlayerVoiceIcon.sprite = micIcons[current ? 1 : 0];
|
||||
}
|
||||
|
||||
void UpdateSquelchedState(bool squelched)
|
||||
{
|
||||
m_SquelchedIcon.enabled = squelched;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7282738eeb6afb24e9419b8ff287a61e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user