Organize custom scripts and Shared under Assets/Scripts, and delete assembly definition files
This commit is contained in:
181
.idea/.idea.BABA_YAGA/.idea/workspace.xml
generated
181
.idea/.idea.BABA_YAGA/.idea/workspace.xml
generated
@@ -7,7 +7,186 @@
|
||||
<configurations />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="d308d1cb-09fc-4331-ba20-00f7b43d1576" name="Changes" comment="" />
|
||||
<list default="true" id="d308d1cb-09fc-4331-ba20-00f7b43d1576" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/BehavourTreeCore.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/BehavourTreeCore.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/ChatBubble.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/ChatBubble.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/FieldOfView.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/FieldOfView.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/GeminiService.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/GeminiService.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/KamikazeAI.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/KamikazeAI.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/Sequence.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/AI NPC/Sequence.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Audio.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Camera.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Duy.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Duy/LobbyManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Duy/LobbyManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Game.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Game/EloData.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Game/EloData.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Game/EloSystem.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Game/EloSystem.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Game/MatchEloManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Game/MatchEloManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/CharacterAutoSetup.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/CharacterAutoSetup.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/CharacterSetupSettings.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/CharacterSetupSettings.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/GameSettings.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/GameSettings.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/CrawlerAlgorithm.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/CrawlerAlgorithm.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Extensions.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Extensions.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Interfaces.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Interfaces/IMazeAlgorithm.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Interfaces/IMazeAlgorithm.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MapLocation.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MapLocation.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeCellType.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeCellType.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeGrid.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeGrid.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeRenderer.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeRenderer.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeVisualProfile.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/MazeVisualProfile.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Native.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Native/NativeNoiseProvider.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/Native/NativeNoiseProvider.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/NoiseRecursiveGenerator.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/NoiseRecursiveGenerator.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/PrimsAlgorithm.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/PrimsAlgorithm.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/RecursiveAlgorithm.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/RecursiveAlgorithm.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/WilsonsAlgorithm.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/Maze/WilsonsAlgorithm.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/ObjectInteraction.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/ObjectInteraction.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/SettingsManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/GameSetup/SettingsManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Interaction.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Manager.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Manager/GameManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Manager/GameManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/BasicSpawner.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/BasicSpawner.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/FusionClientMovementBridge.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/FusionClientMovementBridge.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/MatchResultManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/MatchResultManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerData.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerData.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerDataManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerDataManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerInfo.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerInfo.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerInputData.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Network/PlayerInputData.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Others.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Others/StickyNote.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Others/StickyNote.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Player.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Trap.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Trap/TeleportTrap.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Trap/TeleportTrap.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Tuấn.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Tuấn/Plan.txt" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/Tuấn/Plan.txt.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/BaseUIController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/BaseUIController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/Components.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/Components/VectorShapeElement.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/Components/VectorShapeElement.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/FirebaseConfig.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/FirebaseConfig.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/FirebaseService.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/FirebaseService.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/FirebaseTest.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/FirebaseTest.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/HUDController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/HUDController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/LobbyController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/LobbyController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/LocalizationManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/LocalizationManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/LoginController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/LoginController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/MainMenuController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/MainMenuController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/MouseMetricsHelper.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/MouseMetricsHelper.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/PauseMenuController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/PauseMenuController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/PerformanceOverlay.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/PerformanceOverlay.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/ProfileController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/ProfileController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/SettingsController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/SettingsController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/UIAudioHelper.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/UIAudioHelper.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/UIManager.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/UI/UIManager.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SlashMeshGenerator.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SlashMeshGenerator.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaAbilityController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaAbilityController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaDomainController.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaDomainController.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaProjectile.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaProjectile.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaSlashEffect.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Baba_yaga/VFX/SukunaSlashEffect.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/DomainResetter.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/DomainResetter.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Game.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Game/Opsive.Shared.Editor.Game.dll" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Game/Opsive.Shared.Editor.Game.dll.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Opsive.Shared.Editor.asmdef" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Opsive.Shared.Editor.asmdef.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Utility.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Utility/Opsive.Shared.Editor.Utility.dll" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Editor/Utility/Opsive.Shared.Editor.Utility.dll.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Events.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Events/Opsive.Shared.Events.dll" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Events/Opsive.Shared.Events.dll.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Game.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Game/ObjectPool.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Game/ObjectPool.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Game/Opsive.Shared.Game.dll" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Game/Opsive.Shared.Game.dll.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Game/Scheduler.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Game/Scheduler.cs.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Inventory.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Inventory/Opsive.Shared.Inventory.dll" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Inventory/Opsive.Shared.Inventory.dll.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Opsive.Shared.asmdef" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Opsive.Shared.asmdef.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Utility.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Utility/Opsive.Shared.Utility.dll" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/Shared/Utility/Opsive.Shared.Utility.dll.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/UltimateCharacterController_Documentation.pdf" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/UltimateCharacterController_Documentation.pdf.meta" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/UltimateCharacterController_README.txt" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Assets/UltimateCharacterController_README.txt.meta" beforeDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using PrimeTween;
|
||||
using System.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using Tween = PrimeTween.Tween;
|
||||
using Ease = PrimeTween.Ease;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
public abstract class BaseUIController : ScriptableObject
|
||||
{
|
||||
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;
|
||||
uiManager = manager;
|
||||
|
||||
// Đảm bảo ban đầu ẩn hết
|
||||
Hide();
|
||||
|
||||
// Tự động gán âm thanh phản hồi cho các UI elements
|
||||
UIAudioHelper.BindFeedback(root);
|
||||
}
|
||||
|
||||
public virtual void Show()
|
||||
{
|
||||
if (root != null)
|
||||
{
|
||||
root.style.display = DisplayStyle.Flex;
|
||||
root.style.opacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Hide()
|
||||
{
|
||||
if (root != null)
|
||||
{
|
||||
root.style.display = DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetLoc(string key)
|
||||
{
|
||||
if (LocalizationManager.Instance != null)
|
||||
return LocalizationManager.Instance.GetLocalizedString(key);
|
||||
return key;
|
||||
}
|
||||
|
||||
public virtual void Update() { }
|
||||
|
||||
/*public virtual async Task PlayTransitionIn()
|
||||
{
|
||||
if (root == null) return;
|
||||
|
||||
Show();
|
||||
// Reset vị trí mặc định để tránh lỗi trôi màn hình
|
||||
root.style.translate = new StyleTranslate(new Translate(Length.Percent(100), 0));
|
||||
|
||||
await Tween.Custom(100f, 0f, duration: 0.5f, ease: Ease.OutBack,
|
||||
onValueChange: val => root.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
|
||||
}
|
||||
|
||||
public virtual async Task PlayTransitionOut()
|
||||
{
|
||||
if (root == null) return;
|
||||
|
||||
await Tween.Custom(0f, -100f, duration: 0.5f, ease: Ease.InBack,
|
||||
onValueChange: val => root.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
|
||||
|
||||
Hide();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 872f8bfaee91588488a3393579135de9
|
||||
@@ -1,11 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[CreateAssetMenu(fileName = "FirebaseConfig", menuName = "BABA_YAGA/Configs/FirebaseConfig")]
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class FirebaseConfig : ScriptableObject
|
||||
{
|
||||
public string baseUrl;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0551a27408b84c040a2e009ae17debde
|
||||
@@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
public static class FirebaseService
|
||||
{
|
||||
private static string _baseUrl;
|
||||
|
||||
private static string BASE_URL
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_baseUrl))
|
||||
{
|
||||
// Nó sẽ tìm file tên "FirebaseConfig" trong bất kỳ folder "Resources" nào
|
||||
var config = Resources.Load<FirebaseConfig>("FirebaseConfig");
|
||||
if (config != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(config.baseUrl))
|
||||
{
|
||||
Debug.LogError("<color=red>[FirebaseService]</color> Base URL trong file FirebaseConfig đang trống!");
|
||||
return null;
|
||||
}
|
||||
_baseUrl = config.baseUrl.TrimEnd('/');
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("<color=red>[FirebaseService]</color> Không tìm thấy file 'FirebaseConfig' trong folder Resources! " +
|
||||
"Hãy đảm bảo bạn đã tạo file tại: Assets/.../Resources/FirebaseConfig");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return _baseUrl + "/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<Baba_yaga.Game.PlayerEloData> GetPlayerData(string username)
|
||||
{
|
||||
string url = $"{BASE_URL}/{username}/elo.json";
|
||||
using (UnityWebRequest request = UnityWebRequest.Get(url))
|
||||
{
|
||||
var operation = request.SendWebRequest();
|
||||
while (!operation.isDone) await Task.Yield();
|
||||
|
||||
if (request.result != UnityWebRequest.Result.Success || request.downloadHandler.text == "null")
|
||||
{
|
||||
return Baba_yaga.Game.PlayerEloData.Default;
|
||||
}
|
||||
|
||||
return JsonUtility.FromJson<Baba_yaga.Game.PlayerEloData>(request.downloadHandler.text);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<bool> SavePlayerData(string username, Baba_yaga.Game.PlayerEloData data)
|
||||
{
|
||||
string url = $"{BASE_URL}/{username}/elo.json";
|
||||
string jsonData = JsonUtility.ToJson(data);
|
||||
|
||||
using (UnityWebRequest request = UnityWebRequest.Put(url, jsonData))
|
||||
{
|
||||
var operation = request.SendWebRequest();
|
||||
while (!operation.isDone) await Task.Yield();
|
||||
|
||||
return request.result == UnityWebRequest.Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf13e7d21e483574882c6b687a6ae19c
|
||||
@@ -1,45 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Baba_yaga.UI;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class FirebaseTest : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
[SerializeField] private string testUsername = "TuanPlayer_01";
|
||||
|
||||
async void Start()
|
||||
{
|
||||
Debug.Log("<color=cyan>--- Firebase Test Started ---</color>");
|
||||
|
||||
// Bước 1: Kiểm tra xem username đã tồn tại chưa
|
||||
Debug.Log($"[Firebase] Đang kiểm tra username: {testUsername}...");
|
||||
bool isTaken = await FirebaseService.IsUsernameTaken(testUsername);
|
||||
|
||||
if (isTaken)
|
||||
{
|
||||
Debug.Log($"<color=yellow>[Firebase] Username '{testUsername}' đã tồn tại trên Database!</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"<color=green>[Firebase] Username '{testUsername}' còn trống. Tiến hành đăng ký...</color>");
|
||||
|
||||
// // Bước 2: Thử đăng ký user mới
|
||||
// bool success = await FirebaseService.RegisterUser(testUsername);
|
||||
//
|
||||
// if (success)
|
||||
// {
|
||||
// Debug.Log("<color=green>[Firebase] Đăng ký thành công! Hãy kiểm tra trình duyệt (Firebase Console).</color>");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Debug.LogError("[Firebase] Đăng ký thất bại. Kiểm tra link URL hoặc Internet.");
|
||||
// }
|
||||
}
|
||||
|
||||
Debug.Log("<color=cyan>--- Firebase Test Finished ---</color>");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db205c30e8f41d84fa79269745feaf84
|
||||
@@ -1,112 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using PrimeTween;
|
||||
using System.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using Tween = PrimeTween.Tween;
|
||||
using Ease = PrimeTween.Ease;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class HUDController : BaseUIController
|
||||
{
|
||||
private VisualElement _topLeft;
|
||||
private VisualElement _bottomLeft;
|
||||
|
||||
private ProgressBar _healthBar;
|
||||
private ProgressBar _staminaBar;
|
||||
|
||||
private float _lastActionTime;
|
||||
private const float FADE_TIMEOUT = 5.0f;
|
||||
private bool _isFaded = false;
|
||||
|
||||
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
|
||||
{
|
||||
base.Initialize(uxmlRoot, manager);
|
||||
|
||||
_topLeft = root.Q<VisualElement>("TopLeft");
|
||||
_bottomLeft = root.Q<VisualElement>("BottomLeft");
|
||||
_healthBar = root.Q<ProgressBar>("HealthBar");
|
||||
_staminaBar = root.Q<ProgressBar>("StaminaBar");
|
||||
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
LocalizationManager.Instance.OnLanguageChanged += ApplyLocalization;
|
||||
ApplyLocalization();
|
||||
}
|
||||
|
||||
_lastActionTime = Time.time;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
LocalizationManager.Instance.OnLanguageChanged -= ApplyLocalization;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLocalization()
|
||||
{
|
||||
if (LocalizationManager.Instance == null) return;
|
||||
|
||||
root.Query<Label>().ForEach(l => {
|
||||
if (l.text == "HEALTH") l.text = LocalizationManager.Instance.GetLocalizedString("HUD_HEALTH");
|
||||
if (l.text == "STAMINA") l.text = LocalizationManager.Instance.GetLocalizedString("HUD_STAMINA");
|
||||
if (l.text == "MINIMAP") l.text = LocalizationManager.Instance.GetLocalizedString("HUD_MINIMAP");
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateHUD(float health, float stamina)
|
||||
{
|
||||
_healthBar.value = health;
|
||||
_staminaBar.value = stamina;
|
||||
WakeUpHUD();
|
||||
}
|
||||
|
||||
public void UpdateStats(int ping, int fps)
|
||||
{
|
||||
string pingPrefix = LocalizationManager.Instance != null ? LocalizationManager.Instance.GetLocalizedString("HUD_PING_PREFIX") : "PING: ";
|
||||
string fpsPrefix = LocalizationManager.Instance != null ? LocalizationManager.Instance.GetLocalizedString("HUD_FPS_PREFIX") : "FPS: ";
|
||||
|
||||
root.Q<Label>("PingLabel").text = $"{pingPrefix}{ping}ms";
|
||||
root.Q<Label>("FPSLabel").text = $"{fpsPrefix}{fps}";
|
||||
}
|
||||
|
||||
public void WakeUpHUD()
|
||||
{
|
||||
_lastActionTime = Time.time;
|
||||
/*if (_isFaded)
|
||||
{
|
||||
_isFaded = false;
|
||||
Tween.Custom(_topLeft.style.opacity.value, 1f, duration: 0.3f, onValueChange: val => _topLeft.style.opacity = val);
|
||||
Tween.Custom(_bottomLeft.style.opacity.value, 1f, duration: 0.3f, onValueChange: val => _bottomLeft.style.opacity = val);
|
||||
}*/
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
/*if (!_isFaded && Time.time - _lastActionTime > FADE_TIMEOUT)
|
||||
{
|
||||
_isFaded = true;
|
||||
Tween.Custom(_topLeft.style.opacity.value, 0.2f, duration: 1.0f, onValueChange: val => _topLeft.style.opacity = val);
|
||||
Tween.Custom(_bottomLeft.style.opacity.value, 0.2f, duration: 1.0f, onValueChange: val => _bottomLeft.style.opacity = val);
|
||||
}*/
|
||||
}
|
||||
|
||||
/*public override Task PlayTransitionIn()
|
||||
{
|
||||
Show();
|
||||
_topLeft.style.opacity = 1;
|
||||
_bottomLeft.style.opacity = 1;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task PlayTransitionOut()
|
||||
{
|
||||
Hide();
|
||||
return Task.CompletedTask;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e79b70607af6eeb458c8eb6605e39b56
|
||||
@@ -1,489 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Fusion;
|
||||
using System.Linq;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class LobbyController : BaseUIController
|
||||
{
|
||||
private VisualTreeAsset _roomItemTemplate;
|
||||
private PlayerDataManager _playerDataManager;
|
||||
|
||||
private VisualElement _joinContainer, _createContainer, _loungeContainer, _passOverlay;
|
||||
private TextField _roomIDInput, _roomNameInput, _roomPassInput;
|
||||
private Toggle _passToggle;
|
||||
private Label _createErrorLabel;
|
||||
private Button _confirmCreateBtn;
|
||||
private ScrollView _roomList;
|
||||
private TextField _joinPassInput;
|
||||
private Label _joinPassError;
|
||||
private SessionInfo _selectedSession;
|
||||
private Label _loungeRoomName;
|
||||
private Button _readyBtn, _startBtn;
|
||||
private Label _hostNameLabel, _hostStatusLabel;
|
||||
private VisualElement _hostChatBox;
|
||||
private Label _hostChatMessage;
|
||||
private Label _guestNameLabel, _guestStatusLabel;
|
||||
private VisualElement _guestChatBox;
|
||||
private Label _guestChatMessage;
|
||||
private TextField _chatInput;
|
||||
|
||||
private VisualElement _hostAvatar, _guestAvatar;
|
||||
private VisualElement _transferHostOverlay;
|
||||
private Button _confirmTransferBtn, _closeTransferBtn;
|
||||
private PlayerRef _pendingTransferPlayer;
|
||||
|
||||
private bool _isBusy = false;
|
||||
|
||||
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
|
||||
{
|
||||
base.Initialize(uxmlRoot, manager);
|
||||
_joinContainer = root.Q<VisualElement>("JoinContainer");
|
||||
_createContainer = root.Q<VisualElement>("CreateContainer");
|
||||
_loungeContainer = root.Q<VisualElement>("LoungeContainer");
|
||||
_passOverlay = root.Q<VisualElement>("PasswordOverlay");
|
||||
_roomIDInput = root.Q<TextField>("RoomIDInput");
|
||||
_roomNameInput = root.Q<TextField>("RoomNameInput");
|
||||
_roomPassInput = root.Q<TextField>("RoomPassInput");
|
||||
_passToggle = root.Q<Toggle>("PassToggle");
|
||||
_createErrorLabel = root.Q<Label>("CreateErrorLabel");
|
||||
_roomList = root.Q<ScrollView>("RoomList");
|
||||
_joinPassInput = root.Q<TextField>("JoinPassInput");
|
||||
_joinPassError = root.Q<Label>("JoinPassError");
|
||||
_loungeRoomName = root.Q<Label>("LoungeRoomName");
|
||||
_readyBtn = root.Q<Button>("ReadyBtn");
|
||||
_startBtn = root.Q<Button>("StartBtn");
|
||||
if (_startBtn != null) _startBtn.style.display = DisplayStyle.None; // Default to hidden
|
||||
_hostNameLabel = root.Q<Label>("HostName");
|
||||
_hostStatusLabel = root.Q<Label>("HostReadyStatus");
|
||||
_hostChatBox = root.Q<VisualElement>("HostChatBox");
|
||||
_hostChatMessage = root.Q<Label>("HostChatMessage");
|
||||
_guestNameLabel = root.Q<Label>("GuestName");
|
||||
_guestStatusLabel = root.Q<Label>("GuestReadyStatus");
|
||||
_guestChatBox = root.Q<VisualElement>("GuestChatBox");
|
||||
_guestChatMessage = root.Q<Label>("GuestChatMessage");
|
||||
_chatInput = root.Q<TextField>("ChatInput");
|
||||
|
||||
_hostAvatar = root.Q<VisualElement>("HostAvatar");
|
||||
_guestAvatar = root.Q<VisualElement>("GuestAvatar");
|
||||
_transferHostOverlay = root.Q<VisualElement>("TransferHostOverlay");
|
||||
_confirmTransferBtn = root.Q<Button>("ConfirmTransferBtn");
|
||||
_closeTransferBtn = root.Q<Button>("CloseTransferBtn");
|
||||
|
||||
root.Q<Button>("GoToCreateBtn").clicked += ShowCreate;
|
||||
root.Q<Button>("CancelCreateBtn").clicked += ShowJoin;
|
||||
/*root.Q<Button>("BackToMenuBtn").clicked += async () => { if (_isBusy) return; await uiManager.Pop(); };*/
|
||||
_confirmCreateBtn = root.Q<Button>("ConfirmCreateBtn");
|
||||
if (_confirmCreateBtn != null) _confirmCreateBtn.clicked += OnCreateRoomClicked;
|
||||
root.Q<Button>("ConfirmJoinBtn").clicked += OnConfirmPasswordClicked;
|
||||
root.Q<Button>("ClosePassBtn").clicked += () => { if(_passOverlay != null) _passOverlay.style.display = DisplayStyle.None; };
|
||||
root.Q<Button>("LeaveLoungeBtn").clicked += OnLeaveLoungeClicked;
|
||||
|
||||
if (_readyBtn != null) _readyBtn.clicked += OnReadyClicked;
|
||||
if (_startBtn != null) _startBtn.clicked += OnStartClicked;
|
||||
if (_passToggle != null) _passToggle.RegisterValueChangedCallback(evt => { if (_roomPassInput != null) _roomPassInput.style.display = evt.newValue ? DisplayStyle.Flex : DisplayStyle.None; });
|
||||
if (_chatInput != null) _chatInput.RegisterCallback<KeyDownEvent>(OnChatKeyDown, TrickleDown.TrickleDown);
|
||||
|
||||
if (_hostAvatar != null) _hostAvatar.RegisterCallback<ClickEvent>(evt => OnAvatarClicked(true));
|
||||
if (_guestAvatar != null) _guestAvatar.RegisterCallback<ClickEvent>(evt => OnAvatarClicked(false));
|
||||
if (_confirmTransferBtn != null) _confirmTransferBtn.clicked += OnConfirmTransferHost;
|
||||
if (_closeTransferBtn != null) _closeTransferBtn.clicked += () => { if(_transferHostOverlay != null) _transferHostOverlay.style.display = DisplayStyle.None; };
|
||||
|
||||
if (LocalizationManager.Instance != null) { LocalizationManager.Instance.OnLanguageChanged += ApplyLocalization; ApplyLocalization(); }
|
||||
if (BasicSpawner.Instance != null) RegisterSpawnerEvents();
|
||||
else Invoke(nameof(RegisterSpawnerEvents), 0.1f);
|
||||
}
|
||||
|
||||
private void RegisterSpawnerEvents()
|
||||
{
|
||||
if (BasicSpawner.Instance == null) return;
|
||||
BasicSpawner.Instance.OnSessionListUpdatedEvent += UpdateRoomList;
|
||||
BasicSpawner.Instance.OnJoinFailedEvent += () => { if(_joinPassError != null) _joinPassError.style.display = DisplayStyle.Flex; };
|
||||
}
|
||||
|
||||
private void OnChatKeyDown(KeyDownEvent evt)
|
||||
{
|
||||
if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)
|
||||
{
|
||||
evt.StopImmediatePropagation();
|
||||
evt.PreventDefault();
|
||||
string msg = _chatInput.value.Trim();
|
||||
if (!string.IsNullOrEmpty(msg) && PlayerDataManager.Instance != null)
|
||||
{
|
||||
var runner = BasicSpawner.Instance.Runner;
|
||||
if (runner != null) { PlayerDataManager.Instance.RPC_SendChatMessage(runner.LocalPlayer, msg); _chatInput.value = ""; _chatInput.Focus(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnChatMessageReceived(PlayerRef sender, string message)
|
||||
{
|
||||
var runner = BasicSpawner.Instance.Runner;
|
||||
if (runner == null) return;
|
||||
var sortedPlayers = runner.ActivePlayers.OrderBy(p => p.PlayerId).ToList();
|
||||
bool isHost = sortedPlayers.Count > 0 && sender == sortedPlayers[0];
|
||||
if (isHost) ShowChatBubble(_hostChatBox, _hostChatMessage, message);
|
||||
else ShowChatBubble(_guestChatBox, _guestChatMessage, message);
|
||||
}
|
||||
|
||||
private async void ShowChatBubble(VisualElement box, Label label, string msg)
|
||||
{
|
||||
if (box == null || label == null) return;
|
||||
label.text = msg;
|
||||
box.style.display = DisplayStyle.Flex;
|
||||
await Task.Delay(4000);
|
||||
if (label.text == msg) box.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
private void ApplyLocalization() { if (LocalizationManager.Instance == null) return; }
|
||||
private string GetT(string key) => LocalizationManager.Instance != null ? LocalizationManager.Instance.GetLocalizedString(key) : key;
|
||||
public void SetRoomTemplate(VisualTreeAsset template) => _roomItemTemplate = template;
|
||||
|
||||
/*public override async Task PlayTransitionIn()
|
||||
{
|
||||
_isBusy = false;
|
||||
await base.PlayTransitionIn();
|
||||
ShowJoin();
|
||||
}*/
|
||||
|
||||
public void ShowJoin()
|
||||
{
|
||||
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.Flex;
|
||||
if (_createContainer != null) _createContainer.style.display = DisplayStyle.None;
|
||||
if (_loungeContainer != null) _loungeContainer.style.display = DisplayStyle.None;
|
||||
var spawner = BasicSpawner.Instance;
|
||||
if (spawner != null && (spawner.Runner == null || !spawner.Runner.IsRunning)) _ = spawner.StartLobby();
|
||||
}
|
||||
|
||||
public void ShowCreate()
|
||||
{
|
||||
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.None;
|
||||
if (_createContainer != null) _createContainer.style.display = DisplayStyle.Flex;
|
||||
if (_createErrorLabel != null) _createErrorLabel.style.display = DisplayStyle.None;
|
||||
if (_confirmCreateBtn != null) _confirmCreateBtn.SetEnabled(true);
|
||||
if (_roomIDInput != null) _roomIDInput.value = "ROOM_" + Random.Range(1000, 9999).ToString();
|
||||
}
|
||||
|
||||
private void ShowLounge(string roomName)
|
||||
{
|
||||
if (_joinContainer != null) _joinContainer.style.display = DisplayStyle.None;
|
||||
if (_createContainer != null) _createContainer.style.display = DisplayStyle.None;
|
||||
if (_loungeContainer != null) _loungeContainer.style.display = DisplayStyle.Flex;
|
||||
if (_loungeRoomName != null) _loungeRoomName.text = roomName.ToUpper();
|
||||
var spawner = BasicSpawner.Instance;
|
||||
if (spawner != null && spawner.Runner != null && spawner.Runner.SessionInfo != null)
|
||||
{
|
||||
var loungeIdLabel = root.Q<Label>("LoungeID");
|
||||
if (loungeIdLabel != null) loungeIdLabel.text = GetT("LOBBY_ID_PREFIX") + spawner.Runner.SessionInfo.Name;
|
||||
}
|
||||
_playerDataManager = PlayerDataManager.Instance;
|
||||
if (_playerDataManager != null) _playerDataManager.OnChatMessageReceived += OnChatMessageReceived;
|
||||
}
|
||||
|
||||
private async void OnCreateRoomClicked()
|
||||
{
|
||||
if (_isBusy) return;
|
||||
_isBusy = true;
|
||||
|
||||
if (_confirmCreateBtn != null) _confirmCreateBtn.SetEnabled(false);
|
||||
if (_createErrorLabel != null) _createErrorLabel.style.display = DisplayStyle.None;
|
||||
|
||||
var spawner = BasicSpawner.Instance;
|
||||
if (spawner == null)
|
||||
{
|
||||
ShowCreateError("System Error: Spawner missing. Please re-enter the Lobby.");
|
||||
_isBusy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
string id = (_roomIDInput != null && !string.IsNullOrEmpty(_roomIDInput.value)) ? _roomIDInput.value.Trim() : "ROOM_" + Random.Range(1000, 9999).ToString();
|
||||
string name = (_roomNameInput != null && !string.IsNullOrEmpty(_roomNameInput.value)) ? _roomNameInput.value.Trim() : id;
|
||||
string pass = (_passToggle != null && _passToggle.value && _roomPassInput != null) ? _roomPassInput.value : null;
|
||||
|
||||
try
|
||||
{
|
||||
bool success = await spawner.StartHost(id, name, pass);
|
||||
if (success) ShowLounge(name);
|
||||
else ShowCreateError("Failed to create room. ID might be taken.");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
ShowCreateError("Network Error: " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isBusy = false;
|
||||
if (_confirmCreateBtn != null) _confirmCreateBtn.SetEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowCreateError(string message)
|
||||
{
|
||||
if (_createErrorLabel != null) { _createErrorLabel.text = message; _createErrorLabel.style.display = DisplayStyle.Flex; }
|
||||
if (_confirmCreateBtn != null) _confirmCreateBtn.SetEnabled(true);
|
||||
}
|
||||
|
||||
private void UpdateRoomList(List<SessionInfo> sessions)
|
||||
{
|
||||
if (_roomList == null) return;
|
||||
_roomList.Clear();
|
||||
foreach (var session in sessions)
|
||||
{
|
||||
if (_roomItemTemplate == null) continue;
|
||||
var item = _roomItemTemplate.Instantiate();
|
||||
string displayName = session.Name;
|
||||
if (session.Properties.TryGetValue("rn", out var rnProp)) displayName = rnProp;
|
||||
item.Q<Label>("RoomName").text = displayName;
|
||||
item.Q<Label>("PlayerCount").text = $"{session.PlayerCount}/{session.MaxPlayers}";
|
||||
var statusBadge = item.Q<Label>("StatusBadge");
|
||||
if (statusBadge != null) statusBadge.text = GetT("ROOM_STATUS_WAITING");
|
||||
bool needsPass = session.Properties.ContainsKey("pw");
|
||||
var lockIcon = item.Q<Label>("LockIcon");
|
||||
if (lockIcon != null) lockIcon.style.display = needsPass ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
var joinBtn = item.Q<Button>("JoinBtn");
|
||||
if (joinBtn != null) { joinBtn.text = GetT("ROOM_JOIN_BTN"); joinBtn.clicked += () => OnRoomItemClicked(session); }
|
||||
_roomList.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnRoomItemClicked(SessionInfo session)
|
||||
{
|
||||
if (_isBusy) return;
|
||||
|
||||
bool needsPass = session.Properties.ContainsKey("pw");
|
||||
if (needsPass)
|
||||
{
|
||||
_selectedSession = session;
|
||||
if (_passOverlay != null) _passOverlay.style.display = DisplayStyle.Flex;
|
||||
if (_joinPassError != null) _joinPassError.style.display = DisplayStyle.None;
|
||||
if (_joinPassInput != null) _joinPassInput.value = "";
|
||||
}
|
||||
else await JoinRoom(session.Name, null);
|
||||
}
|
||||
|
||||
private async void OnConfirmPasswordClicked()
|
||||
{
|
||||
if (_isBusy || _selectedSession == null) return;
|
||||
_isBusy = true;
|
||||
|
||||
string pass = _joinPassInput != null ? _joinPassInput.value : "";
|
||||
if (_passOverlay != null) _passOverlay.style.display = DisplayStyle.None;
|
||||
await JoinRoom(_selectedSession.Name, pass);
|
||||
_isBusy = false;
|
||||
}
|
||||
|
||||
private async Task JoinRoom(string sessionName, string password)
|
||||
{
|
||||
if (BasicSpawner.Instance != null)
|
||||
{
|
||||
if (await BasicSpawner.Instance.StartClient(sessionName, password)) ShowLounge(sessionName);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnReadyClicked()
|
||||
{
|
||||
if (_isBusy) return;
|
||||
var runner = BasicSpawner.Instance.Runner;
|
||||
if (runner != null && _playerDataManager != null && _playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData))
|
||||
_playerDataManager.RPC_SetReady(runner.LocalPlayer, !myData.IsReady);
|
||||
}
|
||||
|
||||
private void OnStartClicked()
|
||||
{
|
||||
if (_isBusy) return;
|
||||
BasicSpawner.Instance?.StartGame();
|
||||
}
|
||||
|
||||
private void OnAvatarClicked(bool isHostSlot)
|
||||
{
|
||||
if (_playerDataManager == null || _playerDataManager.Leader != BasicSpawner.Instance.Runner.LocalPlayer) return;
|
||||
|
||||
var runner = BasicSpawner.Instance.Runner;
|
||||
var sortedPlayers = runner.ActivePlayers.OrderBy(p => p.PlayerId).ToList();
|
||||
|
||||
PlayerRef clickedPlayer = PlayerRef.None;
|
||||
if (isHostSlot && sortedPlayers.Count > 0) clickedPlayer = sortedPlayers[0];
|
||||
else if (!isHostSlot && sortedPlayers.Count > 1) clickedPlayer = sortedPlayers[1];
|
||||
|
||||
if (clickedPlayer != PlayerRef.None && clickedPlayer != runner.LocalPlayer)
|
||||
{
|
||||
_pendingTransferPlayer = clickedPlayer;
|
||||
if (_transferHostOverlay != null) _transferHostOverlay.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConfirmTransferHost()
|
||||
{
|
||||
if (_pendingTransferPlayer != PlayerRef.None && _playerDataManager != null)
|
||||
{
|
||||
_playerDataManager.RPC_TransferLeader(_pendingTransferPlayer);
|
||||
if (_transferHostOverlay != null) _transferHostOverlay.style.display = DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnLeaveLoungeClicked()
|
||||
{
|
||||
if (_isBusy) return;
|
||||
_isBusy = true;
|
||||
|
||||
var runner = BasicSpawner.Instance.Runner;
|
||||
if (runner != null) await runner.Shutdown(false);
|
||||
if (_playerDataManager != null) _playerDataManager.OnChatMessageReceived -= OnChatMessageReceived;
|
||||
ShowJoin();
|
||||
|
||||
_isBusy = false;
|
||||
}
|
||||
|
||||
public override void Update() { if (_loungeContainer != null && _loungeContainer.style.display == DisplayStyle.Flex) UpdateLoungeUI(); }
|
||||
|
||||
private void UpdateLoungeUI()
|
||||
{
|
||||
var spawner = BasicSpawner.Instance;
|
||||
if (spawner == null) return;
|
||||
var runner = spawner.Runner;
|
||||
if (runner == null) return;
|
||||
|
||||
// 1. PlayerDataManager Sync
|
||||
if (_playerDataManager == null || _playerDataManager.Object == null || !_playerDataManager.Object.IsValid)
|
||||
{
|
||||
_playerDataManager = PlayerDataManager.Instance;
|
||||
if (_playerDataManager != null)
|
||||
{
|
||||
_playerDataManager.OnChatMessageReceived += OnChatMessageReceived;
|
||||
}
|
||||
else return; // Still waiting for synchronization
|
||||
}
|
||||
|
||||
// 2. Identify Players
|
||||
var sortedPlayers = runner.ActivePlayers.OrderBy(p => p.PlayerId).ToList();
|
||||
PlayerRef hostRef = sortedPlayers.Count > 0 ? sortedPlayers[0] : PlayerRef.None;
|
||||
PlayerRef guestRef = sortedPlayers.Count > 1 ? sortedPlayers[1] : PlayerRef.None;
|
||||
PlayerRef leaderRef = _playerDataManager.Leader;
|
||||
|
||||
// 3. Strict Visibility Check (Leader Only)
|
||||
bool isLeader = runner.LocalPlayer == leaderRef;
|
||||
if (_startBtn != null)
|
||||
{
|
||||
_startBtn.style.display = isLeader ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
}
|
||||
|
||||
if (runner.SessionInfo != null && runner.SessionInfo.Properties.TryGetValue("rn", out var rnProp)) _loungeRoomName.text = rnProp.ToString().ToUpper();
|
||||
|
||||
// Host Display
|
||||
if (hostRef != PlayerRef.None && _playerDataManager.TryGetPlayerMetaData(hostRef, out var hostData))
|
||||
{
|
||||
_hostNameLabel.text = hostData.Name.ToString().ToUpper();
|
||||
string readyStatus = hostData.IsReady ? GetT("LOBBY_READY") : GetT("LOBBY_NOT_READY");
|
||||
string roleLabel = (hostRef == leaderRef) ? GetT("LOBBY_HOST_LABEL") : GetT("LOBBY_PLAYER_LABEL");
|
||||
_hostStatusLabel.text = $"{roleLabel} - {readyStatus}";
|
||||
_hostStatusLabel.style.color = hostData.IsReady ? Color.green : Color.red;
|
||||
|
||||
// Highlight leader avatar
|
||||
if (_hostAvatar != null)
|
||||
{
|
||||
float width = (hostRef == leaderRef) ? 2f : 0f;
|
||||
_hostAvatar.style.borderTopWidth = width;
|
||||
_hostAvatar.style.borderBottomWidth = width;
|
||||
_hostAvatar.style.borderLeftWidth = width;
|
||||
_hostAvatar.style.borderRightWidth = width;
|
||||
}
|
||||
}
|
||||
else { _hostNameLabel.text = GetT("LOBBY_SYNCING"); _hostStatusLabel.text = "-"; }
|
||||
|
||||
// Guest Display
|
||||
if (guestRef != PlayerRef.None && _playerDataManager.TryGetPlayerMetaData(guestRef, out var guestData))
|
||||
{
|
||||
_guestNameLabel.text = guestData.Name.ToString().ToUpper();
|
||||
string readyStatus = guestData.IsReady ? GetT("LOBBY_READY") : GetT("LOBBY_NOT_READY");
|
||||
string roleLabel = (guestRef == leaderRef) ? GetT("LOBBY_HOST_LABEL") : GetT("LOBBY_PLAYER_LABEL");
|
||||
_guestStatusLabel.text = $"{roleLabel} - {readyStatus}";
|
||||
_guestStatusLabel.style.color = guestData.IsReady ? Color.green : Color.red;
|
||||
|
||||
// Highlight leader avatar
|
||||
if (_guestAvatar != null)
|
||||
{
|
||||
float width = (guestRef == leaderRef) ? 2f : 0f;
|
||||
_guestAvatar.style.borderTopWidth = width;
|
||||
_guestAvatar.style.borderBottomWidth = width;
|
||||
_guestAvatar.style.borderLeftWidth = width;
|
||||
_guestAvatar.style.borderRightWidth = width;
|
||||
_guestAvatar.style.borderTopColor = Color.white;
|
||||
_guestAvatar.style.borderBottomColor = Color.white;
|
||||
_guestAvatar.style.borderLeftColor = Color.white;
|
||||
_guestAvatar.style.borderRightColor = Color.white;
|
||||
}
|
||||
}
|
||||
else if (runner.ActivePlayers.Count() >= 2) { _guestNameLabel.text = GetT("LOBBY_SYNCING"); _guestStatusLabel.text = "-"; }
|
||||
else
|
||||
{
|
||||
_guestNameLabel.text = GetT("LOBBY_WAITING_LABEL");
|
||||
_guestStatusLabel.text = "-";
|
||||
_guestStatusLabel.style.color = Color.gray;
|
||||
if (_guestAvatar != null)
|
||||
{
|
||||
_guestAvatar.style.borderTopWidth = 0;
|
||||
_guestAvatar.style.borderBottomWidth = 0;
|
||||
_guestAvatar.style.borderLeftWidth = 0;
|
||||
_guestAvatar.style.borderRightWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Start Button Logic (Leader Only)
|
||||
if (_startBtn != null && isLeader)
|
||||
{
|
||||
bool allReady = true;
|
||||
int playerCount = 0;
|
||||
foreach (var p in runner.ActivePlayers)
|
||||
{
|
||||
playerCount++;
|
||||
if (_playerDataManager.TryGetPlayerMetaData(p, out var data))
|
||||
{
|
||||
if (!data.IsReady) allReady = false;
|
||||
}
|
||||
else allReady = false;
|
||||
}
|
||||
|
||||
bool canStart = allReady && playerCount >= 2;
|
||||
_startBtn.SetEnabled(canStart);
|
||||
_startBtn.text = GetT("LOBBY_START_BTN");
|
||||
|
||||
if (canStart)
|
||||
{
|
||||
_startBtn.style.backgroundColor = new StyleColor(Color.green);
|
||||
_startBtn.style.color = new StyleColor(Color.black);
|
||||
}
|
||||
else
|
||||
{
|
||||
_startBtn.style.backgroundColor = new StyleColor(new Color(0.2f, 0.2f, 0.2f, 0.8f));
|
||||
_startBtn.style.color = new StyleColor(new Color(1f, 1f, 1f, 0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
// Ready Button Logic (Everyone)
|
||||
if (_readyBtn != null)
|
||||
{
|
||||
if (_playerDataManager.TryGetPlayerMetaData(runner.LocalPlayer, out var myData))
|
||||
{
|
||||
if (myData.IsReady)
|
||||
{
|
||||
_readyBtn.text = GetT("LOBBY_UNREADY_BTN");
|
||||
_readyBtn.style.backgroundColor = new StyleColor(Color.green);
|
||||
_readyBtn.style.color = new StyleColor(Color.black);
|
||||
}
|
||||
else
|
||||
{
|
||||
_readyBtn.text = GetT("LOBBY_READY_BTN");
|
||||
_readyBtn.style.backgroundColor = new StyleColor(new Color(0.2f, 0.2f, 0.2f, 0.8f));
|
||||
_readyBtn.style.color = new StyleColor(Color.white);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void Invoke(string methodName, float delay) { await Task.Delay((int)(delay * 1000)); if (methodName == nameof(RegisterSpawnerEvents)) RegisterSpawnerEvents(); }
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c37c552a9c18a242bcc8860a0a5212f
|
||||
@@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class LocalizationManager : MonoBehaviour
|
||||
{
|
||||
public static LocalizationManager Instance { get; private set; }
|
||||
|
||||
private Dictionary<string, string> _localizedText = new Dictionary<string, string>();
|
||||
private string _currentLanguage = "en";
|
||||
|
||||
public event Action OnLanguageChanged;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
// Đọc ngôn ngữ đã lưu hoặc mặc định là tiếng Anh
|
||||
string savedLang = PlayerPrefs.GetString("Language", "en");
|
||||
LoadLanguage(savedLang);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadLanguage(string langCode)
|
||||
{
|
||||
_currentLanguage = langCode;
|
||||
TextAsset jsonAsset = Resources.Load<TextAsset>($"Localization/{langCode}");
|
||||
|
||||
if (jsonAsset != null)
|
||||
{
|
||||
ParseJsonRobust(jsonAsset.text);
|
||||
|
||||
PlayerPrefs.SetString("Language", langCode);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
// Thông báo cho các UI khác biết ngôn ngữ đã đổi
|
||||
OnLanguageChanged?.Invoke();
|
||||
Debug.Log($"[Localization] Successfully loaded language: {langCode} ({_localizedText.Count} keys)");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[Localization] Language file NOT FOUND in Resources/Localization/{langCode}");
|
||||
}
|
||||
}
|
||||
|
||||
// Dùng Regex để bóc tách Key-Value từ JSON cực kỳ chính xác
|
||||
private void ParseJsonRobust(string json)
|
||||
{
|
||||
_localizedText.Clear();
|
||||
|
||||
// Regex này sẽ tìm tất cả các cặp "key" : "value" bất kể khoảng trắng hay xuống dòng
|
||||
MatchCollection matches = Regex.Matches(json, "\"([^\"]+)\"\\s*:\\s*\"([^\"]+)\"");
|
||||
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
if (match.Groups.Count == 3)
|
||||
{
|
||||
string key = match.Groups[1].Value;
|
||||
string value = match.Groups[2].Value;
|
||||
_localizedText[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetLocalizedString(string key)
|
||||
{
|
||||
if (_localizedText.TryGetValue(key, out string value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return key; // Trả về chính key nếu không tìm thấy dịch thuật
|
||||
}
|
||||
|
||||
public string CurrentLanguage => _currentLanguage;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff7ac0ce8c8c98445b895ac53a4618f1
|
||||
@@ -1,119 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using PrimeTween;
|
||||
using System.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using Tween = PrimeTween.Tween;
|
||||
using Ease = PrimeTween.Ease;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
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;
|
||||
*/
|
||||
|
||||
// Đăng ký Localization
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
LocalizationManager.Instance.OnLanguageChanged += ApplyLocalization;
|
||||
}
|
||||
ApplyLocalization();
|
||||
}
|
||||
|
||||
private void ApplyLocalization()
|
||||
{
|
||||
if (LocalizationManager.Instance == null) return;
|
||||
|
||||
var title = root.Q<Label>(className: "text-heading");
|
||||
if (title != null) title.text = LocalizationManager.Instance.GetLocalizedString("LOGIN_TITLE");
|
||||
|
||||
if (_nameInput != null) _nameInput.label = LocalizationManager.Instance.GetLocalizedString("LOGIN_USER");
|
||||
if (_confirmBtn != null) _confirmBtn.text = LocalizationManager.Instance.GetLocalizedString("LOGIN_BTN");
|
||||
|
||||
var guestBtn = root.Q<Button>("GuestBtn");
|
||||
if (guestBtn != null) guestBtn.text = LocalizationManager.Instance.GetLocalizedString("LOGIN_GUEST");
|
||||
|
||||
}
|
||||
|
||||
/*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 Tween.Custom(0f, 1f, duration: 0.5f, onValueChange: val => root.style.opacity = val);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fbd606c21d317da47820446e4da1c55b
|
||||
@@ -1,309 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using PrimeTween;
|
||||
using System.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using Tween = PrimeTween.Tween;
|
||||
using Ease = PrimeTween.Ease;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class MainMenuController : BaseUIController
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public enum MenuState { Idle, Ribbon }
|
||||
private MenuState _currentState = MenuState.Idle;
|
||||
|
||||
private VisualElement _logo;
|
||||
private VisualElement _ribbon;
|
||||
private VisualElement _logoSpace;
|
||||
|
||||
private float _lastInteractionTime;
|
||||
private const float IDLE_TIMEOUT = 5.0f;
|
||||
private bool _isFirstLoad = true;
|
||||
|
||||
private Tween _pulseTween;
|
||||
private Tween _rotationTween;
|
||||
private Texture2D _currentIcon;
|
||||
|
||||
private bool _isBusy = false;
|
||||
|
||||
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
|
||||
{
|
||||
base.Initialize(uxmlRoot, manager);
|
||||
|
||||
_logo = root.Q<VisualElement>("Logo");
|
||||
_ribbon = root.Q<VisualElement>("Ribbon");
|
||||
_logoSpace = root.Q<VisualElement>("LogoSpace");
|
||||
|
||||
if (_logo == null)
|
||||
{
|
||||
Debug.LogError($"[MainMenuController] Element 'Logo' not found in UXML!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Lắng nghe sự kiện thay đổi kích thước toàn màn hình
|
||||
root.RegisterCallback<GeometryChangedEvent>(OnScreenResize);
|
||||
|
||||
/*_logo.RegisterCallback<ClickEvent>(OnLogoClicked);*/
|
||||
|
||||
var settingsBtn = root.Q<Button>("SettingsBtn");
|
||||
/*if (settingsBtn != null) settingsBtn.clicked += () => { if (_isBusy) return; uiManager.ToggleSettings(); };
|
||||
|
||||
root.Q<Button>("JoinBtn").clicked += async () => { if (_isBusy) return; _isBusy = true; await uiManager.Push<LobbyController>(); };
|
||||
root.Q<Button>("CreateBtn").clicked += async () => { if (_isBusy) return; _isBusy = true; await uiManager.Push<LobbyController>(); };
|
||||
root.Q<Button>("ProfileBtn").clicked += async () => { if (_isBusy) return; _isBusy = true; await uiManager.Push<ProfileController>(); };
|
||||
root.Q<Button>("ExitBtn").clicked += () => Application.Quit();*/
|
||||
|
||||
// Đăng ký Localization
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
LocalizationManager.Instance.OnLanguageChanged += ApplyLocalization;
|
||||
}
|
||||
ApplyLocalization();
|
||||
|
||||
ResetLogoPosition();
|
||||
StartPulse();
|
||||
_lastInteractionTime = Time.time;
|
||||
}
|
||||
|
||||
private void ApplyLocalization()
|
||||
{
|
||||
if (LocalizationManager.Instance == null) return;
|
||||
|
||||
var joinBtn = root.Q<Button>("JoinBtn");
|
||||
if (joinBtn != null) joinBtn.text = LocalizationManager.Instance.GetLocalizedString("MENU_JOIN");
|
||||
|
||||
var createBtn = root.Q<Button>("CreateBtn");
|
||||
if (createBtn != null) createBtn.text = LocalizationManager.Instance.GetLocalizedString("MENU_CREATE");
|
||||
|
||||
var settingsBtn = root.Q<Button>("SettingsBtn");
|
||||
if (settingsBtn != null) settingsBtn.text = LocalizationManager.Instance.GetLocalizedString("MENU_SETTINGS");
|
||||
|
||||
var profileBtn = root.Q<Button>("ProfileBtn");
|
||||
if (profileBtn != null) profileBtn.text = LocalizationManager.Instance.GetLocalizedString("MENU_PROFILE");
|
||||
|
||||
var exitBtn = root.Q<Button>("ExitBtn");
|
||||
if (exitBtn != null) exitBtn.text = LocalizationManager.Instance.GetLocalizedString("MENU_EXIT");
|
||||
|
||||
var playLabel = _logo.Q<Label>();
|
||||
if (playLabel != null) playLabel.text = LocalizationManager.Instance.GetLocalizedString("MENU_PLAY");
|
||||
}
|
||||
|
||||
private void OnScreenResize(GeometryChangedEvent evt)
|
||||
{
|
||||
// Khi màn hình thay đổi kích thước, nếu đang ở Ribbon thì cập nhật theo LogoSpace
|
||||
if (_currentState == MenuState.Ribbon)
|
||||
{
|
||||
UpdateLogoToSpace();
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetLogoPosition();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetLogoPosition()
|
||||
{
|
||||
if (_logo == null) return;
|
||||
|
||||
// Sử dụng phần trăm để luôn ở giữa bất kể độ phân giải
|
||||
_logo.style.left = Length.Percent(50);
|
||||
_logo.style.top = Length.Percent(50);
|
||||
_logo.style.translate = new StyleTranslate(new Translate(Length.Percent(-50), Length.Percent(-50)));
|
||||
|
||||
_logo.style.width = 200;
|
||||
_logo.style.height = 200;
|
||||
}
|
||||
|
||||
public void SetGameIcon(Texture2D icon)
|
||||
{
|
||||
if (icon == null || _logo == null) return;
|
||||
_currentIcon = icon;
|
||||
_logo.style.backgroundImage = icon;
|
||||
|
||||
var radius = new StyleLength(new Length(50, LengthUnit.Percent));
|
||||
_logo.style.borderTopLeftRadius = radius;
|
||||
_logo.style.borderTopRightRadius = radius;
|
||||
_logo.style.borderBottomLeftRadius = radius;
|
||||
_logo.style.borderBottomRightRadius = radius;
|
||||
_logo.style.overflow = Overflow.Hidden;
|
||||
|
||||
var label = _logo.Q<Label>();
|
||||
if (label != null) label.style.display = DisplayStyle.None;
|
||||
|
||||
StartRotation();
|
||||
}
|
||||
|
||||
private void StartRotation()
|
||||
{
|
||||
/*if (_currentIcon == null) return;
|
||||
if (_rotationTween.isAlive) _rotationTween.Stop();
|
||||
|
||||
_rotationTween = Tween.Custom(0f, 360f, duration: 4f,
|
||||
onValueChange: val => _logo.style.rotate = new StyleRotate(new Rotate(Angle.Degrees(val))),
|
||||
cycles: -1,
|
||||
ease: Ease.Linear);*/
|
||||
}
|
||||
|
||||
/*public override async Task PlayTransitionIn()
|
||||
{
|
||||
_isBusy = false;
|
||||
_lastInteractionTime = Time.time;
|
||||
_currentState = MenuState.Idle;
|
||||
ResetLogoPosition();
|
||||
|
||||
if (_ribbon != null)
|
||||
{
|
||||
_ribbon.style.display = DisplayStyle.None;
|
||||
_ribbon.style.opacity = 0;
|
||||
}
|
||||
|
||||
StartRotation();
|
||||
await base.PlayTransitionIn();
|
||||
|
||||
if (!_isFirstLoad) TransitionToRibbon();
|
||||
else _isFirstLoad = false;
|
||||
}
|
||||
|
||||
public override async Task PlayTransitionOut()
|
||||
{
|
||||
/*if (_rotationTween.isAlive) _rotationTween.Stop();
|
||||
await base.PlayTransitionOut();#1#
|
||||
}*/
|
||||
|
||||
/*private async void OnLogoClicked(ClickEvent evt)
|
||||
{
|
||||
if (_isBusy) return;
|
||||
_lastInteractionTime = Time.time;
|
||||
if (_currentState == MenuState.Idle) TransitionToRibbon();
|
||||
else
|
||||
{
|
||||
_isBusy = true;
|
||||
await uiManager.Push<LobbyController>();
|
||||
}
|
||||
}*/
|
||||
|
||||
private void TransitionToRibbon()
|
||||
{
|
||||
if (_currentState == MenuState.Ribbon && _ribbon.resolvedStyle.display == DisplayStyle.Flex) return;
|
||||
_currentState = MenuState.Ribbon;
|
||||
_lastInteractionTime = Time.time;
|
||||
|
||||
_ribbon.style.display = DisplayStyle.Flex;
|
||||
/*
|
||||
Tween.Custom(0f, 1f, duration: 0.3f, onValueChange: val => _ribbon.style.opacity = val);
|
||||
*/
|
||||
|
||||
// Đợi một frame để Ribbon layout xong rồi mới lấy vị trí LogoSpace
|
||||
_logoSpace.RegisterCallback<GeometryChangedEvent>(OnLogoSpaceReady);
|
||||
}
|
||||
|
||||
private void OnLogoSpaceReady(GeometryChangedEvent evt)
|
||||
{
|
||||
_logoSpace.UnregisterCallback<GeometryChangedEvent>(OnLogoSpaceReady);
|
||||
UpdateLogoToSpace(true);
|
||||
}
|
||||
|
||||
private void UpdateLogoToSpace(bool animate = false)
|
||||
{
|
||||
Rect targetBounds = _logoSpace.worldBound;
|
||||
if (targetBounds.width <= 0) return;
|
||||
|
||||
// Chuyển đổi tọa độ world của LogoSpace sang tọa độ local của root
|
||||
Vector2 localPos = root.WorldToLocal(new Vector2(targetBounds.x, targetBounds.y));
|
||||
|
||||
float targetX = localPos.x + (targetBounds.width / 2f);
|
||||
float targetY = localPos.y + (targetBounds.height / 2f);
|
||||
|
||||
// Khi ở Ribbon, chúng ta bỏ translate -50% để tính toán chính xác tâm
|
||||
_logo.style.translate = new StyleTranslate(new Translate(Length.Percent(-50), Length.Percent(-50)));
|
||||
|
||||
if (animate)
|
||||
{
|
||||
/*Tween.Custom(_logo.resolvedStyle.left, targetX, duration: 0.5f,
|
||||
onValueChange: val => _logo.style.left = val,
|
||||
ease: Ease.OutQuad);
|
||||
|
||||
Tween.Custom(_logo.resolvedStyle.top, targetY, duration: 0.5f,
|
||||
onValueChange: val => _logo.style.top = val,
|
||||
ease: Ease.OutQuad);
|
||||
|
||||
Tween.Custom(_logo.resolvedStyle.width, 100f, duration: 0.5f,
|
||||
onValueChange: val => _logo.style.width = val,
|
||||
ease: Ease.OutQuad);
|
||||
|
||||
Tween.Custom(_logo.resolvedStyle.height, 100f, duration: 0.5f,
|
||||
onValueChange: val => _logo.style.height = val,
|
||||
ease: Ease.OutQuad);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
_logo.style.left = targetX;
|
||||
_logo.style.top = targetY;
|
||||
_logo.style.width = 100;
|
||||
_logo.style.height = 100;
|
||||
}
|
||||
|
||||
_lastInteractionTime = Time.time;
|
||||
}
|
||||
|
||||
private void TransitionToIdle()
|
||||
{
|
||||
if (_currentState == MenuState.Idle) return;
|
||||
_currentState = MenuState.Idle;
|
||||
|
||||
// Quay lại dùng phần trăm để tự động căn giữa
|
||||
/*Tween.Custom(_logo.resolvedStyle.width, 200f, duration: 0.5f, onValueChange: val => _logo.style.width = val, ease: Ease.OutQuad);
|
||||
Tween.Custom(_logo.resolvedStyle.height, 200f, duration: 0.5f, onValueChange: val => _logo.style.height = val, ease: Ease.OutQuad);
|
||||
|
||||
// Animate left/top về 50%
|
||||
float startLeft = _logo.resolvedStyle.left;
|
||||
float startTop = _logo.resolvedStyle.top;
|
||||
float targetLeft = root.resolvedStyle.width / 2f;
|
||||
float targetTop = root.resolvedStyle.height / 2f;
|
||||
|
||||
Tween.Custom(0f, 1f, duration: 0.5f, ease: Ease.OutQuad, onValueChange: t => {
|
||||
_logo.style.left = Mathf.Lerp(startLeft, targetLeft, t);
|
||||
_logo.style.top = Mathf.Lerp(startTop, targetTop, t);
|
||||
}).OnComplete(() => {
|
||||
ResetLogoPosition(); // Đảm bảo cuối cùng dùng đơn vị Percent
|
||||
});
|
||||
|
||||
Tween.Custom(1f, 0f, duration: 0.5f, onValueChange: val => _ribbon.style.opacity = val)
|
||||
.OnComplete(() => _ribbon.style.display = DisplayStyle.None);*/
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0 || Input.anyKey)
|
||||
{
|
||||
_lastInteractionTime = Time.time;
|
||||
}
|
||||
|
||||
if (_currentState == MenuState.Ribbon && Time.time - _lastInteractionTime > IDLE_TIMEOUT)
|
||||
{
|
||||
TransitionToIdle();
|
||||
}
|
||||
}
|
||||
|
||||
private void StartPulse()
|
||||
{
|
||||
/*if (_pulseTween.isAlive) _pulseTween.Stop();
|
||||
_pulseTween = Tween.Custom(Vector3.one, Vector3.one * 1.1f, duration: 0.8f,
|
||||
onValueChange: val => _logo.style.scale = new StyleScale(new Scale(val)),
|
||||
cycles: -1,
|
||||
cycleMode: CycleMode.Yoyo,
|
||||
ease: Ease.InOutSine);*/
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
LocalizationManager.Instance.OnLanguageChanged -= ApplyLocalization;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 691980524acfc544f9660cfc35ce3616
|
||||
@@ -1,44 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
public static class MouseMetricsHelper
|
||||
{
|
||||
private static int _reportCount = 0;
|
||||
private static float _timer = 0f;
|
||||
private static int _lastPollingRate = 0;
|
||||
private static float _lastLatency = 0f;
|
||||
private static Vector2 _lastMousePos;
|
||||
|
||||
public static (int pollingRate, float latencyMs) GetMetrics()
|
||||
{
|
||||
Update();
|
||||
return (_lastPollingRate, _lastLatency);
|
||||
}
|
||||
|
||||
private static void Update()
|
||||
{
|
||||
_timer += Time.unscaledDeltaTime;
|
||||
|
||||
// Count "reports" based on position changes (simulated polling rate)
|
||||
Vector2 currentPos = Input.mousePosition;
|
||||
if (currentPos != _lastMousePos)
|
||||
{
|
||||
_reportCount++;
|
||||
_lastMousePos = currentPos;
|
||||
}
|
||||
|
||||
if (_timer >= 1f)
|
||||
{
|
||||
_lastPollingRate = (int)(_reportCount / _timer);
|
||||
_reportCount = 0;
|
||||
_timer = 0f;
|
||||
}
|
||||
|
||||
// Dummy latency simulation (Input System doesn't expose raw hardware latency easily)
|
||||
// In a real scenario, this would involve timestamping HID reports
|
||||
_lastLatency = (1.0f / (Screen.currentResolution.refreshRateRatio.value > 0 ? (float)Screen.currentResolution.refreshRateRatio.value : 60f)) * 1000f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff50ca9a6ee819b48b273986e55f2772
|
||||
@@ -1,77 +0,0 @@
|
||||
using UnityEngine.UIElements;
|
||||
using System.Threading.Tasks;
|
||||
using Baba_yaga;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class PauseMenuController : BaseUIController
|
||||
{
|
||||
private Button _resumeBtn;
|
||||
private Button _quitBtn;
|
||||
|
||||
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
|
||||
{
|
||||
base.Initialize(uxmlRoot, manager);
|
||||
|
||||
_resumeBtn = root.Q<Button>("ResumeBtn");
|
||||
_quitBtn = root.Q<Button>("QuitBtn");
|
||||
|
||||
/*if (_resumeBtn != null) _resumeBtn.clicked += OnResumeClicked;*/
|
||||
if (_quitBtn != null) _quitBtn.clicked += OnQuitClicked;
|
||||
|
||||
ApplyLocalization();
|
||||
if (LocalizationManager.Instance != null)
|
||||
LocalizationManager.Instance.OnLanguageChanged += ApplyLocalization;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (LocalizationManager.Instance != null)
|
||||
LocalizationManager.Instance.OnLanguageChanged -= ApplyLocalization;
|
||||
}
|
||||
|
||||
private void ApplyLocalization()
|
||||
{
|
||||
if (_resumeBtn != null) _resumeBtn.text = GetLoc("PAUSE_RESUME");
|
||||
if (_quitBtn != null) _quitBtn.text = GetLoc("PAUSE_QUIT");
|
||||
|
||||
var title = root.Q<Label>("PauseTitle");
|
||||
if (title != null) title.text = GetLoc("PAUSE_TITLE");
|
||||
}
|
||||
|
||||
/*private void OnResumeClicked()
|
||||
{
|
||||
uiManager.TogglePauseMenu();
|
||||
}*/
|
||||
|
||||
private void OnQuitClicked()
|
||||
{
|
||||
Debug.Log("[PauseMenu] Quit clicked - shutting down runner.");
|
||||
/*if (BasicSpawner.Instance != null && BasicSpawner.Instance.Runner != null)
|
||||
{
|
||||
BasicSpawner.Instance.Runner.Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
uiManager.OnBackToMenu();
|
||||
}*/
|
||||
}
|
||||
|
||||
/*public override async Task PlayTransitionIn()
|
||||
{
|
||||
/*Show();
|
||||
root.style.opacity = 0;
|
||||
await PrimeTween.Tween.Custom(0f, 1f, duration: 0.2f, onValueChange: val => root.style.opacity = val);
|
||||
await Task.Delay(200);#1#
|
||||
}
|
||||
|
||||
public override async Task PlayTransitionOut()
|
||||
{
|
||||
/*await PrimeTween.Tween.Custom(1f, 0f, duration: 0.2f, onValueChange: val => root.style.opacity = val);
|
||||
await Task.Delay(200);
|
||||
Hide();#1#
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8be766526476e44ea7c5e19567f2568
|
||||
@@ -1,98 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Fusion;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class PerformanceOverlay : MonoBehaviour
|
||||
{
|
||||
private static PerformanceOverlay _instance;
|
||||
private Label _fpsLabel;
|
||||
private UIDocument _uiDocument;
|
||||
private VisualElement _root;
|
||||
|
||||
private float _deltaTime = 0f;
|
||||
private bool _isVisible = false;
|
||||
|
||||
public static void SetVisible(bool visible)
|
||||
{
|
||||
if (_instance == null && visible)
|
||||
{
|
||||
var go = new GameObject("PerformanceOverlay");
|
||||
_instance = go.AddComponent<PerformanceOverlay>();
|
||||
DontDestroyOnLoad(go);
|
||||
}
|
||||
|
||||
if (_instance != null)
|
||||
{
|
||||
_instance._isVisible = visible;
|
||||
if (_instance._root != null)
|
||||
{
|
||||
_instance._root.style.display = visible ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_uiDocument = gameObject.AddComponent<UIDocument>();
|
||||
|
||||
// Đặt thứ tự hiển thị cực cao để luôn nằm trên cùng
|
||||
_uiDocument.sortingOrder = 999;
|
||||
|
||||
// Thử lấy PanelSettings từ UIManager để đồng bộ tỉ lệ scale
|
||||
if (UIManager.Instance != null && UIManager.Instance.GetComponent<UIDocument>() != null)
|
||||
{
|
||||
_uiDocument.panelSettings = UIManager.Instance.GetComponent<UIDocument>().panelSettings;
|
||||
}
|
||||
|
||||
_root = new VisualElement();
|
||||
_root.style.position = Position.Absolute;
|
||||
_root.style.bottom = 15;
|
||||
_root.style.right = 15;
|
||||
_root.pickingMode = PickingMode.Ignore;
|
||||
|
||||
_fpsLabel = new Label("0 FPS | 0.0ms | PING: 0ms");
|
||||
_fpsLabel.pickingMode = PickingMode.Ignore;
|
||||
_fpsLabel.style.color = Color.white;
|
||||
_fpsLabel.style.fontSize = 12;
|
||||
_fpsLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||
// Shadow effect
|
||||
_fpsLabel.style.textShadow = new TextShadow { offset = new Vector2(1, 1), blurRadius = 1, color = Color.black };
|
||||
|
||||
_root.Add(_fpsLabel);
|
||||
_uiDocument.rootVisualElement.Add(_root);
|
||||
|
||||
_root.style.display = _isVisible ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_isVisible) return;
|
||||
|
||||
_deltaTime += (Time.unscaledDeltaTime - _deltaTime) * 0.1f;
|
||||
float fps = 1.0f / _deltaTime;
|
||||
float ms = _deltaTime * 1000.0f;
|
||||
|
||||
int ping = 0;
|
||||
if (BasicSpawner.Instance != null && BasicSpawner.Instance.Runner != null && BasicSpawner.Instance.Runner.IsRunning)
|
||||
{
|
||||
var runner = BasicSpawner.Instance.Runner;
|
||||
if (runner.LocalPlayer != PlayerRef.None)
|
||||
{
|
||||
ping = (int)(runner.GetPlayerRtt(runner.LocalPlayer) * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
var (_, deviceLatency) = MouseMetricsHelper.GetMetrics();
|
||||
|
||||
_fpsLabel.text = $"{Mathf.Ceil(fps)} FPS | {ms:F1}ms | LATENCY: {deviceLatency:F0}ms | PING: {ping}ms";
|
||||
|
||||
// Color coding based on performance
|
||||
if (fps < 30) _fpsLabel.style.color = Color.red;
|
||||
else if (fps < 55) _fpsLabel.style.color = Color.yellow;
|
||||
else _fpsLabel.style.color = Color.green;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e018e7d76dda004e89cd989a7413168
|
||||
@@ -1,135 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Baba_yaga.Game;
|
||||
using Baba_yaga.UI;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class ProfileController : BaseUIController
|
||||
{
|
||||
private Label _username;
|
||||
private Label _rank;
|
||||
private Label _eloLabel;
|
||||
private ProgressBar _winRateBar;
|
||||
private Label _winRateText;
|
||||
private Button _logoutBtn;
|
||||
|
||||
// Future authentication schema placeholders
|
||||
private string _googleIdPlaceholder = "";
|
||||
private string _avatarUrlPlaceholder = "";
|
||||
|
||||
public override void Initialize(VisualElement uxmlRoot, UIManager manager)
|
||||
{
|
||||
base.Initialize(uxmlRoot, manager);
|
||||
|
||||
_username = root.Q<Label>("Username");
|
||||
_rank = root.Q<Label>("Rank");
|
||||
_eloLabel = root.Q<Label>("EloLabel");
|
||||
_winRateBar = root.Q<ProgressBar>("WinRateBar");
|
||||
_winRateText = root.Q<Label>("WinRateText");
|
||||
_logoutBtn = root.Q<Button>("LogoutBtn");
|
||||
|
||||
/*root.Q<Button>("BackBtn").clicked += async () => await uiManager.Pop();*/
|
||||
|
||||
/*if (_logoutBtn != null)
|
||||
{
|
||||
_logoutBtn.clicked += Logout;
|
||||
}*/
|
||||
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
LocalizationManager.Instance.OnLanguageChanged += ApplyLocalization;
|
||||
ApplyLocalization();
|
||||
}
|
||||
|
||||
LoadProfileData();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (LocalizationManager.Instance != null)
|
||||
{
|
||||
LocalizationManager.Instance.OnLanguageChanged -= ApplyLocalization;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLocalization()
|
||||
{
|
||||
if (LocalizationManager.Instance == null) return;
|
||||
|
||||
root.Query<Label>().ForEach(l => {
|
||||
if (l.text == "WIN RATE") l.text = LocalizationManager.Instance.GetLocalizedString("PROFILE_WIN_RATE");
|
||||
if (l.text == "INVENTORY") l.text = LocalizationManager.Instance.GetLocalizedString("PROFILE_INVENTORY");
|
||||
});
|
||||
|
||||
var backBtn = root.Q<Button>("BackBtn");
|
||||
if (backBtn != null) backBtn.text = LocalizationManager.Instance.GetLocalizedString("PROFILE_BACK");
|
||||
|
||||
if (_logoutBtn != null) _logoutBtn.text = LocalizationManager.Instance.GetLocalizedString("PROFILE_LOGOUT");
|
||||
}
|
||||
|
||||
/*public override async Task PlayTransitionIn()
|
||||
{
|
||||
await LoadProfileData(); // Refresh data every time we show the profile
|
||||
await base.PlayTransitionIn();
|
||||
}*/
|
||||
|
||||
private async Task LoadProfileData()
|
||||
{
|
||||
// Load saved username or fallback
|
||||
string savedName = PlayerPrefs.GetString("Username", "Unknown Player");
|
||||
_username.text = savedName.ToUpper();
|
||||
|
||||
// Future schema mockup (Google Sign-In)
|
||||
_googleIdPlaceholder = PlayerPrefs.GetString("GoogleID", "NOT_LINKED");
|
||||
_avatarUrlPlaceholder = PlayerPrefs.GetString("AvatarURL", "");
|
||||
|
||||
// Fetch real Elo data
|
||||
var eloData = await FirebaseService.GetPlayerData(savedName);
|
||||
|
||||
if (_eloLabel != null) _eloLabel.text = eloData.Rating.ToString();
|
||||
|
||||
if (_rank != null)
|
||||
{
|
||||
_rank.text = EloSystem.GetRank(eloData.Rating).ToUpper();
|
||||
if (ColorUtility.TryParseHtmlString(EloSystem.GetRankColor(eloData.Rating), out Color rankColor))
|
||||
{
|
||||
_rank.style.color = rankColor;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate Win Rate from GamesPlayed (requires adding wins to schema, but for now we use mock/partial)
|
||||
if (eloData.GamesPlayed > 0)
|
||||
{
|
||||
// Note: To show a real winrate, we'd need to store 'Wins' in PlayerEloData.
|
||||
// For now, keeping the mock or setting a placeholder.
|
||||
_winRateText.text = "CALCULATING...";
|
||||
}
|
||||
}
|
||||
|
||||
/*private async void Logout()
|
||||
{
|
||||
// Clear local save data
|
||||
PlayerPrefs.DeleteKey("Username");
|
||||
PlayerPrefs.DeleteKey("GoogleID");
|
||||
PlayerPrefs.DeleteKey("AvatarURL");
|
||||
PlayerPrefs.Save();
|
||||
|
||||
Debug.Log("[Profile] User logged out.");
|
||||
|
||||
// Disconnect from network if currently running
|
||||
var runner = Object.FindFirstObjectByType<Fusion.NetworkRunner>();
|
||||
if (runner != null && runner.IsRunning)
|
||||
{
|
||||
await runner.Shutdown();
|
||||
}
|
||||
|
||||
// Redirect to Login Screen
|
||||
await uiManager.Push<LoginController>();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdea16b110511ef45889ed832b63560b
|
||||
@@ -1,612 +0,0 @@
|
||||
// using UnityEngine;
|
||||
// using UnityEngine.UIElements;
|
||||
// using UnityEngine.Audio;
|
||||
// using UnityEngine.InputSystem;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System;
|
||||
// using System.Threading.Tasks;
|
||||
// using DG.Tweening;
|
||||
// using Baba_yaga;
|
||||
// using PrimeTween;
|
||||
// using Tween = PrimeTween.Tween;
|
||||
// using Ease = PrimeTween.Ease;
|
||||
//
|
||||
// namespace Baba_yaga.UI
|
||||
// {
|
||||
// [UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class SettingsController : BaseUIController
|
||||
// {
|
||||
// private VisualElement _sidebar;
|
||||
// private VisualElement _tabsColumn;
|
||||
// private Label _tabTitle;
|
||||
// private ScrollView _content;
|
||||
// private Dictionary<string, Button> _tabButtons = new Dictionary<string, Button>();
|
||||
// private string _activeTab = "GENERAL";
|
||||
//
|
||||
// private Tween _hoverTimer;
|
||||
// private bool _isExpanded;
|
||||
//
|
||||
// // Osu Style Scroll Tracking
|
||||
// private readonly Dictionary<string, VisualElement> _sectionHeaders = new Dictionary<string, VisualElement>();
|
||||
// private bool _isManualScrolling;
|
||||
//
|
||||
// // Advanced Mouse Metrics
|
||||
// private Label _mouseMetricsLabel;
|
||||
//
|
||||
// // FPS State
|
||||
// private bool _fpsVisible;
|
||||
//
|
||||
// // Hover Tracking for Arrow Key Slider Control
|
||||
// private Slider _hoveredSlider;
|
||||
// private Action<float> _hoveredOnChanged;
|
||||
// private float _sliderMin, _sliderMax;
|
||||
//
|
||||
// // Audio Slider Tracking for Sync
|
||||
// private readonly Dictionary<string, (Slider slider, TextField input)> _audioSliders = new Dictionary<string, (Slider slider, TextField input)>();
|
||||
//
|
||||
// // Osu-style Volume Overlay
|
||||
// private VisualElement _volumeContainer;
|
||||
// private VisualElement _masterRing;
|
||||
// private Label _masterVolLabel;
|
||||
// private Dictionary<string, (VisualElement ring, Label label)> _subRings = new Dictionary<string, (VisualElement, Label)>();
|
||||
// private string _hoveredSubVolume = null;
|
||||
// private float _masterVol = 80f;
|
||||
// private int _overlayActiveCount = 0;
|
||||
//
|
||||
// /*public override void Initialize(VisualElement uxmlRoot, UIManager manager)
|
||||
// {
|
||||
// base.Initialize(uxmlRoot, manager);
|
||||
//
|
||||
// _sidebar = root.Q<VisualElement>("Sidebar");
|
||||
// _tabsColumn = root.Q<VisualElement>("TabsColumn");
|
||||
// _tabTitle = root.Q<Label>("TabTitle");
|
||||
// _content = root.Q<ScrollView>("SettingsContent");
|
||||
//
|
||||
// // Smart Sidebar Hover Logic
|
||||
// _tabsColumn.RegisterCallback<PointerEnterEvent>(OnSidebarPointerEnter);
|
||||
// _tabsColumn.RegisterCallback<PointerLeaveEvent>(OnSidebarPointerLeave);
|
||||
//
|
||||
// // Scroll Tracking cho Osu Style
|
||||
// _content.verticalScroller.valueChanged += OnScrollValueChanged;
|
||||
//
|
||||
// // Đăng ký sự kiện đổi ngôn ngữ
|
||||
// if (LocalizationManager.Instance != null)
|
||||
// {
|
||||
// LocalizationManager.Instance.OnLanguageChanged += OnLanguageChanged;
|
||||
// }
|
||||
//
|
||||
// // Global Volume Catch
|
||||
// uiManager.Root.RegisterCallback<WheelEvent>(OnMouseWheel, TrickleDown.TrickleDown);
|
||||
// SetupHierarchicalVolumeOverlay();
|
||||
//
|
||||
// root.RegisterCallback<PointerDownEvent>(evt => {
|
||||
// if (evt.target == root) uiManager.ToggleSettings();
|
||||
// });
|
||||
//
|
||||
// root.RegisterCallback<KeyDownEvent>(OnKeyDown);
|
||||
//
|
||||
// SetupTab("GeneralTab", "GENERAL");
|
||||
// SetupTab("VideoTab", "VIDEO");
|
||||
// SetupTab("SoundTab", "SOUND");
|
||||
// SetupTab("ControlTab", "CONTROL");
|
||||
//
|
||||
// var closeBtn = root.Q<Button>("CloseSettingsBtn");
|
||||
// if (closeBtn != null) closeBtn.clicked += () => uiManager.ToggleSettings();
|
||||
//
|
||||
// _masterVol = PlayerPrefs.GetFloat("MasterVolume", 80f);
|
||||
//
|
||||
// // Render ban đầu
|
||||
// RefreshUI();
|
||||
// ApplyVideoSettings();
|
||||
// }*/
|
||||
//
|
||||
// private void OnLanguageChanged()
|
||||
// {
|
||||
// // Lưu lại vị trí cuộn hiện tại
|
||||
// float currentScroll = _content.scrollOffset.y;
|
||||
// RefreshUI();
|
||||
// // Khôi phục vị trí cuộn sau một frame để layout kịp cập nhật
|
||||
// _content.schedule.Execute(() => _content.scrollOffset = new Vector2(0, currentScroll)).StartingIn(10);
|
||||
// }
|
||||
//
|
||||
// private void RefreshUI()
|
||||
// {
|
||||
// RenderAllSettings();
|
||||
// UpdateTabLabels();
|
||||
// HighlightTab(_activeTab);
|
||||
// }
|
||||
//
|
||||
// private void UpdateTabLabels()
|
||||
// {
|
||||
// foreach (var kvp in _tabButtons)
|
||||
// {
|
||||
// var label = kvp.Value.Q<Label>(className: "tab-label");
|
||||
// if (label != null) label.text = GetT(kvp.Key);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private string GetT(string key) => LocalizationManager.Instance != null ? LocalizationManager.Instance.GetLocalizedString(key) : key;
|
||||
//
|
||||
// private void OnSidebarPointerEnter(PointerEnterEvent evt)
|
||||
// {
|
||||
// /*_hoverTimer.Stop();
|
||||
// ExpandSidebar();*/
|
||||
// }
|
||||
//
|
||||
// private void OnSidebarPointerLeave(PointerLeaveEvent evt)
|
||||
// {
|
||||
// /*_hoverTimer.Stop();
|
||||
// CollapseSidebar();*/
|
||||
// }
|
||||
//
|
||||
// /*private void ExpandSidebar()
|
||||
// {
|
||||
// if (_isExpanded) return;
|
||||
// _isExpanded = true;
|
||||
// _tabsColumn.AddToClassList("sidebar-expanded");
|
||||
// Tween.Custom(_tabsColumn.resolvedStyle.width, 240f, duration: 0.5f, ease: Ease.OutQuart, onValueChange: val => _tabsColumn.style.width = val);
|
||||
// }*/
|
||||
//
|
||||
// /*rivate void CollapseSidebar()
|
||||
// {
|
||||
// if (!_isExpanded) return;
|
||||
// _isExpanded = false;
|
||||
// _tabsColumn.RemoveFromClassList("sidebar-expanded");
|
||||
// Tween.Custom(_tabsColumn.resolvedStyle.width, 80f, duration: 0.45f, ease: Ease.OutQuart, onValueChange: val => _tabsColumn.style.width = val);
|
||||
// }*/
|
||||
//
|
||||
// private void RenderAllSettings()
|
||||
// {
|
||||
// _content.Clear();
|
||||
// _sectionHeaders.Clear();
|
||||
//
|
||||
// RenderGeneralTab();
|
||||
// RenderVideoTab();
|
||||
// RenderSoundTab();
|
||||
// RenderControlTab();
|
||||
//
|
||||
// // Thêm khoảng trống cuối để cuộn thoải mái
|
||||
// var spacer = new VisualElement { style = { height = 200 } };
|
||||
// _content.Add(spacer);
|
||||
// }
|
||||
//
|
||||
// private void SetupTab(string btnName, string tabId)
|
||||
// {
|
||||
// var btn = root.Q<Button>(btnName);
|
||||
// if (btn != null)
|
||||
// {
|
||||
// _tabButtons[tabId] = btn;
|
||||
// btn.clicked += () => ScrollToSection(tabId);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void ScrollToSection(string tabId)
|
||||
// {
|
||||
// if (!_sectionHeaders.TryGetValue(tabId, out var header)) return;
|
||||
//
|
||||
// _isManualScrolling = true;
|
||||
// HighlightTab(tabId);
|
||||
//
|
||||
// float targetY = header.layout.y;
|
||||
// /*Tween.Custom(_content.scrollOffset.y, targetY, duration: 0.5f, ease: Ease.OutQuart, onValueChange: val => {
|
||||
// _content.scrollOffset = new Vector2(0, val);
|
||||
// }).OnComplete(() => _isManualScrolling = false);*/
|
||||
// }
|
||||
//
|
||||
// private void OnScrollValueChanged(float val)
|
||||
// {
|
||||
// if (_isManualScrolling) return;
|
||||
//
|
||||
// string currentActive = "GENERAL";
|
||||
// float minDistance = float.MaxValue;
|
||||
//
|
||||
// foreach (var kvp in _sectionHeaders)
|
||||
// {
|
||||
// float dist = Math.Abs(kvp.Value.worldBound.y - _content.worldBound.y);
|
||||
// if (dist < minDistance)
|
||||
// {
|
||||
// minDistance = dist;
|
||||
// currentActive = kvp.Key;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (_activeTab != currentActive) HighlightTab(currentActive);
|
||||
// }
|
||||
//
|
||||
// private void HighlightTab(string tabId)
|
||||
// {
|
||||
// _activeTab = tabId;
|
||||
// _tabTitle.text = GetT(tabId);
|
||||
// foreach (var kvp in _tabButtons)
|
||||
// {
|
||||
// if (kvp.Key == tabId) kvp.Value.AddToClassList("active-tab");
|
||||
// else kvp.Value.RemoveFromClassList("active-tab");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void RenderGeneralTab()
|
||||
// {
|
||||
// var header = CreateSection("GENERAL");
|
||||
// _sectionHeaders["GENERAL"] = header;
|
||||
// _content.Add(header);
|
||||
//
|
||||
// _content.Add(CreateSubSection("ACCOUNT"));
|
||||
// var userRow = new VisualElement { style = { flexDirection = FlexDirection.Row, alignItems = Align.Center, marginBottom = 10 } };
|
||||
// var loggedInLabel = new Label(GetT("LOGGED_IN_AS")); loggedInLabel.AddToClassList("text-body");
|
||||
// userRow.Add(loggedInLabel);
|
||||
// userRow.Add(new Label(PlayerPrefs.GetString("Username", "Guest")) { style = { color = Color.cyan, marginLeft = 5, unityFontStyleAndWeight = FontStyle.Bold } });
|
||||
// _content.Add(userRow);
|
||||
//
|
||||
// _content.Add(CreateSubSection("LANGUAGE"));
|
||||
// var langDropdown = new DropdownField(new List<string> { "English", "Tiếng Việt" }, LocalizationManager.Instance?.CurrentLanguage == "vi" ? 1 : 0);
|
||||
// langDropdown.AddToClassList("custom-dropdown");
|
||||
// langDropdown.RegisterValueChangedCallback(evt => {
|
||||
// LocalizationManager.Instance?.LoadLanguage(evt.newValue == "Tiếng Việt" ? "vi" : "en");
|
||||
// });
|
||||
// _content.Add(langDropdown);
|
||||
//
|
||||
// _content.Add(CreateSubSection("UPDATES"));
|
||||
// var versionBox = new VisualElement { style = { flexDirection = FlexDirection.Row, alignItems = Align.Center } };
|
||||
// var versionLabel = new Label($"{GetT("VERSION")} {Application.version}"); versionLabel.AddToClassList("text-body");
|
||||
// versionBox.Add(versionLabel);
|
||||
// var checkBtn = new Button { text = GetT("CHECK_FOR_UPDATES") }; checkBtn.AddToClassList("button-spring");
|
||||
// checkBtn.clicked += () => checkBtn.text = GetT("UP_TO_DATE");
|
||||
// versionBox.Add(checkBtn);
|
||||
// _content.Add(versionBox);
|
||||
//
|
||||
// _content.Add(CreateSubSection("CURSOR_MOUSE"));
|
||||
// _content.Add(CreateSliderWithInput(GetT("CURSOR_SIZE"), 10, 150, PlayerPrefs.GetFloat("CursorSize", 40), val => uiManager.SetCursorSize(val)));
|
||||
// var trailToggle = new Toggle(GetT("ENABLE_TRAIL")) { value = PlayerPrefs.GetInt("CursorTrail", 1) == 1 };
|
||||
// trailToggle.RegisterValueChangedCallback(evt => uiManager.SetCursorTrail(evt.newValue));
|
||||
// _content.Add(trailToggle);
|
||||
// var rippleToggle = new Toggle(GetT("ENABLE_RIPPLES")) { value = PlayerPrefs.GetInt("CursorRipples", 1) == 1 };
|
||||
// rippleToggle.RegisterValueChangedCallback(evt => uiManager.SetCursorRipples(evt.newValue));
|
||||
// _content.Add(rippleToggle);
|
||||
// _content.Add(CreateSliderWithInput(GetT("SENSITIVITY"), 0.1f, 5.0f, PlayerPrefs.GetFloat("MouseSensitivity", 1.0f), val => uiManager.SetMouseSensitivity(val)));
|
||||
// _mouseMetricsLabel = new Label($"{GetT("MOUSE_LATENCY")} report: 0/sec latency: 0ms") { style = { fontSize = 11, color = Color.gray, marginTop = 5 } };
|
||||
// _content.Add(_mouseMetricsLabel);
|
||||
// }
|
||||
//
|
||||
// private void RenderVideoTab()
|
||||
// {
|
||||
// var header = CreateSection("VIDEO");
|
||||
// _sectionHeaders["VIDEO"] = header;
|
||||
// _content.Add(header);
|
||||
//
|
||||
// _content.Add(CreateSubSection("RENDERER"));
|
||||
// var frameLimit = new DropdownField(GetT("FRAME_LIMITER"), new List<string> { "VSync", "Power Saving", "Optimal", "Unlimited" }, PlayerPrefs.GetInt("FrameLimiter", 2));
|
||||
// frameLimit.RegisterValueChangedCallback(evt => ApplyFrameLimit(frameLimit.index));
|
||||
// _content.Add(frameLimit);
|
||||
// var fpsToggle = new Toggle(GetT("SHOW_FPS")) { value = _fpsVisible };
|
||||
// fpsToggle.RegisterValueChangedCallback(evt => { _fpsVisible = evt.newValue; PlayerPrefs.SetInt("ShowFPS", _fpsVisible ? 1 : 0); PerformanceOverlay.SetVisible(_fpsVisible); });
|
||||
// _content.Add(fpsToggle);
|
||||
//
|
||||
// _content.Add(CreateSubSection("LAYOUT"));
|
||||
// Resolution native = Screen.currentResolution;
|
||||
// var resList = Screen.resolutions.Select(r => $"{r.width}x{r.height}").Distinct().Select(s => s == $"{native.width}x{native.height}" ? s + " (native)" : s).ToList();
|
||||
// string currentResStr = $"{Screen.width}x{Screen.height}";
|
||||
// int currentResIdx = resList.FindIndex(s => s.StartsWith(currentResStr));
|
||||
// if (currentResIdx == -1) currentResIdx = resList.FindIndex(s => s.Contains("native"));
|
||||
// var resDropdown = new DropdownField(GetT("RESOLUTION"), resList, currentResIdx);
|
||||
// resDropdown.RegisterValueChangedCallback(evt => {
|
||||
// string[] parts = evt.newValue.Split(' ')[0].Split('x');
|
||||
// int w = int.Parse(parts[0]), h = int.Parse(parts[1]);
|
||||
// Screen.SetResolution(w, h, Screen.fullScreen);
|
||||
// PlayerPrefs.SetInt("ScreenWidth", w); PlayerPrefs.SetInt("ScreenHeight", h);
|
||||
// });
|
||||
// _content.Add(resDropdown);
|
||||
// var fullToggle = new Toggle(GetT("FULLSCREEN")) { value = Screen.fullScreen };
|
||||
// fullToggle.RegisterValueChangedCallback(evt => { Screen.fullScreen = evt.newValue; PlayerPrefs.SetInt("Fullscreen", evt.newValue ? 1 : 0); });
|
||||
// _content.Add(fullToggle);
|
||||
// // _content.Add(CreateSliderWithInput(GetT("BACKGROUND_DIM"), 0, 100, PlayerPrefs.GetFloat("BackgroundDim", 50), val => ApplyBackgroundDim(val)));
|
||||
// // _content.Add(CreateSliderWithInput(GetT("UI_SCALE"), 0.5f, 2.0f, PlayerPrefs.GetFloat("UIScale", 1.0f), val => uiManager.SetUIScale(val)));
|
||||
// }
|
||||
//
|
||||
// private void RenderSoundTab()
|
||||
// {
|
||||
// // var header = CreateSection("SOUND");
|
||||
// // _sectionHeaders["SOUND"] = header;
|
||||
// // _content.Add(header);
|
||||
//
|
||||
// _audioSliders.Clear();
|
||||
// // _content.Add(CreateSubSection("AUDIO_VOLUMES"));
|
||||
// // _content.Add(CreateAudioSlider(GetT("MASTER"), "MasterVolume"));
|
||||
// // _content.Add(CreateAudioSlider(GetT("MUSIC"), "MusicVolume"));
|
||||
// // _content.Add(CreateAudioSlider(GetT("VFX"), "VFXVolume"));
|
||||
// // _content.Add(CreateAudioSlider(GetT("PLAYER"), "PlayerVolume"));
|
||||
// // _content.Add(CreateAudioSlider(GetT("UI"), "UIVolume"));
|
||||
// _content.Add(new Label(GetT("SCROLL_HINT")) { style = { marginTop = 20, color = Color.gray, fontSize = 12 } });
|
||||
// }
|
||||
//
|
||||
// private void RenderControlTab()
|
||||
// {
|
||||
// var header = CreateSection("CONTROL");
|
||||
// _sectionHeaders["CONTROL"] = header;
|
||||
// _content.Add(header);
|
||||
//
|
||||
// _content.Add(CreateSubSection("KEY_BINDINGS"));
|
||||
// // if (uiManager.InputReader?.InputActions == null) return;
|
||||
// // foreach (var map in uiManager.InputReader.InputActions.actionMaps)
|
||||
// // {
|
||||
// // var mapHeader = new Label(map.name.ToUpper()) { style = { fontSize = 14, unityFontStyleAndWeight = FontStyle.Bold, color = Color.cyan, marginTop = 15, marginBottom = 5 } };
|
||||
// // _content.Add(mapHeader);
|
||||
// // foreach (var action in map.actions)
|
||||
// // {
|
||||
// // if (action.name == "Look" || action.name == "Scroll" || action.name == "Navigate" || action.name == "Point" || action.name == "Click") continue;
|
||||
// // if (action.bindings.Any(b => b.isComposite))
|
||||
// // {
|
||||
// // for (int i = 0; i < action.bindings.Count; i++)
|
||||
// // if (action.bindings[i].isPartOfComposite && action.bindings[i].groups.Contains("Keyboard&Mouse"))
|
||||
// // _content.Add(CreateRebindRow(action, i, $"{action.name} {action.bindings[i].name}".ToUpper()));
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // int idx = action.bindings.ToList().FindIndex(b => b.groups.Contains("Keyboard&Mouse"));
|
||||
// // if (idx != -1) _content.Add(CreateRebindRow(action, idx, action.name.ToUpper()));
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// // var resetBtn = new Button { text = GetT("RESET_ALL") }; resetBtn.AddToClassList("button-spring"); resetBtn.style.marginTop = 30; resetBtn.style.alignSelf = Align.Center;
|
||||
// // resetBtn.clicked += () => { uiManager.InputReader.ResetBindings(); RefreshUI(); };
|
||||
// // _content.Add(resetBtn);
|
||||
// // }
|
||||
//
|
||||
// private void ApplyVideoSettings()
|
||||
// {
|
||||
// int frameLimitIdx = PlayerPrefs.GetInt("FrameLimiter", 2);
|
||||
// ApplyFrameLimit(frameLimitIdx);
|
||||
// _fpsVisible = PlayerPrefs.GetInt("ShowFPS", 0) == 1;
|
||||
// PerformanceOverlay.SetVisible(_fpsVisible);
|
||||
// float dim = PlayerPrefs.GetFloat("BackgroundDim", 50f);
|
||||
// ApplyBackgroundDim(dim);
|
||||
// }
|
||||
//
|
||||
// private void ApplyFrameLimit(int index)
|
||||
// {
|
||||
// switch (index)
|
||||
// {
|
||||
// case 0: QualitySettings.vSyncCount = 1; Application.targetFrameRate = -1; break;
|
||||
// case 1: QualitySettings.vSyncCount = 0; Application.targetFrameRate = 60; break;
|
||||
// case 2: QualitySettings.vSyncCount = 0; Application.targetFrameRate = 144; break;
|
||||
// case 3: QualitySettings.vSyncCount = 0; Application.targetFrameRate = 999; break;
|
||||
// }
|
||||
// PlayerPrefs.SetInt("FrameLimiter", index);
|
||||
// }
|
||||
//
|
||||
// private void ApplyBackgroundDim(float value)
|
||||
// {
|
||||
// PlayerPrefs.SetFloat("BackgroundDim", value);
|
||||
// var dimOverlay = uiManager.Root.Q<VisualElement>("BackgroundDimOverlay");
|
||||
// if (dimOverlay != null) dimOverlay.style.backgroundColor = new Color(0, 0, 0, value / 100f);
|
||||
// }
|
||||
//
|
||||
// private void SetupHierarchicalVolumeOverlay()
|
||||
// {
|
||||
// _volumeContainer = new VisualElement { name = "GlobalVolumeOverlay" };
|
||||
// _volumeContainer.style.position = Position.Absolute;
|
||||
// _volumeContainer.style.right = 50; _volumeContainer.style.bottom = 50;
|
||||
// _volumeContainer.style.width = 300; _volumeContainer.style.height = 300;
|
||||
// _volumeContainer.style.display = DisplayStyle.None;
|
||||
// _volumeContainer.pickingMode = PickingMode.Ignore;
|
||||
// uiManager.Root.Add(_volumeContainer);
|
||||
//
|
||||
// _masterRing = CreateRing("Master", 120, cyan: true);
|
||||
// _masterRing.style.right = 0; _masterRing.style.bottom = 0;
|
||||
// _masterVolLabel = _masterRing.Q<Label>();
|
||||
// _volumeContainer.Add(_masterRing);
|
||||
//
|
||||
// string[] subs = { "MusicVolume", "VFXVolume", "PlayerVolume", "UIVolume" };
|
||||
// string[] shortNames = { "MUS", "VFX", "PLY", "UI" };
|
||||
// for (int i = 0; i < subs.Length; i++)
|
||||
// {
|
||||
// var ring = CreateRing(shortNames[i], 70, false);
|
||||
// float angle = (i * 30f) * Mathf.Deg2Rad;
|
||||
// float radius = 140f;
|
||||
// ring.style.right = 25 + Mathf.Sin(angle) * radius;
|
||||
// ring.style.bottom = 25 + Mathf.Cos(angle) * radius;
|
||||
// string key = subs[i];
|
||||
// ring.RegisterCallback<PointerEnterEvent>(evt => _hoveredSubVolume = key);
|
||||
// ring.RegisterCallback<PointerLeaveEvent>(evt => { if (_hoveredSubVolume == key) _hoveredSubVolume = null; });
|
||||
// ring.pickingMode = PickingMode.Position;
|
||||
// _subRings[key] = (ring, ring.Q<Label>());
|
||||
// _volumeContainer.Add(ring);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private VisualElement CreateRing(string text, float size, bool cyan)
|
||||
// {
|
||||
// var ring = new VisualElement();
|
||||
// ring.style.width = size; ring.style.height = size;
|
||||
// ring.style.backgroundColor = new Color(0, 0, 0, 0.85f);
|
||||
// var radius = size / 2;
|
||||
// ring.style.borderTopLeftRadius = radius; ring.style.borderTopRightRadius = radius;
|
||||
// ring.style.borderBottomLeftRadius = radius; ring.style.borderBottomRightRadius = radius;
|
||||
// ring.style.borderTopWidth = 3; ring.style.borderBottomWidth = 3;
|
||||
// ring.style.borderLeftWidth = 3; ring.style.borderRightWidth = 3;
|
||||
// ring.style.borderTopColor = ring.style.borderBottomColor = ring.style.borderLeftColor = ring.style.borderRightColor = cyan ? Color.cyan : new Color(0.7f, 0.7f, 0.7f);
|
||||
// ring.style.justifyContent = Justify.Center; ring.style.alignItems = Align.Center;
|
||||
// ring.style.position = Position.Absolute;
|
||||
// var label = new Label("80%");
|
||||
// label.style.color = Color.white; label.style.fontSize = size * 0.25f;
|
||||
// label.style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||
// ring.Add(label);
|
||||
// var title = new Label(text);
|
||||
// title.style.color = Color.gray; title.style.fontSize = size * 0.15f;
|
||||
// title.style.position = Position.Absolute; title.style.bottom = size * 0.15f;
|
||||
// ring.Add(title);
|
||||
// return ring;
|
||||
// }
|
||||
//
|
||||
// private void OnMouseWheel(WheelEvent evt)
|
||||
// {
|
||||
// var mainMenuRoot = uiManager.Root.Q<VisualElement>("MainMenuRoot");
|
||||
// bool isMainMenuVisible = mainMenuRoot != null && mainMenuRoot.style.display == DisplayStyle.Flex;
|
||||
// if (!uiManager.IsSettingsOpen && isMainMenuVisible) return;
|
||||
// VisualElement target = evt.target as VisualElement;
|
||||
// bool isDirectUIInteraction = _hoveredSubVolume != null || (_hoveredSlider != null && _activeTab == "SOUND");
|
||||
// if (!isDirectUIInteraction && target != null)
|
||||
// {
|
||||
// if (target is ScrollView || target.GetFirstAncestorOfType<ScrollView>() != null) return;
|
||||
// }
|
||||
// _overlayActiveCount++;
|
||||
// ShowVolumeOverlay();
|
||||
// if (_hoveredSubVolume != null) UpdateSubVolume(_hoveredSubVolume, -evt.delta.y * 2f);
|
||||
// else if (_hoveredSlider != null && _activeTab == "SOUND")
|
||||
// {
|
||||
// float step = (_sliderMax - _sliderMin) / 100f;
|
||||
// float newVal = Mathf.Clamp(_hoveredSlider.value - (evt.delta.y * step * 5f), _sliderMin, _sliderMax);
|
||||
// _hoveredSlider.value = newVal;
|
||||
// _hoveredOnChanged?.Invoke(newVal);
|
||||
// }
|
||||
// else UpdateMasterVolume(-evt.delta.y * 2f);
|
||||
// evt.StopPropagation();
|
||||
// }
|
||||
//
|
||||
// private void UpdateMasterVolume(float delta) => UpdateVolume("MasterVolume", _masterVol + delta);
|
||||
//
|
||||
// private void UpdateSubVolume(string key, float delta) => UpdateVolume(key, PlayerPrefs.GetFloat(key, 80f) + delta);
|
||||
//
|
||||
// private void UpdateVolume(string key, float volume, bool updateSlider = true)
|
||||
// {
|
||||
// volume = Mathf.Clamp(volume, 0f, 100f);
|
||||
// PlayerPrefs.SetFloat(key, volume);
|
||||
// // AudioManager.Instance?.SetVolume(key, volume);
|
||||
//
|
||||
// if (key == "MasterVolume")
|
||||
// {
|
||||
// _masterVol = volume;
|
||||
// if (_masterVolLabel != null) _masterVolLabel.text = $"{Mathf.RoundToInt(volume)}%";
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (_subRings.TryGetValue(key, out var data)) data.label.text = $"{Mathf.RoundToInt(volume)}%";
|
||||
// }
|
||||
//
|
||||
// if (updateSlider && _audioSliders.TryGetValue(key, out var sliderData))
|
||||
// {
|
||||
// sliderData.slider.SetValueWithoutNotify(volume);
|
||||
// sliderData.input.value = volume.ToString("F1");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private async void ShowVolumeOverlay()
|
||||
// {
|
||||
// _volumeContainer.BringToFront();
|
||||
// uiManager.Root.Q<VisualElement>("CursorLayer")?.BringToFront();
|
||||
// _volumeContainer.style.display = DisplayStyle.Flex;
|
||||
// _volumeContainer.style.opacity = 1f;
|
||||
// foreach (var kvp in _subRings) kvp.Value.label.text = $"{Mathf.RoundToInt(PlayerPrefs.GetFloat(kvp.Key, 80f))}%";
|
||||
// _masterVolLabel.text = $"{Mathf.RoundToInt(_masterVol)}%";
|
||||
// int currentId = _overlayActiveCount;
|
||||
// await Task.Delay(3000);
|
||||
// /*if (currentId == _overlayActiveCount && _hoveredSubVolume == null)
|
||||
// {
|
||||
// Tween.Custom(1f, 0f, duration: 0.5f, onValueChange: val => _volumeContainer.style.opacity = val)
|
||||
// .OnComplete(() => { if (_volumeContainer.style.opacity == 0f) _volumeContainer.style.display = DisplayStyle.None; });
|
||||
// }*/
|
||||
// }
|
||||
//
|
||||
// private VisualElement CreateSection(string title)
|
||||
// {
|
||||
// var label = new Label(GetT(title));
|
||||
// label.AddToClassList("text-heading");
|
||||
// label.style.marginTop = 60;
|
||||
// label.style.borderBottomWidth = 2;
|
||||
// label.style.borderBottomColor = Color.cyan;
|
||||
// label.style.paddingBottom = 10;
|
||||
// return label;
|
||||
// }
|
||||
//
|
||||
// private VisualElement CreateSubSection(string title)
|
||||
// {
|
||||
// var label = new Label(GetT(title));
|
||||
// label.AddToClassList("setting-section-header");
|
||||
// label.style.marginTop = 20;
|
||||
// return label;
|
||||
// }
|
||||
//
|
||||
// private VisualElement CreateSliderWithInput(string labelText, float min, float max, float startVal, Action<float> OnValueChanged, string audioKey = null)
|
||||
// {
|
||||
// var row = new VisualElement { style = { flexDirection = FlexDirection.Row, alignItems = Align.Center, marginTop = 5, marginBottom = 5 } };
|
||||
// var label = new Label(labelText) { style = { width = Length.Percent(35) } }; label.AddToClassList("text-body");
|
||||
// var slider = new Slider(min, max) { value = startVal, style = { flexGrow = 1 } };
|
||||
// var input = new TextField { value = startVal.ToString("F1"), style = { width = 50, marginLeft = 10 } }; input.AddToClassList("input-field");
|
||||
//
|
||||
// if (audioKey != null) _audioSliders[audioKey] = (slider, input);
|
||||
//
|
||||
// slider.RegisterCallback<PointerEnterEvent>(evt => { _hoveredSlider = slider; _hoveredOnChanged = OnValueChanged; _sliderMin = min; _sliderMax = max; });
|
||||
// slider.RegisterCallback<PointerLeaveEvent>(evt => { if (_hoveredSlider == slider) { _hoveredSlider = null; _hoveredOnChanged = null; } });
|
||||
// slider.RegisterValueChangedCallback(evt => { float val = Mathf.Round(evt.newValue * 10f) / 10f; if (input.panel?.focusController?.focusedElement != input.ElementAt(0)) input.value = val.ToString("F1"); OnValueChanged?.Invoke(val); });
|
||||
// input.RegisterValueChangedCallback(evt => { if (float.TryParse(evt.newValue, out float val)) { slider.value = Mathf.Clamp(val, min, max); OnValueChanged?.Invoke(slider.value); } });
|
||||
// row.Add(label); row.Add(slider); row.Add(input); return row;
|
||||
// }
|
||||
//
|
||||
// private VisualElement CreateAudioSlider(string label, string prefKey)
|
||||
// {
|
||||
// var sliderRow = CreateSliderWithInput(label, 0, 100, PlayerPrefs.GetFloat(prefKey, 80), val => {
|
||||
// UpdateVolume(prefKey, val, false);
|
||||
// }, prefKey);
|
||||
// sliderRow.RegisterCallback<WheelEvent>(evt => {
|
||||
// UpdateVolume(prefKey, PlayerPrefs.GetFloat(prefKey, 80f) - (evt.delta.y * 2f));
|
||||
// });
|
||||
// return sliderRow;
|
||||
// }
|
||||
//
|
||||
// private VisualElement CreateRebindRow(UnityEngine.InputSystem.InputAction action, int bindingIndex, string labelText)
|
||||
// {
|
||||
// var row = new VisualElement(); row.AddToClassList("rebind-row"); row.style.flexDirection = FlexDirection.Row; row.style.justifyContent = Justify.SpaceBetween; row.style.alignItems = Align.Center; row.style.paddingTop = row.style.paddingBottom = 10; row.style.borderBottomWidth = 1; row.style.borderBottomColor = new Color(1, 1, 1, 0.1f);
|
||||
// var label = new Label(labelText); label.AddToClassList("rebind-label"); label.style.color = Color.white; row.Add(label);
|
||||
// var btn = new Button { text = action.GetBindingDisplayString(bindingIndex).ToUpper() }; btn.AddToClassList("rebind-button"); btn.style.width = 150;
|
||||
// btn.clicked += () => StartRebinding(action, bindingIndex, btn); row.Add(btn);
|
||||
// return row;
|
||||
// }
|
||||
//
|
||||
// private void StartRebinding(UnityEngine.InputSystem.InputAction action, int bindingIndex, Button btn)
|
||||
// {
|
||||
// btn.text = "> <"; btn.style.color = Color.yellow; action.actionMap.Disable();
|
||||
// var op = action.PerformInteractiveRebinding(bindingIndex).WithControlsExcluding("<Mouse>/position").WithControlsExcluding("<Mouse>/delta").WithControlsExcluding("<Keyboard>/escape").OnMatchWaitForAnother(0.1f)
|
||||
// .OnComplete(operation => { btn.text = action.GetBindingDisplayString(bindingIndex).ToUpper(); btn.style.color = Color.white; operation.Dispose(); action.actionMap.Enable(); uiManager.InputReader.SaveBindings(); })
|
||||
// .OnCancel(operation => { btn.text = action.GetBindingDisplayString(bindingIndex).ToUpper(); btn.style.color = Color.white; operation.Dispose(); action.actionMap.Enable(); });
|
||||
// op.Start();
|
||||
// }
|
||||
//
|
||||
// private void OnKeyDown(KeyDownEvent evt)
|
||||
// {
|
||||
// if (_hoveredSlider == null) return;
|
||||
// float step = (_sliderMax - _sliderMin) / 100f;
|
||||
// if (evt.keyCode == KeyCode.LeftArrow) _hoveredSlider.value -= step;
|
||||
// if (evt.keyCode == KeyCode.RightArrow) _hoveredSlider.value += step;
|
||||
// }
|
||||
//
|
||||
// public override void Update()
|
||||
// {
|
||||
// if (_mouseMetricsLabel != null && _mouseMetricsLabel.panel != null)
|
||||
// {
|
||||
// var (polling, latency) = MouseMetricsHelper.GetMetrics();
|
||||
// _mouseMetricsLabel.text = $"{GetT("MOUSE_LATENCY")} report: {polling}/sec latency: {latency:F0}ms";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /*public override async Task PlayTransitionIn()
|
||||
// {
|
||||
// root.style.display = DisplayStyle.Flex;
|
||||
// _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)));
|
||||
// }
|
||||
//
|
||||
// public override async Task PlayTransitionOut()
|
||||
// {
|
||||
// await Tween.Custom(0f, -100f, duration: 0.3f, ease: Ease.InQuad, onValueChange: val => _sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
|
||||
// Hide();
|
||||
// }*/
|
||||
//
|
||||
// private void OnDestroy()
|
||||
// {
|
||||
// if (LocalizationManager.Instance != null)
|
||||
// {
|
||||
// LocalizationManager.Instance.OnLanguageChanged -= OnLanguageChanged;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5534bcf4869df944883c6fd2a17a6a5a
|
||||
@@ -1,110 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
public static class UIAudioHelper
|
||||
{
|
||||
public static void BindFeedback(VisualElement root)
|
||||
{
|
||||
if (root == null) return;
|
||||
|
||||
// Bind Buttons (Click & Hover)
|
||||
var buttons = root.Query<Button>().ToList();
|
||||
foreach (var btn in buttons)
|
||||
{
|
||||
btn.RegisterCallback<PointerEnterEvent>(OnButtonHover);
|
||||
btn.RegisterCallback<ClickEvent>(OnButtonClick);
|
||||
}
|
||||
|
||||
// Bind Toggles
|
||||
var toggles = root.Query<Toggle>().ToList();
|
||||
foreach (var tgl in toggles)
|
||||
{
|
||||
tgl.RegisterValueChangedCallback(OnToggleChanged);
|
||||
}
|
||||
|
||||
// Bind TextFields (Focus & Typing)
|
||||
var textFields = root.Query<TextField>().ToList();
|
||||
foreach (var tf in textFields)
|
||||
{
|
||||
tf.RegisterCallback<FocusEvent>(OnTextFieldFocus);
|
||||
tf.RegisterCallback<KeyDownEvent>(OnTextFieldKeyDown, TrickleDown.TrickleDown);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnButtonHover(PointerEnterEvent evt)
|
||||
{
|
||||
var target = evt.target as VisualElement;
|
||||
string sound = "menuclick"; // Default hover
|
||||
|
||||
string name = target.name.ToLower();
|
||||
if (name.Contains("back")) sound = "menu-back-hover";
|
||||
else if (name.Contains("play")) sound = "menu-play-hover";
|
||||
else if (name.Contains("option") || name.Contains("setting")) sound = "menu-options-hover";
|
||||
else if (name.Contains("exit") || name.Contains("quit")) sound = "menu-exit-hover";
|
||||
|
||||
// AudioManager.PlayGlobal(sound, 0.5f, 1.05f);
|
||||
}
|
||||
|
||||
private static void OnButtonClick(ClickEvent evt)
|
||||
{
|
||||
var target = evt.target as VisualElement;
|
||||
string sound = "menuclick"; // Default click
|
||||
|
||||
string name = target.name.ToLower();
|
||||
if (name.Contains("back")) sound = "menu-back-click";
|
||||
else if (name.Contains("close")) sound = "click-close";
|
||||
else if (name.Contains("confirm") || name.Contains("start") || name.Contains("create")) sound = "click-short-confirm";
|
||||
else if (name.Contains("play")) sound = "menu-play-click";
|
||||
else if (name.Contains("option") || name.Contains("setting")) sound = "menu-options-click";
|
||||
else if (name.Contains("exit") || name.Contains("quit")) sound = "menu-exit-click";
|
||||
else if (name.Contains("retry") || name.Contains("restart")) sound = "pause-retry-click";
|
||||
|
||||
float randomPitch = Random.Range(0.98f, 1.02f);
|
||||
// AudioManager.PlayGlobal(sound, 1f, randomPitch);
|
||||
}
|
||||
|
||||
private static void OnToggleChanged(ChangeEvent<bool> evt)
|
||||
{
|
||||
string sound = evt.newValue ? "check-on" : "check-off";
|
||||
// AudioManager.PlayGlobal(sound, 0.8f);
|
||||
}
|
||||
|
||||
private static void OnTextFieldFocus(FocusEvent evt)
|
||||
{
|
||||
// AudioManager.PlayGlobal("UI_Focus", 0.6f);
|
||||
}
|
||||
|
||||
private static void OnTextFieldKeyDown(KeyDownEvent evt)
|
||||
{
|
||||
// Osu style typing feedback
|
||||
switch (evt.keyCode)
|
||||
{
|
||||
case KeyCode.Return:
|
||||
case KeyCode.KeypadEnter:
|
||||
// AudioManager.PlayGlobal("key-confirm", 0.8f);
|
||||
break;
|
||||
case KeyCode.Backspace:
|
||||
case KeyCode.Delete:
|
||||
// AudioManager.PlayGlobal("key-delete", 0.7f);
|
||||
break;
|
||||
case KeyCode.Space:
|
||||
case KeyCode.CapsLock:
|
||||
// AudioManager.PlayGlobal("key-caps", 0.7f);
|
||||
break;
|
||||
case KeyCode.UpArrow:
|
||||
case KeyCode.DownArrow:
|
||||
case KeyCode.LeftArrow:
|
||||
case KeyCode.RightArrow:
|
||||
// AudioManager.PlayGlobal("key-movement", 0.6f);
|
||||
break;
|
||||
default:
|
||||
// Play random variation for normal keys (key-press-1 to 4)
|
||||
// AudioManager.PlayRandomGlobal("key-press", 4, 0.5f, Random.Range(0.95f, 1.1f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28373d86c046d8248b3788daaa019217
|
||||
@@ -1,438 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using PrimeTween;
|
||||
using Tween = PrimeTween.Tween;
|
||||
using Ease = PrimeTween.Ease;
|
||||
using Baba_yaga;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Baba_yaga.UI
|
||||
{
|
||||
[RequireComponent(typeof(UIDocument))]
|
||||
[UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.UI", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class UIManager : MonoBehaviour
|
||||
{
|
||||
public static UIManager Instance { get; private set; }
|
||||
|
||||
private UIDocument _uiDocument;
|
||||
private VisualElement _rootElement;
|
||||
public VisualElement Root => _rootElement;
|
||||
|
||||
private VisualElement _cursorLayer;
|
||||
private VisualElement _mainCursor;
|
||||
|
||||
private readonly Dictionary<Type, BaseUIController> _controllers = new Dictionary<Type, BaseUIController>();
|
||||
private readonly Stack<BaseUIController> _history = new Stack<BaseUIController>();
|
||||
|
||||
[Header("References")]
|
||||
// [SerializeField] private InputReader inputReader;
|
||||
// public InputReader InputReader => inputReader;
|
||||
|
||||
[Header("Game Metadata")]
|
||||
[SerializeField] private Texture2D gameIcon;
|
||||
|
||||
[Header("Cursor & Effects Settings")]
|
||||
[SerializeField] private Sprite cursorSprite;
|
||||
[SerializeField] private Sprite cursorTrailSprite;
|
||||
[SerializeField, Range(10f, 150f)] private float cursorSize = 40f;
|
||||
[SerializeField, Range(2, 50)] private float trailDistanceThreshold = 10f;
|
||||
[SerializeField] private bool enableRipples = true;
|
||||
[SerializeField] private Color rippleColor = new Color(0, 1, 0.8f, 0.4f);
|
||||
|
||||
[Header("UI Templates & Global Styles")]
|
||||
[SerializeField] private VisualTreeAsset loginTemplate;
|
||||
[SerializeField] private VisualTreeAsset mainMenuTemplate;
|
||||
[SerializeField] private VisualTreeAsset lobbyTemplate;
|
||||
[SerializeField] private VisualTreeAsset roomItemTemplate;
|
||||
[SerializeField] private VisualTreeAsset profileTemplate;
|
||||
[SerializeField] private VisualTreeAsset settingsTemplate;
|
||||
[SerializeField] private VisualTreeAsset hudTemplate;
|
||||
[SerializeField] private VisualTreeAsset pauseMenuTemplate;
|
||||
[SerializeField] private StyleSheet globalStyleSheet;
|
||||
|
||||
private LoginController _loginController;
|
||||
private MainMenuController _mainMenuController;
|
||||
private LobbyController _lobbyController;
|
||||
// private SettingsController _settingsController;
|
||||
private PauseMenuController _pauseMenuController;
|
||||
|
||||
// Osu Trail Pooling
|
||||
private const int MAX_TRAIL_PARTICLES = 60;
|
||||
private readonly List<VisualElement> _trailPool = new List<VisualElement>();
|
||||
private int _currentTrailIndex = 0;
|
||||
|
||||
private Vector2 _lastTrailSpawnPos;
|
||||
private bool _isSettingsOpen = false;
|
||||
public bool IsSettingsOpen => _isSettingsOpen;
|
||||
|
||||
private bool _isPauseMenuOpen = false;
|
||||
public bool IsPauseMenuOpen => _isPauseMenuOpen;
|
||||
|
||||
private const string UI_SCALE_KEY = "UIScale";
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (gameIcon == null)
|
||||
{
|
||||
var icons = PlayerSettings.GetIcons(UnityEditor.Build.NamedBuildTarget.Unknown, IconKind.Any);
|
||||
if (icons != null && icons.Length > 0)
|
||||
{
|
||||
gameIcon = icons[0];
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null && Instance != this) { Destroy(gameObject); return; }
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
_uiDocument = GetComponent<UIDocument>();
|
||||
UnityEngine.Cursor.visible = false;
|
||||
|
||||
LoadGeneralSettings();
|
||||
ApplySavedUIScale();
|
||||
}
|
||||
|
||||
private void LoadGeneralSettings()
|
||||
{
|
||||
cursorSize = PlayerPrefs.GetFloat("CursorSize", 40f);
|
||||
enableRipples = PlayerPrefs.GetInt("CursorRipples", 1) == 1;
|
||||
}
|
||||
|
||||
public void SetCursorSize(float size)
|
||||
{
|
||||
cursorSize = size;
|
||||
PlayerPrefs.SetFloat("CursorSize", size);
|
||||
if (_mainCursor != null)
|
||||
{
|
||||
_mainCursor.style.width = cursorSize;
|
||||
_mainCursor.style.height = cursorSize;
|
||||
}
|
||||
foreach(var p in _trailPool) { p.style.width = cursorSize; p.style.height = cursorSize; }
|
||||
}
|
||||
|
||||
public void SetCursorTrail(bool enabled)
|
||||
{
|
||||
PlayerPrefs.SetInt("CursorTrail", enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
public void SetCursorRipples(bool enabled)
|
||||
{
|
||||
enableRipples = enabled;
|
||||
PlayerPrefs.SetInt("CursorRipples", enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
public void SetMouseSensitivity(float sensitivity)
|
||||
{
|
||||
PlayerPrefs.SetFloat("MouseSensitivity", sensitivity);
|
||||
if (Baba_yaga.SettingsManager.Instance != null)
|
||||
{
|
||||
Baba_yaga.SettingsManager.Instance.SetSensitivity(sensitivity);
|
||||
}
|
||||
}
|
||||
|
||||
/*public void OnGameStarted()
|
||||
{
|
||||
_ = Push<HUDController>();
|
||||
}
|
||||
|
||||
public void OnBackToMenu()
|
||||
{
|
||||
_ = Push<MainMenuController>();
|
||||
}*/
|
||||
|
||||
public void SetUIScale(float scale)
|
||||
{
|
||||
if (_uiDocument == null || _uiDocument.panelSettings == null) return;
|
||||
_uiDocument.panelSettings.scale = scale * 1.3f;
|
||||
PlayerPrefs.SetFloat(UI_SCALE_KEY, scale);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
private void ApplySavedUIScale()
|
||||
{
|
||||
float savedScale = PlayerPrefs.GetFloat(UI_SCALE_KEY, 1.0f);
|
||||
SetUIScale(savedScale);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_uiDocument == null) _uiDocument = GetComponent<UIDocument>();
|
||||
_rootElement = _uiDocument.rootVisualElement;
|
||||
|
||||
if (globalStyleSheet != null)
|
||||
_rootElement.panel.visualTree.styleSheets.Add(globalStyleSheet);
|
||||
|
||||
var dimOverlay = new VisualElement { name = "BackgroundDimOverlay" };
|
||||
dimOverlay.style.position = Position.Absolute;
|
||||
dimOverlay.style.width = Length.Percent(100);
|
||||
dimOverlay.style.height = Length.Percent(100);
|
||||
dimOverlay.pickingMode = PickingMode.Ignore;
|
||||
float savedDim = PlayerPrefs.GetFloat("BackgroundDim", 50f);
|
||||
dimOverlay.style.backgroundColor = new Color(0, 0, 0, savedDim / 100f);
|
||||
_rootElement.Add(dimOverlay);
|
||||
|
||||
_cursorLayer = new VisualElement { name = "CursorLayer" };
|
||||
_cursorLayer.style.position = Position.Absolute;
|
||||
_cursorLayer.style.width = Length.Percent(100);
|
||||
_cursorLayer.style.height = Length.Percent(100);
|
||||
_cursorLayer.pickingMode = PickingMode.Ignore;
|
||||
_rootElement.Add(_cursorLayer);
|
||||
|
||||
InitializeTrailPool();
|
||||
|
||||
_mainCursor = new VisualElement { name = "MainCursor" };
|
||||
_mainCursor.style.position = Position.Absolute;
|
||||
_mainCursor.style.width = cursorSize;
|
||||
_mainCursor.style.height = cursorSize;
|
||||
_mainCursor.style.backgroundImage = new StyleBackground(Background.FromSprite(cursorSprite));
|
||||
|
||||
// Căn giữa sprite hình tròn bằng translate
|
||||
_mainCursor.style.translate = new StyleTranslate(new Translate(Length.Percent(-50), Length.Percent(-50)));
|
||||
_mainCursor.pickingMode = PickingMode.Ignore;
|
||||
_cursorLayer.Add(_mainCursor);
|
||||
|
||||
_rootElement.RegisterCallback<PointerDownEvent>(OnGlobalClick, TrickleDown.TrickleDown);
|
||||
|
||||
/*if (inputReader != null)
|
||||
{
|
||||
inputReader.OnToggleSettingsEvent += ToggleSettings;
|
||||
inputReader.OnCancelEvent += HandleCancel;
|
||||
}
|
||||
*/
|
||||
|
||||
InitializeControllers();
|
||||
/*CheckLoginStatus();*/
|
||||
}
|
||||
|
||||
private void InitializeTrailPool()
|
||||
{
|
||||
for (int i = 0; i < MAX_TRAIL_PARTICLES; i++)
|
||||
{
|
||||
var particle = new VisualElement();
|
||||
particle.style.position = Position.Absolute;
|
||||
particle.style.width = cursorSize;
|
||||
particle.style.height = cursorSize;
|
||||
particle.style.backgroundImage = new StyleBackground(Background.FromSprite(cursorTrailSprite));
|
||||
particle.style.translate = new StyleTranslate(new Translate(Length.Percent(-50), Length.Percent(-50)));
|
||||
particle.style.opacity = 0;
|
||||
particle.style.display = DisplayStyle.None;
|
||||
particle.pickingMode = PickingMode.Ignore;
|
||||
_cursorLayer.Add(particle);
|
||||
_trailPool.Add(particle);
|
||||
}
|
||||
}
|
||||
|
||||
/*private void CheckLoginStatus()
|
||||
{
|
||||
string savedName = PlayerPrefs.GetString("Username", "");
|
||||
if (string.IsNullOrEmpty(savedName)) _ = Push<LoginController>();
|
||||
else _ = Push<MainMenuController>();
|
||||
}
|
||||
|
||||
public void OnLoginSuccess() => _ = Push<MainMenuController>();
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (inputReader != null)
|
||||
{
|
||||
inputReader.OnToggleSettingsEvent -= ToggleSettings;
|
||||
inputReader.OnCancelEvent -= HandleCancel;
|
||||
}
|
||||
}*/
|
||||
|
||||
/*private void HandleCancel()
|
||||
{
|
||||
if (_isSettingsOpen) ToggleSettings();
|
||||
else if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "Main Scene")
|
||||
{
|
||||
TogglePauseMenu();
|
||||
}
|
||||
}*/
|
||||
|
||||
/*public async void TogglePauseMenu()
|
||||
{
|
||||
if (_pauseMenuController == null) return;
|
||||
if (!_isPauseMenuOpen)
|
||||
{
|
||||
_isPauseMenuOpen = true;
|
||||
_pauseMenuController.Root.BringToFront();
|
||||
if (_cursorLayer != null) _cursorLayer.BringToFront();
|
||||
|
||||
// Unlock cursor when menu is open
|
||||
UnityEngine.Cursor.lockState = CursorLockMode.None;
|
||||
UnityEngine.Cursor.visible = false;
|
||||
|
||||
await _pauseMenuController.PlayTransitionIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
_isPauseMenuOpen = false;
|
||||
|
||||
// Re-lock cursor when menu is closed
|
||||
if (!_isSettingsOpen)
|
||||
{
|
||||
UnityEngine.Cursor.lockState = CursorLockMode.Locked;
|
||||
}
|
||||
|
||||
await _pauseMenuController.PlayTransitionOut();
|
||||
}
|
||||
}*/
|
||||
|
||||
/*public async void ToggleSettings()
|
||||
{
|
||||
if (_settingsController == null) return;
|
||||
if (!_isSettingsOpen)
|
||||
{
|
||||
_isSettingsOpen = true;
|
||||
_settingsController.Root.BringToFront();
|
||||
if (_cursorLayer != null) _cursorLayer.BringToFront();
|
||||
await /*_settingsController.PlayTransitionIn();#1#
|
||||
}
|
||||
else
|
||||
{
|
||||
_isSettingsOpen = false;
|
||||
await /*_settingsController.PlayTransitionOut();#1#
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_history.Count > 0) _history.Peek().Update();
|
||||
UpdateCursorInput();
|
||||
}
|
||||
|
||||
private void UpdateCursorInput()
|
||||
{
|
||||
if (!Application.isFocused || _cursorLayer == null) return;
|
||||
|
||||
// Dùng cách tính tọa độ thủ công để tránh offset khi pivot ở giữa
|
||||
Vector2 mousePos = Input.mousePosition;
|
||||
float scale = GetCurrentScale();
|
||||
Vector2 uiPos = new Vector2(mousePos.x / scale, (Screen.height - mousePos.y) / scale);
|
||||
|
||||
if (_mainCursor != null)
|
||||
{
|
||||
_mainCursor.style.left = uiPos.x;
|
||||
_mainCursor.style.top = uiPos.y;
|
||||
}
|
||||
|
||||
bool trailEnabled = PlayerPrefs.GetInt("CursorTrail", 1) == 1;
|
||||
if (trailEnabled && cursorTrailSprite != null)
|
||||
{
|
||||
float dist = Vector2.Distance(uiPos, _lastTrailSpawnPos);
|
||||
if (dist > trailDistanceThreshold)
|
||||
{
|
||||
SpawnPooledTrail(uiPos);
|
||||
_lastTrailSpawnPos = uiPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnPooledTrail(Vector2 pos)
|
||||
{
|
||||
var particle = _trailPool[_currentTrailIndex];
|
||||
_currentTrailIndex = (_currentTrailIndex + 1) % MAX_TRAIL_PARTICLES;
|
||||
|
||||
/*Tween.StopAll(particle);*/
|
||||
particle.style.display = DisplayStyle.Flex;
|
||||
particle.style.left = pos.x;
|
||||
particle.style.top = pos.y;
|
||||
particle.style.opacity = 0f;
|
||||
particle.style.scale = Vector3.one;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private float GetCurrentScale() => (_uiDocument != null && _uiDocument.panelSettings != null) ? _uiDocument.panelSettings.scale : 1.0f;
|
||||
|
||||
private void OnGlobalClick(PointerDownEvent evt)
|
||||
{
|
||||
if (!enableRipples || _cursorLayer == null) return;
|
||||
|
||||
var ripple = new VisualElement();
|
||||
ripple.style.position = Position.Absolute;
|
||||
ripple.style.width = cursorSize;
|
||||
ripple.style.height = cursorSize;
|
||||
ripple.style.translate = new StyleTranslate(new Translate(Length.Percent(-50), Length.Percent(-50)));
|
||||
ripple.style.left = evt.localPosition.x;
|
||||
ripple.style.top = evt.localPosition.y;
|
||||
|
||||
var radius = new StyleLength(new Length(50, LengthUnit.Percent));
|
||||
ripple.style.borderTopLeftRadius = radius; ripple.style.borderTopRightRadius = radius;
|
||||
ripple.style.borderBottomLeftRadius = radius; ripple.style.borderBottomRightRadius = radius;
|
||||
ripple.style.borderTopColor = rippleColor; ripple.style.borderBottomColor = rippleColor;
|
||||
ripple.style.borderLeftColor = rippleColor; ripple.style.borderRightColor = rippleColor;
|
||||
ripple.style.borderTopWidth = 2; ripple.style.borderBottomWidth = 2;
|
||||
ripple.pickingMode = PickingMode.Ignore;
|
||||
|
||||
_cursorLayer.Add(ripple);
|
||||
|
||||
/*Tween.Custom(Vector3.one, Vector3.one * 2.5f, duration: 0.4f, onValueChange: val => ripple.style.scale = new StyleScale(new Scale(val)), ease: Ease.OutQuad);
|
||||
Tween.Custom(1f, 0f, duration: 0.4f, onValueChange: val => ripple.style.opacity = val).OnComplete(() => ripple.RemoveFromHierarchy());*/
|
||||
}
|
||||
|
||||
private void InitializeControllers()
|
||||
{
|
||||
try
|
||||
{
|
||||
_mainMenuController = RegisterController<MainMenuController>(mainMenuTemplate);
|
||||
if (_mainMenuController != null && gameIcon != null) _mainMenuController.SetGameIcon(gameIcon);
|
||||
_lobbyController = RegisterController<LobbyController>(lobbyTemplate);
|
||||
if (_lobbyController != null) _lobbyController.SetRoomTemplate(roomItemTemplate);
|
||||
RegisterController<ProfileController>(profileTemplate);
|
||||
// _settingsController = RegisterController<SettingsController>(settingsTemplate);
|
||||
RegisterController<HUDController>(hudTemplate);
|
||||
_pauseMenuController = RegisterController<PauseMenuController>(pauseMenuTemplate);
|
||||
_loginController = RegisterController<LoginController>(loginTemplate);
|
||||
}
|
||||
catch (Exception e) { Debug.LogError($"[UIManager] Failed to initialize controllers: {e}"); }
|
||||
}
|
||||
|
||||
private T RegisterController<T>(VisualTreeAsset template) where T : BaseUIController
|
||||
{
|
||||
if (template == null || _rootElement == null) return null;
|
||||
VisualElement instance = template.Instantiate();
|
||||
if (instance == null) return null;
|
||||
instance.style.flexGrow = 1; instance.style.position = Position.Absolute;
|
||||
instance.style.width = Length.Percent(100); instance.style.height = Length.Percent(100);
|
||||
instance.style.display = DisplayStyle.None;
|
||||
_rootElement.Add(instance);
|
||||
if (_cursorLayer != null) _cursorLayer.BringToFront();
|
||||
var controller = ScriptableObject.CreateInstance<T>();
|
||||
controller.Initialize(instance, this);
|
||||
_controllers[typeof(T)] = controller;
|
||||
return controller;
|
||||
}
|
||||
|
||||
/*public async Task Push<T>() where T : BaseUIController
|
||||
{
|
||||
if (!_controllers.TryGetValue(typeof(T), out var newScreen)) return;
|
||||
if (_history.Count > 0 && _history.Peek() == newScreen) return;
|
||||
if (_history.Count > 0) await _history.Peek().PlayTransitionOut();
|
||||
_history.Push(newScreen);
|
||||
await newScreen.PlayTransitionIn();
|
||||
if (_cursorLayer != null) _cursorLayer.BringToFront();
|
||||
}
|
||||
|
||||
public async Task Pop()
|
||||
{
|
||||
if (_history.Count <= 1) return;
|
||||
await _history.Pop().PlayTransitionOut();
|
||||
if (_history.Count > 0) await _history.Peek().PlayTransitionIn();
|
||||
if (_cursorLayer != null) _cursorLayer.BringToFront();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcb7b8ed439bb4546b0648c627c2ce5d
|
||||
@@ -1,71 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
|
||||
public class SlashMeshGenerator : MonoBehaviour
|
||||
{
|
||||
[Header("Mesh Settings")]
|
||||
public int segments = 10; // Số lượng phân đoạn (càng cao càng mượt)
|
||||
public float length = 5f; // Chiều dài vệt chém
|
||||
public float width = 0.5f; // Chiều rộng ở giữa
|
||||
public float curviness = 1f; // Độ cong của nhát chém
|
||||
|
||||
[ContextMenu("Generate Slash Mesh")]
|
||||
public void GenerateMesh()
|
||||
{
|
||||
Mesh mesh = new Mesh();
|
||||
mesh.name = "SukunaSlashMesh";
|
||||
|
||||
int vertexCount = (segments + 1) * 2;
|
||||
Vector3[] vertices = new Vector3[vertexCount];
|
||||
Vector2[] uvs = new Vector2[vertexCount];
|
||||
int[] triangles = new int[segments * 6];
|
||||
|
||||
for (int i = 0; i <= segments; i++)
|
||||
{
|
||||
float t = (float)i / segments; // Tiến trình từ 0 đến 1
|
||||
|
||||
// Tính toán vị trí X (chiều dài)
|
||||
float x = (t - 0.5f) * length;
|
||||
|
||||
// Tính toán độ nhọn (Width Taper): Nhỏ ở 2 đầu, to ở giữa
|
||||
// Dùng hàm Sin để tạo độ mượt hoặc (1 - |2t-1|)
|
||||
float currentWidth = Mathf.Sin(t * Mathf.PI) * width;
|
||||
|
||||
// Tính toán độ cong (Y Offset)
|
||||
float yOffset = Mathf.Pow((t - 0.5f) * 2f, 2f) * curviness;
|
||||
|
||||
// Tạo 2 đỉnh (trên và dưới) cho mỗi phân đoạn
|
||||
vertices[i * 2] = new Vector3(x, yOffset + currentWidth / 2f, 0);
|
||||
vertices[i * 2 + 1] = new Vector3(x, yOffset - currentWidth / 2f, 0);
|
||||
|
||||
// Gán UV (để Shader chạy đúng)
|
||||
uvs[i * 2] = new Vector2(t, 1);
|
||||
uvs[i * 2 + 1] = new Vector2(t, 0);
|
||||
|
||||
// Tạo tam giác (trừ phân đoạn cuối)
|
||||
if (i < segments)
|
||||
{
|
||||
int start = i * 2;
|
||||
triangles[i * 6] = start;
|
||||
triangles[i * 6 + 1] = start + 2;
|
||||
triangles[i * 6 + 2] = start + 1;
|
||||
triangles[i * 6 + 3] = start + 1;
|
||||
triangles[i * 6 + 4] = start + 2;
|
||||
triangles[i * 6 + 5] = start + 3;
|
||||
}
|
||||
}
|
||||
|
||||
mesh.vertices = vertices;
|
||||
mesh.uv = uvs;
|
||||
mesh.triangles = triangles;
|
||||
mesh.RecalculateNormals();
|
||||
mesh.RecalculateBounds();
|
||||
|
||||
GetComponent<MeshFilter>().mesh = mesh;
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
GenerateMesh();
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78fcc45270373164cadbaa6681bab73b
|
||||
@@ -1,69 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Baba_yaga;
|
||||
|
||||
public class SukunaAbilityController : MonoBehaviour
|
||||
{
|
||||
[Header("Dependencies")]
|
||||
// [SerializeField] private InputReader inputReader;
|
||||
|
||||
[Header("VFX Projectiles")]
|
||||
public GameObject blackProjectilePrefab;
|
||||
public GameObject redProjectilePrefab;
|
||||
|
||||
[Header("Settings")]
|
||||
public float attackRate = 0.15f;
|
||||
public float forwardOffset = 1.5f;
|
||||
public float verticalOffset = 1.0f;
|
||||
|
||||
[Header("Random Rotation Ranges")]
|
||||
public Vector2 rangeX = new Vector2(-360f, 360f);
|
||||
public Vector2 rangeY = new Vector2(-10f, 10f);
|
||||
public Vector2 rangeZ = new Vector2(50f, 120f);
|
||||
|
||||
private float lastAttackTime = 0f;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// if (inputReader != null && inputReader.IsAttackHeld)
|
||||
// {
|
||||
// if (Time.time - lastAttackTime >= attackRate)
|
||||
// {
|
||||
// PerformDismantle();
|
||||
// lastAttackTime = Time.time;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private void PerformDismantle()
|
||||
{
|
||||
GameObject selectedPrefab = GetRandomSlashVariant();
|
||||
if (selectedPrefab == null) return;
|
||||
|
||||
// Vị trí spawn trước mặt Player
|
||||
Vector3 spawnPos = transform.position + transform.forward * forwardOffset + Vector3.up * verticalOffset;
|
||||
|
||||
// Tạo góc xoay ngẫu nhiên theo yêu cầu của bạn
|
||||
float randX = Random.Range(rangeX.x, rangeX.y);
|
||||
float randY = Random.Range(rangeY.x, rangeY.y);
|
||||
float randZ = Random.Range(rangeZ.x, rangeZ.y);
|
||||
|
||||
// Kết hợp với hướng của Player
|
||||
Quaternion spawnRot = transform.rotation * Quaternion.Euler(randX, randY, randZ);
|
||||
|
||||
// Tạo đạn
|
||||
GameObject projectile = Instantiate(selectedPrefab, spawnPos, spawnRot);
|
||||
|
||||
// Bắt đạn bay về phía trước (hướng nhìn của Player)
|
||||
if (projectile.TryGetComponent<SukunaProjectile>(out var projScript))
|
||||
{
|
||||
projScript.SetDirection(transform.forward);
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject GetRandomSlashVariant()
|
||||
{
|
||||
float chance = Random.Range(0f, 100f);
|
||||
if (chance <= 20f) return redProjectilePrefab != null ? redProjectilePrefab : blackProjectilePrefab;
|
||||
return blackProjectilePrefab;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1630760c9d97a5f4eb1bc179549c95cd
|
||||
@@ -1,230 +0,0 @@
|
||||
// using UnityEngine;
|
||||
// using UnityEngine.Rendering;
|
||||
// using UnityEngine.Rendering.Universal;
|
||||
// using System.Collections;
|
||||
// using System.Collections.Generic;
|
||||
//
|
||||
// namespace Baba_yaga
|
||||
// {
|
||||
// [UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "OnlyScove.Scripts", sourceAssembly: "Opsive.UltimateCharacterController")]
|
||||
public class SukunaDomainController : MonoBehaviour
|
||||
// {
|
||||
// [Header("References")]
|
||||
// // public PlayerStateMachine playerStateMachine;
|
||||
// public GameObject slashPrefab;
|
||||
// public GameObject shrinePrefab;
|
||||
// public VolumeProfile domainVolumeProfile;
|
||||
// public Transform cinematicCameraPoint;
|
||||
//
|
||||
// [Header("Domain Settings")]
|
||||
// public float domainRadius = 15f;
|
||||
// public float domainDuration = 10f;
|
||||
//
|
||||
// [Tooltip("Số lượng vệt chém tạo ra mỗi giây")]
|
||||
// public float slashRate = 15f;
|
||||
//
|
||||
// public float shrineRiseHeight = 7f; // Độ sâu bắt đầu của miếu
|
||||
//
|
||||
// [Tooltip("Khoảng cách từ Pivot của Miếu đến mặt sàn nơi Player đứng")]
|
||||
// public float shrineFloorOffset = 0.5f;
|
||||
//
|
||||
// public float camMoveSpeed = 4f;
|
||||
//
|
||||
// private bool isActive = false;
|
||||
// private List<GameObject> activeSlashes = new List<GameObject>();
|
||||
// private Volume localVolume;
|
||||
// private GameObject spawnedShrine;
|
||||
//
|
||||
// // private void Start()
|
||||
// // {
|
||||
// // if (playerStateMachine == null)
|
||||
// // playerStateMachine = GetComponent<PlayerStateMachine>();
|
||||
// //
|
||||
// // if (playerStateMachine != null && playerStateMachine.Input != null)
|
||||
// // {
|
||||
// // playerStateMachine.Input.OnPreviousInteractEvent += HandleDomainExpansion;
|
||||
// // Debug.Log("<color=green>[Sukuna] Sẵn sàng. slashRate: " + slashRate + "</color>");
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// // private void OnDestroy()
|
||||
// // {
|
||||
// // if (playerStateMachine != null && playerStateMachine.Input != null)
|
||||
// // {
|
||||
// // playerStateMachine.Input.OnPreviousInteractEvent -= HandleDomainExpansion;
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// private void HandleDomainExpansion()
|
||||
// {
|
||||
// if (isActive) return;
|
||||
// Debug.Log("<color=red>[Sukuna] RYŌIKI TENKAI: FUKUMA MIZUZUSHI!</color>");
|
||||
// StartCoroutine(DomainSequence());
|
||||
// }
|
||||
//
|
||||
// // private IEnumerator DomainSequence()
|
||||
// // {
|
||||
// // isActive = true;
|
||||
// //
|
||||
// // // Lưu vị trí ban đầu của Player (Vị trí thực tế trên mặt đất)
|
||||
// // Vector3 playerStartPos = playerStateMachine.transform.position;
|
||||
// // playerStateMachine.SetControl(false);
|
||||
// //
|
||||
// // CameraController camController = playerStateMachine.Cam;
|
||||
// // bool originalCamEnabled = true;
|
||||
// // Transform mainCam = Camera.main.transform;
|
||||
// //
|
||||
// // if (camController != null)
|
||||
// // {
|
||||
// // originalCamEnabled = camController.enabled;
|
||||
// // camController.enabled = false;
|
||||
// // }
|
||||
// //
|
||||
// // // 1. Tạo Volume (Bóng bong lãnh địa)
|
||||
// // GameObject volumeObj = new GameObject("SukunaDomainVolume");
|
||||
// // volumeObj.transform.position = playerStartPos;
|
||||
// // localVolume = volumeObj.AddComponent<Volume>();
|
||||
// // localVolume.isGlobal = false;
|
||||
// // localVolume.priority = 100;
|
||||
// // localVolume.profile = domainVolumeProfile;
|
||||
// // SphereCollider volumeCollider = volumeObj.AddComponent<SphereCollider>();
|
||||
// // volumeCollider.isTrigger = true;
|
||||
// // volumeCollider.radius = 0.1f;
|
||||
// //
|
||||
// // // 2. Mọc miếu và đẩy Player
|
||||
// // if (shrinePrefab != null)
|
||||
// // {
|
||||
// // // Spawn miếu ở vị trí rất sâu dưới chân Player
|
||||
// // Vector3 shrineSpawnPos = playerStartPos - Vector3.up * shrineRiseHeight;
|
||||
// // spawnedShrine = Instantiate(shrinePrefab, shrineSpawnPos, playerStateMachine.transform.rotation);
|
||||
// //
|
||||
// // float riseDuration = 2.0f;
|
||||
// // float elapsed = 0;
|
||||
// // while (elapsed < riseDuration)
|
||||
// // {
|
||||
// // elapsed += Time.deltaTime;
|
||||
// // float t = Mathf.SmoothStep(0, 1, elapsed / riseDuration);
|
||||
// //
|
||||
// // // Di chuyển miếu lên dần dần
|
||||
// // Vector3 currentShrinePos = Vector3.Lerp(shrineSpawnPos, playerStartPos, t);
|
||||
// // spawnedShrine.transform.position = currentShrinePos;
|
||||
// //
|
||||
// // // Logic đẩy Player:
|
||||
// // // floorY là độ cao mặt sàn của miếu tại khung hình hiện tại
|
||||
// // float floorY = currentShrinePos.y + shrineFloorOffset;
|
||||
// //
|
||||
// // // Nếu mặt sàn của miếu đã trồi lên cao hơn vị trí chân Player ban đầu
|
||||
// // if (floorY > playerStartPos.y)
|
||||
// // {
|
||||
// // // Player đi theo miếu
|
||||
// // playerStateMachine.transform.position = new Vector3(playerStartPos.x, floorY, playerStartPos.z);
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // // Player đứng yên trên mặt đất ban đầu, chờ miếu trồi lên đỡ
|
||||
// // playerStateMachine.transform.position = playerStartPos;
|
||||
// // }
|
||||
// //
|
||||
// // // Mở rộng bán kính Volume
|
||||
// // volumeCollider.radius = Mathf.Lerp(0.1f, domainRadius, t);
|
||||
// //
|
||||
// // // Lia Camera mượt mà
|
||||
// // if (cinematicCameraPoint != null)
|
||||
// // {
|
||||
// // mainCam.position = Vector3.Lerp(mainCam.position, cinematicCameraPoint.position, Time.deltaTime * camMoveSpeed);
|
||||
// // mainCam.rotation = Quaternion.Slerp(mainCam.rotation, Quaternion.LookRotation((playerStateMachine.transform.position + Vector3.up * 2f) - mainCam.position), Time.deltaTime * camMoveSpeed);
|
||||
// // }
|
||||
// // yield return null;
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// // 3. Thực thi chém liên tục dựa trên slashRate
|
||||
// float timer = 0;
|
||||
// float slashCooldown = 1f / slashRate;
|
||||
// float lastSlashTime = 0;
|
||||
//
|
||||
// while (timer < domainDuration)
|
||||
// {
|
||||
// timer += Time.deltaTime;
|
||||
//
|
||||
// if (timer - lastSlashTime >= slashCooldown)
|
||||
// {
|
||||
// SpawnRandomSlash(playerStateMachine.transform.position);
|
||||
// lastSlashTime = timer;
|
||||
// }
|
||||
//
|
||||
// // Camera luôn theo dõi Player trên đỉnh miếu
|
||||
// if (cinematicCameraPoint != null)
|
||||
// {
|
||||
// mainCam.position = Vector3.Lerp(mainCam.position, cinematicCameraPoint.position, Time.deltaTime * camMoveSpeed * 0.5f);
|
||||
// mainCam.LookAt(playerStateMachine.transform.position + Vector3.up * 2f);
|
||||
// }
|
||||
// yield return null;
|
||||
// }
|
||||
//
|
||||
// // 4. Miếu sụp xuống (Player đứng lại vị trí Y ban đầu)
|
||||
// if (spawnedShrine != null)
|
||||
// {
|
||||
// float sinkTime = 1f;
|
||||
// float elapsed = 0;
|
||||
// Vector3 currentShrinePos = spawnedShrine.transform.position;
|
||||
// Vector3 targetSinkPos = currentShrinePos - Vector3.up * shrineRiseHeight;
|
||||
// while (elapsed < sinkTime)
|
||||
// {
|
||||
// elapsed += Time.deltaTime;
|
||||
// float t = elapsed / sinkTime;
|
||||
// spawnedShrine.transform.position = Vector3.Lerp(currentShrinePos, targetSinkPos, t);
|
||||
//
|
||||
// // Player từ từ hạ xuống sàn ban đầu
|
||||
// float floorY = spawnedShrine.transform.position.y + shrineFloorOffset;
|
||||
// if (floorY > playerStartPos.y)
|
||||
// playerStateMachine.transform.position = new Vector3(playerStartPos.x, floorY, playerStartPos.z);
|
||||
// else
|
||||
// playerStateMachine.transform.position = playerStartPos;
|
||||
//
|
||||
// yield return null;
|
||||
// }
|
||||
// Destroy(spawnedShrine);
|
||||
// }
|
||||
//
|
||||
// // 5. Thu nhỏ Volume
|
||||
// float shrinkDuration = 0.5f;
|
||||
// float sElapsed = 0;
|
||||
// while (sElapsed < shrinkDuration)
|
||||
// {
|
||||
// sElapsed += Time.deltaTime;
|
||||
// volumeCollider.radius = Mathf.Lerp(domainRadius, 0.1f, sElapsed / shrinkDuration);
|
||||
// yield return null;
|
||||
// }
|
||||
// Destroy(volumeObj);
|
||||
//
|
||||
// // Dọn dẹp
|
||||
// foreach (var s in activeSlashes) if (s != null) Destroy(s);
|
||||
// activeSlashes.Clear();
|
||||
//
|
||||
// if (camController != null) camController.enabled = originalCamEnabled;
|
||||
// playerStateMachine.SetControl(true);
|
||||
// isActive = false;
|
||||
// }
|
||||
//
|
||||
// private void SpawnRandomSlash(Vector3 center)
|
||||
// {
|
||||
// Vector2 randCircle = Random.insideUnitCircle * domainRadius;
|
||||
// Vector3 spawnPos = center + new Vector3(randCircle.x, Random.Range(1f, 6f), randCircle.y);
|
||||
//
|
||||
// if (slashPrefab != null)
|
||||
// {
|
||||
// GameObject slash = Instantiate(slashPrefab, spawnPos, Random.rotation);
|
||||
// slash.transform.localScale *= Random.Range(0.6f, 2.5f);
|
||||
// activeSlashes.Add(slash);
|
||||
// StartCoroutine(DestroySlashAfterTime(slash, 0.7f));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private IEnumerator DestroySlashAfterTime(GameObject slash, float time)
|
||||
// {
|
||||
// yield return new WaitForSeconds(time);
|
||||
// if (activeSlashes != null && activeSlashes.Contains(slash)) activeSlashes.Remove(slash);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 271dd39a46bad974485107bb1a070e0a
|
||||
@@ -1,27 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class SukunaProjectile : MonoBehaviour
|
||||
{
|
||||
[Header("Movement")]
|
||||
public float speed = 50f;
|
||||
public float lifetime = 3f;
|
||||
|
||||
private Vector3 moveDirection;
|
||||
|
||||
public void SetDirection(Vector3 direction)
|
||||
{
|
||||
// Nhận hướng bay từ Player (luôn là hướng phía trước)
|
||||
moveDirection = direction.normalized;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
Destroy(gameObject, lifetime);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Di chuyển đạn theo hướng đã gán, bất kể góc xoay hiển thị của nó là gì
|
||||
transform.position += moveDirection * speed * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9b0aad9f1697954a9f8710b4e8f3f2e
|
||||
@@ -1,53 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class SukunaSlashEffect : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
public float duration = 0.2f;
|
||||
public float maxScale = 5f;
|
||||
public AnimationCurve scaleCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
|
||||
|
||||
[Header("Visuals")]
|
||||
private MeshRenderer meshRenderer;
|
||||
private MaterialPropertyBlock propBlock;
|
||||
private float timer = 0f;
|
||||
private static readonly int DissolveId = Shader.PropertyToID("_Dissolve");
|
||||
|
||||
void Awake()
|
||||
{
|
||||
meshRenderer = GetComponent<MeshRenderer>();
|
||||
propBlock = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Reset scale ban đầu
|
||||
transform.localScale = new Vector3(maxScale, 0.1f, 0.1f);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
timer += Time.deltaTime;
|
||||
float normalizedTime = timer / duration;
|
||||
|
||||
if (normalizedTime <= 1.0f)
|
||||
{
|
||||
// Mở rộng vệt chém theo chiều ngang (Y hoặc Z tùy mesh)
|
||||
float currentScaleY = scaleCurve.Evaluate(normalizedTime) * maxScale;
|
||||
transform.localScale = new Vector3(maxScale, currentScaleY, 1f);
|
||||
|
||||
// Điều khiển Shader bằng MaterialPropertyBlock
|
||||
if (meshRenderer != null)
|
||||
{
|
||||
meshRenderer.GetPropertyBlock(propBlock);
|
||||
propBlock.SetFloat(DissolveId, normalizedTime);
|
||||
meshRenderer.SetPropertyBlock(propBlock);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tự hủy sau khi xong
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66ad11f71e7aac841be73f4b03cf0d83
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "Opsive.UltimateCharacterController.Editor",
|
||||
"references": [
|
||||
"Opsive.UltimateCharacterController",
|
||||
"Opsive.Shared",
|
||||
"Opsive.Shared.Editor",
|
||||
"Unity.InputSystem"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20dfc4c7578775b408501a7e6bd820e7
|
||||
timeCreated: 1545599552
|
||||
licenseType: Pro
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user