diff --git a/include/InstrumentTrackWindow.h b/include/InstrumentTrackWindow.h index 48a352cbd30..a5ad0d2b2fd 100644 --- a/include/InstrumentTrackWindow.h +++ b/include/InstrumentTrackWindow.h @@ -29,6 +29,7 @@ #include "ModelView.h" #include "SerializingObject.h" +#include "PluginView.h" class QLabel; class QLineEdit; @@ -67,6 +68,11 @@ class InstrumentTrackWindow : public QWidget, public ModelView, InstrumentTrackWindow( InstrumentTrackView * _tv ); ~InstrumentTrackWindow() override; + // Is this needed? + /* void resizeEvent(QResizeEvent* event) override { m_instrumentView->resize(size()); } */ + void resizeEvent(QResizeEvent* event) override; + + // parent for all internal tab-widgets TabWidget * tabWidgetParent() { @@ -152,6 +158,7 @@ protected slots: InstrumentSoundShapingView * m_ssView; InstrumentFunctionNoteStackingView* m_noteStackingView; InstrumentFunctionArpeggioView* m_arpeggioView; + QWidget* m_instrumentFunctionsView; // container of note stacking and arpeggio InstrumentMidiIOView * m_midiView; EffectRackView * m_effectView; InstrumentTuningView *m_tuningView; diff --git a/include/PluginView.h b/include/PluginView.h index 3c78cb00af2..a85b0b9e185 100644 --- a/include/PluginView.h +++ b/include/PluginView.h @@ -27,23 +27,26 @@ #include -#include "Plugin.h" #include "ModelView.h" +#include "Plugin.h" -namespace lmms::gui -{ +namespace lmms::gui { -class LMMS_EXPORT PluginView : public QWidget, public ModelView +class LMMS_EXPORT PluginView : public QWidget, public ModelView { public: - PluginView( Plugin * _plugin, QWidget * _parent ) : - QWidget( _parent ), - ModelView( _plugin, this ) + PluginView(Plugin* _plugin, QWidget* _parent) + : QWidget(_parent) + , ModelView(_plugin, this) { } -} ; + void setResizable(bool resizable) { m_isResizable = resizable; } + bool isResizable() { return m_isResizable; } +private: + bool m_isResizable = false; +}; } // namespace lmms::gui diff --git a/plugins/SlicerT/SlicerT.cpp b/plugins/SlicerT/SlicerT.cpp index dcfbf6bc551..1365acb02f2 100644 --- a/plugins/SlicerT/SlicerT.cpp +++ b/plugins/SlicerT/SlicerT.cpp @@ -152,6 +152,7 @@ void SlicerT::playNote(NotePlayHandle* handle, SampleFrame* workingBuffer) void SlicerT::deleteNotePluginData(NotePlayHandle* handle) { delete static_cast(handle->m_pluginData); + emit isPlaying(-1, 0, 0); } // uses the spectral flux to determine the change in magnitude @@ -246,7 +247,7 @@ void SlicerT::findSlices() if (noteSnap == 0) { sliceLock = 1; } for (float& sliceValue : m_slicePoints) { - sliceValue += sliceLock / 2; + sliceValue += sliceLock / 2.; sliceValue -= static_cast(sliceValue) % sliceLock; } diff --git a/plugins/SlicerT/SlicerT.h b/plugins/SlicerT/SlicerT.h index 06b55687b4e..53b8bfb2a04 100644 --- a/plugins/SlicerT/SlicerT.h +++ b/plugins/SlicerT/SlicerT.h @@ -84,6 +84,8 @@ public slots: void findSlices(); void findBPM(); + QString getSampleName() { return m_originalSample.sampleFile(); } + QString nodeName() const override; gui::PluginView* instantiateView(QWidget* parent) override; diff --git a/plugins/SlicerT/SlicerTView.cpp b/plugins/SlicerT/SlicerTView.cpp index bbdb53ccbc2..2668018c816 100644 --- a/plugins/SlicerT/SlicerTView.cpp +++ b/plugins/SlicerT/SlicerTView.cpp @@ -26,14 +26,20 @@ #include #include +#include +#include +#include +#include +#include +#include #include "Clipboard.h" #include "DataFile.h" -#include "Engine.h" #include "InstrumentTrack.h" +#include "InstrumentView.h" +#include "PixmapButton.h" #include "SampleLoader.h" #include "SlicerT.h" -#include "Song.h" #include "StringPairDrag.h" #include "Track.h" #include "embed.h" @@ -43,57 +49,63 @@ namespace lmms { namespace gui { SlicerTView::SlicerTView(SlicerT* instrument, QWidget* parent) - : InstrumentViewFixedSize(instrument, parent) + : InstrumentView(instrument, parent) , m_slicerTParent(instrument) + , m_fullLogo(PLUGIN_NAME::getIconPixmap("full_logo")) + , m_background(PLUGIN_NAME::getIconPixmap("toolbox")) { // window settings setAcceptDrops(true); setAutoFillBackground(true); - // render background - QPalette pal; - pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); - setPalette(pal); + setMaximumSize(QSize(10000, 10000)); + setMinimumSize(QSize(516, 400)); + setResizable(true); m_wf = new SlicerTWaveform(248, 128, instrument, this); - m_wf->move(2, 6); + m_wf->move(0, s_topBarHeight); m_snapSetting = new ComboBox(this, tr("Slice snap")); m_snapSetting->setGeometry(185, 200, 55, ComboBox::DEFAULT_HEIGHT); m_snapSetting->setToolTip(tr("Set slice snapping for detection")); m_snapSetting->setModel(&m_slicerTParent->m_sliceSnap); - m_syncToggle = new LedCheckBox("Sync", this, tr("SyncToggle"), LedCheckBox::LedColor::Green); - m_syncToggle->move(135, 187); + m_syncToggle = new PixmapButton(this, tr("Sync sample")); + m_syncToggle->setActiveGraphic(PLUGIN_NAME::getIconPixmap("sync_active")); + m_syncToggle->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("sync_inactive")); + m_syncToggle->setCheckable(true); m_syncToggle->setToolTip(tr("Enable BPM sync")); m_syncToggle->setModel(&m_slicerTParent->m_enableSync); m_bpmBox = new LcdSpinBox(3, "19purple", this); - m_bpmBox->move(130, 201); m_bpmBox->setToolTip(tr("Original sample BPM")); m_bpmBox->setModel(&m_slicerTParent->m_originalBPM); m_noteThresholdKnob = createStyledKnob(); - m_noteThresholdKnob->move(10, 197); m_noteThresholdKnob->setToolTip(tr("Threshold used for slicing")); m_noteThresholdKnob->setModel(&m_slicerTParent->m_noteThreshold); m_fadeOutKnob = createStyledKnob(); - m_fadeOutKnob->move(64, 197); m_fadeOutKnob->setToolTip(tr("Fade Out per note in milliseconds")); m_fadeOutKnob->setModel(&m_slicerTParent->m_fadeOutFrames); m_midiExportButton = new QPushButton(this); - m_midiExportButton->move(199, 150); m_midiExportButton->setIcon(PLUGIN_NAME::getIconPixmap("copy_midi")); m_midiExportButton->setToolTip(tr("Copy midi pattern to clipboard")); connect(m_midiExportButton, &PixmapButton::clicked, this, &SlicerTView::exportMidi); + m_folderButton = new PixmapButton(this); + m_folderButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("folder_icon")); + m_folderButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("folder_icon")); + m_folderButton->setToolTip(tr("Open sample selector")); + connect(m_folderButton, &PixmapButton::clicked, this, &SlicerTView::openFiles); + m_resetButton = new QPushButton(this); - m_resetButton->move(18, 150); m_resetButton->setIcon(PLUGIN_NAME::getIconPixmap("reset_slices")); - m_resetButton->setToolTip(tr("Reset Slices")); + m_resetButton->setToolTip(tr("Reset slices")); connect(m_resetButton, &PixmapButton::clicked, m_slicerTParent, &SlicerT::updateSlices); + + update(); } Knob* SlicerTView::createStyledKnob() @@ -178,16 +190,101 @@ void SlicerTView::dropEvent(QDropEvent* de) void SlicerTView::paintEvent(QPaintEvent* pe) { QPainter brush(this); - brush.setPen(QColor(255, 255, 255)); brush.setFont(QFont(brush.font().family(), 7, -1, false)); - brush.drawText(8, s_topTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Reset")); - brush.drawText(188, s_topTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Midi")); + int boxTopY = height() - s_bottomBoxHeight; + + // --- backgrounds and limiters + brush.drawPixmap(QRect(0, boxTopY, s_leftBoxWidth, s_bottomBoxHeight), m_background); // left + brush.fillRect( + QRect(s_leftBoxWidth, boxTopY, width() - s_leftBoxWidth, s_bottomBoxHeight), QColor(23, 26, 31)); // right + brush.fillRect(QRect(0, 0, width(), s_topBarHeight), QColor(20, 23, 27)); // top + + // top bar dividers + brush.setPen(QColor(56, 58, 60)); + brush.drawLine(0, s_topBarHeight - 1, width(), s_topBarHeight - 1); + brush.drawLine(0, 0, width(), 0); + + // sample name divider + brush.setPen(QColor(56, 58, 60)); + brush.drawLine(0, boxTopY, width(), boxTopY); + + // boxes divider + brush.setPen(QColor(56, 24, 94)); + brush.drawLine(s_leftBoxWidth, boxTopY, s_leftBoxWidth, height()); + + // --- top bar + brush.drawPixmap( + QRect(10, (s_topBarHeight - m_fullLogo.height()) / 2, m_fullLogo.width(), m_fullLogo.height()), m_fullLogo); + + int y1_text = m_y1 + 27; + + // --- left box + brush.setPen(QColor(255, 255, 255)); + brush.drawText(s_x1 - 25, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Threshold")); + brush.drawText(s_x2 - 25, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Fade Out")); + brush.drawText(s_x3 - 25, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Reset")); + brush.drawText(s_x4 - 8, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Midi")); + brush.drawText(s_x5 - 16, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("BPM")); + brush.drawText(s_x6 - 8, y1_text, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Snap")); + + int kor = 15; // knob outer radius + int kir = 9; // knob inner radius + + // draw knob backgrounds + brush.setRenderHint(QPainter::Antialiasing); + + // draw outer radius 2 times to make smooth + brush.setPen(QPen(QColor(159, 124, 223, 100), 4)); + brush.drawArc(QRect(s_x1 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); + brush.drawArc(QRect(s_x2 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); + + brush.setPen(QPen(QColor(159, 124, 223, 255), 2)); + brush.drawArc(QRect(s_x1 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); + brush.drawArc(QRect(s_x2 - kor, m_y1, kor * 2, kor * 2), -45 * 16, 270 * 16); + + // inner knob circle + brush.setBrush(QColor(106, 90, 138)); + brush.setPen(QColor(0, 0, 0, 0)); + brush.drawEllipse(QPoint(s_x1, m_y1 + 15), kir, kir); + brush.drawEllipse(QPoint(s_x2, m_y1 + 15), kir, kir); + + // current sample bar + brush.fillRect(QRect(0, boxTopY - s_sampleBoxHeight, width(), s_sampleBoxHeight), QColor(5, 5, 5)); + + brush.setPen(QColor(56, 58, 60)); + brush.drawLine(width() - 24, boxTopY - s_sampleBoxHeight, width() - 24, boxTopY); + + brush.setPen(QColor(255, 255, 255, 180)); + brush.setFont(QFont(brush.font().family(), 8, -1, false)); + QString sampleName = m_slicerTParent->getSampleName(); + if (sampleName == "") { sampleName = "No sample loaded"; } + + brush.drawText(5, boxTopY - s_sampleBoxHeight, width(), s_sampleBoxHeight, Qt::AlignLeft, sampleName); +} + +void SlicerTView::resizeEvent(QResizeEvent* re) +{ + m_y1 = height() - s_bottomBoxOffset; + + // left box + m_noteThresholdKnob->move(s_x1 - 25, m_y1); + m_fadeOutKnob->move(s_x2 - 25, m_y1); + + m_resetButton->move(s_x3 - 15, m_y1 + 3); + m_midiExportButton->move(s_x4 + 2, m_y1 + 3); + + m_bpmBox->move(s_x5 - 13, m_y1 + 4); + m_snapSetting->move(s_x6 - 8, m_y1 + 3); + + // right box + m_syncToggle->move((width() - 100), m_y1 + 5); + + m_folderButton->move(width() - 20, height() - s_bottomBoxHeight - s_sampleBoxHeight + 1); + + int waveFormHeight = height() - s_bottomBoxHeight - s_topBarHeight - s_sampleBoxHeight; - brush.drawText(8, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Threshold")); - brush.drawText(63, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Fade Out")); - brush.drawText(127, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("BPM")); - brush.drawText(188, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Snap")); + m_wf->resize(width(), waveFormHeight); } } // namespace gui diff --git a/plugins/SlicerT/SlicerTView.h b/plugins/SlicerT/SlicerTView.h index ea2b979fc42..83ee2965252 100644 --- a/plugins/SlicerT/SlicerTView.h +++ b/plugins/SlicerT/SlicerTView.h @@ -26,9 +26,9 @@ #define LMMS_GUI_SLICERT_VIEW_H #include +#include #include "ComboBox.h" -#include "Instrument.h" #include "InstrumentView.h" #include "Knob.h" #include "LcdSpinBox.h" @@ -42,7 +42,7 @@ class SlicerT; namespace gui { -class SlicerTView : public InstrumentViewFixedSize +class SlicerTView : public InstrumentView { Q_OBJECT @@ -55,14 +55,29 @@ public slots: static constexpr int s_textBoxHeight = 20; static constexpr int s_textBoxWidth = 50; - static constexpr int s_topTextY = 170; - static constexpr int s_bottomTextY = 220; + static constexpr int s_topBarHeight = 50; + static constexpr int s_bottomBoxHeight = 97; + static constexpr int s_bottomBoxOffset = 65; + static constexpr int s_sampleBoxHeight = 14; + static constexpr int s_folderButtonWidth = 15; + static constexpr int s_leftBoxWidth = 400; + + + static constexpr int s_x1 = 35; + static constexpr int s_x2 = 85; + static constexpr int s_x3 = 160; + static constexpr int s_x4 = 190; + static constexpr int s_x5 = 275; + static constexpr int s_x6 = 325; protected: - virtual void dragEnterEvent(QDragEnterEvent* dee); - virtual void dropEvent(QDropEvent* de); + void dragEnterEvent(QDragEnterEvent* dee) override; + void dropEvent(QDropEvent* de) override; - virtual void paintEvent(QPaintEvent* pe); + void paintEvent(QPaintEvent* pe) override; + /* QSize sizeHint() const override { return QSize(150, 150); } */ + /* QSize minimumSizeHint() const override { return QSize(300, 300); } */ + void resizeEvent(QResizeEvent* event) override; private: SlicerT* m_slicerTParent; @@ -71,7 +86,8 @@ public slots: Knob* m_fadeOutKnob; LcdSpinBox* m_bpmBox; ComboBox* m_snapSetting; - LedCheckBox* m_syncToggle; + PixmapButton* m_syncToggle; + PixmapButton* m_folderButton; QPushButton* m_resetButton; QPushButton* m_midiExportButton; @@ -79,6 +95,13 @@ public slots: SlicerTWaveform* m_wf; Knob* createStyledKnob(); + + QPixmap m_fullLogo; + QPixmap m_background; + + + int m_y1; + int m_y2; }; } // namespace gui } // namespace lmms diff --git a/plugins/SlicerT/SlicerTWaveform.cpp b/plugins/SlicerT/SlicerTWaveform.cpp index 808b81c399b..17fab42e220 100644 --- a/plugins/SlicerT/SlicerTWaveform.cpp +++ b/plugins/SlicerT/SlicerTWaveform.cpp @@ -25,6 +25,7 @@ #include "SlicerTWaveform.h" #include +#include #include "SampleWaveform.h" #include "SlicerT.h" @@ -35,43 +36,52 @@ namespace lmms { namespace gui { +// waveform colors static QColor s_emptyColor = QColor(0, 0, 0, 0); -static QColor s_waveformColor = QColor(123, 49, 212); -static QColor s_waveformBgColor = QColor(255, 255, 255, 0); -static QColor s_waveformMaskColor = QColor(151, 65, 255); // update this if s_waveformColor changes -static QColor s_waveformInnerColor = QColor(183, 124, 255); - -static QColor s_playColor = QColor(255, 255, 255, 200); -static QColor s_playHighlightColor = QColor(255, 255, 255, 70); - -static QColor s_sliceColor = QColor(218, 193, 255); -static QColor s_sliceShadowColor = QColor(136, 120, 158); -static QColor s_sliceHighlightColor = QColor(255, 255, 255); - -static QColor s_seekerColor = QColor(178, 115, 255); -static QColor s_seekerHighlightColor = QColor(178, 115, 255, 100); -static QColor s_seekerShadowColor = QColor(0, 0, 0, 120); +static QColor s_waveformColor = QColor(123, 49, 212); // color of outer waveform +static QColor s_waveformSeekerBgColor = QColor(0, 0, 0, 255); +static QColor s_waveformEditorBgColor = QColor(15, 15, 15, 255); +static QColor s_waveformMaskColor = QColor(151, 65, 255); // update this if s_waveformColor changes +static QColor s_waveformInnerColor = QColor(183, 124, 255); // color of inner waveform + +// now playing colors +static QColor s_playColor = QColor(255, 255, 255, 200); // now playing line +static QColor s_playHighlightColor = QColor(255, 255, 255, 70); // now playing note marker + +// slice markers +static QColor s_sliceColor = QColor(218, 193, 255); // color of slice marker +static QColor s_sliceShadowColor = QColor(136, 120, 158); // color of dark side of slice marker +static QColor s_sliceHighlightColor = QColor(255, 255, 255); // color of highlighted slice marker + +// seeker rect colors +static QColor s_seekerColor = QColor(178, 115, 255); // outline of seeker +static QColor s_seekerHighlightColor = QColor(178, 115, 255, 100); // inside of seeker +static QColor s_seekerShadowColor = QColor(0, 0, 0, 120); // color used for darkening outside seeker + +// decor colors +static QColor s_editorBounding = QColor(53, 22, 90); // color of the editor bounding box +static QColor s_gradientEnd = QColor(29, 16, 47); // end color of the seeker gradient SlicerTWaveform::SlicerTWaveform(int totalWidth, int totalHeight, SlicerT* instrument, QWidget* parent) : QWidget(parent) , m_width(totalWidth) , m_height(totalHeight) + , m_seekerHeight(40) , m_seekerWidth(totalWidth - s_seekerHorMargin * 2) - , m_editorHeight(totalHeight - s_seekerHeight - s_middleMargin) + , m_editorHeight(totalHeight - m_seekerHeight - s_middleMargin - s_seekerVerMargin) , m_editorWidth(totalWidth) , m_sliceArrow(PLUGIN_NAME::getIconPixmap("slice_indicator_arrow")) - , m_seeker(QPixmap(m_seekerWidth, s_seekerHeight)) - , m_seekerWaveform(QPixmap(m_seekerWidth, s_seekerHeight)) - , m_editorWaveform(QPixmap(m_editorWidth, m_editorHeight)) + , m_seeker(QPixmap(m_seekerWidth, m_seekerHeight)) + , m_seekerWaveform(QPixmap(m_seekerWidth, m_seekerHeight)) + , m_editorWaveform(QPixmap(m_editorWidth, m_editorHeight - s_arrowHeight)) , m_sliceEditor(QPixmap(totalWidth, m_editorHeight)) , m_emptySampleIcon(embed::getIconPixmap("sample_track")) , m_slicerTParent(instrument) { - setFixedSize(m_width, m_height); setMouseTracking(true); - m_seekerWaveform.fill(s_waveformBgColor); - m_editorWaveform.fill(s_waveformBgColor); + m_seekerWaveform.fill(s_waveformSeekerBgColor); + m_editorWaveform.fill(s_waveformEditorBgColor); connect(instrument, &SlicerT::isPlaying, this, &SlicerTWaveform::isPlaying); connect(instrument, &SlicerT::dataChanged, this, &SlicerTWaveform::updateUI); @@ -82,15 +92,31 @@ SlicerTWaveform::SlicerTWaveform(int totalWidth, int totalHeight, SlicerT* instr updateUI(); } +void SlicerTWaveform::resizeEvent(QResizeEvent* event) +{ + m_width = width(); + m_height = height(); + m_seekerWidth = m_width - s_seekerHorMargin * 2; + /* m_seekerHeight = m_height * 0.33f; */ + m_editorWidth = m_width; + m_editorHeight = m_height - m_seekerHeight - s_middleMargin - s_seekerVerMargin; + + m_seeker = QPixmap(m_seekerWidth, m_seekerHeight); + m_seekerWaveform = QPixmap(m_seekerWidth, m_seekerHeight); + m_editorWaveform = QPixmap(m_editorWidth, m_editorHeight - s_arrowHeight); + m_sliceEditor = QPixmap(m_width, m_editorHeight); + updateUI(); +} void SlicerTWaveform::drawSeekerWaveform() { - m_seekerWaveform.fill(s_waveformBgColor); + m_seekerWaveform.fill(s_emptyColor); if (m_slicerTParent->m_originalSample.sampleSize() <= 1) { return; } QPainter brush(&m_seekerWaveform); brush.setPen(s_waveformColor); const auto& sample = m_slicerTParent->m_originalSample; - const auto waveform = SampleWaveform::Parameters{sample.data(), sample.sampleSize(), sample.amplification(), sample.reversed()}; + const auto waveform + = SampleWaveform::Parameters{sample.data(), sample.sampleSize(), sample.amplification(), sample.reversed()}; const auto rect = QRect(0, 0, m_seekerWaveform.width(), m_seekerWaveform.height()); SampleWaveform::visualize(waveform, brush, rect); @@ -102,15 +128,16 @@ void SlicerTWaveform::drawSeekerWaveform() void SlicerTWaveform::drawSeeker() { - m_seeker.fill(s_emptyColor); + m_seeker.fill(s_waveformSeekerBgColor); if (m_slicerTParent->m_originalSample.sampleSize() <= 1) { return; } QPainter brush(&m_seeker); + brush.drawPixmap(0, 0, m_seekerWaveform); brush.setPen(s_sliceColor); for (float sliceValue : m_slicerTParent->m_slicePoints) { float xPos = sliceValue * m_seekerWidth; - brush.drawLine(xPos, 0, xPos, s_seekerHeight); + brush.drawLine(xPos, 0, xPos, m_seekerHeight); } float seekerStartPosX = m_seekerStart * m_seekerWidth; @@ -122,16 +149,16 @@ void SlicerTWaveform::drawSeeker() float noteEndPosX = (m_noteEnd - m_noteStart) * m_seekerWidth; brush.setPen(s_playColor); - brush.drawLine(noteCurrentPosX, 0, noteCurrentPosX, s_seekerHeight); - brush.fillRect(noteStartPosX, 0, noteEndPosX, s_seekerHeight, s_playHighlightColor); + brush.drawLine(noteCurrentPosX, 0, noteCurrentPosX, m_seekerHeight); + brush.fillRect(noteStartPosX, 0, noteEndPosX, m_seekerHeight, s_playHighlightColor); - brush.fillRect(seekerStartPosX, 0, seekerMiddleWidth - 1, s_seekerHeight, s_seekerHighlightColor); + brush.fillRect(seekerStartPosX, 0, seekerMiddleWidth - 1, m_seekerHeight, s_seekerHighlightColor); - brush.fillRect(0, 0, seekerStartPosX, s_seekerHeight, s_seekerShadowColor); - brush.fillRect(seekerEndPosX - 1, 0, m_seekerWidth, s_seekerHeight, s_seekerShadowColor); + brush.fillRect(0, 0, seekerStartPosX, m_seekerHeight, s_seekerShadowColor); + brush.fillRect(seekerEndPosX - 1, 0, m_seekerWidth, m_seekerHeight, s_seekerShadowColor); brush.setPen(QPen(s_seekerColor, 1)); - brush.drawRect(seekerStartPosX, 0, seekerMiddleWidth - 1, s_seekerHeight - 1); // -1 needed + brush.drawRoundedRect(seekerStartPosX, 0, seekerMiddleWidth - 1, m_seekerHeight - 1, 2, 2); } void SlicerTWaveform::drawEditorWaveform() @@ -147,7 +174,8 @@ void SlicerTWaveform::drawEditorWaveform() float zoomOffset = (m_editorHeight - m_zoomLevel * m_editorHeight) / 2; const auto& sample = m_slicerTParent->m_originalSample; - const auto waveform = SampleWaveform::Parameters{sample.data() + startFrame, endFrame - startFrame, sample.amplification(), sample.reversed()}; + const auto waveform = SampleWaveform::Parameters{ + sample.data() + startFrame, endFrame - startFrame, sample.amplification(), sample.reversed()}; const auto rect = QRect(0, zoomOffset, m_editorWidth, m_zoomLevel * m_editorHeight); SampleWaveform::visualize(waveform, brush, rect); @@ -159,7 +187,7 @@ void SlicerTWaveform::drawEditorWaveform() void SlicerTWaveform::drawEditor() { - m_sliceEditor.fill(s_waveformBgColor); + m_sliceEditor.fill(s_waveformEditorBgColor); QPainter brush(&m_sliceEditor); // No sample loaded @@ -185,13 +213,16 @@ void SlicerTWaveform::drawEditor() float noteLength = (m_noteEnd - m_noteStart) / (m_seekerEnd - m_seekerStart) * m_editorWidth; brush.setPen(s_playHighlightColor); - brush.drawLine(0, m_editorHeight / 2, m_editorWidth, m_editorHeight / 2); + int middleY = m_editorHeight / 2 + s_arrowHeight; + brush.drawLine(0, middleY, m_editorWidth, middleY); + + brush.drawPixmap(0, s_arrowHeight, m_editorWaveform); - brush.drawPixmap(0, 0, m_editorWaveform); + brush.fillRect(0, 0, m_editorWidth, s_arrowHeight, s_waveformSeekerBgColor); brush.setPen(s_playColor); - brush.drawLine(noteCurrentPos, 0, noteCurrentPos, m_editorHeight); - brush.fillRect(noteStartPos, 0, noteLength, m_editorHeight, s_playHighlightColor); + brush.drawLine(noteCurrentPos, s_arrowHeight, noteCurrentPos, m_editorHeight); + brush.fillRect(noteStartPos, s_arrowHeight, noteLength, m_editorHeight, s_playHighlightColor); brush.setPen(QPen(s_sliceColor, 2)); @@ -215,6 +246,11 @@ void SlicerTWaveform::drawEditor() brush.drawPixmap(xPos - m_sliceArrow.width() / 2.0f, 0, m_sliceArrow); } } + + // decor + brush.setPen(s_editorBounding); + brush.drawLine(0, s_arrowHeight, m_editorWidth, s_arrowHeight); + brush.drawLine(0, m_editorHeight - 1, m_editorWidth, m_editorHeight - 1); } void SlicerTWaveform::isPlaying(float current, float start, float end) @@ -248,7 +284,7 @@ void SlicerTWaveform::updateClosest(QMouseEvent* me) m_closestObject = UIObjects::Nothing; m_closestSlice = -1; - if (me->y() < s_seekerHeight) + if (me->y() < m_seekerHeight) { if (std::abs(normalizedClickSeeker - m_seekerStart) < s_distanceForClick) { @@ -394,7 +430,7 @@ void SlicerTWaveform::mouseMoveEvent(QMouseEvent* me) void SlicerTWaveform::mouseDoubleClickEvent(QMouseEvent* me) { - if (me->button() != Qt::MouseButton::LeftButton) { return; } + if (me->button() != Qt::MouseButton::LeftButton || me->y() < m_seekerHeight) { return; } float normalizedClickEditor = static_cast(me->x()) / m_editorWidth; float startFrame = m_seekerStart; @@ -416,9 +452,27 @@ void SlicerTWaveform::wheelEvent(QWheelEvent* we) void SlicerTWaveform::paintEvent(QPaintEvent* pe) { QPainter p(this); - p.drawPixmap(s_seekerHorMargin, 0, m_seekerWaveform); - p.drawPixmap(s_seekerHorMargin, 0, m_seeker); - p.drawPixmap(0, s_seekerHeight + s_middleMargin, m_sliceEditor); + + // top gradient + QLinearGradient bgGrad(QPointF(0, 0), QPointF(width(), height() - m_editorHeight)); + bgGrad.setColorAt(0, s_waveformEditorBgColor); + bgGrad.setColorAt(1, s_gradientEnd); + + p.setBrush(bgGrad); + p.setPen(s_emptyColor); + p.drawRect(QRect(0, 0, width(), height())); + p.setBrush(QBrush()); + + // seeker + QPainterPath path; + path.addRoundedRect( + QRect(s_seekerHorMargin - 2, s_seekerVerMargin - 2, m_seekerWidth + 4, m_seekerHeight + 4), 4, 4); + p.fillPath(path, s_seekerShadowColor); + p.drawPixmap(s_seekerHorMargin, s_seekerVerMargin, m_seeker); + + // editor + p.setPen(QColor(s_waveformColor)); + p.drawPixmap(0, m_seekerHeight + s_middleMargin + s_seekerVerMargin, m_sliceEditor); } } // namespace gui } // namespace lmms diff --git a/plugins/SlicerT/SlicerTWaveform.h b/plugins/SlicerT/SlicerTWaveform.h index 6478e7f8684..d22e83f5eaa 100644 --- a/plugins/SlicerT/SlicerTWaveform.h +++ b/plugins/SlicerT/SlicerTWaveform.h @@ -32,9 +32,6 @@ #include #include -#include "Instrument.h" -#include "SampleBuffer.h" - namespace lmms { class SlicerT; @@ -54,8 +51,9 @@ public slots: // predefined sizes static constexpr int s_seekerHorMargin = 5; - static constexpr int s_seekerHeight = 38; // used to calcualte all vertical sizes + static constexpr int s_seekerVerMargin = 6; static constexpr int s_middleMargin = 6; + static constexpr int s_arrowHeight = 5; // interaction behavior values static constexpr float s_distanceForClick = 0.02f; @@ -80,11 +78,13 @@ public slots: void wheelEvent(QWheelEvent* we) override; void paintEvent(QPaintEvent* pe) override; + void resizeEvent(QResizeEvent* event) override; private: int m_width; int m_height; + int m_seekerHeight; // used to calcualte all vertical sizes int m_seekerWidth; int m_editorHeight; int m_editorWidth; diff --git a/plugins/SlicerT/artwork.png b/plugins/SlicerT/artwork.png deleted file mode 100644 index e166273c705..00000000000 Binary files a/plugins/SlicerT/artwork.png and /dev/null differ diff --git a/plugins/SlicerT/folder_icon.png b/plugins/SlicerT/folder_icon.png new file mode 100644 index 00000000000..4dd60c8ff26 Binary files /dev/null and b/plugins/SlicerT/folder_icon.png differ diff --git a/plugins/SlicerT/full_logo.png b/plugins/SlicerT/full_logo.png new file mode 100644 index 00000000000..aa8c1d26a00 Binary files /dev/null and b/plugins/SlicerT/full_logo.png differ diff --git a/plugins/SlicerT/sync_active.png b/plugins/SlicerT/sync_active.png new file mode 100644 index 00000000000..9db13c7944e Binary files /dev/null and b/plugins/SlicerT/sync_active.png differ diff --git a/plugins/SlicerT/sync_inactive.png b/plugins/SlicerT/sync_inactive.png new file mode 100644 index 00000000000..573958de0a0 Binary files /dev/null and b/plugins/SlicerT/sync_inactive.png differ diff --git a/plugins/SlicerT/toolbox.png b/plugins/SlicerT/toolbox.png new file mode 100644 index 00000000000..2b7c2a14c48 Binary files /dev/null and b/plugins/SlicerT/toolbox.png differ diff --git a/src/gui/EffectRackView.cpp b/src/gui/EffectRackView.cpp index eb8c6c43ea4..1f21c4b1916 100644 --- a/src/gui/EffectRackView.cpp +++ b/src/gui/EffectRackView.cpp @@ -216,14 +216,16 @@ void EffectRackView::update() } else { + ( *it )->resize(width() - 35, EffectView::DEFAULT_HEIGHT); ( *it )->move( EffectViewMargin, m_lastY ); + ( *it )->update(); m_lastY += ( *it )->height(); ++nView; ++it; } } - w->setFixedSize( EffectView::DEFAULT_WIDTH + 2*EffectViewMargin, m_lastY); + w->resize( width() - 35 + 2*EffectViewMargin, m_lastY); QWidget::update(); } diff --git a/src/gui/EffectView.cpp b/src/gui/EffectView.cpp index 6f2b984c32a..2200121ea17 100644 --- a/src/gui/EffectView.cpp +++ b/src/gui/EffectView.cpp @@ -52,8 +52,8 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_controlView(nullptr), m_dragging(false) { - setFixedSize(EffectView::DEFAULT_WIDTH, EffectView::DEFAULT_HEIGHT); - setFocusPolicy(Qt::StrongFocus); + /* resize(EffectView::DEFAULT_WIDTH, EffectView::DEFAULT_HEIGHT); */ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // TODO: Actual effect resizing // Disable effects that are of type "DummyEffect" bool isEnabled = !dynamic_cast( effect() ); diff --git a/src/gui/instrument/EnvelopeAndLfoView.cpp b/src/gui/instrument/EnvelopeAndLfoView.cpp index 1b639e6c326..0f1f47e638f 100644 --- a/src/gui/instrument/EnvelopeAndLfoView.cpp +++ b/src/gui/instrument/EnvelopeAndLfoView.cpp @@ -85,9 +85,11 @@ EnvelopeAndLfoView::EnvelopeAndLfoView(QWidget * parent) : envelopeLayout->addLayout(graphAndAmountLayout); m_envelopeGraph = new EnvelopeGraph(this); + m_envelopeGraph->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); graphAndAmountLayout->addWidget(m_envelopeGraph); m_amountKnob = buildKnob(tr("AMT"), tr("Modulation amount:")); + m_amountKnob->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); graphAndAmountLayout->addWidget(m_amountKnob, 0, Qt::AlignCenter); QHBoxLayout* envKnobsLayout = new QHBoxLayout(); diff --git a/src/gui/instrument/EnvelopeGraph.cpp b/src/gui/instrument/EnvelopeGraph.cpp index 4cf5da74bfa..3102c02a93e 100644 --- a/src/gui/instrument/EnvelopeGraph.cpp +++ b/src/gui/instrument/EnvelopeGraph.cpp @@ -211,8 +211,8 @@ void EnvelopeGraph::paintEvent(QPaintEvent*) const QColor lineColor{ColorHelper::interpolateInRgb(noAmountColor, fullAmountColor, absAmount)}; // Determine the line width so that it scales with the widget - // Use the minimum value of the current width and height to compute it. - const qreal lineWidth = std::min(width(), height()) / 20.; + // Use the diagonal of the box to compute it + const qreal lineWidth = sqrt(width()*width() + height()*height()) / 80.; const QPen linePen{lineColor, lineWidth}; p.setPen(linePen); diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 1c9c93a09f9..6d48b8714dd 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -105,7 +105,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : connect( m_nameLineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( textChanged( const QString& ) ) ); - m_nameLineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred)); + m_nameLineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); nameAndChangeTrackLayout->addWidget(m_nameLineEdit, 1); @@ -118,7 +118,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // m_leftRightNav->setShortcuts(); nameAndChangeTrackLayout->addWidget(m_leftRightNav); - + nameAndChangeTrackWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); generalSettingsLayout->addWidget( nameAndChangeTrackWidget ); auto basicControlsLayout = new QGridLayout; @@ -238,8 +238,8 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : m_ssView = new InstrumentSoundShapingView( m_tabWidget ); // FUNC tab - auto instrumentFunctions = new QWidget(m_tabWidget); - auto instrumentFunctionsLayout = new QVBoxLayout(instrumentFunctions); + m_instrumentFunctionsView = new QWidget(m_tabWidget); + auto instrumentFunctionsLayout = new QVBoxLayout(m_instrumentFunctionsView); instrumentFunctionsLayout->setContentsMargins(5, 5, 5, 5); m_noteStackingView = new InstrumentFunctionNoteStackingView( &m_track->m_noteStacking ); m_arpeggioView = new InstrumentFunctionArpeggioView( &m_track->m_arpeggio ); @@ -259,21 +259,21 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : m_tabWidget->addTab(m_ssView, tr("Envelope, filter & LFO"), "env_lfo_tab", 1); - m_tabWidget->addTab(instrumentFunctions, tr("Chord stacking & arpeggio"), "func_tab", 2); + m_tabWidget->addTab(m_instrumentFunctionsView, tr("Chord stacking & arpeggio"), "func_tab", 2); m_tabWidget->addTab(m_effectView, tr("Effects"), "fx_tab", 3); m_tabWidget->addTab(m_midiView, tr("MIDI"), "midi_tab", 4); m_tabWidget->addTab(m_tuningView, tr("Tuning and transposition"), "tuning_tab", 5); - adjustTabSize(m_ssView); - adjustTabSize(instrumentFunctions); - // EffectRackView has sizeHint to be QSize(EffectRackView::DEFAULT_WIDTH, INSTRUMENT_HEIGHT - 4 - 1) - adjustTabSize(m_midiView); - adjustTabSize(m_tuningView); // setup piano-widget m_pianoView = new PianoView( this ); m_pianoView->setMinimumHeight( PIANO_HEIGHT ); m_pianoView->setMaximumHeight( PIANO_HEIGHT ); + // setup sizes and policies + generalSettingsWidget->setMaximumHeight(90); + generalSettingsWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + vlayout->addWidget( generalSettingsWidget ); // Use QWidgetItem explicitly to make the size hint change on instrument changes // QLayout::addWidget() uses QWidgetItemV2 with size hint caching @@ -281,13 +281,20 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : vlayout->addWidget( m_pianoView ); setModel( _itv->model() ); + updateInstrumentView(); + QMdiSubWindow* subWin = getGUI()->mainWindow()->addWindowedWidget( this ); Qt::WindowFlags flags = subWin->windowFlags(); - flags |= Qt::MSWindowsFixedSizeDialogHint; + if (!m_instrumentView->isResizable()) { + flags |= Qt::MSWindowsFixedSizeDialogHint; + // any better way than this? + } else { + subWin->setMaximumSize(m_instrumentView->maximumHeight() + 12, m_instrumentView->maximumWidth() + 208); + subWin->setMinimumSize( m_instrumentView->minimumWidth() + 12, m_instrumentView->minimumHeight() + 208); + } flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); - updateInstrumentView(); // Hide the Size and Maximize options from the system menu // since the dialog size is fixed. @@ -296,10 +303,18 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : systemMenu->actions().at( 4 )->setVisible( false ); // Maximize subWin->setWindowIcon( embed::getIconPixmap( "instrument_track" ) ); - subWin->setMinimumSize( subWin->size() ); subWin->hide(); } +void InstrumentTrackWindow::resizeEvent(QResizeEvent * event) { + /* m_instrumentView->resize(QSize(size().width()-1, maxHeight)); */ + adjustTabSize(m_instrumentView); + adjustTabSize(m_instrumentFunctionsView); + adjustTabSize(m_ssView); + adjustTabSize(m_effectView); + adjustTabSize(m_midiView); + adjustTabSize(m_tuningView); +} @@ -669,6 +684,13 @@ void InstrumentTrackWindow::viewInstrumentInDirection(int d) } Q_ASSERT(bringToFront); bringToFront->getInstrumentTrackWindow()->setFocus(); + Qt::WindowFlags flags = windowFlags(); + if (!m_instrumentView->isResizable()) { + flags |= Qt::MSWindowsFixedSizeDialogHint; + } else { + flags &= ~Qt::MSWindowsFixedSizeDialogHint; + } + setWindowFlags( flags ); } void InstrumentTrackWindow::viewNextInstrument() @@ -685,7 +707,8 @@ void InstrumentTrackWindow::adjustTabSize(QWidget *w) // "-1" : // in "TabWidget::addTab", under "Position tab's window", the widget is // moved up by 1 pixel - w->setMinimumSize(INSTRUMENT_WIDTH - 4, INSTRUMENT_HEIGHT - 4 - 1); + w->resize(width() - 4, height() - 180); + w->update(); } diff --git a/src/gui/instrument/InstrumentView.cpp b/src/gui/instrument/InstrumentView.cpp index fe2c04cfbcb..9b681b7964e 100644 --- a/src/gui/instrument/InstrumentView.cpp +++ b/src/gui/instrument/InstrumentView.cpp @@ -35,6 +35,7 @@ namespace lmms::gui InstrumentView::InstrumentView( Instrument * _Instrument, QWidget * _parent ) : PluginView( _Instrument, _parent ) { + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setModel( _Instrument ); setAttribute( Qt::WA_DeleteOnClose, true ); } @@ -44,6 +45,7 @@ InstrumentView::InstrumentView( Instrument * _Instrument, QWidget * _parent ) : InstrumentView::~InstrumentView() { + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); if( instrumentTrackWindow() ) { instrumentTrackWindow()->m_instrumentView = nullptr; @@ -76,4 +78,4 @@ InstrumentTrackWindow * InstrumentView::instrumentTrackWindow() -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui