This commit is contained in:
2026-04-29 02:31:15 +07:00
parent 21c999a904
commit ed86fface3
12 changed files with 433 additions and 79 deletions

View File

@@ -36,6 +36,9 @@ namespace Hallucinate.UI
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");
@@ -51,12 +54,28 @@ namespace Hallucinate.UI
_lastInteractionTime = Time.time;
}
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;
_logo.style.translate = new StyleTranslate(new Translate(0, 0));
_logo.style.left = (Screen.width / 2f) - 100;
_logo.style.top = (Screen.height / 2f) - 100;
// 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;
}
@@ -132,34 +151,55 @@ namespace Hallucinate.UI
_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;
// Center logo in LogoSpace (within the centered Ribbon)
float targetX = targetBounds.x + (targetBounds.width / 2f) - 50f;
float targetY = targetBounds.y + (targetBounds.height / 2f) - 50f;
// 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));
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);
float targetX = localPos.x + (targetBounds.width / 2f);
float targetY = localPos.y + (targetBounds.height / 2f);
Tween.Custom(_logo.resolvedStyle.width, 100f, duration: 0.5f,
onValueChange: val => _logo.style.width = val,
ease: Ease.OutQuad);
// 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)));
Tween.Custom(_logo.resolvedStyle.height, 100f, duration: 0.5f,
onValueChange: val => _logo.style.height = val,
ease: Ease.OutQuad);
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;
}
@@ -169,13 +209,22 @@ namespace Hallucinate.UI
if (_currentState == MenuState.Idle) return;
_currentState = MenuState.Idle;
float targetX = (Screen.width / 2f) - 100;
float targetY = (Screen.height / 2f) - 100;
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);
// 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);