Merge pull request #203 from wongcc966422/issue1

Automation points are now draggable
This commit is contained in:
Tobias Doerffel
2014-01-30 11:27:38 -08:00
5 changed files with 134 additions and 76 deletions

View File

@@ -34,6 +34,7 @@
#include "MidiTime.h"
#include "AutomationPattern.h"
#include "ComboBoxModel.h"
#include "knob.h"
class QPainter;
@@ -103,7 +104,7 @@ protected:
void getSelectedValues( timeMap & _selected_values );
void drawLine( int x0, float y0, int x1, float y1 );
void disableTensionComboBox();
void disableTensionKnob();
protected slots:
void play();
@@ -188,9 +189,8 @@ private:
toolButton * m_discreteButton;
toolButton * m_linearButton;
toolButton * m_cubicHermiteButton;
comboBox * m_tensionComboBox;
ComboBoxModel m_tensionModel;
ComboBoxModel m_tensionDisabledModel;
knob * m_tensionKnob;
FloatModel * m_tensionModel;
toolButton * m_cutButton;
toolButton * m_copyButton;

View File

@@ -66,7 +66,7 @@ public:
}
void setProgressionType( ProgressionTypes _new_progression_type );
inline QString getTension() const
inline float getTension() const
{
return m_tension;
}
@@ -77,7 +77,19 @@ public:
MidiTime putValue( const MidiTime & _time, const float _value,
const bool _quant_pos = true );
void removeValue( const MidiTime & _time );
void removeValue( const MidiTime & _time,
const bool _quant_pos = true );
MidiTime setDragValue( const MidiTime & _time, const float _value,
const bool _quant_pos = true );
void applyDragValue();
bool isDragging() const
{
return m_dragging;
}
inline const timeMap & getTimeMap() const
{
@@ -149,11 +161,14 @@ private:
QVector<jo_id_t> m_idsToResolve;
objectVector m_objects;
timeMap m_timeMap; // actual values
timeMap m_oldTimeMap; // old values for storing the values before setDragValue() is called.
timeMap m_tangents; // slope at each point for calculating spline
QString m_tension;
float m_tension;
bool m_hasAutomation;
ProgressionTypes m_progressionType;
bool m_dragging;
friend class AutomationPatternView;

View File

@@ -46,7 +46,7 @@ libdir=/usr/local/lib
srcdir=.
# compiler names
CC="gcc"
CC="cc"
CXX="c++"
# flags for C++ compiler:

View File

@@ -42,8 +42,9 @@ AutomationPattern::AutomationPattern( AutomationTrack * _auto_track ) :
trackContentObject( _auto_track ),
m_autoTrack( _auto_track ),
m_objects(),
m_tension( "1.0" ),
m_progressionType( DiscreteProgression )
m_tension( 1.0 ),
m_progressionType( DiscreteProgression ),
m_dragging( false )
{
changeLength( MidiTime( 1, 0 ) );
}
@@ -142,7 +143,7 @@ void AutomationPattern::setTension( QString _new_tension )
if( ok && nt > -0.01 && nt < 1.01 )
{
m_tension = _new_tension;
m_tension = _new_tension.toFloat();
}
}
@@ -215,13 +216,19 @@ MidiTime AutomationPattern::putValue( const MidiTime & _time,
void AutomationPattern::removeValue( const MidiTime & _time )
void AutomationPattern::removeValue( const MidiTime & _time,
const bool _quant_pos )
{
cleanObjects();
m_timeMap.remove( _time );
m_tangents.remove( _time );
timeMap::const_iterator it = m_timeMap.lowerBound( _time );
MidiTime newTime = _quant_pos && engine::automationEditor() ?
note::quantized( _time,
engine::automationEditor()->quantization() ) :
_time;
m_timeMap.remove( newTime );
m_tangents.remove( newTime );
timeMap::const_iterator it = m_timeMap.lowerBound( newTime );
if( it != m_timeMap.begin() )
{
it--;
@@ -240,6 +247,55 @@ void AutomationPattern::removeValue( const MidiTime & _time )
/**
* @brief Set the position of the point that is being draged.
* Calling this function will also automatically set m_dragging to true,
* which applyDragValue() have to be called to m_dragging.
* @param the time(x position) of the point being dragged
* @param the value(y position) of the point being dragged
* @param true to snip x position
* @return
*/
MidiTime AutomationPattern::setDragValue( const MidiTime & _time, const float _value,
const bool _quant_pos )
{
if( m_dragging == false )
{
MidiTime newTime = _quant_pos && engine::automationEditor() ?
note::quantized( _time,
engine::automationEditor()->quantization() ) :
_time;
this->removeValue( newTime );
m_oldTimeMap = m_timeMap;
m_dragging = true;
}
//Restore to the state before it the point were being dragged
m_timeMap = m_oldTimeMap;
for( timeMap::const_iterator it = m_timeMap.begin(); it != m_timeMap.end(); it++ )
{
generateTangents(it, 3);
}
return this->putValue( _time, _value, _quant_pos );
}
/**
* @brief After the point is dragged, this function is called to apply the change.
*/
void AutomationPattern::applyDragValue()
{
m_dragging = false;
}
float AutomationPattern::valueAt( const MidiTime & _time ) const
{
if( m_timeMap.isEmpty() )
@@ -291,10 +347,8 @@ float AutomationPattern::valueAt( timeMap::const_iterator v, int offset ) const
// tangents _m1 and _m2
int numValues = ((v+1).key() - v.key());
float t = (float) offset / (float) numValues;
float m1 = (m_tangents[v.key()]) * numValues
* m_tension.toFloat();
float m2 = (m_tangents[(v+1).key()]) * numValues
* m_tension.toFloat();
float m1 = (m_tangents[v.key()]) * numValues * m_tension;
float m2 = (m_tangents[(v+1).key()]) * numValues * m_tension;
return ( 2*pow(t,3) - 3*pow(t,2) + 1 ) * v.value()
+ ( pow(t,3) - 2*pow(t,2) + t) * m1
@@ -334,7 +388,7 @@ void AutomationPattern::saveSettings( QDomDocument & _doc, QDomElement & _this )
_this.setAttribute( "len", trackContentObject::length() );
_this.setAttribute( "name", name() );
_this.setAttribute( "prog", QString::number( progressionType() ) );
_this.setAttribute( "tens", getTension() );
_this.setAttribute( "tens", QString::number( getTension() ) );
for( timeMap::const_iterator it = m_timeMap.begin();
it != m_timeMap.end(); ++it )

View File

@@ -200,7 +200,8 @@ AutomationEditor::AutomationEditor() :
m_toolBar );
m_eraseButton->setCheckable( TRUE );
m_selectButton = new toolButton( embed::getIconPixmap(
//TODO: m_selectButton and m_moveButton are broken.
/*m_selectButton = new toolButton( embed::getIconPixmap(
"edit_select" ),
tr( "Select mode (Shift+S)" ),
this, SLOT( selectButtonToggled() ),
@@ -211,13 +212,13 @@ AutomationEditor::AutomationEditor() :
tr( "Move selection mode (Shift+M)" ),
this, SLOT( moveButtonToggled() ),
m_toolBar );
m_moveButton->setCheckable( TRUE );
m_moveButton->setCheckable( TRUE );*/
QButtonGroup * tool_button_group = new QButtonGroup( this );
tool_button_group->addButton( m_drawButton );
tool_button_group->addButton( m_eraseButton );
tool_button_group->addButton( m_selectButton );
tool_button_group->addButton( m_moveButton );
//tool_button_group->addButton( m_selectButton );
//tool_button_group->addButton( m_moveButton );
tool_button_group->setExclusive( TRUE );
m_drawButton->setWhatsThis(
@@ -230,7 +231,7 @@ AutomationEditor::AutomationEditor() :
tr( "Click here and erase-mode will be activated. In this "
"mode you can erase single values. You can also press "
"'Shift+E' on your keyboard to activate this mode." ) );
m_selectButton->setWhatsThis(
/*m_selectButton->setWhatsThis(
tr( "Click here and select-mode will be activated. In this "
"mode you can select values. This is necessary "
"if you want to cut, copy, paste, delete, or move "
@@ -240,7 +241,7 @@ AutomationEditor::AutomationEditor() :
tr( "If you click here, move-mode will be activated. In this "
"mode you can move the values you selected in select-"
"mode. You can also press 'Shift+M' on your keyboard "
"to activate this mode." ) );
"to activate this mode." ) );*/
m_discreteButton = new toolButton( embed::getIconPixmap(
"progression_discrete" ),
@@ -266,21 +267,13 @@ AutomationEditor::AutomationEditor() :
m_cubicHermiteButton->setCheckable( true );
// setup tension-stuff
m_tensionComboBox = new comboBox( m_toolBar );
m_tensionComboBox->setFixedSize( 60, 22 );
m_tensionKnob = new knob( knobSmall_17, this, "Tension" );
m_tensionModel = new FloatModel(1.0, 0.0, 1.0, 0.01);
connect( m_tensionModel, SIGNAL( dataChanged() ),
this, SLOT( tensionChanged() ) );
for( int i = 0; i < 4; ++i )
{
m_tensionModel.addItem( "0." + QString::number( 25 * i ) );
}
m_tensionModel.addItem( "1.0" );
m_tensionModel.setValue( m_tensionModel.findText( "1.0" ) );
m_tensionDisabledModel.addItem( "-----" );
disableTensionComboBox();
connect( &m_tensionModel, SIGNAL( dataChanged() ),
this, SLOT( tensionChanged() ) );
QLabel * tension_lbl = new QLabel( m_toolBar );
tension_lbl->setText( tr("Tension: ") );
tool_button_group = new QButtonGroup( this );
tool_button_group->addButton( m_discreteButton );
@@ -397,14 +390,16 @@ AutomationEditor::AutomationEditor() :
tb_layout->addSpacing( 10 );
tb_layout->addWidget( m_drawButton );
tb_layout->addWidget( m_eraseButton );
tb_layout->addWidget( m_selectButton );
tb_layout->addWidget( m_moveButton );
//tb_layout->addWidget( m_selectButton );
//tb_layout->addWidget( m_moveButton );
tb_layout->addSpacing( 10 );
tb_layout->addWidget( m_discreteButton );
tb_layout->addWidget( m_linearButton );
tb_layout->addWidget( m_cubicHermiteButton );
tb_layout->addSpacing( 5 );
tb_layout->addWidget( m_tensionComboBox );
tb_layout->addWidget( tension_lbl );
tb_layout->addSpacing( 5 );
tb_layout->addWidget( m_tensionKnob );
tb_layout->addSpacing( 10 );
tb_layout->addWidget( m_cutButton );
tb_layout->addWidget( m_copyButton );
@@ -456,7 +451,7 @@ AutomationEditor::~AutomationEditor()
{
m_zoomingXModel.disconnect();
m_zoomingYModel.disconnect();
m_tensionModel.disconnect();
m_tensionModel->disconnect();
}
@@ -548,8 +543,6 @@ void AutomationEditor::updateAfterPatternChange()
m_cubicHermiteButton->setChecked( true );
}
m_tensionModel.setValue( m_tensionModel.findText(
m_pattern->getTension() ) );
m_minLevel = m_pattern->firstObject()->minValue<float>();
m_maxLevel = m_pattern->firstObject()->maxValue<float>();
m_step = m_pattern->firstObject()->step<float>();
@@ -664,8 +657,8 @@ void AutomationEditor::keyPressEvent( QKeyEvent * _ke )
_ke->accept();
}
break;
case Qt::Key_A:
//TODO: m_selectButton and m_moveButton are broken.
/*case Qt::Key_A:
if( _ke->modifiers() & Qt::ControlModifier )
{
m_selectButton->setChecked( TRUE );
@@ -673,7 +666,7 @@ void AutomationEditor::keyPressEvent( QKeyEvent * _ke )
update();
_ke->accept();
}
break;
break;*/
case Qt::Key_D:
if( _ke->modifiers() & Qt::ShiftModifier )
@@ -690,8 +683,8 @@ void AutomationEditor::keyPressEvent( QKeyEvent * _ke )
_ke->accept();
}
break;
case Qt::Key_S:
//TODO: m_selectButton and m_moveButton are broken.
/*case Qt::Key_S:
if( _ke->modifiers() & Qt::ShiftModifier )
{
m_selectButton->setChecked( TRUE );
@@ -705,7 +698,7 @@ void AutomationEditor::keyPressEvent( QKeyEvent * _ke )
m_moveButton->setChecked( TRUE );
_ke->accept();
}
break;
break;*/
case Qt::Key_Delete:
deleteSelectedValues();
@@ -800,14 +793,9 @@ void AutomationEditor::drawLine( int _x0, float _y0, int _x1, float _y1 )
void AutomationEditor::disableTensionComboBox()
void AutomationEditor::disableTensionKnob()
{
m_tensionComboBox->setEnabled( false );
m_tensionComboBox->setModel( &m_tensionDisabledModel );
m_tensionComboBox->setToolTip(
tr( "Choose Cubic Hermite progression to enable" ) );
m_tensionComboBox->setWhatsThis(
tr( "Choose Cubic Hermite progression to enable" ) );
m_tensionKnob->setEnabled( false );
}
@@ -884,7 +872,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me )
MidiTime value_pos( pos_ticks );
MidiTime new_time =
m_pattern->putValue( value_pos,
m_pattern->setDragValue( value_pos,
level );
// reset it so that it can be used for
@@ -916,6 +904,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me )
m_pattern->removeValue( it.key() );
engine::getSong()->setModified();
}
m_action = NONE;
}
else if( _me->button() == Qt::LeftButton &&
m_editMode == SELECT )
@@ -966,17 +955,21 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me )
void AutomationEditor::mouseReleaseEvent( QMouseEvent * _me )
{
m_action = NONE;
if( m_editMode == DRAW )
{
if( m_action == MOVE_VALUE )
{
m_pattern->applyDragValue();
}
QApplication::restoreOverrideCursor();
}
m_action = NONE;
}
#include <stdio.h>
void AutomationEditor::mouseMoveEvent( QMouseEvent * _me )
{
QMutexLocker m( &m_patternMutex );
@@ -1016,15 +1009,14 @@ void AutomationEditor::mouseMoveEvent( QMouseEvent * _me )
drawLine( m_drawLastTick, m_drawLastLevel,
pos_ticks, level );
m_drawLastTick = pos_ticks;
m_drawLastLevel = level;
// we moved the value so the value has to be
// moved properly according to new starting-
// time in the time map of pattern
m_pattern->removeValue(
MidiTime( pos_ticks ) );
m_pattern->putValue( MidiTime( pos_ticks ),
m_pattern->setDragValue( MidiTime( pos_ticks ),
level );
}
@@ -1992,7 +1984,7 @@ void AutomationEditor::discreteButtonToggled()
if ( validPattern() )
{
QMutexLocker m( &m_patternMutex );
disableTensionComboBox();
disableTensionKnob();
m_pattern->setProgressionType(
AutomationPattern::DiscreteProgression );
engine::getSong()->setModified();
@@ -2008,7 +2000,7 @@ void AutomationEditor::linearButtonToggled()
if ( validPattern() )
{
QMutexLocker m( &m_patternMutex );
disableTensionComboBox();
disableTensionKnob();
m_pattern->setProgressionType(
AutomationPattern::LinearProgression );
engine::getSong()->setModified();
@@ -2023,12 +2015,10 @@ void AutomationEditor::cubicHermiteButtonToggled()
{
if ( validPattern() )
{
QMutexLocker m( &m_patternMutex );
m_tensionComboBox->setEnabled( true );
m_tensionComboBox->setModel( &m_tensionModel );
m_tensionComboBox->setToolTip(
tr( "Tension value for spline" ) );
m_tensionComboBox->setWhatsThis(
m_tensionKnob->setModel( m_tensionModel );
m_tensionKnob->setEnabled( true );
toolTip::add( m_tensionKnob, tr( "Tension value for spline" ) );
m_tensionKnob->setWhatsThis(
tr( "A higher tension value may make a smoother curve "
"but overshoot some values. A low tension "
"value will cause the slope of the curve to "
@@ -2045,13 +2035,12 @@ void AutomationEditor::cubicHermiteButtonToggled()
void AutomationEditor::tensionChanged()
{
m_pattern->setTension( m_tensionModel.currentText() );
m_pattern->setTension( QString::number( m_tensionModel->value() ) );
update();
}
void AutomationEditor::selectAll()
{
QMutexLocker m( &m_patternMutex );