Skip to content

Commit

Permalink
Add sample ghost for automation
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielKauss committed Nov 16, 2023
1 parent 7735d59 commit 6921ce5
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 4 deletions.
1 change: 1 addition & 0 deletions data/themes/classic/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ lmms--gui--AutomationEditor {

qproperty-ghostNoteColor: rgba(248, 248, 255, 125);
qproperty-detuningNoteColor: rgba(248, 11, 11, 125);
qproperty-ghostSampleColor: rgba(125, 125, 125, 125);
}

/* text box */
Expand Down
1 change: 1 addition & 0 deletions data/themes/default/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ lmms--gui--AutomationEditor {
qproperty-scaleColor: #262b30;
qproperty-ghostNoteColor: rgba(248, 248, 255, 125);
qproperty-detuningNoteColor: rgba(248, 11, 11, 125);
qproperty-ghostSampleColor: rgba(125, 125, 125, 125);
}

/* text box */
Expand Down
10 changes: 10 additions & 0 deletions include/AutomationEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "Editor.h"
#include "JournallingObject.h"
#include "MidiClip.h"
#include "SampleClip.h"
#include "TimePos.h"
#include "lmms_basics.h"

Expand Down Expand Up @@ -71,9 +72,11 @@ class AutomationEditor : public QWidget, public JournallingObject
Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade)
Q_PROPERTY(QColor ghostNoteColor MEMBER m_ghostNoteColor)
Q_PROPERTY(QColor detuningNoteColor MEMBER m_detuningNoteColor)
Q_PROPERTY(QColor ghostSampleColor MEMBER m_ghostSampleColor)
public:
void setCurrentClip(AutomationClip * new_clip);
void setGhostMidiClip(MidiClip* newMidiClip);
void setGhostSample(SampleClip* newSample);

inline const AutomationClip * currentClip() const
{
Expand Down Expand Up @@ -166,6 +169,7 @@ protected slots:
void resetGhostNotes()
{
m_ghostNotes = nullptr;
m_ghostSample = nullptr;
update();
}

Expand Down Expand Up @@ -196,6 +200,8 @@ protected slots:
static const int NOTE_HEIGHT = 10; // height of individual notes
static const int NOTE_MARGIN = 40; // total border margin for notes
static const int MIN_NOTE_RANGE = 20; // min number of keys for fixed size
static const int SAMPLE_MARGIN = 40;
static const int MAX_SAMPLE_HEIGHT = 400;

AutomationEditor();
AutomationEditor( const AutomationEditor & );
Expand Down Expand Up @@ -226,6 +232,8 @@ protected slots:
float m_topLevel;

MidiClip* m_ghostNotes = nullptr;
QPointer<SampleClip> m_ghostSample = nullptr; // QPointer to set to nullptr on deletion
bool m_renderSample = false;

void centerTopBottomScroll();
void updateTopBottomLevels();
Expand Down Expand Up @@ -279,6 +287,7 @@ protected slots:
QColor m_backgroundShade;
QColor m_ghostNoteColor;
QColor m_detuningNoteColor;
QColor m_ghostSampleColor;

friend class AutomationEditorWindow;

Expand All @@ -303,6 +312,7 @@ class AutomationEditorWindow : public Editor

void setCurrentClip(AutomationClip* clip);
void setGhostMidiClip(MidiClip* clip) { m_editor->setGhostMidiClip(clip); };
void setGhostSample(SampleClip* newSample) { m_editor->setGhostSample(newSample); };

const AutomationClip* currentClip();

Expand Down
1 change: 1 addition & 0 deletions include/SampleClipView.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class SampleClipView : public ClipView
public slots:
void updateSample();
void reverseSample();
void setAutomationGhost();



Expand Down
16 changes: 16 additions & 0 deletions src/gui/clips/SampleClipView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <QMenu>
#include <QPainter>

#include "GuiApplication.h"
#include "AutomationEditor.h"
#include "embed.h"
#include "PathUtil.h"
#include "SampleBuffer.h"
Expand Down Expand Up @@ -83,6 +85,12 @@ void SampleClipView::constructContextMenu(QMenu* cm)
SLOT(reverseSample())
);

cm->addAction(
embed::getIconPixmap("automation_ghost_note"),
tr("Set as ghost in automation editor"),
this,
SLOT(setAutomationGhost())
);

}

Expand Down Expand Up @@ -325,6 +333,14 @@ void SampleClipView::reverseSample()



void SampleClipView::setAutomationGhost()
{
auto aEditor = gui::getGUI()->automationEditor();
aEditor->setGhostSample(m_clip);
aEditor->parentWidget()->show();
aEditor->show();
aEditor->setFocus();
}

//! Split this Clip.
/*! \param pos the position of the split, relative to the start of the clip */
Expand Down
35 changes: 31 additions & 4 deletions src/gui/editors/AutomationEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,32 @@
#include <QToolTip>
#include <cmath>

#include "SampleClip.h"

#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif

#include "ActionGroup.h"
#include "AutomationNode.h"
#include "ComboBox.h"
#include "debug.h"
#include "DeprecationHelper.h"
#include "DetuningHelper.h"
#include "embed.h"
#include "Engine.h"
#include "GuiApplication.h"
#include "gui_templates.h"
#include "Knob.h"
#include "MainWindow.h"
#include "MidiClip.h"
#include "PatternStore.h"
#include "PianoRoll.h"
#include "ProjectJournal.h"
#include "SampleBuffer.h"
#include "StringPairDrag.h"
#include "TextFloat.h"
#include "TimeLineWidget.h"
#include "debug.h"
#include "embed.h"
#include "gui_templates.h"


namespace lmms::gui
Expand Down Expand Up @@ -1080,6 +1083,14 @@ void AutomationEditor::setGhostMidiClip(MidiClip* newMidiClip)
{
// Expects a pointer to a MIDI clip or nullptr.
m_ghostNotes = newMidiClip;
m_renderSample = false;
}

void AutomationEditor::setGhostSample(SampleClip* newGhostSample)
{
// Expects a pointer to a Sample buffer or nullptr.
m_ghostSample = newGhostSample;
m_renderSample = true;
}

void AutomationEditor::paintEvent(QPaintEvent * pe )
Expand Down Expand Up @@ -1266,8 +1277,24 @@ void AutomationEditor::paintEvent(QPaintEvent * pe )
p.drawLine( x, grid_bottom, x, x_line_end );
}

// draw ghost sample
if (m_ghostSample != nullptr && m_ghostSample->sampleBuffer()->frames() > 1 && m_renderSample)
{
int sampleFrames = m_ghostSample->sampleBuffer()->frames();
int length = static_cast<float>(sampleFrames) / Engine::framesPerTick();
int editorHeight = grid_bottom - TOP_MARGIN;

int startPos = xCoordOfTick(0);
int sampleWidth = xCoordOfTick(length) - startPos;
int sampleHeight = std::min(editorHeight - SAMPLE_MARGIN, MAX_SAMPLE_HEIGHT);
int yOffset = (editorHeight - sampleHeight) / 2.0f + TOP_MARGIN;

p.setPen(m_ghostSampleColor);
m_ghostSample->sampleBuffer()->visualize(p, QRect(startPos, yOffset, sampleWidth, sampleHeight), 0, sampleFrames);
}

// draw ghost notes
if (m_ghostNotes != nullptr)
if (m_ghostNotes != nullptr && !m_renderSample)
{
const NoteVector& notes = m_ghostNotes->notes();
int minKey = 128;
Expand Down

0 comments on commit 6921ce5

Please sign in to comment.