This commit is contained in:
2026-04-28 10:48:04 +07:00
parent f925c61277
commit 3bbc623b2d
2 changed files with 54 additions and 48 deletions

View File

@@ -5,10 +5,7 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="f9183c68-daf0-43b8-be4c-fad79983f91b" name="Changes" comment=""> <list default="true" id="f9183c68-daf0-43b8-be4c-fad79983f91b" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/UI/MainMenuController.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/UI/MainMenuController.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/UI/UIManager.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/UI/UIManager.cs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Assets/Scripts/UI/UIManager.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/UI/UIManager.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/UI/MainMenu.uxml" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/UI/MainMenu.uxml" afterDir="false" />
</list> </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" />
@@ -145,7 +142,7 @@
<workItem from="1777150520438" duration="58000" /> <workItem from="1777150520438" duration="58000" />
<workItem from="1777150592854" duration="4699000" /> <workItem from="1777150592854" duration="4699000" />
<workItem from="1777181837663" duration="1519000" /> <workItem from="1777181837663" duration="1519000" />
<workItem from="1777269364664" duration="28868000" /> <workItem from="1777269364664" duration="29255000" />
</task> </task>
<servers /> <servers />
</component> </component>

View File

@@ -17,7 +17,7 @@ namespace Hallucinate.UI
private UIDocument _uiDocument; private UIDocument _uiDocument;
private VisualElement _rootElement; private VisualElement _rootElement;
private VisualElement _cursorLayer; // Lớp trên cùng chứa trail và ripples private VisualElement _cursorLayer;
private readonly Dictionary<Type, BaseUIController> _controllers = new Dictionary<Type, BaseUIController>(); private readonly Dictionary<Type, BaseUIController> _controllers = new Dictionary<Type, BaseUIController>();
private readonly Stack<BaseUIController> _history = new Stack<BaseUIController>(); private readonly Stack<BaseUIController> _history = new Stack<BaseUIController>();
@@ -41,6 +41,7 @@ namespace Hallucinate.UI
private MainMenuController _mainMenuController; private MainMenuController _mainMenuController;
private List<VisualElement> _trailSegments = new List<VisualElement>(); private List<VisualElement> _trailSegments = new List<VisualElement>();
private List<Vector2> _trailPositions = new List<Vector2>();
private void Awake() private void Awake()
{ {
@@ -55,32 +56,38 @@ namespace Hallucinate.UI
return; return;
} }
_uiDocument = GetComponent<UIDocument>(); try
_rootElement = _uiDocument.rootVisualElement; {
_uiDocument = GetComponent<UIDocument>();
_rootElement = _uiDocument.rootVisualElement;
// Tạo lớp Cursor trên cùng // Tạo lớp Cursor
_cursorLayer = new VisualElement(); _cursorLayer = new VisualElement();
_cursorLayer.name = "CursorLayer"; _cursorLayer.name = "CursorLayer";
_cursorLayer.style.position = Position.Absolute; _cursorLayer.style.position = Position.Absolute;
_cursorLayer.style.width = Length.Percent(100); _cursorLayer.style.width = Length.Percent(100);
_cursorLayer.style.height = Length.Percent(100); _cursorLayer.style.height = Length.Percent(100);
_cursorLayer.pickingMode = PickingMode.Ignore; _cursorLayer.pickingMode = PickingMode.Ignore;
_rootElement.Add(_cursorLayer); _rootElement.Add(_cursorLayer);
SetupCursorTrail(); SetupCursorTrail();
// Đăng ký ripple toàn cục // Ripple
_rootElement.RegisterCallback<PointerDownEvent>(OnGlobalClick, TrickleDown.TrickleDown); _rootElement.RegisterCallback<PointerDownEvent>(OnGlobalClick, TrickleDown.TrickleDown);
#if UNITY_EDITOR #if UNITY_EDITOR
if (gameIcon == null) if (gameIcon == null)
{ {
var icons = PlayerSettings.GetIconsForTargetGroup(BuildTargetGroup.Unknown); var icons = PlayerSettings.GetIconsForTargetGroup(BuildTargetGroup.Unknown);
if (icons != null && icons.Length > 0) gameIcon = icons[0]; if (icons != null && icons.Length > 0) gameIcon = icons[0];
} }
#endif #endif
InitializeControllers();
InitializeControllers(); }
catch (Exception e)
{
Debug.LogError($"[UIManager] Error during Awake: {e.Message}\n{e.StackTrace}");
}
} }
private void SetupCursorTrail() private void SetupCursorTrail()
@@ -93,13 +100,16 @@ namespace Hallucinate.UI
segment.style.position = Position.Absolute; segment.style.position = Position.Absolute;
segment.style.width = cursorSize; segment.style.width = cursorSize;
segment.style.height = cursorSize; segment.style.height = cursorSize;
segment.style.backgroundImage = new StyleBackground(cursorTrailSprite); segment.style.backgroundImage = new StyleBackground(Background.FromSprite(cursorTrailSprite));
segment.style.opacity = 1f - ((float)i / trailLength);
segment.style.scale = new StyleScale(new Vector2(1f - ((float)i / trailLength), 1f - ((float)i / trailLength))); float ratio = 1f - ((float)i / trailLength);
segment.style.opacity = ratio;
segment.style.scale = new StyleScale(new Scale(new Vector3(ratio, ratio, 1f)));
segment.pickingMode = PickingMode.Ignore; segment.pickingMode = PickingMode.Ignore;
_cursorLayer.Add(segment); _cursorLayer.Add(segment);
_trailSegments.Add(segment); _trailSegments.Add(segment);
_trailPositions.Add(Vector2.zero);
} }
} }
@@ -111,10 +121,13 @@ namespace Hallucinate.UI
ripple.style.position = Position.Absolute; ripple.style.position = Position.Absolute;
ripple.style.width = cursorSize; ripple.style.width = cursorSize;
ripple.style.height = cursorSize; ripple.style.height = cursorSize;
ripple.style.borderTopLeftRadius = cursorSize;
ripple.style.borderTopRightRadius = cursorSize; var radius = new StyleLength(new Length(50, LengthUnit.Percent));
ripple.style.borderBottomLeftRadius = cursorSize; ripple.style.borderTopLeftRadius = radius;
ripple.style.borderBottomRightRadius = cursorSize; ripple.style.borderTopRightRadius = radius;
ripple.style.borderBottomLeftRadius = radius;
ripple.style.borderBottomRightRadius = radius;
ripple.style.borderTopColor = rippleColor; ripple.style.borderTopColor = rippleColor;
ripple.style.borderBottomColor = rippleColor; ripple.style.borderBottomColor = rippleColor;
ripple.style.borderLeftColor = rippleColor; ripple.style.borderLeftColor = rippleColor;
@@ -130,7 +143,6 @@ namespace Hallucinate.UI
_cursorLayer.Add(ripple); _cursorLayer.Add(ripple);
// Hiệu ứng Ripple: To ra và nhạt dần (Sửa lỗi dùng Vector3 thay vì float)
Tween.Scale(ripple.transform, Vector3.one * 3f, duration: 0.5f, ease: Ease.OutQuad); Tween.Scale(ripple.transform, Vector3.one * 3f, duration: 0.5f, ease: Ease.OutQuad);
Tween.Custom(1f, 0f, duration: 0.5f, onValueChange: val => ripple.style.opacity = val) Tween.Custom(1f, 0f, duration: 0.5f, onValueChange: val => ripple.style.opacity = val)
.OnComplete(() => ripple.RemoveFromHierarchy()); .OnComplete(() => ripple.RemoveFromHierarchy());
@@ -149,22 +161,20 @@ namespace Hallucinate.UI
Vector2 mousePos = Input.mousePosition; Vector2 mousePos = Input.mousePosition;
Vector2 uiPos = new Vector2(mousePos.x, Screen.height - mousePos.y); Vector2 uiPos = new Vector2(mousePos.x, Screen.height - mousePos.y);
// Segment đầu tiên đi theo chuột // Cập nhật vị trí đầu tiên
_trailSegments[0].style.left = uiPos.x - (cursorSize / 2); _trailPositions[0] = uiPos;
_trailSegments[0].style.top = uiPos.y - (cursorSize / 2);
// Các segment sau đuổi theo segment trước // Đuổi theo mượt mà
for (int i = 1; i < _trailSegments.Count; i++) for (int i = 1; i < _trailPositions.Count; i++)
{ {
float targetX = _trailSegments[i - 1].resolvedStyle.left; _trailPositions[i] = Vector2.Lerp(_trailPositions[i], _trailPositions[i - 1], Time.deltaTime * 25f);
float targetY = _trailSegments[i - 1].resolvedStyle.top; }
float currX = _trailSegments[i].resolvedStyle.left; // Áp dụng vào UI
float currY = _trailSegments[i].resolvedStyle.top; for (int i = 0; i < _trailSegments.Count; i++)
{
// Nội suy để mượt mà (Lerp) _trailSegments[i].style.left = _trailPositions[i].x - (cursorSize / 2);
_trailSegments[i].style.left = Mathf.Lerp(currX, targetX, Time.deltaTime * 20f); _trailSegments[i].style.top = _trailPositions[i].y - (cursorSize / 2);
_trailSegments[i].style.top = Mathf.Lerp(currY, targetY, Time.deltaTime * 20f);
} }
} }
@@ -196,7 +206,6 @@ namespace Hallucinate.UI
instance.style.display = DisplayStyle.None; instance.style.display = DisplayStyle.None;
_rootElement.Add(instance); _rootElement.Add(instance);
// Luôn đảm bảo CursorLayer nằm trên cùng sau khi add màn hình mới
_cursorLayer.BringToFront(); _cursorLayer.BringToFront();
var controller = new T(); var controller = new T();
@@ -214,7 +223,7 @@ namespace Hallucinate.UI
_history.Push(newScreen); _history.Push(newScreen);
await newScreen.PlayTransitionIn(); await newScreen.PlayTransitionIn();
_cursorLayer.BringToFront(); // Giữ trail luôn trên cùng _cursorLayer.BringToFront();
} }
public async Task Pop() public async Task Pop()