// ---------------------------------------------------------------------------- // // Photon Voice Demo for PUN - Copyright (C) Exit Games GmbH // // // UI manager class for the PUN Voice Demo // // developer@photonengine.com // ---------------------------------------------------------------------------- using System; using Photon.Voice.Unity; using Photon.Voice.PUN; #pragma warning disable 0649 // Field is never assigned to, and will always have its default value namespace ExitGames.Demos.DemoPunVoice { using Photon.Pun; using UnityEngine; using UnityEngine.UI; using Client.Photon; #if !UNITY_EDITOR && UNITY_PS4 using Sony.NP; #elif !UNITY_EDITOR && UNITY_SHARLIN using System.Runtime.InteropServices; #endif public class VoiceDemoUI : MonoBehaviour { #if !UNITY_EDITOR && UNITY_SHARLIN [DllImport("PhotonVoiceLocalUserIDPlugin")] private static extern int egpvgetLocalUserID(); // returns the user ID of the user at index 0 in the list of local users #endif [SerializeField] private Text punState; [SerializeField] private Text voiceState; private PhotonVoiceNetwork punVoiceNetwork; private Canvas canvas; [SerializeField] private Button punSwitch; private Text punSwitchText; [SerializeField] private Button voiceSwitch; private Text voiceSwitchText; [SerializeField] private Button calibrateButton; private Text calibrateText; [SerializeField] private Text voiceDebugText; public Recorder recorder; [SerializeField] private GameObject inGameSettings; [SerializeField] private GameObject globalSettings; [SerializeField] private Text devicesInfoText; private GameObject debugGO; private bool debugMode; private float volumeBeforeMute; private DebugLevel previousDebugLevel; public bool DebugMode { get { return this.debugMode; } set { this.debugMode = value; this.debugGO.SetActive(this.debugMode); this.voiceDebugText.text = String.Empty; if (this.debugMode) { this.previousDebugLevel = this.punVoiceNetwork.Client.LoadBalancingPeer.DebugOut; this.punVoiceNetwork.Client.LoadBalancingPeer.DebugOut = DebugLevel.ALL; } else { this.punVoiceNetwork.Client.LoadBalancingPeer.DebugOut = this.previousDebugLevel; } if (DebugToggled != null) { DebugToggled(this.debugMode); } } } public delegate void OnDebugToggle(bool debugMode); public static event OnDebugToggle DebugToggled; [SerializeField] private int calibrationMilliSeconds = 2000; private void Awake() { this.punVoiceNetwork = PhotonVoiceNetwork.Instance; } private void OnEnable() { ChangePOV.CameraChanged += this.OnCameraChanged; BetterToggle.ToggleValueChanged += this.BetterToggle_ToggleValueChanged; CharacterInstantiation.CharacterInstantiated += this.CharacterInstantiation_CharacterInstantiated; this.punVoiceNetwork.Client.StateChanged += this.VoiceClientStateChanged; PhotonNetwork.NetworkingClient.StateChanged += this.PunClientStateChanged; } private void OnDisable() { ChangePOV.CameraChanged -= this.OnCameraChanged; BetterToggle.ToggleValueChanged -= this.BetterToggle_ToggleValueChanged; CharacterInstantiation.CharacterInstantiated -= this.CharacterInstantiation_CharacterInstantiated; this.punVoiceNetwork.Client.StateChanged -= this.VoiceClientStateChanged; PhotonNetwork.NetworkingClient.StateChanged -= this.PunClientStateChanged; } private void CharacterInstantiation_CharacterInstantiated(GameObject character) { if (this.recorder) // probably using a global recorder { return; } PhotonVoiceView photonVoiceView = character.GetComponent(); if (photonVoiceView.IsRecorder) { this.recorder = photonVoiceView.RecorderInUse; } } private void InitToggles(Toggle[] toggles) { if (toggles == null) { return; } for (int i = 0; i < toggles.Length; i++) { Toggle toggle = toggles[i]; switch (toggle.name) { case "Mute": toggle.isOn = AudioListener.volume <= 0.001f; break; case "VoiceDetection": toggle.isOn = this.recorder != null && this.recorder.VoiceDetection; break; case "DebugVoice": toggle.isOn = this.DebugMode; break; case "Transmit": toggle.isOn = this.recorder != null && this.recorder.TransmitEnabled; break; case "DebugEcho": toggle.isOn = this.recorder != null && this.recorder.DebugEchoMode; break; case "AutoConnectAndJoin": toggle.isOn = this.punVoiceNetwork.AutoConnectAndJoin; break; case "AutoLeaveAndDisconnect": toggle.isOn = this.punVoiceNetwork.AutoLeaveAndDisconnect; break; } } } private void BetterToggle_ToggleValueChanged(Toggle toggle) { switch (toggle.name) { case "Mute": //AudioListener.pause = toggle.isOn; if (toggle.isOn) { this.volumeBeforeMute = AudioListener.volume; AudioListener.volume = 0f; } else { AudioListener.volume = this.volumeBeforeMute; this.volumeBeforeMute = 0f; } break; case "Transmit": if (this.recorder) { this.recorder.TransmitEnabled = toggle.isOn; } break; case "VoiceDetection": if (this.recorder) { this.recorder.VoiceDetection = toggle.isOn; } break; case "DebugEcho": if (this.recorder) { this.recorder.DebugEchoMode = toggle.isOn; } break; case "DebugVoice": this.DebugMode = toggle.isOn; break; case "AutoConnectAndJoin": this.punVoiceNetwork.AutoConnectAndJoin = toggle.isOn; break; case "AutoLeaveAndDisconnect": this.punVoiceNetwork.AutoLeaveAndDisconnect = toggle.isOn; break; } } private void OnCameraChanged(Camera newCamera) { this.canvas.worldCamera = newCamera; } private void Start() { this.canvas = this.GetComponentInChildren(); if (this.punSwitch != null) { this.punSwitchText = this.punSwitch.GetComponentInChildren(); this.punSwitch.onClick.AddListener(this.PunSwitchOnClick); } if (this.voiceSwitch != null) { this.voiceSwitchText = this.voiceSwitch.GetComponentInChildren(); this.voiceSwitch.onClick.AddListener(this.VoiceSwitchOnClick); } if (this.calibrateButton != null) { this.calibrateButton.onClick.AddListener(this.CalibrateButtonOnClick); this.calibrateText = this.calibrateButton.GetComponentInChildren(); } if (this.punState != null) { this.debugGO = this.punState.transform.parent.gameObject; } this.volumeBeforeMute = AudioListener.volume; this.previousDebugLevel = this.punVoiceNetwork.Client.LoadBalancingPeer.DebugOut; if (this.globalSettings != null) { this.globalSettings.SetActive(true); this.InitToggles(this.globalSettings.GetComponentsInChildren()); } if (this.devicesInfoText != null) { if (UnityMicrophone.devices == null || UnityMicrophone.devices.Length == 0) { this.devicesInfoText.enabled = true; this.devicesInfoText.color = Color.red; this.devicesInfoText.text = "No microphone device detected!"; } else if (UnityMicrophone.devices.Length == 1) { this.devicesInfoText.text = string.Format("Mic.: {0}", UnityMicrophone.devices[0]); } else { this.devicesInfoText.text = string.Format("Multi.Mic.Devices:\n0. {0} (active)\n", UnityMicrophone.devices[0]); for (int i = 1; i < UnityMicrophone.devices.Length; i++) { this.devicesInfoText.text = string.Concat(this.devicesInfoText.text, string.Format("{0}. {1}\n", i, UnityMicrophone.devices[i])); } } } #if !UNITY_EDITOR && UNITY_PS4 UserProfiles.LocalUsers localUsers = new UserProfiles.LocalUsers(); UserProfiles.GetLocalUsers(localUsers); int userID = localUsers.LocalUsersIds[0].UserId.Id; punVoiceNetwork.PlayStationUserID = userID; #elif !UNITY_EDITOR && UNITY_SHARLIN punVoiceNetwork.PlayStationUserID = egpvgetLocalUserID(); #endif } private void PunSwitchOnClick() { if (PhotonNetwork.NetworkClientState == Photon.Realtime.ClientState.Joined) { PhotonNetwork.Disconnect(); } else if (PhotonNetwork.NetworkClientState == Photon.Realtime.ClientState.Disconnected || PhotonNetwork.NetworkClientState == Photon.Realtime.ClientState.PeerCreated) { PhotonNetwork.ConnectUsingSettings(); } } private void VoiceSwitchOnClick() { if (this.punVoiceNetwork.ClientState == Photon.Realtime.ClientState.Joined) { this.punVoiceNetwork.Disconnect(); } else if (this.punVoiceNetwork.ClientState == Photon.Realtime.ClientState.PeerCreated || this.punVoiceNetwork.ClientState == Photon.Realtime.ClientState.Disconnected) { this.punVoiceNetwork.ConnectAndJoinRoom(); } } private void CalibrateButtonOnClick() { if (this.recorder && !this.recorder.VoiceDetectorCalibrating) { this.recorder.VoiceDetectorCalibrate(this.calibrationMilliSeconds); } } private void Update() { // editor only two-ways binding for toggles #if UNITY_EDITOR this.InitToggles(this.globalSettings.GetComponentsInChildren()); #endif if (this.recorder != null && this.recorder.LevelMeter != null) { this.voiceDebugText.text = string.Format("Amp: avg. {0:0.000000}, peak {1:0.000000}", this.recorder.LevelMeter.CurrentAvgAmp, this.recorder.LevelMeter.CurrentPeakAmp); } } private void PunClientStateChanged(Photon.Realtime.ClientState fromState, Photon.Realtime.ClientState toState) { this.punState.text = string.Format("PUN: {0}", toState); switch (toState) { case Photon.Realtime.ClientState.PeerCreated: case Photon.Realtime.ClientState.Disconnected: this.punSwitch.interactable = true; this.punSwitchText.text = "PUN Connect"; break; case Photon.Realtime.ClientState.Joined: this.punSwitch.interactable = true; this.punSwitchText.text = "PUN Disconnect"; break; default: this.punSwitch.interactable = false; this.punSwitchText.text = "PUN busy"; break; } this.UpdateUiBasedOnVoiceState(this.punVoiceNetwork.ClientState); } private void VoiceClientStateChanged(Photon.Realtime.ClientState fromState, Photon.Realtime.ClientState toState) { this.UpdateUiBasedOnVoiceState(toState); } private void UpdateUiBasedOnVoiceState(Photon.Realtime.ClientState voiceClientState) { this.voiceState.text = string.Format("PhotonVoice: {0}", voiceClientState); switch (voiceClientState) { case Photon.Realtime.ClientState.Joined: this.voiceSwitch.interactable = true; this.inGameSettings.SetActive(true); this.voiceSwitchText.text = "Voice Disconnect"; this.InitToggles(this.inGameSettings.GetComponentsInChildren()); if (this.recorder != null) { this.calibrateButton.interactable = !this.recorder.VoiceDetectorCalibrating; this.calibrateText.text = this.recorder.VoiceDetectorCalibrating ? "Calibrating" : string.Format("Calibrate ({0}s)", this.calibrationMilliSeconds / 1000); } else { this.calibrateButton.interactable = false; this.calibrateText.text = "Unavailable"; } break; case Photon.Realtime.ClientState.PeerCreated: case Photon.Realtime.ClientState.Disconnected: if (PhotonNetwork.InRoom) { this.voiceSwitch.interactable = true; this.voiceSwitchText.text = "Voice Connect"; this.voiceDebugText.text = String.Empty; } else { this.voiceSwitch.interactable = false; this.voiceSwitchText.text = "Voice N/A"; this.voiceDebugText.text = String.Empty; } this.calibrateButton.interactable = false; this.voiceSwitchText.text = "Voice Connect"; this.calibrateText.text = "Unavailable"; this.inGameSettings.SetActive(false); break; default: this.voiceSwitch.interactable = false; this.voiceSwitchText.text = "Voice busy"; break; } } } }