diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 2b44eee848..a140e09d77 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -843,6 +843,7 @@ Edit time signature (top)=Edit time signature (beats per measure) Edit time signature (bottom)=Edit time signature (single beat note value) Edit tickcount=Edit tickcount Edit combo=Edit combo +Edit label=Edit label Edit warp=Edit warp Editor options=Options EditorShowBGChangesPlay=Show Backgrounds @@ -1210,6 +1211,7 @@ Enter a new Time Signature numerator value.=Enter the number of beats per measur Enter a new Time Signature denominator value.=Enter the note value that represents one beat. Enter a new Tickcount value.=Enter a new Tickcount value. Enter a new Combo value.=Enter a new Combo value. +Enter a new Label value.=Enter a name for this section of the chart. Enter a new Warp value.=Enter the beat you will warp to when you reach this point. Enter a new artist transliteration.=Enter a new artist transliteration. Enter a new artist.=Enter a new artist. diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 524bda0550..ab4339e527 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -981,6 +981,7 @@ WarpColor=color("1,0,0.5,1") TimeSignatureColor=color("1,0.55,0,1") TickcountColor=color("0,1,0,1") ComboColor=color("0.55,1,0,1") +LabelColor=color("1,0,0,1") # BPMIsLeftSide=true StopIsLeftSide=true @@ -989,6 +990,7 @@ WarpIsLeftSide=false TimeSignatureIsLeftSide=true TickcountIsLeftSide=false ComboIsLeftSide=false +LabelIsLeftSide=false # BPMOffsetX=60 StopOffsetX=50 @@ -997,6 +999,7 @@ WarpOffsetX=60 TimeSignatureOffsetX=30 TickcountOffsetX=10 ComboOffsetX=30 +LabelOffsetX=80 [PlayerStageStats] # Original CVS Grading diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 958866b0a5..c1b7a9f0e7 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -426,6 +426,7 @@ static ThemeMetric WARP_COLOR ( "NoteField", "WarpColor" ); static ThemeMetric TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignatureColor" ); static ThemeMetric TICKCOUNT_COLOR ( "NoteField", "TickcountColor" ); static ThemeMetric COMBO_COLOR ( "NoteField", "ComboColor" ); +static ThemeMetric LABEL_COLOR ( "NoteField", "LabelColor" ); static ThemeMetric BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" ); static ThemeMetric STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" ); static ThemeMetric DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" ); @@ -433,6 +434,7 @@ static ThemeMetric WARP_IS_LEFT_SIDE ( "NoteField", "WarpIsLeftSide" ); static ThemeMetric TIME_SIGNATURE_IS_LEFT_SIDE ( "NoteField", "TimeSignatureIsLeftSide" ); static ThemeMetric TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftSide" ); static ThemeMetric COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" ); +static ThemeMetric LABEL_IS_LEFT_SIDE ( "NoteField", "LabelIsLeftSide" ); static ThemeMetric BPM_OFFSETX ( "NoteField", "BPMOffsetX" ); static ThemeMetric STOP_OFFSETX ( "NoteField", "StopOffsetX" ); static ThemeMetric DELAY_OFFSETX ( "NoteField", "DelayOffsetX" ); @@ -440,6 +442,7 @@ static ThemeMetric WARP_OFFSETX ( "NoteField", "WarpOffsetX" ); static ThemeMetric TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOffsetX" ); static ThemeMetric TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" ); static ThemeMetric COMBO_OFFSETX ( "NoteField", "ComboOffsetX" ); +static ThemeMetric LABEL_OFFSETX ( "NoteField", "LabelOffsetX" ); void NoteField::DrawBPMText( const float fBeat, const float fBPM ) { @@ -552,6 +555,23 @@ void NoteField::DrawComboText( const float fBeat, int iCombo ) m_textMeasureNumber.Draw(); } +void NoteField::DrawLabelText( const float fBeat, RString sLabel ) +{ + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); + const float xBase = GetWidth()/2.f; + const float xOffset = LABEL_OFFSETX * fZoom; + + m_textMeasureNumber.SetZoom( fZoom ); + m_textMeasureNumber.SetHorizAlign( LABEL_IS_LEFT_SIDE ? align_right : align_left ); + m_textMeasureNumber.SetDiffuse( LABEL_COLOR ); + m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); + m_textMeasureNumber.SetText( sLabel.c_str() ); + m_textMeasureNumber.SetXY( (LABEL_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); + m_textMeasureNumber.Draw(); +} + void NoteField::DrawAttackText( const float fBeat, const Attack &attack ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); diff --git a/src/NoteField.h b/src/NoteField.h index 08a83e11aa..23502eca00 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -61,6 +61,7 @@ protected: void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator ); void DrawTickcountText( const float fBeat, int iTicks ); void DrawComboText( const float fBeat, int iCombo ); + void DrawLabelText( const float fBeat, RString sLabel ); void DrawAttackText( const float fBeat, const Attack &attack ); void DrawBGChangeText( const float fBeat, const RString sNewBGName ); float GetWidth() const; diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index b315b74098..c483ca0a7c 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -80,6 +80,7 @@ AutoScreenMessage( SM_BackFromTimeSignatureNumeratorChange ); AutoScreenMessage( SM_BackFromTimeSignatureDenominatorChange ); AutoScreenMessage( SM_BackFromTickcountChange ); AutoScreenMessage( SM_BackFromComboChange ); +AutoScreenMessage( SM_BackFromLabelChange ); AutoScreenMessage( SM_BackFromWarpChange ); AutoScreenMessage( SM_DoSaveAndExit ); AutoScreenMessage( SM_DoExit ); @@ -255,6 +256,14 @@ void ScreenEdit::InitEditMappings() m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT); m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT); + m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_PERIOD); + m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL); + m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL); + + m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_COMMA); + m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL); + m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL); + m_EditMappingsDeviceInput.button[EDIT_BUTTON_SNAP_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LEFT); m_EditMappingsDeviceInput.button[EDIT_BUTTON_SNAP_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_RIGHT); @@ -551,6 +560,7 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ) ); @@ -1425,6 +1435,18 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) ScrollTo( NoteRowToBeat(iRow) ); } break; + case EDIT_BUTTON_LABEL_NEXT: + { + ScrollTo( GAMESTATE->m_pCurSong->m_Timing. + GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) ); + } + break; + case EDIT_BUTTON_LABEL_PREV: + { + ScrollTo( GAMESTATE->m_pCurSong->m_Timing. + GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) ); + } + break; case EDIT_BUTTON_SNAP_NEXT: if( m_SnapDisplay.PrevSnapMode() ) OnSnapModeChange(); @@ -2644,6 +2666,14 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } SetDirty( true ); } + else if ( SM == SM_BackFromLabelChange ) + { + RString sLabel = ScreenTextEntry::s_sLastAnswer; + sLabel.Replace("=", "_"); + sLabel.Replace(",", "_"); + m_pSong->m_Timing.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel ); + SetDirty( true ); + } else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); @@ -3187,6 +3217,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); @@ -3618,6 +3649,7 @@ static LocalizedString ENTER_TIME_SIGNATURE_NUMERATOR_VALUE ( "ScreenEdit", "Ent static LocalizedString ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature denominator value." ); static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tickcount value." ); static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." ); +static LocalizedString ENTER_LABEL_VALUE ( "ScreenEdit", "Enter a new Label value." ); static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp value." ); void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector &iAnswers ) { @@ -3680,6 +3712,14 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice 4 ); break; + case label: + ScreenTextEntry::TextEntry( + SM_BackFromLabelChange, + ENTER_LABEL_VALUE, + ssprintf( "%s", m_pSong->m_Timing.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ), + 64 + ); + break; case warp: ScreenTextEntry::TextEntry( SM_BackFromWarpChange, diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 1f79b78528..f64772cc27 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -70,6 +70,9 @@ enum EditButton EDIT_BUTTON_SCROLL_NEXT, EDIT_BUTTON_SCROLL_PREV, + EDIT_BUTTON_LABEL_NEXT, + EDIT_BUTTON_LABEL_PREV, + // These are modifiers to EDIT_BUTTON_SCROLL_*. EDIT_BUTTON_SCROLL_SELECT, @@ -456,6 +459,7 @@ public: time_signature_denominator, tickcount, combo, + label, warp, NUM_TIMING_DATA_INFORMATION_CHOICES }; diff --git a/src/TimingData.cpp b/src/TimingData.cpp index b1f36960fa..68f0a81431 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -496,11 +496,11 @@ WarpSegment& TimingData::GetWarpSegmentAtRow( int iRow ) int TimingData::GetTickcountSegmentIndexAtRow( int iRow ) const { - int i; - for (i=0; i < (int)(m_TickcountSegments.size()) - 1; i++ ) + unsigned i; + for (i=0; i < m_TickcountSegments.size() - 1; i++ ) if( m_TickcountSegments[i+1].m_iStartRow > iRow ) break; - return i; + return static_cast(i); } TickcountSegment& TimingData::GetTickcountSegmentAtRow( int iRow ) @@ -518,6 +518,37 @@ int TimingData::GetTickcountAtRow( int iRow ) const return m_TickcountSegments[GetTickcountSegmentIndexAtRow( iRow )].m_iTicks; } +float TimingData::GetPreviousLabelSegmentBeatAtRow( int iRow ) const +{ + float backup = -1; + for (unsigned i = 0; i < m_LabelSegments.size(); i++ ) + { + if( m_LabelSegments[i].m_iStartRow > iRow ) + { + if( backup > -1 ) + { + return backup; + } + break; + } + backup = NoteRowToBeat(m_LabelSegments[i].m_iStartRow); + } + return NoteRowToBeat(iRow); +} + +float TimingData::GetNextLabelSegmentBeatAtRow( int iRow ) const +{ + for (unsigned i = 0; i < m_LabelSegments.size(); i++ ) + { + if( m_LabelSegments[i].m_iStartRow <= iRow ) + { + continue; + } + return NoteRowToBeat(m_LabelSegments[i].m_iStartRow); + } + return NoteRowToBeat(iRow); +} + void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const { fElapsedTime += PREFSMAN->m_fGlobalOffsetSeconds; @@ -634,9 +665,6 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float } - - - float TimingData::GetElapsedTimeFromBeat( float fBeat ) const { return TimingData::GetElapsedTimeFromBeatNoOffset( fBeat ) - PREFSMAN->m_fGlobalOffsetSeconds; diff --git a/src/TimingData.h b/src/TimingData.h index e542c60d89..1c0a7edcb2 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -1202,6 +1202,32 @@ public: */ void AddLabelSegment( const LabelSegment &seg ); + /** + * @brief Retrieve the previous beat that contains a LabelSegment. + * @param iRow the present row. + * @return the previous beat with a LabelSegment, or fBeat if there is none prior. + */ + float GetPreviousLabelSegmentBeatAtRow( int iRow ) const; + /** + * @brief Retrieve the previous beat that contains a LabelSegment. + * @param fBeat the present beat. + * @return the previous beat with a LabelSegment, or fBeat if there is none prior. + */ + float GetPreviousLabelSegmentBeatAtBeat( float fBeat ) const { return GetPreviousLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); } + + /** + * @brief Retrieve the next beat that contains a LabelSegment. + * @param iRow the present row. + * @return the next beat with a LabelSegment, or fBeat if there is none ahead. + */ + float GetNextLabelSegmentBeatAtRow( int iRow ) const; + /** + * @brief Retrieve the previous beat that contains a LabelSegment. + * @param fBeat the present beat. + * @return the next beat with a LabelSegment, or fBeat if there is none ahead. + */ + float GetNextLabelSegmentBeatAtBeat( float fBeat ) const { return GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); } + void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const;