Untitled
unknown
plain_text
a month ago
19 kB
4
Indexable
using System; using System.Collections; using System.Collections.Generic; using DG.Tweening; using OnboardingSystem.Scripts.Interfaces; using OnboardingSystem.Scripts.Utilities; using TMPro; using UnityEngine; using UnityEngine.UI; namespace OnboardingSystem.Scripts { public class OnboardingUI : MonoBehaviour, IOnboardingUI { [SerializeField] private GameObject panel; [SerializeField] private GameObject messagePanel; [SerializeField] private TextMeshProUGUI messageLabel; [SerializeField] private GameObject highlightPrefab; [SerializeField] private RectTransform highlightParent; [SerializeField] private RectTransform finger; [SerializeField] private Image fingerImage; [SerializeField] private Image highlightBackground; [SerializeField] private Image messageBackground; private Sprite _fingerPressedSprite; private Sprite _fingerReleasedSprite; private Coroutine _fingerMoveRoutine; private Sequence _activeFingerSequence; private readonly List<GameObject> activeHighlights = new(); private void Start() { ToggleHighlightBackground(false); OnboardingEvents.OnShowOnboarding += Show; OnboardingEvents.OnHideOnboarding += Hide; } private void OnDisable() { finger?.DOKill(); finger?.transform.DOKill(); messagePanel?.transform.DOKill(); foreach (var highlight in activeHighlights) { highlight?.transform.DOKill(); } OnboardingEvents.OnShowOnboarding -= Show; OnboardingEvents.OnHideOnboarding -= Hide; } public void ShowMessage(string message, float textAnimationSpeed, bool canDismiss, float displayTime, Action onDismiss = null, Vector2? anchor = null, Vector2? offset = null, float scaleAnimationDuration = 0.5f, Ease scaleAnimationEase = Ease.OutBack) { messagePanel.transform.DOKill(); messageLabel.DOKill(); RectTransform messageRect = messagePanel.GetComponent<RectTransform>(); if (anchor.HasValue) { messageRect.anchorMin = anchor.Value; messageRect.anchorMax = anchor.Value; messageRect.pivot = anchor.Value; } if (offset.HasValue) messageRect.anchoredPosition = offset.Value; messageLabel.text = ""; messagePanel.SetActive(true); messageLabel.DOText(message, textAnimationSpeed).SetEase(Ease.Linear); Tween tween = messagePanel.transform.DOScale(Vector3.one, scaleAnimationDuration).SetEase(scaleAnimationEase); if (canDismiss) { tween.OnComplete(() => { Button btn = messagePanel.GetComponent<Button>(); if (btn == null) btn = messagePanel.AddComponent<Button>(); btn.onClick.RemoveAllListeners(); btn.onClick.AddListener(() => { HideMessage(() => onDismiss?.Invoke()); }); }); } else if (messagePanel.TryGetComponent(out Button button)) Destroy(button); if (displayTime > 0) DOVirtual.DelayedCall(displayTime, () => HideMessage(null)); } public void SetFontSize(bool useConstantFontSize, float constantFontSize, float minFontSize, float maxFontSize) { if (useConstantFontSize) messageLabel.fontSize = constantFontSize; else { messageLabel.enableAutoSizing = true; messageLabel.fontSizeMin = minFontSize; messageLabel.fontSizeMax = maxFontSize; } } public void HideMessage(Action onComplete) { messagePanel.transform.DOKill(); messageLabel.text = ""; messagePanel.transform.DOScale(Vector3.zero, 0.3f).SetEase(Ease.InBack).OnComplete(() => { messagePanel.SetActive(false); onComplete?.Invoke(); }); } public void Highlight(Vector3 position, Vector2 size, bool useWorldPosition = true, Sprite highlightSprite = null) { ToggleHighlightBackground(true); Camera uiCamera = highlightParent.GetComponentInParent<Canvas>().worldCamera; Vector2 screenPos; if (useWorldPosition) { screenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, position); } else { screenPos = position; } RectTransformUtility.ScreenPointToLocalPointInRectangle(highlightParent, screenPos, uiCamera, out Vector2 localPos); GameObject newHighlight = Instantiate(highlightPrefab, highlightParent.transform); if (highlightSprite != null) newHighlight.GetComponent<Image>().sprite = highlightSprite; newHighlight.transform.SetAsFirstSibling(); RectTransform highlightRect = newHighlight.GetComponent<RectTransform>(); highlightRect.anchoredPosition = localPos; highlightRect.sizeDelta = size; activeHighlights.Add(newHighlight); } public void HighlightWithId(int id, Vector2 size, bool useWorldPosition = true, Sprite highlightSprite = null) { var target = OnboardingUtilities.GetTargetById(id); if (target == null) return; Vector3 position; if (useWorldPosition) { position = target.transform.position; } else { RectTransform rectTransform = target.GetComponent<RectTransform>(); if (rectTransform != null) { position = rectTransform.position; } else { Camera uiCamera = highlightParent.GetComponentInParent<Canvas>().worldCamera; position = RectTransformUtility.WorldToScreenPoint(uiCamera, target.transform.position); } } Highlight(position, size, useWorldPosition, highlightSprite); } public void DragDropFingerAnimation(Vector3 startWorldPos, Vector3 endWorldPos, Vector2 offset, float duration, Ease ease, LoopType loopType, int loopCount, float startScale, float pressScale, float endScale) { HideFinger(); Camera uiCamera = GetComponentInParent<Canvas>().worldCamera; Vector2 startScreenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, startWorldPos); Vector2 endScreenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, endWorldPos); RectTransformUtility.ScreenPointToLocalPointInRectangle(transform as RectTransform, startScreenPos, uiCamera, out Vector2 startLocalPos); RectTransformUtility.ScreenPointToLocalPointInRectangle(transform as RectTransform, endScreenPos, uiCamera, out Vector2 endLocalPos); finger.gameObject.SetActive(true); finger.anchoredPosition = startLocalPos + offset; endLocalPos += offset; fingerImage.color = new Color(1, 1, 1, 0); finger.localScale = Vector3.one * startScale; _activeFingerSequence?.Kill(); _activeFingerSequence = DOTween.Sequence(); _activeFingerSequence.Append(fingerImage.DOFade(1, 0.3f).SetEase(Ease.OutQuad)); _activeFingerSequence.AppendCallback(() => { fingerImage.sprite = _fingerPressedSprite; finger.localScale = Vector3.one * pressScale; }); _activeFingerSequence.Join(finger.DOScale(Vector3.one * pressScale, 0.2f).SetEase(Ease.OutBack)); _activeFingerSequence.Append(finger.DOAnchorPos(endLocalPos, duration).SetEase(Ease.InOutQuad)); _activeFingerSequence.AppendCallback(() => { fingerImage.sprite = _fingerReleasedSprite; finger.localScale = Vector3.one * endScale; }); _activeFingerSequence.Join(finger.DOScale(Vector3.one * endScale, 0.2f).SetEase(Ease.OutBack)); _activeFingerSequence.Append(fingerImage.DOFade(0, 0.3f).SetEase(Ease.InQuad)); _activeFingerSequence.Join(finger.DOScale(Vector3.one * startScale, 0.3f)); if (loopCount > 0) _activeFingerSequence.SetLoops(loopCount, loopType).OnComplete(() => finger.gameObject.SetActive(false)); else _activeFingerSequence.SetLoops(-1, loopType); _activeFingerSequence.OnKill(() => { fingerImage.color = Color.white; finger.localScale = Vector3.one; }); } public void DragDropFingerAnimationWithIds(int startId, int endId, Vector2 offset, float duration, Ease ease, LoopType loopType, int loopCount, float startScale, float pressScale, float endScale) { if (finger != null) { finger.DOKill(); finger.transform.DOKill(); } if (_fingerMoveRoutine != null) StopCoroutine(_fingerMoveRoutine); _fingerMoveRoutine = StartCoroutine(MoveFingerRoutine(startId, endId, offset, duration, ease, loopType, loopCount, startScale, pressScale, endScale)); } private IEnumerator MoveFingerRoutine(int startId, int endId, Vector2 offset, float duration, Ease ease, LoopType loopType, int loopCount, float startScale, float pressScale, float endScale) { Canvas canvas = GetComponentInParent<Canvas>(); Camera uiCamera = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera; if (finger == null || fingerImage == null) yield break; finger.gameObject.SetActive(true); fingerImage.color = new Color(1, 1, 1, 0); finger.localScale = Vector3.one * startScale; int currentLoop = 0; while (loopCount <= 0 || currentLoop < loopCount) { var onboardingObjects = FindObjectsOfType<OnboardingObject>(); var startObject = Array.Find(onboardingObjects, obj => obj.id == startId); var endObject = Array.Find(onboardingObjects, obj => obj.id == endId); if (startObject == null || endObject == null) { Debug.LogError("Onboarding object with id not found"); yield break; } Vector2 startScreenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, startObject.transform.position); Vector2 endScreenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, endObject.transform.position); RectTransform rt = transform as RectTransform; if (rt == null || !RectTransformUtility.ScreenPointToLocalPointInRectangle(rt, startScreenPos, uiCamera, out Vector2 startLocalPos) || !RectTransformUtility.ScreenPointToLocalPointInRectangle(rt, endScreenPos, uiCamera, out Vector2 endLocalPos)) { yield return null; continue; } finger.DOKill(); finger.transform.DOKill(); finger.anchoredPosition = startLocalPos + offset; endLocalPos += offset; Sequence seq = DOTween.Sequence(); seq.SetTarget(finger); seq.SetEase(ease); seq.Append(fingerImage.DOFade(1, 0.3f).SetEase(Ease.OutQuad)); seq.AppendCallback(() => { fingerImage.sprite = _fingerPressedSprite; finger.localScale = Vector3.one * pressScale; }); seq.Join(finger.DOScale(Vector3.one * pressScale, 0.2f).SetEase(Ease.OutBack)); seq.Append(finger.DOAnchorPos(endLocalPos, duration).SetEase(Ease.InOutQuad)); seq.AppendCallback(() => { fingerImage.sprite = _fingerReleasedSprite; finger.localScale = Vector3.one * endScale; }); seq.Join(finger.DOScale(Vector3.one * endScale, 0.2f).SetEase(Ease.OutBack)); seq.Append(fingerImage.DOFade(0, 0.3f).SetEase(Ease.InQuad)); seq.Join(finger.DOScale(Vector3.one * startScale, 0.3f)); seq.AppendInterval(0.3f); yield return seq.WaitForCompletion(); currentLoop++; } finger.gameObject.SetActive(false); } public void PointFingerAt(Vector3 worldPosition, Vector2 offset, float duration, Ease ease, LoopType loopType, int loopCount, float startScale, float pressScale, float endScale) { HideFinger(); Camera uiCamera = GetComponentInParent<Canvas>().worldCamera; Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, worldPosition); RectTransformUtility.ScreenPointToLocalPointInRectangle(transform as RectTransform, screenPos, uiCamera, out Vector2 localPos); finger.gameObject.SetActive(true); finger.anchoredPosition = localPos + offset; finger.localScale = Vector3.one * startScale; _activeFingerSequence?.Kill(); _activeFingerSequence = DOTween.Sequence(); _activeFingerSequence.SetEase(ease); _activeFingerSequence.AppendCallback(() => { fingerImage.sprite = _fingerPressedSprite; }); _activeFingerSequence.Append(finger.DOScale(Vector3.one * pressScale, 0.2f).SetEase(Ease.OutBack)); _activeFingerSequence.AppendInterval(duration); _activeFingerSequence.AppendCallback(() => { fingerImage.sprite = _fingerReleasedSprite; }); _activeFingerSequence.Append(finger.DOScale(Vector3.one * endScale, 0.3f).SetEase(Ease.OutBack)); _activeFingerSequence.AppendInterval(0.3f); if (loopCount > 0) _activeFingerSequence.SetLoops(loopCount, loopType).OnComplete(() => finger.gameObject.SetActive(false)); else _activeFingerSequence.SetLoops(-1, loopType); } public void PointFingerAtWithId(int id, Vector2 offset, float duration, Ease ease, LoopType loopType, int loopCount, float startScale, float pressScale, float endScale) { if (finger != null) { finger.DOKill(); finger.transform.DOKill(); } if (_fingerMoveRoutine != null) StopCoroutine(_fingerMoveRoutine); _fingerMoveRoutine = StartCoroutine(PointFingerAtWithIdRoutine(id, offset, duration, ease, loopType, loopCount, startScale, pressScale, endScale)); } private IEnumerator PointFingerAtWithIdRoutine(int endId, Vector2 offset, float duration, Ease ease, LoopType loopType, int loopCount, float startScale, float pressScale, float endScale) { Canvas canvas = GetComponentInParent<Canvas>(); Camera uiCamera = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera; if (finger == null || fingerImage == null) yield break; int currentLoop = 0; while (loopCount <= 0 || currentLoop < loopCount) { var onboardingObjects = FindObjectsOfType<OnboardingObject>(); var endObject = Array.Find(onboardingObjects, obj => obj.id == endId); if (endObject == null) { Debug.LogError("Onboarding object with id not found"); yield break; } Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, endObject.transform.position); RectTransformUtility.ScreenPointToLocalPointInRectangle(transform as RectTransform, screenPos, uiCamera, out Vector2 targetLocalPos); finger.anchoredPosition = targetLocalPos + offset; finger.gameObject.SetActive(true); finger.localScale = Vector3.one * startScale; Sequence seq = DOTween.Sequence(); seq.SetEase(ease); seq.AppendCallback(() => { fingerImage.sprite = _fingerPressedSprite; }); seq.Append(finger.DOScale(Vector3.one * pressScale, 0.2f).SetEase(Ease.OutBack)); seq.AppendInterval(duration); seq.AppendCallback(() => { fingerImage.sprite = _fingerReleasedSprite; }); seq.Append(finger.DOScale(Vector3.one * endScale, 0.3f).SetEase(Ease.OutBack)); seq.AppendInterval(0.3f); yield return seq.WaitForCompletion(); currentLoop++; } finger.gameObject.SetActive(false); } public void HideFinger() { if (_fingerMoveRoutine != null) StopCoroutine(_fingerMoveRoutine); _fingerMoveRoutine = null; finger.DOKill(); finger.transform.DOKill(); if (_activeFingerSequence != null && _activeFingerSequence.IsActive()) _activeFingerSequence.Kill(); finger.gameObject.SetActive(false); finger.anchoredPosition = Vector2.zero; fingerImage.color = Color.white; finger.localScale = Vector3.one; } public void ClearHighlights(bool hideBackground) { foreach (var highlight in activeHighlights) Destroy(highlight); activeHighlights.Clear(); ToggleHighlightBackground(!hideBackground); } public void Hide() => panel.SetActive(false); public void Show() => panel.SetActive(true); public void SetFingerSprites(Sprite released, Sprite pressed) { _fingerReleasedSprite = released; _fingerPressedSprite = pressed; } public void SetMessageBackground(Sprite sprite) => messageBackground.sprite = sprite; public void Deactivate() { Hide(); HideMessage(null); HideFinger(); ClearHighlights(true); } private void ToggleHighlightBackground(bool show) => highlightBackground.gameObject.SetActive(show); } }
Editor is loading...
Leave a Comment