GSoC 2020 Week 5 Recap: Laying Out Measure Repeats
Update from last week
My goals for last week were as follows:
- Expand MeasureRepeat class to support varying numbers under the hood
- Draw the MeasureRepeat from the font instead of with a hard-coded path
- Make all current uses of MeasureRepeat specify that it is the one-measure version being called (i.e., keeping same functionality, but changing implementation)
I did all of that in the first couple of days, and went on to, well, take those under-the-hood changes out from under the hood. Here's a demonstration of the current level of functionality:
To get here, I consulted with my mentor and we figured out the essential architectural concept: the measure repeat consists of the symbol, which is only attached to one measure, and then the possibly two or four measures which are treated as a group associated with the measure repeat (grouped with the "Group Measures" element I worked on earlier). Thus, it was necessary to make measures aware when they were they are part of a measure repeat group. In addition, since measures cannot be entirely empty but must at least hold a full measure rest, those rests must be present but not laid out when they are in a measure repeat group.
The way I have this implemented currently, each measure knows how to find the first measure of the group, and that's enough; knowing the total number of measures and the place where they start, they can all be reached when needed.
It is also worth noting that I used only two positioning algorithms—the measure repeat symbol can be either centered within the measure or centered over the barline at the end of the measure—and for the four-measure repeat, it simply gets attached to the second measure of the group rather than the first.
Here's the MSCX code for a four-measure repeat. Note that each measure has its measureRepeatCount, showing that it is part of the group, and the MeasureRepeat itself, with subtype 4, is in the second measure. (The MeasureRepeat holds a faux "duration" because it is occupying the place of a rest in the second measure; I will probably revise this implementation further and make it merely an element attached to the measure, in addition to, rather than instead of, a full measure rest.)
All of this is meant to be as automatic as possible. So, for example, everything to do with creating the measure group is handled at the same time that the MeasureRepeat is inserted, and everything to do with making the measures independent again is handled at the same time that the MeasureRepeat is deleted. At the moment, as seen in the video, there's the rather serious problem that this doesn't happen when undoing an insertion or a deletion.
Looking forward to this week
Priority 1 is figuring out the undo/redo system and fixing that rather serious problem. Priority 2 is figuring out and fixing the glitch that happened while I was recording the video. After that, there are any number of things that could be improved:
- Making the MeasureRepeat merely an element attached to the measure, in addition to, rather than instead of, a full measure rest
- Warning the user if adding the MeasureRepeat will cause existing content to be cleared out of the way
- Deleting symbol and ungrouping measures (with a warning) if user tries to enter notes within the group
- Adding Inspector properties to show/hide outriggers, as well as the numbers
- Including the numbers in autoplace calculations (currently left out because it distorts the width of whichever measure the symbol is attached to)
Work will be pushed here: https://github.com/IsaacWeiss/MuseScore/commits/gsoc-2020-measure-repea…