Dynamics and Hairpins overlap

• Sep 25, 2015 - 22:35
Reported version
S5 - Suggestion

As discussed here: https://musescore.org/en/node/70581

Dynamics and hairpins overlap when inserted without manual adjustment. Dynamics should offset hairpins.



...should look like...



I realized I set the category as a "task", but I'm thinking it should be a bug report. So I'm curious, what is considered a task when submitting an issue?

It's a feature request. You want automatic detection and resolution of this particular type of collision, but that is a feature we don't currently have, so you are requesting it be implemented.

I'm not really clear on what "task" is really intended for, but I think of it as mostly for internal use, like if we want to remind ourselves we need to update something on the web site after making some sort of change to some other part of the web site, or whatever.

To my knowledge, according to SCRUM principles, a "task" is a subpart of a "story". And a "story" can have several "tasks".

What SCRUM is, and what its principles are. I was trying to guess what it might stand for, based on no information at all: "Special Coding Rules for User Mitigation"? ;-) I'll take a closer look at that article. My first impression is that the word is not an acronym, just a proper noun.

I have an implementation that works well without introducing any real complications to the code. The only issue is how to handle existing scores, especially ones where the user has already tried adjusting things manually. Ideally I think we'd do the necessary magic to preserve existing manual adjustments while letting unadjusted hairpins take advantage of the improvements. It's tricky to make this happen though.

BTW, the example in the original post here is incorrect. It you want a cresendo to stop before a given note, you should not include that last note in the haiin. That is, the end of the hairpin should attach to the previous note. Otherwise, there would be no way to have a crescendo on on a single note.

Status (old) active patch (code needs review)


PR includes a vtest:

As mentioned in the PR, I have included comaptibility code so existing scores with manual adjustments will still render correctly (existing scores *without* manual adjustments will automatically pick up the improved rendering). However, the compatibility code will not work correctly until we sort out an issue with how we manage the mscVersion for a score. Currently, 2.0.x scores show as 206 during the read and remain that way until saved, at which point they change to 207. I think they need to change to 207 immediately after the read / first layout, and have proposed that changed elsewhere.

Correct; the test file is designed to show how the hairpin responds both with default dynamic placement but also if a dynamic is manually adjusted.

Assuming you don't make any manual adjustments to the hairpin, then yes, it is laid out relative to the actual position of the dynamic, as shown in the graphic above. The default layout of the hairpin starts is from just after the previous dynamic to just before the next, if there are in fact dynamics at that position. So if a dynamic is moved to the right, the corresponding end point of the hairpin moves as well.

I've spent ~15min testing your PR, and haven't produced a crash or insane behavior, so I support this PR. When fiddling with positions of dynamics, the hairpins respond nicely, so it seems manual adjustment of horizontal-offsets will be a thing of the past.

I'm noticing the following new behavior that I wouldn't consider to be a bug, but I feel like mentioning for the record:

  1. the hairpins/lines adjust their start/stop x positions even if they don't have the same y-position as their corresponding start&stop dynamics. (not really a problem).
  2. if there are multiple dynamics at a segment (of course no musical reason why a chart should do this), then only one of them will be controlling the hairpins/lines.
  3. while dragging a dynamic with mouse, the hairpin/line will adjust up until the point when the dynamic has been re-anchored to another segment, at which point the hairpin/line will return to its original position. A "smarter" version might have the hairpin/line also be re-anchored to the new segment when the corresponding dynamic gets re-anchored. But I realize that the hairpins/lines are not linked with their start/stop dynamic, but rather they are linked to a segment, which is why the observed behavior is expected.
  4. If change the center or start/end x-offset of a hairpin/line, then the hairpin/line will respond to the dynamic as if the hairpin/line had all its x-offsets at default of 0. I don't consider this a problem. This is rather more of an argument for telling users to leave all their x-offsets of hairpins/lines at the default of 0, so that this new auto-adjust code can work best.

Actually, I notice one behavior that I currently don't like. If a hairpin/line ends with a dynamic that is at the first segment of a measure, e.g.:


Then the default behavior (without any manual x-offsets) is fine, as shown above.

However, if decide to manually adjust the x-offset of that dynamic, e.g. offset left:
then you can see that hairpin & dynamic now overlap.

Alternatively if offset right:

Eight way, the end of the hairpin/line is not adjusted. This behavior is inconsistent with cases where the ending segment is not the first segment of a measure. I understand why it happens, because the if statement on line 656, which contains the auto-adjust logic, checks that the next chordrest is in same measure. So this case has basically the same behavior pre-PR.

I admit it is debatable whether it is desirable for the hairpins/lines to always cuttoff 1sp before the barline if they end with a dynamic marking under the first note of the next measure.

Your observations are good. It is true my code doesn't check for the vertical position to see if there really is a collision, and that would make a nice enhancement for a second iteration of this. Mutliple dynamics at the same position would indeed not necesarily be handled "correctly", but it's debatable what that would even mean. As for the drag of dynamic re-anchoring it - I'd be happy to see that "feature" go away, and I know a few others would as well. Anyhow, I can't see any reason why moving a dynamic to a different segment wshould have any effect on the end segment for a hairpin, any more than it does the end segment of an ottava or the vertical position of a chord symbol etc. And it is true that automatic layout functions best if you let it truly be automatic - that's true everywhere.

What you show in the example with the hairpin ending at a barline is worth considering. Presumably it would not be hard to restructure the code so that the cherck for dynamics is performed whether the next chordrest is in the same measure or not. This would also do nice things if the dynamic is not actually offset but happens to be pretty far to the right because the measure starts off with a key and/or time signature change.

This PR can't be merged for 2.0.3 anyhow, and that's my focus right now, but I'm happy to revisit this later.

all good points.

Regarding "As for the drag of dynamic re-anchoring it - I'd be happy to see that "feature" go away, and I know a few others would as well", the most accommodating solution would be to allow user to enable/disalbe the feature from preferences.

Something strange going on with the dynamic at the right end of hairpin—if it's placed on the same note, then it's offset too far to the right, and oddly, if it's actually on the next note, it doesn't stay aligned horizontally with the rest when part of the group is offset vertically to avoid a note. Other than that, it seems to work.