diff --git a/src/engraving/layout/pal/tlayout.cpp b/src/engraving/layout/pal/tlayout.cpp index 78a19dbd4928..fa8513d88725 100644 --- a/src/engraving/layout/pal/tlayout.cpp +++ b/src/engraving/layout/pal/tlayout.cpp @@ -1080,166 +1080,16 @@ void TLayout::layout(FretCircle* item, LayoutContext&) item->setbbox(item->rect().adjusted(-lw, -lw, lw, lw)); } -void TLayout::layout(Glissando* item, LayoutContext& ctx) +void TLayout::layout(Glissando*, LayoutContext&) { - double _spatium = item->spatium(); - - if (ctx.conf().isPaletteMode() || !item->startElement() || !item->endElement()) { // for use in palettes or while dragging - if (item->spannerSegments().empty()) { - item->add(item->createLineSegment(ctx.mutDom().dummyParent()->system())); - } - LineSegment* s = item->frontSegment(); - s->setPos(PointF(-_spatium * Glissando::GLISS_PALETTE_WIDTH / 2, _spatium * Glissando::GLISS_PALETTE_HEIGHT / 2)); - s->setPos2(PointF(_spatium * Glissando::GLISS_PALETTE_WIDTH, -_spatium * Glissando::GLISS_PALETTE_HEIGHT)); - layout(s, ctx); - return; - } - layoutLine(item, ctx); - if (item->spannerSegments().empty()) { - LOGD("no segments"); - return; - } - item->setPos(0.0, 0.0); - - Note* anchor1 = toNote(item->startElement()); - Note* anchor2 = toNote(item->endElement()); - Chord* cr1 = anchor1->chord(); - Chord* cr2 = anchor2->chord(); - GlissandoSegment* segm1 = toGlissandoSegment(item->frontSegment()); - GlissandoSegment* segm2 = toGlissandoSegment(item->backSegment()); - - // Note: line segments are defined by - // initial point: ipos() (relative to system origin) - // ending point: pos2() (relative to initial point) - - // LINE ENDING POINTS TO NOTEHEAD CENTRES - - // assume gliss. line goes from centre of initial note centre to centre of ending note: - // move first segment origin and last segment ending point from notehead origin to notehead centre - // For TAB: begin at the right-edge of initial note rather than centre - PointF offs1 = (cr1->staff()->isTabStaff(cr1->tick())) - ? PointF(anchor1->bbox().right(), 0.0) - : PointF(anchor1->headWidth() * 0.5, 0.0); - - PointF offs2 = PointF(anchor2->headWidth() * 0.5, 0.0); - - // AVOID HORIZONTAL LINES - - int upDown = (0 < (anchor2->pitch() - anchor1->pitch())) - ((anchor2->pitch() - anchor1->pitch()) < 0); - // on TAB's, glissando are by necessity on the same string, this gives an horizontal glissando line; - // make bottom end point lower and top ending point higher - if (cr1->staff()->isTabStaff(cr1->tick())) { - double yOff = cr1->staff()->lineDistance(cr1->tick()) * 0.4 * _spatium; - offs1.ry() += yOff * upDown; - offs2.ry() -= yOff * upDown; - } - // if not TAB, angle glissando between notes on the same line - else { - if (anchor1->line() == anchor2->line()) { - offs1.ry() += _spatium * 0.25 * upDown; - offs2.ry() -= _spatium * 0.25 * upDown; - } - } - - // move initial point of first segment and adjust its length accordingly - segm1->setPos(segm1->ipos() + offs1); - segm1->setPos2(segm1->ipos2() - offs1); - // adjust ending point of last segment - segm2->setPos2(segm2->ipos2() + offs2); - - // INTERPOLATION OF INTERMEDIATE POINTS - // This probably belongs to SLine class itself; currently it does not seem - // to be needed for anything else than Glissando, though - - // get total x-width and total y-height of all segments - double xTot = 0.0; - for (SpannerSegment* segm : item->spannerSegments()) { - xTot += segm->ipos2().x(); - } - double y0 = segm1->ipos().y(); - double yTot = segm2->ipos().y() + segm2->ipos2().y() - y0; - yTot -= yStaffDifference(segm2->system(), segm2->staffIdx(), segm1->system(), segm1->staffIdx()); - double ratio = yTot / xTot; - // interpolate y-coord of intermediate points across total width and height - double xCurr = 0.0; - double yCurr; - for (unsigned i = 0; i + 1 < item->spannerSegments().size(); i++) { - SpannerSegment* segm = item->segmentAt(i); - xCurr += segm->ipos2().x(); - yCurr = y0 + ratio * xCurr; - segm->rypos2() = yCurr - segm->ipos().y(); // position segm. end point at yCurr - // next segment shall start where this segment stopped, corrected for the staff y-difference - SpannerSegment* nextSeg = item->segmentAt(i + 1); - yCurr += yStaffDifference(nextSeg->system(), nextSeg->staffIdx(), segm->system(), segm->staffIdx()); - segm = nextSeg; - segm->rypos2() += segm->ipos().y() - yCurr; // adjust next segm. vertical length - segm->setPosY(yCurr); // position next segm. start point at yCurr - } - - // KEEP CLEAR OF ALL ELEMENTS OF THE CHORD - // Remove offset already applied - offs1 *= -1.0; - offs2 *= -1.0; - // Look at chord shapes (but don't consider lyrics) - Shape cr1shape = cr1->shape(); - mu::remove_if(cr1shape, [](ShapeElement& s) { - if (!s.toItem || s.toItem->isLyrics()) { - return true; - } else { - return false; - } - }); - offs1.rx() += cr1shape.right() - anchor1->pos().x(); - if (!cr2->staff()->isTabStaff(cr2->tick())) { - offs2.rx() -= cr2->shape().left() + anchor2->pos().x(); - } - // Add note distance - const double glissNoteDist = 0.25 * item->spatium(); // TODO: style - offs1.rx() += glissNoteDist; - offs2.rx() -= glissNoteDist; - - // apply offsets: shorten first segment by x1 (and proportionally y) and adjust its length accordingly - offs1.ry() = segm1->ipos2().y() * offs1.x() / segm1->ipos2().x(); - segm1->setPos(segm1->ipos() + offs1); - segm1->setPos2(segm1->ipos2() - offs1); - // adjust last segment length by x2 (and proportionally y) - offs2.ry() = segm2->ipos2().y() * offs2.x() / segm2->ipos2().x(); - segm2->setPos2(segm2->ipos2() + offs2); - - for (SpannerSegment* segm : item->spannerSegments()) { - layoutItem(segm, ctx); - } - - // compute glissando bbox as the bbox of the last segment, relative to the end anchor note - PointF anchor2PagePos = anchor2->pagePos(); - PointF system2PagePos; - IF_ASSERT_FAILED(cr2->segment()->system()) { - system2PagePos = segm2->pos(); - } else { - system2PagePos = cr2->segment()->system()->pagePos(); - } - - PointF anchor2SystPos = anchor2PagePos - system2PagePos; - RectF r = RectF(anchor2SystPos - segm2->pos(), anchor2SystPos - segm2->pos() - segm2->pos2()).normalized(); - double lw = item->lineWidth() * .5; - item->setbbox(r.adjusted(-lw, -lw, lw, lw)); - - item->addLineAttachPoints(); + //! NOTE Moved to PaletteLayout + UNREACHABLE; } -void TLayout::layout(GlissandoSegment* item, LayoutContext&) +void TLayout::layout(GlissandoSegment*, LayoutContext&) { - if (item->pos2().x() <= 0) { - item->setbbox(RectF()); - return; - } - - if (item->staff()) { - item->setMag(item->staff()->staffMag(item->tick())); - } - RectF r = RectF(0.0, 0.0, item->pos2().x(), item->pos2().y()).normalized(); - double lw = item->glissando()->lineWidth() * .5; - item->setbbox(r.adjusted(-lw, -lw, lw, lw)); + //! NOTE Moved to PaletteLayout + UNREACHABLE; } void TLayout::layout(GraceNotesGroup* item, LayoutContext& ctx) diff --git a/src/palette/internal/palettelayout.cpp b/src/palette/internal/palettelayout.cpp index d5e4d2fa4caa..7f8761ac20c9 100644 --- a/src/palette/internal/palettelayout.cpp +++ b/src/palette/internal/palettelayout.cpp @@ -27,6 +27,8 @@ #include "engraving/types/typesconv.h" #include "engraving/types/symnames.h" +#include "engraving/compat/dummyelement.h" + #include "engraving/libmscore/engravingitem.h" #include "engraving/libmscore/score.h" @@ -44,6 +46,7 @@ #include "engraving/libmscore/expression.h" #include "engraving/libmscore/fingering.h" #include "engraving/libmscore/fret.h" +#include "engraving/libmscore/glissando.h" #include "engraving/libmscore/gradualtempochange.h" #include "engraving/libmscore/hairpin.h" #include "engraving/libmscore/harppedaldiagram.h" @@ -115,6 +118,8 @@ void PaletteLayout::layoutItem(EngravingItem* item) break; case ElementType::FRET_DIAGRAM: layout(toFretDiagram(item), ctx); break; + case ElementType::GLISSANDO: layout(toGlissando(item), ctx); + break; case ElementType::GRADUAL_TEMPO_CHANGE: layout(toGradualTempoChange(item), ctx); break; case ElementType::HAIRPIN: layout(toHairpin(item), ctx); @@ -206,6 +211,11 @@ std::shared_ptr PaletteLayout::Context::engravingFont() const return m_score->engravingFont(); } +compat::DummyElement* PaletteLayout::Context::dummyParent() const +{ + return m_score->dummy(); +} + void PaletteLayout::layout(Accidental* item, const Context&) { SymId s = item->symId(); @@ -629,6 +639,31 @@ void PaletteLayout::layout(Dynamic* item, const Context& ctx) layoutTextBase(item, ctx); } +void PaletteLayout::layout(Glissando* item, const Context& ctx) +{ + double spatium = item->spatium(); + + if (item->spannerSegments().empty()) { + item->add(item->createLineSegment(ctx.dummyParent()->system())); + } + LineSegment* s = item->frontSegment(); + s->setPos(PointF(-spatium * Glissando::GLISS_PALETTE_WIDTH / 2, spatium * Glissando::GLISS_PALETTE_HEIGHT / 2)); + s->setPos2(PointF(spatium * Glissando::GLISS_PALETTE_WIDTH, -spatium * Glissando::GLISS_PALETTE_HEIGHT)); + layout(static_cast(s), ctx); +} + +void PaletteLayout::layout(GlissandoSegment* item, const Context&) +{ + if (item->pos2().x() <= 0) { + item->setbbox(RectF()); + return; + } + + RectF r = RectF(0.0, 0.0, item->pos2().x(), item->pos2().y()).normalized(); + double lw = item->glissando()->lineWidth() * .5; + item->setbbox(r.adjusted(-lw, -lw, lw, lw)); +} + void PaletteLayout::layout(GradualTempoChange* item, const Context& ctx) { layoutLine(item, ctx); diff --git a/src/palette/internal/palettelayout.h b/src/palette/internal/palettelayout.h index 29d5c1804dd0..c984dec5ba83 100644 --- a/src/palette/internal/palettelayout.h +++ b/src/palette/internal/palettelayout.h @@ -50,6 +50,8 @@ class Expression; class Fingering; class FretDiagram; +class Glissando; +class GlissandoSegment; class GradualTempoChange; class GradualTempoChangeSegment; @@ -102,6 +104,10 @@ class Volta; class VoltaSegment; } +namespace mu::engraving::compat { +class DummyElement; +} + namespace mu::palette { class PaletteLayout { @@ -116,6 +122,7 @@ class PaletteLayout const engraving::MStyle& style() const; std::shared_ptr engravingFont() const; + engraving::compat::DummyElement* dummyParent() const; private: engraving::Score* m_score = nullptr; @@ -141,6 +148,7 @@ class PaletteLayout static void layout(engraving::Fingering* item, const Context& ctx); static void layout(engraving::FretDiagram* item, const Context& ctx); + static void layout(engraving::Glissando* item, const Context& ctx); static void layout(engraving::GradualTempoChange* item, const Context& ctx); static void layout(engraving::Hairpin* item, const Context& ctx); @@ -178,6 +186,7 @@ class PaletteLayout static void layout(engraving::Volta* item, const Context& ctx); private: + static void layout(engraving::GlissandoSegment* item, const Context& ctx); static void layout(engraving::GradualTempoChangeSegment* item, const Context& ctx); static void layout(engraving::HairpinSegment* item, const Context& ctx); static void layout(engraving::LetRingSegment* item, const Context& ctx);