add background support to BMS files (only #BMP, not #BGA)
This commit is contained in:
+132
-1
@@ -14,6 +14,7 @@
|
|||||||
#include "NoteTypes.h"
|
#include "NoteTypes.h"
|
||||||
#include "NotesLoader.h"
|
#include "NotesLoader.h"
|
||||||
#include "PrefsManager.h"
|
#include "PrefsManager.h"
|
||||||
|
#include "BackgroundUtil.h"
|
||||||
|
|
||||||
/* BMS encoding: tap-hold
|
/* BMS encoding: tap-hold
|
||||||
* 4&8panel: Player1 Player2
|
* 4&8panel: Player1 Player2
|
||||||
@@ -273,9 +274,14 @@ class BMSSong {
|
|||||||
map<RString, int> mapKeysoundToIndex;
|
map<RString, int> mapKeysoundToIndex;
|
||||||
Song *out;
|
Song *out;
|
||||||
|
|
||||||
|
bool backgroundsPrecached = false;
|
||||||
|
void PrecacheBackgrounds(const RString &dir);
|
||||||
|
map<RString, RString> mapBackground;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BMSSong( Song *song );
|
BMSSong( Song *song );
|
||||||
int AllocateKeysound( RString filename, RString path );
|
int AllocateKeysound( RString filename, RString path );
|
||||||
|
bool GetBackground( RString filename, RString path, RString &bgfile );
|
||||||
Song *GetSong();
|
Song *GetSong();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -304,7 +310,7 @@ int BMSSong::AllocateKeysound( RString filename, RString path )
|
|||||||
|
|
||||||
// try to normalize the filename first!
|
// try to normalize the filename first!
|
||||||
|
|
||||||
// FIXME: garbled song names seem to crash the app.
|
// FIXME: garbled file names seem to crash the app.
|
||||||
// this might not be the best place to put this code.
|
// this might not be the best place to put this code.
|
||||||
if( !utf8_is_valid(filename) )
|
if( !utf8_is_valid(filename) )
|
||||||
return -1;
|
return -1;
|
||||||
@@ -351,6 +357,88 @@ int BMSSong::AllocateKeysound( RString filename, RString path )
|
|||||||
mapKeysoundToIndex[filename] = index;
|
mapKeysoundToIndex[filename] = index;
|
||||||
mapKeysoundToIndex[normalizedFilename] = index;
|
mapKeysoundToIndex[normalizedFilename] = index;
|
||||||
return index;
|
return index;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BMSSong::GetBackground( RString filename, RString path, RString &bgfile )
|
||||||
|
{
|
||||||
|
// Check for already tried backgrounds
|
||||||
|
if( mapBackground.find( filename ) != mapBackground.end() )
|
||||||
|
{
|
||||||
|
RString bg = mapBackground[filename];
|
||||||
|
if( bg == "" )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bgfile = bg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: garbled file names seem to crash the app.
|
||||||
|
// this might not be the best place to put this code.
|
||||||
|
if( !utf8_is_valid(filename) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
RString normalizedFilename = filename;
|
||||||
|
RString dir = out->GetSongDir();
|
||||||
|
|
||||||
|
if (dir.empty())
|
||||||
|
dir = Dirname(path);
|
||||||
|
|
||||||
|
if( !backgroundsPrecached )
|
||||||
|
{
|
||||||
|
PrecacheBackgrounds(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !IsAFile(dir + normalizedFilename) )
|
||||||
|
{
|
||||||
|
const char *exts[] = { "ogv", "avi", "mpg", "mpeg", "bmp", "png", "jpeg", NULL }; // XXX: stop duplicating these everywhere
|
||||||
|
for( unsigned i = 0; exts[i] != NULL; ++i )
|
||||||
|
{
|
||||||
|
RString fn = SetExtension( normalizedFilename, exts[i] );
|
||||||
|
if( IsAFile(dir + fn) )
|
||||||
|
{
|
||||||
|
normalizedFilename = fn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !IsAFile(dir + normalizedFilename) )
|
||||||
|
{
|
||||||
|
mapBackground[filename] = "";
|
||||||
|
LOG->UserLog( "Song file", dir, "references bmp \"%s\" that can't be found", normalizedFilename.c_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapBackground[filename] = normalizedFilename;
|
||||||
|
bgfile = normalizedFilename;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void BMSSong::PrecacheBackgrounds(const RString &dir)
|
||||||
|
{
|
||||||
|
if( backgroundsPrecached ) return;
|
||||||
|
backgroundsPrecached = true;
|
||||||
|
vector<RString> arrayPossibleFiles;
|
||||||
|
|
||||||
|
const char *exts[] = { "ogv", "avi", "mpg", "mpeg", "bmp", "png", "jpeg", NULL }; // XXX: stop duplicating these everywhere
|
||||||
|
|
||||||
|
for( unsigned i = 0; exts[i] != NULL; ++i )
|
||||||
|
{
|
||||||
|
GetDirListing( dir + RString("*.") + RString(exts[i]), arrayPossibleFiles );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned i = 0; i < arrayPossibleFiles.size(); i++ )
|
||||||
|
{
|
||||||
|
for( unsigned j = 0; exts[j] != NULL; ++j )
|
||||||
|
{
|
||||||
|
RString fn = SetExtension( arrayPossibleFiles[i], exts[j] );
|
||||||
|
mapBackground[fn] = arrayPossibleFiles[i];
|
||||||
|
}
|
||||||
|
mapBackground[arrayPossibleFiles[i]] = arrayPossibleFiles[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BMSChartInfo {
|
struct BMSChartInfo {
|
||||||
@@ -361,9 +449,12 @@ struct BMSChartInfo {
|
|||||||
RString backgroundFile;
|
RString backgroundFile;
|
||||||
RString stageFile;
|
RString stageFile;
|
||||||
RString musicFile;
|
RString musicFile;
|
||||||
|
|
||||||
|
map<int, RString> backgroundChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BMSChartReader {
|
class BMSChartReader {
|
||||||
|
|
||||||
BMSChart *in;
|
BMSChart *in;
|
||||||
Steps *out;
|
Steps *out;
|
||||||
BMSSong *song;
|
BMSSong *song;
|
||||||
@@ -785,6 +876,33 @@ bool BMSChartReader::ReadNoteData()
|
|||||||
if( bpm > 0 ) td.SetBPMAtRow( row, measureAdjust * (currentBPM = bpm) );
|
if( bpm > 0 ) td.SetBPMAtRow( row, measureAdjust * (currentBPM = bpm) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if( channel == 4 ) // bga change
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if( !bgaFound )
|
||||||
|
{
|
||||||
|
info.bgaRow = row;
|
||||||
|
bgaFound = true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
RString search = ssprintf( "#bga%s", obj.value.c_str() );
|
||||||
|
BMSHeaders::iterator it = in->headers.find( search );
|
||||||
|
if( it != in->headers.end() )
|
||||||
|
{
|
||||||
|
// TODO: #BGA isn't supported yet.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
search = ssprintf( "#bmp%s", obj.value.c_str() );
|
||||||
|
it = in->headers.find( search );
|
||||||
|
|
||||||
|
RString bg;
|
||||||
|
if (song->GetBackground(it->second, in->path, bg))
|
||||||
|
{
|
||||||
|
info.backgroundChanges[row] = bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if( channel == 8 ) // bpm change (extended)
|
else if( channel == 8 ) // bpm change (extended)
|
||||||
{
|
{
|
||||||
RString search = ssprintf( "#bpm%s", obj.value.c_str() );
|
RString search = ssprintf( "#bpm%s", obj.value.c_str() );
|
||||||
@@ -1073,6 +1191,19 @@ void BMSSongLoader::AddToSong()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map<int, RString>::const_iterator it = main.info.backgroundChanges.begin();
|
||||||
|
|
||||||
|
for (; it != main.info.backgroundChanges.end(); it++)
|
||||||
|
{
|
||||||
|
out->AddBackgroundChange(BACKGROUND_LAYER_1,
|
||||||
|
BackgroundChange(NoteRowToBeat(it->first),
|
||||||
|
it->second,
|
||||||
|
"",
|
||||||
|
1.f,
|
||||||
|
SBE_StretchNoLoop));
|
||||||
|
fprintf(stderr, "Adding background change %s %d %s\n", dir.c_str(), it->first, it->second.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
out->m_sMusicFile = main.info.musicFile;
|
out->m_sMusicFile = main.info.musicFile;
|
||||||
out->m_SongTiming = main.steps->m_Timing;
|
out->m_SongTiming = main.steps->m_Timing;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -309,14 +309,15 @@ void SongManager::LoadStepManiaSongDir( RString sDir, LoadingWindow *ld )
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Song* pNewSong = new Song;
|
Song* pNewSong = new Song;
|
||||||
|
m_pSongs.push_back( pNewSong );
|
||||||
if( !pNewSong->LoadFromSongDir( sSongDirName ) )
|
if( !pNewSong->LoadFromSongDir( sSongDirName ) )
|
||||||
{
|
{
|
||||||
// The song failed to load.
|
// The song failed to load.
|
||||||
|
m_pSongs.pop_back();
|
||||||
delete pNewSong;
|
delete pNewSong;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pSongs.push_back( pNewSong );
|
|
||||||
index_entry.push_back( pNewSong );
|
index_entry.push_back( pNewSong );
|
||||||
loaded++;
|
loaded++;
|
||||||
songIndex++;
|
songIndex++;
|
||||||
|
|||||||
Reference in New Issue
Block a user