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 />
|
<configurations />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<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="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
<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