diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 7e3c0d289..123370dc6 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -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; diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index ea20bb3a0..858ec131e 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -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 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; diff --git a/plugins/zynaddsubfx/fltk/fltk-config b/plugins/zynaddsubfx/fltk/fltk-config index 97ed9a514..f079deada 100755 --- a/plugins/zynaddsubfx/fltk/fltk-config +++ b/plugins/zynaddsubfx/fltk/fltk-config @@ -46,7 +46,7 @@ libdir=/usr/local/lib srcdir=. # compiler names -CC="gcc" +CC="cc" CXX="c++" # flags for C++ compiler: diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 1ce04941c..382f906fc 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -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 ) diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index f7a25ec7b..7129d199a 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -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(); m_maxLevel = m_pattern->firstObject()->maxValue(); m_step = m_pattern->firstObject()->step(); @@ -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 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 );