move Steps searching out of song into SongUtil so that it can be shared with CourseEntry
This commit is contained in:
@@ -99,7 +99,7 @@ void CatalogXml::Save( LoadingWindow *loading_window )
|
||||
iNumSongsInGroup++;
|
||||
FOREACH_CONST( Difficulty, CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue(), dc )
|
||||
{
|
||||
Steps* pSteps = pSong->GetStepsByDifficulty( *st, *dc, false ); // no autogen
|
||||
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, *st, *dc, false ); // no autogen
|
||||
|
||||
/*
|
||||
* There is no point in storing the steps if either there
|
||||
@@ -193,7 +193,7 @@ void CatalogXml::Save( LoadingWindow *loading_window )
|
||||
{
|
||||
FOREACH_CONST( Difficulty, CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue(), dc )
|
||||
{
|
||||
Steps* pSteps = pSong->GetStepsByDifficulty( *st, *dc, false ); // no autogen
|
||||
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, *st, *dc, false ); // no autogen
|
||||
if( pSteps == NULL )
|
||||
continue; // skip
|
||||
if( UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <set>
|
||||
#include "EnumHelper.h"
|
||||
#include "RageTypes.h"
|
||||
#include "SongUtil.h"
|
||||
#include "StepsUtil.h"
|
||||
|
||||
class PlayerOptions;
|
||||
class SongOptions;
|
||||
@@ -59,11 +61,9 @@ public:
|
||||
// filter criteria, applied from top to bottom
|
||||
// TODO: change this to be a SongID
|
||||
Song* pSong; // don't filter if NULL
|
||||
RString sSongGroup; // don't filter if empty
|
||||
Difficulty baseDifficulty; // don't filter if DIFFICULTY_INVALID
|
||||
SongCriteria songCriteria;
|
||||
StepsCriteria stepsCriteria;
|
||||
bool bNoDifficult; // if true, CourseDifficulty doesn't affect this entry
|
||||
int iLowMeter; // don't filter if -1
|
||||
int iHighMeter; // don't filter if -1
|
||||
|
||||
SongSort songSort; // sort by this after filtering
|
||||
int iChooseIndex; //
|
||||
@@ -77,11 +77,7 @@ public:
|
||||
bSecret = false;
|
||||
|
||||
pSong = NULL;
|
||||
sSongGroup = "";
|
||||
baseDifficulty = DIFFICULTY_INVALID;
|
||||
bNoDifficult = false;
|
||||
iLowMeter = -1;
|
||||
iHighMeter = -1;
|
||||
|
||||
songSort = SongSort_Randomize;
|
||||
iChooseIndex = 0;
|
||||
|
||||
@@ -129,8 +129,8 @@ void CourseEntryDisplay::SetFromGameState( int iCourseEntryIndex )
|
||||
if( te == NULL || ce == NULL )
|
||||
continue;
|
||||
|
||||
int iLow = ce->iLowMeter;
|
||||
int iHigh = ce->iHighMeter;
|
||||
int iLow = ce->stepsCriteria.m_iLowMeter;
|
||||
int iHigh = ce->stepsCriteria.m_iHighMeter;
|
||||
|
||||
bool bLowIsSet = iLow != -1;
|
||||
bool bHighIsSet = iHigh != -1;
|
||||
|
||||
@@ -192,7 +192,7 @@ void CourseUtil::SortByMostRecentlyPlayedForMachine( vector<Course*> &vpCoursesI
|
||||
void CourseUtil::MakeDefaultEditCourseEntry( CourseEntry& out )
|
||||
{
|
||||
out.pSong = GAMESTATE->GetDefaultSong();
|
||||
out.baseDifficulty = DIFFICULTY_MEDIUM;
|
||||
out.stepsCriteria.m_difficulty = DIFFICULTY_MEDIUM;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
@@ -223,12 +223,12 @@ void CourseUtil::AutogenEndlessFromGroup( const RString &sGroupName, Difficulty
|
||||
// gameplay. (We might still get a repeat at the repeat boundary,
|
||||
// but that'd be rare.) -glenn
|
||||
CourseEntry e;
|
||||
e.sSongGroup = sGroupName;
|
||||
e.baseDifficulty = diff;
|
||||
e.songCriteria.m_sGroupName = sGroupName;
|
||||
e.stepsCriteria.m_difficulty = diff;
|
||||
e.bSecret = true;
|
||||
|
||||
vector<Song*> vSongs;
|
||||
SONGMAN->GetSongs( vSongs, e.sSongGroup );
|
||||
SONGMAN->GetSongs( vSongs, e.songCriteria.m_sGroupName );
|
||||
for( unsigned i = 0; i < vSongs.size(); ++i)
|
||||
out.m_vEntries.push_back( e );
|
||||
}
|
||||
@@ -283,7 +283,7 @@ void CourseUtil::AutogenOniFromArtist( const RString &sArtistName, RString sArti
|
||||
aSongs.erase( aSongs.begin()+4, aSongs.end() );
|
||||
|
||||
CourseEntry e;
|
||||
e.baseDifficulty = dc;
|
||||
e.stepsCriteria.m_difficulty = dc;
|
||||
|
||||
for( unsigned i = 0; i < aSongs.size(); ++i )
|
||||
{
|
||||
|
||||
@@ -105,13 +105,13 @@ bool CourseWriterCRS::Write( const Course &course, RageFileBasic &f, bool bSavin
|
||||
const RString &sSong = Basename( entry.pSong->GetSongDir() );
|
||||
|
||||
f.Write( "#SONG:" );
|
||||
if( !entry.sSongGroup.empty() )
|
||||
f.Write( entry.sSongGroup + '/' );
|
||||
if( !entry.songCriteria.m_sGroupName.empty() )
|
||||
f.Write( entry.songCriteria.m_sGroupName + '/' );
|
||||
f.Write( sSong );
|
||||
}
|
||||
else if( !entry.sSongGroup.empty() )
|
||||
else if( !entry.songCriteria.m_sGroupName.empty() )
|
||||
{
|
||||
f.Write( ssprintf( "#SONG:%s/*", entry.sSongGroup.c_str() ) );
|
||||
f.Write( ssprintf( "#SONG:%s/*", entry.songCriteria.m_sGroupName.c_str() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -119,10 +119,10 @@ bool CourseWriterCRS::Write( const Course &course, RageFileBasic &f, bool bSavin
|
||||
}
|
||||
|
||||
f.Write( ":" );
|
||||
if( entry.baseDifficulty != DIFFICULTY_INVALID )
|
||||
f.Write( DifficultyToString(entry.baseDifficulty) );
|
||||
else if( entry.iLowMeter != -1 && entry.iHighMeter != -1 )
|
||||
f.Write( ssprintf( "%d..%d", entry.iLowMeter, entry.iHighMeter ) );
|
||||
if( entry.stepsCriteria.m_difficulty != DIFFICULTY_INVALID )
|
||||
f.Write( DifficultyToString(entry.stepsCriteria.m_difficulty) );
|
||||
else if( entry.stepsCriteria.m_iLowMeter != -1 && entry.stepsCriteria.m_iHighMeter != -1 )
|
||||
f.Write( ssprintf( "%d..%d", entry.stepsCriteria.m_iLowMeter, entry.stepsCriteria.m_iHighMeter ) );
|
||||
f.Write( ":" );
|
||||
|
||||
RString sModifiers = entry.sModifiers;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "CommonMetrics.h"
|
||||
#include "Command.h"
|
||||
#include "Foreach.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
#define MAX_METERS NUM_Difficulty + MAX_EDITS_PER_SONG
|
||||
|
||||
@@ -276,7 +277,7 @@ void DifficultyList::SetFromGameState()
|
||||
else
|
||||
{
|
||||
vector<Steps*> CurSteps;
|
||||
pSong->GetSteps( CurSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
|
||||
SongUtil::GetSteps( pSong, CurSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
|
||||
|
||||
/* Should match the sort in ScreenSelectMusic::AfterMusicChange. */
|
||||
StepsUtil::RemoveLockedSteps( pSong, CurSteps );
|
||||
|
||||
@@ -409,7 +409,7 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
|
||||
case EditMode_Practice:
|
||||
{
|
||||
vector<Steps*> v;
|
||||
GetSelectedSong()->GetSteps( v, GetSelectedStepsType(), DIFFICULTY_EDIT );
|
||||
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedStepsType(), DIFFICULTY_EDIT );
|
||||
StepsUtil::SortStepsByDescription( v );
|
||||
FOREACH_CONST( Steps*, v, p )
|
||||
m_vpSteps.push_back( StepsAndDifficulty(*p,dc) );
|
||||
@@ -437,7 +437,7 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
|
||||
}
|
||||
else
|
||||
{
|
||||
Steps *pSteps = GetSelectedSong()->GetStepsByDifficulty( GetSelectedStepsType(), dc );
|
||||
Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedStepsType(), dc );
|
||||
if( pSteps && UNLOCKMAN->StepsIsLocked( GetSelectedSong(), pSteps ) )
|
||||
pSteps = NULL;
|
||||
|
||||
@@ -512,14 +512,14 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
|
||||
// fill in m_vpSourceSteps
|
||||
if( dc != DIFFICULTY_EDIT )
|
||||
{
|
||||
Steps *pSteps = GetSelectedSong()->GetStepsByDifficulty( GetSelectedSourceStepsType(), dc );
|
||||
Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedSourceStepsType(), dc );
|
||||
if( pSteps != NULL )
|
||||
m_vpSourceSteps.push_back( StepsAndDifficulty(pSteps,dc) );
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<Steps*> v;
|
||||
GetSelectedSong()->GetSteps( v, GetSelectedSourceStepsType(), dc );
|
||||
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedSourceStepsType(), dc );
|
||||
StepsUtil::SortStepsByDescription( v );
|
||||
FOREACH_CONST( Steps*, v, pSteps )
|
||||
m_vpSourceSteps.push_back( StepsAndDifficulty(*pSteps,dc) );
|
||||
|
||||
@@ -254,9 +254,9 @@ void GameCommand::LoadOne( const Command& cmd )
|
||||
|
||||
Difficulty dc = StringToDifficulty( sSteps );
|
||||
if( dc != DIFFICULTY_EDIT )
|
||||
m_pSteps = pSong->GetStepsByDifficulty( pStyle->m_StepsType, dc );
|
||||
m_pSteps = SongUtil::GetStepsByDifficulty( pSong, pStyle->m_StepsType, dc );
|
||||
else
|
||||
m_pSteps = pSong->GetStepsByDescription( pStyle->m_StepsType, sSteps );
|
||||
m_pSteps = SongUtil::GetStepsByDescription( pSong, pStyle->m_StepsType, sSteps );
|
||||
if( m_pSteps == NULL )
|
||||
{
|
||||
m_sInvalidReason = "steps not found";
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "song.h"
|
||||
#include "Steps.h"
|
||||
#include "LightsManager.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
GameSoundManager *SOUND = NULL;
|
||||
|
||||
@@ -142,7 +143,7 @@ static void StartMusic( MusicToPlay &ToPlay )
|
||||
ToPlay.HasTiming = true;
|
||||
ToPlay.timing_data = song.m_Timing;
|
||||
// get cabinet lights if any
|
||||
Steps *pStepsCabinetLights = song.GetOneSteps( STEPS_TYPE_LIGHTS_CABINET );
|
||||
Steps *pStepsCabinetLights = SongUtil::GetOneSteps( &song, STEPS_TYPE_LIGHTS_CABINET );
|
||||
if( pStepsCabinetLights )
|
||||
pStepsCabinetLights->GetNoteData( ToPlay.lights_data );
|
||||
}
|
||||
|
||||
@@ -1222,14 +1222,6 @@ bool GameState::ShowW1() const
|
||||
}
|
||||
}
|
||||
|
||||
struct SongAndSteps
|
||||
{
|
||||
Song* pSong;
|
||||
Steps* pSteps;
|
||||
bool operator==( const SongAndSteps& other ) const { return pSong==other.pSong && pSteps==other.pSteps; }
|
||||
bool operator<( const SongAndSteps& other ) const { return pSong<=other.pSong && pSteps<=other.pSteps; }
|
||||
};
|
||||
|
||||
void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOut ) const
|
||||
{
|
||||
if( !IsHumanPlayer(pn) )
|
||||
|
||||
@@ -21,6 +21,7 @@ TODO:
|
||||
#include "song.h"
|
||||
#include "Steps.h"
|
||||
#include "ActorUtil.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
#define BANNERSPACING THEME->GetMetricI("ScreenEz2SelectMusic","BannerSpacing")
|
||||
#define MAXSONGSINBUFFER 5
|
||||
@@ -68,7 +69,7 @@ MusicBannerWheel::MusicBannerWheel()
|
||||
for ( unsigned i = 0; i < arraySongs.size(); i++)
|
||||
{
|
||||
//ONLY get non-autogenned steps
|
||||
Steps* pSteps = arraySongs[i]->GetStepsByDifficulty( GAMESTATE->GetCurrentStyle()->m_StepsType, DIFFICULTY_INVALID, false );
|
||||
Steps* pSteps = SongUtil::GetStepsByDifficulty( arraySongs[i], GAMESTATE->GetCurrentStyle()->m_StepsType, DIFFICULTY_INVALID, false );
|
||||
if ( pSteps != NULL )
|
||||
pNotAutogen.push_back( arraySongs[i] );
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "GameManager.h"
|
||||
#include "RageException.h"
|
||||
#include "RageFile.h"
|
||||
#include "SongUtil.h"
|
||||
#include "StepsUtil.h"
|
||||
#include "song.h"
|
||||
#include "Steps.h"
|
||||
@@ -997,7 +998,7 @@ void BMSLoader::SlideDuplicateDifficulties( Song &p )
|
||||
continue;
|
||||
|
||||
vector<Steps*> vSteps;
|
||||
p.GetSteps( vSteps, st, dc );
|
||||
SongUtil::GetSteps( &p, vSteps, st, dc );
|
||||
|
||||
StepsUtil::SortNotesArrayByDifficulty( vSteps );
|
||||
for( unsigned k=1; k<vSteps.size(); k++ )
|
||||
|
||||
@@ -672,10 +672,10 @@ void ProfileManager::GetHighScoreForDifficulty( const Song *s, const Style *st,
|
||||
{
|
||||
// return max grade of notes in difficulty class
|
||||
vector<Steps*> aNotes;
|
||||
s->GetSteps( aNotes, st->m_StepsType );
|
||||
SongUtil::GetSteps( s, aNotes, st->m_StepsType );
|
||||
StepsUtil::SortNotesArrayByDifficulty( aNotes );
|
||||
|
||||
const Steps* pSteps = s->GetStepsByDifficulty( st->m_StepsType, dc );
|
||||
const Steps* pSteps = SongUtil::GetStepsByDifficulty( s, st->m_StepsType, dc );
|
||||
|
||||
if( pSteps && PROFILEMAN->IsPersistentProfile(slot) )
|
||||
hsOut = PROFILEMAN->GetProfile(slot)->GetStepsHighScoreList(s,pSteps).GetTopScore();
|
||||
|
||||
@@ -978,7 +978,7 @@ void ScreenEdit::UpdateTextInfo()
|
||||
|
||||
m_bTextInfoNeedsUpdate = false;
|
||||
|
||||
RString sNoteType = NoteTypeToLocalizedString(m_SnapDisplay.GetNoteType()) + " notes";
|
||||
RString sNoteType = NoteTypeToLocalizedString(m_SnapDisplay.GetNoteType());
|
||||
|
||||
RString sText;
|
||||
sText += ssprintf( "%s:\n %.3f\n", CURRENT_BEAT.GetValue().c_str(), GAMESTATE->m_fSongBeat );
|
||||
@@ -1379,7 +1379,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
// Get all Steps of this StepsType
|
||||
StepsType st = pSteps->m_StepsType;
|
||||
vector<Steps*> vSteps;
|
||||
GAMESTATE->m_pCurSong->GetSteps( vSteps, st );
|
||||
SongUtil::GetSteps( GAMESTATE->m_pCurSong, vSteps, st );
|
||||
|
||||
// Sort them by difficulty.
|
||||
StepsUtil::SortStepsByTypeAndDifficulty( vSteps );
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "ActorUtil.h"
|
||||
#include "AnnouncerManager.h"
|
||||
#include "MenuTimer.h"
|
||||
#include "SongUtil.h"
|
||||
#include "StepsUtil.h"
|
||||
#include "ScreenDimensions.h"
|
||||
#include "ScreenPrompt.h"
|
||||
@@ -640,7 +641,7 @@ void ScreenEz2SelectMusic::MusicChanged()
|
||||
|
||||
for( pn = 0; pn < NUM_PLAYERS; ++pn)
|
||||
{
|
||||
pSong->GetSteps( m_arrayNotes[pn], GAMESTATE->GetCurrentStyle()->m_StepsType );
|
||||
SongUtil::GetSteps( pSong, m_arrayNotes[pn], GAMESTATE->GetCurrentStyle()->m_StepsType );
|
||||
StepsUtil::SortNotesArrayByDifficulty( m_arrayNotes[pn] );
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "Foreground.h"
|
||||
#include "ScreenSaveSync.h"
|
||||
#include "AdjustSync.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
//
|
||||
// Defines
|
||||
@@ -1295,7 +1296,7 @@ void ScreenGameplay::LoadLights()
|
||||
m_CabinetLightsNoteData.Init();
|
||||
ASSERT( GAMESTATE->m_pCurSong );
|
||||
|
||||
const Steps *pSteps = GAMESTATE->m_pCurSong->GetClosestNotes( STEPS_TYPE_LIGHTS_CABINET, DIFFICULTY_MEDIUM );
|
||||
const Steps *pSteps = SongUtil::GetClosestNotes( GAMESTATE->m_pCurSong, STEPS_TYPE_LIGHTS_CABINET, DIFFICULTY_MEDIUM );
|
||||
if( pSteps != NULL )
|
||||
{
|
||||
pSteps->GetNoteData( m_CabinetLightsNoteData );
|
||||
@@ -1312,7 +1313,7 @@ void ScreenGameplay::LoadLights()
|
||||
Difficulty d1 = DIFFICULTY_INVALID;
|
||||
if( asDifficulties.size() > 0 )
|
||||
d1 = StringToDifficulty( asDifficulties[0] );
|
||||
pSteps = GAMESTATE->m_pCurSong->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, d1 );
|
||||
pSteps = SongUtil::GetClosestNotes( GAMESTATE->m_pCurSong, GAMESTATE->GetCurrentStyle()->m_StepsType, d1 );
|
||||
|
||||
// If we can't find anything at all, stop.
|
||||
if( pSteps == NULL )
|
||||
@@ -1324,7 +1325,7 @@ void ScreenGameplay::LoadLights()
|
||||
if( asDifficulties.size() > 1 )
|
||||
{
|
||||
Difficulty d2 = StringToDifficulty( asDifficulties[1] );
|
||||
const Steps *pSteps2 = GAMESTATE->m_pCurSong->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, d2 );
|
||||
const Steps *pSteps2 = SongUtil::GetClosestNotes( GAMESTATE->m_pCurSong, GAMESTATE->GetCurrentStyle()->m_StepsType, d2 );
|
||||
if( pSteps != NULL && pSteps2 != NULL && pSteps != pSteps2 )
|
||||
{
|
||||
NoteData TapNoteData2;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "AdjustSync.h"
|
||||
#include "ScreenDimensions.h"
|
||||
#include "InputEventPlus.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
REGISTER_SCREEN_CLASS( ScreenGameplaySyncMachine );
|
||||
|
||||
@@ -23,7 +24,7 @@ void ScreenGameplaySyncMachine::Init()
|
||||
m_Song.TidyUpData();
|
||||
|
||||
GAMESTATE->m_pCurSong.Set( &m_Song );
|
||||
Steps *pSteps = m_Song.GetOneSteps();
|
||||
Steps *pSteps = SongUtil::GetOneSteps( &m_Song );
|
||||
ASSERT( pSteps );
|
||||
GAMESTATE->m_pCurSteps[0].Set( pSteps );
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "PrefsManager.h"
|
||||
#include "CharacterManager.h"
|
||||
#include "StatsManager.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
static const ThemeMetric<RString> STEPFILE ("ScreenHowToPlay","Stepfile");
|
||||
static const ThemeMetric<int> NUM_W2S ("ScreenHowToPlay","NumW2s");
|
||||
@@ -142,7 +143,7 @@ void ScreenHowToPlay::Init()
|
||||
|
||||
const Style* pStyle = GAMESTATE->GetCurrentStyle();
|
||||
|
||||
Steps *pSteps = m_Song.GetStepsByDescription( pStyle->m_StepsType, "" );
|
||||
Steps *pSteps = SongUtil::GetStepsByDescription( &m_Song, pStyle->m_StepsType, "" );
|
||||
ASSERT_M( pSteps != NULL, ssprintf("%i", pStyle->m_StepsType) );
|
||||
|
||||
NoteData tempNoteData;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "PrefsManager.h"
|
||||
#include "InputEventPlus.h"
|
||||
#include "AdjustSync.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
#define SHOW_COURSE_MODIFIERS_PROBABILITY THEME->GetMetricF(m_sName,"ShowCourseModifiersProbability")
|
||||
|
||||
@@ -85,7 +86,7 @@ void ScreenJukebox::SetSong()
|
||||
continue; // skip
|
||||
|
||||
Difficulty dc = vDifficultiesToShow[ rand()%vDifficultiesToShow.size() ];
|
||||
Steps* pSteps = pSong->GetStepsByDifficulty( GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
|
||||
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
|
||||
|
||||
if( pSteps == NULL )
|
||||
continue; // skip
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Steps.h"
|
||||
#include "OptionRowHandler.h"
|
||||
#include "PlayerState.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
enum EditCourseEntryRow
|
||||
{
|
||||
@@ -208,7 +209,7 @@ void ScreenOptionsEditCourseEntry::BeginScreen()
|
||||
const CourseEntry &ce = pCourse->m_vEntries[ GAMESTATE->m_iEditCourseEntryIndex ];
|
||||
m_Original = ce;
|
||||
|
||||
m_pSongHandler->m_sSongGroup = ce.sSongGroup;
|
||||
m_pSongHandler->m_sSongGroup = ce.songCriteria.m_sGroupName;
|
||||
|
||||
if( SHOW_MODS_ROW )
|
||||
m_pModChangesHandler->m_Def.m_vsChoices[0] = ssprintf( "%d mod changes", ce.GetNumModChanges() );
|
||||
@@ -241,8 +242,8 @@ void ScreenOptionsEditCourseEntry::HandleScreenMessage( const ScreenMessage SM )
|
||||
Song *pSong = ce.pSong;
|
||||
Steps *pSteps;
|
||||
StepsType st = GAMESTATE->m_stEdit;
|
||||
CourseDifficulty cd = ( ce.baseDifficulty == DIFFICULTY_INVALID ?
|
||||
GAMESTATE->m_cdEdit : ce.baseDifficulty );
|
||||
CourseDifficulty cd = ( ce.stepsCriteria.m_difficulty == DIFFICULTY_INVALID ?
|
||||
GAMESTATE->m_cdEdit : ce.stepsCriteria.m_difficulty );
|
||||
|
||||
if( pSong == NULL )
|
||||
pSong = m_pLongSong;
|
||||
@@ -273,13 +274,13 @@ void ScreenOptionsEditCourseEntry::HandleScreenMessage( const ScreenMessage SM )
|
||||
}
|
||||
|
||||
// Try to find steps first using st and cd, then st, then cd, then any.
|
||||
pSteps = pSong->GetStepsByDifficulty( st, cd, false );
|
||||
pSteps = SongUtil::GetStepsByDifficulty( pSong, st, cd, false );
|
||||
if( !pSteps )
|
||||
pSteps = pSong->GetStepsByDifficulty( st, DIFFICULTY_INVALID, false );
|
||||
pSteps = SongUtil::GetStepsByDifficulty( pSong, st, DIFFICULTY_INVALID, false );
|
||||
if( !pSteps )
|
||||
pSteps = pSong->GetStepsByDifficulty( STEPS_TYPE_INVALID, cd, false );
|
||||
pSteps = SongUtil::GetStepsByDifficulty( pSong, STEPS_TYPE_INVALID, cd, false );
|
||||
if( !pSteps )
|
||||
pSteps = pSong->GetStepsByDifficulty( STEPS_TYPE_INVALID, DIFFICULTY_INVALID, false );
|
||||
pSteps = SongUtil::GetStepsByDifficulty( pSong, STEPS_TYPE_INVALID, DIFFICULTY_INVALID, false );
|
||||
ASSERT( pSteps );
|
||||
|
||||
// Set up for ScreenEdit
|
||||
@@ -340,7 +341,7 @@ void ScreenOptionsEditCourseEntry::AfterChangeValueInRow( int iRow, PlayerNumber
|
||||
vpns.push_back( pn );
|
||||
ExportOptions( ROW_SONG_GROUP, vpns );
|
||||
|
||||
m_pSongHandler->m_sSongGroup = ce.sSongGroup;
|
||||
m_pSongHandler->m_sSongGroup = ce.songCriteria.m_sGroupName;
|
||||
|
||||
OptionRow &row = *m_pRows[ROW_SONG];
|
||||
row.Reload();
|
||||
@@ -371,7 +372,7 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
|
||||
case ROW_SONG_GROUP:
|
||||
FOREACH_CONST( RString, row.GetRowDef().m_vsChoices, s )
|
||||
{
|
||||
if( *s == ce.sSongGroup )
|
||||
if( *s == ce.songCriteria.m_sGroupName )
|
||||
{
|
||||
int iChoice = s - row.GetRowDef().m_vsChoices.begin();
|
||||
row.SetOneSharedSelection( iChoice );
|
||||
@@ -393,7 +394,7 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
|
||||
}
|
||||
case ROW_BASE_DIFFICULTY:
|
||||
{
|
||||
vector<Difficulty>::const_iterator iter = find( CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().begin(), CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().end(), ce.baseDifficulty );
|
||||
vector<Difficulty>::const_iterator iter = find( CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().begin(), CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().end(), ce.stepsCriteria.m_difficulty );
|
||||
int iChoice = 0;
|
||||
if( iter != CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().end() )
|
||||
iChoice = iter - CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue().begin() + 1;
|
||||
@@ -404,8 +405,8 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
|
||||
case ROW_LOW_METER:
|
||||
{
|
||||
int iChoice = 0;
|
||||
if( ce.iLowMeter != -1 )
|
||||
iChoice = ce.iLowMeter;
|
||||
if( ce.stepsCriteria.m_iLowMeter != -1 )
|
||||
iChoice = ce.stepsCriteria.m_iLowMeter;
|
||||
OptionRow &row = *m_pRows[ROW_LOW_METER];
|
||||
row.SetOneSharedSelection( iChoice );
|
||||
break;
|
||||
@@ -413,8 +414,8 @@ void ScreenOptionsEditCourseEntry::ImportOptions( int iRow, const vector<PlayerN
|
||||
case ROW_HIGH_METER:
|
||||
{
|
||||
int iChoice = 0;
|
||||
if( ce.iHighMeter != -1 )
|
||||
iChoice = ce.iHighMeter;
|
||||
if( ce.stepsCriteria.m_iHighMeter != -1 )
|
||||
iChoice = ce.stepsCriteria.m_iHighMeter;
|
||||
OptionRow &row = *m_pRows[ROW_HIGH_METER];
|
||||
row.SetOneSharedSelection( iChoice );
|
||||
break;
|
||||
@@ -453,9 +454,9 @@ void ScreenOptionsEditCourseEntry::ExportOptions( int iRow, const vector<PlayerN
|
||||
case ROW_SONG_GROUP:
|
||||
{
|
||||
if( iChoice == 0 )
|
||||
ce.sSongGroup = "";
|
||||
ce.songCriteria.m_sGroupName = "";
|
||||
else
|
||||
ce.sSongGroup = row.GetRowDef().m_vsChoices[ iChoice ];
|
||||
ce.songCriteria.m_sGroupName = row.GetRowDef().m_vsChoices[ iChoice ];
|
||||
break;
|
||||
}
|
||||
case ROW_SONG:
|
||||
@@ -477,29 +478,29 @@ void ScreenOptionsEditCourseEntry::ExportOptions( int iRow, const vector<PlayerN
|
||||
{
|
||||
if( iChoice == 0 )
|
||||
{
|
||||
ce.baseDifficulty = DIFFICULTY_INVALID;
|
||||
ce.stepsCriteria.m_difficulty = DIFFICULTY_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
Difficulty d = CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue()[iChoice-1];
|
||||
ce.baseDifficulty = d;
|
||||
ce.stepsCriteria.m_difficulty = d;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ROW_LOW_METER:
|
||||
{
|
||||
if( iChoice == 0 )
|
||||
ce.iLowMeter = -1;
|
||||
ce.stepsCriteria.m_iLowMeter = -1;
|
||||
else
|
||||
ce.iLowMeter = iChoice;
|
||||
ce.stepsCriteria.m_iLowMeter = iChoice;
|
||||
break;
|
||||
}
|
||||
case ROW_HIGH_METER:
|
||||
{
|
||||
if( iChoice == 0 )
|
||||
ce.iHighMeter = -1;
|
||||
ce.stepsCriteria.m_iHighMeter = -1;
|
||||
else
|
||||
ce.iHighMeter = iChoice;
|
||||
ce.stepsCriteria.m_iHighMeter = iChoice;
|
||||
break;
|
||||
}
|
||||
case ROW_SORT:
|
||||
|
||||
@@ -277,7 +277,7 @@ void ScoreScroller::ConfigureActor( Actor *pActor, int iItem )
|
||||
|
||||
FOREACH_CONST( Difficulty, m_DifficultiesToShow, iter )
|
||||
{
|
||||
const Steps* pSteps = pSong->GetStepsByDifficulty( m_StepsType, *iter, false );
|
||||
const Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, m_StepsType, *iter, false );
|
||||
if( pSteps && UNLOCKMAN->StepsIsLocked(pSong, pSteps) )
|
||||
pSteps = NULL;
|
||||
BitmapText* pTextStepsScore = &item.m_textScore[*iter];
|
||||
|
||||
@@ -1521,7 +1521,7 @@ void ScreenSelectMusic::AfterMusicChange()
|
||||
m_textNumSongs.SetText( ssprintf("%d", SongManager::GetNumStagesForSong(pSong) ) );
|
||||
m_textTotalTime.SetText( SecondsToMMSSMsMs(pSong->m_fMusicLengthSeconds) );
|
||||
|
||||
pSong->GetSteps( m_vpSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
|
||||
SongUtil::GetSteps( pSong, m_vpSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
|
||||
StepsUtil::RemoveLockedSteps( pSong, m_vpSteps );
|
||||
StepsUtil::SortNotesArrayByDifficulty( m_vpSteps );
|
||||
|
||||
|
||||
+12
-254
@@ -19,9 +19,9 @@
|
||||
#include "RageFileManager.h"
|
||||
#include "RageSurface.h"
|
||||
#include "NoteDataUtil.h"
|
||||
#include "SongUtil.h"
|
||||
#include "StepsUtil.h"
|
||||
#include "Foreach.h"
|
||||
#include "UnlockManager.h"
|
||||
#include "BackgroundUtil.h"
|
||||
#include "SpecialFiles.h"
|
||||
|
||||
@@ -319,114 +319,6 @@ static void GetImageDirListing( RString sPath, vector<RString> &AddTo, bool bRet
|
||||
GetDirListing( sPath + ".gif", AddTo, false, bReturnPathToo );
|
||||
}
|
||||
|
||||
static RString RemoveInitialWhitespace( RString s )
|
||||
{
|
||||
size_t i = s.find_first_not_of(" \t\r\n");
|
||||
if( i != s.npos )
|
||||
s.erase( 0, i );
|
||||
return s;
|
||||
}
|
||||
|
||||
/* This is called within TidyUpData, before autogen notes are added. */
|
||||
void Song::DeleteDuplicateSteps( vector<Steps*> &vSteps )
|
||||
{
|
||||
/* vSteps have the same StepsType and Difficulty. Delete them if they have the
|
||||
* same m_sDescription, m_iMeter and SMNoteData. */
|
||||
CHECKPOINT;
|
||||
for( unsigned i=0; i<vSteps.size(); i++ )
|
||||
{
|
||||
CHECKPOINT;
|
||||
const Steps *s1 = vSteps[i];
|
||||
|
||||
for( unsigned j=i+1; j<vSteps.size(); j++ )
|
||||
{
|
||||
CHECKPOINT;
|
||||
const Steps *s2 = vSteps[j];
|
||||
|
||||
if( s1->GetDescription() != s2->GetDescription() )
|
||||
continue;
|
||||
if( s1->GetMeter() != s2->GetMeter() )
|
||||
continue;
|
||||
/* Compare, ignoring whitespace. */
|
||||
RString sSMNoteData1;
|
||||
s1->GetSMNoteData( sSMNoteData1 );
|
||||
RString sSMNoteData2;
|
||||
s2->GetSMNoteData( sSMNoteData2 );
|
||||
if( RemoveInitialWhitespace(sSMNoteData1) != RemoveInitialWhitespace(sSMNoteData2) )
|
||||
continue;
|
||||
|
||||
LOG->Trace("Removed %p duplicate steps in song \"%s\" with description \"%s\" and meter \"%i\"",
|
||||
s2, this->GetSongDir().c_str(), s1->GetDescription().c_str(), s1->GetMeter() );
|
||||
|
||||
/* Don't use RemoveSteps; autogen notes havn't yet been created and it'll
|
||||
* create them. */
|
||||
FOREACH_StepsType( st )
|
||||
{
|
||||
for( int k=this->m_vpStepsByType[st].size()-1; k>=0; k-- )
|
||||
{
|
||||
if( this->m_vpStepsByType[st][k] == s2 )
|
||||
{
|
||||
// delete this->m_vpStepsByType[k]; // delete below
|
||||
this->m_vpStepsByType[st].erase( this->m_vpStepsByType[st].begin()+k );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( int k=this->m_vpSteps.size()-1; k>=0; k-- )
|
||||
{
|
||||
if( this->m_vpSteps[k] == s2 )
|
||||
{
|
||||
delete this->m_vpSteps[k];
|
||||
this->m_vpSteps.erase( this->m_vpSteps.begin()+k );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vSteps.erase(vSteps.begin()+j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make any duplicate difficulties edits. (Note that BMS files do a first pass
|
||||
* on this; see BMSLoader::SlideDuplicateDifficulties.) */
|
||||
void Song::AdjustDuplicateSteps()
|
||||
{
|
||||
FOREACH_StepsType( st )
|
||||
{
|
||||
FOREACH_Difficulty( dc )
|
||||
{
|
||||
if( dc == DIFFICULTY_EDIT )
|
||||
continue;
|
||||
|
||||
vector<Steps*> vSteps;
|
||||
this->GetSteps( vSteps, st, dc );
|
||||
|
||||
/* Delete steps that are completely identical. This happened due to a
|
||||
* bug in an earlier version. */
|
||||
DeleteDuplicateSteps( vSteps );
|
||||
|
||||
CHECKPOINT;
|
||||
StepsUtil::SortNotesArrayByDifficulty( vSteps );
|
||||
CHECKPOINT;
|
||||
for( unsigned k=1; k<vSteps.size(); k++ )
|
||||
{
|
||||
vSteps[k]->SetDifficulty( DIFFICULTY_EDIT );
|
||||
if( vSteps[k]->GetDescription() == "" )
|
||||
{
|
||||
/* "Hard Edit" */
|
||||
RString EditName = Capitalize( DifficultyToString(dc) ) + " Edit";
|
||||
vSteps[k]->SetDescription( EditName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: Don't allow edits to have descriptions that look like regular difficulties.
|
||||
* These are confusing, and they're ambiguous when passed to GetStepsByID. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix up song paths. If there's a leading "./", be sure to keep it: it's
|
||||
* a signal that the path is from the root directory, not the song directory.
|
||||
* Other than a leading "./", song paths must never contain "." or "..". */
|
||||
@@ -738,7 +630,7 @@ void Song::TidyUpData()
|
||||
|
||||
/* Don't allow multiple Steps of the same StepsType and Difficulty (except for edits).
|
||||
* We should be able to use difficulty names as unique identifiers for steps. */
|
||||
AdjustDuplicateSteps();
|
||||
SongUtil::AdjustDuplicateSteps( this );
|
||||
|
||||
{
|
||||
/* Generated filename; this doesn't always point to a loadable file,
|
||||
@@ -835,142 +727,6 @@ void Song::ReCalculateRadarValuesAndLastBeat()
|
||||
m_fLastBeat = fLastBeat;
|
||||
}
|
||||
|
||||
void Song::GetSteps(
|
||||
vector<Steps*>& arrayAddTo,
|
||||
StepsType st,
|
||||
Difficulty dc,
|
||||
int iMeterLow,
|
||||
int iMeterHigh,
|
||||
const RString &sDescription,
|
||||
bool bIncludeAutoGen,
|
||||
unsigned uHash,
|
||||
int iMaxToGet
|
||||
) const
|
||||
{
|
||||
if( !iMaxToGet )
|
||||
return;
|
||||
|
||||
const vector<Steps*> &vpSteps = st == STEPS_TYPE_INVALID ? GetAllSteps() : GetStepsByStepsType(st);
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
|
||||
continue;
|
||||
if( iMeterLow != -1 && iMeterLow > pSteps->GetMeter() )
|
||||
continue;
|
||||
if( iMeterHigh != -1 && iMeterHigh < pSteps->GetMeter() )
|
||||
continue;
|
||||
if( sDescription.size() && sDescription != pSteps->GetDescription() )
|
||||
continue;
|
||||
if( uHash != 0 && uHash != pSteps->GetHash() )
|
||||
continue;
|
||||
if( !bIncludeAutoGen && pSteps->IsAutogen() )
|
||||
continue;
|
||||
|
||||
arrayAddTo.push_back( pSteps );
|
||||
|
||||
if( iMaxToGet != -1 )
|
||||
{
|
||||
--iMaxToGet;
|
||||
if( !iMaxToGet )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Steps* Song::GetOneSteps(
|
||||
StepsType st,
|
||||
Difficulty dc,
|
||||
int iMeterLow,
|
||||
int iMeterHigh,
|
||||
const RString &sDescription,
|
||||
unsigned uHash,
|
||||
bool bIncludeAutoGen
|
||||
) const
|
||||
{
|
||||
vector<Steps*> vpSteps;
|
||||
GetSteps( vpSteps, st, dc, iMeterLow, iMeterHigh, sDescription, bIncludeAutoGen, uHash, 1 ); // get max 1
|
||||
if( vpSteps.empty() )
|
||||
return NULL;
|
||||
else
|
||||
return vpSteps[0];
|
||||
}
|
||||
|
||||
Steps* Song::GetStepsByDifficulty( StepsType st, Difficulty dc, bool bIncludeAutoGen ) const
|
||||
{
|
||||
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? GetAllSteps():GetStepsByStepsType(st);
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
|
||||
continue;
|
||||
if( !bIncludeAutoGen && pSteps->IsAutogen() )
|
||||
continue;
|
||||
|
||||
return pSteps;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Steps* Song::GetStepsByMeter( StepsType st, int iMeterLow, int iMeterHigh ) const
|
||||
{
|
||||
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? GetAllSteps():GetStepsByStepsType(st);
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( iMeterLow > pSteps->GetMeter() )
|
||||
continue;
|
||||
if( iMeterHigh < pSteps->GetMeter() )
|
||||
continue;
|
||||
|
||||
return pSteps;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Steps* Song::GetStepsByDescription( StepsType st, RString sDescription ) const
|
||||
{
|
||||
vector<Steps*> vNotes;
|
||||
GetSteps( vNotes, st, DIFFICULTY_INVALID, -1, -1, sDescription );
|
||||
if( vNotes.size() == 0 )
|
||||
return NULL;
|
||||
else
|
||||
return vNotes[0];
|
||||
}
|
||||
|
||||
|
||||
Steps* Song::GetClosestNotes( StepsType st, Difficulty dc, bool bIgnoreLocked ) const
|
||||
{
|
||||
ASSERT( dc != DIFFICULTY_INVALID );
|
||||
|
||||
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? GetAllSteps():GetStepsByStepsType(st);
|
||||
Steps *pClosest = NULL;
|
||||
int iClosestDistance = 999;
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( pSteps->GetDifficulty() == DIFFICULTY_EDIT && dc != DIFFICULTY_EDIT )
|
||||
continue;
|
||||
if( bIgnoreLocked && UNLOCKMAN->StepsIsLocked(this, pSteps) )
|
||||
continue;
|
||||
|
||||
int iDistance = abs(dc - pSteps->GetDifficulty());
|
||||
if( iDistance < iClosestDistance )
|
||||
{
|
||||
pClosest = pSteps;
|
||||
iClosestDistance = iDistance;
|
||||
}
|
||||
}
|
||||
|
||||
return pClosest;
|
||||
}
|
||||
|
||||
/* Return whether the song is playable in the given style. */
|
||||
bool Song::SongCompleteForStyle( const Style *st ) const
|
||||
{
|
||||
@@ -979,12 +735,12 @@ bool Song::SongCompleteForStyle( const Style *st ) const
|
||||
|
||||
bool Song::HasStepsType( StepsType st ) const
|
||||
{
|
||||
return GetOneSteps( st ) != NULL;
|
||||
return SongUtil::GetOneSteps( this, st ) != NULL;
|
||||
}
|
||||
|
||||
bool Song::HasStepsTypeAndDifficulty( StepsType st, Difficulty dc ) const
|
||||
{
|
||||
return GetOneSteps( st, dc ) != NULL;
|
||||
return SongUtil::GetOneSteps( this, st, dc ) != NULL;
|
||||
}
|
||||
|
||||
void Song::Save()
|
||||
@@ -1156,11 +912,11 @@ bool Song::IsEasy( StepsType st ) const
|
||||
/* The easy marker indicates which songs a beginner, having selected "beginner",
|
||||
* can play and actually get a very easy song: if there are actual beginner
|
||||
* steps, or if the light steps are 1- or 2-foot. */
|
||||
const Steps* pBeginnerNotes = GetStepsByDifficulty( st, DIFFICULTY_BEGINNER );
|
||||
const Steps* pBeginnerNotes = SongUtil::GetStepsByDifficulty( this, st, DIFFICULTY_BEGINNER );
|
||||
if( pBeginnerNotes )
|
||||
return true;
|
||||
|
||||
const Steps* pEasyNotes = GetStepsByDifficulty( st, DIFFICULTY_EASY );
|
||||
const Steps* pEasyNotes = SongUtil::GetStepsByDifficulty( this, st, DIFFICULTY_EASY );
|
||||
if( pEasyNotes && pEasyNotes->GetMeter() == 1 )
|
||||
return true;
|
||||
|
||||
@@ -1349,12 +1105,13 @@ void Song::AddSteps( Steps* pSteps )
|
||||
m_vpStepsByType[pSteps->m_StepsType].push_back( pSteps );
|
||||
}
|
||||
|
||||
void Song::DeleteSteps( const Steps* pSteps )
|
||||
void Song::DeleteSteps( const Steps* pSteps, bool bReAutoGen )
|
||||
{
|
||||
// Avoid any stale Note::parent pointers by removing all AutoGen'd Steps,
|
||||
// then adding them again.
|
||||
|
||||
RemoveAutoGenNotes();
|
||||
if( bReAutoGen )
|
||||
RemoveAutoGenNotes();
|
||||
|
||||
|
||||
vector<Steps*> &vpSteps = m_vpStepsByType[pSteps->m_StepsType];
|
||||
@@ -1378,7 +1135,8 @@ void Song::DeleteSteps( const Steps* pSteps )
|
||||
}
|
||||
}
|
||||
|
||||
AddAutoGenNotes();
|
||||
if( bReAutoGen )
|
||||
AddAutoGenNotes();
|
||||
}
|
||||
|
||||
bool Song::Matches(RString sGroup, RString sSong) const
|
||||
@@ -1404,7 +1162,7 @@ bool Song::Matches(RString sGroup, RString sSong) const
|
||||
|
||||
void Song::FreeAllLoadedFromProfile( ProfileSlot slot )
|
||||
{
|
||||
/* RemoveSteps will remove and recreate autogen notes, which may reorder
|
||||
/* DeleteSteps will remove and recreate autogen notes, which may reorder
|
||||
* m_vpSteps, so be careful not to skip over entries. */
|
||||
vector<Steps*> apToRemove;
|
||||
for( int s=m_vpSteps.size()-1; s>=0; s-- )
|
||||
|
||||
@@ -1033,7 +1033,7 @@ Song *SongManager::GetSongFromSteps( Steps *pSteps )
|
||||
FOREACH_CONST( Song*, vSongs, song )
|
||||
{
|
||||
vector<Steps*> vSteps;
|
||||
(*song)->GetSteps( vSteps );
|
||||
SongUtil::GetSteps( *song, vSteps );
|
||||
|
||||
FOREACH_CONST( Steps*, vSteps, steps )
|
||||
{
|
||||
@@ -1171,7 +1171,7 @@ void SongManager::GetExtraStageInfo( bool bExtra2, const Style *sd, Song*& pSong
|
||||
Song* pSong = apSongs[s];
|
||||
|
||||
vector<Steps*> apSteps;
|
||||
pSong->GetSteps( apSteps, sd->m_StepsType );
|
||||
SongUtil::GetSteps( pSong, apSteps, sd->m_StepsType );
|
||||
for( unsigned n=0; n<apSteps.size(); n++ ) // foreach Steps
|
||||
{
|
||||
Steps* pSteps = apSteps[n];
|
||||
@@ -1678,7 +1678,7 @@ int SongManager::GetNumEditsLoadedFromProfile( ProfileSlot slot ) const
|
||||
{
|
||||
const Song *pSong = m_pSongs[s];
|
||||
vector<Steps*> apSteps;
|
||||
pSong->GetSteps( apSteps );
|
||||
SongUtil::GetSteps( pSong, apSteps );
|
||||
|
||||
for( unsigned i = 0; i < apSteps.size(); ++i )
|
||||
{
|
||||
|
||||
+257
-8
@@ -13,14 +13,249 @@
|
||||
#include "UnlockManager.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "LocalizedString.h"
|
||||
#include "RageLog.h"
|
||||
|
||||
bool SongCriteria::Matches( const Song *p ) const
|
||||
{
|
||||
if( !m_sGroupName.empty() && m_sGroupName != p->m_sGroupName )
|
||||
return false;
|
||||
if( !m_sGenre.empty() && m_sGenre != p->m_sGenre )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SongUtil::GetSteps(
|
||||
const Song *pSong,
|
||||
vector<Steps*>& arrayAddTo,
|
||||
StepsType st,
|
||||
Difficulty dc,
|
||||
int iMeterLow,
|
||||
int iMeterHigh,
|
||||
const RString &sDescription,
|
||||
bool bIncludeAutoGen,
|
||||
unsigned uHash,
|
||||
int iMaxToGet
|
||||
)
|
||||
{
|
||||
if( !iMaxToGet )
|
||||
return;
|
||||
|
||||
const vector<Steps*> &vpSteps = st == STEPS_TYPE_INVALID ? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
|
||||
continue;
|
||||
if( iMeterLow != -1 && iMeterLow > pSteps->GetMeter() )
|
||||
continue;
|
||||
if( iMeterHigh != -1 && iMeterHigh < pSteps->GetMeter() )
|
||||
continue;
|
||||
if( sDescription.size() && sDescription != pSteps->GetDescription() )
|
||||
continue;
|
||||
if( uHash != 0 && uHash != pSteps->GetHash() )
|
||||
continue;
|
||||
if( !bIncludeAutoGen && pSteps->IsAutogen() )
|
||||
continue;
|
||||
|
||||
arrayAddTo.push_back( pSteps );
|
||||
|
||||
if( iMaxToGet != -1 )
|
||||
{
|
||||
--iMaxToGet;
|
||||
if( !iMaxToGet )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Steps* SongUtil::GetOneSteps(
|
||||
const Song *pSong,
|
||||
StepsType st,
|
||||
Difficulty dc,
|
||||
int iMeterLow,
|
||||
int iMeterHigh,
|
||||
const RString &sDescription,
|
||||
unsigned uHash,
|
||||
bool bIncludeAutoGen
|
||||
)
|
||||
{
|
||||
vector<Steps*> vpSteps;
|
||||
GetSteps( pSong, vpSteps, st, dc, iMeterLow, iMeterHigh, sDescription, bIncludeAutoGen, uHash, 1 ); // get max 1
|
||||
if( vpSteps.empty() )
|
||||
return NULL;
|
||||
else
|
||||
return vpSteps[0];
|
||||
}
|
||||
|
||||
Steps* SongUtil::GetStepsByDifficulty( const Song *pSong, StepsType st, Difficulty dc, bool bIncludeAutoGen )
|
||||
{
|
||||
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( dc != DIFFICULTY_INVALID && dc != pSteps->GetDifficulty() )
|
||||
continue;
|
||||
if( !bIncludeAutoGen && pSteps->IsAutogen() )
|
||||
continue;
|
||||
|
||||
return pSteps;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Steps* SongUtil::GetStepsByMeter( const Song *pSong, StepsType st, int iMeterLow, int iMeterHigh )
|
||||
{
|
||||
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( iMeterLow > pSteps->GetMeter() )
|
||||
continue;
|
||||
if( iMeterHigh < pSteps->GetMeter() )
|
||||
continue;
|
||||
|
||||
return pSteps;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Steps* SongUtil::GetStepsByDescription( const Song *pSong, StepsType st, RString sDescription )
|
||||
{
|
||||
vector<Steps*> vNotes;
|
||||
GetSteps( pSong, vNotes, st, DIFFICULTY_INVALID, -1, -1, sDescription );
|
||||
if( vNotes.size() == 0 )
|
||||
return NULL;
|
||||
else
|
||||
return vNotes[0];
|
||||
}
|
||||
|
||||
|
||||
Steps* SongUtil::GetClosestNotes( const Song *pSong, StepsType st, Difficulty dc, bool bIgnoreLocked )
|
||||
{
|
||||
ASSERT( dc != DIFFICULTY_INVALID );
|
||||
|
||||
const vector<Steps*>& vpSteps = (st == STEPS_TYPE_INVALID)? pSong->GetAllSteps() : pSong->GetStepsByStepsType(st);
|
||||
Steps *pClosest = NULL;
|
||||
int iClosestDistance = 999;
|
||||
for( unsigned i=0; i<vpSteps.size(); i++ ) // for each of the Song's Steps
|
||||
{
|
||||
Steps* pSteps = vpSteps[i];
|
||||
|
||||
if( pSteps->GetDifficulty() == DIFFICULTY_EDIT && dc != DIFFICULTY_EDIT )
|
||||
continue;
|
||||
if( bIgnoreLocked && UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
|
||||
continue;
|
||||
|
||||
int iDistance = abs(dc - pSteps->GetDifficulty());
|
||||
if( iDistance < iClosestDistance )
|
||||
{
|
||||
pClosest = pSteps;
|
||||
iClosestDistance = iDistance;
|
||||
}
|
||||
}
|
||||
|
||||
return pClosest;
|
||||
}
|
||||
|
||||
|
||||
/* Make any duplicate difficulties edits. (Note that BMS files do a first pass
|
||||
* on this; see BMSLoader::SlideDuplicateDifficulties.) */
|
||||
void SongUtil::AdjustDuplicateSteps( Song *pSong )
|
||||
{
|
||||
FOREACH_StepsType( st )
|
||||
{
|
||||
FOREACH_Difficulty( dc )
|
||||
{
|
||||
if( dc == DIFFICULTY_EDIT )
|
||||
continue;
|
||||
|
||||
vector<Steps*> vSteps;
|
||||
SongUtil::GetSteps( pSong, vSteps, st, dc );
|
||||
|
||||
/* Delete steps that are completely identical. This happened due to a
|
||||
* bug in an earlier version. */
|
||||
DeleteDuplicateSteps( pSong, vSteps );
|
||||
|
||||
CHECKPOINT;
|
||||
StepsUtil::SortNotesArrayByDifficulty( vSteps );
|
||||
CHECKPOINT;
|
||||
for( unsigned k=1; k<vSteps.size(); k++ )
|
||||
{
|
||||
vSteps[k]->SetDifficulty( DIFFICULTY_EDIT );
|
||||
if( vSteps[k]->GetDescription() == "" )
|
||||
{
|
||||
/* "Hard Edit" */
|
||||
RString EditName = Capitalize( DifficultyToString(dc) ) + " Edit";
|
||||
vSteps[k]->SetDescription( EditName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: Don't allow edits to have descriptions that look like regular difficulties.
|
||||
* These are confusing, and they're ambiguous when passed to GetStepsByID. */
|
||||
}
|
||||
}
|
||||
|
||||
static RString RemoveInitialWhitespace( RString s )
|
||||
{
|
||||
size_t i = s.find_first_not_of(" \t\r\n");
|
||||
if( i != s.npos )
|
||||
s.erase( 0, i );
|
||||
return s;
|
||||
}
|
||||
|
||||
/* This is called within TidyUpData, before autogen notes are added. */
|
||||
void SongUtil::DeleteDuplicateSteps( Song *pSong, vector<Steps*> &vSteps )
|
||||
{
|
||||
/* vSteps have the same StepsType and Difficulty. Delete them if they have the
|
||||
* same m_sDescription, m_iMeter and SMNoteData. */
|
||||
CHECKPOINT;
|
||||
for( unsigned i=0; i<vSteps.size(); i++ )
|
||||
{
|
||||
CHECKPOINT;
|
||||
const Steps *s1 = vSteps[i];
|
||||
|
||||
for( unsigned j=i+1; j<vSteps.size(); j++ )
|
||||
{
|
||||
CHECKPOINT;
|
||||
const Steps *s2 = vSteps[j];
|
||||
|
||||
if( s1->GetDescription() != s2->GetDescription() )
|
||||
continue;
|
||||
if( s1->GetMeter() != s2->GetMeter() )
|
||||
continue;
|
||||
/* Compare, ignoring whitespace. */
|
||||
RString sSMNoteData1;
|
||||
s1->GetSMNoteData( sSMNoteData1 );
|
||||
RString sSMNoteData2;
|
||||
s2->GetSMNoteData( sSMNoteData2 );
|
||||
if( RemoveInitialWhitespace(sSMNoteData1) != RemoveInitialWhitespace(sSMNoteData2) )
|
||||
continue;
|
||||
|
||||
LOG->Trace("Removed %p duplicate steps in song \"%s\" with description \"%s\" and meter \"%i\"",
|
||||
s2, pSong->GetSongDir().c_str(), s1->GetDescription().c_str(), s1->GetMeter() );
|
||||
|
||||
pSong->DeleteSteps( s2, false );
|
||||
|
||||
vSteps.erase(vSteps.begin()+j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LocalizedString SORT_NOT_AVAILABLE( "Sort", "NotAvailable" );
|
||||
static LocalizedString SORT_OTHER ( "Sort", "Other" );
|
||||
|
||||
/////////////////////////////////////
|
||||
// Sorting
|
||||
/////////////////////////////////////
|
||||
|
||||
static LocalizedString SORT_NOT_AVAILABLE( "Sort", "NotAvailable" );
|
||||
static LocalizedString SORT_OTHER ( "Sort", "Other" );
|
||||
|
||||
/* Just calculating GetNumTimesPlayed within the sort is pretty slow, so let's precompute
|
||||
* it. (This could be generalized with a template.) */
|
||||
static map<const Song*, RString> g_mapSongSortVal;
|
||||
@@ -280,28 +515,28 @@ RString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so
|
||||
}
|
||||
case SORT_EASY_METER:
|
||||
{
|
||||
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_EASY);
|
||||
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_EASY);
|
||||
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
|
||||
return ssprintf("%02d", pSteps->GetMeter() );
|
||||
return SORT_NOT_AVAILABLE.GetValue();
|
||||
}
|
||||
case SORT_MEDIUM_METER:
|
||||
{
|
||||
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_MEDIUM);
|
||||
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_MEDIUM);
|
||||
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
|
||||
return ssprintf("%02d", pSteps->GetMeter() );
|
||||
return SORT_NOT_AVAILABLE.GetValue();
|
||||
}
|
||||
case SORT_HARD_METER:
|
||||
{
|
||||
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_HARD);
|
||||
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_HARD);
|
||||
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
|
||||
return ssprintf("%02d", pSteps->GetMeter() );
|
||||
return SORT_NOT_AVAILABLE.GetValue();
|
||||
}
|
||||
case SORT_CHALLENGE_METER:
|
||||
{
|
||||
Steps* pSteps = pSong->GetStepsByDifficulty(GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_CHALLENGE);
|
||||
Steps* pSteps = GetStepsByDifficulty(pSong, GAMESTATE->GetCurrentStyle()->m_StepsType,DIFFICULTY_CHALLENGE);
|
||||
if( pSteps && !UNLOCKMAN->StepsIsLocked(pSong,pSteps) )
|
||||
return ssprintf("%02d", pSteps->GetMeter() );
|
||||
return SORT_NOT_AVAILABLE.GetValue();
|
||||
@@ -343,7 +578,7 @@ void SongUtil::SortSongPointerArrayByMeter( vector<Song*> &vpSongsInOut, Difficu
|
||||
for(unsigned i = 0; i < vpSongsInOut.size(); ++i)
|
||||
{
|
||||
/* Ignore locked steps. */
|
||||
const Steps* pSteps = vpSongsInOut[i]->GetClosestNotes( GAMESTATE->GetCurrentStyle()->m_StepsType, dc, true );
|
||||
const Steps* pSteps = GetClosestNotes( vpSongsInOut[i], GAMESTATE->GetCurrentStyle()->m_StepsType, dc, true );
|
||||
RString &s = g_mapSongSortVal[vpSongsInOut[i]];
|
||||
s = ssprintf("%03d", pSteps ? pSteps->GetMeter() : 0);
|
||||
|
||||
@@ -448,7 +683,7 @@ bool SongUtil::ValidateCurrentEditStepsDescription( const RString &sAnswer, RStr
|
||||
|
||||
// Steps name must be unique for this song.
|
||||
vector<Steps*> v;
|
||||
pSong->GetSteps( v, STEPS_TYPE_INVALID, DIFFICULTY_EDIT );
|
||||
GetSteps( pSong, v, STEPS_TYPE_INVALID, DIFFICULTY_EDIT );
|
||||
FOREACH_CONST( Steps*, v, s )
|
||||
{
|
||||
if( pSteps == *s )
|
||||
@@ -486,6 +721,20 @@ bool SongUtil::ValidateCurrentStepsDescription( const RString &sAnswer, RString
|
||||
return true;
|
||||
}
|
||||
|
||||
void SongUtil::GetAllSongGenres( vector<RString> &vsOut )
|
||||
{
|
||||
set<RString> genres;
|
||||
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), song )
|
||||
{
|
||||
if( !(*song)->m_sGenre.empty() )
|
||||
genres.insert( (*song)->m_sGenre );
|
||||
}
|
||||
|
||||
FOREACHS_CONST( RString, genres, s )
|
||||
{
|
||||
vsOut.push_back( *s );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
|
||||
@@ -11,8 +11,52 @@ class Steps;
|
||||
class Profile;
|
||||
class XNode;
|
||||
|
||||
|
||||
class SongCriteria
|
||||
{
|
||||
public:
|
||||
RString m_sGroupName; // "" means don't match
|
||||
RString m_sGenre; // "" means don't match
|
||||
|
||||
SongCriteria()
|
||||
{
|
||||
|
||||
}
|
||||
bool Matches( const Song *p ) const;
|
||||
};
|
||||
|
||||
namespace SongUtil
|
||||
{
|
||||
void GetSteps(
|
||||
const Song *pSong,
|
||||
vector<Steps*>& arrayAddTo,
|
||||
StepsType st = STEPS_TYPE_INVALID,
|
||||
Difficulty dc = DIFFICULTY_INVALID,
|
||||
int iMeterLow = -1,
|
||||
int iMeterHigh = -1,
|
||||
const RString &sDescription = "",
|
||||
bool bIncludeAutoGen = true,
|
||||
unsigned uHash = 0,
|
||||
int iMaxToGet = -1
|
||||
);
|
||||
Steps* GetOneSteps(
|
||||
const Song *pSong,
|
||||
StepsType st = STEPS_TYPE_INVALID,
|
||||
Difficulty dc = DIFFICULTY_INVALID,
|
||||
int iMeterLow = -1,
|
||||
int iMeterHigh = -1,
|
||||
const RString &sDescription = "",
|
||||
unsigned uHash = 0,
|
||||
bool bIncludeAutoGen = true
|
||||
);
|
||||
Steps* GetStepsByDifficulty( const Song *pSong, StepsType st, Difficulty dc, bool bIncludeAutoGen = true );
|
||||
Steps* GetStepsByMeter( const Song *pSong, StepsType st, int iMeterLow, int iMeterHigh );
|
||||
Steps* GetStepsByDescription( const Song *pSong, StepsType st, RString sDescription );
|
||||
Steps* GetClosestNotes( const Song *pSong, StepsType st, Difficulty dc, bool bIgnoreLocked=false );
|
||||
|
||||
void AdjustDuplicateSteps( Song *pSong ); // part of TidyUpData
|
||||
void DeleteDuplicateSteps( Song *pSong, vector<Steps*> &vSteps );
|
||||
|
||||
RString MakeSortString( RString s );
|
||||
void SortSongPointerArrayByTitle( vector<Song*> &vpSongsInOut );
|
||||
void SortSongPointerArrayByBPM( vector<Song*> &vpSongsInOut );
|
||||
@@ -24,7 +68,7 @@ namespace SongUtil
|
||||
void SortSongPointerArrayByNumPlays( vector<Song*> &vpSongsInOut, ProfileSlot slot, bool bDescending );
|
||||
void SortSongPointerArrayByNumPlays( vector<Song*> &vpSongsInOut, const Profile* pProfile, bool bDescending );
|
||||
void SortSongPointerArrayByMeter( vector<Song*> &vpSongsInOut, Difficulty dc );
|
||||
RString GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so );
|
||||
RString GetSectionNameFromSongAndSort( const Song *pSong, SortOrder so );
|
||||
void SortSongPointerArrayBySectionName( vector<Song*> &vpSongsInOut, SortOrder so );
|
||||
void SortByMostRecentlyPlayedForMachine( vector<Song*> &vpSongsInOut );
|
||||
|
||||
@@ -34,6 +78,9 @@ namespace SongUtil
|
||||
RString MakeUniqueEditDescription( const Song* pSong, StepsType st, const RString &sPreferredDescription );
|
||||
bool ValidateCurrentEditStepsDescription( const RString &sAnswer, RString &sErrorOut );
|
||||
bool ValidateCurrentStepsDescription( const RString &sAnswer, RString &sErrorOut );
|
||||
|
||||
void GetAllSongGenres( vector<RString> &vsOut );
|
||||
void FilterSongs( const SongCriteria &sc, const vector<Song*> &in, vector<Song*> &out );
|
||||
}
|
||||
|
||||
class SongID
|
||||
|
||||
@@ -8,18 +8,47 @@
|
||||
#include "GameManager.h"
|
||||
#include "XmlFile.h"
|
||||
#include "UnlockManager.h"
|
||||
#include "SongUtil.h"
|
||||
|
||||
|
||||
bool StepsCriteria::Matches( const Steps *p ) const
|
||||
{
|
||||
if( m_difficulty != DIFFICULTY_INVALID && p->GetDifficulty() != m_difficulty )
|
||||
return false;
|
||||
if( m_iLowMeter != -1 && p->GetMeter() < m_iLowMeter )
|
||||
return false;
|
||||
if( m_iHighMeter != -1 && p->GetMeter() > m_iHighMeter )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StepsUtil::GetAllMatching( const SongCriteria &soc, const StepsCriteria &stc, vector<SongAndSteps> &out )
|
||||
{
|
||||
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), so )
|
||||
{
|
||||
if( !soc.Matches(*so) )
|
||||
continue;
|
||||
FOREACH_CONST( Steps*, (*so)->GetAllSteps(), st )
|
||||
{
|
||||
if( !stc.Matches(*st) )
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Sorting stuff
|
||||
//
|
||||
map<const Steps*, RString> steps_sort_val;
|
||||
|
||||
bool CompareStepsPointersBySortValueAscending(const Steps *pSteps1, const Steps *pSteps2)
|
||||
static bool CompareStepsPointersBySortValueAscending(const Steps *pSteps1, const Steps *pSteps2)
|
||||
{
|
||||
return steps_sort_val[pSteps1] < steps_sort_val[pSteps2];
|
||||
}
|
||||
|
||||
bool CompareStepsPointersBySortValueDescending(const Steps *pSteps1, const Steps *pSteps2)
|
||||
static bool CompareStepsPointersBySortValueDescending(const Steps *pSteps1, const Steps *pSteps2)
|
||||
{
|
||||
return steps_sort_val[pSteps1] > steps_sort_val[pSteps2];
|
||||
}
|
||||
@@ -191,11 +220,11 @@ Steps *StepsID::ToSteps( const Song *p, bool bAllowNull, bool bUseCache ) const
|
||||
Steps *ret = NULL;
|
||||
if( dc == DIFFICULTY_EDIT )
|
||||
{
|
||||
ret = p->GetOneSteps( st, dc, -1, -1, sDescription, uHash, true );
|
||||
ret = SongUtil::GetOneSteps( p, st, dc, -1, -1, sDescription, uHash, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = p->GetOneSteps( st, dc, -1, -1, "", 0, true );
|
||||
ret = SongUtil::GetOneSteps( p, st, dc, -1, -1, "", 0, true );
|
||||
}
|
||||
|
||||
if( !bAllowNull && ret == NULL )
|
||||
|
||||
@@ -8,9 +8,39 @@ class Steps;
|
||||
class Song;
|
||||
class Profile;
|
||||
class XNode;
|
||||
class SongCriteria;
|
||||
|
||||
class StepsCriteria
|
||||
{
|
||||
public:
|
||||
Difficulty m_difficulty; // don't filter if DIFFICULTY_INVALID
|
||||
int m_iLowMeter; // don't filter if -1
|
||||
int m_iHighMeter; // don't filter if -1
|
||||
|
||||
StepsCriteria()
|
||||
{
|
||||
m_difficulty = DIFFICULTY_INVALID;
|
||||
m_iLowMeter = -1;
|
||||
m_iHighMeter = -1;
|
||||
}
|
||||
|
||||
bool Matches( const Steps *p ) const;
|
||||
};
|
||||
|
||||
class SongAndSteps
|
||||
{
|
||||
public:
|
||||
Song* pSong;
|
||||
Steps* pSteps;
|
||||
bool operator==( const SongAndSteps& other ) const { return pSong==other.pSong && pSteps==other.pSteps; }
|
||||
bool operator<( const SongAndSteps& other ) const { return pSong<=other.pSong && pSteps<=other.pSteps; }
|
||||
};
|
||||
|
||||
namespace StepsUtil
|
||||
{
|
||||
|
||||
void GetAllMatching( const SongCriteria &soc, const StepsCriteria &stc, vector<SongAndSteps> &out ); // look up in SONGMAN
|
||||
|
||||
bool CompareNotesPointersByRadarValues(const Steps* pSteps1, const Steps* pSteps2);
|
||||
bool CompareNotesPointersByMeter(const Steps *pSteps1, const Steps* pSteps2);
|
||||
bool CompareNotesPointersByDifficulty(const Steps *pSteps1, const Steps *pSteps2);
|
||||
|
||||
@@ -307,7 +307,8 @@ UnlockEntryStatus UnlockEntry::GetUnlockEntryStatus() const
|
||||
if( m_bRequirePassHardSteps && m_pSong )
|
||||
{
|
||||
vector<Steps*> vp;
|
||||
m_pSong->GetSteps(
|
||||
SongUtil::GetSteps(
|
||||
m_pSong,
|
||||
vp,
|
||||
STEPS_TYPE_INVALID,
|
||||
DIFFICULTY_HARD
|
||||
@@ -454,11 +455,11 @@ void UnlockManager::Load()
|
||||
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), s )
|
||||
{
|
||||
// If no hard steps to play to unlock, skip
|
||||
if( (*s)->GetOneSteps(STEPS_TYPE_INVALID, DIFFICULTY_HARD) == NULL )
|
||||
if( SongUtil::GetOneSteps(*s, STEPS_TYPE_INVALID, DIFFICULTY_HARD) == NULL )
|
||||
continue;
|
||||
|
||||
// If no challenge steps to unlock, skip
|
||||
if( (*s)->GetOneSteps(STEPS_TYPE_INVALID, DIFFICULTY_CHALLENGE) == NULL )
|
||||
if( SongUtil::GetOneSteps(*s, STEPS_TYPE_INVALID, DIFFICULTY_CHALLENGE) == NULL )
|
||||
continue;
|
||||
|
||||
if( SONGMAN->WasLoadedFromAdditionalSongs(*s) )
|
||||
|
||||
+1
-27
@@ -186,30 +186,6 @@ public:
|
||||
bool HasStepsTypeAndDifficulty( StepsType st, Difficulty dc ) const;
|
||||
const vector<Steps*>& GetAllSteps() const { return m_vpSteps; }
|
||||
const vector<Steps*>& GetStepsByStepsType( StepsType st ) const { return m_vpStepsByType[st]; }
|
||||
void GetSteps(
|
||||
vector<Steps*>& arrayAddTo,
|
||||
StepsType st = STEPS_TYPE_INVALID,
|
||||
Difficulty dc = DIFFICULTY_INVALID,
|
||||
int iMeterLow = -1,
|
||||
int iMeterHigh = -1,
|
||||
const RString &sDescription = "",
|
||||
bool bIncludeAutoGen = true,
|
||||
unsigned uHash = 0,
|
||||
int iMaxToGet = -1
|
||||
) const;
|
||||
Steps* GetOneSteps(
|
||||
StepsType st = STEPS_TYPE_INVALID,
|
||||
Difficulty dc = DIFFICULTY_INVALID,
|
||||
int iMeterLow = -1,
|
||||
int iMeterHigh = -1,
|
||||
const RString &sDescription = "",
|
||||
unsigned uHash = 0,
|
||||
bool bIncludeAutoGen = true
|
||||
) const;
|
||||
Steps* GetStepsByDifficulty( StepsType st, Difficulty dc, bool bIncludeAutoGen = true ) const;
|
||||
Steps* GetStepsByMeter( StepsType st, int iMeterLow, int iMeterHigh ) const;
|
||||
Steps* GetStepsByDescription( StepsType st, RString sDescription ) const;
|
||||
Steps* GetClosestNotes( StepsType st, Difficulty dc, bool bIgnoreLocked=false ) const;
|
||||
bool IsEasy( StepsType st ) const;
|
||||
bool IsTutorial() const;
|
||||
bool HasEdits( StepsType st ) const;
|
||||
@@ -220,7 +196,7 @@ public:
|
||||
bool ShowInDemonstrationAndRanking() const;
|
||||
|
||||
void AddSteps( Steps* pSteps ); // we are responsible for deleting the memory pointed to by pSteps!
|
||||
void DeleteSteps( const Steps* pSteps );
|
||||
void DeleteSteps( const Steps* pSteps, bool bReAutoGen = true );
|
||||
|
||||
void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_INVALID );
|
||||
bool WasLoadedFromProfile() const { return m_LoadedFromProfile != ProfileSlot_INVALID; }
|
||||
@@ -239,8 +215,6 @@ public:
|
||||
void PushSelf( lua_State *L );
|
||||
|
||||
private:
|
||||
void AdjustDuplicateSteps(); // part of TidyUpData
|
||||
void DeleteDuplicateSteps( vector<Steps*> &vSteps );
|
||||
|
||||
vector<Steps*> m_vpSteps;
|
||||
vector<Steps*> m_vpStepsByType[NUM_STEPS_TYPES];
|
||||
|
||||
Reference in New Issue
Block a user