using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using TMPro; using DG.Tweening; using HeavenStudio.Util; using HeavenStudio.Editor.Track; using System.Text; using System.Configuration; using System; using HeavenStudio.InputSystem; using UnityEngine.U2D; namespace HeavenStudio.Editor { // I LOVE the antichrist! public class GridGameSelector : MonoBehaviour { public Minigames.Minigame SelectedMinigame; [Header("Components")] public GameObject SelectedGameIcon; public GameObject GameEventSelector; public GameObject EventRef; public GameObject CurrentSelected; public Scrollbar Scrollbar; public RectTransform GameSelectionRect; public RectTransform GameEventSelectorCanScroll; public TMP_InputField SearchBar; private RectTransform GameEventSelectorRect; private RectTransform eventsParent; [Header("Properties")] [SerializeField] private int currentEventIndex; public Texture Square; public Texture Circle; public List mgsActive = new(); public List fxActive = new(); public float posDif; public int ignoreSelectCount; private int dragTimes; private bool gameOpen; private float selectorHeight; private float eventSize; private float timeSinceUpdateIndex = 0.0f; public static GridGameSelector instance; private void Awake() { instance = this; } private void Start() { GameEventSelectorRect = GameEventSelector.GetComponent(); selectorHeight = GameEventSelectorRect.rect.height; eventSize = EventRef.GetComponent().rect.height; eventsParent = EventRef.transform.parent.GetChild(2).GetComponent(); SelectGame(fxActive[0].name); } private void Update() { if (!EventParameterManager.instance.active && !IsPointerOverUIElement()) { if (gameOpen) { if (Input.GetKeyDown(KeyCode.DownArrow)) { UpdateIndex(currentEventIndex + 1); } else if (Input.GetKeyDown(KeyCode.UpArrow)) { UpdateIndex(currentEventIndex - 1); } } if (RectTransformUtility.RectangleContainsScreenPoint(GameEventSelectorCanScroll, Input.mousePosition, Editor.instance.EditorCamera) && Input.mouseScrollDelta.y != 0) { UpdateIndex(currentEventIndex - Mathf.RoundToInt(Input.mouseScrollDelta.y)); } } //moved here so this updates dynamically with window scale UpdateScrollPosition(); } #region Functions public void UpdateIndex(int amount, bool updateCol = true) { currentEventIndex = amount; CurrentSelected.transform.DOKill(); if (currentEventIndex < 0) currentEventIndex = eventsParent.childCount - 1; else if (currentEventIndex > eventsParent.childCount - 1) currentEventIndex = 0; CurrentSelected.transform.DOLocalMoveY(eventsParent.transform.GetChild(currentEventIndex).localPosition.y + eventsParent.transform.localPosition.y, 0.35f).SetEase(Ease.OutExpo); timeSinceUpdateIndex = 0; } private void UpdateScrollPosition() { selectorHeight = GameEventSelectorRect.rect.height; //eventSize = EventRef.GetComponent().rect.height; Vector3 lastPos = EventRef.transform.parent.transform.localPosition; float end = 0; if ((currentEventIndex * eventSize >= selectorHeight/2) && (eventsParent.childCount * eventSize >= selectorHeight)) { if (currentEventIndex * eventSize < eventsParent.childCount * eventSize - selectorHeight/2) end = (currentEventIndex * eventSize) - selectorHeight/2; else end = (eventsParent.childCount * eventSize) - selectorHeight + (eventSize * 0.33f); } EventRef.transform.parent.transform.localPosition = new Vector3( lastPos.x, Mathf.Lerp(lastPos.y, end, 12 * Time.deltaTime), lastPos.z ); timeSinceUpdateIndex += Time.deltaTime; CurrentSelected.GetComponent().anchoredPosition = new Vector2( (Mathf.Cos(timeSinceUpdateIndex * 2.65f) * 12) + 12, CurrentSelected.GetComponent().anchoredPosition.y); SetColors(); } // will automatically select game + game icon, and (eventually?) scroll to the game if it's offscreen // index is the event it will highlight (which was basically just added for pick block) // TODO: automatically scroll if the game is offscreen, because i can't figure out a good way to do it rn. -AJ public void SelectGame(string gameName, int index = 0) { if (SelectedGameIcon != null) { SelectedGameIcon.GetComponent().UnClickIcon(); } SelectedMinigame = EventCaller.instance.GetMinigame(gameName); if (SelectedMinigame == null) { SelectGame("gameManager"); Debug.LogWarning($"SelectGame() has failed, did you mean to input '{gameName}'?"); return; } EventParameterManager.instance.Disable(); gameOpen = true; DestroyEvents(); AddEvents(index); SelectedGameIcon = transform.Find(gameName).gameObject; SelectedGameIcon.GetComponent().ClickIcon(); currentEventIndex = index; UpdateIndex(index, false); // Editor.instance?.SetGameEventTitle($"Select game event for {SelectedMinigame.displayName.Replace("\n", "")}"); if (Editor.instance != null) Editor.instance.SetGameEventTitle(SelectedMinigame.displayName.Replace("\n", "")); } private void AddEvents(int index = 0) { if (!EventCaller.FXOnlyGames().Contains(SelectedMinigame)) { GameObject sg = Instantiate(EventRef, eventsParent); sg.GetComponentInChildren().text = "Switch Game"; sg.SetActive(true); if (index == 0) { sg.GetComponentInChildren().color = EditorTheme.theme.properties.EventSelectedCol.Hex2RGB(); } } else { index++; if (SelectedMinigame.name == "gameManager") index++; } for (var i = 0; i < SelectedMinigame.actions.Count; i++) { var action = SelectedMinigame.actions[i]; if (action.actionName == "switchGame" || action.hidden) continue; var g = Instantiate(EventRef, eventsParent); var label = g.GetComponentInChildren(); label.text = action.displayName; if (action.parameters != null && action.parameters.Count > 0) g.transform.GetChild(0).GetChild(0).gameObject.SetActive(true); if (index - 1 == i) label.color = EditorTheme.theme.properties.EventSelectedCol.Hex2RGB(); g.SetActive(true); } } private void DestroyEvents() { for (int i = 0; i < transform.childCount; i++) { transform.GetChild(i).GetChild(0).gameObject.SetActive(false); } for (int i = 0; i < eventsParent.childCount; i++) { Destroy(eventsParent.GetChild(i).gameObject); } } private void SetColors() { //CurrentSelected.GetComponent().color = EditorTheme.theme.properties.EventSelectedCol.Hex2RGB(); for (int i = 0; i < eventsParent.transform.childCount; i++) { var eventTxt = eventsParent.GetChild(i).GetChild(0).GetComponent(); var goalX = -25; if (i == currentEventIndex) { eventTxt.color = EditorTheme.theme.properties.EventSelectedCol.Hex2RGB(); goalX = 16; } else { eventTxt.color = EditorTheme.theme.properties.EventNormalCol.Hex2RGB(); } eventTxt.rectTransform.anchoredPosition = new Vector2( Mathf.Lerp(eventTxt.rectTransform.anchoredPosition.x, goalX, Time.deltaTime * 12f), eventTxt.rectTransform.anchoredPosition.y); } } public void Zoom() { if (!Input.GetKey(InputKeyboard.MODIFIER)) return; var glg = GetComponent(); int max = 20; // arbitrary if (glg.constraintCount + 1 > max && Input.mouseScrollDelta.y < 0) return; glg.constraintCount += (Input.mouseScrollDelta.y > 0) ? -1 : 1; // thanks to blank3times (tri) for helping me with this var size = (1 / (0.00317 * glg.constraintCount)) - 4.75248; // this, however, doesn't work // var totalWidth = Editor.instance.GridGameSelectorRect.rect.width; // var size = (totalWidth - glg.padding.right) * (glg.constraintCount + 1) / glg.constraintCount; glg.cellSize = Vector2.one * (float)size; } // method called when clicking the sort button in the editor, skips sorting fx only "games" // sorts depending on which sorting button you click public void Sort(string type) { List mgsSort = mgsActive; mgsSort.Sort((x, y) => string.Compare(x.name, y.name)); Action> action = type switch { "favorites" => SortFavorites, "chronologic" => SortChronologic, "usage" => SortUsage, _ => SortAlphabet }; action.Invoke(mgsSort); } void SortAlphabet(List mgs) { List alph = mgs.OrderBy(AlphabetSortKey).ToList(); for (int i = 0; i < alph.Count; i++) { alph[i].SetSiblingIndex(i + fxActive.Count + 1); } } string AlphabetSortKey(RectTransform minigame) { Minigames.Minigame mg = EventCaller.instance.GetMinigame(minigame.name); if (mg.displayName.StartsWith("the ", StringComparison.InvariantCultureIgnoreCase)) return mg.displayName[4..]; else return mg.displayName; } // if there are no favorites, the games will sort alphabetically void SortFavorites(List allMgs) { List favs = allMgs.FindAll(mg => mg.GetComponent().StarActive).OrderBy(AlphabetSortKey).ToList(); List mgs = allMgs.FindAll(mg => !mg.GetComponent().StarActive).OrderBy(AlphabetSortKey).ToList(); if (Input.GetKey(KeyCode.LeftShift)) { foreach (var fav in favs) fav.GetComponent().Star(); return; } for (int i = 0; i < favs.Count; i++) { favs[i].SetSiblingIndex(i + fxActive.Count + 1); } for (int i = 0; i < mgs.Count; i++) { mgs[i].SetSiblingIndex(i + fxActive.Count + favs.Count + 1); } } void SortChronologic(List mgs) { List chrono = mgs.OrderBy(GameOriginSortKey).ThenBy(ChronologicSortKey).ThenBy(AlphabetSortKey).ToList(); for (int i = 0; i < chrono.Count; i++) { chrono[i].SetSiblingIndex(i + fxActive.Count + 1); } } int GameOriginSortKey(RectTransform minigame) { Minigames.Minigame mg = EventCaller.instance.GetMinigame(minigame.name); if (mg.tags.Count > 0) { return mg.tags[0] switch { "agb" => 0, "ntr" => 1, "rvl" => 2, "ctr" => 3, _ => 10, }; } return 10; } uint ChronologicSortKey(RectTransform minigame) { Minigames.Minigame mg = EventCaller.instance.GetMinigame(minigame.name); if (mg.chronologicalSortKey is uint i) return i; return uint.MaxValue; } void SortUsage(List mgs) { List usage = mgs.OrderByDescending(UsageSortKey).ThenBy(AlphabetSortKey).ToList(); for (int i = 0; i < usage.Count; i++) { usage[i].SetSiblingIndex(i + fxActive.Count + 1); } } int UsageSortKey(RectTransform minigame) { return EventCaller.GetAllInGameManagerList(minigame.name).Count; } public void Search() { for (int i = 0; i < mgsActive.Count; i++) { mgsActive[i].gameObject.SetActive( System.Text.RegularExpressions.Regex.IsMatch( EventCaller.instance.GetMinigame(mgsActive[i].name).displayName, SearchBar.text, System.Text.RegularExpressions.RegexOptions.IgnoreCase ) ); } } public bool IsPointerOverUIElement() { return IsPointerOverUIElement(GetEventSystemRaycastResults()); } private bool IsPointerOverUIElement(List eventSystemRaysastResults) { for (int index = 0; index < eventSystemRaysastResults.Count; index++) { RaycastResult curRaysastResult = eventSystemRaysastResults[index]; if (curRaysastResult.gameObject.layer == 5) return true; } return false; } static List GetEventSystemRaycastResults() { PointerEventData eventData = new PointerEventData(EventSystem.current); eventData.position = Input.mousePosition; List raysastResults = new List(); EventSystem.current.RaycastAll(eventData, raysastResults); return raysastResults; } #endregion #region Events public void Drag() { if (Conductor.instance.NotStopped() || Editor.instance.inAuthorativeMenu) { if (Conductor.instance.isPaused) { Debug.Log("it's fuckin paused dude"); } return; } if (Timeline.instance.MouseInTimeline && dragTimes < 1) { Timeline.instance.timelineState.SetState(Timeline.CurrentTimelineState.State.Selection); dragTimes++; TimelineEventObj eventObj; if (currentEventIndex == 0) { if (EventCaller.FXOnlyGames().Contains(SelectedMinigame)) { int index = currentEventIndex + 1; if (currentEventIndex - 1 > SelectedMinigame.actions.Count) { index = currentEventIndex; } else if (currentEventIndex - 1 < 0) { if (SelectedMinigame.actions[0].actionName == "switchGame") index = 1; else index = 0; } eventObj = Timeline.instance.AddEventObject(SelectedMinigame.name + "/" + SelectedMinigame.actions[index].actionName, true, new Vector3(0, 0), null, true); } else eventObj = Timeline.instance.AddEventObject($"gameManager/switchGame/{SelectedMinigame.name}", true, new Vector3(0, 0), null, true); } else { int index = currentEventIndex - 1; if (SelectedMinigame.actions[0].actionName == "switchGame") { index = currentEventIndex + 1; } else if (EventCaller.FXOnlyGames().Contains(SelectedMinigame) && SelectedMinigame.actions[0].actionName != "switchGame") { index = currentEventIndex; } eventObj = Timeline.instance.AddEventObject(SelectedMinigame.name + "/" + SelectedMinigame.actions[index].actionName, true, new Vector3(0, 0), null, true); } eventObj.isCreating = true; // CommandManager.instance.Execute(new Commands.Place(eventObj)); } } public void Drop() { if (Conductor.instance.NotStopped()) return; dragTimes = 0; } #endregion } }