This commit is contained in:
2026-04-28 18:49:05 +07:00
parent f4f345b412
commit 9484f1f1d4
15 changed files with 496 additions and 155 deletions

View File

@@ -10,6 +10,8 @@ namespace Hallucinate.UI
protected VisualElement root;
protected UIManager uiManager;
public VisualElement Root => root; // Thêm thuộc tính này
public virtual void Initialize(VisualElement uxmlRoot, UIManager manager)
{
root = uxmlRoot;

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
namespace Hallucinate.UI
{
public static class FirebaseService
{
// Thay link database của bạn vào đây
private const string BASE_URL = "https://YOUR_FIREBASE_URL.firebaseio.com/users";
public static async Task<bool> IsUsernameTaken(string username)
{
string url = $"{BASE_URL}/{username}.json";
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
var operation = request.SendWebRequest();
while (!operation.isDone) await Task.Yield();
if (request.result != UnityWebRequest.Result.Success) return false;
// Nếu kết quả trả về không phải "null" nghĩa là user đã tồn tại
return request.downloadHandler.text != "null";
}
}
public static async Task<bool> RegisterUser(string username)
{
string url = $"{BASE_URL}/{username}.json";
string jsonData = "{\"created_at\": \"" + DateTime.Now.ToString() + "\"}";
using (UnityWebRequest request = UnityWebRequest.Put(url, jsonData))
{
var operation = request.SendWebRequest();
while (!operation.isDone) await Task.Yield();
return request.result == UnityWebRequest.Result.Success;
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bf13e7d21e483574882c6b687a6ae19c

View File

@@ -0,0 +1,90 @@
using UnityEngine;
using UnityEngine.UIElements;
using System.Threading.Tasks;
namespace Hallucinate.UI
{
public class LoginController : BaseUIController
{
private TextField _nameInput;
private Label _errorLabel;
private Button _confirmBtn;
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
{
base.Initialize(uxmlRoot, manager);
_nameInput = root.Q<TextField>("UsernameInput");
_errorLabel = root.Q<Label>("ErrorMsg");
_confirmBtn = root.Q<Button>("ConfirmBtn");
if (_confirmBtn != null)
_confirmBtn.clicked += OnConfirmClicked;
}
private async void OnConfirmClicked()
{
string username = _nameInput.value.Trim();
if (string.IsNullOrEmpty(username))
{
ShowError("Name cannot be empty!");
return;
}
_confirmBtn.SetEnabled(false);
_confirmBtn.text = "CHECKING...";
// 1. Kiểm tra trùng tên trên Firebase
bool isTaken = await FirebaseService.IsUsernameTaken(username);
if (isTaken)
{
ShowError("This name is already taken!");
_confirmBtn.SetEnabled(true);
_confirmBtn.text = "CONFIRM";
}
else
{
// 2. Đăng ký user mới
bool success = await FirebaseService.RegisterUser(username);
if (success)
{
// 3. Lưu lại và đóng popup
PlayerPrefs.SetString("Username", username);
PlayerPrefs.Save();
Debug.Log($"[Login] Registered as {username}");
// Thông báo cho UIManager biết đã login xong
uiManager.OnLoginSuccess();
await PlayTransitionOut();
}
else
{
ShowError("Connection error!");
_confirmBtn.SetEnabled(true);
_confirmBtn.text = "CONFIRM";
}
}
}
private void ShowError(string msg)
{
if (_errorLabel == null) return;
_errorLabel.text = msg;
_errorLabel.style.display = DisplayStyle.Flex;
}
public override async Task PlayTransitionIn()
{
// Login hiện ra như một overlay trung tâm
if (root != null)
{
root.style.translate = new StyleTranslate(new Translate(0, 0));
root.style.opacity = 0;
}
Show();
await PrimeTween.Tween.Custom(0f, 1f, duration: 0.5f, onValueChange: val => root.style.opacity = val);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: fbd606c21d317da47820446e4da1c55b

View File

@@ -19,10 +19,12 @@ namespace Hallucinate.UI
_tabTitle = root.Q<Label>("TabTitle");
_content = root.Q<ScrollView>("SettingsContent");
// Logic đóng khi nhấn vào vùng nền bên ngoài sidebar
root.RegisterCallback<ClickEvent>(evt => {
// Đăng ký sự kiện Click vào vùng nền tối
root.RegisterCallback<PointerDownEvent>(evt => {
// Nếu click trực tiếp vào SettingsRoot (không phải sidebar)
if (evt.target == root)
{
Debug.Log("[Settings] Clicked outside sidebar, closing...");
uiManager.ToggleSettings();
}
});
@@ -43,14 +45,13 @@ namespace Hallucinate.UI
public override async Task PlayTransitionIn()
{
// Reset vị trí root về 0 (Overlay trên màn hình hiện tại)
if (root != null)
{
root.style.translate = new StyleTranslate(new Translate(0, 0));
root.style.display = DisplayStyle.Flex;
}
// Trượt sidebar từ trái vào
// Hiệu ứng trượt sidebar
_sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(-100), 0));
await Tween.Custom(-100f, 0f, duration: 0.4f, ease: Ease.OutQuad,
onValueChange: val => _sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
@@ -58,7 +59,6 @@ namespace Hallucinate.UI
public override async Task PlayTransitionOut()
{
// Trượt sidebar ra trái
await Tween.Custom(0f, -100f, duration: 0.4f, ease: Ease.InQuad,
onValueChange: val => _sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));

View File

@@ -4,7 +4,7 @@ using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using PrimeTween;
using OnlyScove.Scripts; // Namespace của InputReader
using OnlyScove.Scripts;
#if UNITY_EDITOR
using UnityEditor;
#endif
@@ -40,12 +40,14 @@ namespace Hallucinate.UI
[SerializeField] private Color rippleColor = new Color(1, 1, 1, 0.4f);
[Header("UI Templates")]
[SerializeField] private VisualTreeAsset loginTemplate; // Template mới
[SerializeField] private VisualTreeAsset mainMenuTemplate;
[SerializeField] private VisualTreeAsset lobbyTemplate;
[SerializeField] private VisualTreeAsset profileTemplate;
[SerializeField] private VisualTreeAsset settingsTemplate;
[SerializeField] private VisualTreeAsset hudTemplate;
private LoginController _loginController;
private MainMenuController _mainMenuController;
private SettingsController _settingsController;
private List<VisualElement> _trailSegments = new List<VisualElement>();
@@ -79,7 +81,6 @@ namespace Hallucinate.UI
_rootElement.RegisterCallback<PointerDownEvent>(OnGlobalClick, TrickleDown.TrickleDown);
// Đăng ký sự kiện từ InputReader (Chuẩn New Input System)
if (inputReader != null)
{
inputReader.OnToggleSettingsEvent += ToggleSettings;
@@ -94,6 +95,29 @@ namespace Hallucinate.UI
}
#endif
InitializeControllers();
// KIỂM TRA LOGIN
CheckLoginStatus();
}
private void CheckLoginStatus()
{
string savedName = PlayerPrefs.GetString("Username", "");
if (string.IsNullOrEmpty(savedName))
{
_ = Push<LoginController>();
}
else
{
Debug.Log($"[UIManager] Welcome back, {savedName}!");
_ = Push<MainMenuController>();
}
}
public void OnLoginSuccess()
{
// Sau khi login xong thì hiện MainMenu
_ = Push<MainMenuController>();
}
private void OnDestroy()
@@ -117,6 +141,7 @@ namespace Hallucinate.UI
if (!_isSettingsOpen)
{
_isSettingsOpen = true;
_settingsController.Root.BringToFront();
_cursorLayer.BringToFront();
await _settingsController.PlayTransitionIn();
}
@@ -261,6 +286,7 @@ namespace Hallucinate.UI
private void InitializeControllers()
{
_loginController = RegisterController<LoginController>(loginTemplate);
_mainMenuController = RegisterController<MainMenuController>(mainMenuTemplate);
if (_mainMenuController != null && gameIcon != null) _mainMenuController.SetGameIcon(gameIcon);
@@ -268,8 +294,6 @@ namespace Hallucinate.UI
RegisterController<ProfileController>(profileTemplate);
_settingsController = RegisterController<SettingsController>(settingsTemplate);
RegisterController<HUDController>(hudTemplate);
_ = Push<MainMenuController>();
}
private T RegisterController<T>(VisualTreeAsset template) where T : BaseUIController, new()