public void GeneratePath()
    {
        Paths.Add(new PathPoint
        {
            x    = gameObject.transform.position.x,
            y    = gameObject.transform.position.y,
            time = ApproachTime
        });
        while (NextID > 0)
        {
            Paths.Add(new PathPoint
            {
                x    = (float)(GlobalState.CurrentChart.note_list[NextID].x - 0.5) * GlobalState.PlayAreaWidth,
                y    = (float)(GlobalState.CurrentChart.note_list[NextID].y - 0.5) * GlobalState.PlayAreaHeight,
                time = (float)(GlobalState.CurrentChart.note_list[NextID].time - StartTime + ApproachTime),
                connector_start_time = (float)(GlobalState.CurrentChart.note_list[NextID].time - GlobalState.CurrentChart.note_list[NextID].approach_time - StartTime + ApproachTime)
            });

            float      x1 = Paths[Paths.Count - 2].x, x2 = Paths[Paths.Count - 1].x, y1 = Paths[Paths.Count - 2].y, y2 = Paths[Paths.Count - 1].y;
            GameObject obj = Instantiate(DragConnector);
            obj.SetActive(!GlobalState.IsGameRunning);
            obj.transform.position = new Vector3(x2, y2);
            obj.GetComponent <SpriteRenderer>().size = new Vector2(0.25f, GlobalState.GetDistance(x1, y1, x2, y2));
            obj.transform.rotation        = Quaternion.AngleAxis(-90 + (float)(Math.Atan2(y1 - y2, x1 - x2) * 180 / Math.PI), Vector3.forward);
            gameObject.transform.rotation = Quaternion.AngleAxis(-90 + (float)(Math.Atan2(y1 - y2, x1 - x2) * 180 / Math.PI), Vector3.forward);
            Connectors.Add(obj);
            NextID = GlobalState.CurrentChart.note_list[NextID].next_id;
        }
        if (Paths.Count > 1)
        {
            gameObject.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[0].y - Paths[1].y, Paths[0].x - Paths[1].x) * 180 / Math.PI), Vector3.forward);
        }
    }
    public void GeneratePath()
    {
        Paths.Add(new PathPoint
        {
            x    = gameObject.transform.position.x,
            y    = gameObject.transform.position.y,
            time = ApproachTime
        });
        while (NextID > 0)
        {
            Paths.Add(new PathPoint
            {
                x    = (float)(GlobalState.CurrentChart.note_list[NextID].x - 0.5) * GlobalState.PlayAreaWidth,
                y    = (float)(GlobalState.CurrentChart.note_list[NextID].y - 0.5) * GlobalState.PlayAreaHeight,
                time = (float)(GlobalState.CurrentChart.note_list[NextID].time - StartTime + ApproachTime),
                connector_start_time = (float)(GlobalState.CurrentChart.note_list[NextID].time - GlobalState.CurrentChart.note_list[NextID].approach_time - StartTime + ApproachTime),
            });

            NextID = GlobalState.CurrentChart.note_list[NextID].next_id;
        }
        if (Paths.Count > 1)
        {
            DragConnector.GetComponent <SpriteRenderer>().size = new Vector2(0.175f, GlobalState.GetDistance(Paths[1].x, Paths[1].y, Paths[0].x, Paths[0].y) / gameObject.transform.localScale.x);
            if (Notetype == (int)NoteType.CDRAG_HEAD)
            {
                gameObject.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[0].y - Paths[1].y, Paths[0].x - Paths[1].x) * 180 / Math.PI), Vector3.forward);
            }
            else
            {
                DragConnector.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[0].y - Paths[1].y, Paths[0].x - Paths[1].x) * 180 / Math.PI), Vector3.forward);
            }
            DragConnector.SetActive(true);
        }
        else
        {
            DragConnector.SetActive(false);
        }
    }
    private void UpdateComponentVisuals()
    {
        if (GlobalState.IsGameRunning)
        {
            float time = Delay + sw.ElapsedMilliseconds / 1000f;
            ApproachPercentage = time / ApproachTime;

            while (CurrentlyShownPath < Paths.Count && Paths[CurrentlyShownPath].connector_start_time <= time)
            {
                Connectors[CurrentlyShownPath - 1].SetActive(true);
                CurrentlyShownPath++;
            }

            if (ApproachPercentage > 1)
            {
                NoteFill.transform.localScale = NoteBorder.transform.localScale = new Vector3(0.8f, 0.8f);
                if (CurrentPath < Paths.Count)
                {
                    float pathcompletion = (Delay + sw.ElapsedMilliseconds / 1000f - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0)) / (Paths[CurrentPath].time - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0));
                    while (pathcompletion > 1) // for when the note is jumped to during path movement using the timeline
                    {
                        if (CurrentPath > 0 && CurrentPath < Paths.Count)
                        {
                            Destroy(Connectors[CurrentPath - 1]);
                        }
                        if (CurrentPath + 1 < Paths.Count)
                        {
                            gameObject.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[CurrentPath].y - Paths[CurrentPath + 1].y,
                                                                                                         Paths[CurrentPath].x - Paths[CurrentPath + 1].x) * 180 / Math.PI), Vector3.forward);
                        }
                        CurrentPath++;
                        pathcompletion -= 1;
                    }
                    if (CurrentPath < Paths.Count)
                    {
                        gameObject.transform.position = new Vector3(Paths[CurrentPath - 1].x + pathcompletion * (Paths[CurrentPath].x - Paths[CurrentPath - 1].x),
                                                                    Paths[CurrentPath - 1].y + pathcompletion * (Paths[CurrentPath].y - Paths[CurrentPath - 1].y));

                        if (CurrentPath + 1 < Paths.Count)
                        {
                            gameObject.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[CurrentPath].y - Paths[CurrentPath + 1].y,
                                                                                                         Paths[CurrentPath].x - Paths[CurrentPath + 1].x) * 180 / Math.PI), Vector3.forward);
                        }

                        if (CurrentPath > 0)
                        {
                            Connectors[CurrentPath - 1].GetComponent <SpriteRenderer>().size = new Vector2(0.25f, (1.0f - pathcompletion) *
                                                                                                           GlobalState.GetDistance(Paths[CurrentPath - 1].x, Paths[CurrentPath - 1].y, Paths[CurrentPath].x, Paths[CurrentPath].y));
                        }
                    }
                }

                if (CurrentPath >= Paths.Count) // no, this CANNOT be an else
                {
                    Destroy(gameObject);
                }
            }
            else
            {
                NoteFill.transform.localScale = NoteBorder.transform.localScale = new Vector3(0.4f + ApproachPercentage * 0.4f, 0.4f + ApproachPercentage * 0.4f);
            }
        }
        else
        {
            for (int i = 0; i < Connectors.Count; i++)
            {
                Connectors[i].SetActive(true);
            }
            NoteFill.transform.localScale = NoteBorder.transform.localScale = new Vector3(0.8f, 0.8f);
        }
    }
    protected override void UpdateVisuals()
    {
        float time = Delay + NoteStopwatch.ElapsedMilliseconds * PlaybackSpeed / 1000f;

        ApproachPercentage = time / ApproachTime;

        if (!DragConnector.activeSelf && NextID > 0)
        {
            DragConnector.SetActive(true);
        }

        if (ApproachPercentage > 1)
        {
            NoteFill.transform.localScale = NoteBorder.transform.localScale = new Vector3(0.8f, 0.8f);

            if (CurrentPath < Paths.Count)
            {
                float pathcompletion = (Delay + NoteStopwatch.ElapsedMilliseconds * PlaybackSpeed / 1000f - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0)) /
                                       (Paths[CurrentPath].time - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0));

                while (float.IsInfinity(pathcompletion))
                {
                    CurrentPath++;
                    if (CurrentPath < Paths.Count)
                    {
                        pathcompletion = (Delay + NoteStopwatch.ElapsedMilliseconds * PlaybackSpeed / 1000f - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0)) /
                                         (Paths[CurrentPath].time - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0));

                        gameObject.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[CurrentPath - 1].y - Paths[CurrentPath].y,
                                                                                                     Paths[CurrentPath - 1].x - Paths[CurrentPath].x) * 180 / Math.PI), Vector3.forward);
                    }
                    else
                    {
                        pathcompletion = 0;
                    }
                }

                while (pathcompletion > 1)
                {
                    if (CurrentPath > 0 && CurrentPath + 1 < Paths.Count && Notetype == (int)NoteType.CDRAG_HEAD)
                    {
                        gameObject.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[CurrentPath].y - Paths[CurrentPath + 1].y,
                                                                                                     Paths[CurrentPath].x - Paths[CurrentPath + 1].x) * 180 / Math.PI), Vector3.forward);
                    }

                    CurrentPath++;
                    if (CurrentPath < Paths.Count)
                    {
                        pathcompletion = (Delay + NoteStopwatch.ElapsedMilliseconds * PlaybackSpeed / 1000f - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0)) /
                                         (Paths[CurrentPath].time - (CurrentPath > 0 ? Paths[CurrentPath - 1].time : 0));
                    }
                    else
                    {
                        pathcompletion = 0;
                    }
                }

                if (CurrentPath < Paths.Count)
                {
                    gameObject.transform.position = new Vector3(Paths[CurrentPath - 1].x + pathcompletion * (Paths[CurrentPath].x - Paths[CurrentPath - 1].x),
                                                                Paths[CurrentPath - 1].y + pathcompletion * (Paths[CurrentPath].y - Paths[CurrentPath - 1].y));

                    if (CurrentPath > 0)
                    {
                        DragConnector.GetComponent <SpriteRenderer>().size = new Vector2(0.175f, (1.0f - pathcompletion) *
                                                                                         GlobalState.GetDistance(Paths[CurrentPath - 1].x, Paths[CurrentPath - 1].y, Paths[CurrentPath].x, Paths[CurrentPath].y) / gameObject.transform.localScale.x);

                        DragConnector.transform.rotation = Quaternion.AngleAxis(90 + (float)(Math.Atan2(Paths[CurrentPath - 1].y - Paths[CurrentPath].y, Paths[CurrentPath - 1].x - Paths[CurrentPath].x) * 180 / Math.PI), Vector3.forward);
                    }
                }
            }

            if (CurrentPath >= Paths.Count)
            {
                ParentPool.ReturnToPool(gameObject, Notetype);
            }
        }
        else
        {
            NoteFill.transform.localScale = NoteBorder.transform.localScale = new Vector3(0.4f + ApproachPercentage * 0.4f, 0.4f + ApproachPercentage * 0.4f);
        }
    }