-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Collisions overhaul (and other improvements to horizontal spacing) #11099
Conversation
dce2f17
to
2bc67f4
Compare
This is fantastic! Happy to update the issues once this is merged. But, I did want to verify something. When I took a crck at fixing this a couple of years ago, the issue I ran into was that at the point where we were calculating the spacing requirements for a given note, we didn't yet know for sure if the previous note was upstem or downstem if it was beamed. That's because beam directions weren't computer until later. So in any case where the initially guessed stem direction was up, but the actual stem direction turned out to be down, we would make the wrong call regarding the tucking. See for instance my examples in #4784 I can totally believe this might not be an issue any \more because the beam code has been rewritten. But I wouldn't mind hearing confirmation. |
// be squeezed. I'm temporarily rolling back the idea (still a bit too risky in some edge cases) [M.S.] | ||
double acceptanceRange = 1; | ||
bool doBreak = (system->measures().size() > 1) && ((curSysWidth + ww) > systemWidth * acceptanceRange); | ||
double acceptanceRange = 0.3 * system->squeezableSpace(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does the 0.3 come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing, it just looks good. May be worth a comment though, thanks.
@@ -745,6 +745,26 @@ void LayoutMeasure::getNextMeasure(const LayoutOptions& options, LayoutContext& | |||
} | |||
|
|||
LayoutBeams::createBeams(score, ctx, measure); | |||
/* HACK: The real beam layout is computed at much later stage (you can't do the beams until you know |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MarcSabatella This may be the answer to your question
One tiny question: Is there any performance overhead for this more complex layout algorithm? |
@MarcSabatella stems were a real head scratcher. It turned out that now direction was known at the point of horizontal spacing, but extension was not. And yes, @Marr11317 pointed out the answer. Not an elegant solution at all (and I may look for a better one in future) but one that seems to do the job. |
@Marr11317 Clefs/timesigs/keysigs are an exception to kerning, meaning they shouldn't kern above/below other items. Lyrics are the exception to the exception to kerning. Gonna look into that. |
13b7758
to
16847fc
Compare
@@ -4098,7 +4101,8 @@ void Measure::computeWidth(Segment* s, qreal x, bool isSystemHeader, Fraction mi | |||
bool first = isFirstInSystem(); | |||
const Shape ls(first ? RectF(0.0, -1000000.0, 0.0, 2000000.0) : RectF(0.0, 0.0, 0.0, spatium() * 4)); | |||
|
|||
qreal minNoteSpace = score()->noteHeadWidth() + score()->styleMM(Sid::minNoteDistance); | |||
static constexpr double spacingMultiplier = 1.2; | |||
qreal minNoteSpace = score()->noteHeadWidth() + spacingMultiplier * score()->styleMM(Sid::minNoteDistance); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this spacingMultiplier
is only used there, why not modify Sid::minNoteDistance
instead?
src/engraving/libmscore/score.cpp
Outdated
@@ -5401,6 +5405,160 @@ void Score::doLayoutRange(const Fraction& st, const Fraction& et) | |||
} | |||
} | |||
|
|||
void Score::createPaddingTable() | |||
{ | |||
double minimumPaddingUnit = 0.1 * spatium(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another magic number. Why not 0.01?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a hard limit on the distance that two items can come within; it only applies in certain special situations, e.g. polyrhythms between notes in two voices where the normal minNoteDistance
does not apply. 0.01 would be too small, but like all the other settings this is to become user-configurable eventually.
} | ||
} | ||
|
||
const double ledgerPad = 0.25 * spatium(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should'nt that ledger padding come from the score's configured staff weight?
* but we introduce an appropriate exception for same-voice cases in Shape::minHorizontalDistance(). | ||
*/ | ||
_paddingTable[ElementType::NOTE][ElementType::NOTE] = minimumPaddingUnit; | ||
_paddingTable[ElementType::NOTE][ElementType::LEDGER_LINE] = 0.35 * spatium(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dito
_paddingTable[ElementType::STEM][ElementType::STEM] = 0.85 * spatium(); | ||
_paddingTable[ElementType::STEM][ElementType::ACCIDENTAL] = 0.35 * spatium(); | ||
_paddingTable[ElementType::STEM][ElementType::LEDGER_LINE] = 0.35 * spatium(); | ||
_paddingTable[ElementType::LEDGER_LINE][ElementType::STEM] = 0.35 * spatium(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these magic numbers may need to be modified with other music fonts.
Did you just set these values because you tried them?
If yes, you tried them with Leland I guess?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The magic numbers emanate from me (@mike-spa working here under my brutal and unforgiving instruction).
In the end we want all the values of the padding table to be user-configurable. We can't do that right now as there's a high design cost and it will need a lot of thought to work out how to expose them all, since there are so many values and potential interactions between them.
For now we're taking the settings that do already exist (in the Style -> Measure/Bar dialog) and using them in the relevant slots in the table, and then deriving other values from them where possible. For the remainder I have supplied defaults for the time being, which aren't arbitrary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good then. It can always be made configurable when users ask for it I guess.
@@ -513,6 +513,9 @@ class Score : public QObject, public EngravingObject | |||
void assignIdIfNeed(Staff& staff) const; | |||
void assignIdIfNeed(Part& part) const; | |||
|
|||
PaddingTable _paddingTable; | |||
void createPaddingTable(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the padding table updated when the user changes score properties?
b2d48c3
to
4f505a8
Compare
4f505a8
to
43f14c5
Compare
"8 - engraving_utests (SEGFAULT)" |
Yeah I saw that. I never had that kind failure: how can I replicate that specific test on my machine to debug it? |
Not sure at all. There are other failures too, diffs. Maybe those in the end result in a crash? |
Yeah I'm now going through the diffs and fix those, then I'll force push again and let's see what happens |
772e62e
to
9c351ab
Compare
9c351ab
to
f955849
Compare
Complete overhaul of horizontal spacing collision management. Items are finally allowed to kern above/below each other.
and changed in all the templates
f955849
to
a0e69a5
Compare
@igorkorsukov I got a compiler error after the last rebase related to a QList vs std conflict. I hope I've fixed it correctly |
codestyle
a0e69a5
to
bc0455d
Compare
// These are necessary to be sure that ALL the layout is correctly updated when loading any file | ||
masterScore->styleChanged(); | ||
masterScore->update(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mike-spa can we remove this block of code?
This code takes a lot of time when opening a big score.
You can test on the score from this PR #8143
This code does not solve all the problems with the long opening, but it significantly reduces the time.
And the comment says that this code may not be executed, we just make sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Eism I had to do that because many scores were not loading the new spacing settings correctly, so for now we can't just remove the code, unfortunately. But there is probably a smarter way to do it, I can try to look into that. Just for my understanding: which one of them is more time consuming? styleChanged()
or update()
?
Side note: #8143 was opened before this PR was merged, so there must be also something else going on, I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent, thank you. I'll try to look into it as soon as I can!
This PR rewrites a substantial part of horizontal spacing, particularly the way we perform collision checks. Most notably (and finally) now items can tuck (or kern) above/below each other.
In more detail, what I did is:
A side benefit of allowing items to tuck is that we save a huge amount of horizontal space that we were previously wasting, which lets us:
8. Increase the default value of minNoteDistance to a much more reasonable 0.6 spaces.
This is done in a separate commit, as it requires to also change all template files.
Basically, every single visual test is expected to fail, and I've usually had also utests failing on beams, so that's also to be expected.
@MarcSabatella if I may bother you, it'd be great if you could link some of the old issues that will be fixed by this (one of which you mentioned already). Thanks for the amazing support!
Before:
![Screenshot from 2022-04-01 12-35-00](https://user-images.githubusercontent.com/93707756/161784325-f17edf7a-52b6-44e2-a918-99b27305cbfb.png)
After:
![Screenshot from 2022-04-01 12-36-27](https://user-images.githubusercontent.com/93707756/161784360-ce10b6f7-a118-4e99-be39-2977a29732a8.png)
Before:
![Screenshot from 2022-04-05 17-13-49](https://user-images.githubusercontent.com/93707756/161786906-505e6371-eeb6-41a3-92e2-bffd1cea64ec.png)
![Screenshot from 2022-04-05 17-12-48](https://user-images.githubusercontent.com/93707756/161786953-e77cbb62-6d0b-4042-ada7-b60f2edf8952.png)
After:
![Screenshot from 2022-04-05 17-05-42](https://user-images.githubusercontent.com/93707756/161787043-39061ad1-1dab-4166-9bd0-ae7875adb85c.png)