Skip to content

Commit 2a70fdb

Browse files
Merge pull request #20911 from miiizen/20795-hide-clef
Improve clef hiding logic and create new style menu page
2 parents 0e9df9c + ab5e9c3 commit 2a70fdb

File tree

17 files changed

+822
-656
lines changed

17 files changed

+822
-656
lines changed

src/engraving/dom/measure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ Segment* Measure::findFirstR(SegmentType st, const Fraction& t) const
693693
Segment* s;
694694
// search forwards
695695
for (s = first(); s && s->rtick() <= t; s = s->next()) {
696-
if (s->segmentType() == st) {
696+
if (s->segmentType() & st) {
697697
return s;
698698
}
699699
}

src/engraving/rendering/dev/layoutcontext.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,14 @@ Measure* DomAccessor::firstMeasure()
260260
return score()->firstMeasure();
261261
}
262262

263+
Measure* DomAccessor::tick2measure(const Fraction& tick)
264+
{
265+
IF_ASSERT_FAILED(score()) {
266+
return nullptr;
267+
}
268+
return score()->tick2measure(tick);
269+
}
270+
263271
const SpannerMap& DomAccessor::spannerMap() const
264272
{
265273
IF_ASSERT_FAILED(score()) {

src/engraving/rendering/dev/layoutcontext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class DomAccessor
181181

182182
MeasureBase* first();
183183
Measure* firstMeasure();
184+
Measure* tick2measure(const Fraction& tick);
184185

185186
ChordRest* findCR(Fraction tick, track_idx_t track);
186187

src/engraving/rendering/dev/measurelayout.cpp

Lines changed: 182 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,7 @@ double MeasureLayout::createEndBarLines(Measure* m, bool isLastMeasureInSystem,
15091509
visibleInt = 1;
15101510
}
15111511
} else {
1512-
TLayout::layoutClef(clef, clef->mutldata());
1512+
TLayout::layoutClef(clef, clef->mutldata(), ctx.conf());
15131513
clefSeg->createShape(staffIdx);
15141514
visibleInt = 2;
15151515
}
@@ -1552,6 +1552,147 @@ double MeasureLayout::createEndBarLines(Measure* m, bool isLastMeasureInSystem,
15521552
return m->width() - oldWidth;
15531553
}
15541554

1555+
Segment* MeasureLayout::addHeaderClef(Measure* m, bool isFirstClef, const Staff* staff, LayoutContext& ctx)
1556+
{
1557+
const staff_idx_t staffIdx = staff->idx();
1558+
const track_idx_t track = staffIdx * VOICES;
1559+
Segment* cSegment = m->findFirstR(SegmentType::HeaderClef, Fraction(0, 1));
1560+
const StaffType* staffType = staff->staffType(m->tick());
1561+
1562+
const bool hideClef = staffType->isTabStaff() ? ctx.conf().styleB(Sid::hideTabClefAfterFirst) : !ctx.conf().styleB(Sid::genClef);
1563+
1564+
// find the clef type at the previous tick
1565+
ClefTypeList cl = staff->clefType(m->tick() - Fraction::fromTicks(1));
1566+
bool showCourtesy = true;
1567+
Segment* s = nullptr;
1568+
if (m->prevMeasure()) {
1569+
// look for a clef change at the end of the previous measure
1570+
s = m->prevMeasure()->findSegment(SegmentType::Clef, m->tick());
1571+
} else if (m->isMMRest()) {
1572+
// look for a header clef at the beginning of the first underlying measure
1573+
s = m->mmRestFirst()->findFirstR(SegmentType::HeaderClef, Fraction(0, 1));
1574+
}
1575+
if (s) {
1576+
Clef* c = toClef(s->element(track));
1577+
if (c) {
1578+
cl = c->clefTypeList();
1579+
showCourtesy = c->showCourtesy();
1580+
}
1581+
}
1582+
Clef* clef = nullptr;
1583+
if (cSegment) {
1584+
clef = toClef(cSegment->element(track));
1585+
}
1586+
if (staff->staffTypeForElement(m)->genClef() && (isFirstClef || !hideClef)) {
1587+
if (!cSegment) {
1588+
cSegment = Factory::createSegment(m, SegmentType::HeaderClef, Fraction(0, 1));
1589+
cSegment->setHeader(true);
1590+
m->add(cSegment);
1591+
}
1592+
if (!clef) {
1593+
//
1594+
// create missing clef
1595+
//
1596+
clef = Factory::createClef(cSegment);
1597+
clef->setTrack(track);
1598+
clef->setGenerated(true);
1599+
clef->setParent(cSegment);
1600+
clef->setIsHeader(true);
1601+
clef->setShowCourtesy(showCourtesy);
1602+
cSegment->add(clef);
1603+
}
1604+
if (clef->generated()) {
1605+
clef->setClefType(cl);
1606+
}
1607+
clef->setSmall(false);
1608+
clef->mutldata()->reset();
1609+
TLayout::layoutClef(clef, clef->mutldata(), ctx.conf());
1610+
cSegment->setEnabled(true);
1611+
} else if (clef) {
1612+
clef->parentItem()->remove(clef);
1613+
if (clef->generated()) {
1614+
delete clef;
1615+
}
1616+
}
1617+
1618+
return cSegment;
1619+
}
1620+
1621+
Segment* MeasureLayout::addHeaderKeySig(Measure* m, bool isFirstKeysig, const Staff* staff, LayoutContext& ctx)
1622+
{
1623+
const staff_idx_t staffIdx = staff->idx();
1624+
const track_idx_t track = staffIdx * VOICES;
1625+
Segment* kSegment = m->findFirstR(SegmentType::KeySig, Fraction(0, 1));
1626+
// If we need a Key::C KeySig (which would be invisible) and there is
1627+
// a courtesy key sig, don’t create it and switch generated flags.
1628+
// This avoids creating an invisible KeySig which can distort layout.
1629+
1630+
KeySigEvent keyIdx = staff->keySigEvent(m->tick());
1631+
KeySig* ksAnnounce = 0;
1632+
if ((isFirstKeysig || ctx.conf().styleB(Sid::genKeysig)) && (keyIdx.key() == Key::C)) {
1633+
Measure* pm = m->prevMeasure();
1634+
if (pm && pm->hasCourtesyKeySig()) {
1635+
Segment* ks = pm->first(SegmentType::KeySigAnnounce);
1636+
if (ks) {
1637+
ksAnnounce = toKeySig(ks->element(track));
1638+
if (ksAnnounce) {
1639+
isFirstKeysig = false;
1640+
// if (keysig) {
1641+
// ksAnnounce->setGenerated(false);
1642+
//TODO keysig->setGenerated(true);
1643+
// }
1644+
}
1645+
}
1646+
}
1647+
}
1648+
1649+
bool isPitchedStaff = staff->isPitchedStaff(m->tick());
1650+
1651+
KeySig* keysig = nullptr;
1652+
if (kSegment) {
1653+
keysig = toKeySig(kSegment->element(track));
1654+
}
1655+
// keep key sigs in TABs: TABs themselves should hide them
1656+
if ((isFirstKeysig || ctx.conf().styleB(Sid::genKeysig)) && isPitchedStaff) {
1657+
if (!kSegment) {
1658+
kSegment = Factory::createSegment(m, SegmentType::KeySig, Fraction(0, 1));
1659+
kSegment->setHeader(true);
1660+
m->add(kSegment);
1661+
}
1662+
if (!keysig) {
1663+
//
1664+
// create missing key signature
1665+
//
1666+
keysig = Factory::createKeySig(kSegment);
1667+
keysig->setTrack(track);
1668+
keysig->setGenerated(true);
1669+
keysig->setParent(kSegment);
1670+
kSegment->add(keysig);
1671+
}
1672+
keysig->setKeySigEvent(keyIdx);
1673+
keysig->mutldata()->reset();
1674+
TLayout::layoutKeySig(keysig, keysig->mutldata(), ctx.conf());
1675+
kSegment->setEnabled(true);
1676+
} else if (keysig && isPitchedStaff) {
1677+
// do not remove user modified keysigs
1678+
bool remove = true;
1679+
EngravingItem* e = kSegment->element(staffIdx * VOICES);
1680+
Key key = staff->key(m->tick());
1681+
if ((e && !e->generated()) || (key != keyIdx.key())) {
1682+
remove = false;
1683+
}
1684+
1685+
if (remove) {
1686+
keysig->parentItem()->remove(keysig);
1687+
if (keysig->generated()) {
1688+
delete keysig;
1689+
}
1690+
}
1691+
}
1692+
1693+
return kSegment;
1694+
}
1695+
15551696
//-------------------------------------------------------------------
15561697
// addSystemHeader
15571698
/// Add elements to make this measure suitable as the first measure
@@ -1563,145 +1704,57 @@ double MeasureLayout::createEndBarLines(Measure* m, bool isLastMeasureInSystem,
15631704
void MeasureLayout::addSystemHeader(Measure* m, bool isFirstSystem, LayoutContext& ctx)
15641705
{
15651706
int staffIdx = 0;
1566-
Segment* kSegment = m->findFirstR(SegmentType::KeySig, Fraction(0, 1));
1567-
Segment* cSegment = m->findFirstR(SegmentType::HeaderClef, Fraction(0, 1));
1707+
Segment* kSegment = nullptr;
1708+
Segment* cSegment = nullptr;
15681709

15691710
for (const Staff* staff : ctx.dom().staves()) {
15701711
const int track = staffIdx * VOICES;
15711712

1572-
if (isFirstSystem || ctx.conf().styleB(Sid::genClef)) {
1573-
// find the clef type at the previous tick
1574-
ClefTypeList cl = staff->clefType(m->tick() - Fraction::fromTicks(1));
1575-
bool showCourtesy = true;
1576-
Segment* s = nullptr;
1577-
if (m->prevMeasure()) {
1578-
// look for a clef change at the end of the previous measure
1579-
s = m->prevMeasure()->findSegment(SegmentType::Clef, m->tick());
1580-
} else if (m->isMMRest()) {
1581-
// look for a header clef at the beginning of the first underlying measure
1582-
s = m->mmRestFirst()->findFirstR(SegmentType::HeaderClef, Fraction(0, 1));
1583-
}
1584-
if (s) {
1585-
Clef* c = toClef(s->element(track));
1586-
if (c) {
1587-
cl = c->clefTypeList();
1588-
showCourtesy = c->showCourtesy();
1589-
}
1590-
}
1591-
Clef* clef = nullptr;
1592-
if (!cSegment) {
1593-
cSegment = Factory::createSegment(m, SegmentType::HeaderClef, Fraction(0, 1));
1594-
cSegment->setHeader(true);
1595-
m->add(cSegment);
1596-
} else {
1597-
clef = toClef(cSegment->element(track));
1598-
}
1599-
if (staff->staffTypeForElement(m)->genClef()) {
1600-
if (!clef) {
1601-
//
1602-
// create missing clef
1603-
//
1604-
clef = Factory::createClef(cSegment);
1605-
clef->setTrack(track);
1606-
clef->setGenerated(true);
1607-
clef->setParent(cSegment);
1608-
clef->setIsHeader(true);
1609-
clef->setShowCourtesy(showCourtesy);
1610-
cSegment->add(clef);
1611-
}
1612-
if (clef->generated()) {
1613-
clef->setClefType(cl);
1614-
}
1615-
clef->setSmall(false);
1616-
clef->mutldata()->reset();
1617-
TLayout::layoutClef(clef, clef->mutldata());
1618-
} else if (clef) {
1619-
clef->parentItem()->remove(clef);
1620-
if (clef->generated()) {
1621-
delete clef;
1713+
// Check if this is the first VISIBLE appearance
1714+
bool isFirstClef = true;
1715+
bool isFirstKeySig = true;
1716+
if (!isFirstSystem) {
1717+
const Fraction clefTick = staff->currentClefTick(m->tick());
1718+
const Fraction keySigTick = staff->currentKeyTick(m->tick());
1719+
// Get first measure whether MMR or not
1720+
Measure* searchMeasure = ctx.mutDom().tick2measure(std::min(clefTick, keySigTick));
1721+
searchMeasure = searchMeasure->hasMMRest()
1722+
&& ctx.conf().styleB(Sid::createMultiMeasureRests) ? searchMeasure->mmRest() : searchMeasure;
1723+
while (searchMeasure->tick() < m->tick() && (isFirstClef || isFirstKeySig)) {
1724+
const System* sys = searchMeasure->system();
1725+
if (isFirstClef && searchMeasure->tick() >= clefTick) {
1726+
// Need to check previous measure for clef change if one not found in this measure
1727+
Segment* clefSeg = searchMeasure->findFirstR(SegmentType::Clef | SegmentType::HeaderClef, Fraction(0, 0));
1728+
if (Measure* prevMeas = searchMeasure->prevMeasure(); !clefSeg) {
1729+
clefSeg = prevMeas->findSegment(SegmentType::Clef, m->tick());
1730+
}
1731+
if (clefSeg && clefSeg->enabled()) {
1732+
const Clef* c = toClef(clefSeg->element(track));
1733+
if (c && sys && sys->staff(staffIdx)->show()) {
1734+
isFirstClef = false;
1735+
}
1736+
}
16221737
}
1623-
}
1624-
//cSegment->createShape(staffIdx);
1625-
cSegment->setEnabled(true);
1626-
} else {
1627-
if (cSegment) {
1628-
cSegment->setEnabled(false);
1629-
}
1630-
}
1631-
1632-
// keep key sigs in TABs: TABs themselves should hide them
1633-
bool needKeysig = isFirstSystem || ctx.conf().styleB(Sid::genKeysig);
1634-
1635-
// If we need a Key::C KeySig (which would be invisible) and there is
1636-
// a courtesy key sig, don’t create it and switch generated flags.
1637-
// This avoids creating an invisible KeySig which can distort layout.
1638-
1639-
KeySigEvent keyIdx = staff->keySigEvent(m->tick());
1640-
KeySig* ksAnnounce = 0;
1641-
if (needKeysig && (keyIdx.key() == Key::C)) {
1642-
Measure* pm = m->prevMeasure();
1643-
if (pm && pm->hasCourtesyKeySig()) {
1644-
Segment* ks = pm->first(SegmentType::KeySigAnnounce);
1645-
if (ks) {
1646-
ksAnnounce = toKeySig(ks->element(track));
1647-
if (ksAnnounce) {
1648-
needKeysig = false;
1649-
// if (keysig) {
1650-
// ksAnnounce->setGenerated(false);
1651-
//TODO keysig->setGenerated(true);
1652-
// }
1738+
if (isFirstKeySig && searchMeasure->tick() >= keySigTick) {
1739+
const Segment* ksSeg = searchMeasure->findSegment(SegmentType::KeySig, searchMeasure->tick());
1740+
if (ksSeg && ksSeg->enabled()) {
1741+
const KeySig* ks = toKeySig(ksSeg->element(track));
1742+
if (ks && sys && sys->staff(staffIdx)->show()) {
1743+
isFirstKeySig = false;
1744+
}
16531745
}
16541746
}
1747+
// Get next measure, factoring in MMRs
1748+
searchMeasure = searchMeasure->nextMeasure();
1749+
if (searchMeasure && searchMeasure->hasMMRest()) {
1750+
searchMeasure = searchMeasure->mmRest();
1751+
}
16551752
}
16561753
}
16571754

1658-
bool isPitchedStaff = staff->isPitchedStaff(m->tick());
1755+
cSegment = addHeaderClef(m, isFirstSystem || isFirstClef, staff, ctx);
16591756

1660-
if (needKeysig && isPitchedStaff) {
1661-
KeySig* keysig;
1662-
if (!kSegment) {
1663-
kSegment = Factory::createSegment(m, SegmentType::KeySig, Fraction(0, 1));
1664-
kSegment->setHeader(true);
1665-
m->add(kSegment);
1666-
keysig = 0;
1667-
} else {
1668-
keysig = toKeySig(kSegment->element(track));
1669-
}
1670-
if (!keysig) {
1671-
//
1672-
// create missing key signature
1673-
//
1674-
keysig = Factory::createKeySig(kSegment);
1675-
keysig->setTrack(track);
1676-
keysig->setGenerated(true);
1677-
keysig->setParent(kSegment);
1678-
kSegment->add(keysig);
1679-
}
1680-
keysig->setKeySigEvent(keyIdx);
1681-
TLayout::layoutKeySig(keysig, keysig->mutldata(), ctx.conf());
1682-
//kSegment->createShape(staffIdx);
1683-
kSegment->setEnabled(true);
1684-
} else if (kSegment && isPitchedStaff) {
1685-
// do not disable user modified keysigs
1686-
bool disable = true;
1687-
for (size_t i = 0; i < ctx.dom().nstaves(); ++i) {
1688-
EngravingItem* e = kSegment->element(i * VOICES);
1689-
Key key = ctx.dom().staff(i)->key(m->tick());
1690-
if ((e && !e->generated()) || (key != keyIdx.key())) {
1691-
disable = false;
1692-
}
1693-
}
1694-
1695-
if (disable) {
1696-
kSegment->setEnabled(false);
1697-
} else {
1698-
EngravingItem* e = kSegment->element(track);
1699-
if (e && e->isKeySig()) {
1700-
KeySig* keysig = toKeySig(e);
1701-
TLayout::layoutKeySig(keysig, keysig->mutldata(), ctx.conf());
1702-
}
1703-
}
1704-
}
1757+
kSegment = addHeaderKeySig(m, isFirstSystem || isFirstKeySig, staff, ctx);
17051758

17061759
++staffIdx;
17071760
}

src/engraving/rendering/dev/measurelayout.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class MeasureLayout
5151
static void layoutCrossStaff(MeasureBase* mb, LayoutContext& ctx);
5252

5353
static double createEndBarLines(Measure* m, bool isLastMeasureInSystem, LayoutContext& ctx);
54+
static Segment* addHeaderClef(Measure* m, bool isFirstClef, const Staff* staff, LayoutContext& ctx);
55+
static Segment* addHeaderKeySig(Measure* m, bool isFirstKeysig, const Staff* staff, LayoutContext& ctx);
5456
static void addSystemHeader(Measure* m, bool isFirstSystem, LayoutContext& ctx);
5557
static void removeSystemHeader(Measure* m);
5658
static void addSystemTrailer(Measure* m, Measure* nm, LayoutContext& ctx);

src/engraving/rendering/dev/pagelayout.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,13 @@ void PageLayout::collectPage(LayoutContext& ctx)
272272
}
273273
}
274274

275+
// All staves have been hidden, so correct last system's header
276+
System* lastSys = ctx.mutState().page()->systems().back();
277+
Measure* lastSysMeasure = lastSys->firstMeasure();
278+
if (lastSysMeasure) {
279+
MeasureLayout::addSystemHeader(lastSysMeasure, false, ctx);
280+
}
281+
275282
Fraction stick2 = Fraction(-1, 1);
276283
for (System* s : page->systems()) {
277284
for (MeasureBase* mb : s->measures()) {

0 commit comments

Comments
 (0)