using UnityEngine; using UnityEngine.UI; using TMPro; using Unheimlich.Utility; namespace Unheimlich.Interactions.FloatingWords { public class SketchFadeEffect : MonoBehaviour { private TextMeshProUGUI _textComponent; private TextMeshProUGUI _ghostTextComponent; private Image _scribbleOverlay; private Material _scribbleMaterialInstance; private Material _scribbleMaterialTemplate; private static readonly int ProgressID = Shader.PropertyToID("_Progress"); private bool _isEffectActive = false; private bool _overlayCreated = false; private Color _originalTextColor; private Color _originalGhostColor; private int _scribbleTweenId = -1; private int _fadeTweenId = -1; public void Initialize(TextMeshProUGUI textComponent, TextMeshProUGUI ghostComponent, Material scribbleMaterial) { _textComponent = textComponent; _ghostTextComponent = ghostComponent; _scribbleMaterialTemplate = scribbleMaterial; _originalTextColor = _textComponent.color; if (_ghostTextComponent != null) _originalGhostColor = _ghostTextComponent.color; } private void CreateScribbleOverlay() { if (_overlayCreated || _scribbleMaterialTemplate == null || _textComponent == null) return; GameObject overlayObject = new GameObject("ScribbleOverlay"); overlayObject.transform.SetParent(_textComponent.transform, false); _scribbleOverlay = overlayObject.AddComponent(); _scribbleOverlay.raycastTarget = false; RectTransform overlayRect = overlayObject.GetComponent(); RectTransform textRect = _textComponent.GetComponent(); _textComponent.ForceMeshUpdate(); Vector2 textSize = _textComponent.GetRenderedValues(false); float horizontalPadding = 1.2f; float verticalPadding = 0.8f; Vector2 paddedSize = new Vector2( textSize.x + horizontalPadding, textSize.y + verticalPadding ); overlayRect.anchorMin = new Vector2(0.5f, 0.5f); overlayRect.anchorMax = new Vector2(0.5f, 0.5f); overlayRect.pivot = new Vector2(0.5f, 0.5f); float leftOffset = -horizontalPadding * 0.9f; overlayRect.anchoredPosition = new Vector2(leftOffset, 0f); overlayRect.sizeDelta = paddedSize; overlayRect.localScale = Vector3.one; _scribbleMaterialInstance = new Material(_scribbleMaterialTemplate); _scribbleMaterialInstance.SetFloat(ProgressID, 0f); _scribbleOverlay.material = _scribbleMaterialInstance; _scribbleOverlay.gameObject.SetActive(false); _overlayCreated = true; } public void PlaySketchFadeEffect(float scribbleDuration, float fadeDuration, float finalAlpha) { if (_isEffectActive || _textComponent == null) return; CancelActiveTweens(); CreateScribbleOverlay(); if (_scribbleOverlay == null || _scribbleMaterialInstance == null) return; _scribbleOverlay.gameObject.SetActive(true); _isEffectActive = true; _scribbleTweenId = LeanTween.value(gameObject, 0f, 1f, scribbleDuration) .setEase(LeanTweenType.easeInOutQuad) .setOnUpdate((float val) => { if (_scribbleMaterialInstance != null) _scribbleMaterialInstance.SetFloat(ProgressID, val); }) .setOnComplete(() => { _scribbleTweenId = -1; float ghostAlphaRatio = _ghostTextComponent != null ? (_originalGhostColor.a / _originalTextColor.a) : 0f; _fadeTweenId = LeanTween.value(gameObject, _originalTextColor.a, finalAlpha, fadeDuration) .setEase(LeanTweenType.easeInQuad) .setOnUpdate((float val) => { if (_textComponent != null) { _textComponent.color = _textComponent.color.WithAlpha(val); } if (_ghostTextComponent != null) { _ghostTextComponent.color = _ghostTextComponent.color.WithAlpha(val * ghostAlphaRatio); } if (_scribbleOverlay != null) { _scribbleOverlay.color = _scribbleOverlay.color.WithAlpha(val); } }) .setOnComplete(() => { _fadeTweenId = -1; _isEffectActive = false; }).id; }).id; } public void ResetEffect() { if (!_overlayCreated || _scribbleOverlay == null) { _isEffectActive = false; return; } bool overlayIsActive = _scribbleOverlay.gameObject.activeSelf; if (!overlayIsActive) { _isEffectActive = false; return; } CancelActiveTweens(); _isEffectActive = false; if (_scribbleMaterialInstance != null) { float currentProgress = _scribbleMaterialInstance.GetFloat(ProgressID); _scribbleTweenId = LeanTween.value(gameObject, currentProgress, 0f, 0.3f) .setEase(LeanTweenType.easeOutQuad) .setOnUpdate((float val) => { if (_scribbleMaterialInstance != null) _scribbleMaterialInstance.SetFloat(ProgressID, val); }) .setOnComplete(() => { _scribbleTweenId = -1; if (_scribbleOverlay != null) _scribbleOverlay.gameObject.SetActive(false); }).id; } if (_textComponent != null) { float currentAlpha = _textComponent.color.a; float ghostAlphaRatio = _ghostTextComponent != null ? (_originalGhostColor.a / _originalTextColor.a) : 0f; _fadeTweenId = LeanTween.value(gameObject, currentAlpha, _originalTextColor.a, 0.3f) .setEase(LeanTweenType.easeOutQuad) .setOnUpdate((float val) => { if (_textComponent != null) { _textComponent.color = _textComponent.color.WithAlpha(val); } if (_ghostTextComponent != null) { _ghostTextComponent.color = _ghostTextComponent.color.WithAlpha(val * ghostAlphaRatio); } if (_scribbleOverlay != null) { _scribbleOverlay.color = _scribbleOverlay.color.WithAlpha(val); } }) .setOnComplete(() => { _fadeTweenId = -1; }).id; } } private void CancelActiveTweens() { TweenHelper.CancelTween(ref _scribbleTweenId); TweenHelper.CancelTween(ref _fadeTweenId); } private void OnDestroy() { CancelActiveTweens(); if (_scribbleMaterialInstance != null) Destroy(_scribbleMaterialInstance); if (_scribbleOverlay != null) Destroy(_scribbleOverlay.gameObject); } } }