Just about all that can be done before Loading.
This next commit will be the big one it seems.
This commit is contained in:
+97
-106
@@ -258,7 +258,7 @@ static set<RString> BlacklistedImages;
|
||||
bool Song::LoadFromSongDir( RString sDir )
|
||||
{
|
||||
// LOG->Trace( "Song::LoadFromSongDir(%s)", sDir.c_str() );
|
||||
ASSERT( sDir != "" );
|
||||
ASSERT_M( sDir != "", "Songs can't be loaded from an empty directory!" );
|
||||
|
||||
// make sure there is a trailing slash at the end of sDir
|
||||
if( sDir.Right(1) != "/" )
|
||||
@@ -321,10 +321,14 @@ bool Song::LoadFromSongDir( RString sDir )
|
||||
LOG->UserLog( "Song", sDir, "has no music file either. Ignoring this song directory." );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure we have a future filename figured out.
|
||||
vector<RString> folders;
|
||||
split(sDir, "/", folders);
|
||||
RString songName = folders[2] + ".ssc";
|
||||
this->m_sSongFileName = sDir + songName;
|
||||
// Continue on with a blank Song so that people can make adjustments using the editor.
|
||||
}
|
||||
TidyUpData();
|
||||
TidyUpData(false, true);
|
||||
|
||||
// save a cache file so we don't have to parse it all over again next time
|
||||
if( !SaveToCacheFile() )
|
||||
@@ -333,8 +337,6 @@ bool Song::LoadFromSongDir( RString sDir )
|
||||
|
||||
FOREACH( Steps*, m_vpSteps, s )
|
||||
{
|
||||
(*s)->SetFilename( sCacheFilePath );
|
||||
|
||||
/* Compress all Steps. During initial caching, this will remove cached
|
||||
* NoteData; during cached loads, this will just remove cached SMData. */
|
||||
(*s)->Compress();
|
||||
@@ -446,7 +448,7 @@ void FixupPath( RString &path, const RString &sSongPath )
|
||||
}
|
||||
|
||||
// Songs in BlacklistImages will never be autodetected as song images.
|
||||
void Song::TidyUpData( bool bFromCache )
|
||||
void Song::TidyUpData( bool fromCache, bool duringCache )
|
||||
{
|
||||
// We need to do this before calling any of HasMusic, HasHasCDTitle, etc.
|
||||
ASSERT_M( m_sSongDir.Left(3) != "../", m_sSongDir ); // meaningless
|
||||
@@ -543,7 +545,7 @@ void Song::TidyUpData( bool bFromCache )
|
||||
|
||||
/* Generate these before we autogen notes, so the new notes can inherit
|
||||
* their source's values. */
|
||||
ReCalculateRadarValuesAndLastSecond( bFromCache );
|
||||
ReCalculateRadarValuesAndLastSecond( fromCache, true );
|
||||
|
||||
Trim( m_sMainTitle );
|
||||
Trim( m_sSubTitle );
|
||||
@@ -779,11 +781,11 @@ void Song::TidyUpData( bool bFromCache )
|
||||
* music starts. */
|
||||
if( arrayPossibleMovies.size() == 1 )
|
||||
this->AddBackgroundChange(BACKGROUND_LAYER_1,
|
||||
BackgroundChange(0,
|
||||
arrayPossibleMovies[0],
|
||||
"",
|
||||
1.f,
|
||||
SBE_StretchNoLoop));
|
||||
BackgroundChange(0,
|
||||
arrayPossibleMovies[0],
|
||||
"",
|
||||
1.f,
|
||||
SBE_StretchNoLoop));
|
||||
}
|
||||
|
||||
|
||||
@@ -791,64 +793,6 @@ void Song::TidyUpData( bool bFromCache )
|
||||
* for edits). We should be able to use difficulty names as unique
|
||||
* identifiers for steps. */
|
||||
SongUtil::AdjustDuplicateSteps( this );
|
||||
|
||||
{
|
||||
/* Generated filename; this doesn't always point to a loadable file,
|
||||
* but instead points to the file we should write changed files to,
|
||||
* and will always be a .SSC.
|
||||
*
|
||||
* This is a little tricky. We can't always use the song title directly,
|
||||
* since it might contain characters we can't store in filenames. Two
|
||||
* easy options: we could manually filter out invalid characters, or we
|
||||
* could use the name of the directory, which is always a valid filename
|
||||
* and should always be the same as the song. The former might not catch
|
||||
* everything--filename restrictions are platform-specific; we might even
|
||||
* be on an 8.3 filesystem, so let's do the latter.
|
||||
*
|
||||
* We can't rely on searching for other data filenames; it works for DWIs,
|
||||
* but not KSFs and BMSs.
|
||||
*
|
||||
* So, let's do this (by priority):
|
||||
* 1. If there's a .SSC file, use that filename. No reason to use anything
|
||||
* else; it's the filename in use.
|
||||
* 2. If there's an .SM, use it with a changed extension.
|
||||
* 3. If there's a .DWI, use it with a changed extension.
|
||||
* 4. Otherwise, use the name of the directory, since it's definitely a valid
|
||||
* filename, and should always be the title of the song (unlike KSFs). */
|
||||
m_sSongFileName = m_sSongDir;
|
||||
vector<RString> asFileNames;
|
||||
do
|
||||
{
|
||||
GetDirListing( m_sSongDir+"*.ssc", asFileNames );
|
||||
if( !asFileNames.empty() )
|
||||
{
|
||||
m_sSongFileName += asFileNames[0];
|
||||
break;
|
||||
}
|
||||
|
||||
GetDirListing( m_sSongDir+"*.sma", asFileNames );
|
||||
if (!asFileNames.empty() )
|
||||
{
|
||||
m_sSongFileName += SetExtension( asFileNames[0], "ssc" );
|
||||
break;
|
||||
}
|
||||
|
||||
GetDirListing( m_sSongDir+"*.sm", asFileNames );
|
||||
if( !asFileNames.empty() )
|
||||
{
|
||||
m_sSongFileName += SetExtension( asFileNames[0], "ssc" );
|
||||
break;
|
||||
}
|
||||
|
||||
GetDirListing( m_sSongDir+"*.dwi", asFileNames );
|
||||
if( !asFileNames.empty() ) {
|
||||
m_sSongFileName += SetExtension( asFileNames[0], "ssc" );
|
||||
break;
|
||||
}
|
||||
m_sSongFileName += Basename(m_sSongDir);
|
||||
m_sSongFileName += ".ssc";
|
||||
} while(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Song::TranslateTitles()
|
||||
@@ -863,9 +807,9 @@ void Song::TranslateTitles()
|
||||
m_sMainTitleTranslit, m_sSubTitleTranslit, m_sArtistTranslit );
|
||||
}
|
||||
|
||||
void Song::ReCalculateRadarValuesAndLastSecond( bool bFromCache )
|
||||
void Song::ReCalculateRadarValuesAndLastSecond(bool fromCache, bool duringCache)
|
||||
{
|
||||
if( bFromCache && this->GetFirstSecond() >= 0 && this->GetLastSecond() > 0 )
|
||||
if( fromCache && this->GetFirstSecond() >= 0 && this->GetLastSecond() > 0 )
|
||||
{
|
||||
// this is loaded from cache, then we just have to calculate the radar values.
|
||||
for( unsigned i=0; i<m_vpSteps.size(); i++ )
|
||||
@@ -883,35 +827,41 @@ void Song::ReCalculateRadarValuesAndLastSecond( bool bFromCache )
|
||||
|
||||
pSteps->CalculateRadarValues( m_fMusicLengthSeconds );
|
||||
|
||||
// Must initialize before the gotos.
|
||||
NoteData tempNoteData;
|
||||
pSteps->GetNoteData( tempNoteData );
|
||||
|
||||
// calculate lastSecond
|
||||
|
||||
// If it's autogen, then first/last beat will come from the parent.
|
||||
if( pSteps->IsAutogen() )
|
||||
continue;
|
||||
goto wipe_notedata;
|
||||
|
||||
/* Don't calculate with edits unless the song only contains an edit
|
||||
* chart, like those in Mungyodance 3. Otherwise, edits installed on
|
||||
* the machine could extend the length of the song. */
|
||||
if( pSteps->IsAnEdit() && m_vpSteps.size() > 1 )
|
||||
continue;
|
||||
goto wipe_notedata;
|
||||
|
||||
// Don't set first/last beat based on lights. They often start very
|
||||
// early and end very late.
|
||||
if( pSteps->m_StepsType == StepsType_lights_cabinet )
|
||||
continue;
|
||||
|
||||
NoteData tempNoteData;
|
||||
pSteps->GetNoteData( tempNoteData );
|
||||
continue; // no need to wipe this.
|
||||
|
||||
/* Many songs have stray, empty song patterns. Ignore them, so they
|
||||
* don't force the first beat of the whole song to 0. */
|
||||
if( tempNoteData.GetLastRow() == 0 )
|
||||
continue;
|
||||
|
||||
localFirst = min(localFirst,
|
||||
if( tempNoteData.GetLastRow() != 0 )
|
||||
{
|
||||
localFirst = min(localFirst,
|
||||
pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetFirstBeat()));
|
||||
localLast = max(localLast,
|
||||
localLast = max(localLast,
|
||||
pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetLastBeat()));
|
||||
}
|
||||
wipe_notedata:
|
||||
if (duringCache)
|
||||
{
|
||||
// update this when at that point.
|
||||
}
|
||||
}
|
||||
|
||||
this->firstSecond = localFirst;
|
||||
@@ -1005,11 +955,15 @@ bool Song::SaveToSMFile()
|
||||
|
||||
bool Song::SaveToSSCFile( RString sPath, bool bSavingCache )
|
||||
{
|
||||
LOG->Trace( "Song::SaveToSSCFile('%s')", sPath.c_str() );
|
||||
RString path = sPath;
|
||||
if (!bSavingCache)
|
||||
path = SetExtension(sPath, "ssc");
|
||||
|
||||
LOG->Trace( "Song::SaveToSSCFile('%s')", path.c_str() );
|
||||
|
||||
// If the file exists, make a backup.
|
||||
if( !bSavingCache && IsAFile(sPath) )
|
||||
FileCopy( sPath, sPath + ".old" );
|
||||
if( !bSavingCache && IsAFile(path) )
|
||||
FileCopy( path, path + ".old" );
|
||||
|
||||
vector<Steps*> vpStepsToSave;
|
||||
FOREACH_CONST( Steps*, m_vpSteps, s )
|
||||
@@ -1022,16 +976,23 @@ bool Song::SaveToSSCFile( RString sPath, bool bSavingCache )
|
||||
if( pSteps->WasLoadedFromProfile() )
|
||||
continue;
|
||||
|
||||
if (!bSavingCache)
|
||||
pSteps->SetFilename(path);
|
||||
vpStepsToSave.push_back( pSteps );
|
||||
}
|
||||
|
||||
if (bSavingCache)
|
||||
{
|
||||
return NotesWriterSSC::Write(path, *this, vpStepsToSave, bSavingCache);
|
||||
}
|
||||
|
||||
if( !NotesWriterSSC::Write(sPath, *this, vpStepsToSave, bSavingCache) )
|
||||
if( !NotesWriterSSC::Write(path, *this, vpStepsToSave, bSavingCache) )
|
||||
return false;
|
||||
|
||||
if( !bSavingCache && g_BackUpAllSongSaves.Get() )
|
||||
if( g_BackUpAllSongSaves.Get() )
|
||||
{
|
||||
RString sExt = GetExtension( sPath );
|
||||
RString sBackupFile = SetExtension( sPath, "" );
|
||||
RString sExt = GetExtension( path );
|
||||
RString sBackupFile = SetExtension( path, "" );
|
||||
|
||||
time_t cur_time;
|
||||
time( &cur_time );
|
||||
@@ -1043,18 +1004,15 @@ bool Song::SaveToSSCFile( RString sPath, bool bSavingCache )
|
||||
sBackupFile = SetExtension( sBackupFile, sExt );
|
||||
sBackupFile += ssprintf( ".old" );
|
||||
|
||||
if( FileCopy(sPath, sBackupFile) )
|
||||
LOG->Trace( "Backed up %s to %s", sPath.c_str(), sBackupFile.c_str() );
|
||||
if( FileCopy(path, sBackupFile) )
|
||||
LOG->Trace( "Backed up %s to %s", path.c_str(), sBackupFile.c_str() );
|
||||
else
|
||||
LOG->Trace( "Failed to back up %s to %s", sPath.c_str(), sBackupFile.c_str() );
|
||||
LOG->Trace( "Failed to back up %s to %s", path.c_str(), sBackupFile.c_str() );
|
||||
}
|
||||
|
||||
if( !bSavingCache )
|
||||
{
|
||||
// Mark these steps saved to disk.
|
||||
FOREACH( Steps*, vpStepsToSave, s )
|
||||
(*s)->SetSavedToDisk( true );
|
||||
}
|
||||
// Mark these steps saved to disk.
|
||||
FOREACH( Steps*, vpStepsToSave, s )
|
||||
(*s)->SetSavedToDisk( true );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1063,13 +1021,7 @@ bool Song::SaveToCacheFile()
|
||||
{
|
||||
SONGINDEX->AddCacheIndex(m_sSongDir, GetHashForDirectory(m_sSongDir));
|
||||
const RString sPath = GetCacheFilePath();
|
||||
if( !SaveToSSCFile(sPath, true) )
|
||||
return false;
|
||||
|
||||
FOREACH( Steps*, m_vpSteps, pSteps )
|
||||
(*pSteps)->SetFilename( sPath );
|
||||
|
||||
return true;
|
||||
return SaveToSSCFile(sPath, true);
|
||||
}
|
||||
|
||||
bool Song::SaveToDWIFile()
|
||||
@@ -1295,6 +1247,45 @@ vector<BackgroundChange> &Song::GetForegroundChanges()
|
||||
return *m_ForegroundChanges.Get();
|
||||
}
|
||||
|
||||
vector<RString> Song::GetChangesToVectorString(const vector<BackgroundChange> & changes) const
|
||||
{
|
||||
vector<RString> ret;
|
||||
FOREACH_CONST( BackgroundChange, changes, bgc )
|
||||
{
|
||||
ret.push_back((*bgc).ToString());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
vector<RString> Song::GetBGChanges1ToVectorString() const
|
||||
{
|
||||
return this->GetChangesToVectorString(this->GetBackgroundChanges(BACKGROUND_LAYER_1));
|
||||
}
|
||||
|
||||
vector<RString> Song::GetBGChanges2ToVectorString() const
|
||||
{
|
||||
return this->GetChangesToVectorString(this->GetBackgroundChanges(BACKGROUND_LAYER_2));
|
||||
}
|
||||
|
||||
vector<RString> Song::GetFGChanges1ToVectorString() const
|
||||
{
|
||||
return this->GetChangesToVectorString(this->GetForegroundChanges());
|
||||
}
|
||||
|
||||
vector<RString> Song::GetInstrumentTracksToVectorString() const
|
||||
{
|
||||
vector<RString> ret;
|
||||
FOREACH_ENUM(InstrumentTrack, it)
|
||||
{
|
||||
if (this->HasInstrumentTrack(it))
|
||||
{
|
||||
ret.push_back(InstrumentTrackToString(it)
|
||||
+ "="
|
||||
+ this->m_sInstrumentTrackFile[it]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RString GetSongAssetPath( RString sPath, const RString &sSongPath )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user