Skip to content
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

Merged

Conversation

krkartikay
Copy link
Contributor

@krkartikay krkartikay commented Jun 29, 2020

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

@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch 2 times, most recently from ead9407 to 7f04542 Compare July 2, 2020 19:40
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch from 5820a3f to 10dbe58 Compare July 9, 2020 05:00
libmscore/measure.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@shoogle shoogle left a 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/stafflines.cpp Outdated Show resolved Hide resolved
libmscore/tuplet.cpp Outdated Show resolved Hide resolved
libmscore/barline.cpp Outdated Show resolved Hide resolved
libmscore/barline.cpp Outdated Show resolved Hide resolved
Comment on lines 236 to 237
// (Note: apply function even if non-leaf node, to the following element types:
// {PAGE, NOTE, REST, GLISSANDO, VBOX, TUPLET} )
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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.

libmscore/element.cpp Outdated Show resolved Hide resolved
libmscore/note.cpp Outdated Show resolved Hide resolved
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch 3 times, most recently from ebacb1e to 95840a1 Compare July 13, 2020 11:09
Copy link
Contributor

@shoogle shoogle left a 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.

libmscore/beam.cpp Show resolved Hide resolved
libmscore/iname.h Outdated Show resolved Hide resolved
libmscore/measure.cpp Outdated Show resolved Hide resolved
libmscore/note.h Outdated Show resolved Hide resolved
libmscore/tuplet.cpp Outdated Show resolved Hide resolved
mtest/libmscore/all_elements/tst_tree_model.cpp Outdated Show resolved Hide resolved
mtest/libmscore/all_elements/tst_tree_model.cpp Outdated Show resolved Hide resolved
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch 2 times, most recently from eb5fc94 to 3a9e243 Compare July 14, 2020 14:25
@krkartikay krkartikay marked this pull request as ready for review July 14, 2020 15:00
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch from 3a9e243 to 0abf7a3 Compare July 14, 2020 15:42
Copy link
Contributor

@shoogle shoogle left a 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).

libmscore/spacer.h Outdated Show resolved Hide resolved
Comment on lines +153 to +154
if (all || (measure()->visible(staffIdx()) && score()->staff(staffIdx())->show())) {
func(data, this);
Copy link
Contributor

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.

mtest/libmscore/all_elements/tst_tree_model.cpp Outdated Show resolved Hide resolved
libmscore/spanner.cpp Outdated Show resolved Hide resolved
libmscore/scoreElement.cpp Outdated Show resolved Hide resolved
libmscore/element.cpp Outdated Show resolved Hide resolved
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch 4 times, most recently from c3321bc to f356801 Compare July 16, 2020 15:12
@krkartikay
Copy link
Contributor Author

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.

Copy link
Contributor

@shoogle shoogle left a 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.

libmscore/beam.cpp Show resolved Hide resolved
libmscore/spacer.h Outdated Show resolved Hide resolved
libmscore/barline.h Outdated Show resolved Hide resolved
libmscore/spacer.cpp Outdated Show resolved Hide resolved
libmscore/spanner.cpp Outdated Show resolved Hide resolved
libmscore/system.cpp Show resolved Hide resolved
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch from 944fe1b to 9aa91c6 Compare July 17, 2020 07:56
@krkartikay krkartikay marked this pull request as draft July 17, 2020 12:04
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch 4 times, most recently from 3458fc6 to af50103 Compare July 20, 2020 13:03
@krkartikay krkartikay marked this pull request as ready for review July 20, 2020 13:37
@krkartikay krkartikay changed the title [WIP] GSoC 2020: scanElements refactoring based on tree model GSoC 2020: scanElements refactoring based on tree model [vtests] Jul 20, 2020
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch from af50103 to 85e6ba2 Compare July 20, 2020 14:24
Copy link
Contributor

@shoogle shoogle left a 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.)

@shoogle
Copy link
Contributor

shoogle commented Jul 24, 2020

Rebase needed. Also, .cpp and .h files will need to be passed through Uncrustify because there is now a test to enforce coding style. On the bright side, it is now possible to enable the pre-commit hook without causing unwanted changes.

@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch 2 times, most recently from dbce00b to ff6e434 Compare July 25, 2020 15:36
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.
@krkartikay krkartikay force-pushed the gsoc-2020-scanElements-refactor branch from ff6e434 to a0ecbba Compare August 8, 2020 08:24
@krkartikay
Copy link
Contributor Author

Rebased again and resolved conflict in note.cpp.

@igorkorsukov igorkorsukov merged commit b7007f3 into musescore:master Aug 11, 2020
Eism added a commit to Eism/MuseScore that referenced this pull request Feb 11, 2022
Eism added a commit that referenced this pull request Feb 11, 2022
RomanPudashkin added a commit to RomanPudashkin/MuseScore that referenced this pull request Oct 28, 2022
RomanPudashkin added a commit to RomanPudashkin/MuseScore that referenced this pull request Oct 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants