How to Traverse a Score in Reverse When No Selection Is Made?

• Aug 23, 2024 - 11:31

I'm working on a MuseScore plugin where I need to reverse traverse a score, starting from the last tick. However, I've encountered an issue where, if no selection is made, calling cursor.rewind(2) resets the cursor.tick value to 0 instead of positioning the cursor at the end of the score. Additionally, using cursor.prev() doesn't seem to correctly move the cursor to the previous segment when trying to traverse backward from the end.

Here's my simplified code that demonstrates the problem:

import QtQuick 2.2
import QtQuick.Controls 2.0
import MuseScore 3.0

MuseScore {
version: "3.4.2.1"
description: qsTr("Reverse Traverse Score")
menuPath: "Plugins.Reverse Traverse"

function reverseTraverseScore() {
    var cursor = curScore.newCursor();
    cursor.rewind(2);  // Attempt to move the cursor to the end of the score

    if (cursor.tick === 0) {
        // Cursor failed to move to the end of the score
        console.error("Failed to move cursor to the end of the score.");
        return;
    }

    // Reverse traversal from the end of the score
    while (cursor.tick > 0) {
        console.log("Current tick: " + cursor.tick);
        cursor.prev();  // Attempt to move to the previous segment
    }
}

onRun: {
    reverseTraverseScore();
}

}


Comments

This is a well known bug:
cursor.rewind(2);
if (cursor.tick === 0) {
// this happens when the selection includes
// the last measure of the score.
// rewind(2) goes behind the last segment (where
// there's none) and sets tick=0
endTick = curScore.lastSegment.tick + 1;

Also, there are already a couple of plugins that do the retrograde

https://musescore.org/en/project/new-retrograde
https://musescore.org/en/project/pitch-and-rhythm-transformer
EDIT: cursor.prev() only works after cursor.next() (I think). It does not go to the previous segment in the score but to the previous position of the cursor
EDIT2: I was wrong: you can walk backwards. This works:

cursor.rewindToTick(3840)
while (cursor.tick > 0){
console.log ("tick = ",cursor.tick)
cursor.prev()
}
EDIT3: But I see no way to find the last proper cursor.tick except by walking forwards:
while (cursor.segment && cursor.tick < endTick) {

Do you still have an unanswered question? Please log in first to post your question.