void UpdateNoteStringsInfo()
    {
        bool hasCurrentNote   = currentNote != null;
        bool hasPreviousNote  = prevClonedNote != null;
        bool valuesAreTheSame = hasCurrentNote && hasPreviousNote && prevClonedNote.AllValuesCompare(currentNote);

        if (currentNote != null && (prevClonedNote != currentNote || !valuesAreTheSame))
        {
            string noteTypeString = string.Empty;
            if (Globals.drumMode)
            {
                noteTypeString = currentNote.GetDrumString(editor.laneInfo);
            }
            else if (Globals.ghLiveMode)
            {
                noteTypeString = currentNote.ghliveGuitarFret.ToString();
            }
            else
            {
                noteTypeString = currentNote.guitarFret.ToString();
            }

            fretText.text     = "Fret: " + noteTypeString;
            positionText.text = "Position: " + currentNote.tick.ToString();
            sustainText.text  = "Length: " + currentNote.length.ToString();

            prevClonedNote.CopyFrom(currentNote);
        }
    }
    void UpdateNoteStringsInfo()
    {
        bool hasCurrentNote   = currentNote != null;
        bool hasPreviousNote  = prevClonedNote != null;
        bool valuesAreTheSame = hasCurrentNote && hasPreviousNote && prevClonedNote.AllValuesCompare(currentNote);

        if (IsInNoteTool() && Globals.gameSettings.keysModeEnabled)
        {
            // Don't update the string unless the position has actually changed. Results in per-frame garbage otherwise
            if (lastKnownKeysModePos != editor.currentTickPos)
            {
                positionText.text    = "Position: " + editor.currentTickPos;
                lastKnownKeysModePos = editor.currentTickPos;
            }

            fretText.text    = "Fret: N/A";
            sustainText.text = "Length: N/A";
        }
        else if (currentNote != null && (prevClonedNote != currentNote || !valuesAreTheSame))
        {
            string noteTypeString = string.Empty;
            if (Globals.drumMode)
            {
                noteTypeString = currentNote.GetDrumString(editor.laneInfo);
            }
            else if (Globals.ghLiveMode)
            {
                noteTypeString = currentNote.ghliveGuitarFret.ToString();
            }
            else
            {
                noteTypeString = currentNote.guitarFret.ToString();
            }

            fretText.text     = "Fret: " + noteTypeString;
            positionText.text = "Position: " + currentNote.tick.ToString();
            sustainText.text  = "Length: " + currentNote.length.ToString();

            prevClonedNote.CopyFrom(currentNote);
            lastKnownKeysModePos = uint.MaxValue;
        }
    }
    public static ActionHistory.Action[] AddObjectToCurrentChart(Note note, ChartEditor editor, out Note addedNote, bool update = true, bool copy = true)
    {
        List <ActionHistory.Action> noteRecord = new List <ActionHistory.Action>();

        int index, length;

        SongObjectHelper.GetRange(editor.currentChart.notes, note.tick, note.tick, out index, out length);

        // Account for when adding an exact note as what's already in
        if (length > 0)
        {
            bool cancelAdd = false;
            for (int i = index; i < index + length; ++i)
            {
                Note overwriteNote = editor.currentChart.notes[i];

                if (note.AllValuesCompare(overwriteNote))
                {
                    cancelAdd = true;
                    break;
                }
                if ((((note.IsOpenNote() || overwriteNote.IsOpenNote()) && !Globals.drumMode) || note.guitarFret == overwriteNote.guitarFret) && !note.AllValuesCompare(overwriteNote))
                {
                    noteRecord.Add(new ActionHistory.Delete(overwriteNote));
                }
            }
            if (!cancelAdd)
            {
                noteRecord.Add(new ActionHistory.Add(note));
            }
        }
        else
        {
            noteRecord.Add(new ActionHistory.Add(note));
        }

        Note noteToAdd;

        if (copy)
        {
            noteToAdd = new Note(note);
        }
        else
        {
            noteToAdd = note;
        }

        if (noteToAdd.IsOpenNote())
        {
            noteToAdd.flags &= ~Note.Flags.Tap;
        }

        editor.currentChart.Add(noteToAdd, update);
        if (noteToAdd.cannotBeForced)
        {
            noteToAdd.flags &= ~Note.Flags.Forced;
        }

        noteToAdd.ApplyFlagsToChord();

        //NoteController nCon = editor.CreateNoteObject(noteToAdd);
        standardOverwriteOpen(noteToAdd);

        noteRecord.InsertRange(0, CapNoteCheck(noteToAdd));
        noteRecord.InsertRange(0, ForwardCap(noteToAdd));     // Do this due to pasting from the clipboard

        // Check if the automatic un-force will kick in
        ActionHistory.Action forceCheck = AutoForcedCheck(noteToAdd);

        addedNote = noteToAdd;

        if (forceCheck != null)
        {
            noteRecord.Insert(0, forceCheck);           // Insert at the start so that the modification happens at the end of the undo function, otherwise the natural force check prevents it from being forced
        }
        foreach (Note chordNote in addedNote.chord)
        {
            if (chordNote.controller)
            {
                chordNote.controller.SetDirty();
            }
        }

        Note next = addedNote.nextSeperateNote;

        if (next != null)
        {
            foreach (Note chordNote in next.chord)
            {
                if (chordNote.controller)
                {
                    chordNote.controller.SetDirty();
                }
            }
        }

        return(noteRecord.ToArray());
    }