Skip to content

Commit 03ebc92

Browse files
Fixed editor note time mapping
1 parent 54ca278 commit 03ebc92

File tree

2 files changed

+96
-74
lines changed

2 files changed

+96
-74
lines changed

src/ui/component/editor/MIDIContentViewer.cpp

Lines changed: 89 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void MIDIContentViewer::updateBlocks() {
100100
auto list = quickAPI::getBlockList(
101101
{ quickAPI::TrackType::Track, this->index });
102102
for (auto [startTime, endTime, offset] : list) {
103-
this->blockItemTemp.add({ startTime, endTime, startTime - offset });
103+
this->blockItemTemp.add({ startTime, endTime, startTime + offset });
104104
}
105105

106106
/** Sort by Source Start Time to Optimize Note Drawing Time */
@@ -117,6 +117,7 @@ void MIDIContentViewer::updateBlocks() {
117117

118118
/** Update UI */
119119
this->updateBlockImageTemp();
120+
this->updateNoteImageTemp();
120121
this->repaint();
121122
}
122123

@@ -534,8 +535,18 @@ void MIDIContentViewer::midiChannelChanged() {
534535
void MIDIContentViewer::insertNote(
535536
double startTime, double length,
536537
uint8_t pitch, uint8_t channel) {
537-
CoreActions::midiAddNote(this->ref, this->currentMIDITrack,
538-
startTime, startTime + length, channel, pitch, NOTE_VELOCITY_INIT);
538+
/** Match Block */
539+
double endTime = startTime + length;
540+
for (int i = 0; i < this->blockItemTemp.size(); i++) {
541+
auto [blockStartTime, blockEndTime, sourceStartTime] = this->blockItemTemp.getUnchecked(i);
542+
if (blockStartTime <= startTime &&
543+
blockEndTime >= endTime) {
544+
double noteMappedStartTime = sourceStartTime + (startTime - blockStartTime);
545+
CoreActions::midiAddNote(this->ref, this->currentMIDITrack,
546+
noteMappedStartTime, noteMappedStartTime + length, channel, pitch, NOTE_VELOCITY_INIT);
547+
break;
548+
}
549+
}
539550
}
540551

541552
void MIDIContentViewer::updateKeyImageTemp() {
@@ -723,57 +734,71 @@ void MIDIContentViewer::updateNoteImageTemp() {
723734
this->noteRectTempList.clear();
724735
uint8_t midiChannel = Tools::getInstance()->getMIDIChannel();
725736

726-
/** Notes */
737+
/** Blocks */
727738
int minNoteNum = std::floor(this->keyBottom), maxNoteNum = std::floor(this->keyTop);
728-
for (int i = 0; i < this->midiDataTemp.size(); i++) {
729-
auto& note = this->midiDataTemp.getReference(i);
730-
if (note.startSec <= this->secEnd &&
731-
this->secStart <= note.endSec) {
732-
if (note.num >= (minNoteNum - 1) &&
733-
note.num <= maxNoteNum) {
734-
/** Opaque */
735-
float opaque = (note.channel == midiChannel) ? 1.0f : 0.4f;
736-
737-
/** Note Rect */
738-
float startXPos = (note.startSec - this->secStart) / (this->secEnd - this->secStart) * width;
739-
float endXPos = (note.endSec - this->secStart) / (this->secEnd - this->secStart) * width;
740-
float noteYPos = ((note.num + 1) - this->keyTop) / (this->keyBottom - this->keyTop) * height;
741-
juce::Rectangle<float> noteRect(
742-
startXPos, noteYPos,
743-
endXPos - startXPos, (float)this->vItemSize);
744-
g.setColour(noteBaseColor);
745-
g.fillRoundedRectangle(noteRect, noteCornerSize);
746-
g.setColour(this->noteColorGradient[note.channel - 1].withAlpha(opaque));
747-
g.fillRoundedRectangle(noteRect,noteCornerSize);
748-
g.setColour(noteOutlineColor.withAlpha(opaque));
749-
g.drawRoundedRectangle(noteRect, noteCornerSize, noteOutlineThickness);
750-
751-
/** Note Name */
752-
juce::String noteName = this->keyNames[note.num % this->keyMasks.size()] + juce::String{ note.num / this->keyMasks.size() };
753-
float noteNameWidth = juce::TextLayout::getStringWidth(noteLabelFont, noteName);
754-
if ((noteNameWidth + notePaddingWidth * 2) <= noteRect.getWidth()
755-
&& (noteFontHeight + notePaddingHeight * 2) <= noteRect.getHeight()) {
756-
juce::Rectangle<float> noteLabelRect = noteRect.withWidth(noteNameWidth + notePaddingWidth * 2);
757-
g.setFont(noteLabelFont);
758-
g.setColour(this->noteLabelColorGradient[note.channel - 1].withAlpha(opaque));
759-
g.drawFittedText(noteName, noteLabelRect.toNearestInt(),
760-
juce::Justification::centred, 1, 0.75f);
761-
}
762-
763-
/** Lyrics */
764-
float noteLyricsWidth = juce::TextLayout::getStringWidth(noteLyricsFont, note.lyrics);
765-
if (notePaddingWidth * 2 <= noteRect.getWidth()) {
766-
juce::Rectangle<float> noteLyricsRect(
767-
noteRect.getX() + notePaddingWidth, noteRect.getY() - (float)this->vItemSize,
768-
noteRect.getWidth() - notePaddingWidth * 2, (float)this->vItemSize);
769-
g.setFont(noteLyricsFont);
770-
g.setColour(noteLyricsColor.withAlpha(opaque));
771-
g.drawFittedText(note.lyrics, noteLyricsRect.toNearestInt(),
772-
juce::Justification::left, 1, 1.0f);
739+
for (int i = 0; i < this->blockItemTemp.size(); i++) {
740+
auto [blockStartTime, blockEndTime, sourceStartTime] = this->blockItemTemp.getUnchecked(i);
741+
if ((blockStartTime <= this->secEnd)
742+
&& (blockEndTime >= this->secStart)) {
743+
double sourceEndTime = sourceStartTime + (blockEndTime - blockStartTime);
744+
745+
/** For Each Notes */
746+
for (int j = 0; j < this->midiDataTemp.size(); j++) {
747+
auto& note = this->midiDataTemp.getReference(j);
748+
if (note.startSec <= sourceEndTime &&
749+
sourceStartTime <= note.endSec) {
750+
double noteMappedStartSec = blockStartTime + (note.startSec - sourceStartTime);
751+
double noteMappedEndSec = blockStartTime + (note.endSec - sourceStartTime);
752+
if (noteMappedStartSec <= this->secEnd &&
753+
this->secStart <= noteMappedEndSec) {
754+
if (note.num >= (minNoteNum - 1) &&
755+
note.num <= maxNoteNum) {
756+
/** Opaque */
757+
float opaque = (note.channel == midiChannel) ? 1.0f : 0.4f;
758+
759+
/** Note Rect */
760+
float startXPos = (noteMappedStartSec - this->secStart) / (this->secEnd - this->secStart) * width;
761+
float endXPos = (noteMappedEndSec - this->secStart) / (this->secEnd - this->secStart) * width;
762+
float noteYPos = ((note.num + 1) - this->keyTop) / (this->keyBottom - this->keyTop) * height;
763+
juce::Rectangle<float> noteRect(
764+
startXPos, noteYPos,
765+
endXPos - startXPos, (float)this->vItemSize);
766+
g.setColour(noteBaseColor);
767+
g.fillRoundedRectangle(noteRect, noteCornerSize);
768+
g.setColour(this->noteColorGradient[note.channel - 1].withAlpha(opaque));
769+
g.fillRoundedRectangle(noteRect, noteCornerSize);
770+
g.setColour(noteOutlineColor.withAlpha(opaque));
771+
g.drawRoundedRectangle(noteRect, noteCornerSize, noteOutlineThickness);
772+
773+
/** Note Name */
774+
juce::String noteName = this->keyNames[note.num % this->keyMasks.size()] + juce::String{ note.num / this->keyMasks.size() };
775+
float noteNameWidth = juce::TextLayout::getStringWidth(noteLabelFont, noteName);
776+
if ((noteNameWidth + notePaddingWidth * 2) <= noteRect.getWidth()
777+
&& (noteFontHeight + notePaddingHeight * 2) <= noteRect.getHeight()) {
778+
juce::Rectangle<float> noteLabelRect = noteRect.withWidth(noteNameWidth + notePaddingWidth * 2);
779+
g.setFont(noteLabelFont);
780+
g.setColour(this->noteLabelColorGradient[note.channel - 1].withAlpha(opaque));
781+
g.drawFittedText(noteName, noteLabelRect.toNearestInt(),
782+
juce::Justification::centred, 1, 0.75f);
783+
}
784+
785+
/** Lyrics */
786+
float noteLyricsWidth = juce::TextLayout::getStringWidth(noteLyricsFont, note.lyrics);
787+
if (notePaddingWidth * 2 <= noteRect.getWidth()) {
788+
juce::Rectangle<float> noteLyricsRect(
789+
noteRect.getX() + notePaddingWidth, noteRect.getY() - (float)this->vItemSize,
790+
noteRect.getWidth() - notePaddingWidth * 2, (float)this->vItemSize);
791+
g.setFont(noteLyricsFont);
792+
g.setColour(noteLyricsColor.withAlpha(opaque));
793+
g.drawFittedText(note.lyrics, noteLyricsRect.toNearestInt(),
794+
juce::Justification::left, 1, 1.0f);
795+
}
796+
797+
/** Add Temp */
798+
this->noteRectTempList.add({ j, noteRect, note.channel });
799+
}
800+
}
773801
}
774-
775-
/** Add Temp */
776-
this->noteRectTempList.add({ i, noteRect, note.channel });
777802
}
778803
}
779804
}
@@ -820,9 +845,9 @@ MIDIContentViewer::getNoteController(const juce::Point<float>& pos) const {
820845
/** Check Pos Inside Note */
821846
auto [type, index] = this->getNoteControllerWithoutEdge(pos);
822847
if (index >= 0) {
823-
auto& note = this->midiDataTemp.getReference(index);
824-
float startXPos = (note.startSec - this->secStart) / (this->secEnd - this->secStart) * width;
825-
float endXPos = (note.endSec - this->secStart) / (this->secEnd - this->secStart) * width;
848+
auto& note = this->noteRectTempList.getReference(index);
849+
float startXPos = std::get<1>(note).getX();
850+
float endXPos = std::get<1>(note).getRight();
826851

827852
/** Judge Area */
828853
float judgeSSX = startXPos - noteJudgeWidth, judgeSEX = startXPos + noteJudgeWidth;
@@ -844,8 +869,9 @@ MIDIContentViewer::getNoteController(const juce::Point<float>& pos) const {
844869
}
845870
}
846871

847-
/** Get Each Block */
848-
for (auto& [index, rect, channel] : this->noteRectTempList) {
872+
/** Get Each Note */
873+
for (int i = 0; i < this->noteRectTempList.size(); i++) {
874+
auto& [index, rect, channel] = this->noteRectTempList.getReference(i);
849875
if (channel == midiChannel) {
850876
if (pos.getY() >= rect.getY() && pos.getY() < rect.getBottom()) {
851877
/** Judge Area */
@@ -858,13 +884,13 @@ MIDIContentViewer::getNoteController(const juce::Point<float>& pos) const {
858884

859885
/** Get Controller */
860886
if (pos.getX() >= judgeSSX && pos.getX() < judgeSEX) {
861-
return { NoteControllerType::Left, index };
887+
return { NoteControllerType::Left, i };
862888
}
863889
else if (pos.getX() >= judgeESX && pos.getX() < judgeEEX) {
864-
return { NoteControllerType::Right, index };
890+
return { NoteControllerType::Right, i };
865891
}
866892
else if (pos.getX() >= judgeSEX && pos.getX() < judgeESX) {
867-
return { NoteControllerType::Inside, index };
893+
return { NoteControllerType::Inside, i };
868894
}
869895
}
870896
}
@@ -880,12 +906,13 @@ MIDIContentViewer::getNoteControllerWithoutEdge(const juce::Point<float>& pos) c
880906
uint8_t midiChannel = Tools::getInstance()->getMIDIChannel();
881907

882908
/** Get Each Note */
883-
for (auto& [index, rect, channel] : this->noteRectTempList) {
909+
for (int i = 0; i < this->noteRectTempList.size(); i++) {
910+
auto& [index, rect, channel] = this->noteRectTempList.getReference(i);
884911
/** Inside Note */
885912
if (channel == midiChannel) {
886913
if (pos.getX() >= rect.getX() && pos.getX() < rect.getRight()
887914
&& pos.getY() >= rect.getY() && pos.getY() < rect.getBottom()) {
888-
return { NoteControllerType::Inside, index };
915+
return { NoteControllerType::Inside, i };
889916
}
890917
}
891918
}

src/ui/component/editor/MIDISourceEditor.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ void MIDISourceEditor::updateBlockTemp() {
482482
auto list = quickAPI::getBlockList(
483483
{ quickAPI::TrackType::Track, this->index });
484484
for (auto [startTime, endTime, offset] : list) {
485-
this->blockItemTemp.add({ startTime, endTime, startTime - offset });
485+
this->blockItemTemp.add({ startTime, endTime, startTime + offset });
486486
}
487487

488488
/** Sort by Source Start Time to Optimize Note Drawing Time */
@@ -551,7 +551,7 @@ void MIDISourceEditor::updateMIDIScrollerImageTemp() {
551551

552552
/** Actual Total Length */
553553
double totalLength = ScrollerBase::limitItemNum(
554-
this->hScroller->getItemNum(), this->getViewWidth(),
554+
this->getTimeLength(), this->getViewWidth(),
555555
std::get<0>(this->getTimeWidthLimit()));
556556
juce::Rectangle<float> paintableArea = this->midiScrollerTemp->getBounds()
557557
.toFloat().withTrimmedTop(paddingHeight).withTrimmedBottom(paddingHeight);
@@ -569,24 +569,19 @@ void MIDISourceEditor::updateMIDIScrollerImageTemp() {
569569

570570
/** Paint Each Block */
571571
g.setColour(noteColor);
572-
int startNoteIndexTemp = 0;
573572
for (int i = 0; i < this->blockItemTemp.size(); i++) {
574573
auto [blockStart, blockEnd, sourceStart] = this->blockItemTemp.getUnchecked(i);
575-
576-
/** Skip Notes Before Block */
577-
for (; startNoteIndexTemp < this->midiDataTemp.size(); startNoteIndexTemp++) {
578-
auto [start, end, num] = this->midiDataTemp.getUnchecked(startNoteIndexTemp);
579-
if (start >= blockStart) { break; }
580-
}
574+
double sourceEnd = sourceStart + (blockEnd - blockStart);
581575

582576
/** Paint Each Note */
583-
for (int j = startNoteIndexTemp; j < this->midiDataTemp.size(); j++) {
577+
for (int j = 0; j < this->midiDataTemp.size(); j++) {
584578
auto [start, end, num] = this->midiDataTemp.getUnchecked(j);
585-
if (start >= blockEnd) { break; }
579+
if (end < sourceStart) { continue; }
580+
if (start > sourceEnd) { break; }
586581

587582
/** Get Time */
588583
double startInSeq = blockStart + (start - sourceStart);
589-
double endInSeq = std::min(blockStart + (end - sourceStart), blockEnd);
584+
double endInSeq = blockStart + (end - sourceStart);
590585

591586
/** Note Rect */
592587
float startPosX = startInSeq / totalLength * paintableArea.getWidth();

0 commit comments

Comments
 (0)