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 = TweenHelper.AnimateMaterialFloat( gameObject, _scribbleMaterialInstance, ProgressID, 0f, 1f, scribbleDuration, () => { _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; }).id; }, LeanTweenType.easeInOutQuad); } public void ResetEffect() { CancelActiveTweens(); if (_scribbleMaterialInstance != null) { float currentProgress = _scribbleMaterialInstance.GetFloat(ProgressID); if (currentProgress > 0f) { _scribbleTweenId = TweenHelper.AnimateMaterialFloat( gameObject, _scribbleMaterialInstance, ProgressID, currentProgress, 0f, 0.3f, () => { _scribbleTweenId = -1; if (_scribbleOverlay != null) _scribbleOverlay.gameObject.SetActive(false); }, LeanTweenType.easeOutQuad); } } if (_textComponent != null) { float currentAlpha = _textComponent.color.a; if (currentAlpha < _originalTextColor.a) { float ghostAlphaRatio = _ghostTextComponent != null ? (_originalGhostColor.a / _originalTextColor.a) : 0f; _fadeTweenId = TweenHelper.FadeText( gameObject, _textComponent, _ghostTextComponent, _originalTextColor.a, 0.3f, ghostAlphaRatio, () => { _fadeTweenId = -1; }, LeanTweenType.easeOutQuad); } } if (_scribbleOverlay != null) { _scribbleOverlay.color = _scribbleOverlay.color.WithAlpha(1f); } _isEffectActive = false; } 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); } } }