Backport custom song support. Prefs are CustomSongsEnable, CustomSongsMaxCount, CustomSongsLoadTimeout, CustomSongsMaxSeconds, CustomSongsMaxMegabytes. Metrics are NumProfileSongGroupColors and the colors with it. Profile custom load function is passed PlayerNumber now. Stepmania must run as root to save USB profile scores. (#1470)
This commit is contained in:
+295
-229
@@ -14,7 +14,9 @@
|
||||
#include "TitleSubstitution.h"
|
||||
#include "BannerCache.h"
|
||||
//#include "BackgroundCache.h"
|
||||
#include "ProfileManager.h"
|
||||
#include "Sprite.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageFileManager.h"
|
||||
#include "RageSurface.h"
|
||||
#include "RageTextureManager.h"
|
||||
@@ -271,7 +273,7 @@ static set<RString> BlacklistedImages;
|
||||
* HasMusic(), HasBanner() or GetHashForDirectory().
|
||||
* If true, check the directory hash and reload the song from scratch if it's changed.
|
||||
*/
|
||||
bool Song::LoadFromSongDir( RString sDir, bool load_autosave )
|
||||
bool Song::LoadFromSongDir(RString sDir, bool load_autosave, ProfileSlot from_profile)
|
||||
{
|
||||
// LOG->Trace( "Song::LoadFromSongDir(%s)", sDir.c_str() );
|
||||
ASSERT_M( sDir != "", "Songs can't be loaded from an empty directory!" );
|
||||
@@ -283,26 +285,40 @@ bool Song::LoadFromSongDir( RString sDir, bool load_autosave )
|
||||
// save song dir
|
||||
m_sSongDir = sDir;
|
||||
|
||||
bool use_cache = true;
|
||||
|
||||
// save group name
|
||||
vector<RString> sDirectoryParts;
|
||||
split( m_sSongDir, "/", sDirectoryParts, false );
|
||||
ASSERT( sDirectoryParts.size() >= 4 ); /* e.g. "/Songs/Slow/Taps/" */
|
||||
m_sGroupName = sDirectoryParts[sDirectoryParts.size()-3]; // second from last item
|
||||
ASSERT( m_sGroupName != "" );
|
||||
if(from_profile == ProfileSlot_Invalid)
|
||||
{
|
||||
vector<RString> sDirectoryParts;
|
||||
split( m_sSongDir, "/", sDirectoryParts, false );
|
||||
ASSERT( sDirectoryParts.size() >= 4 ); /* e.g. "/Songs/Slow/Taps/" */
|
||||
m_sGroupName = sDirectoryParts[sDirectoryParts.size()-3]; // second from last item
|
||||
ASSERT( m_sGroupName != "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LoadedFromProfile= from_profile;
|
||||
m_sGroupName= PROFILEMAN->GetProfile(from_profile)->m_sDisplayName;
|
||||
use_cache= false;
|
||||
}
|
||||
|
||||
// First, look in the cache for this song (without loading NoteData)
|
||||
unsigned uCacheHash = SONGINDEX->GetCacheHash(m_sSongDir);
|
||||
bool bUseCache = true;
|
||||
RString sCacheFilePath = GetCacheFilePath();
|
||||
RString cache_file_path;
|
||||
if(m_LoadedFromProfile == ProfileSlot_Invalid)
|
||||
{
|
||||
// First, look in the cache for this song (without loading NoteData)
|
||||
unsigned uCacheHash = SONGINDEX->GetCacheHash(m_sSongDir);
|
||||
cache_file_path = GetCacheFilePath();
|
||||
|
||||
if( !DoesFileExist(sCacheFilePath) )
|
||||
{ bUseCache = false; }
|
||||
else if(!PREFSMAN->m_bFastLoad && GetHashForDirectory(m_sSongDir) != uCacheHash)
|
||||
{ bUseCache = false; } // this cache is out of date
|
||||
else if(load_autosave)
|
||||
{ bUseCache= false; }
|
||||
if( !DoesFileExist(cache_file_path) )
|
||||
{ use_cache = false; }
|
||||
else if(!PREFSMAN->m_bFastLoad && GetHashForDirectory(m_sSongDir) != uCacheHash)
|
||||
{ use_cache = false; } // this cache is out of date
|
||||
else if(load_autosave)
|
||||
{ use_cache= false; }
|
||||
}
|
||||
|
||||
if( bUseCache )
|
||||
if(use_cache)
|
||||
{
|
||||
/*
|
||||
LOG->Trace("Loading '%s' from cache file '%s'.",
|
||||
@@ -310,12 +326,12 @@ bool Song::LoadFromSongDir( RString sDir, bool load_autosave )
|
||||
GetCacheFilePath().c_str());
|
||||
*/
|
||||
SSCLoader loaderSSC;
|
||||
bool bLoadedFromSSC = loaderSSC.LoadFromSimfile( sCacheFilePath, *this, true );
|
||||
bool bLoadedFromSSC = loaderSSC.LoadFromSimfile( cache_file_path, *this, true );
|
||||
if( !bLoadedFromSSC )
|
||||
{
|
||||
// load from .sm
|
||||
SMLoader loaderSM;
|
||||
loaderSM.LoadFromSimfile( sCacheFilePath, *this, true );
|
||||
loaderSM.LoadFromSimfile( cache_file_path, *this, true );
|
||||
loaderSM.TidyUpData( *this, true );
|
||||
}
|
||||
if(m_sMainTitle == "" || (m_sMusicFile == "" && m_vsKeysoundFile.empty()))
|
||||
@@ -335,13 +351,12 @@ bool Song::LoadFromSongDir( RString sDir, bool load_autosave )
|
||||
{
|
||||
LOG->UserLog( "Song", sDir, "has no SSC, SM, SMA, DWI, BMS, or KSF files." );
|
||||
|
||||
vector<RString> vs;
|
||||
GetDirListing( sDir + "*.mp3", vs, false, false );
|
||||
GetDirListing( sDir + "*.oga", vs, false, false );
|
||||
GetDirListing( sDir + "*.ogg", vs, false, false );
|
||||
bool bHasMusic = !vs.empty();
|
||||
vector<RString> audios;
|
||||
FILEMAN->GetDirListingWithMultipleExtensions(sDir,
|
||||
ActorUtil::GetTypeExtensionList(FT_Sound), audios);
|
||||
bool has_music = !audios.empty();
|
||||
|
||||
if( !bHasMusic )
|
||||
if(!has_music)
|
||||
{
|
||||
LOG->UserLog( "Song", sDir, "has no music file either. Ignoring this song directory." );
|
||||
return false;
|
||||
@@ -361,16 +376,52 @@ bool Song::LoadFromSongDir( RString sDir, bool load_autosave )
|
||||
|
||||
// Don't save a cache file if the autosave is being loaded, because the
|
||||
// cache file would contain the autosave filename. -Kyz
|
||||
if(!load_autosave)
|
||||
// Songs loaded from removable profile are never cached, on the
|
||||
// assumption that they'll change frequently and have invalid cache
|
||||
// entries. -Kyz
|
||||
if(!load_autosave && m_LoadedFromProfile == ProfileSlot_Invalid)
|
||||
{
|
||||
// save a cache file so we don't have to parse it all over again next time
|
||||
if(!SaveToCacheFile())
|
||||
{ sCacheFilePath = RString(); }
|
||||
{ cache_file_path = RString(); }
|
||||
}
|
||||
}
|
||||
|
||||
if(m_LoadedFromProfile != ProfileSlot_Invalid)
|
||||
{
|
||||
if(m_fMusicLengthSeconds > PREFSMAN->m_custom_songs_max_seconds)
|
||||
{
|
||||
LOG->Trace("Custom song %s is too long.", m_sSongDir.c_str());
|
||||
return false;
|
||||
}
|
||||
RageFile music;
|
||||
if(!music.Open(GetMusicPath(), RageFile::READ))
|
||||
{
|
||||
LOG->Trace("Custom song %s could not open music.", m_sSongDir.c_str());
|
||||
return false;
|
||||
}
|
||||
if(music.GetFileSize() > PREFSMAN->m_custom_songs_max_megabytes * 1000000)
|
||||
{
|
||||
LOG->Trace("Custom song %s music file is too big.", m_sSongDir.c_str());
|
||||
return false;
|
||||
}
|
||||
m_pre_customify_song_dir= m_sSongDir;
|
||||
m_sSongDir= custom_songify_path(m_sSongDir);
|
||||
m_sBannerFile.clear();
|
||||
m_sJacketFile.clear();
|
||||
m_sCDFile.clear();
|
||||
m_sDiscFile.clear();
|
||||
m_sLyricsFile.clear();
|
||||
m_sBackgroundFile.clear();
|
||||
m_sCDTitleFile.clear();
|
||||
}
|
||||
|
||||
FOREACH( Steps*, m_vpSteps, s )
|
||||
{
|
||||
if(m_LoadedFromProfile != ProfileSlot_Invalid)
|
||||
{
|
||||
(*s)->ChangeFilenamesForCustomSong();
|
||||
}
|
||||
/* Compress all Steps. During initial caching, this will remove cached
|
||||
* NoteData; during cached loads, this will just remove cached SMData. */
|
||||
(*s)->Compress();
|
||||
@@ -653,10 +704,15 @@ void Song::TidyUpData( bool from_cache, bool /* duringCache */ )
|
||||
fill_exts.reserve(4);
|
||||
lists_to_fill.push_back(&music_list);
|
||||
fill_exts.push_back(&ActorUtil::GetTypeExtensionList(FT_Sound));
|
||||
lists_to_fill.push_back(&image_list);
|
||||
fill_exts.push_back(&ActorUtil::GetTypeExtensionList(FT_Bitmap));
|
||||
lists_to_fill.push_back(&movie_list);
|
||||
fill_exts.push_back(&ActorUtil::GetTypeExtensionList(FT_Movie));
|
||||
// Disable bg and banner images and movies for custom songs. Loading
|
||||
// them takes too long. -Kyz
|
||||
if(m_LoadedFromProfile == ProfileSlot_Invalid)
|
||||
{
|
||||
lists_to_fill.push_back(&image_list);
|
||||
fill_exts.push_back(&ActorUtil::GetTypeExtensionList(FT_Bitmap));
|
||||
lists_to_fill.push_back(&movie_list);
|
||||
fill_exts.push_back(&ActorUtil::GetTypeExtensionList(FT_Movie));
|
||||
}
|
||||
lists_to_fill.push_back(&lyric_list);
|
||||
fill_exts.push_back(&lyric_extensions);
|
||||
for(vector<RString>::iterator filename= song_dir_listing.begin();
|
||||
@@ -801,85 +857,6 @@ void Song::TidyUpData( bool from_cache, bool /* duringCache */ )
|
||||
|
||||
}
|
||||
|
||||
// Here's the problem: We have a directory full of images. We want to
|
||||
// determine which image is the banner, which is the background, and
|
||||
// which is the CDTitle.
|
||||
|
||||
// For blank args to FindFirstFilenameContaining. -Kyz
|
||||
vector<RString> empty_list;
|
||||
|
||||
bool has_jacket= HasJacket();
|
||||
bool has_cdimage= HasCDImage();
|
||||
bool has_disc= HasDisc();
|
||||
bool has_cdtitle= HasCDTitle();
|
||||
|
||||
// First, check the file name for hints.
|
||||
if(!m_bHasBanner)
|
||||
{
|
||||
/* If a nonexistant banner file is specified, and we can't find a
|
||||
* replacement, don't wipe out the old value. */
|
||||
//m_sBannerFile = "";
|
||||
|
||||
// find an image with "banner" in the file name
|
||||
vector<RString> contains(1, "banner");
|
||||
/* Some people do things differently for the sake of being different.
|
||||
* Don't match eg. abnormal, numbness. */
|
||||
vector<RString> ends_with(1, " bn");
|
||||
m_bHasBanner= FindFirstFilenameContaining(image_list,
|
||||
m_sBannerFile, empty_list, contains, ends_with);
|
||||
}
|
||||
|
||||
if(!m_bHasBackground)
|
||||
{
|
||||
//m_sBackgroundFile = "";
|
||||
|
||||
// find an image with "bg" or "background" in the file name
|
||||
vector<RString> contains(1, "background");
|
||||
vector<RString> ends_with(1, "bg");
|
||||
m_bHasBackground= FindFirstFilenameContaining(image_list,
|
||||
m_sBackgroundFile, empty_list, contains, ends_with);
|
||||
}
|
||||
|
||||
if(!has_jacket)
|
||||
{
|
||||
// find an image with "jacket" or "albumart" in the filename.
|
||||
vector<RString> starts_with(1, "jk_");
|
||||
vector<RString> contains;
|
||||
contains.reserve(2);
|
||||
contains.push_back("jacket");
|
||||
contains.push_back("albumart");
|
||||
has_jacket= FindFirstFilenameContaining(image_list,
|
||||
m_sJacketFile, starts_with, contains, empty_list);
|
||||
}
|
||||
|
||||
if(!has_cdimage)
|
||||
{
|
||||
// CD image, a la ddr 1st-3rd (not to be confused with CDTitles)
|
||||
// find an image with "-cd" at the end of the filename.
|
||||
vector<RString> ends_with(1, "-cd");
|
||||
has_cdimage= FindFirstFilenameContaining(image_list,
|
||||
m_sCDFile, empty_list, empty_list, ends_with);
|
||||
}
|
||||
|
||||
if(!has_disc)
|
||||
{
|
||||
// a rectangular graphic, not to be confused with CDImage above.
|
||||
vector<RString> ends_with;
|
||||
ends_with.reserve(2);
|
||||
ends_with.push_back(" disc");
|
||||
ends_with.push_back(" title");
|
||||
has_disc= FindFirstFilenameContaining(image_list,
|
||||
m_sDiscFile, empty_list, empty_list, ends_with);
|
||||
}
|
||||
|
||||
if(!has_cdtitle)
|
||||
{
|
||||
// find an image with "cdtitle" in the file name
|
||||
vector<RString> contains(1, "cdtitle");
|
||||
has_cdtitle= FindFirstFilenameContaining(image_list,
|
||||
m_sCDTitleFile, empty_list, contains, empty_list);
|
||||
}
|
||||
|
||||
if(!HasLyrics())
|
||||
{
|
||||
// Check if there is a lyric file in here
|
||||
@@ -889,155 +866,238 @@ void Song::TidyUpData( bool from_cache, bool /* duringCache */ )
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, For the images we still haven't found,
|
||||
* look at the image dimensions of the remaining unclassified images. */
|
||||
for(unsigned int i= 0; i < image_list.size(); ++i) // foreach image
|
||||
// Since banner, bg, and cdtitle are disabled for custom songs, don't try
|
||||
// to find them. -Kyz
|
||||
if(m_LoadedFromProfile == ProfileSlot_Invalid)
|
||||
{
|
||||
if(m_bHasBanner && m_bHasBackground && has_cdtitle)
|
||||
// Here's the problem: We have a directory full of images. We want to
|
||||
// determine which image is the banner, which is the background, and
|
||||
// which is the CDTitle.
|
||||
|
||||
// For blank args to FindFirstFilenameContaining. -Kyz
|
||||
vector<RString> empty_list;
|
||||
|
||||
bool has_jacket= HasJacket();
|
||||
bool has_cdimage= HasCDImage();
|
||||
bool has_disc= HasDisc();
|
||||
bool has_cdtitle= HasCDTitle();
|
||||
|
||||
// First, check the file name for hints.
|
||||
if(!m_bHasBanner)
|
||||
{
|
||||
/* If a nonexistant banner file is specified, and we can't find a
|
||||
* replacement, don't wipe out the old value. */
|
||||
//m_sBannerFile = "";
|
||||
|
||||
// find an image with "banner" in the file name
|
||||
vector<RString> contains(1, "banner");
|
||||
/* Some people do things differently for the sake of being different.
|
||||
* Don't match eg. abnormal, numbness. */
|
||||
vector<RString> ends_with(1, " bn");
|
||||
m_bHasBanner= FindFirstFilenameContaining(image_list,
|
||||
m_sBannerFile, empty_list, contains, ends_with);
|
||||
}
|
||||
|
||||
if(!m_bHasBackground)
|
||||
{
|
||||
//m_sBackgroundFile = "";
|
||||
|
||||
// find an image with "bg" or "background" in the file name
|
||||
vector<RString> contains(1, "background");
|
||||
vector<RString> ends_with(1, "bg");
|
||||
m_bHasBackground= FindFirstFilenameContaining(image_list,
|
||||
m_sBackgroundFile, empty_list, contains, ends_with);
|
||||
}
|
||||
|
||||
if(!has_jacket)
|
||||
{
|
||||
// find an image with "jacket" or "albumart" in the filename.
|
||||
vector<RString> starts_with(1, "jk_");
|
||||
vector<RString> contains;
|
||||
contains.reserve(2);
|
||||
contains.push_back("jacket");
|
||||
contains.push_back("albumart");
|
||||
has_jacket= FindFirstFilenameContaining(image_list,
|
||||
m_sJacketFile, starts_with, contains, empty_list);
|
||||
}
|
||||
|
||||
if(!has_cdimage)
|
||||
{
|
||||
// CD image, a la ddr 1st-3rd (not to be confused with CDTitles)
|
||||
// find an image with "-cd" at the end of the filename.
|
||||
vector<RString> ends_with(1, "-cd");
|
||||
has_cdimage= FindFirstFilenameContaining(image_list,
|
||||
m_sCDFile, empty_list, empty_list, ends_with);
|
||||
}
|
||||
|
||||
if(!has_disc)
|
||||
{
|
||||
// a rectangular graphic, not to be confused with CDImage above.
|
||||
vector<RString> ends_with;
|
||||
ends_with.reserve(2);
|
||||
ends_with.push_back(" disc");
|
||||
ends_with.push_back(" title");
|
||||
has_disc= FindFirstFilenameContaining(image_list,
|
||||
m_sDiscFile, empty_list, empty_list, ends_with);
|
||||
}
|
||||
|
||||
if(!has_cdtitle)
|
||||
{
|
||||
// find an image with "cdtitle" in the file name
|
||||
vector<RString> contains(1, "cdtitle");
|
||||
has_cdtitle= FindFirstFilenameContaining(image_list,
|
||||
m_sCDTitleFile, empty_list, contains, empty_list);
|
||||
}
|
||||
|
||||
/* Now, For the images we still haven't found,
|
||||
* look at the image dimensions of the remaining unclassified images. */
|
||||
for(unsigned int i= 0; i < image_list.size(); ++i) // foreach image
|
||||
{
|
||||
if(m_bHasBanner && m_bHasBackground && has_cdtitle)
|
||||
break; // done
|
||||
|
||||
// ignore DWI "-char" graphics
|
||||
RString lower = image_list[i];
|
||||
lower.MakeLower();
|
||||
if(BlacklistedImages.find(lower) != BlacklistedImages.end())
|
||||
// ignore DWI "-char" graphics
|
||||
RString lower = image_list[i];
|
||||
lower.MakeLower();
|
||||
if(BlacklistedImages.find(lower) != BlacklistedImages.end())
|
||||
continue; // skip
|
||||
|
||||
// Skip any image that we've already classified
|
||||
// Skip any image that we've already classified
|
||||
|
||||
if(m_bHasBanner && m_sBannerFile.EqualsNoCase(image_list[i]))
|
||||
if(m_bHasBanner && m_sBannerFile.EqualsNoCase(image_list[i]))
|
||||
continue; // skip
|
||||
|
||||
if(m_bHasBackground && m_sBackgroundFile.EqualsNoCase(image_list[i]))
|
||||
if(m_bHasBackground && m_sBackgroundFile.EqualsNoCase(image_list[i]))
|
||||
continue; // skip
|
||||
|
||||
if(has_cdtitle && m_sCDTitleFile.EqualsNoCase(image_list[i]))
|
||||
if(has_cdtitle && m_sCDTitleFile.EqualsNoCase(image_list[i]))
|
||||
continue; // skip
|
||||
|
||||
if(has_jacket && m_sJacketFile.EqualsNoCase(image_list[i]))
|
||||
if(has_jacket && m_sJacketFile.EqualsNoCase(image_list[i]))
|
||||
continue; // skip
|
||||
|
||||
if(has_disc && m_sDiscFile.EqualsNoCase(image_list[i]))
|
||||
if(has_disc && m_sDiscFile.EqualsNoCase(image_list[i]))
|
||||
continue; // skip
|
||||
|
||||
if(has_cdimage && m_sCDFile.EqualsNoCase(image_list[i]))
|
||||
if(has_cdimage && m_sCDFile.EqualsNoCase(image_list[i]))
|
||||
continue; // skip
|
||||
|
||||
RString sPath = m_sSongDir + image_list[i];
|
||||
RString sPath = m_sSongDir + image_list[i];
|
||||
|
||||
// We only care about the dimensions.
|
||||
RString error;
|
||||
RageSurface *img = RageSurfaceUtils::LoadFile(sPath, error, true);
|
||||
if(!img)
|
||||
{
|
||||
LOG->UserLog("Graphic file", sPath, "couldn't be loaded: %s", error.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
const int width = img->w;
|
||||
const int height = img->h;
|
||||
delete img;
|
||||
|
||||
if(!m_bHasBackground && width >= 320 && height >= 240)
|
||||
{
|
||||
m_sBackgroundFile = image_list[i];
|
||||
m_bHasBackground= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!m_bHasBanner && 100 <= width && width <= 320 &&
|
||||
50 <= height && height <= 240)
|
||||
{
|
||||
m_sBannerFile = image_list[i];
|
||||
m_bHasBanner= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Some songs have overlarge banners. Check if the ratio is reasonable
|
||||
* (over 2:1; usually over 3:1), and large (not a cdtitle). */
|
||||
if(!m_bHasBanner && width > 200 && float(width) / height > 2.0f)
|
||||
{
|
||||
m_sBannerFile = image_list[i];
|
||||
m_bHasBanner= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Agh. DWI's inline title images are triggering this, resulting in
|
||||
* kanji, etc., being used as a CDTitle for songs with none. Some
|
||||
* sample data from random incarnations:
|
||||
* 42x50 35x50 50x50 144x49
|
||||
* It looks like ~50 height is what people use to align to DWI's font.
|
||||
*
|
||||
* My tallest CDTitle is 44. Let's cut off in the middle and hope for
|
||||
* the best. -(who? -aj) */
|
||||
/* The proper size of a CDTitle is 64x48 or sometihng. Simfile artists
|
||||
* typically don't give a shit about this (see Cetaka's fucking banner
|
||||
* -sized CDTitle). This is also subverted in certain designs (beta
|
||||
* Mungyodance 3 simfiles, for instance, used the CDTitle to hold
|
||||
* various information about the song in question). As it stands,
|
||||
* I'm keeping this code until I figure out wtf to do -aj
|
||||
*/
|
||||
if(!has_cdtitle && width <= 100 && height <= 48)
|
||||
{
|
||||
m_sCDTitleFile = image_list[i];
|
||||
has_cdtitle= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Jacket files typically have the same width and height.
|
||||
if(!has_jacket && width == height)
|
||||
{
|
||||
m_sJacketFile = image_list[i];
|
||||
has_jacket= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disc images are typically rectangular; make sure we have a banner already.
|
||||
if(!has_disc && (width > height) && m_bHasBanner)
|
||||
{
|
||||
if(image_list[i] != m_sBannerFile)
|
||||
// We only care about the dimensions.
|
||||
RString error;
|
||||
RageSurface *img = RageSurfaceUtils::LoadFile(sPath, error, true);
|
||||
if(!img)
|
||||
{
|
||||
m_sDiscFile = image_list[i];
|
||||
has_disc= true;
|
||||
LOG->UserLog("Graphic file", sPath, "couldn't be loaded: %s", error.c_str());
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// CD images are the same as Jackets, typically the same width and height
|
||||
if(!has_cdimage && width == height)
|
||||
{
|
||||
m_sCDFile = image_list[i];
|
||||
has_cdimage= true;
|
||||
continue;
|
||||
const int width = img->w;
|
||||
const int height = img->h;
|
||||
delete img;
|
||||
|
||||
if(!m_bHasBackground && width >= 320 && height >= 240)
|
||||
{
|
||||
m_sBackgroundFile = image_list[i];
|
||||
m_bHasBackground= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!m_bHasBanner && 100 <= width && width <= 320 &&
|
||||
50 <= height && height <= 240)
|
||||
{
|
||||
m_sBannerFile = image_list[i];
|
||||
m_bHasBanner= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Some songs have overlarge banners. Check if the ratio is reasonable
|
||||
* (over 2:1; usually over 3:1), and large (not a cdtitle). */
|
||||
if(!m_bHasBanner && width > 200 && float(width) / height > 2.0f)
|
||||
{
|
||||
m_sBannerFile = image_list[i];
|
||||
m_bHasBanner= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Agh. DWI's inline title images are triggering this, resulting in
|
||||
* kanji, etc., being used as a CDTitle for songs with none. Some
|
||||
* sample data from random incarnations:
|
||||
* 42x50 35x50 50x50 144x49
|
||||
* It looks like ~50 height is what people use to align to DWI's font.
|
||||
*
|
||||
* My tallest CDTitle is 44. Let's cut off in the middle and hope for
|
||||
* the best. -(who? -aj) */
|
||||
/* The proper size of a CDTitle is 64x48 or sometihng. Simfile artists
|
||||
* typically don't give a shit about this (see Cetaka's fucking banner
|
||||
* -sized CDTitle). This is also subverted in certain designs (beta
|
||||
* Mungyodance 3 simfiles, for instance, used the CDTitle to hold
|
||||
* various information about the song in question). As it stands,
|
||||
* I'm keeping this code until I figure out wtf to do -aj
|
||||
*/
|
||||
if(!has_cdtitle && width <= 100 && height <= 48)
|
||||
{
|
||||
m_sCDTitleFile = image_list[i];
|
||||
has_cdtitle= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Jacket files typically have the same width and height.
|
||||
if(!has_jacket && width == height)
|
||||
{
|
||||
m_sJacketFile = image_list[i];
|
||||
has_jacket= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disc images are typically rectangular; make sure we have a banner already.
|
||||
if(!has_disc && (width > height) && m_bHasBanner)
|
||||
{
|
||||
if(image_list[i] != m_sBannerFile)
|
||||
{
|
||||
m_sDiscFile = image_list[i];
|
||||
has_disc= true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// CD images are the same as Jackets, typically the same width and height
|
||||
if(!has_cdimage && width == height)
|
||||
{
|
||||
m_sCDFile = image_list[i];
|
||||
has_cdimage= true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If no BGChanges are specified and there are movies in the song
|
||||
// directory, then assume they are DWI style where the movie begins at
|
||||
// beat 0.
|
||||
if(!HasBGChanges())
|
||||
{
|
||||
/* Use this->GetBeatFromElapsedTime(0) instead of 0 to start when the
|
||||
* music starts. */
|
||||
if(movie_list.size() == 1)
|
||||
// If no BGChanges are specified and there are movies in the song
|
||||
// directory, then assume they are DWI style where the movie begins at
|
||||
// beat 0.
|
||||
if(!HasBGChanges())
|
||||
{
|
||||
this->AddBackgroundChange(BACKGROUND_LAYER_1,
|
||||
BackgroundChange(0, movie_list[0], "", 1.f,
|
||||
SBE_StretchNoLoop));
|
||||
/* Use this->GetBeatFromElapsedTime(0) instead of 0 to start when the
|
||||
* music starts. */
|
||||
if(movie_list.size() == 1)
|
||||
{
|
||||
this->AddBackgroundChange(BACKGROUND_LAYER_1,
|
||||
BackgroundChange(0, movie_list[0], "", 1.f,
|
||||
SBE_StretchNoLoop));
|
||||
}
|
||||
}
|
||||
// Clear fields for files that turned out to not exist.
|
||||
#define CLEAR_NOT_HAS(has_name, field_name) if(!has_name) { field_name= ""; }
|
||||
CLEAR_NOT_HAS(m_bHasBanner, m_sBannerFile);
|
||||
CLEAR_NOT_HAS(m_bHasBackground, m_sBackgroundFile);
|
||||
CLEAR_NOT_HAS(has_jacket, m_sJacketFile);
|
||||
CLEAR_NOT_HAS(has_cdimage, m_sCDFile);
|
||||
CLEAR_NOT_HAS(has_disc, m_sDiscFile);
|
||||
CLEAR_NOT_HAS(has_cdtitle, m_sCDTitleFile);
|
||||
#undef CLEAR_NOT_HAS
|
||||
}
|
||||
// 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. */
|
||||
SongUtil::AdjustDuplicateSteps(this);
|
||||
|
||||
// Clear fields for files that turned out to not exist.
|
||||
#define CLEAR_NOT_HAS(has_name, field_name) if(!has_name) { field_name= ""; }
|
||||
CLEAR_NOT_HAS(m_bHasBanner, m_sBannerFile);
|
||||
CLEAR_NOT_HAS(m_bHasBackground, m_sBackgroundFile);
|
||||
CLEAR_NOT_HAS(has_jacket, m_sJacketFile);
|
||||
CLEAR_NOT_HAS(has_cdimage, m_sCDFile);
|
||||
CLEAR_NOT_HAS(has_disc, m_sDiscFile);
|
||||
CLEAR_NOT_HAS(has_cdtitle, m_sCDTitleFile);
|
||||
#undef CLEAR_NOT_HAS
|
||||
}
|
||||
|
||||
/* Generate these before we autogen notes, so the new notes can inherit
|
||||
@@ -2140,6 +2200,11 @@ public:
|
||||
lua_pushboolean(L, p->GetEnabled());
|
||||
return 1;
|
||||
}
|
||||
static int IsCustomSong(T* p, lua_State* L)
|
||||
{
|
||||
lua_pushboolean(L, p->m_LoadedFromProfile != ProfileSlot_Invalid);
|
||||
return 1;
|
||||
}
|
||||
static int GetGroupName( T* p, lua_State *L )
|
||||
{
|
||||
lua_pushstring(L, p->m_sGroupName);
|
||||
@@ -2362,6 +2427,7 @@ public:
|
||||
ADD_METHOD( GetSongFilePath );
|
||||
ADD_METHOD( IsTutorial );
|
||||
ADD_METHOD( IsEnabled );
|
||||
ADD_METHOD(IsCustomSong);
|
||||
ADD_METHOD( GetGroupName );
|
||||
ADD_METHOD( MusicLengthSeconds );
|
||||
ADD_METHOD( GetSampleStart );
|
||||
|
||||
Reference in New Issue
Block a user