-
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
GSoC 2020: scanElements refactoring based on tree model [vtests] #6274
GSoC 2020: scanElements refactoring based on tree model [vtests] #6274
Conversation
ead9407
to
7f04542
Compare
5820a3f
to
10dbe58
Compare
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.
Looks pretty good, but I don't like how Element::scanElements
forces you to check the treeChildCount()
multiple times (e.g. in barline.cpp). As mentioned on Telegram, a cleaner approach might be this:
void ScoreElement::scanElements(data, func, all)
{
// Apply to all children recursively
for (ScoreElement* el : (*this)) {
el->scanElements(data, func, all);
}
}
void Element::scanElements(data, func, all)
{
// Apply to self
if (all || visible() || score()->showInvisible()) {
func(data, this);
}
}
void BarLine::scanElements(data, func, all)
{
Element::scanElements(data, func, all) // Apply to self
ScoreElement::scanElements(data, func, all) // Apply to children
}
Or you could create non-virtual functions scanSelf
and scanChildren
to do the same thing.
However, these methods might mean that you have to override scanElements
in more places than you do currently, so it's up to you.
libmscore/element.cpp
Outdated
// (Note: apply function even if non-leaf node, to the following element types: | ||
// {PAGE, NOTE, REST, GLISSANDO, VBOX, TUPLET} ) |
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.
No need to keep a list here since it will just go out of date. Better to say something generic like "override this if you need to apply to apply to this element as well as its children".
But why have the treeChildCount()
check anyway? What problems occur if you just apply the function to all elements regardless of whether they are leaf nodes?
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.
I applying the function to all nodes, surprisingly it seemed to work with no obvious bugs. But I couldn't select measures as I could earlier, by clicking on the staff, the system got selected instead. There might be other subtle bugs like this, but I could only find one right now.
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.
Interesting! Normally systems cannot be selected. The same goes for pages, but they have special handling here. Perhaps if you handle systems in a similar way then the bug will disappear?
Note that the bug has nothing to do with drawing. Element::draw is a virtual function that does nothing by default, and it is not overridden by System. The bug actually occurs here, where scanElements
is used to build a BSP Tree of elements that will be searched to find the element at the given position. System is added to that tree when it wasn't previously.
If bugs occur with other classes then we should aim to fix them in the same way as the drawing case: Rather than skipping elements, scanElements
should visit every element, but the effect of calling func
on certain elements should be no-op.
ebacb1e
to
95840a1
Compare
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 are some places where an element is scanned before its children, and in other places it is scanned after its children. I realize that the old scanElements was also inconsistent in this regard, but I think you should pick one method to use exclusively and see if the tests still pass. I recommend children first because I think children are more likely to affect the layout of parents than the other way around, but I could be wrong.
eb5fc94
to
3a9e243
Compare
3a9e243
to
0abf7a3
Compare
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.
Nearly there! There's also a few comments left from previous reviews that need to be addressed (either to fix the problem or to explain why it is not a problem).
if (all || (measure()->visible(staffIdx()) && score()->staff(staffIdx())->show())) { | ||
func(data, this); |
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.
It's code like this that makes me think MStaff should be a proper element and part of the tree model. Then this could be simply:
if (all || mstaff()->isVisible()) {
func(data, this);
}
Anyway, keep it as it is for now. We can add this to our list of things to consider later.
c3321bc
to
f356801
Compare
Note: vtest faliure is intended, because this PR causes ties to be drawn only once (as opposed to twice earlier which was a bug) so the ties appear thinner. |
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.
A few more suggestions.
944fe1b
to
9aa91c6
Compare
3458fc6
to
af50103
Compare
af50103
to
85e6ba2
Compare
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.
Looks good to me! Not sure why the vtests failed given that you updated the PR title, but as far as I am concerned this is ready to merge. (The vests change is due to fixing a bug in the old scanElements that caused ties to be scanned twice.)
Rebase needed. Also, |
dbce00b
to
ff6e434
Compare
Added Tuplets and Melismas (present in unmanaged spanners), and bug fixes involving Tremolo, Ambitus, ChordRest and Measure.
As soon as the measures are added to the linked list they are put into the same system as the previous measure. This is so that each measure should appear in the score tree even if a layout is not done yet.
Now its just a simple iteration over generic children, rather than having to specify each child manually as we did before. This makes the code simpler, and we have to override the virtual function in fewer places. Also, whether an element should be scanned or not is now checked in the child class rather than the parent class. E.g. showLedgerLines() is checked in LedgerLines class now, instead of Chord, etc.
ff6e434
to
a0ecbba
Compare
Rebased again and resolved conflict in |
…g a large score
… a large score" This reverts commit 83e7732.
This PR refactors the scanElements function to scan the elements using the score tree to traverse the elements instead of handling each element case by case.
This builds up on the tree model that I created in my previous PR, #6174 .
Latest GSoC blog link: https://musescore.org/en/user/1743616/blog/2020/07/20/gsoc-2020-tree-model-week-7-finished-scanelements-refactoring