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

Avoid collisions in full tab layout #22860

Merged
merged 1 commit into from
Jul 23, 2024
Merged

Conversation

miiizen
Copy link
Contributor

@miiizen miiizen commented May 16, 2024

Resolves: #21394
This PR will avoid collisions between up & down stemmed chords in full TAB staves in the same way as we do in standard staves. It will also offset fret markings in common tabs, so voices and stems can be distinguished
Screenshot 2024-07-15 at 09 53 17

@miiizen miiizen marked this pull request as ready for review July 12, 2024 14:06
@miiizen miiizen force-pushed the tab-full-layout branch 3 times, most recently from 327409a to abda505 Compare July 15, 2024 12:54
@oktophonie oktophonie added the vtests This PR produces approved changes to vtest results label Jul 15, 2024
@oktophonie oktophonie requested a review from mike-spa July 15, 2024 15:56

int Note::stringOrLine() const
{
return staff()->staffType(tick())->isTabStaff() ? string() * 2 : line();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, why string() * 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 6 strings are numbered 1 to 6 whereas the 5 stave lines are numbered 1 to 10 including spaces. This method is used in layout methods which are built around lines and assume even numbers are spaces and odd are lines.
I could make this more clear - rename it staveLine() or just leave a comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha! Good point. No I think the name is fine, but definitely worth a comment :)

const bool isSimpleTab = !staff->staffType() || (!staff->staffType()->stemThrough() && !staff->staffType()->isCommonTabStaff());
if (staff && staff->isTabStaff(tick) && isSimpleTab) {
// Reset position
for (track_idx_t track = partStartTrack; track < partEndTrack; ++track) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why you need to do this reset here? Do chords in normal staves also perform this reset? If so, it would be better to perform it in the same place if we can

Copy link
Contributor Author

@miiizen miiizen Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed when switching from full/common TAB to simple TAB. It isn't needed for normal staves as these always have offsets calculated and applied later on in layoutChords1. I'll leave a clearer comment.

double nominalWidth = ctx.conf().noteHeadWidth() * staff->staffMag(tick);
// Fret width plus white background box for TAB
double nominalWidth = !isTab ? ctx.conf().noteHeadWidth() * staff->staffMag(tick)
: (ctx.conf().fretWidth(staffType) + 0.2 * staff->spatium(tick)) * staff->staffMag(tick);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is 0.2? Is that the white background padding around the fret number? If so, it would be better to properly define/retrieve this value (I think I may have seen it defined somewhere, it definitely should be a style definition if it isn't already)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is. It isn't defined properly anywhere. I'll add it as a style value.

@@ -2155,7 +2186,8 @@ double ChordLayout::layoutChords2(std::vector<Note*>& notes, bool up, LayoutCont

// accumulate return value
if (!mirror) {
maxWidth = std::max(maxWidth, note->bboxRightPos());
const double noteWidth = isTab ? note->tabHeadWidth(tab) + 0.2 * note->spatium() : note->bboxRightPos();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same 0.2 as above, I think?


if (isTab) {
// Need to lay out TAB note to know width
TLayout::layoutNote(note, note->mutldata());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar question as before: why do we need this here for TABs but not for normal staves? Ideally, this should be done in the same place as it's done for normal staves (that is, I would imagine, well before we get here)

Copy link
Contributor Author

@miiizen miiizen Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The layout in this area just uses the notehead symbol dimensions and doesn't need the whole note to be laid out.
TAB notes need to have m_fretString set correctly (which happens during note layout) before tabHeadWidth can return an accurate value. I can change tabHeadWidth to set m_fretString to avoid needing to call note layout.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok I see, makes sense. Then I'd leave it as it is (perhaps, again, with a comment to give this context). Let's keep tabHeadWidth single-responsibility and do the layout call here


muse::draw::Font f = tab->fretFont();
f.setPointSizeF(tab->fretFontSize());
return muse::draw::FontMetrics::width(f, u"0");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels quite hacky though. Fret width is highly variable from one fret mark to another (a two-digit fret is about twice as wide) so it doesn't feel like something that should be in LayoutConfiguration, which is about styles and general constants. Ideally we should just use the individual width of the fret that we are working on. If you really need a "reference" value of some sort, than I'd call this function "referenceFretWidth" or something like that and put it probably in the fret class. Though I think it'd be better to avoid this if we can

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The process of centering notes in chords needs a reference value, though it isn't important as to what that value is. I'll remove this and we can just use ctx.conf().noteHeadWidth() (which is the width of the noteheadBlack symbol) for both staves.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After another look, we don't need to centre frets at all. (See chordlayout.cpp line 1641)

@miiizen miiizen force-pushed the tab-full-layout branch 2 times, most recently from b370da6 to 9a45e79 Compare July 16, 2024 12:08
@mike-spa mike-spa merged commit 04122ec into musescore:master Jul 23, 2024
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
vtests This PR produces approved changes to vtest results
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bass TAB: Note in 2nd Voice Gets Beamed Together with Notes in 1st Voice
3 participants