/// <summary>
        /// Creates a new beats key instance.
        /// </summary>
        private BeatsKey CreateKey()
        {
            var key = new BeatsKey();

            key.OnRelease += () => OnKeyStateRelease(key);
            return(key);
        }
 protected override void OnKeyStateRelease(BeatsKey key)
 {
     InvokeKeyRelease(key);
     JudgeKeyRelease(key);
     
     keyRecycler.Return(key);
 }
        /// <summary>
        /// Judges the specified key release against hit objects.
        /// </summary>
        private void JudgeKeyRelease(BeatsKey key)
        {
            if (key.DraggerView == null)
                return;

            key.DraggerView.StartCircle.SetHold(false, key.LastUpdateTime);
        }
        public void UpdateInputs(float curTime)
        {
            if (!GameSession.IsPaused)
            {
                // Process beats cursor aiming.
                if (hitBarCursor.IsActive)
                {
                    // Aiming on hit bar?
                    if (IsOnHitBar(hitBarCursor.Input, out float pos))
                    {
                        hitBarCursor.HitBarPos = pos;
                        hitBarCursor.IsOnHitBar.Value = true;
                    }
                    else
                    {
                        hitBarCursor.IsOnHitBar.Value = false;
                    }

                    // Check all key strokes whether the cursor is within the hit object boundary.
                    foreach (var key in keyRecycler.ActiveObjects)
                    {
                        key.LastUpdateTime = curTime;
                        if (key.IsActive && key.DraggerView != null)
                        {
                            var dragger = key.DraggerView;
                            bool isHolding = dragger.IsCursorInRange(pos);
                            dragger.StartCircle.SetHold(isHolding, curTime);
                        }
                    }
                }

                var cursors = InputManager.GetCursors();
                foreach (var cursor in cursors)
                {
                    if (cursor.State.Value == InputState.Press)
                    {
                        BeatsKey pressedKey = null;
                        // If hit on the hit bar, register this as a new BeatsCursor.
                        if (!hitBarCursor.IsActive && IsOnHitBar(cursor, out float pos))
                            pressedKey = TriggerCursorPress(curTime, cursor, pos);
                        // If not hit on hit bar, this is treated as a key stoke.
                        else
                            pressedKey = TriggerKeyPress(curTime, cursor, cursor);
                        JudgeKeyPress(curTime, pressedKey);
                    }

                    // Record replay input data
                    if (cursor.IsActive.Value)
                        gameProcessor.RecordInput(cursor);
                }
            }
        }
        /// <summary>
        /// Judges the specified key press against hit objects.
        /// </summary>
        private void JudgeKeyPress(float time, BeatsKey key)
        {
            // Return if no cursor is active.
            if(!hitBarCursor.IsActive)
                return;

            // Find the first hit object where the cursor is within the X range.
            foreach (var objView in hitObjectHolder.GetActiveObjects())
            {
                if (objView.IsCursorInRange(hitBarCursor.HitBarPos))
                {
                    // Associate the hit object view with the key stroke.
                    if(objView is DraggerView draggerView)
                        key.DraggerView = draggerView;
                    var judgement = objView.JudgeInput(time, key.Input);
                    if (judgement != null)
                    {
                        gameProcessor.RecordJudgement(objView, judgement, false, keyCode: key.Input.Key);
                        gameProcessor.AddJudgement(judgement);
                    }
                    break;
                }
            }
        }
 /// <summary>
 /// Invokes the OnKeyRelease event.
 /// </summary>
 protected void InvokeKeyRelease(BeatsKey key) => OnKeyRelease?.Invoke(key);
 /// <summary>
 /// Invokes the OnKeyPress event.
 /// </summary>
 protected void InvokeKeyPress(BeatsKey key) => OnKeyPress?.Invoke(key);
        /// <summary>
        /// Event called on key stroke release state.
        /// </summary>
        protected virtual void OnKeyStateRelease(BeatsKey key)
        {
            InvokeKeyRelease(key);

            keyRecycler.Return(key);
        }