Implemented note input cursor

This commit is contained in:
Eism 2020-12-10 13:22:54 +02:00 committed by Igor Korsukov
parent 854faa2c65
commit 4ffa1a6772
14 changed files with 264 additions and 12 deletions

View file

@ -185,7 +185,7 @@ Ret FluidSynth::removeSoundFonts()
Ret FluidSynth::setupChannels(const std::vector<Event>& events)
{
IF_ASSERT_FAILED(m_fluid->synth) {
if (!m_fluid->synth) {
return make_ret(Err::SynthNotInited);
}
@ -271,7 +271,7 @@ void FluidSynth::allSoundsOff()
void FluidSynth::flushSound()
{
IF_ASSERT_FAILED(m_fluid->synth) {
if (!m_fluid->synth) {
return;
}

View file

@ -37,6 +37,7 @@
#include "xml.h"
#include "undo.h"
#include "harmony.h"
#include "hook.h"
namespace Ms {
//---------------------------------------------------------
@ -1217,6 +1218,35 @@ void Segment::scanElements(void* data, void (* func)(void*, Element*), bool all)
}
}
QRectF Segment::contentRect() const
{
QRectF result;
for (const Element* element: elist()) {
if (!element) {
continue;
}
if (element->isChord()) {
const Chord* chord = dynamic_cast<const Chord*>(element);
for (const Note* note: chord->notes()) {
result = result.united(note->bbox());
}
Hook* hook = chord->hook();
if (hook) {
QRectF rect = QRectF(hook->pos().x(), hook->pos().y(), hook->width(), hook->height());
result = result.united(rect);
}
continue;
}
result = result.united(element->bbox());
}
return result;
}
//---------------------------------------------------------
// firstElement
// This function returns the first main element from a

View file

@ -136,6 +136,8 @@ public:
qreal x() const override { return ipos().x(); }
void setX(qreal v) { rxpos() = v; }
QRectF contentRect() const;
void insertStaff(int staff);
void removeStaff(int staff);

View file

@ -128,8 +128,10 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/view/viewmodecontrolmodel.h
${CMAKE_CURRENT_LIST_DIR}/view/notationaccessibilitymodel.cpp
${CMAKE_CURRENT_LIST_DIR}/view/notationaccessibilitymodel.h
${CMAKE_CURRENT_LIST_DIR}/view/playbackcursor.h
${CMAKE_CURRENT_LIST_DIR}/view/playbackcursor.cpp
${CMAKE_CURRENT_LIST_DIR}/view/playbackcursor.h
${CMAKE_CURRENT_LIST_DIR}/view/noteinputcursor.cpp
${CMAKE_CURRENT_LIST_DIR}/view/noteinputcursor.h
${CMAKE_CURRENT_LIST_DIR}/view/notationswitchlistmodel.cpp
${CMAKE_CURRENT_LIST_DIR}/view/notationswitchlistmodel.h
${CMAKE_CURRENT_LIST_DIR}/view/partlistmodel.cpp

View file

@ -49,7 +49,7 @@ public:
virtual QColor anchorLineColor() const = 0;
virtual QColor playbackCursorColor() const = 0;
virtual QColor selectionColor() const = 0;
virtual QColor selectionColor(int voice = 0) const = 0;
virtual int selectionProximity() const = 0;

View file

@ -48,6 +48,9 @@ public:
virtual void setCurrentVoiceIndex(int voiceIndex) = 0;
virtual QRectF cursorRect() const = 0;
virtual QColor cursorColor() const = 0;
virtual async::Notification noteAdded() const = 0;
virtual async::Notification stateChanged() const = 0;
};

View file

@ -18,14 +18,15 @@
//=============================================================================
#include "notationconfiguration.h"
#include "log.h"
#include "settings.h"
#include "io/path.h"
#include "libmscore/preferences.h"
#include "libmscore/mscore.h"
#include "log.h"
#include "settings.h"
#include "io/path.h"
#include "notationtypes.h"
using namespace mu;
using namespace mu::notation;
using namespace mu::framework;
@ -160,9 +161,13 @@ QColor NotationConfiguration::playbackCursorColor() const
return c;
}
QColor NotationConfiguration::selectionColor() const
QColor NotationConfiguration::selectionColor(int voice) const
{
return Ms::MScore::selectColor[0];
if (!isVoiceIndexValid(voice)) {
return QColor();
}
return Ms::MScore::selectColor[voice];
}
int NotationConfiguration::selectionProximity() const

View file

@ -50,7 +50,7 @@ public:
io::path foregroundWallpaper() const override;
QColor playbackCursorColor() const override;
QColor selectionColor() const override;
QColor selectionColor(int voice) const override;
int selectionProximity() const override;

View file

@ -25,6 +25,9 @@
#include "libmscore/chord.h"
#include "libmscore/slur.h"
#include "libmscore/articulation.h"
#include "libmscore/system.h"
#include "libmscore/page.h"
#include "libmscore/stafftype.h"
#include "scorecallbacks.h"
@ -255,6 +258,63 @@ void NotationNoteInput::putTuplet(const TupletOptions& options)
m_stateChanged.notify();
}
QRectF NotationNoteInput::cursorRect() const
{
if (!isNoteInputMode()) {
return QRectF();
}
Ms::InputState& inputState = score()->inputState();
Ms::Segment* segment = inputState.segment();
if (!segment) {
return QRectF();
}
Ms::System* system = segment->measure()->system();
if (!system) {
return QRectF();
}
int track = inputState.track() == -1 ? 0 : inputState.track();
int staffIdx = track / VOICES;
QRectF segmentContentRect = segment->contentRect();
double x = segmentContentRect.translated(segment->pagePos()).x() - 6;
double y = system->staffYpage(staffIdx) + system->page()->pos().y();
double w = segmentContentRect.width() + 12;
double h;
Staff* staff = score()->staff(staffIdx);
const Ms::StaffType* staffType = staff->staffType(inputState.tick());
double spatium = score()->spatium();
double lineDist = staffType->lineDistance().val() * spatium;
int lines = staffType->lines();
int strg = inputState.string();
int instrStrgs = staff->part()->instrument()->stringData()->strings();
if (staff->isTabStaff(inputState.tick()) && strg >= 0 && strg <= instrStrgs) {
h = lineDist;
y += staffType->physStringToYOffset(strg) * spatium;
y -= (staffType->onLines() ? lineDist * 0.5 : lineDist);
} else {
h = (lines - 1) * lineDist + 4 * spatium;
y -= 2.0 * spatium;
}
QRectF result = QRectF(x, y, w, h);
return result;
}
QColor NotationNoteInput::cursorColor() const
{
Ms::InputState& inputState = score()->inputState();
int track = inputState.track() == -1 ? 0 : inputState.track();
int voice = track % VOICES;
return configuration()->selectionColor(voice);
}
void NotationNoteInput::setSlur(Ms::Slur* slur)
{
Ms::InputState& inputState = score()->inputState();

View file

@ -20,7 +20,9 @@
#define MU_NOTATION_NOTATIONNOTEINPUT_H
#include "../inotationnoteinput.h"
#include "modularity/ioc.h"
#include "async/asyncable.h"
#include "inotationconfiguration.h"
#include "igetscore.h"
#include "inotationinteraction.h"
#include "inotationundostack.h"
@ -33,6 +35,8 @@ namespace mu::notation {
class ScoreCallbacks;
class NotationNoteInput : public INotationNoteInput, public async::Asyncable
{
INJECT(notation, INotationConfiguration, configuration)
public:
NotationNoteInput(const IGetScore* getScore, INotationInteraction* interaction, INotationUndoStackPtr undoStack);
~NotationNoteInput() override;
@ -56,6 +60,9 @@ public:
void setCurrentVoiceIndex(int voiceIndex) override;
QRectF cursorRect() const override;
QColor cursorColor() const override;
async::Notification noteAdded() const override;
async::Notification stateChanged() const override;

View file

@ -47,6 +47,8 @@ NotationPaintView::NotationPaintView(QQuickItem* parent)
m_playbackCursor->setColor(configuration()->playbackCursorColor());
m_playbackCursor->setVisible(false);
m_noteInputCursor = new NoteInputCursor();
playbackController()->isPlayingChanged().onNotify(this, [this]() {
onPlayingChanged();
});
@ -73,6 +75,7 @@ NotationPaintView::~NotationPaintView()
{
delete m_inputController;
delete m_playbackCursor;
delete m_noteInputCursor;
}
void NotationPaintView::handleAction(const QString& actionName)
@ -208,6 +211,7 @@ void NotationPaintView::paint(QPainter* painter)
m_notation->paint(painter, toLogical(rect));
m_playbackCursor->paint(painter);
m_noteInputCursor->paint(painter);
} else {
painter->drawText(10, 10, "no notation");
}

View file

@ -36,6 +36,7 @@
#include "notationviewinputcontroller.h"
#include "playbackcursor.h"
#include "noteinputcursor.h"
namespace mu {
namespace notation {
@ -124,6 +125,7 @@ private:
QTransform m_matrix;
NotationViewInputController* m_inputController = nullptr;
PlaybackCursor* m_playbackCursor = nullptr;
NoteInputCursor* m_noteInputCursor = nullptr;
};
}
}

View file

@ -0,0 +1,84 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "noteinputcursor.h"
#include <QPainter>
using namespace mu::notation;
void NoteInputCursor::paint(QPainter* painter)
{
if (!isNoteInputMode()) {
return;
}
QRectF cursorRect = rect();
QColor fillColor = color();
fillColor.setAlpha(50);
painter->fillRect(cursorRect, fillColor);
QRectF leftLine = QRectF(cursorRect.topLeft().x(), cursorRect.topLeft().y(), 3, cursorRect.height());
QColor lineColor = color();
painter->fillRect(leftLine, lineColor);
}
INotationNoteInputPtr NoteInputCursor::currentNoteInput() const
{
auto notation = globalContext()->currentNotation();
if (!notation) {
return nullptr;
}
auto interaction = notation->interaction();
if (!interaction) {
return nullptr;
}
return interaction->noteInput();
}
bool NoteInputCursor::isNoteInputMode() const
{
auto noteInput = currentNoteInput();
if (!noteInput) {
return false;
}
return noteInput->isNoteInputMode();
}
QRectF NoteInputCursor::rect() const
{
auto noteInput = currentNoteInput();
if (!noteInput) {
return QRectF();
}
return noteInput->cursorRect();
}
QColor NoteInputCursor::color() const
{
auto noteInput = currentNoteInput();
if (!noteInput) {
return QColor();
}
return noteInput->cursorColor();
}

View file

@ -0,0 +1,53 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef MU_NOTATION_NOTEINPUTCURSOR_H
#define MU_NOTATION_NOTEINPUTCURSOR_H
#include <QRect>
#include <QColor>
#include "modularity/ioc.h"
#include "context/iglobalcontext.h"
#include "async/asyncable.h"
#include "inotationconfiguration.h"
class QPainter;
namespace mu::notation {
class NoteInputCursor : public async::Asyncable
{
INJECT(notation, context::IGlobalContext, globalContext)
INJECT(notation, INotationConfiguration, configuration)
public:
NoteInputCursor() = default;
void paint(QPainter* painter);
private:
INotationNoteInputPtr currentNoteInput() const;
bool isNoteInputMode() const;
QRectF rect() const;
QColor color() const;
};
}
#endif // MU_NOTATION_NOTEINPUTCURSOR_H