using System; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.UI; namespace HeavenStudio.Common { public class OverlaysManager : MonoBehaviour { public static OverlaysManager instance { get; private set; } public static bool OverlaysEnabled; const float WIDTH_SPAN = 10f; const float HEIGHT_SPAN = 10f * (9f / 16f); [Header("Prefabs")] [SerializeField] GameObject TimingDisplayPrefab; [SerializeField] GameObject SkillStarPrefab; [SerializeField] GameObject ChartSectionPrefab; [SerializeField] SectionMedalsManager SectionMedalsManager; [Header("Components")] [SerializeField] Transform ComponentHolder; List lytElements = new List(); public static bool OverlaysReady { get { return instance != null && TimingAccuracyDisplay.instance != null && SkillStarManager.instance != null && SectionMedalsManager.instance != null && HeavenStudio.Games.Global.Textbox.instance != null; } } // Start is called before the first frame update public void Start() { RefreshOverlaysLayout(); instance = this; } // Update is called once per frame void Update() { } public void TogleOverlaysVisibility(bool visible) { OverlaysEnabled = visible; RepositionElements(); } public void RefreshOverlaysLayout() { if (PersistentDataManager.gameSettings.timingDisplayComponents == null || PersistentDataManager.gameSettings.timingDisplayComponents.Count == 0) { PersistentDataManager.gameSettings.timingDisplayComponents = new List() { TimingDisplayComponent.CreateDefaultDual() }; } if (PersistentDataManager.gameSettings.skillStarComponents == null || PersistentDataManager.gameSettings.skillStarComponents.Count == 0) { PersistentDataManager.gameSettings.skillStarComponents = new List() { SkillStarComponent.CreateDefault() }; } if (PersistentDataManager.gameSettings.sectionComponents == null || PersistentDataManager.gameSettings.sectionComponents.Count == 0) { PersistentDataManager.gameSettings.sectionComponents = new List() { SectionComponent.CreateDefault() }; } lytElements = new List(); foreach (var c in PersistentDataManager.gameSettings.timingDisplayComponents) { lytElements.Add(c); } foreach (var c in PersistentDataManager.gameSettings.skillStarComponents) { lytElements.Add(c); } foreach (var c in PersistentDataManager.gameSettings.sectionComponents) { lytElements.Add(c); } foreach (Transform child in ComponentHolder.transform) { Destroy(child.gameObject); } foreach (var c in lytElements) { if (c is TimingDisplayComponent) { c.CreateElement(TimingDisplayPrefab, ComponentHolder); Debug.Log("Create TimingDisplayComponent"); } else if (c is SkillStarComponent) { c.CreateElement(SkillStarPrefab, ComponentHolder); Debug.Log("Create SkillStarComponent"); } else if (c is SectionComponent) { c.CreateElement(ChartSectionPrefab, ComponentHolder); Debug.Log("Create SectionComponent"); } c.PositionElement(); } } void RepositionElements() { lytElements = new List(); foreach (var c in PersistentDataManager.gameSettings.timingDisplayComponents) { lytElements.Add(c); } foreach (var c in PersistentDataManager.gameSettings.skillStarComponents) { lytElements.Add(c); } foreach (var c in PersistentDataManager.gameSettings.sectionComponents) { lytElements.Add(c); } foreach (var c in lytElements) { c.PositionElement(); } } [Serializable] public class TimingDisplayComponent : OverlayOption { public enum TimingDisplayType { Dual, Single, } [NonSerialized] GameObject go2; [SerializeField] public TimingDisplayType tdType; public TimingDisplayComponent(TimingDisplayType type, bool enable, Vector2 position, float scale, float rotation) { tdType = type; this.enable = enable; this.position = position; this.scale = scale; this.rotation = rotation; } public override void CreateElement(GameObject prefab, Transform holder) { if (go == null) go = Instantiate(prefab, holder); if (go2 == null) go2 = Instantiate(prefab, holder); } public override void PositionElement() { if (go != null) { switch (tdType) { case TimingDisplayType.Dual: go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN) * new Vector2(-1, 1); go.transform.localScale = Vector3.one * scale; go.transform.localRotation = Quaternion.Euler(0, 0, -rotation); go2.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN); go2.transform.localScale = Vector3.one * scale; go2.transform.localRotation = Quaternion.Euler(0, 0, rotation); go.SetActive(enable && OverlaysManager.OverlaysEnabled); go2.SetActive(enable && OverlaysManager.OverlaysEnabled); break; case TimingDisplayType.Single: go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN); go.transform.localScale = Vector3.one * scale; go.transform.localRotation = Quaternion.Euler(0, 0, rotation); go.SetActive(enable && OverlaysManager.OverlaysEnabled); go2.SetActive(false); break; } } } public override void EnablePreview() { } public override void DisablePreview() { } public static TimingDisplayComponent CreateDefaultDual() { return new TimingDisplayComponent(TimingDisplayType.Dual, true, new Vector2(-0.84f, 0), 1f, 0f); } public static TimingDisplayComponent CreateDefaultSingle() { return new TimingDisplayComponent(TimingDisplayType.Single, true, new Vector2(0, -0.8f), 1f, 90f); } } [Serializable] public class SkillStarComponent : OverlayOption { public SkillStarComponent(bool enable, Vector2 position, float scale, float rotation) { this.enable = enable; this.position = position; this.scale = scale; this.rotation = rotation; } public override void PositionElement() { if (go != null) { go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN); go.transform.localScale = Vector3.one * scale; go.transform.localRotation = Quaternion.Euler(0, 0, rotation); go.SetActive(enable && OverlaysManager.OverlaysEnabled); } } public override void EnablePreview() { SkillStarManager.instance?.DoStarPreview(); } public override void DisablePreview() { SkillStarManager.instance.ResetStarPreview(); } public static SkillStarComponent CreateDefault() { return new SkillStarComponent(true, new Vector2(0.75f, -0.7f), 1f, 0f); } } [Serializable] public class SectionComponent : OverlayOption { public SectionComponent(bool enable, Vector2 position, float scale, float rotation) { this.enable = enable; this.position = position; this.scale = scale; this.rotation = rotation; } public override void PositionElement() { if (go != null) { go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN); go.transform.localScale = Vector3.one * scale; go.transform.localRotation = Quaternion.Euler(0, 0, rotation); go.SetActive(enable && OverlaysManager.OverlaysEnabled); HeavenStudio.Common.SectionMedalsManager.instance?.AnchorToOverlay(go); } } public override void EnablePreview() { if (go != null) { go.GetComponent().enabled = true; } } public override void DisablePreview() { if (go != null) { go.GetComponent().enabled = false; } } public static SectionComponent CreateDefault() { return new SectionComponent(true, new Vector2(-0.7f, 0.765f), 1f, 0f); } } [Serializable] public class DurationComponent : OverlayOption { public override void DisablePreview() { throw new NotImplementedException(); } public override void EnablePreview() { throw new NotImplementedException(); } public override void PositionElement() { throw new NotImplementedException(); } } [Serializable] public class WordJudgementComponent : OverlayOption { public override void DisablePreview() { throw new NotImplementedException(); } public override void EnablePreview() { throw new NotImplementedException(); } public override void PositionElement() { throw new NotImplementedException(); } } [Serializable] public abstract class OverlayOption { static long uuidCounter = 0; [NonSerialized] protected GameObject go; [NonSerialized] public long uuid = GenerateUUID(); [SerializeField] public bool enable; [SerializeField] public Vector2 position; [SerializeField] public float scale; [SerializeField] public float rotation; static long GenerateUUID() { return uuidCounter++; } public virtual void CreateElement(GameObject prefab, Transform holder) { if (go == null) go = Instantiate(prefab, holder); } public abstract void PositionElement(); public abstract void EnablePreview(); public abstract void DisablePreview(); } } }