Update
This commit is contained in:
14
.idea/.idea.HALLUCINATE/.idea/workspace.xml
generated
14
.idea/.idea.HALLUCINATE/.idea/workspace.xml
generated
@@ -11,21 +11,12 @@
|
|||||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="EmbeddingIndexingInfo">
|
<component name="EmbeddingIndexingInfo">
|
||||||
<option name="cachedIndexableFilesCount" value="1" />
|
<option name="cachedIndexableFilesCount" value="39" />
|
||||||
<option name="fileBasedEmbeddingIndicesEnabled" value="true" />
|
<option name="fileBasedEmbeddingIndicesEnabled" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="HighlightingSettingsPerFile">
|
|
||||||
<setting file="file://$PROJECT_DIR$/Assets/Scripts/Attributes/Health.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Assets/Scripts/Interactables/BaseInteractable.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Assets/Scripts/Interactables/HealthInteractable.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Assets/Scripts/UI/LobbyController.cs" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Assets/Third Parties/Photon/Fusion/Editor/Fusion.Unity.Editor.cs" root0="SKIP_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Assets/UI/MainPanelSettings.asset" root0="FORCE_HIGHLIGHTING" />
|
|
||||||
<setting file="file://$PROJECT_DIR$/Library/PackageCache/com.unity.ugui@bb329a87fcdc/Runtime/TMP/TMP_PackageResourceImporter.cs" root0="SKIP_HIGHLIGHTING" />
|
|
||||||
</component>
|
|
||||||
<component name="McpProjectServerCommands">
|
<component name="McpProjectServerCommands">
|
||||||
<commands />
|
<commands />
|
||||||
<urls />
|
<urls />
|
||||||
@@ -140,7 +131,8 @@
|
|||||||
<workItem from="1777150520438" duration="58000" />
|
<workItem from="1777150520438" duration="58000" />
|
||||||
<workItem from="1777150592854" duration="4699000" />
|
<workItem from="1777150592854" duration="4699000" />
|
||||||
<workItem from="1777181837663" duration="1519000" />
|
<workItem from="1777181837663" duration="1519000" />
|
||||||
<workItem from="1777269364664" duration="33315000" />
|
<workItem from="1777269364664" duration="40284000" />
|
||||||
|
<workItem from="1777373072815" duration="1852000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ namespace Hallucinate.UI
|
|||||||
protected VisualElement root;
|
protected VisualElement root;
|
||||||
protected UIManager uiManager;
|
protected UIManager uiManager;
|
||||||
|
|
||||||
|
public VisualElement Root => root; // Thêm thuộc tính này
|
||||||
|
|
||||||
public virtual void Initialize(VisualElement uxmlRoot, UIManager manager)
|
public virtual void Initialize(VisualElement uxmlRoot, UIManager manager)
|
||||||
{
|
{
|
||||||
root = uxmlRoot;
|
root = uxmlRoot;
|
||||||
|
|||||||
43
Assets/Scripts/UI/FirebaseService.cs
Normal file
43
Assets/Scripts/UI/FirebaseService.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/UI/FirebaseService.cs.meta
Normal file
2
Assets/Scripts/UI/FirebaseService.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bf13e7d21e483574882c6b687a6ae19c
|
||||||
90
Assets/Scripts/UI/LoginController.cs
Normal file
90
Assets/Scripts/UI/LoginController.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/UI/LoginController.cs.meta
Normal file
2
Assets/Scripts/UI/LoginController.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fbd606c21d317da47820446e4da1c55b
|
||||||
@@ -19,10 +19,12 @@ namespace Hallucinate.UI
|
|||||||
_tabTitle = root.Q<Label>("TabTitle");
|
_tabTitle = root.Q<Label>("TabTitle");
|
||||||
_content = root.Q<ScrollView>("SettingsContent");
|
_content = root.Q<ScrollView>("SettingsContent");
|
||||||
|
|
||||||
// Logic đóng khi nhấn vào vùng nền bên ngoài sidebar
|
// Đăng ký sự kiện Click vào vùng nền tối
|
||||||
root.RegisterCallback<ClickEvent>(evt => {
|
root.RegisterCallback<PointerDownEvent>(evt => {
|
||||||
|
// Nếu click trực tiếp vào SettingsRoot (không phải sidebar)
|
||||||
if (evt.target == root)
|
if (evt.target == root)
|
||||||
{
|
{
|
||||||
|
Debug.Log("[Settings] Clicked outside sidebar, closing...");
|
||||||
uiManager.ToggleSettings();
|
uiManager.ToggleSettings();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -43,14 +45,13 @@ namespace Hallucinate.UI
|
|||||||
|
|
||||||
public override async Task PlayTransitionIn()
|
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)
|
if (root != null)
|
||||||
{
|
{
|
||||||
root.style.translate = new StyleTranslate(new Translate(0, 0));
|
root.style.translate = new StyleTranslate(new Translate(0, 0));
|
||||||
root.style.display = DisplayStyle.Flex;
|
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));
|
_sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(-100), 0));
|
||||||
await Tween.Custom(-100f, 0f, duration: 0.4f, ease: Ease.OutQuad,
|
await Tween.Custom(-100f, 0f, duration: 0.4f, ease: Ease.OutQuad,
|
||||||
onValueChange: val => _sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
|
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()
|
public override async Task PlayTransitionOut()
|
||||||
{
|
{
|
||||||
// Trượt sidebar ra trái
|
|
||||||
await Tween.Custom(0f, -100f, duration: 0.4f, ease: Ease.InQuad,
|
await Tween.Custom(0f, -100f, duration: 0.4f, ease: Ease.InQuad,
|
||||||
onValueChange: val => _sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
|
onValueChange: val => _sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Threading.Tasks;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
using PrimeTween;
|
using PrimeTween;
|
||||||
using OnlyScove.Scripts; // Namespace của InputReader
|
using OnlyScove.Scripts;
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
#endif
|
#endif
|
||||||
@@ -40,12 +40,14 @@ namespace Hallucinate.UI
|
|||||||
[SerializeField] private Color rippleColor = new Color(1, 1, 1, 0.4f);
|
[SerializeField] private Color rippleColor = new Color(1, 1, 1, 0.4f);
|
||||||
|
|
||||||
[Header("UI Templates")]
|
[Header("UI Templates")]
|
||||||
|
[SerializeField] private VisualTreeAsset loginTemplate; // Template mới
|
||||||
[SerializeField] private VisualTreeAsset mainMenuTemplate;
|
[SerializeField] private VisualTreeAsset mainMenuTemplate;
|
||||||
[SerializeField] private VisualTreeAsset lobbyTemplate;
|
[SerializeField] private VisualTreeAsset lobbyTemplate;
|
||||||
[SerializeField] private VisualTreeAsset profileTemplate;
|
[SerializeField] private VisualTreeAsset profileTemplate;
|
||||||
[SerializeField] private VisualTreeAsset settingsTemplate;
|
[SerializeField] private VisualTreeAsset settingsTemplate;
|
||||||
[SerializeField] private VisualTreeAsset hudTemplate;
|
[SerializeField] private VisualTreeAsset hudTemplate;
|
||||||
|
|
||||||
|
private LoginController _loginController;
|
||||||
private MainMenuController _mainMenuController;
|
private MainMenuController _mainMenuController;
|
||||||
private SettingsController _settingsController;
|
private SettingsController _settingsController;
|
||||||
private List<VisualElement> _trailSegments = new List<VisualElement>();
|
private List<VisualElement> _trailSegments = new List<VisualElement>();
|
||||||
@@ -79,7 +81,6 @@ namespace Hallucinate.UI
|
|||||||
|
|
||||||
_rootElement.RegisterCallback<PointerDownEvent>(OnGlobalClick, TrickleDown.TrickleDown);
|
_rootElement.RegisterCallback<PointerDownEvent>(OnGlobalClick, TrickleDown.TrickleDown);
|
||||||
|
|
||||||
// Đăng ký sự kiện từ InputReader (Chuẩn New Input System)
|
|
||||||
if (inputReader != null)
|
if (inputReader != null)
|
||||||
{
|
{
|
||||||
inputReader.OnToggleSettingsEvent += ToggleSettings;
|
inputReader.OnToggleSettingsEvent += ToggleSettings;
|
||||||
@@ -94,6 +95,29 @@ namespace Hallucinate.UI
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
InitializeControllers();
|
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()
|
private void OnDestroy()
|
||||||
@@ -117,6 +141,7 @@ namespace Hallucinate.UI
|
|||||||
if (!_isSettingsOpen)
|
if (!_isSettingsOpen)
|
||||||
{
|
{
|
||||||
_isSettingsOpen = true;
|
_isSettingsOpen = true;
|
||||||
|
_settingsController.Root.BringToFront();
|
||||||
_cursorLayer.BringToFront();
|
_cursorLayer.BringToFront();
|
||||||
await _settingsController.PlayTransitionIn();
|
await _settingsController.PlayTransitionIn();
|
||||||
}
|
}
|
||||||
@@ -261,6 +286,7 @@ namespace Hallucinate.UI
|
|||||||
|
|
||||||
private void InitializeControllers()
|
private void InitializeControllers()
|
||||||
{
|
{
|
||||||
|
_loginController = RegisterController<LoginController>(loginTemplate);
|
||||||
_mainMenuController = RegisterController<MainMenuController>(mainMenuTemplate);
|
_mainMenuController = RegisterController<MainMenuController>(mainMenuTemplate);
|
||||||
if (_mainMenuController != null && gameIcon != null) _mainMenuController.SetGameIcon(gameIcon);
|
if (_mainMenuController != null && gameIcon != null) _mainMenuController.SetGameIcon(gameIcon);
|
||||||
|
|
||||||
@@ -268,8 +294,6 @@ namespace Hallucinate.UI
|
|||||||
RegisterController<ProfileController>(profileTemplate);
|
RegisterController<ProfileController>(profileTemplate);
|
||||||
_settingsController = RegisterController<SettingsController>(settingsTemplate);
|
_settingsController = RegisterController<SettingsController>(settingsTemplate);
|
||||||
RegisterController<HUDController>(hudTemplate);
|
RegisterController<HUDController>(hudTemplate);
|
||||||
|
|
||||||
_ = Push<MainMenuController>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private T RegisterController<T>(VisualTreeAsset template) where T : BaseUIController, new()
|
private T RegisterController<T>(VisualTreeAsset template) where T : BaseUIController, new()
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ MonoBehaviour:
|
|||||||
- folder: {fileID: 102900000, guid: 8c41df02b38b2ee40b792b146c0493f2, type: 3}
|
- folder: {fileID: 102900000, guid: 8c41df02b38b2ee40b792b146c0493f2, type: 3}
|
||||||
folderIcon: {fileID: 2800000, guid: 9687b8a9002844d4b8ece997ce390043, type: 3}
|
folderIcon: {fileID: 2800000, guid: 9687b8a9002844d4b8ece997ce390043, type: 3}
|
||||||
overlayIcon: {fileID: 0}
|
overlayIcon: {fileID: 0}
|
||||||
- folder: {fileID: 102900000, guid: 4e6e9b4a0c2e35242b749c3b025c2b6d, type: 3}
|
- folder: {fileID: 102900000, guid: 55d9223ee943a5248a49f0c45b440900, type: 3}
|
||||||
folderIcon: {fileID: 2800000, guid: f98ab23e70af0464ba10b820ef66cf70, type: 3}
|
folderIcon: {fileID: 2800000, guid: f98ab23e70af0464ba10b820ef66cf70, type: 3}
|
||||||
overlayIcon: {fileID: 0}
|
overlayIcon: {fileID: 0}
|
||||||
- folder: {fileID: 102900000, guid: e4342b7ac2b8c524bbfd5ed650d13a32, type: 3}
|
- folder: {fileID: 102900000, guid: e4342b7ac2b8c524bbfd5ed650d13a32, type: 3}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 4e6e9b4a0c2e35242b749c3b025c2b6d
|
guid: 55d9223ee943a5248a49f0c45b440900
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 80 KiB |
@@ -1,130 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d6e88709eb6360c4187aedc8a351b609
|
|
||||||
TextureImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 13
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 0
|
|
||||||
sRGBTexture: 1
|
|
||||||
linearTexture: 0
|
|
||||||
fadeOut: 0
|
|
||||||
borderMipMap: 0
|
|
||||||
mipMapsPreserveCoverage: 0
|
|
||||||
alphaTestReferenceValue: 0.5
|
|
||||||
mipMapFadeDistanceStart: 1
|
|
||||||
mipMapFadeDistanceEnd: 3
|
|
||||||
bumpmap:
|
|
||||||
convertToNormalMap: 0
|
|
||||||
externalNormalMap: 0
|
|
||||||
heightScale: 0.25
|
|
||||||
normalMapFilter: 0
|
|
||||||
flipGreenChannel: 0
|
|
||||||
isReadable: 0
|
|
||||||
streamingMipmaps: 0
|
|
||||||
streamingMipmapsPriority: 0
|
|
||||||
vTOnly: 0
|
|
||||||
ignoreMipmapLimit: 0
|
|
||||||
grayScaleToAlpha: 0
|
|
||||||
generateCubemap: 6
|
|
||||||
cubemapConvolution: 0
|
|
||||||
seamlessCubemap: 0
|
|
||||||
textureFormat: 1
|
|
||||||
maxTextureSize: 2048
|
|
||||||
textureSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
filterMode: 1
|
|
||||||
aniso: 1
|
|
||||||
mipBias: 0
|
|
||||||
wrapU: 1
|
|
||||||
wrapV: 1
|
|
||||||
wrapW: 0
|
|
||||||
nPOTScale: 0
|
|
||||||
lightmap: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
spriteMode: 1
|
|
||||||
spriteExtrude: 1
|
|
||||||
spriteMeshType: 1
|
|
||||||
alignment: 0
|
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
|
||||||
spritePixelsToUnits: 100
|
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
|
||||||
alphaUsage: 1
|
|
||||||
alphaIsTransparency: 1
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 8
|
|
||||||
textureShape: 1
|
|
||||||
singleChannelComponent: 0
|
|
||||||
flipbookRows: 1
|
|
||||||
flipbookColumns: 1
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
ignorePngGamma: 0
|
|
||||||
applyGammaDecoding: 0
|
|
||||||
swizzle: 50462976
|
|
||||||
cookieLightType: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 4
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 16384
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 2
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 4
|
|
||||||
buildTarget: Standalone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 4
|
|
||||||
buildTarget: Android
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
customData:
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID: 5e97eb03825dee720800000000000000
|
|
||||||
internalID: 0
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
secondaryTextures: []
|
|
||||||
spriteCustomMetadata:
|
|
||||||
entries: []
|
|
||||||
nameFileIdTable: {}
|
|
||||||
mipmapLimitGroupName:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,12 +1,51 @@
|
|||||||
/* Global Styles for Hallucinate UI */
|
/* Global Styles for Hallucinate UI */
|
||||||
|
/* osu!lazer-inspired — extends existing rules, nothing removed */
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
DESIGN TOKENS
|
||||||
|
============================================================ */
|
||||||
:root {
|
:root {
|
||||||
|
/* --- Giữ nguyên biến cũ --- */
|
||||||
--primary-color: #ffffff;
|
--primary-color: #ffffff;
|
||||||
--accent-color: #00ffcc;
|
--accent-color: #00ffcc;
|
||||||
--background-blur: rgba(0, 0, 0, 0.5);
|
--background-blur: rgba(0, 0, 0, 0.5);
|
||||||
--font-main: resource("Fonts/Ancient Medium SDF"); /* Place holder font */
|
--font-main: resource("Fonts/Ancient Medium SDF");
|
||||||
|
|
||||||
|
/* --- Spacing system (base 4px) --- */
|
||||||
|
--space-1: 4px;
|
||||||
|
--space-2: 8px;
|
||||||
|
--space-3: 12px;
|
||||||
|
--space-4: 16px;
|
||||||
|
--space-6: 24px;
|
||||||
|
--space-8: 32px;
|
||||||
|
|
||||||
|
/* --- Color system --- */
|
||||||
|
--color-surface: rgba(0, 0, 0, 0.65);
|
||||||
|
--color-surface-light: rgba(255, 255, 255, 0.06);
|
||||||
|
--color-border: rgba(255, 255, 255, 0.12);
|
||||||
|
--color-border-hover: rgba(255, 255, 255, 0.28);
|
||||||
|
|
||||||
|
/* Palette — mỗi nút 1 màu (giống osu) */
|
||||||
|
--color-btn-settings: #7B6EE8; /* tím */
|
||||||
|
--color-btn-join: #4DC8A0; /* teal */
|
||||||
|
--color-btn-create: #E8834D; /* cam */
|
||||||
|
--color-btn-profile: #E84D8A; /* hồng */
|
||||||
|
--color-btn-exit: #888888; /* xám trung tính */
|
||||||
|
|
||||||
|
/* Text */
|
||||||
|
--color-text-primary: rgba(255, 255, 255, 0.95);
|
||||||
|
--color-text-secondary: rgba(255, 255, 255, 0.55);
|
||||||
|
|
||||||
|
/* --- Border radius --- */
|
||||||
|
--radius-sm: 6px;
|
||||||
|
--radius-md: 10px;
|
||||||
|
--radius-lg: 16px;
|
||||||
|
--radius-pill: 999px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
BASE RESET
|
||||||
|
============================================================ */
|
||||||
.screen-root {
|
.screen-root {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -14,24 +53,277 @@
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
BUTTON — SPRING (giữ nguyên, chỉ thêm visual)
|
||||||
|
============================================================ */
|
||||||
.button-spring {
|
.button-spring {
|
||||||
|
/* --- Giữ nguyên animation cũ --- */
|
||||||
transition-duration: 0.1s;
|
transition-duration: 0.1s;
|
||||||
transition-timing-function: ease-out-back;
|
transition-timing-function: ease-out-back;
|
||||||
|
|
||||||
|
/* --- Thêm visual --- */
|
||||||
|
height: 48px;
|
||||||
|
padding-left: var(--space-4);
|
||||||
|
padding-right: var(--space-4);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border-width: 0;
|
||||||
|
-unity-font-definition: resource("Fonts/Ancient Medium SDF");
|
||||||
|
font-size: 15px;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
-unity-font-style: bold;
|
||||||
|
cursor: link;
|
||||||
|
|
||||||
|
/* Màu mặc định — bị override bởi modifier class bên dưới */
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-spring:hover {
|
.button-spring:hover {
|
||||||
scale: 1.05;
|
scale: 1.05;
|
||||||
|
background-color: rgba(255, 255, 255, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-spring:active {
|
.button-spring:active {
|
||||||
scale: 0.9;
|
scale: 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Per-button accent colors (gán thêm class vào UXML) */
|
||||||
|
.btn-settings { background-color: var(--color-btn-settings); }
|
||||||
|
.btn-settings:hover { background-color: #9080F0; }
|
||||||
|
|
||||||
|
.btn-join { background-color: var(--color-btn-join); }
|
||||||
|
.btn-join:hover { background-color: #60DEB8; }
|
||||||
|
|
||||||
|
.btn-create { background-color: var(--color-btn-create); }
|
||||||
|
.btn-create:hover { background-color: #F09A68; }
|
||||||
|
|
||||||
|
.btn-profile { background-color: var(--color-btn-profile); }
|
||||||
|
.btn-profile:hover { background-color: #F060A0; }
|
||||||
|
|
||||||
|
.btn-exit { background-color: var(--color-btn-exit); }
|
||||||
|
.btn-exit:hover { background-color: #AAAAAA; }
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
RIBBON — dải băng main menu
|
||||||
|
============================================================ */
|
||||||
|
.ribbon {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: var(--color-surface);
|
||||||
|
padding-top: var(--space-2);
|
||||||
|
padding-bottom: var(--space-2);
|
||||||
|
padding-left: var(--space-6);
|
||||||
|
padding-right: var(--space-6);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--color-border);
|
||||||
|
|
||||||
|
/* gap giữa các button */
|
||||||
|
/* Unity UIToolkit không có gap trực tiếp, dùng margin trên button */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spacing giữa các nút trong ribbon */
|
||||||
|
.ribbon .button-spring {
|
||||||
|
margin-left: var(--space-2);
|
||||||
|
margin-right: var(--space-2);
|
||||||
|
min-width: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
LOGO
|
||||||
|
============================================================ */
|
||||||
.logo-pulse {
|
.logo-pulse {
|
||||||
/* Pulse effect will be handled via PrimeTween in Controller,
|
|
||||||
but we can define base styles here */
|
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
/* Thêm visual */
|
||||||
|
border-radius: var(--radius-pill);
|
||||||
|
border-width: 2px;
|
||||||
|
border-color: var(--color-border-hover);
|
||||||
|
background-color: rgba(255, 255, 255, 0.08);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
SURFACE / PANEL — dùng cho Lobby, Profile, Settings
|
||||||
|
============================================================ */
|
||||||
|
.panel-glass {
|
||||||
|
background-color: var(--color-surface);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--color-border);
|
||||||
|
padding: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-glass--right {
|
||||||
|
/* Right pane trong Lobby / Profile */
|
||||||
|
width: 40%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 0;
|
||||||
|
border-top-left-radius: var(--radius-lg);
|
||||||
|
border-bottom-left-radius: var(--radius-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
TYPOGRAPHY
|
||||||
|
============================================================ */
|
||||||
|
.text-heading {
|
||||||
|
font-size: 28px;
|
||||||
|
-unity-font-style: bold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
-unity-font-definition: resource("Fonts/Ancient Medium SDF");
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
-unity-font-definition: resource("Fonts/Ancient Medium SDF");
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-body {
|
||||||
|
font-size: 15px;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
-unity-font-definition: resource("Fonts/Ancient Medium SDF");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
INPUT FIELD
|
||||||
|
============================================================ */
|
||||||
|
.input-field {
|
||||||
|
height: 44px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--color-border);
|
||||||
|
background-color: var(--color-surface-light);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
font-size: 14px;
|
||||||
|
padding-left: var(--space-3);
|
||||||
|
padding-right: var(--space-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-field:focus {
|
||||||
|
border-color: var(--color-border-hover);
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
SIDEBAR (Settings)
|
||||||
|
============================================================ */
|
||||||
|
.sidebar-tab {
|
||||||
|
height: 48px;
|
||||||
|
padding-left: var(--space-4);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
background-color: transparent;
|
||||||
|
border-width: 0;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
font-size: 14px;
|
||||||
|
-unity-text-align: middle-left;
|
||||||
|
margin-bottom: var(--space-1);
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-tab:hover {
|
||||||
|
background-color: var(--color-surface-light);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-tab.active-tab {
|
||||||
|
background-color: rgba(123, 110, 232, 0.2);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
border-left-color: var(--color-btn-settings);
|
||||||
|
border-left-width: 3px;
|
||||||
|
border-radius: 0;
|
||||||
|
border-top-right-radius: var(--radius-sm);
|
||||||
|
border-bottom-right-radius: var(--radius-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
HUD
|
||||||
|
============================================================ */
|
||||||
|
.hud-root {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
picking-mode: ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hud-bar {
|
||||||
|
border-radius: var(--radius-pill);
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--color-border);
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hud-slot {
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--color-border);
|
||||||
|
background-color: var(--color-surface);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hud-slot--active {
|
||||||
|
width: 72px;
|
||||||
|
height: 72px;
|
||||||
|
border-color: var(--color-border-hover);
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hud-text-debug {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
-unity-font-definition: resource("Fonts/Ancient Medium SDF");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
READY BUTTON (Lounge)
|
||||||
|
============================================================ */
|
||||||
|
.btn-ready {
|
||||||
|
height: 56px;
|
||||||
|
min-width: 160px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border-width: 2px;
|
||||||
|
border-color: var(--color-btn-join);
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--color-btn-join);
|
||||||
|
font-size: 16px;
|
||||||
|
-unity-font-style: bold;
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-ready.is-ready {
|
||||||
|
background-color: var(--color-btn-join);
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
SCROLL VIEW
|
||||||
|
============================================================ */
|
||||||
|
.scroll-list {
|
||||||
|
background-color: transparent;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-item {
|
||||||
|
height: 56px;
|
||||||
|
margin-bottom: var(--space-2);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background-color: var(--color-surface-light);
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--color-border);
|
||||||
|
padding-left: var(--space-4);
|
||||||
|
padding-right: var(--space-4);
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-item:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
border-color: var(--color-border-hover);
|
||||||
}
|
}
|
||||||
|
|||||||
14
Assets/UI/LoginPopup.uxml
Normal file
14
Assets/UI/LoginPopup.uxml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
|
||||||
|
<Style src="project:/Assets/UI/Global.uss" />
|
||||||
|
<ui:VisualElement name="LoginRoot" class="screen-root" style="background-color: rgba(0, 0, 0, 0.85); justify-content: center; align-items: center;">
|
||||||
|
<ui:VisualElement name="Window" style="width: 400px; padding: 30px; background-color: #1a1a1a; border-radius: 15px; border-width: 2px; border-color: #333;">
|
||||||
|
<ui:Label text="WELCOME TRAVELLER" style="font-size: 24px; -unity-font-style: bold; color: white; align-self: center; margin-bottom: 10px;" />
|
||||||
|
<ui:Label text="Enter your username to begin" style="font-size: 14px; color: #888; align-self: center; margin-bottom: 25px;" />
|
||||||
|
|
||||||
|
<ui:TextField name="UsernameInput" placeholder-text="Your name..." style="margin-bottom: 10px;" />
|
||||||
|
<ui:Label name="ErrorMsg" text="Name is already taken!" style="color: #ff4444; font-size: 12px; display: none; margin-bottom: 10px;" />
|
||||||
|
|
||||||
|
<ui:Button name="ConfirmBtn" text="CONFIRM" class="button-spring" style="height: 45px; background-color: #00ffcc; color: black; -unity-font-style: bold; margin-top: 10px;" />
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:VisualElement>
|
||||||
|
</ui:UXML>
|
||||||
10
Assets/UI/LoginPopup.uxml.meta
Normal file
10
Assets/UI/LoginPopup.uxml.meta
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4f11f2cb91fbd4748bcbc70cd0f5afe7
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
Reference in New Issue
Block a user