From 35aaa529f6e2c56bedddbaab5c7190cec610ee89 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Mon, 10 Jun 2024 20:27:44 +0200 Subject: [PATCH 01/14] AutomatableModelView_implemented_automationPoint_adding --- include/AutomatableModel.h | 17 ++++ include/AutomatableModelView.h | 13 +++ src/gui/AutomatableModelView.cpp | 149 +++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 15285e17ab3..1baaa294eb7 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -170,6 +170,23 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject return castValue( m_value ); } + inline float getTrueValue(int frameOffset = 0) const + { + if (m_controllerConnection != nullptr) + { + if (m_useControllerValue == true) + { + return controllerValue(frameOffset); + } + } + else if (hasLinkedModels() == true) + { + return controllerValue(frameOffset); + } + + return m_value; + } + float controllerValue( int frameOffset ) const; //! @brief Function that returns sample-exact data as a ValueBuffer diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 12b2e4d4919..925e1cd0545 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -28,9 +28,14 @@ #include "ModelView.h" #include "AutomatableModel.h" +#include "AutomationTrack.h" +#include "AutomationClip.h" +#include "SongEditor.h" +#include "Song.h" class QMenu; class QMouseEvent; +class Song; namespace lmms::gui { @@ -83,6 +88,7 @@ class LMMS_EXPORT AutomatableModelView : public ModelView QString m_description; QString m_unit; float m_conversionFactor; // Factor to be applied when the m_model->value is displayed + } ; @@ -97,10 +103,17 @@ class AutomatableModelViewSlots : public QObject public slots: void execConnectionDialog(); void removeConnection(); + void addSongAutomationPoint(); + void addSongAutomationPointAndClip(); + void removeSongNearestAutomationPoint(); void editSongGlobalAutomation(); void unlinkAllModels(); void removeSongGlobalAutomation(); +private: + AutomationTrack* getCurrentAutomationTrack(std::vector* clips); + AutomationClip* getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip); + AutomationClip* makeNewClip(AutomationTrack* track, TimePos position, bool canSnap); private slots: /// Copy the model's value to the clipboard. void copyToClipboard(); diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 0e364993f06..c8712abd7c9 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -34,6 +34,7 @@ #include "MainWindow.h" #include "StringPairDrag.h" #include "Clipboard.h" +#include "Engine.h" #include "AutomationEditor.h" @@ -83,6 +84,21 @@ void AutomatableModelView::addDefaultActions( QMenu* menu ) menu->addSeparator(); + menu->addAction(embed::getIconPixmap("automation"), + AutomatableModel::tr("add automation point"), + amvSlots, + SLOT(addSongAutomationPoint())); + menu->addAction(embed::getIconPixmap("automation"), + AutomatableModel::tr("add automation point to new clip"), + amvSlots, + SLOT(addSongAutomationPointAndClip())); + menu->addAction(embed::getIconPixmap("automation"), + AutomatableModel::tr("remove closest automation point"), + amvSlots, + SLOT(editSongGlobalAutomation())); + + menu->addSeparator(); + menu->addAction( embed::getIconPixmap( "automation" ), AutomatableModel::tr( "Edit song-global automation" ), amvSlots, @@ -258,7 +274,140 @@ void AutomatableModelViewSlots::removeConnection() } +void AutomatableModelViewSlots::addSongAutomationPoint() +{ + std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); + AutomationTrack* track = getCurrentAutomationTrack(&clips); + AutomationClip* clip = getCurrentAutomationClip(track, true); + + TimePos timePos = static_cast(Engine::getSong()->getPlayPos());// getGUI()->songEditor()->m_editor->currentPosition(); + qDebug("timepos: %d", timePos.getTicks()); + timePos -= clip->startPosition(); + bool autoResize = clip->getAutoResize(); + + clip->setAutoResize(true); + clip->recordValue(timePos, m_amv->modelUntyped()->getTrueValue()); + clip->setAutoResize(autoResize); +} +void AutomatableModelViewSlots::addSongAutomationPointAndClip() +{ + std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); + AutomationTrack* track = getCurrentAutomationTrack(&clips); + AutomationClip* clip = getCurrentAutomationClip(track, true); + + TimePos timePos = static_cast(Engine::getSong()->getPlayPos());// getGUI()->songEditor()->m_editor->currentPosition(); + qDebug("timepos: %d", timePos.getTicks()); + + if (clip != nullptr && clip->endPosition().getTicks() < timePos.getTicks()) + { + AutomationClip* newClip = makeNewClip(track, timePos, true); + timePos -= newClip->startPosition(); + bool autoResize = newClip->getAutoResize(); + + newClip->setAutoResize(true); + newClip->recordValue(timePos, m_amv->modelUntyped()->getTrueValue()); + newClip->setAutoResize(autoResize); + } + else + { + addSongAutomationPoint(); + } +} +void AutomatableModelViewSlots::removeSongNearestAutomationPoint() +{ + + std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); + AutomationTrack* track = getCurrentAutomationTrack(&clips); + AutomationClip* clip = getCurrentAutomationClip(track, true); + + tick_t minDistance = 0; + QMap timeMap; + for(QMap::iterator it = timeMap.begin(); + it != timeMap.end(); ++it ) + { + //if () + // Copies the automation node (in/out values and in/out tangents) + //timeMap[POS(it)] = it.value(); + // Sets the node's clip to this one + //timeMap[POS(it)].setClip(this); + } +} +AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vector* clips) +{ + AutomationTrack* output = nullptr; + // getting all of the clips that are connected to this model + //std::vector clips = AutomationClip().clipsForModel(m_model.data()); + if (clips->size() > 0) + { + // selecting the track with the most amount of clips + // connected to this model + AutomationTrack* maxTrack = dynamic_cast((*clips)[0]->getTrack()); + int maxTrackCount = 1; + for (size_t i = 1; i < clips->size(); i++) + { + int currentCount = 0; + for (size_t j = 0; j < clips->size(); j++) + { + if ((*clips)[i]->getTrack() == (*clips)[j]->getTrack()) + { + currentCount++; + } + } + if (maxTrackCount < currentCount) + { + maxTrackCount = currentCount; + maxTrack = dynamic_cast((*clips)[i]->getTrack());; + } + } + output = maxTrack; + } + else + { + // adding new track + output = new AutomationTrack(getGUI()->songEditor()->m_editor->model(), false); + } + return output; +} +AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip) +{ + AutomationClip* output = nullptr; + std::vector trackClips = track->getClips(); + TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); + if (trackClips.size() > 0) + { + // getting the closest clip + tick_t closestTime = trackClips[0]->startPosition().getTicks(); + int closestClipLocation = 0; + for (size_t i = 1; i < trackClips.size(); i++) + { + if (trackClips[i]->startPosition().getTicks() > closestTime && timePos.getTicks() > trackClips[i]->startPosition().getTicks()) + { + closestTime = trackClips[i]->startPosition().getTicks(); + closestClipLocation = i; + } + } + output = dynamic_cast(trackClips[closestClipLocation]); + } + else if (canAddNewClip == true) + { + // adding a new clip + output = makeNewClip(track, timePos, true); + } + return output; +} +AutomationClip* AutomatableModelViewSlots::makeNewClip(AutomationTrack* track, TimePos position, bool canSnap) +{ + if (canSnap == true) + { + position.setTicks(position.getTicks() - position.getTickWithinBar(TimeSig(Engine::getSong()->getTimeSigModel()))); + //position.setTicks(position.getTicks() - position.getTicks() % TimePos::ticksPerBar()); + } + AutomationClip* output = dynamic_cast(track->createClip(position)); + // connect to model + output->addObject(m_amv->modelUntyped(), true); + return output; +} void AutomatableModelViewSlots::editSongGlobalAutomation() { From bdc5be48df1294c028ec48e710e70ea3b1a2af2d Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 12 Jun 2024 21:55:37 +0200 Subject: [PATCH 02/14] AutomatableModelView_added_node_removing_and_updating_options --- include/AutomatableModelView.h | 12 +- src/gui/AutomatableModelView.cpp | 267 +++++++++++++++++++++++++++---- 2 files changed, 240 insertions(+), 39 deletions(-) diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 925e1cd0545..04eaf1d6a44 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -103,16 +103,18 @@ class AutomatableModelViewSlots : public QObject public slots: void execConnectionDialog(); void removeConnection(); - void addSongAutomationPoint(); - void addSongAutomationPointAndClip(); - void removeSongNearestAutomationPoint(); + void addSongAutomationNode(); + void addSongAutomationNodeAndClip(); + void updateSongNearestAutomationNode(); + void removeSongNearestAutomationNode(); void editSongGlobalAutomation(); void unlinkAllModels(); void removeSongGlobalAutomation(); private: - AutomationTrack* getCurrentAutomationTrack(std::vector* clips); - AutomationClip* getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip); + AutomationTrack* getCurrentAutomationTrack(std::vector* clips, bool canAddNewTrack); + AutomationClip* getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip, bool searchAfter); + const TimePos getNearestAutomationNode(AutomationTrack* track, AutomationClip** clipOut); AutomationClip* makeNewClip(AutomationTrack* track, TimePos position, bool canSnap); private slots: /// Copy the model's value to the clipboard. diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index c8712abd7c9..ad2e4f4304b 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -27,6 +27,7 @@ #include "AutomatableModelView.h" #include "AutomationClip.h" +#include "AutomationNode.h" #include "ControllerConnectionDialog.h" #include "ControllerConnection.h" #include "embed.h" @@ -85,17 +86,21 @@ void AutomatableModelView::addDefaultActions( QMenu* menu ) menu->addSeparator(); menu->addAction(embed::getIconPixmap("automation"), - AutomatableModel::tr("add automation point"), + AutomatableModel::tr("add automation node"), amvSlots, - SLOT(addSongAutomationPoint())); + SLOT(addSongAutomationNode())); menu->addAction(embed::getIconPixmap("automation"), - AutomatableModel::tr("add automation point to new clip"), + AutomatableModel::tr("add automation node to new clip"), amvSlots, - SLOT(addSongAutomationPointAndClip())); + SLOT(addSongAutomationNodeAndClip())); menu->addAction(embed::getIconPixmap("automation"), - AutomatableModel::tr("remove closest automation point"), + AutomatableModel::tr("update closest automation node"), amvSlots, - SLOT(editSongGlobalAutomation())); + SLOT(updateSongNearestAutomationNode())); + menu->addAction(embed::getIconPixmap("automation"), + AutomatableModel::tr("remove closest automation node"), + amvSlots, + SLOT(removeSongNearestAutomationNode())); menu->addSeparator(); @@ -274,11 +279,11 @@ void AutomatableModelViewSlots::removeConnection() } -void AutomatableModelViewSlots::addSongAutomationPoint() +void AutomatableModelViewSlots::addSongAutomationNode() { std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); - AutomationTrack* track = getCurrentAutomationTrack(&clips); - AutomationClip* clip = getCurrentAutomationClip(track, true); + AutomationTrack* track = getCurrentAutomationTrack(&clips, true); + AutomationClip* clip = getCurrentAutomationClip(track, true, false); TimePos timePos = static_cast(Engine::getSong()->getPlayPos());// getGUI()->songEditor()->m_editor->currentPosition(); qDebug("timepos: %d", timePos.getTicks()); @@ -289,11 +294,11 @@ void AutomatableModelViewSlots::addSongAutomationPoint() clip->recordValue(timePos, m_amv->modelUntyped()->getTrueValue()); clip->setAutoResize(autoResize); } -void AutomatableModelViewSlots::addSongAutomationPointAndClip() +void AutomatableModelViewSlots::addSongAutomationNodeAndClip() { std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); - AutomationTrack* track = getCurrentAutomationTrack(&clips); - AutomationClip* clip = getCurrentAutomationClip(track, true); + AutomationTrack* track = getCurrentAutomationTrack(&clips, true); + AutomationClip* clip = getCurrentAutomationClip(track, false, false); TimePos timePos = static_cast(Engine::getSong()->getPlayPos());// getGUI()->songEditor()->m_editor->currentPosition(); qDebug("timepos: %d", timePos.getTicks()); @@ -310,30 +315,136 @@ void AutomatableModelViewSlots::addSongAutomationPointAndClip() } else { - addSongAutomationPoint(); + addSongAutomationNode(); } } -void AutomatableModelViewSlots::removeSongNearestAutomationPoint() +void AutomatableModelViewSlots::updateSongNearestAutomationNode() { + qDebug("\nupdate nearest"); std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); - AutomationTrack* track = getCurrentAutomationTrack(&clips); - AutomationClip* clip = getCurrentAutomationClip(track, true); + AutomationTrack* track = getCurrentAutomationTrack(&clips, false); + if (track != nullptr) + { + AutomationClip* nodeClip = nullptr; + TimePos nodePos = getNearestAutomationNode(track, &nodeClip); + if (nodeClip != nullptr) + { + nodeClip->recordValue(nodePos, m_amv->modelUntyped()->getTrueValue()); + } + /* + AutomationClip* clipBefore = getCurrentAutomationClip(track, false, false); + AutomationClip* clipAfter = getCurrentAutomationClip(track, false, true); + + TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); + + bool validBefore = clipBefore != nullptr && clipBefore->hasAutomation(); + bool validAfter = clipAfter != nullptr && clipAfter->hasAutomation(); + + if (validBefore == true && validAfter == false) + { + clipBefore->recordValue(getNearestAutomationNode(clipBefore, false), m_amv->modelUntyped()->getTrueValue()); + } + else if (validBefore == false && validAfter == true) + { + clipAfter->recordValue(getNearestAutomationNode(clipAfter, true), m_amv->modelUntyped()->getTrueValue()); + } + else if (validBefore == true && validAfter == true) + { + TimePos timeBefore = getNearestAutomationNode(clipBefore, false); + TimePos timeAfter = getNearestAutomationNode(clipAfter, true); + if (timePos.getTicks() - timeBefore.getTicks() - clipBefore->startPosition() + > timeAfter.getTicks() + clipAfter->startPosition() - timePos.getTicks()) + { + clipBefore->recordValue(getNearestAutomationNode(clipBefore, false), m_amv->modelUntyped()->getTrueValue()); + } + else + { + clipAfter->recordValue(getNearestAutomationNode(clipAfter, true), m_amv->modelUntyped()->getTrueValue()); + } + } + */ + } +} +void AutomatableModelViewSlots::removeSongNearestAutomationNode() +{ - tick_t minDistance = 0; - QMap timeMap; - for(QMap::iterator it = timeMap.begin(); - it != timeMap.end(); ++it ) + qDebug("\nremove nearest"); + std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); + AutomationTrack* track = getCurrentAutomationTrack(&clips, false); + if (track != nullptr) { - //if () - // Copies the automation node (in/out values and in/out tangents) - //timeMap[POS(it)] = it.value(); - // Sets the node's clip to this one - //timeMap[POS(it)].setClip(this); + AutomationClip* nodeClip = nullptr; + TimePos nodePos = getNearestAutomationNode(track, &nodeClip); + if (nodeClip != nullptr) + { + nodeClip->removeNode(nodePos); + if (nodeClip->hasAutomation() == false) + { + delete nodeClip; + } + } + /* + qDebug("clip before"); + AutomationClip* clipBefore = getCurrentAutomationClip(track, false, false); + qDebug("clip after"); + AutomationClip* clipAfter = getCurrentAutomationClip(track, false, true); + + TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); + + bool validBefore = clipBefore != nullptr && clipBefore->hasAutomation(); + bool validAfter = clipAfter != nullptr && clipAfter->hasAutomation(); + + if (validBefore == true && validAfter == false) + { + clipBefore->removeNode(getNearestAutomationNode(clipBefore, false)); + qDebug("removed before"); + if (clipBefore->hasAutomation() == false) + { + delete clipBefore; + } + } + else if (validBefore == false && validAfter == true) + { + clipAfter->removeNode(getNearestAutomationNode(clipAfter, true)); + qDebug("removed after"); + if (clipAfter->hasAutomation() == false) + { + delete clipAfter; + } + } + else if (validBefore == true && validAfter == true) + { + TimePos timeBefore = getNearestAutomationNode(clipBefore, false); + TimePos timeAfter = getNearestAutomationNode(clipAfter, true); + + qDebug("timePos: %d, before: %d, before_start: %d, after: %d, after_start: %d", timePos.getTicks(), timeBefore.getTicks(), clipBefore->startPosition().getTicks(), timeAfter.getTicks(), clipAfter->startPosition().getTicks()); + + if (timePos.getTicks() - timeBefore.getTicks() - clipBefore->startPosition().getTicks() + < timeAfter.getTicks() + clipAfter->startPosition().getTicks() - timePos.getTicks()) + { + qDebug("removed before"); + clipBefore->removeNode(timeBefore); + if (clipBefore->hasAutomation() == false) + { + delete clipBefore; + } + } + else + { + qDebug("removed after"); + clipAfter->removeNode(timeAfter); + if (clipAfter->hasAutomation() == false) + { + delete clipAfter; + } + } + } + */ } } -AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vector* clips) +AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vector* clips, bool canAddNewTrack) { AutomationTrack* output = nullptr; // getting all of the clips that are connected to this model @@ -362,40 +473,128 @@ AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vecto } output = maxTrack; } - else + else if (canAddNewTrack == true) { // adding new track output = new AutomationTrack(getGUI()->songEditor()->m_editor->model(), false); } return output; } -AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip) +AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip, bool searchAfter) { AutomationClip* output = nullptr; std::vector trackClips = track->getClips(); TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); + + + bool tryAdding = false; if (trackClips.size() > 0) { // getting the closest clip - tick_t closestTime = trackClips[0]->startPosition().getTicks(); - int closestClipLocation = 0; - for (size_t i = 1; i < trackClips.size(); i++) + tick_t closestTime = -1; //trackClips[0]->startPosition().getTicks(); + int closestClipLocation = -1; + for (size_t i = 0; i < trackClips.size(); i++) { - if (trackClips[i]->startPosition().getTicks() > closestTime && timePos.getTicks() > trackClips[i]->startPosition().getTicks()) + tick_t currentTime = trackClips[i]->startPosition().getTicks(); + qDebug("current time: %d, closest: %d, i: %d, timepos: %d", currentTime, closestTime, i, timePos.getTicks()); + if ((searchAfter == false && currentTime > closestTime && timePos.getTicks() > currentTime) + || (searchAfter == true && (currentTime < closestTime || closestTime < 0) && timePos.getTicks() < currentTime)) { closestTime = trackClips[i]->startPosition().getTicks(); closestClipLocation = i; } } - output = dynamic_cast(trackClips[closestClipLocation]); + + qDebug("closest clip: %d", closestClipLocation); + // in some cases the current time position can be before or after every clip + // if this is the case, try adding + if (closestClipLocation < 0) + { + tryAdding = true; + qDebug("return nullptr"); + } + else + { + output = dynamic_cast(trackClips[closestClipLocation]); + } } - else if (canAddNewClip == true) + else + { + tryAdding = true; + } + if (tryAdding == true && canAddNewClip == true) { // adding a new clip output = makeNewClip(track, timePos, true); } return output; } +const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrack* track, AutomationClip** clipOut) +{ + TimePos output; + AutomationClip* minClip = nullptr; + int minDistance = -1; + + TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); + qDebug("clip before"); + AutomationClip* clipBefore = getCurrentAutomationClip(track, false, false); + qDebug("clip after"); + AutomationClip* clipAfter = getCurrentAutomationClip(track, false, true); + + if (clipBefore != nullptr && clipBefore->hasAutomation() == true) + { + for(AutomationClip::timeMap::const_iterator it = clipBefore->getTimeMap().begin(); it != clipBefore->getTimeMap().end(); ++it) + { + int curDistance = std::abs(static_cast(POS(it) + clipBefore->startPosition().getTicks()) - static_cast(timePos.getTicks())); + if (curDistance < minDistance || minDistance < 0) + { + minDistance = curDistance; + output = TimePos(POS(it)); + minClip = clipBefore; + qDebug("nearest before key: %d, %d", POS(it), timePos.getTicks()); + } + } + /* + for(AutomationClip::timeMap::const_iterator it = clip->getTimeMap().end() - 1; it != clip->getTimeMap().begin() - 1; --it) + { + qDebug("nearest before key: %d, %d", POS(it), timePos.getTicks()); + output = TimePos(POS(it)); + if (POS(it) + clip->startPosition().getTicks() < timePos.getTicks()) + { + break; + } + } + */ + } + if (clipAfter != nullptr && clipAfter->hasAutomation() == true) + { + //AutomationClip::timeMap::const_iterator it = clipAfter->getTimeMap().begin(); + int curDistance = static_cast(POS(clipAfter->getTimeMap().begin()) + clipAfter->startPosition().getTicks()) - static_cast(timePos.getTicks()); + if (curDistance < minDistance || minDistance < 0) + { + minDistance = curDistance; + output = TimePos(POS(clipAfter->getTimeMap().begin())); + minClip = clipAfter; + qDebug("nearest after key: %d, %d", output.getTicks(), timePos.getTicks()); + } + /* + for(AutomationClip::timeMap::const_iterator it = clipAfter->getTimeMap().begin(); it != clipAfter->getTimeMap().end(); ++it) + { + qDebug("nearest after key: %d, %d", POS(it), timePos.getTicks()); + output = TimePos(POS(it)); + if (POS(it) + clipAfter->startPosition().getTicks() > timePos.getTicks()) + { + break; + } + + } + */ + } + + *clipOut = minClip; + + return output; +} AutomationClip* AutomatableModelViewSlots::makeNewClip(AutomationTrack* track, TimePos position, bool canSnap) { if (canSnap == true) From 6458654553e6d4c5aff1ac77a0db9b357188489a Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Wed, 12 Jun 2024 22:30:37 +0200 Subject: [PATCH 03/14] AutomatableModelView_added_comments --- include/AutomatableModelView.h | 9 ++ src/gui/AutomatableModelView.cpp | 174 ++++++------------------------- 2 files changed, 43 insertions(+), 140 deletions(-) diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 04eaf1d6a44..59d70a6cdeb 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -112,9 +112,18 @@ public slots: void removeSongGlobalAutomation(); private: + // gets the automationTrack with the most amount of clips connected to it + // if this track doesn't exists and "canAddNewTrack", then add a new one else return nullptr + // "clips" = clips that are connected to this model AutomationTrack* getCurrentAutomationTrack(std::vector* clips, bool canAddNewTrack); + // gets the clip that start before or after the song time position (playback pos) + // if this clip doesn't exists and "canAddNewClip", then add a new one else return nullptr AutomationClip* getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip, bool searchAfter); + // gets the automationNode closest to the song time position (playback pos) + // "clipOut" is the clip that has the node + // can return nullptr on "clipOut" const TimePos getNearestAutomationNode(AutomationTrack* track, AutomationClip** clipOut); + // makes new clip and connects it to this model AutomationClip* makeNewClip(AutomationTrack* track, TimePos position, bool canSnap); private slots: /// Copy the model's value to the clipboard. diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index ad2e4f4304b..5970114ff7d 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -85,19 +85,19 @@ void AutomatableModelView::addDefaultActions( QMenu* menu ) menu->addSeparator(); - menu->addAction(embed::getIconPixmap("automation"), + menu->addAction(QPixmap(), AutomatableModel::tr("add automation node"), amvSlots, SLOT(addSongAutomationNode())); - menu->addAction(embed::getIconPixmap("automation"), + menu->addAction(QPixmap(), AutomatableModel::tr("add automation node to new clip"), amvSlots, SLOT(addSongAutomationNodeAndClip())); - menu->addAction(embed::getIconPixmap("automation"), + menu->addAction(QPixmap(), AutomatableModel::tr("update closest automation node"), amvSlots, SLOT(updateSongNearestAutomationNode())); - menu->addAction(embed::getIconPixmap("automation"), + menu->addAction(QPixmap(), AutomatableModel::tr("remove closest automation node"), amvSlots, SLOT(removeSongNearestAutomationNode())); @@ -281,16 +281,21 @@ void AutomatableModelViewSlots::removeConnection() void AutomatableModelViewSlots::addSongAutomationNode() { + // getting all the clips that have this model std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); + // selecting the track with the most clips connected to this model AutomationTrack* track = getCurrentAutomationTrack(&clips, true); + // getting the clip before the current song time position AutomationClip* clip = getCurrentAutomationClip(track, true, false); - TimePos timePos = static_cast(Engine::getSong()->getPlayPos());// getGUI()->songEditor()->m_editor->currentPosition(); - qDebug("timepos: %d", timePos.getTicks()); + // getting global song time + TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); + // account for the node's relative position inside clip timePos -= clip->startPosition(); bool autoResize = clip->getAutoResize(); clip->setAutoResize(true); + // adding model value clip->recordValue(timePos, m_amv->modelUntyped()->getTrueValue()); clip->setAutoResize(autoResize); } @@ -300,12 +305,13 @@ void AutomatableModelViewSlots::addSongAutomationNodeAndClip() AutomationTrack* track = getCurrentAutomationTrack(&clips, true); AutomationClip* clip = getCurrentAutomationClip(track, false, false); - TimePos timePos = static_cast(Engine::getSong()->getPlayPos());// getGUI()->songEditor()->m_editor->currentPosition(); - qDebug("timepos: %d", timePos.getTicks()); + TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); if (clip != nullptr && clip->endPosition().getTicks() < timePos.getTicks()) { AutomationClip* newClip = makeNewClip(track, timePos, true); + // copying the progressionType of the clip before + newClip->setProgressionType(clip->progressionType()); timePos -= newClip->startPosition(); bool autoResize = newClip->getAutoResize(); @@ -320,59 +326,30 @@ void AutomatableModelViewSlots::addSongAutomationNodeAndClip() } void AutomatableModelViewSlots::updateSongNearestAutomationNode() { - - qDebug("\nupdate nearest"); std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); + // getting the track without adding a new one if no track was found AutomationTrack* track = getCurrentAutomationTrack(&clips, false); + // this needs to be checked because getCurrentAutomationTrack might give + // a nullptr if it can not find and add a track if (track != nullptr) { + // getting nearest node position AutomationClip* nodeClip = nullptr; TimePos nodePos = getNearestAutomationNode(track, &nodeClip); if (nodeClip != nullptr) { + // modifying its value nodeClip->recordValue(nodePos, m_amv->modelUntyped()->getTrueValue()); } - /* - AutomationClip* clipBefore = getCurrentAutomationClip(track, false, false); - AutomationClip* clipAfter = getCurrentAutomationClip(track, false, true); - - TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); - - bool validBefore = clipBefore != nullptr && clipBefore->hasAutomation(); - bool validAfter = clipAfter != nullptr && clipAfter->hasAutomation(); - - if (validBefore == true && validAfter == false) - { - clipBefore->recordValue(getNearestAutomationNode(clipBefore, false), m_amv->modelUntyped()->getTrueValue()); - } - else if (validBefore == false && validAfter == true) - { - clipAfter->recordValue(getNearestAutomationNode(clipAfter, true), m_amv->modelUntyped()->getTrueValue()); - } - else if (validBefore == true && validAfter == true) - { - TimePos timeBefore = getNearestAutomationNode(clipBefore, false); - TimePos timeAfter = getNearestAutomationNode(clipAfter, true); - - if (timePos.getTicks() - timeBefore.getTicks() - clipBefore->startPosition() - > timeAfter.getTicks() + clipAfter->startPosition() - timePos.getTicks()) - { - clipBefore->recordValue(getNearestAutomationNode(clipBefore, false), m_amv->modelUntyped()->getTrueValue()); - } - else - { - clipAfter->recordValue(getNearestAutomationNode(clipAfter, true), m_amv->modelUntyped()->getTrueValue()); - } - } - */ } } void AutomatableModelViewSlots::removeSongNearestAutomationNode() { - - qDebug("\nremove nearest"); std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); + // getting the track without adding a new one if no track was found AutomationTrack* track = getCurrentAutomationTrack(&clips, false); + // this needs to be checked because getCurrentAutomationTrack might give + // a nullptr if it can not find and add a track if (track != nullptr) { AutomationClip* nodeClip = nullptr; @@ -380,75 +357,17 @@ void AutomatableModelViewSlots::removeSongNearestAutomationNode() if (nodeClip != nullptr) { nodeClip->removeNode(nodePos); + // if there is no node left, the automationClip will be deleted if (nodeClip->hasAutomation() == false) { delete nodeClip; } } - /* - qDebug("clip before"); - AutomationClip* clipBefore = getCurrentAutomationClip(track, false, false); - qDebug("clip after"); - AutomationClip* clipAfter = getCurrentAutomationClip(track, false, true); - - TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); - - bool validBefore = clipBefore != nullptr && clipBefore->hasAutomation(); - bool validAfter = clipAfter != nullptr && clipAfter->hasAutomation(); - - if (validBefore == true && validAfter == false) - { - clipBefore->removeNode(getNearestAutomationNode(clipBefore, false)); - qDebug("removed before"); - if (clipBefore->hasAutomation() == false) - { - delete clipBefore; - } - } - else if (validBefore == false && validAfter == true) - { - clipAfter->removeNode(getNearestAutomationNode(clipAfter, true)); - qDebug("removed after"); - if (clipAfter->hasAutomation() == false) - { - delete clipAfter; - } - } - else if (validBefore == true && validAfter == true) - { - TimePos timeBefore = getNearestAutomationNode(clipBefore, false); - TimePos timeAfter = getNearestAutomationNode(clipAfter, true); - - qDebug("timePos: %d, before: %d, before_start: %d, after: %d, after_start: %d", timePos.getTicks(), timeBefore.getTicks(), clipBefore->startPosition().getTicks(), timeAfter.getTicks(), clipAfter->startPosition().getTicks()); - - if (timePos.getTicks() - timeBefore.getTicks() - clipBefore->startPosition().getTicks() - < timeAfter.getTicks() + clipAfter->startPosition().getTicks() - timePos.getTicks()) - { - qDebug("removed before"); - clipBefore->removeNode(timeBefore); - if (clipBefore->hasAutomation() == false) - { - delete clipBefore; - } - } - else - { - qDebug("removed after"); - clipAfter->removeNode(timeAfter); - if (clipAfter->hasAutomation() == false) - { - delete clipAfter; - } - } - } - */ } } AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vector* clips, bool canAddNewTrack) { AutomationTrack* output = nullptr; - // getting all of the clips that are connected to this model - //std::vector clips = AutomationClip().clipsForModel(m_model.data()); if (clips->size() > 0) { // selecting the track with the most amount of clips @@ -490,13 +409,12 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr bool tryAdding = false; if (trackClips.size() > 0) { - // getting the closest clip - tick_t closestTime = -1; //trackClips[0]->startPosition().getTicks(); + // getting the closest clip that start before or after the global time position + tick_t closestTime = -1; int closestClipLocation = -1; for (size_t i = 0; i < trackClips.size(); i++) { tick_t currentTime = trackClips[i]->startPosition().getTicks(); - qDebug("current time: %d, closest: %d, i: %d, timepos: %d", currentTime, closestTime, i, timePos.getTicks()); if ((searchAfter == false && currentTime > closestTime && timePos.getTicks() > currentTime) || (searchAfter == true && (currentTime < closestTime || closestTime < 0) && timePos.getTicks() < currentTime)) { @@ -505,13 +423,12 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr } } - qDebug("closest clip: %d", closestClipLocation); - // in some cases the current time position can be before or after every clip - // if this is the case, try adding + // in some cases there could be no clips before or after the global time position + // if this is the case, try adding a new + // (if this fails, return nullptr) if (closestClipLocation < 0) { tryAdding = true; - qDebug("return nullptr"); } else { @@ -536,13 +453,14 @@ const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrac int minDistance = -1; TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); - qDebug("clip before"); + // getting the clips before and after the global time position AutomationClip* clipBefore = getCurrentAutomationClip(track, false, false); - qDebug("clip after"); AutomationClip* clipAfter = getCurrentAutomationClip(track, false, true); if (clipBefore != nullptr && clipBefore->hasAutomation() == true) { + // getting nearest node + // in the clip that starts before this for(AutomationClip::timeMap::const_iterator it = clipBefore->getTimeMap().begin(); it != clipBefore->getTimeMap().end(); ++it) { int curDistance = std::abs(static_cast(POS(it) + clipBefore->startPosition().getTicks()) - static_cast(timePos.getTicks())); @@ -551,44 +469,20 @@ const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrac minDistance = curDistance; output = TimePos(POS(it)); minClip = clipBefore; - qDebug("nearest before key: %d, %d", POS(it), timePos.getTicks()); - } - } - /* - for(AutomationClip::timeMap::const_iterator it = clip->getTimeMap().end() - 1; it != clip->getTimeMap().begin() - 1; --it) - { - qDebug("nearest before key: %d, %d", POS(it), timePos.getTicks()); - output = TimePos(POS(it)); - if (POS(it) + clip->startPosition().getTicks() < timePos.getTicks()) - { - break; } } - */ } if (clipAfter != nullptr && clipAfter->hasAutomation() == true) { - //AutomationClip::timeMap::const_iterator it = clipAfter->getTimeMap().begin(); + // getting the nearest node + // in the clip that starts after this int curDistance = static_cast(POS(clipAfter->getTimeMap().begin()) + clipAfter->startPosition().getTicks()) - static_cast(timePos.getTicks()); if (curDistance < minDistance || minDistance < 0) { minDistance = curDistance; output = TimePos(POS(clipAfter->getTimeMap().begin())); minClip = clipAfter; - qDebug("nearest after key: %d, %d", output.getTicks(), timePos.getTicks()); - } - /* - for(AutomationClip::timeMap::const_iterator it = clipAfter->getTimeMap().begin(); it != clipAfter->getTimeMap().end(); ++it) - { - qDebug("nearest after key: %d, %d", POS(it), timePos.getTicks()); - output = TimePos(POS(it)); - if (POS(it) + clipAfter->startPosition().getTicks() > timePos.getTicks()) - { - break; - } - } - */ } *clipOut = minClip; @@ -599,8 +493,8 @@ AutomationClip* AutomatableModelViewSlots::makeNewClip(AutomationTrack* track, T { if (canSnap == true) { + // snapping to the bar before position.setTicks(position.getTicks() - position.getTickWithinBar(TimeSig(Engine::getSong()->getTimeSigModel()))); - //position.setTicks(position.getTicks() - position.getTicks() % TimePos::ticksPerBar()); } AutomationClip* output = dynamic_cast(track->createClip(position)); // connect to model From a400a5ad4756b2365ec33dfb5d70ae695918e446 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:25:38 +0200 Subject: [PATCH 04/14] AutomatableModelView_fixed_closest_node_search_at_clip_start_position --- src/gui/AutomatableModelView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 5970114ff7d..5b7a6f3cf1b 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -415,8 +415,8 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr for (size_t i = 0; i < trackClips.size(); i++) { tick_t currentTime = trackClips[i]->startPosition().getTicks(); - if ((searchAfter == false && currentTime > closestTime && timePos.getTicks() > currentTime) - || (searchAfter == true && (currentTime < closestTime || closestTime < 0) && timePos.getTicks() < currentTime)) + if ((searchAfter == false && (currentTime > closestTime || closestTime < 0) && timePos.getTicks() > currentTime) + || (searchAfter == true && (currentTime < closestTime || closestTime < 0) && timePos.getTicks() <= currentTime)) { closestTime = trackClips[i]->startPosition().getTicks(); closestClipLocation = i; From 1da957650b419096da12e89968213b22682b0930 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 18:32:21 +0200 Subject: [PATCH 05/14] AutomatableModelView_changed_loop_to_range_loop --- include/AutomatableModelView.h | 1 - src/gui/AutomatableModelView.cpp | 16 ++++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 59d70a6cdeb..f4e3e04b5b3 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -133,7 +133,6 @@ private slots: protected: AutomatableModelView* m_amv; - } ; diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 5b7a6f3cf1b..93dec026c1b 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -411,28 +411,28 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr { // getting the closest clip that start before or after the global time position tick_t closestTime = -1; - int closestClipLocation = -1; - for (size_t i = 0; i < trackClips.size(); i++) + Clip* closestClip = nullptr; + for (Clip* currentClip : trackClips) { - tick_t currentTime = trackClips[i]->startPosition().getTicks(); + tick_t currentTime = currentClip->startPosition().getTicks(); if ((searchAfter == false && (currentTime > closestTime || closestTime < 0) && timePos.getTicks() > currentTime) || (searchAfter == true && (currentTime < closestTime || closestTime < 0) && timePos.getTicks() <= currentTime)) { - closestTime = trackClips[i]->startPosition().getTicks(); - closestClipLocation = i; + closestTime = currentTime; + closestClip = currentClip; } } // in some cases there could be no clips before or after the global time position - // if this is the case, try adding a new + // if this is the case, try adding a new one // (if this fails, return nullptr) - if (closestClipLocation < 0) + if (closestClip == nullptr) { tryAdding = true; } else { - output = dynamic_cast(trackClips[closestClipLocation]); + output = dynamic_cast(closestClip); } } else From 8488b14e302352534984f75b7b45e48af5bc3404 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 19:09:30 +0200 Subject: [PATCH 06/14] AutomatableModel_inverted_getTrueValue_function --- include/AutomatableModel.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 1baaa294eb7..4c84dced9e8 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -172,19 +172,14 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject inline float getTrueValue(int frameOffset = 0) const { - if (m_controllerConnection != nullptr) + if (m_controllerConnection == nullptr && hasLinkedModels() == false) { - if (m_useControllerValue == true) - { - return controllerValue(frameOffset); - } + return m_value; } - else if (hasLinkedModels() == true) + else { return controllerValue(frameOffset); } - - return m_value; } float controllerValue( int frameOffset ) const; From 5dbfc90c8b4a41b6b9f5a788e114be1b69318038 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 19:10:56 +0200 Subject: [PATCH 07/14] AutomatableModelView_inverted_functions --- src/gui/AutomatableModelView.cpp | 37 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 93dec026c1b..119b62cc2e8 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -331,16 +331,15 @@ void AutomatableModelViewSlots::updateSongNearestAutomationNode() AutomationTrack* track = getCurrentAutomationTrack(&clips, false); // this needs to be checked because getCurrentAutomationTrack might give // a nullptr if it can not find and add a track - if (track != nullptr) + if (track == nullptr) { return; } + + // getting nearest node position + AutomationClip* nodeClip = nullptr; + TimePos nodePos = getNearestAutomationNode(track, &nodeClip); + if (nodeClip != nullptr) { - // getting nearest node position - AutomationClip* nodeClip = nullptr; - TimePos nodePos = getNearestAutomationNode(track, &nodeClip); - if (nodeClip != nullptr) - { - // modifying its value - nodeClip->recordValue(nodePos, m_amv->modelUntyped()->getTrueValue()); - } + // modifying its value + nodeClip->recordValue(nodePos, m_amv->modelUntyped()->getTrueValue()); } } void AutomatableModelViewSlots::removeSongNearestAutomationNode() @@ -348,20 +347,20 @@ void AutomatableModelViewSlots::removeSongNearestAutomationNode() std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); // getting the track without adding a new one if no track was found AutomationTrack* track = getCurrentAutomationTrack(&clips, false); + // this needs to be checked because getCurrentAutomationTrack might give // a nullptr if it can not find and add a track - if (track != nullptr) + if (track == nullptr) { return; } + + AutomationClip* nodeClip = nullptr; + TimePos nodePos = getNearestAutomationNode(track, &nodeClip); + if (nodeClip != nullptr) { - AutomationClip* nodeClip = nullptr; - TimePos nodePos = getNearestAutomationNode(track, &nodeClip); - if (nodeClip != nullptr) + nodeClip->removeNode(nodePos); + // if there is no node left, the automationClip will be deleted + if (nodeClip->hasAutomation() == false) { - nodeClip->removeNode(nodePos); - // if there is no node left, the automationClip will be deleted - if (nodeClip->hasAutomation() == false) - { - delete nodeClip; - } + delete nodeClip; } } } From 226bfb47ae1c10e7eb0bca7174c812ff1eaf4eda Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 19:27:36 +0200 Subject: [PATCH 08/14] AutomatableModel_getTrueValue_function_else_removed --- include/AutomatableModel.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 4c84dced9e8..ece11ca6335 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -176,10 +176,8 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject { return m_value; } - else - { - return controllerValue(frameOffset); - } + + return controllerValue(frameOffset); } float controllerValue( int frameOffset ) const; From e7aa54241aed54f0e016b4616b5638f566f56177 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 20:22:58 +0200 Subject: [PATCH 09/14] AutomatableModel_style_changes --- include/AutomatableModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index ece11ca6335..da082c2e66b 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -172,7 +172,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject inline float getTrueValue(int frameOffset = 0) const { - if (m_controllerConnection == nullptr && hasLinkedModels() == false) + if (!m_controllerConnection && !hasLinkedModels()) { return m_value; } From 39f8e30f47e227ef76f7a2a789ccf2dac21a7a93 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 20:48:25 +0200 Subject: [PATCH 10/14] AutomatableModelView_style_changes_1 --- src/gui/AutomatableModelView.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 119b62cc2e8..243e25ea571 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -299,6 +299,7 @@ void AutomatableModelViewSlots::addSongAutomationNode() clip->recordValue(timePos, m_amv->modelUntyped()->getTrueValue()); clip->setAutoResize(autoResize); } + void AutomatableModelViewSlots::addSongAutomationNodeAndClip() { std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); @@ -324,6 +325,7 @@ void AutomatableModelViewSlots::addSongAutomationNodeAndClip() addSongAutomationNode(); } } + void AutomatableModelViewSlots::updateSongNearestAutomationNode() { std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); @@ -342,6 +344,7 @@ void AutomatableModelViewSlots::updateSongNearestAutomationNode() nodeClip->recordValue(nodePos, m_amv->modelUntyped()->getTrueValue()); } } + void AutomatableModelViewSlots::removeSongNearestAutomationNode() { std::vector clips = AutomationClip::clipsForModel(m_amv->modelUntyped()); @@ -364,6 +367,7 @@ void AutomatableModelViewSlots::removeSongNearestAutomationNode() } } } + AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vector* clips, bool canAddNewTrack) { AutomationTrack* output = nullptr; @@ -398,6 +402,7 @@ AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vecto } return output; } + AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip, bool searchAfter) { AutomationClip* output = nullptr; @@ -445,6 +450,7 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr } return output; } + const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrack* track, AutomationClip** clipOut) { TimePos output; @@ -460,7 +466,7 @@ const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrac { // getting nearest node // in the clip that starts before this - for(AutomationClip::timeMap::const_iterator it = clipBefore->getTimeMap().begin(); it != clipBefore->getTimeMap().end(); ++it) + for (auto it = clipBefore->getTimeMap().begin(); it != clipBefore->getTimeMap().end(); ++it) { int curDistance = std::abs(static_cast(POS(it) + clipBefore->startPosition().getTicks()) - static_cast(timePos.getTicks())); if (curDistance < minDistance || minDistance < 0) @@ -488,6 +494,7 @@ const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrac return output; } + AutomationClip* AutomatableModelViewSlots::makeNewClip(AutomationTrack* track, TimePos position, bool canSnap) { if (canSnap == true) From 243e69ff59be504a4956e0a0499dad16b44280d8 Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:07:38 +0200 Subject: [PATCH 11/14] AutomatableModelView_reference_and_getCurrentAutomationTrack_range_based_loop --- src/gui/AutomatableModelView.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 243e25ea571..b9475a1782f 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -380,9 +380,9 @@ AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vecto for (size_t i = 1; i < clips->size(); i++) { int currentCount = 0; - for (size_t j = 0; j < clips->size(); j++) + for (AutomationClip* j : (*clips)) { - if ((*clips)[i]->getTrack() == (*clips)[j]->getTrack()) + if ((*clips)[i]->getTrack() == j->getTrack()) { currentCount++; } @@ -406,10 +406,9 @@ AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vecto AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTrack* track, bool canAddNewClip, bool searchAfter) { AutomationClip* output = nullptr; - std::vector trackClips = track->getClips(); + const std::vector& trackClips = track->getClips(); TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); - bool tryAdding = false; if (trackClips.size() > 0) { From 7b891c292aefca9cb0e3e22dcfb525f4f037e3ae Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:33:25 +0200 Subject: [PATCH 12/14] AutomatableModelView_style_changes_2 --- src/gui/AutomatableModelView.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index b9475a1782f..bbf9c975b23 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -308,7 +308,7 @@ void AutomatableModelViewSlots::addSongAutomationNodeAndClip() TimePos timePos = static_cast(Engine::getSong()->getPlayPos()); - if (clip != nullptr && clip->endPosition().getTicks() < timePos.getTicks()) + if (clip && clip->endPosition().getTicks() < timePos.getTicks()) { AutomationClip* newClip = makeNewClip(track, timePos, true); // copying the progressionType of the clip before @@ -333,12 +333,12 @@ void AutomatableModelViewSlots::updateSongNearestAutomationNode() AutomationTrack* track = getCurrentAutomationTrack(&clips, false); // this needs to be checked because getCurrentAutomationTrack might give // a nullptr if it can not find and add a track - if (track == nullptr) { return; } + if (!track) { return; } // getting nearest node position AutomationClip* nodeClip = nullptr; TimePos nodePos = getNearestAutomationNode(track, &nodeClip); - if (nodeClip != nullptr) + if (nodeClip) { // modifying its value nodeClip->recordValue(nodePos, m_amv->modelUntyped()->getTrueValue()); @@ -353,11 +353,11 @@ void AutomatableModelViewSlots::removeSongNearestAutomationNode() // this needs to be checked because getCurrentAutomationTrack might give // a nullptr if it can not find and add a track - if (track == nullptr) { return; } + if (!track) { return; } AutomationClip* nodeClip = nullptr; TimePos nodePos = getNearestAutomationNode(track, &nodeClip); - if (nodeClip != nullptr) + if (nodeClip) { nodeClip->removeNode(nodePos); // if there is no node left, the automationClip will be deleted @@ -395,7 +395,7 @@ AutomationTrack* AutomatableModelViewSlots::getCurrentAutomationTrack(std::vecto } output = maxTrack; } - else if (canAddNewTrack == true) + else if (canAddNewTrack) { // adding new track output = new AutomationTrack(getGUI()->songEditor()->m_editor->model(), false); @@ -418,8 +418,11 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr for (Clip* currentClip : trackClips) { tick_t currentTime = currentClip->startPosition().getTicks(); - if ((searchAfter == false && (currentTime > closestTime || closestTime < 0) && timePos.getTicks() > currentTime) - || (searchAfter == true && (currentTime < closestTime || closestTime < 0) && timePos.getTicks() <= currentTime)) + bool smallerCheck = currentTime > closestTime || closestTime < 0; + bool biggerCheck = currentTime < closestTime || closestTime < 0; + + if ((!searchAfter && smallerCheck && timePos.getTicks() > currentTime) + || (searchAfter && biggerCheck && timePos.getTicks() <= currentTime)) { closestTime = currentTime; closestClip = currentClip; @@ -429,7 +432,7 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr // in some cases there could be no clips before or after the global time position // if this is the case, try adding a new one // (if this fails, return nullptr) - if (closestClip == nullptr) + if (!closestClip) { tryAdding = true; } @@ -442,7 +445,7 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr { tryAdding = true; } - if (tryAdding == true && canAddNewClip == true) + if (tryAdding && canAddNewClip) { // adding a new clip output = makeNewClip(track, timePos, true); @@ -461,7 +464,7 @@ const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrac AutomationClip* clipBefore = getCurrentAutomationClip(track, false, false); AutomationClip* clipAfter = getCurrentAutomationClip(track, false, true); - if (clipBefore != nullptr && clipBefore->hasAutomation() == true) + if (clipBefore && clipBefore->hasAutomation()) { // getting nearest node // in the clip that starts before this @@ -476,7 +479,7 @@ const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrac } } } - if (clipAfter != nullptr && clipAfter->hasAutomation() == true) + if (clipAfter && clipAfter->hasAutomation()) { // getting the nearest node // in the clip that starts after this @@ -496,7 +499,7 @@ const TimePos AutomatableModelViewSlots::getNearestAutomationNode(AutomationTrac AutomationClip* AutomatableModelViewSlots::makeNewClip(AutomationTrack* track, TimePos position, bool canSnap) { - if (canSnap == true) + if (canSnap) { // snapping to the bar before position.setTicks(position.getTicks() - position.getTickWithinBar(TimeSig(Engine::getSong()->getTimeSigModel()))); From 3b49c44a431de0ef1f8667fc1ae76d47af3704cf Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Fri, 21 Jun 2024 21:09:35 +0200 Subject: [PATCH 13/14] AutomatableModelView_changed_SLOT_to_function_pointer --- src/gui/AutomatableModelView.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index bbf9c975b23..63aa43d97c3 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -88,19 +88,19 @@ void AutomatableModelView::addDefaultActions( QMenu* menu ) menu->addAction(QPixmap(), AutomatableModel::tr("add automation node"), amvSlots, - SLOT(addSongAutomationNode())); + &AutomatableModelViewSlots::addSongAutomationNode); menu->addAction(QPixmap(), AutomatableModel::tr("add automation node to new clip"), amvSlots, - SLOT(addSongAutomationNodeAndClip())); + &AutomatableModelViewSlots::addSongAutomationNodeAndClip); menu->addAction(QPixmap(), AutomatableModel::tr("update closest automation node"), amvSlots, - SLOT(updateSongNearestAutomationNode())); + &AutomatableModelViewSlots::updateSongNearestAutomationNode); menu->addAction(QPixmap(), AutomatableModel::tr("remove closest automation node"), amvSlots, - SLOT(removeSongNearestAutomationNode())); + &AutomatableModelViewSlots::removeSongNearestAutomationNode); menu->addSeparator(); From 94a339b4d046c1c2c751dce587d884af6da2a35c Mon Sep 17 00:00:00 2001 From: szeli1 <143485814+szeli1@users.noreply.github.com> Date: Fri, 21 Jun 2024 21:25:31 +0200 Subject: [PATCH 14/14] AutomatableModelView_formatting_changes --- include/AutomatableModelView.h | 1 - src/gui/AutomatableModelView.cpp | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index f4e3e04b5b3..2e53023660f 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -88,7 +88,6 @@ class LMMS_EXPORT AutomatableModelView : public ModelView QString m_description; QString m_unit; float m_conversionFactor; // Factor to be applied when the m_model->value is displayed - } ; diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 63aa43d97c3..89cce3290cd 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -420,9 +420,10 @@ AutomationClip* AutomatableModelViewSlots::getCurrentAutomationClip(AutomationTr tick_t currentTime = currentClip->startPosition().getTicks(); bool smallerCheck = currentTime > closestTime || closestTime < 0; bool biggerCheck = currentTime < closestTime || closestTime < 0; + bool searchBeforeCheck = !searchAfter && smallerCheck && timePos.getTicks() > currentTime; + bool searchAfterCheck = searchAfter && biggerCheck && timePos.getTicks() <= currentTime; - if ((!searchAfter && smallerCheck && timePos.getTicks() > currentTime) - || (searchAfter && biggerCheck && timePos.getTicks() <= currentTime)) + if (searchBeforeCheck || searchAfterCheck) { closestTime = currentTime; closestClip = currentClip;