This commit is contained in:
2026-04-28 11:35:49 +07:00
parent 99f2b0621a
commit 8e6643beaf
9 changed files with 341 additions and 48 deletions

View File

@@ -10,10 +10,9 @@ namespace OnlyScove.Scripts
public virtual Vector2 MoveInput { get; protected set; }
public virtual Vector2 LookInput { get; protected set; }
public virtual Vector2 ScrollInput { get; protected set; }
public virtual bool IsSprintHeld { get; protected set; } // Left Shift
public virtual bool IsAttackHeld { get; protected set; } // Left Mouse Button
public virtual bool IsSprintHeld { get; protected set; }
public virtual bool IsAttackHeld { get; protected set; }
// THÊM HÀM NÀY ĐỂ ĐỒNG BỘ MẠNG
public void ApplyNetworkInput(Vector2 move, bool isSprint)
{
MoveInput = move;
@@ -21,15 +20,19 @@ namespace OnlyScove.Scripts
}
// One-shot Events
public event Action OnJumpEvent; // Space
public event Action OnDodgeEvent; // Right Mouse Button (RMB)
public event Action OnSprintEvent; // Left Shift
public event Action OnAttackEvent; // Left Mouse Button (LMB)
public event Action OnCrouchEvent; // C Key
public event Action OnInteractEvent; // E Key
public event Action OnNextInteractEvent; // R Key
public event Action OnPreviousInteractEvent; // Q Key
public event Action OnToggleViewEvent; // F2 - New event for toggling camera view
public event Action OnJumpEvent;
public event Action OnDodgeEvent;
public event Action OnSprintEvent;
public event Action OnAttackEvent;
public event Action OnCrouchEvent;
public event Action OnInteractEvent;
public event Action OnNextInteractEvent;
public event Action OnPreviousInteractEvent;
public event Action OnToggleViewEvent;
// UI Events
public event Action OnToggleSettingsEvent; // Cho Ctrl+O
public event Action OnCancelEvent; // Cho phím ESC hoặc phím đóng UI
public void OnAttack(InputAction.CallbackContext context)
{
@@ -69,13 +72,9 @@ namespace OnlyScove.Scripts
if (context.canceled) IsSprintHeld = false;
}
// New method for ToggleView input
public void OnToggleView(InputAction.CallbackContext context)
{
if (context.performed)
{
OnToggleViewEvent?.Invoke();
}
if (context.performed) OnToggleViewEvent?.Invoke();
}
public void OnJump(InputAction.CallbackContext context)
@@ -95,13 +94,7 @@ namespace OnlyScove.Scripts
public void OnInteract(InputAction.CallbackContext context)
{
Debug.Log($"[InputReader] Interaction State: {context.phase} | Started: {context.started} | Performed: {context.performed} | Canceled: {context.canceled}");
if (context.performed)
{
Debug.Log("[InputReader] Event OnInteractEvent triggered!");
OnInteractEvent?.Invoke();
}
if (context.performed) OnInteractEvent?.Invoke();
}
public void OnNext(InputAction.CallbackContext context)
@@ -113,5 +106,20 @@ namespace OnlyScove.Scripts
{
if (context.performed) OnPreviousInteractEvent?.Invoke();
}
// UI Callbacks
public void OnToggleSettings(InputAction.CallbackContext context)
{
if (context.performed)
{
Debug.Log("[InputReader] Toggle Settings Action Performed!");
OnToggleSettingsEvent?.Invoke();
}
}
public void OnCancel(InputAction.CallbackContext context)
{
if (context.performed) OnCancelEvent?.Invoke();
}
}
}
}

View File

@@ -103,7 +103,6 @@ namespace Hallucinate.UI
// Khởi động lại rotation nếu có icon
StartRotation();
UnityEngine.Cursor.visible = true;
await base.PlayTransitionIn();
// Nếu không phải lần đầu load (tức là quay lại bằng nút Back), tự động bung Ribbon

View File

@@ -19,25 +19,38 @@ namespace Hallucinate.UI
_tabTitle = root.Q<Label>("TabTitle");
_content = root.Q<ScrollView>("SettingsContent");
// Logic đóng khi nhấn vào vùng nền bên ngoài sidebar
root.RegisterCallback<ClickEvent>(evt => {
if (evt.target == root)
{
uiManager.ToggleSettings();
}
});
root.Q<Button>("GeneralTab").clicked += () => SwitchTab("GENERAL");
root.Q<Button>("VideoTab").clicked += () => SwitchTab("VIDEO");
root.Q<Button>("SoundTab").clicked += () => SwitchTab("SOUND");
root.Q<Button>("ControlTab").clicked += () => SwitchTab("CONTROL");
root.Q<Button>("CloseSettingsBtn").clicked += () => uiManager.Pop();
root.Q<Button>("CloseSettingsBtn").clicked += () => uiManager.ToggleSettings();
}
private void SwitchTab(string title)
{
_tabTitle.text = title;
// Clear and add specific settings content
_content.Clear();
_content.Add(new Label($"Settings for {title} coming soon..."));
}
public override async Task PlayTransitionIn()
{
if (root != null) root.style.translate = new StyleTranslate(new Translate(0, 0));
Show();
// Reset vị trí root về 0 (Overlay trên màn hình hiện tại)
if (root != null)
{
root.style.translate = new StyleTranslate(new Translate(0, 0));
root.style.display = DisplayStyle.Flex;
}
// Trượt sidebar từ trái vào
_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)));
@@ -45,8 +58,10 @@ namespace Hallucinate.UI
public override async Task PlayTransitionOut()
{
// Trượt sidebar ra trái
await Tween.Custom(0f, -100f, duration: 0.4f, ease: Ease.InQuad,
onValueChange: val => _sidebar.style.translate = new StyleTranslate(new Translate(Length.Percent(val), 0)));
Hide();
}
}

View File

@@ -4,6 +4,7 @@ using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using PrimeTween;
using OnlyScove.Scripts; // Namespace của InputReader
#if UNITY_EDITOR
using UnityEditor;
#endif
@@ -23,6 +24,9 @@ namespace Hallucinate.UI
private readonly Dictionary<Type, BaseUIController> _controllers = new Dictionary<Type, BaseUIController>();
private readonly Stack<BaseUIController> _history = new Stack<BaseUIController>();
[Header("References")]
[SerializeField] private InputReader inputReader;
[Header("Game Metadata")]
[SerializeField] private Texture2D gameIcon;
@@ -41,16 +45,20 @@ namespace Hallucinate.UI
[SerializeField] private VisualTreeAsset profileTemplate;
[SerializeField] private VisualTreeAsset settingsTemplate;
[SerializeField] private VisualTreeAsset hudTemplate;
private MainMenuController _mainMenuController;
private SettingsController _settingsController;
private List<VisualElement> _trailSegments = new List<VisualElement>();
private List<Vector2> _posHistory = new List<Vector2>();
private Vector2 _lastMousePos;
private float _trailOpacity = 1f;
private bool _isSettingsOpen = false;
private void Awake()
{
Instance = this;
_uiDocument = GetComponent<UIDocument>();
// Chỉ định rõ UnityEngine.Cursor để tránh lỗi Ambiguous
UnityEngine.Cursor.visible = false;
}
@@ -71,6 +79,13 @@ namespace Hallucinate.UI
_rootElement.RegisterCallback<PointerDownEvent>(OnGlobalClick, TrickleDown.TrickleDown);
// Đăng ký sự kiện từ InputReader (Chuẩn New Input System)
if (inputReader != null)
{
inputReader.OnToggleSettingsEvent += ToggleSettings;
inputReader.OnCancelEvent += HandleCancel;
}
#if UNITY_EDITOR
if (gameIcon == null)
{
@@ -81,6 +96,43 @@ namespace Hallucinate.UI
InitializeControllers();
}
private void OnDestroy()
{
if (inputReader != null)
{
inputReader.OnToggleSettingsEvent -= ToggleSettings;
inputReader.OnCancelEvent -= HandleCancel;
}
}
private void HandleCancel()
{
if (_isSettingsOpen) ToggleSettings();
}
public async void ToggleSettings()
{
if (_settingsController == null) return;
if (!_isSettingsOpen)
{
_isSettingsOpen = true;
_cursorLayer.BringToFront();
await _settingsController.PlayTransitionIn();
}
else
{
_isSettingsOpen = false;
await _settingsController.PlayTransitionOut();
}
}
private void Update()
{
if (_mainMenuController != null) _mainMenuController.Update();
UpdateCursorAndTrail();
}
private void SetupVirtualCursor()
{
_cursorLayer.Clear();
@@ -98,7 +150,7 @@ namespace Hallucinate.UI
segment.style.backgroundImage = new StyleBackground(Background.FromSprite(cursorTrailSprite));
float ratio = 1f - ((float)i / trailLength);
segment.style.opacity = ratio * 0.5f;
segment.style.opacity = 0f;
segment.style.scale = new StyleScale(new Scale(new Vector3(ratio, ratio, 1f)));
segment.style.translate = new StyleTranslate(new Translate(Length.Percent(-50), Length.Percent(-50)));
segment.pickingMode = PickingMode.Ignore;
@@ -118,6 +170,7 @@ namespace Hallucinate.UI
_cursorLayer.Add(_mainCursor);
Vector2 startPos = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y);
_lastMousePos = startPos;
for (int i = 0; i < trailLength * trailSpacing + 1; i++) _posHistory.Add(startPos);
}
@@ -157,12 +210,6 @@ namespace Hallucinate.UI
.OnComplete(() => ripple.RemoveFromHierarchy());
}
private void Update()
{
if (_mainMenuController != null) _mainMenuController.Update();
UpdateCursorAndTrail();
}
private void UpdateCursorAndTrail()
{
if (!Application.isFocused)
@@ -183,6 +230,12 @@ namespace Hallucinate.UI
if (_cursorLayer != null) _cursorLayer.style.display = DisplayStyle.Flex;
Vector2 uiPos = new Vector2(mousePos.x, Screen.height - mousePos.y);
float mouseSpeed = Vector2.Distance(uiPos, _lastMousePos);
_lastMousePos = uiPos;
if (mouseSpeed > 0.1f) _trailOpacity = Mathf.MoveTowards(_trailOpacity, 1f, Time.deltaTime * 5f);
else _trailOpacity = Mathf.MoveTowards(_trailOpacity, 0f, Time.deltaTime * 3f);
_posHistory.Insert(0, uiPos);
if (_posHistory.Count > trailLength * trailSpacing + 1)
_posHistory.RemoveAt(_posHistory.Count - 1);
@@ -200,6 +253,8 @@ namespace Hallucinate.UI
{
_trailSegments[i].style.left = _posHistory[historyIndex].x;
_trailSegments[i].style.top = _posHistory[historyIndex].y;
float baseRatio = 1f - ((float)i / trailLength);
_trailSegments[i].style.opacity = baseRatio * 0.5f * _trailOpacity;
}
}
}
@@ -211,7 +266,7 @@ namespace Hallucinate.UI
RegisterController<LobbyController>(lobbyTemplate);
RegisterController<ProfileController>(profileTemplate);
RegisterController<SettingsController>(settingsTemplate);
_settingsController = RegisterController<SettingsController>(settingsTemplate);
RegisterController<HUDController>(hudTemplate);
_ = Push<MainMenuController>();