-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds feature to merge Instrument Track patterns #5700
Conversation
This branch aims to create a feature for merging Instrument Track's patterns in a single pattern. Current changes: - Adds a getPattern method to PatternView. - Adds a context menu action called "Merge". - Inside TrackContentObjectView::contextMenuEvent, we check if the selected TCOs can be merged and store the answer in a boolean called canMergeTCOs. The conditions to merge TCOs are: Having multiple TCOs selected; All TCOs belonging to a InstrumentTrack; All TCOs belonging to the same track. - If canMergeTCOs is true, add an action on the context menu for merging the selection. - Creates a method called TrackContentObjectView::mergeTCOs( tcovs ). That method first finds the earliest MidiTime from all selected TCOs and creates a pattern on that position. Then, notes are added to that pattern and repositioned depending on the relative position from the current TCOV being merged in relation to the new pattern. Some warnings were added to this method in case dynamic_casts failed, though they shouldn't. After all notes being added and positioned, newPattern->updateLength() and newPattern->dataChanged() are called. Known Bugs: - Some added notes don't play until you make a change (i.e.: move them) in the PianoRoll. To Do: - Remove QDebug include on Track.cpp. - Remove some debugging warnings. - Change the PixMap for the Merge Selection action on the context menu. - Fix bugs.
This commit fixes a previous bug where some notes wouldn't play after a merge operation happened. Apparently the root cause was Pattern->rearrangeAllNotes() not being called. It seems to be crucial that the notes are arranged in the right order for them to play properly. Removes QDebug header and includes Note.h.
This commit reorganizes the code a little bit to make it better suited for review. The code that checked whether a selection can be merged was extracted to a separate method called TrackContentObjectView::canMergeSelection(). Two conditionals inside that code were merged into a single one, since they both resulted in the same action. Also updated a comment next to a line of code that is probably going to be removed after the PR LMMS#5699 is merged (it's currently necessary because of a bug that is fixed on that PR).
🤖 Hey, I'm @LmmsBot from github.com/lmms/bot and I made downloads for this pull request, click me to make them magically appear! 🎩
Linux
Windows
🤖{"platform_name_to_artifacts": {"Linux": [{"artifact": {"title": {"title": "(AppImage)", "platform_name": "Linux"}, "link": {"link": "https://11485-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.65%2Bg65346d7-linux-x86_64.AppImage"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/11485?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}], "Windows": [{"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://11488-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.65%2Bg65346d700-mingw-win64.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/11488?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://11486-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.65%2Bg65346d700-mingw-win32.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/11486?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/2y8s81wi95vhlwdn/artifacts/build/lmms-1.3.0-alpha-msvc2017-win32.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/36757377"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/lg711cavwv87ef5m/artifacts/build/lmms-1.3.0-alpha-msvc2017-win64.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/36757377"}]}, "commit_sha": "1c612163ae20f728635f0b22839f7c214c136f66"} |
[Note: this is my first review, so let me know if you need more detail] The averall functionality works fine with me. Some issues, though:
|
Thanks for testing and giving feedback!
That is expected because the clip's size is recalculated so it is the shorted possible on the song editor (that also happens on the piano roll, if you delete notes from the last bar the clip will be shortened to have the fewest bars it can). So when you merge an empty clip with a non-empty one on that order it doesn't get shortened, because there are notes at the end of the clip. But if you merge a non-empty clip with an empty one the empty bars at the end are ignored and the clip is shortened to be the smallest size possible. They are still being merged though.
Oh yeah, I actually didn't write a history system for merging, so the undo behavior you're seeing is being caused by some calls that are made inside the merge operation (
When you merge 2 clips and hit CTRL+Z, it first undo the clips being removed and then the new empty clip being created. You can confirm it by hitting CTRL+Z only once and then moving the clip: you'll see the two clips you had before below it. I'm not sure it's worth it trying to fix it, specially because the history system is currently in a very unstable state already (I'd advise against using it at all and instead constantly saving the project as a new version) and is among the plans of things to be changed in the future. But I'll take a better look at it! |
You should get most of the way to a correct undo by calling |
You're right, I'll try to make it work here! |
Fixes the history system for the merge operation by adding a journal checkpoint on the track where the merge is happening and disabling the journalling state of everything being handled during the operation, restoring the journalling state at the end.
The history system was fixed for the merge operation, undo and redo should work fine now. I've a small doubt whether it's a good idea to restore the journalling state of a TCO after removing it, when I disabled it before removing. For now, I'm restoring the state but I left a TODO comment to remind me of removing the method call if it's unnecessary. |
It works fine now, both undo as redo. I've tried with like 100 different patterns and it worked! |
Awesome, glad it's working now! Thanks for testing man! |
Fixes merge conflict on include/Track.h
After the bug fix from LMMS#5699, there's no need to call movePosition on a TCO that was created with a position on its constructor. The line that called movePosition was removed. Code style was also fixed.
Merged master and removed line that is now unnecessary since the bug fix from #5699 . |
After recently merge that renames MidiTime to TimePos, the code was updated to use the new class name.
Fixes conflict caused by LMMS#5806, which splitted Track.cpp and Track.h
After removing a TCO I was calling restoreJournallingState on it, thinking it could be necessary for the journalling state be restored when the history Undo brings the TCO back. It doesn't make much sense that this would be necessary, so I'm removing it. After testing, it seems like restoring the TCO through Undo brings it back with the journalling state restored.
Fixed another conflict introduced by #5806 , changed the pointer declarations so they adhere to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Suggested a few potential changes to make things shorter, but I haven't tested them to ensure they're totally correct so there might be syntax issues and such.
Change canMergeTCOs to use logical operators instead of the ternary operator. Avoids repeating the dynamic_cast unnecessarily on the canMergeSelection method.
Saves lots of lines on canMergeSelection by using a data set to store all the TCO owner tracks, so we can later check how many tracks we have. Uses std::min_element to find the earliest TCOV and get it's starting position.
The logic that returned we couldn't merge a single TCO was inside contextMenuEvent, when it suited more the canMergeSelection method. That was moved there and now even if canMergeSelection receives a list with just a single TCO it will return that it can't be merged.
Calls restoreJournallingState respecting the push/pop order in relation to the saveJournallingState calls. Fix a comment.
Merge^2? |
Sure, I think it's good to go! And it has 2 approvals now 😄 |
This PR implements a new action on the context menu of TrackContentObjectViews for merging note patterns. It's only applicable for InstrumentTrack's TCOs. In terms of changes on the code those were the main ones:
getPattern
method on thePatternView
so we can add the notes to a pattern obtained from a pattern view.canMergeSelection
andmergeTCOs
. The first check if a vector of TCOVs can be merged (the conditions: more than one TCO being selected, they all belonging to an Instrument Track and they all belonging to the same track). The second does the actual merging, by creating a new TCO and adding all the notes to it while removing the merged TCOs.TODO:
comment regarding a statement that should be removed once Fixes createTCO method on some classes #5699 is merged.There are a few warnings that might be unnecessary (they cover some situations that should not normally happen). A placeholder icon was created for the action, which could be later substituted by a better one.