Merge pull request #720 from diizy/master
Initial implementation for two additional methods in AutomatableModel, A...
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "Model.h"
|
||||
#include "MidiTime.h"
|
||||
|
||||
|
||||
// simple way to map a property of a view to a model
|
||||
@@ -239,6 +240,7 @@ public:
|
||||
return m_hasLinkedModels;
|
||||
}
|
||||
|
||||
float globalAutomationValueAt( const MidiTime& time );
|
||||
|
||||
public slots:
|
||||
virtual void reset();
|
||||
|
||||
@@ -152,6 +152,7 @@ public:
|
||||
|
||||
|
||||
static bool isAutomated( const AutomatableModel * _m );
|
||||
static QVector<AutomationPattern *> patternsForModel( const AutomatableModel * _m );
|
||||
static AutomationPattern * globalAutomationPattern( AutomatableModel * _m );
|
||||
static void resolveAllIDs();
|
||||
|
||||
|
||||
@@ -555,6 +555,70 @@ void AutomatableModel::pasteValue()
|
||||
|
||||
|
||||
|
||||
float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
|
||||
{
|
||||
// get patterns that connect to this model
|
||||
QVector<AutomationPattern *> patterns = AutomationPattern::patternsForModel( this );
|
||||
if( patterns.isEmpty() )
|
||||
{
|
||||
// if no such patterns exist, return current value
|
||||
return m_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// of those patterns:
|
||||
// find the patterns which overlap with the miditime position
|
||||
QVector<AutomationPattern *> patterns_in_range;
|
||||
for( QVector<AutomationPattern *>::ConstIterator it = patterns.begin(); it != patterns.end(); it++ )
|
||||
{
|
||||
int s = ( *it )->startPosition();
|
||||
int e = ( *it )->endPosition();
|
||||
if( s <= time && e >= time ) { patterns_in_range += ( *it ); }
|
||||
}
|
||||
|
||||
AutomationPattern * latest_pattern = NULL;
|
||||
|
||||
if( ! patterns_in_range.isEmpty() )
|
||||
{
|
||||
// if there are more than one overlapping patterns, just use the first one because
|
||||
// multiple pattern behaviour is undefined anyway
|
||||
latest_pattern = patterns_in_range[0];
|
||||
}
|
||||
else
|
||||
// if we find no patterns at the exact miditime, we need to search for the last pattern before time and use that
|
||||
{
|
||||
int latest_position = 0;
|
||||
|
||||
for( QVector<AutomationPattern *>::ConstIterator it = patterns.begin(); it != patterns.end(); it++ )
|
||||
{
|
||||
int e = ( *it )->endPosition();
|
||||
if( e <= time && e > latest_position )
|
||||
{
|
||||
latest_position = e;
|
||||
latest_pattern = ( *it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( latest_pattern )
|
||||
{
|
||||
// scale/fit the value appropriately and return it
|
||||
const float value = latest_pattern->valueAt( time );
|
||||
const float scaled_value =
|
||||
( m_scaleType == Linear )
|
||||
? value
|
||||
: logToLinearScale(
|
||||
// fits value into [0,1]:
|
||||
(value - minValue<float>()) / maxValue<float>()
|
||||
);
|
||||
return fittedValue( scaled_value );
|
||||
}
|
||||
// if we still find no pattern, the value at that time is undefined so
|
||||
// just return current value as the best we can do
|
||||
else return m_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "moc_AutomatableModel.cxx"
|
||||
|
||||
|
||||
@@ -551,6 +551,51 @@ bool AutomationPattern::isAutomated( const AutomatableModel * _m )
|
||||
}
|
||||
|
||||
|
||||
/*! \brief returns a list of all the automation patterns everywhere that are connected to a specific model
|
||||
* \param _m the model we want to look for
|
||||
*/
|
||||
QVector<AutomationPattern *> AutomationPattern::patternsForModel( const AutomatableModel * _m )
|
||||
{
|
||||
QVector<AutomationPattern *> patterns;
|
||||
TrackContainer::TrackList l;
|
||||
l += engine::getSong()->tracks();
|
||||
l += engine::getBBTrackContainer()->tracks();
|
||||
l += engine::getSong()->globalAutomationTrack();
|
||||
|
||||
// go through all tracks...
|
||||
for( TrackContainer::TrackList::ConstIterator it = l.begin(); it != l.end(); ++it )
|
||||
{
|
||||
// we want only automation tracks...
|
||||
if( ( *it )->type() == track::AutomationTrack ||
|
||||
( *it )->type() == track::HiddenAutomationTrack )
|
||||
{
|
||||
// get patterns in those tracks....
|
||||
const track::tcoVector & v = ( *it )->getTCOs();
|
||||
// go through all the patterns...
|
||||
for( track::tcoVector::ConstIterator j = v.begin(); j != v.end(); ++j )
|
||||
{
|
||||
AutomationPattern * a = dynamic_cast<AutomationPattern *>( *j );
|
||||
// check that the pattern has automation
|
||||
if( a && a->hasAutomation() )
|
||||
{
|
||||
// now check is the pattern is connected to the model we want by going through all the connections
|
||||
// of the pattern
|
||||
bool has_object = false;
|
||||
for( objectVector::const_iterator k = a->m_objects.begin(); k != a->m_objects.end(); ++k )
|
||||
{
|
||||
if( *k == _m )
|
||||
{
|
||||
has_object = true;
|
||||
}
|
||||
}
|
||||
// if the patterns is connected to the model, add it to the list
|
||||
if( has_object ) { patterns += a; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user