#nullable enable using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Events; [RequireComponent(typeof(Collider2D), typeof(Animator))] public class Clickable : MonoBehaviour { [SerializeField] private string goToSubSceneName; [SerializeField] private bool isDiscoverable = true; [SerializeField] private int? discoveredSortingOrder; private Animator animator; [SerializeField] public bool discovered = false; public VideoAsset firstVideoAsset; public VideoAsset secondVideoAsset; public List listRandomVideoAssets; [SerializeField] private bool playRandomClipAfterFirst = false; private List shuffledVideoAssets; [SerializeField] private GameObject discoverParticlePrefab; [SerializeField] private string discoverText; [SerializeField] private FloatingLabelDirection discoverTextDirection = FloatingLabelDirection.Up; [SerializeField] private float discoverTextOffset = 1; [SerializeField] private float discoverXTextOffset = 0; private bool firstVideoPlayed = false; delegate void onVideoEnd(); public UnityEvent OnClick; [SerializeField] SchoolManager associatedStory; private int playedVideoCount = 0; private bool isTransitioning = false; [SerializeField] private bool active = true; private List AllVideoAssets => new List { firstVideoAsset, secondVideoAsset }.Concat(listRandomVideoAssets).ToList().FindAll(video => video != null); private bool HasPlayedAllVideos() { List AllVideoAssets = new List { firstVideoAsset, secondVideoAsset }.Concat(listRandomVideoAssets).ToList().FindAll(video => video != null); return AllVideoAssets.TrueForAll(video => video.PlayCount > 0); } public SubScene? AssociatedSubScene = null; [SerializeField] private bool mute = false; private SpriteRenderer spriteRenderer; private int zindex = 0; void Start() { animator = GetComponent(); shuffledVideoAssets = new List(listRandomVideoAssets); shuffledVideoAssets.Shuffle(); animator.Play("Idle", 0, UnityEngine.Random.Range(0.3f, 1f)); if (GameManager.singleton.AllUnlocked) { discovered = true; } spriteRenderer = GetComponent(); zindex = spriteRenderer.sortingOrder; } private FloatingLabel? floatingLabel; public void Print() { Debug.Log("Clickable<" + gameObject.name + "> initialized with " + AllVideoAssets.Count + " video assets"); for (int i = 0; i < AllVideoAssets.Count; i++) { Debug.Log("VideoAsset " + i + ": " + AllVideoAssets[i].name + " played " + AllVideoAssets[i].PlayCount + " times"); } } // Hover void OnMouseEnter() { if (!GameManager.singleton.CanPlay || isTransitioning) return; if (active) { animator.SetBool("hover", true); CameraManager.singleton.ShowHoverTexture(); if (!mute) GameManager.singleton.soundManager.PlayHoverSound(); } if (discoverText != null && discoverText != "") { if (floatingLabel != null) Destroy(floatingLabel.gameObject); floatingLabel = Instantiate(GameManager.singleton.floatingLabelPrefab, transform.position + new Vector3(discoverXTextOffset, 0, 0), Quaternion.identity).GetComponent(); floatingLabel.Spawn(discoverText, discoverTextDirection, discoverTextOffset); } } void OnMouseExit() { if (!GameManager.singleton.CanPlay || isTransitioning) return; if (active) { animator.SetBool("hover", false); CameraManager.singleton.ShowDefaultTexture(); if (!mute) GameManager.singleton.soundManager.StopSound(); } if (floatingLabel != null) { floatingLabel.Despawn(); } } void Discover() { GameManager.singleton.soundManager.PlayDiscoverSound(); discovered = true; animator.SetTrigger("Discover"); if (discoveredSortingOrder != null) { GetComponent().sortingOrder = discoveredSortingOrder ?? 0; } if (discoverParticlePrefab != null) { Instantiate(discoverParticlePrefab, transform.position, Quaternion.identity); } } public event Action OnClicked; public event Action OnVideoPlayed; public UnityEvent OnVideoPlayedEvent; private bool NeedDeactivating => active && AssociatedSubScene == null && HasPlayedAllVideos(); public void OnMouseDown() { if (!GameManager.singleton.CanPlay || isTransitioning) return; string clickResult = ProcessClick(); OnClicked?.Invoke(this); if (NeedDeactivating) { active = false; animator.speed = 0; } else if (new List { "firstVideoPlayed", "secondVideoPlayed", "randomVideoPlayed" }.Contains(clickResult)) { GameManager.singleton.soundManager.PlayClickSound(); } } public void OnVideoEnd() { if (NeedDeactivating) { active = false; animator.speed = 0; } if (floatingLabel != null) Destroy(floatingLabel.gameObject); OnVideoPlayed?.Invoke(this); OnVideoPlayedEvent?.Invoke(); } public string ProcessClick() { OnClick?.Invoke(); if (isDiscoverable && !discovered) { Discover(); GameManager.singleton.soundManager.StopHoverSound(); GameManager.singleton.soundManager.PlayDiscoverSound(); return "discovered"; } if (goToSubSceneName != null && goToSubSceneName != "") { CameraManager.singleton.MoveToSubScene(goToSubSceneName, () => { PlayVideo(); }); return "moveToSubscene"; } return PlayVideo(); } public string PlayVideo() { if (firstVideoAsset != null || secondVideoAsset != null || listRandomVideoAssets.Count > 0) { if (firstVideoAsset != null && !firstVideoPlayed) { firstVideoPlayed = true; CameraManager.singleton.PlayVideo(firstVideoAsset, () => { OnVideoEnd(); if (playRandomClipAfterFirst) { CameraManager.singleton.PlayVideo(shuffledVideoAssets[playedVideoCount % shuffledVideoAssets.Count], OnVideoEnd); playedVideoCount++; } }); return "firstVideoPlayed"; } else if (secondVideoAsset != null) { CameraManager.singleton.PlayVideo(secondVideoAsset, OnVideoEnd); return "secondVideoPlayed"; } else if (listRandomVideoAssets.Count > 0) { CameraManager.singleton.PlayVideo(shuffledVideoAssets[playedVideoCount % shuffledVideoAssets.Count], OnVideoEnd); playedVideoCount++; return "randomVideoPlayed"; } } return "noVideoToPlay"; } public void Enter() { GameManager.singleton.soundManager.StopSound(); isTransitioning = true; GameManager.singleton.soundManager.PlayEnterSound(); animator.SetTrigger("Enter"); spriteRenderer.sortingOrder = 100; if (associatedStory != null) associatedStory.TriggerStartAnimation(); } public void EndEnterOrExit() { isTransitioning = false; animator.SetBool("hover", false); } public void Exit() { isTransitioning = true; GameManager.singleton.soundManager.PlayExitSound(); animator.SetTrigger("Exit"); spriteRenderer.sortingOrder = zindex; } }