From 4c077514e395437723d93efcbae4d9fe2447e0e3 Mon Sep 17 00:00:00 2001 From: "Jonas Luz Jr." Date: Sun, 23 Nov 2025 16:40:06 -0300 Subject: [PATCH] Iplements and integrates GameManager and UIController. --- Assets/_Client/Scripts/API.meta | 8 ++ Assets/_Client/Scripts/{ => API}/ApiClient.cs | 0 .../Scripts/{ => API}/ApiClient.cs.meta | 0 .../Scripts/{ => API}/ApiClientManager.cs | 44 +++++++-- .../{ => API}/ApiClientManager.cs.meta | 0 Assets/_Client/Scripts/{ => API}/ApiModel.cs | 0 .../Scripts/{ => API}/ApiModel.cs.meta | 0 Assets/_Client/Scripts/Core.meta | 8 ++ Assets/_Client/Scripts/Core/AppManager.cs | 72 +++++++++++++++ .../_Client/Scripts/Core/AppManager.cs.meta | 2 + Assets/_Client/Scripts/UI.meta | 8 ++ Assets/_Client/Scripts/UI/UIController.cs | 91 +++++++++++++++++++ .../_Client/Scripts/UI/UIController.cs.meta | 2 + 13 files changed, 228 insertions(+), 7 deletions(-) create mode 100644 Assets/_Client/Scripts/API.meta rename Assets/_Client/Scripts/{ => API}/ApiClient.cs (100%) rename Assets/_Client/Scripts/{ => API}/ApiClient.cs.meta (100%) rename Assets/_Client/Scripts/{ => API}/ApiClientManager.cs (81%) rename Assets/_Client/Scripts/{ => API}/ApiClientManager.cs.meta (100%) rename Assets/_Client/Scripts/{ => API}/ApiModel.cs (100%) rename Assets/_Client/Scripts/{ => API}/ApiModel.cs.meta (100%) create mode 100644 Assets/_Client/Scripts/Core.meta create mode 100644 Assets/_Client/Scripts/Core/AppManager.cs create mode 100644 Assets/_Client/Scripts/Core/AppManager.cs.meta create mode 100644 Assets/_Client/Scripts/UI.meta create mode 100644 Assets/_Client/Scripts/UI/UIController.cs create mode 100644 Assets/_Client/Scripts/UI/UIController.cs.meta diff --git a/Assets/_Client/Scripts/API.meta b/Assets/_Client/Scripts/API.meta new file mode 100644 index 0000000..56f65d7 --- /dev/null +++ b/Assets/_Client/Scripts/API.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2ef7622eea79d2543b4f52a08c14c5f7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Client/Scripts/ApiClient.cs b/Assets/_Client/Scripts/API/ApiClient.cs similarity index 100% rename from Assets/_Client/Scripts/ApiClient.cs rename to Assets/_Client/Scripts/API/ApiClient.cs diff --git a/Assets/_Client/Scripts/ApiClient.cs.meta b/Assets/_Client/Scripts/API/ApiClient.cs.meta similarity index 100% rename from Assets/_Client/Scripts/ApiClient.cs.meta rename to Assets/_Client/Scripts/API/ApiClient.cs.meta diff --git a/Assets/_Client/Scripts/ApiClientManager.cs b/Assets/_Client/Scripts/API/ApiClientManager.cs similarity index 81% rename from Assets/_Client/Scripts/ApiClientManager.cs rename to Assets/_Client/Scripts/API/ApiClientManager.cs index 806c2de..95bb5e5 100644 --- a/Assets/_Client/Scripts/ApiClientManager.cs +++ b/Assets/_Client/Scripts/API/ApiClientManager.cs @@ -1,3 +1,5 @@ +using System; +using System.Collections; using System.Linq; using UnityEngine; @@ -51,6 +53,7 @@ namespace PPGIA.X540.Project3.API [Header("API State Information")] [SerializeField] private Session _session; + public bool IsSessionActive => _session != null; #endregion ------------------------------------------------------------ #region -- Other Properties & Methods --------------------------------- @@ -88,7 +91,7 @@ namespace PPGIA.X540.Project3.API } [ContextMenu("Session/Initiate Session")] - public void InitiateSession() + public void InitiateSession(Action sessionStartedCallback = null) { StopAllCoroutines(); @@ -100,15 +103,18 @@ namespace PPGIA.X540.Project3.API var body = request.downloadHandler?.text ?? string.Empty; var session = JsonUtility.FromJson(body); _session = session; + + sessionStartedCallback?.Invoke(); })); } [ContextMenu("Session/Close Session")] - public void CloseSession() - { + public void CloseSession(Action sessionClosedCallback = null) + { if (_session == null) { Debug.LogWarning("No active session to close."); + sessionClosedCallback?.Invoke(); return; } @@ -121,11 +127,14 @@ namespace PPGIA.X540.Project3.API { Debug.Log("Session closed successfully."); _session = null; + sessionClosedCallback?.Invoke(); })); } [ContextMenu("Chat/Send Message")] - public void SendChatMessage() + public void SendChatMessage(string message = null, + Action responseReceivedCallback = null, + Action speechFinishedCallback = null) { // Ensure there is an active session if (_session == null) @@ -134,6 +143,8 @@ namespace PPGIA.X540.Project3.API return; } + if (message != null) _query = message; + StopAllCoroutines(); // Build the endpoint URL and payload @@ -146,13 +157,17 @@ namespace PPGIA.X540.Project3.API { var body = request.downloadHandler?.text ?? string.Empty; var response = ApiModel.FromJson(body); + + var chatResponse = response?.Message; + responseReceivedCallback?.Invoke(chatResponse); + var audioUrl = response?.AudioUrl; if (string.IsNullOrEmpty(audioUrl)) { Debug.LogWarning("No audio URL in response."); return; } - + Debug.Log($"Downloading audio from: {audioUrl}"); StartCoroutine(ApiClient.DownloadAudioCoroutine( audioUrl, _timeoutInSeconds, (audioClip) => @@ -162,11 +177,26 @@ namespace PPGIA.X540.Project3.API Debug.LogError("AudioClip is null after download."); return; } - - _audioSource?.PlayOneShot(audioClip); + StartCoroutine(PlayAudioAndNotifyCoroutine( + audioClip, speechFinishedCallback)); })); })); } + + private IEnumerator PlayAudioAndNotifyCoroutine( + AudioClip audioClip, Action onComplete) + { + if (_audioSource == null || audioClip == null) + { + onComplete?.Invoke(); + yield break; + } + + _audioSource.PlayOneShot(audioClip); + yield return new WaitForSeconds(audioClip.length); + + onComplete?.Invoke(); + } #endregion -- API Calls ------------------------------------------------ [ContextMenu("Debug/Play or Stop Test Audio")] diff --git a/Assets/_Client/Scripts/ApiClientManager.cs.meta b/Assets/_Client/Scripts/API/ApiClientManager.cs.meta similarity index 100% rename from Assets/_Client/Scripts/ApiClientManager.cs.meta rename to Assets/_Client/Scripts/API/ApiClientManager.cs.meta diff --git a/Assets/_Client/Scripts/ApiModel.cs b/Assets/_Client/Scripts/API/ApiModel.cs similarity index 100% rename from Assets/_Client/Scripts/ApiModel.cs rename to Assets/_Client/Scripts/API/ApiModel.cs diff --git a/Assets/_Client/Scripts/ApiModel.cs.meta b/Assets/_Client/Scripts/API/ApiModel.cs.meta similarity index 100% rename from Assets/_Client/Scripts/ApiModel.cs.meta rename to Assets/_Client/Scripts/API/ApiModel.cs.meta diff --git a/Assets/_Client/Scripts/Core.meta b/Assets/_Client/Scripts/Core.meta new file mode 100644 index 0000000..308394f --- /dev/null +++ b/Assets/_Client/Scripts/Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8a2376aa5b49eeb41aac7df48220349f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Client/Scripts/Core/AppManager.cs b/Assets/_Client/Scripts/Core/AppManager.cs new file mode 100644 index 0000000..77bd7fa --- /dev/null +++ b/Assets/_Client/Scripts/Core/AppManager.cs @@ -0,0 +1,72 @@ +using UnityEngine; + +using PPGIA.X540.Project3.API; + + +namespace PPGIA.X540.Project3 +{ + public class AppManager : MonoBehaviour + { + [Header("References")] + [SerializeField] + private UIController _uiController; + + [SerializeField] + private ApiClientManager _apiManager; + + private void Awake() + { + if (_uiController == null) + _uiController = GetComponent(); + if (_apiManager == null) + _apiManager = GetComponent(); + } + + void Start() + { + _apiManager.CloseSession( + () => _uiController.SessionActive = _apiManager.IsSessionActive); + } + + private void OnEnable() + { + _uiController.OnSessionButtonClicked += HandleSessionButtonClicked; + _uiController.OnSendChatButtonClicked += HandleSendChatButtonClicked; + } + + private void OnDisable() + { + _uiController.OnSessionButtonClicked -= HandleSessionButtonClicked; + _uiController.OnSendChatButtonClicked -= HandleSendChatButtonClicked; + } + + private void HandleSessionButtonClicked() + { + if (!_apiManager.IsSessionActive) + { + _apiManager.InitiateSession( + () => _uiController.SessionActive = _apiManager.IsSessionActive); + } + else + { + _apiManager.CloseSession( + () => _uiController.SessionActive = _apiManager.IsSessionActive + ); + } + } + + private void HandleSendChatButtonClicked(string message) + { + _apiManager.SendChatMessage(message, + (responseMessage) => + { + _uiController.ChatOutput += $"User: {message}\n"; + _uiController.ChatOutput += $"Bot: {responseMessage}\n"; + }, + () => + { + // Speech finished callback (optional) + }); + } + } +} diff --git a/Assets/_Client/Scripts/Core/AppManager.cs.meta b/Assets/_Client/Scripts/Core/AppManager.cs.meta new file mode 100644 index 0000000..7c43cdc --- /dev/null +++ b/Assets/_Client/Scripts/Core/AppManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7a1ca38af0a96524893a60d620fa5791 \ No newline at end of file diff --git a/Assets/_Client/Scripts/UI.meta b/Assets/_Client/Scripts/UI.meta new file mode 100644 index 0000000..2422f97 --- /dev/null +++ b/Assets/_Client/Scripts/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2accbadde24a9c647b17ab58a3139bfa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Client/Scripts/UI/UIController.cs b/Assets/_Client/Scripts/UI/UIController.cs new file mode 100644 index 0000000..bc787ab --- /dev/null +++ b/Assets/_Client/Scripts/UI/UIController.cs @@ -0,0 +1,91 @@ +using System; + +using UnityEngine; +using UnityEngine.UIElements; + + +namespace PPGIA.X540.Project3 +{ + [RequireComponent(typeof(UIController))] + public class UIController : MonoBehaviour + { + private UIDocument _uiDocument; + private VisualElement _root; + + private readonly string[] _sessionButtonLabels = { + "Iniciar Sessão", + "Encerrar Sessão" + }; + private Button _sessionButton; + private Button _sendChatButton; + private int _currentSessionState = 0; + + private TextField _chatInputField; + private TextField _chatOutputField; + + public string ChatOutput + { + get => _chatOutputField.value; + set => _chatOutputField.value = value; + } + + public bool SessionActive { + get => _currentSessionState == 1; + set + { + _currentSessionState = value ? 1 : 0; + UpdateStateForSession(); + } + } + + public Action OnSessionButtonClicked { get; set; } + public Action OnSendChatButtonClicked { get; set; } + public float Progress { get; set; } + + private void Awake() + { + _uiDocument = GetComponent(); + _root = _uiDocument.rootVisualElement; + + _sessionButton = _root.Q