using UnityEngine; using UnityEngine.UI; using TMPro; 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; _fadeTweenId = LeanTween.value(gameObject, _originalTextColor.a, finalAlpha, fadeDuration) .setEase(LeanTweenType.easeInQuad) .setOnUpdate((float val) => { if (_textComponent != null) { Color textColor = _textComponent.color; textColor.a = val; _textComponent.color = textColor; } if (_ghostTextComponent != null) { Color ghostColor = _ghostTextComponent.color; ghostColor.a = val * (_originalGhostColor.a / _originalTextColor.a); _ghostTextComponent.color = ghostColor; } if (_scribbleOverlay != null) { Color scribbleColor = _scribbleOverlay.color; scribbleColor.a = val; _scribbleOverlay.color = scribbleColor; } }) .setOnComplete(() => { _fadeTweenId = -1; }).id; }).id; } public void ResetEffect() { CancelActiveTweens(); if (_scribbleMaterialInstance != null) { float currentProgress = _scribbleMaterialInstance.GetFloat(ProgressID); if (currentProgress > 0f) { _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; if (currentAlpha < _originalTextColor.a) { _fadeTweenId = LeanTween.value(gameObject, currentAlpha, _originalTextColor.a, 0.3f) .setEase(LeanTweenType.easeOutQuad) .setOnUpdate((float val) => { if (_textComponent != null) { Color c = _textComponent.color; c.a = val; _textComponent.color = c; } if (_ghostTextComponent != null) { Color c = _ghostTextComponent.color; c.a = val * (_originalGhostColor.a / _originalTextColor.a); _ghostTextComponent.color = c; } }) .setOnComplete(() => { _fadeTweenId = -1; }).id; } } if (_scribbleOverlay != null) { Color c = _scribbleOverlay.color; c.a = 1f; _scribbleOverlay.color = c; } _isEffectActive = false; } private void CancelActiveTweens() { if (_scribbleTweenId != -1) { LeanTween.cancel(_scribbleTweenId); _scribbleTweenId = -1; } if (_fadeTweenId != -1) { LeanTween.cancel(_fadeTweenId); _fadeTweenId = -1; } } private void OnDestroy() { CancelActiveTweens(); if (_scribbleMaterialInstance != null) Destroy(_scribbleMaterialInstance); if (_scribbleOverlay != null) Destroy(_scribbleOverlay.gameObject); } } }