Add the copy/paste selected timing data feature.

Not perfect at this stage, but...well, everyone wanted it.
This commit is contained in:
Jason Felds
2011-07-26 16:05:14 -04:00
parent 4eeb2e6442
commit 9505e09f58
5 changed files with 162 additions and 15 deletions
+6
View File
@@ -8,6 +8,12 @@ ________________________________________________________________________________
StepMania 5.0 ????????? | 20110???
--------------------------------------------------------------------------------
2011/07/26
----------
* [ScreenEdit] Add a semi working implementation of the often requested
copy/paste selected timing data feature. This should make it easier for
some charters. [Wolfman2000]
2011/07/21
----------
* [BeginnerHelper] Removed DancePadAngle metric in favor of DancePadOnCommand.
+1
View File
@@ -975,6 +975,7 @@ OsMountPlayer2=OS Mount Player2
Paste at begin marker=Paste at begin marker
Paste at current beat=Paste at current beat
Paste timing data=Paste timing data
Paste Partial Timing at current beat=Paste Partial Timing at current beat
Persp=Persp
Play current beat to end=Play current beat to end
Play preview music=Play preview music
+81 -2
View File
@@ -588,7 +588,8 @@ static MenuDef g_AreaMenu(
"ScreenMiniMenuAreaMenu",
MenuRowDef( ScreenEdit::paste_at_current_beat, "Paste at current beat", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::paste_at_begin_marker, "Paste at begin marker", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::insert_and_shift, "Insert beat and shift down", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::paste_partial_timing_at_beat, "Paste Partial Timing at current beat", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::insert_and_shift, "Insert beat and shift down", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::delete_and_shift, "Delete beat and shift up", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::shift_pauses_forward, "Shift all timing changes down", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::shift_pauses_backward, "Shift all timing changes up", true, EditMode_Full, true, true, 0, NULL ),
@@ -1742,6 +1743,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
// update enabled/disabled in g_AreaMenu
g_AreaMenu.rows[paste_at_current_beat].bEnabled = !m_Clipboard.IsEmpty();
g_AreaMenu.rows[paste_at_begin_marker].bEnabled = !m_Clipboard.IsEmpty() != 0 && m_NoteFieldEdit.m_iBeginMarker!=-1;
g_AreaMenu.rows[paste_partial_timing_at_beat].bEnabled = !this->clipboardTiming.empty();
g_AreaMenu.rows[undo].bEnabled = m_bHasUndo;
EditMiniMenu( &g_AreaMenu, SM_BackFromAreaMenu );
}
@@ -2926,7 +2928,9 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
}
else if( SM == SM_BackFromAreaMenu )
{
HandleAreaMenuChoice( (AreaMenuChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers );
AreaMenuChoice amc = static_cast<AreaMenuChoice>(ScreenMiniMenu::s_iLastRowCode);
const vector<int> &answers = ScreenMiniMenu::s_viLastAnswers;
HandleAreaMenuChoice( amc, answers );
}
else if( SM == SM_BackFromAlterMenu )
{
@@ -4305,6 +4309,81 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
m_NoteDataEdit.CopyRange( m_Clipboard, 0, iRowsToCopy, iDestFirstRow );
}
break;
case paste_partial_timing_at_beat:
{
int firstRow = BeatToNoteRow(GetAppropriatePosition().m_fSongBeat);
FOREACH_ENUM(TimingSegmentType, tst)
{
/* TODO: Maybe wipe out the already there timing data first?
* We need to identify the max row within the timing data first. */
for (unsigned i = 0; i < this->clipboardTiming.allTimingSegments[tst].size(); i++)
{
// TODO: This REALLY needs improving.
TimingSegment * org = this->clipboardTiming.allTimingSegments[tst][i];
TimingSegment * cpy;
switch (tst)
{
case SEGMENT_BPM:
{
cpy = new BPMSegment(*(static_cast<BPMSegment *>(org)));
break;
}
case SEGMENT_STOP_DELAY:
{
cpy = new StopSegment(*(static_cast<StopSegment *>(org)));
break;
}
case SEGMENT_TIME_SIG:
{
cpy = new TimeSignatureSegment(*(static_cast<TimeSignatureSegment *>(org)));
break;
}
case SEGMENT_WARP:
{
cpy = new WarpSegment(*(static_cast<WarpSegment *>(org)));
break;
}
case SEGMENT_LABEL:
{
cpy = new LabelSegment(*(static_cast<LabelSegment *>(org)));
break;
}
case SEGMENT_TICKCOUNT:
{
cpy = new TickcountSegment(*(static_cast<TickcountSegment *>(org)));
break;
}
case SEGMENT_COMBO:
{
cpy = new ComboSegment(*(static_cast<ComboSegment *>(org)));
break;
}
case SEGMENT_SPEED:
{
cpy = new SpeedSegment(*(static_cast<SpeedSegment *>(org)));
break;
}
case SEGMENT_SCROLL:
{
cpy = new ScrollSegment(*(static_cast<ScrollSegment *>(org)));
break;
}
case SEGMENT_FAKE:
{
cpy = new FakeSegment(*(static_cast<FakeSegment *>(org)));
break;
}
default: FAIL_M(ssprintf("An unknown timing segment type %d can't be copied over!", tst));
}
int oldRow = cpy->GetRow();
int newRow = oldRow + firstRow;
cpy->SetRow(newRow);
GetAppropriateTiming().AddSegment(tst, cpy);
}
}
break;
}
case insert_and_shift:
NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow( GetBeat() ), BeatToNoteRow(1) );
break;
+6 -5
View File
@@ -423,17 +423,18 @@ public:
enum AreaMenuChoice
{
paste_at_current_beat,
paste_at_begin_marker,
paste_at_current_beat, /**< Paste note data starting at the current beat. */
paste_at_begin_marker, /**< Paste note data starting at the first market. */
paste_partial_timing_at_beat, /**< Paste TimingData starting at the current beat. */
insert_and_shift,
delete_and_shift,
shift_pauses_forward,
shift_pauses_backward,
shift_pauses_forward, /**< Shift all timing changes forward one beat. */
shift_pauses_backward, /**< Shift all timing changes backward one beat. */
convert_pause_to_beat,
convert_delay_to_beat,
last_second_at_beat,
undo,
clear_clipboard,
clear_clipboard, /**< Clear the clipboards. */
NUM_AREA_MENU_CHOICES
};
void HandleAlterMenuChoice(AlterMenuChoice c,
+68 -8
View File
@@ -29,22 +29,83 @@ bool TimingData::empty() const
TimingData TimingData::CopyRange(int startRow, int endRow) const
{
TimingData tmp;
TimingData ret;
for (unsigned i = 0; i < NUM_TimingSegmentType; i++)
FOREACH_ENUM(TimingSegmentType, tst)
{
for (unsigned j = 0; j < this->allTimingSegments[i].size(); j++)
unsigned cnt = 0;
for (unsigned j = 0; j < this->allTimingSegments[tst].size(); j++)
{
int row = this->allTimingSegments[i][j]->GetRow();
int row = this->allTimingSegments[tst][j]->GetRow();
if (row >= startRow && row < endRow)
{
tmp.AddSegment(static_cast<TimingSegmentType>(i),
this->allTimingSegments[i][j]);
// TODO: This REALLY needs improving.
TimingSegment * org = this->allTimingSegments[tst][j];
TimingSegment * cpy;
switch (tst)
{
case SEGMENT_BPM:
{
cpy = new BPMSegment(*(static_cast<BPMSegment *>(org)));
break;
}
case SEGMENT_STOP_DELAY:
{
cpy = new StopSegment(*(static_cast<StopSegment *>(org)));
break;
}
case SEGMENT_TIME_SIG:
{
cpy = new TimeSignatureSegment(*(static_cast<TimeSignatureSegment *>(org)));
break;
}
case SEGMENT_WARP:
{
cpy = new WarpSegment(*(static_cast<WarpSegment *>(org)));
break;
}
case SEGMENT_LABEL:
{
cpy = new LabelSegment(*(static_cast<LabelSegment *>(org)));
break;
}
case SEGMENT_TICKCOUNT:
{
cpy = new TickcountSegment(*(static_cast<TickcountSegment *>(org)));
break;
}
case SEGMENT_COMBO:
{
cpy = new ComboSegment(*(static_cast<ComboSegment *>(org)));
break;
}
case SEGMENT_SPEED:
{
cpy = new SpeedSegment(*(static_cast<SpeedSegment *>(org)));
break;
}
case SEGMENT_SCROLL:
{
cpy = new ScrollSegment(*(static_cast<ScrollSegment *>(org)));
break;
}
case SEGMENT_FAKE:
{
cpy = new FakeSegment(*(static_cast<FakeSegment *>(org)));
break;
}
default: FAIL_M(ssprintf("An unknown timing segment type %d can't be copied over!", tst));
}
// reset the rows as if startRow was beat 0.
cpy->SetRow(org->GetRow() - startRow);
ret.AddSegment(tst, cpy);
cnt++;
}
}
}
return tmp;
return ret;
}
void TimingData::GetActualBPM( float &fMinBPMOut, float &fMaxBPMOut, float highest ) const
@@ -655,7 +716,6 @@ bool TimingData::IsFakeAtRow( int iNoteRow ) const
BPMSegment* TimingData::GetBPMSegmentAtRow( int iNoteRow )
{
vector<TimingSegment *> &bpms = this->allTimingSegments[SEGMENT_BPM];
static BPMSegment empty;
if( bpms.empty() )
return new BPMSegment();