public void AddToSelectedObjects(IEnumerable <SongObject> songObjects)
    {
        var selectedObjectsList = new List <SongObject>(currentSelectedObjects);

        foreach (SongObject songObject in songObjects)
        {
            if (!selectedObjectsList.Contains(songObject))
            {
                int pos = SongObjectHelper.FindClosestPosition(songObject, selectedObjectsList);
                if (pos != SongObjectHelper.NOTFOUND)
                {
                    if (selectedObjectsList[pos] > songObject)
                    {
                        selectedObjectsList.Insert(pos, songObject);
                    }
                    else
                    {
                        selectedObjectsList.Insert(pos + 1, songObject);
                    }
                }
                else
                {
                    selectedObjectsList.Add(songObject);
                }
            }
        }

        currentSelectedObjects = selectedObjectsList;
    }
Пример #2
0
 void AddToSelection(IEnumerable <ChartObject> chartObjects)
 {
     // Insertion sort
     foreach (ChartObject chartObject in chartObjects)
     {
         if (!data.Contains(chartObject))
         {
             int pos = SongObjectHelper.FindClosestPosition(chartObject, data.ToArray());
             if (pos != SongObjectHelper.NOTFOUND)
             {
                 if (data[pos] > chartObject)
                 {
                     data.Insert(pos, chartObject);
                 }
                 else
                 {
                     data.Insert(pos + 1, chartObject);
                 }
             }
             else
             {
                 data.Add(chartObject);
             }
         }
     }
 }
    // Update is called once per frame
    protected override void Update()
    {
        note.chart = editor.currentChart;
        base.Update();

        // Get previous and next note
        int pos = SongObjectHelper.FindClosestPosition(note.tick, editor.currentChart.notes);

        //Debug.Log(pos);
        if (pos == SongObjectHelper.NOTFOUND)
        {
            note.previous = null;
            note.next     = null;
        }
        else
        {
            if (note.IsOpenNote())
            {
                UpdateOpenPrevAndNext(pos);
            }
            else
            {
                UpdatePrevAndNext(pos);
            }
        }

        UpdateFretType();
    }
Пример #4
0
    void CollectStarpowerInViewRange(IList <Starpower> starpowers)
    {
        collectedStarpowerInRange.Clear();
        int index, length;

        SongObjectHelper.GetRange(starpowers, editor.minPos, editor.maxPos, out index, out length);
        for (int i = index; i < index + length; ++i)
        {
            collectedStarpowerInRange.Add(starpowers[i]);
        }

        int arrayPos = SongObjectHelper.FindClosestPosition(editor.minPos, editor.currentChart.starPower);

        if (arrayPos != SongObjectHelper.NOTFOUND)
        {
            // Find the back-most position
            while (arrayPos > 0 && editor.currentChart.starPower[arrayPos].tick >= editor.minPos)
            {
                --arrayPos;
            }
            // Render previous sp sustain in case of overlap into current position
            if (arrayPos >= 0 && editor.currentChart.starPower[arrayPos].tick + editor.currentChart.starPower[arrayPos].length > editor.minPos &&
                (editor.currentChart.starPower[arrayPos].tick + editor.currentChart.starPower[arrayPos].length) < editor.maxPos)
            {
                collectedStarpowerInRange.Add(editor.currentChart.starPower[arrayPos]);
            }
        }
    }
Пример #5
0
    public uint GetCappedLengthForPos(uint pos)
    {
        uint newLength = length;

        if (pos > tick)
        {
            newLength = pos - tick;
        }
        else
        {
            newLength = 0;
        }

        Starpower nextSp = null;

        if (song != null && chart != null)
        {
            int arrayPos = SongObjectHelper.FindClosestPosition(this, chart.starPower);
            if (arrayPos == SongObjectHelper.NOTFOUND)
            {
                return(newLength);
            }

            while (arrayPos < chart.starPower.Count - 1 && chart.starPower[arrayPos].tick <= tick)
            {
                ++arrayPos;
            }

            if (chart.starPower[arrayPos].tick > tick)
            {
                nextSp = chart.starPower[arrayPos];
            }

            if (nextSp != null)
            {
                // Cap sustain length
                if (nextSp.tick < tick)
                {
                    newLength = 0;
                }
                else if (pos > nextSp.tick)
                {
                    // Cap sustain
                    newLength = nextSp.tick - tick;
                }
            }
            // else it's the only starpower or it's the last starpower
        }

        return(newLength);
    }
Пример #6
0
    /// <summary>
    /// Converts a tick position into the time it will appear in the song.
    /// </summary>
    /// <param name="position">Tick position.</param>
    /// <param name="resolution">Ticks per beat, usually provided from the resolution song of a Song class.</param>
    /// <returns>Returns the time in seconds.</returns>
    public float TickToTime(uint position, float resolution)
    {
        int previousBPMPos = SongObjectHelper.FindClosestPosition(position, bpms);

        if (bpms[previousBPMPos].tick > position)
        {
            --previousBPMPos;
        }

        BPM   prevBPM = bpms[previousBPMPos];
        float time    = prevBPM.assignedTime;

        time += (float)TickFunctions.DisToTime(prevBPM.tick, position, resolution, prevBPM.value / 1000.0f);

        return(time);
    }
Пример #7
0
    protected override void Update()
    {
        base.Update();

        if (setAsLastBpm)
        {
            // Set BPM value to the last bpm in the chart from the current position
            int lastBpmArrayPos = SongObjectHelper.FindClosestPosition(bpm.tick, editor.currentSong.bpms);

            if (editor.currentSong.bpms[lastBpmArrayPos].tick > bpm.tick)
            {
                --lastBpmArrayPos;
            }

            if (lastBpmArrayPos != SongObjectHelper.NOTFOUND && lastBpmArrayPos >= 0)
            {
                bpm.value = editor.currentSong.bpms[lastBpmArrayPos].value;
            }
        }
    }
    static ActionHistory.Action[] CapPrevAndNextPreInsert(Starpower sp, Chart chart)
    {
        List <ActionHistory.Action> record = new List <ActionHistory.Action>();
        int arrayPos = SongObjectHelper.FindClosestPosition(sp, chart.starPower);

        if (arrayPos != SongObjectHelper.NOTFOUND)       // Found an object that matches
        {
            if (chart.starPower[arrayPos] < sp)
            {
                ++arrayPos;
            }

            if (arrayPos > 0 && chart.starPower[arrayPos - 1].tick < sp.tick)
            {
                Starpower prevSp = chart.starPower[arrayPos - 1];
                // Cap previous sp
                if (prevSp.tick + prevSp.length > sp.tick)
                {
                    Starpower originalPrev = (Starpower)prevSp.Clone();

                    prevSp.length = sp.tick - prevSp.tick;
                    record.Add(new ActionHistory.Modify(originalPrev, prevSp));
                }
            }

            if (arrayPos < chart.starPower.Count && chart.starPower[arrayPos].tick > sp.tick)
            {
                Starpower nextSp = chart.starPower[arrayPos];

                // Cap self
                if (sp.tick + sp.length > nextSp.tick)
                {
                    Starpower originalNext = (Starpower)nextSp.Clone();
                    sp.length = nextSp.tick - sp.tick;
                    record.Add(new ActionHistory.Modify(originalNext, nextSp));
                }
            }
        }

        return(record.ToArray());
    }
Пример #9
0
    public void UpdatePrevAndNext()
    {
        // Get previous and next note
        int pos = SongObjectHelper.FindClosestPosition(note, editor.currentChart.notes);

        //Debug.Log(pos);
        if (pos == SongObjectHelper.NOTFOUND)
        {
            note.previous = null;
            note.next     = null;
        }
        else
        {
            if (note.IsOpenNote())
            {
                UpdateOpenPrevAndNext(pos);
            }
            else
            {
                UpdateStandardPrevAndNext(pos);
            }
        }
    }
    public override void OnSelectableMouseDown()
    {
        if (editor.toolManager.currentToolId == EditorObjectToolManager.ToolID.Cursor && editor.currentState == ChartEditor.State.Editor && Input.GetMouseButtonDown(0) && !Input.GetMouseButton(1))
        {
            var selectedObjectsManager = editor.selectedObjectsManager;

            // Ctrl-clicking
            if (Globals.modifierInputActive)
            {
                if (selectedObjectsManager.IsSelected(songObject))
                {
                    selectedObjectsManager.RemoveFromSelectedObjects(songObject);
                }
                else
                {
                    selectedObjectsManager.AddToSelectedObjects(songObject);
                }

                return;
            }

            // Shift-clicking
            if (Globals.secondaryInputActive)
            {
                int pos = SongObjectHelper.FindClosestPosition(this.songObject, editor.selectedObjectsManager.currentSelectedObjects);

                if (pos != SongObjectHelper.NOTFOUND)
                {
                    uint min;
                    uint max;

                    if (editor.selectedObjectsManager.currentSelectedObjects[pos].tick > songObject.tick)
                    {
                        max = editor.selectedObjectsManager.currentSelectedObjects[pos].tick;
                        min = songObject.tick;
                    }
                    else
                    {
                        min = editor.selectedObjectsManager.currentSelectedObjects[pos].tick;
                        max = songObject.tick;
                    }

                    var chartObjects = editor.currentChart.chartObjects;
                    int index, length;
                    SongObjectHelper.GetRange(chartObjects, min, max, out index, out length);
                    selectedObjectsManager.SetCurrentSelectedObjects(chartObjects, index, length);

                    return;
                }
            }

            // Regular clicking
            if (!selectedObjectsManager.IsSelected(songObject))
            {
                if (MSChartEditorInput.GetInput(MSChartEditorInputActions.ChordSelect))
                {
                    selectedObjectsManager.SetCurrentSelectedObjects(note.chord);
                }
                else
                {
                    selectedObjectsManager.currentSelectedObject = songObject;
                }

                return;
            }
        }

        // Delete the object on left and right click shortcut
        else if (editor.currentState == ChartEditor.State.Editor &&
                 Input.GetMouseButtonDown(0) && Input.GetMouseButton(1))
        {
            if (MSChartEditorInput.GetInput(MSChartEditorInputActions.ChordSelect))
            {
                Note[] chordNotes = note.GetChord();
                if (Input.GetMouseButton(1))
                {
                    if (SustainController.SustainDraggingInProgress)
                    {
                        editor.commandStack.Pop();  // Cancel the last sustain drag action
                    }
                    Debug.Log("Deleted " + note + " chord at position " + note.tick + " with hold-right left-click shortcut");
                    editor.commandStack.Push(new SongEditDelete(chordNotes));

                    SustainController.ResetSustainDragData();
                }
            }
            else if (Input.GetMouseButton(1))
            {
                if (SustainController.SustainDraggingInProgress)
                {
                    editor.commandStack.Pop();    // Cancel the last sustain drag action
                }
                Debug.Log("Deleted " + note + " at position " + note.tick + " with hold-right left-click shortcut");
                editor.commandStack.Push(new SongEditDelete(note));
                SustainController.ResetSustainDragData();
            }
        }
        else
        {
            sustain.OnSelectableMouseDown();
        }
    }
Пример #11
0
    void CollectNotesInViewRange(IList <Note> notes)
    {
        bool extendedSustainsEnabled = GameSettings.extendedSustainsEnabled;

        uint min_pos = editor.minPos;

        if (noteVisibilityRangeYPosOverride.HasValue)
        {
            uint gameplayPos = editor.currentSong.WorldYPositionToTick(noteVisibilityRangeYPosOverride.Value, editor.currentSong.resolution);
            if (min_pos < gameplayPos)
            {
                min_pos = gameplayPos;
            }
        }

        collectedNotesInRange.Clear();
        int index, length;

        SongObjectHelper.GetRange(notes, min_pos, editor.maxPos, out index, out length);
        for (int i = index; i < index + length; ++i)
        {
            collectedNotesInRange.Add(notes[i]);
        }

        if (min_pos == editor.minPos)
        {
            if (collectedNotesInRange.Count > 0)
            {
                NoteFunctions.GetPreviousOfSustains(prevSustainCache, collectedNotesInRange[0], extendedSustainsEnabled);
                // Find the last known note of each fret type to find any sustains that might overlap into the camera view
                foreach (Note prevNote in prevSustainCache)
                {
                    if (prevNote.tick + prevNote.length > editor.minPos)
                    {
                        collectedNotesInRange.Add(prevNote);
                    }
                }
            }
            else
            {
                int minArrayPos = SongObjectHelper.FindClosestPosition(editor.minPos, editor.currentChart.notes);

                if (minArrayPos != SongObjectHelper.NOTFOUND)
                {
                    while (minArrayPos > 0 && editor.currentChart.notes[minArrayPos].tick == editor.currentChart.notes[minArrayPos - 1].tick)
                    {
                        --minArrayPos;
                    }

                    Note minNote = editor.currentChart.notes[minArrayPos];

                    if (minNote.tick + minNote.length > editor.minPos && minNote.tick < editor.maxPos)
                    {
                        foreach (Note note in minNote.chord)
                        {
                            if (note.tick + note.length > editor.minPos)
                            {
                                collectedNotesInRange.Add(note);
                            }
                        }
                    }

                    NoteFunctions.GetPreviousOfSustains(prevSustainCache, minNote, extendedSustainsEnabled);
                    foreach (Note prevNote in prevSustainCache)
                    {
                        if (prevNote.tick + prevNote.length > editor.minPos)
                        {
                            collectedNotesInRange.Add(prevNote);
                        }
                    }
                }
            }
        }

        // Make sure the notes are within the allowable lanes
        for (int i = collectedNotesInRange.Count - 1; i >= 0; --i)
        {
            Note note = collectedNotesInRange[i];
            if (!note.IsOpenNote() && ((1 << note.rawNote) & editor.laneInfo.laneMask) == 0)
            {
                collectedNotesInRange.RemoveAt(i);
            }
        }
    }
Пример #12
0
    static void CapPrevAndNextPreInsert(Starpower sp, Chart chart, IList <SongObject> overwrittenList, IList <SongObject> validatedList)
    {
        int arrayPos = SongObjectHelper.FindClosestPosition(sp, chart.chartObjects);

        if (arrayPos != SongObjectHelper.NOTFOUND)       // Found an object that matches
        {
            Starpower previousSp = null;
            Starpower nextSp     = null;

            bool currentArrayPosIsStarpower = chart.chartObjects[arrayPos] as Starpower == null;

            // Find the previous starpower
            {
                int previousSpIndex = currentArrayPosIsStarpower ? arrayPos - 1 : arrayPos;
                while (previousSpIndex >= 0 && chart.chartObjects[previousSpIndex].tick < sp.tick)
                {
                    Starpower maybeSp = chart.chartObjects[previousSpIndex] as Starpower;
                    if (maybeSp == null)
                    {
                        --previousSpIndex;
                    }
                    else
                    {
                        previousSp = maybeSp;
                        break;
                    }
                }
            }

            // Find the next starpower
            {
                int nextSpIndex = currentArrayPosIsStarpower ? arrayPos + 1 : arrayPos;
                while (nextSpIndex < chart.chartObjects.Count && chart.chartObjects[nextSpIndex].tick > sp.tick)
                {
                    Starpower maybeSp = chart.chartObjects[nextSpIndex] as Starpower;
                    if (maybeSp == null)
                    {
                        ++nextSpIndex;
                    }
                    else
                    {
                        nextSp = maybeSp;
                        break;
                    }
                }
            }

            if (previousSp != null)
            {
                // Cap previous sp
                if (previousSp.tick + previousSp.length > sp.tick)
                {
                    previousSp.Delete();
                    overwrittenList.Add(previousSp.Clone());

                    uint      newLength = sp.tick - previousSp.tick;
                    Starpower newSp     = new Starpower(previousSp.tick, newLength);
                    chart.Add(newSp);
                    validatedList.Add(newSp);
                }
            }

            if (nextSp != null)
            {
                // Cap self
                if (sp.tick + sp.length > nextSp.tick)
                {
                    sp.length = nextSp.tick - sp.tick;
                }
            }
        }
    }
Пример #13
0
    public override void OnSelectableMouseDown()
    {
        if (Toolpane.currentTool == Toolpane.Tools.Cursor && Globals.applicationMode == Globals.ApplicationMode.Editor && Input.GetMouseButtonDown(0) && !Input.GetMouseButton(1))
        {
            // Ctrl-clicking
            if (Globals.modifierInputActive)
            {
                if (editor.IsSelected(songObject))
                {
                    editor.RemoveFromSelectedObjects(songObject);
                }
                else
                {
                    editor.AddToSelectedObjects(songObject);
                }
            }
            // Shift-clicking
            else if (Globals.secondaryInputActive)
            {
                int pos = SongObjectHelper.FindClosestPosition(this.songObject, editor.currentSelectedObjects);

                if (pos != SongObjectHelper.NOTFOUND)
                {
                    uint min;
                    uint max;

                    if (editor.currentSelectedObjects[pos].tick > songObject.tick)
                    {
                        max = editor.currentSelectedObjects[pos].tick;
                        min = songObject.tick;
                    }
                    else
                    {
                        min = editor.currentSelectedObjects[pos].tick;
                        max = songObject.tick;
                    }

                    editor.currentSelectedObjects = SongObjectHelper.GetRangeCopy(editor.currentChart.chartObjects, min, max);
                }
            }
            // Regular clicking
            else if (!editor.IsSelected(songObject))
            {
                if (ShortcutInput.GetInput(Shortcut.ChordSelect))
                {
                    editor.currentSelectedObjects = note.GetChord();
                }
                else
                {
                    editor.currentSelectedObject = songObject;
                }
            }
        }

        // Delete the object on erase tool
        else if (Globals.applicationMode == Globals.ApplicationMode.Editor &&
                 (
                     (Toolpane.currentTool == Toolpane.Tools.Eraser && Input.GetMouseButtonDown(0)) ||
                     (Input.GetMouseButtonDown(0) && Input.GetMouseButton(1)) ||
                     Eraser.dragging)
                 )
        {
            if (ShortcutInput.GetInput(Shortcut.ChordSelect))
            {
                Note[] chordNotes = note.GetChord();

                if (!Input.GetMouseButton(1))
                {
                    Debug.Log("Deleted " + note + " chord at position " + note.tick + " with eraser tool");
                    Eraser.dragEraseHistory.Add(new ActionHistory.Delete(chordNotes));
                }
                else
                {
                    Debug.Log("Deleted " + note + " chord at position " + note.tick + " with hold-right left-click shortcut");
                    editor.actionHistory.Insert(new ActionHistory.Delete(chordNotes));
                }


                //editor.actionHistory.Insert(new ActionHistory.Delete(chordNotes));
                foreach (Note chordNote in chordNotes)
                {
                    chordNote.Delete();
                }
            }
            else
            {
                if (!Input.GetMouseButton(1))
                {
                    Debug.Log("Deleted " + note + " at position " + note.tick + " with eraser tool");
                    Eraser.dragEraseHistory.Add(new ActionHistory.Delete(note));
                }
                else
                {
                    Debug.Log("Deleted " + note + " at position " + note.tick + " with hold-right left-click shortcut");
                    editor.actionHistory.Insert(new ActionHistory.Delete(note));
                }

                note.Delete();
            }
        }
    }
Пример #14
0
    static void CapPrevAndNextPreInsert(Starpower sp, Chart chart, IList <BaseAction> subActions)
    {
        int arrayPos = SongObjectHelper.FindClosestPosition(sp, chart.chartObjects);

        if (arrayPos != SongObjectHelper.NOTFOUND)       // Found an object that matches
        {
            Starpower previousSp = null;
            Starpower nextSp     = null;

            bool currentArrayPosIsStarpower = chart.chartObjects[arrayPos] as Starpower == null;

            // Find the previous starpower
            {
                int previousSpIndex = currentArrayPosIsStarpower ? arrayPos - 1 : arrayPos;
                while (previousSpIndex >= 0 && chart.chartObjects[previousSpIndex].tick < sp.tick)
                {
                    Starpower maybeSp = chart.chartObjects[previousSpIndex] as Starpower;
                    if (maybeSp == null)
                    {
                        --previousSpIndex;
                    }
                    else
                    {
                        previousSp = maybeSp;
                        break;
                    }
                }
            }

            // Find the next starpower
            {
                int nextSpIndex = currentArrayPosIsStarpower ? arrayPos + 1 : arrayPos;
                while (nextSpIndex < chart.chartObjects.Count && chart.chartObjects[nextSpIndex].tick > sp.tick)
                {
                    Starpower maybeSp = chart.chartObjects[nextSpIndex] as Starpower;
                    if (maybeSp == null)
                    {
                        ++nextSpIndex;
                    }
                    else
                    {
                        nextSp = maybeSp;
                        break;
                    }
                }
            }

            if (previousSp != null)
            {
                // Cap previous sp
                if (previousSp.tick + previousSp.length > sp.tick)
                {
                    uint      newLength = sp.tick - previousSp.tick;
                    Starpower newSp     = new Starpower(previousSp.tick, newLength, previousSp.flags);

                    AddAndInvokeSubAction(new DeleteAction(previousSp), subActions);
                    AddAndInvokeSubAction(new AddAction(newSp), subActions);
                }
            }

            if (nextSp != null)
            {
                // Cap self
                if (sp.tick + sp.length > nextSp.tick)
                {
                    sp.length = nextSp.tick - sp.tick;
                }
            }
        }
    }
    public override void OnSelectableMouseDown()
    {
        if (Toolpane.currentTool == Toolpane.Tools.Cursor && Globals.applicationMode == Globals.ApplicationMode.Editor && Input.GetMouseButtonDown(0) && !Input.GetMouseButton(1))
        {
            // Ctrl-clicking
            if (Globals.modifierInputActive)
            {
                if (editor.IsSelected(songObject))
                {
                    editor.RemoveFromSelectedObjects(songObject);
                }
                else
                {
                    editor.AddToSelectedObjects(songObject);
                }
            }
            // Shift-clicking
            else if (Globals.secondaryInputActive)
            {
                int pos = SongObjectHelper.FindClosestPosition(this.songObject, editor.currentSelectedObjects);

                if (pos != SongObjectHelper.NOTFOUND)
                {
                    uint min;
                    uint max;

                    if (editor.currentSelectedObjects[pos].tick > songObject.tick)
                    {
                        max = editor.currentSelectedObjects[pos].tick;
                        min = songObject.tick;
                    }
                    else
                    {
                        min = editor.currentSelectedObjects[pos].tick;
                        max = songObject.tick;
                    }

                    var chartObjects = editor.currentChart.chartObjects;
                    int index, length;
                    SongObjectHelper.GetRange(chartObjects, min, max, out index, out length);
                    editor.SetCurrentSelectedObjects(chartObjects, index, length);
                }
            }
            // Regular clicking
            else if (!editor.IsSelected(songObject))
            {
                if (ShortcutInput.GetInput(Shortcut.ChordSelect))
                {
                    editor.SetCurrentSelectedObjects(note.chord);
                }
                else
                {
                    editor.currentSelectedObject = songObject;
                }
            }
        }

        // Delete the object on left and right click shortcut
        else if (Globals.applicationMode == Globals.ApplicationMode.Editor &&
                 Input.GetMouseButtonDown(0) && Input.GetMouseButton(1))
        {
            if (ShortcutInput.GetInput(Shortcut.ChordSelect))
            {
                Note[] chordNotes = note.GetChord();
                if (Input.GetMouseButton(1))
                {
                    Debug.Log("Deleted " + note + " chord at position " + note.tick + " with hold-right left-click shortcut");
                    editor.commandStack.Push(new SongEditDelete(chordNotes));
                }
            }
            else if (Input.GetMouseButton(1))
            {
                Debug.Log("Deleted " + note + " at position " + note.tick + " with hold-right left-click shortcut");
                editor.commandStack.Push(new SongEditDelete(note));
            }
        }
        else
        {
            sustain.OnSelectableMouseDown();
        }
    }
Пример #16
0
    public override void OnSelectableMouseDown()
    {
        if (Toolpane.currentTool == Toolpane.Tools.Cursor && Globals.applicationMode == Globals.ApplicationMode.Editor && Input.GetMouseButtonDown(0) && !Input.GetMouseButton(1))
        {
            // Shift-clicking
            // Find the closest object already selected
            // Select all objects in range of that found and the clicked object

            if (Globals.viewMode == Globals.ViewMode.Chart && (Globals.modifierInputActive || Globals.secondaryInputActive))
            {
                // Ctrl-clicking
                if (Globals.modifierInputActive)
                {
                    if (editor.IsSelected(songObject))
                    {
                        editor.RemoveFromSelectedObjects(songObject);
                    }
                    else
                    {
                        editor.AddToSelectedObjects(songObject);
                    }
                }
                // Shift-clicking
                else
                {
                    int pos = SongObjectHelper.FindClosestPosition(this.songObject, editor.currentSelectedObjects);

                    if (pos != SongObjectHelper.NOTFOUND)
                    {
                        uint min;
                        uint max;

                        if (editor.currentSelectedObjects[pos].tick > songObject.tick)
                        {
                            max = editor.currentSelectedObjects[pos].tick;
                            min = songObject.tick;
                        }
                        else
                        {
                            min = editor.currentSelectedObjects[pos].tick;
                            max = songObject.tick;
                        }

                        editor.currentSelectedObjects = SongObjectHelper.GetRangeCopy(editor.currentChart.chartObjects, min, max);
                    }
                }
            }
            else if (!editor.IsSelected(songObject))
            {
                editor.currentSelectedObject = songObject;
            }
        }

        // Delete the object on erase tool or by holding right click and pressing left-click
        else if (Globals.applicationMode == Globals.ApplicationMode.Editor &&
                 (
                     (Toolpane.currentTool == Toolpane.Tools.Eraser && Input.GetMouseButtonDown(0)) ||
                     (Input.GetMouseButtonDown(0) && Input.GetMouseButton(1)) ||
                     Eraser.dragging)
                 )
        {
            if ((songObject.classID != (int)SongObject.ID.BPM && songObject.classID != (int)SongObject.ID.TimeSignature) || songObject.tick != 0)
            {
                if (!Input.GetMouseButton(1))
                {
                    Debug.Log("Deleted " + songObject + " at position " + songObject.tick + " with eraser tool");
                    Eraser.dragEraseHistory.Add(new ActionHistory.Delete(songObject));
                }
                else
                {
                    Debug.Log("Deleted " + songObject + " at position " + songObject.tick + " with hold-right left-click shortcut");
                    editor.actionHistory.Insert(new ActionHistory.Delete(songObject));
                }
                songObject.Delete();
                editor.currentSelectedObject = null;
            }
        }
    }
    static void SubmitDataGlobals(Song song, List <string> stringData)
    {
        const int TEXT_POS_TICK       = 0;
        const int TEXT_POS_EVENT_TYPE = 2;
        const int TEXT_POS_DATA_1     = 3;

#if TIMING_DEBUG
        float time = Time.realtimeSinceStartup;
#endif

        List <Anchor> anchorData = new List <Anchor>();

        foreach (string line in stringData)
        {
            string[] stringSplit = line.Split(' ');
            uint     tick;
            string   eventType;
            if (stringSplit.Length > TEXT_POS_DATA_1 && uint.TryParse(stringSplit[TEXT_POS_TICK], out tick))
            {
                eventType = stringSplit[TEXT_POS_EVENT_TYPE];
                eventType = eventType.ToLower();
            }
            else
            {
                continue;
            }

            switch (eventType)
            {
            case ("ts"):
                uint numerator;
                uint denominator = 2;

                if (!uint.TryParse(stringSplit[TEXT_POS_DATA_1], out numerator))
                {
                    continue;
                }

                if (stringSplit.Length > TEXT_POS_DATA_1 + 1 && !uint.TryParse(stringSplit[TEXT_POS_DATA_1 + 1], out denominator))
                {
                    continue;
                }

                song.Add(new TimeSignature(tick, numerator, (uint)(Mathf.Pow(2, denominator))), false);
                break;

            case ("b"):
                uint value;
                if (!uint.TryParse(stringSplit[TEXT_POS_DATA_1], out value))
                {
                    continue;
                }

                song.Add(new BPM(tick, value), false);
                break;

            case ("e"):
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                int  startIndex = TEXT_POS_DATA_1;
                bool isSection  = false;

                if (stringSplit.Length > TEXT_POS_DATA_1 + 1 && stringSplit[TEXT_POS_DATA_1] == "\"section")
                {
                    startIndex = TEXT_POS_DATA_1 + 1;
                    isSection  = true;
                }

                for (int i = startIndex; i < stringSplit.Length; ++i)
                {
                    sb.Append(stringSplit[i].Trim('"'));
                    if (i < stringSplit.Length - 1)
                    {
                        sb.Append(" ");
                    }
                }

                if (isSection)
                {
                    song.Add(new Section(sb.ToString(), tick), false);
                }
                else
                {
                    song.Add(new Event(sb.ToString(), tick), false);
                }

                break;

            case ("a"):
                ulong anchorValue;
                if (ulong.TryParse(stringSplit[TEXT_POS_DATA_1], out anchorValue))
                {
                    Anchor a;
                    a.tick       = tick;
                    a.anchorTime = (float)(anchorValue / 1000000.0d);
                    anchorData.Add(a);
                }
                break;

            default:
                break;
            }
        }

        BPM[] bpms = song.syncTrack.OfType <BPM>().ToArray();        // BPMs are currently uncached
        foreach (Anchor anchor in anchorData)
        {
            int arrayPos = SongObjectHelper.FindClosestPosition(anchor.tick, bpms);
            if (bpms[arrayPos].tick == anchor.tick)
            {
                bpms[arrayPos].anchor = anchor.anchorTime;
            }
            else
            {
                // Create a new anchored bpm
                uint value;
                if (bpms[arrayPos].tick > anchor.tick)
                {
                    value = bpms[arrayPos - 1].value;
                }
                else
                {
                    value = bpms[arrayPos].value;
                }

                BPM anchoredBPM = new BPM(anchor.tick, value);
                anchoredBPM.anchor = anchor.anchorTime;
            }
        }
#if TIMING_DEBUG
        Debug.Log("Synctrack load time: " + (Time.realtimeSinceStartup - time));
#endif
    }
    public override void OnSelectableMouseDown()
    {
        if (editor.toolManager.currentToolId == EditorObjectToolManager.ToolID.Cursor && editor.currentState == ChartEditor.State.Editor && Input.GetMouseButtonDown(0) && !Input.GetMouseButton(1))
        {
            // Shift-clicking
            // Find the closest object already selected
            // Select all objects in range of that found and the clicked object

            var selectedObjectsManager = editor.selectedObjectsManager;

            if (Globals.viewMode == Globals.ViewMode.Chart && (Globals.modifierInputActive || Globals.secondaryInputActive))
            {
                // Ctrl-clicking
                if (Globals.modifierInputActive)
                {
                    if (selectedObjectsManager.IsSelected(songObject))
                    {
                        selectedObjectsManager.RemoveFromSelectedObjects(songObject);
                    }
                    else
                    {
                        selectedObjectsManager.AddToSelectedObjects(songObject);
                    }
                }
                // Shift-clicking
                else
                {
                    int pos = SongObjectHelper.FindClosestPosition(this.songObject, editor.selectedObjectsManager.currentSelectedObjects);

                    if (pos != SongObjectHelper.NOTFOUND)
                    {
                        uint min;
                        uint max;

                        if (editor.selectedObjectsManager.currentSelectedObjects[pos].tick > songObject.tick)
                        {
                            max = editor.selectedObjectsManager.currentSelectedObjects[pos].tick;
                            min = songObject.tick;
                        }
                        else
                        {
                            min = editor.selectedObjectsManager.currentSelectedObjects[pos].tick;
                            max = songObject.tick;
                        }

                        var chartObjects = editor.currentChart.chartObjects;
                        int index, length;
                        SongObjectHelper.GetRange(chartObjects, min, max, out index, out length);
                        editor.selectedObjectsManager.currentSelectedObjects.Clear();
                        for (int i = index; i < index + length; ++i)
                        {
                            editor.selectedObjectsManager.currentSelectedObjects.Add(chartObjects[i]);
                        }
                    }
                }
            }
            else if (!selectedObjectsManager.IsSelected(songObject))
            {
                selectedObjectsManager.currentSelectedObject = songObject;
            }
        }

        // Delete the object on erase tool or by holding right click and pressing left-click
        else if (editor.currentState == ChartEditor.State.Editor &&
                 Input.GetMouseButtonDown(0) && Input.GetMouseButton(1)
                 )
        {
            if ((songObject.classID != (int)SongObject.ID.BPM && songObject.classID != (int)SongObject.ID.TimeSignature) || songObject.tick != 0)
            {
                if (Input.GetMouseButton(1))
                {
                    Debug.Log("Deleted " + songObject + " at position " + songObject.tick + " with hold-right left-click shortcut");
                    editor.commandStack.Push(new SongEditDelete(songObject));
                }
                editor.selectedObjectsManager.currentSelectedObject = null;
            }
        }
    }