Added Guest and Test profile types, and profile priorities so the position of a profile in the list can be controlled. Fixes crash bug that occurs when a profile dir is renamed to a non-number and a new profile is made.
This commit is contained in:
+111
@@ -32,6 +32,8 @@ const RString STATS_XML = "Stats.xml";
|
||||
const RString STATS_XML_GZ = "Stats.xml.gz";
|
||||
/** @brief The filename for where one can edit their personal profile information. */
|
||||
const RString EDITABLE_INI = "Editable.ini";
|
||||
/** @brief A tiny file containing the type and list priority. */
|
||||
const RString TYPE_INI = "Type.ini";
|
||||
/** @brief The filename containing the signature for STATS_XML's signature. */
|
||||
const RString DONT_SHARE_SIG = "DontShare.sig";
|
||||
const RString PUBLIC_KEY_FILE = "public.key";
|
||||
@@ -60,6 +62,15 @@ const float DEFAULT_BIRTH_YEAR= 1995;
|
||||
#pragma warning (disable : 4706) // assignment within conditional expression
|
||||
#endif
|
||||
|
||||
static const char* ProfileTypeNames[] = {
|
||||
"Guest",
|
||||
"Normal",
|
||||
"Test",
|
||||
};
|
||||
XToString(ProfileType);
|
||||
StringToX(ProfileType);
|
||||
LuaXType(ProfileType);
|
||||
|
||||
|
||||
int Profile::HighScoresForASong::GetNumTimesPlayed() const
|
||||
{
|
||||
@@ -921,6 +932,64 @@ void Profile::MergeScoresFromOtherProfile(Profile* other, bool skip_totals,
|
||||
}
|
||||
}
|
||||
|
||||
void Profile::swap(Profile& other)
|
||||
{
|
||||
// Type is skipped because this is meant to be used only on matching types,
|
||||
// to move profiles after the priorities have been assigned. -Kyz
|
||||
// A bit of a misnomer, since it actually works on any type that has its
|
||||
// own swap function, which includes the standard containers.
|
||||
#define SWAP_STR_MEMBER(member_name) member_name.swap(other.member_name)
|
||||
#define SWAP_GENERAL(member_name) std::swap(member_name, other.member_name)
|
||||
SWAP_GENERAL(m_ListPriority);
|
||||
SWAP_STR_MEMBER(m_sDisplayName);
|
||||
SWAP_STR_MEMBER(m_sCharacterID);
|
||||
SWAP_STR_MEMBER(m_sLastUsedHighScoreName);
|
||||
SWAP_GENERAL(m_iWeightPounds);
|
||||
SWAP_GENERAL(m_Voomax);
|
||||
SWAP_GENERAL(m_BirthYear);
|
||||
SWAP_GENERAL(m_IgnoreStepCountCalories);
|
||||
SWAP_GENERAL(m_IsMale);
|
||||
SWAP_STR_MEMBER(m_sGuid);
|
||||
SWAP_GENERAL(m_iCurrentCombo);
|
||||
SWAP_GENERAL(m_iTotalSessions);
|
||||
SWAP_GENERAL(m_iTotalSessionSeconds);
|
||||
SWAP_GENERAL(m_iTotalGameplaySeconds);
|
||||
SWAP_GENERAL(m_fTotalCaloriesBurned);
|
||||
SWAP_GENERAL(m_GoalType);
|
||||
SWAP_GENERAL(m_iGoalCalories);
|
||||
SWAP_GENERAL(m_iGoalSeconds);
|
||||
SWAP_GENERAL(m_iTotalDancePoints);
|
||||
SWAP_GENERAL(m_iNumExtraStagesPassed);
|
||||
SWAP_GENERAL(m_iNumExtraStagesFailed);
|
||||
SWAP_GENERAL(m_iNumToasties);
|
||||
SWAP_GENERAL(m_iTotalTapsAndHolds);
|
||||
SWAP_GENERAL(m_iTotalJumps);
|
||||
SWAP_GENERAL(m_iTotalHolds);
|
||||
SWAP_GENERAL(m_iTotalRolls);
|
||||
SWAP_GENERAL(m_iTotalMines);
|
||||
SWAP_GENERAL(m_iTotalHands);
|
||||
SWAP_GENERAL(m_iTotalLifts);
|
||||
SWAP_GENERAL(m_bNewProfile);
|
||||
SWAP_STR_MEMBER(m_UnlockedEntryIDs);
|
||||
SWAP_STR_MEMBER(m_sLastPlayedMachineGuid);
|
||||
SWAP_GENERAL(m_LastPlayedDate);
|
||||
SWAP_GENERAL(m_iNumSongsPlayedByPlayMode);
|
||||
SWAP_STR_MEMBER(m_iNumSongsPlayedByStyle);
|
||||
SWAP_GENERAL(m_iNumSongsPlayedByDifficulty);
|
||||
SWAP_GENERAL(m_iNumSongsPlayedByMeter);
|
||||
SWAP_GENERAL(m_iNumTotalSongsPlayed);
|
||||
SWAP_GENERAL(m_iNumStagesPassedByPlayMode);
|
||||
SWAP_GENERAL(m_iNumStagesPassedByGrade);
|
||||
SWAP_GENERAL(m_UserTable);
|
||||
SWAP_STR_MEMBER(m_SongHighScores);
|
||||
SWAP_STR_MEMBER(m_CourseHighScores);
|
||||
SWAP_GENERAL(m_CategoryHighScores);
|
||||
SWAP_STR_MEMBER(m_vScreenshots);
|
||||
SWAP_STR_MEMBER(m_mapDayToCaloriesBurned);
|
||||
#undef SWAP_STR_MEMBER
|
||||
#undef SWAP_GENERAL
|
||||
}
|
||||
|
||||
// Category high scores
|
||||
void Profile::AddCategoryHighScore( StepsType st, RankingCategory rc, HighScore hs, int &iIndexOut )
|
||||
{
|
||||
@@ -998,6 +1067,7 @@ ProfileLoadResult Profile::LoadAllFromDir( RString sDir, bool bRequireSignature
|
||||
|
||||
InitAll();
|
||||
|
||||
LoadTypeFromDir(sDir);
|
||||
// Not critical if this fails
|
||||
LoadEditableDataFromDir( sDir );
|
||||
|
||||
@@ -1085,6 +1155,34 @@ ProfileLoadResult Profile::LoadAllFromDir( RString sDir, bool bRequireSignature
|
||||
return ProfileLoadResult_Success;
|
||||
}
|
||||
|
||||
void Profile::LoadTypeFromDir(RString dir)
|
||||
{
|
||||
m_Type= ProfileType_Normal;
|
||||
m_ListPriority= 0;
|
||||
RString fn= dir + TYPE_INI;
|
||||
if(FILEMAN->DoesFileExist(fn))
|
||||
{
|
||||
IniFile ini;
|
||||
if(ini.ReadFile(fn))
|
||||
{
|
||||
XNode const* data= ini.GetChild("ListPosition");
|
||||
if(data != NULL)
|
||||
{
|
||||
RString type_str;
|
||||
if(data->GetAttrValue("Type", type_str))
|
||||
{
|
||||
m_Type= StringToProfileType(type_str);
|
||||
if(m_Type >= NUM_ProfileType)
|
||||
{
|
||||
m_Type= ProfileType_Normal;
|
||||
}
|
||||
}
|
||||
data->GetAttrValue("Priority", m_ListPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProfileLoadResult Profile::LoadStatsXmlFromNode( const XNode *xml, bool bIgnoreEditable )
|
||||
{
|
||||
/* The placeholder stats.xml file has an <html> tag. Don't load it,
|
||||
@@ -1135,6 +1233,7 @@ bool Profile::SaveAllToDir( RString sDir, bool bSignData ) const
|
||||
m_sLastPlayedMachineGuid = PROFILEMAN->GetMachineProfile()->m_sGuid;
|
||||
m_LastPlayedDate = DateTime::GetNowDate();
|
||||
|
||||
SaveTypeToDir(sDir);
|
||||
// Save editable.ini
|
||||
SaveEditableDataToDir( sDir );
|
||||
|
||||
@@ -1243,6 +1342,14 @@ bool Profile::SaveStatsXmlToDir( RString sDir, bool bSignData ) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Profile::SaveTypeToDir(RString dir) const
|
||||
{
|
||||
IniFile ini;
|
||||
ini.SetValue("ListPosition", "Type", ProfileTypeToString(m_Type));
|
||||
ini.SetValue("ListPosition", "Priority", m_ListPriority);
|
||||
ini.WriteFile(dir + TYPE_INI);
|
||||
}
|
||||
|
||||
void Profile::SaveEditableDataToDir( RString sDir ) const
|
||||
{
|
||||
IniFile ini;
|
||||
@@ -2289,6 +2396,8 @@ public:
|
||||
p->AddScreenshot(screenshot);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_METHOD(GetType, m_Type);
|
||||
DEFINE_METHOD(GetPriority, m_ListPriority);
|
||||
|
||||
static int GetDisplayName( T* p, lua_State *L ) { lua_pushstring(L, p->m_sDisplayName ); return 1; }
|
||||
static int SetDisplayName( T* p, lua_State *L )
|
||||
@@ -2511,6 +2620,8 @@ public:
|
||||
LunaProfile()
|
||||
{
|
||||
ADD_METHOD( AddScreenshot );
|
||||
ADD_METHOD( GetType );
|
||||
ADD_METHOD( GetPriority );
|
||||
ADD_METHOD( GetDisplayName );
|
||||
ADD_METHOD( SetDisplayName );
|
||||
ADD_METHOD( GetLastUsedHighScoreName );
|
||||
|
||||
+26
-1
@@ -60,6 +60,18 @@ class Song;
|
||||
class Steps;
|
||||
class Course;
|
||||
struct Game;
|
||||
|
||||
// Profile types exist for sorting the list of profiles.
|
||||
// Guest profiles at the top, test at the bottom.
|
||||
enum ProfileType
|
||||
{
|
||||
ProfileType_Guest,
|
||||
ProfileType_Normal,
|
||||
ProfileType_Test,
|
||||
NUM_ProfileType,
|
||||
ProfileType_Invalid
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Player data that persists between sessions.
|
||||
*
|
||||
@@ -73,7 +85,12 @@ public:
|
||||
* Note: there are probably a lot of variables. */
|
||||
// When adding new score related data, add logic for handling it to
|
||||
// MergeScoresFromOtherProfile. -Kyz
|
||||
Profile(): m_sDisplayName(""), m_sCharacterID(""),
|
||||
// When adding any new fields, add them to SwapExceptPriority. Anything not
|
||||
// added to SwapExceptPriority won't be swapped correctly when the user
|
||||
// changes the list priority of a profile. -Kyz
|
||||
Profile():
|
||||
m_Type(ProfileType_Normal), m_ListPriority(0),
|
||||
m_sDisplayName(""), m_sCharacterID(""),
|
||||
m_sLastUsedHighScoreName(""), m_iWeightPounds(0),
|
||||
m_Voomax(0), m_BirthYear(0), m_IgnoreStepCountCalories(false),
|
||||
m_IsMale(true),
|
||||
@@ -149,6 +166,10 @@ public:
|
||||
|
||||
bool IsMachine() const;
|
||||
|
||||
ProfileType m_Type;
|
||||
// Profiles of the same type and priority are sorted by dir name.
|
||||
int m_ListPriority;
|
||||
|
||||
// Editable data
|
||||
RString m_sDisplayName;
|
||||
RString m_sCharacterID;
|
||||
@@ -366,8 +387,11 @@ public:
|
||||
void InitCalorieData();
|
||||
void ClearStats();
|
||||
|
||||
void swap(Profile& other);
|
||||
|
||||
// Loading and saving
|
||||
ProfileLoadResult LoadAllFromDir( RString sDir, bool bRequireSignature );
|
||||
void LoadTypeFromDir(RString dir);
|
||||
void LoadCustomFunction( RString sDir );
|
||||
bool SaveAllToDir( RString sDir, bool bSignData ) const;
|
||||
|
||||
@@ -380,6 +404,7 @@ public:
|
||||
void LoadScreenshotDataFromNode( const XNode* pNode );
|
||||
void LoadCalorieDataFromNode( const XNode* pNode );
|
||||
|
||||
void SaveTypeToDir(RString dir) const;
|
||||
void SaveEditableDataToDir( RString sDir ) const;
|
||||
bool SaveStatsXmlToDir( RString sDir, bool bSignData ) const;
|
||||
XNode* SaveStatsXmlCreateNode() const;
|
||||
|
||||
+210
-25
@@ -27,6 +27,10 @@
|
||||
|
||||
ProfileManager* PROFILEMAN = NULL; // global and accessible from anywhere in our program
|
||||
|
||||
#define ID_DIGITS 8
|
||||
#define ID_DIGITS_STR "8"
|
||||
#define MAX_ID 99999999
|
||||
|
||||
static void DefaultLocalProfileIDInit( size_t /*PlayerNumber*/ i, RString &sNameOut, RString &defaultValueOut )
|
||||
{
|
||||
sNameOut = ssprintf( "DefaultLocalProfileIDP%d", int(i+1) );
|
||||
@@ -54,6 +58,11 @@ struct DirAndProfile
|
||||
{
|
||||
RString sDir;
|
||||
Profile profile;
|
||||
void swap(DirAndProfile& other)
|
||||
{
|
||||
sDir.swap(other.sDir);
|
||||
profile.swap(other.profile);
|
||||
}
|
||||
};
|
||||
static vector<DirAndProfile> g_vLocalProfile;
|
||||
|
||||
@@ -399,20 +408,67 @@ void ProfileManager::UnloadAllLocalProfiles()
|
||||
g_vLocalProfile.clear();
|
||||
}
|
||||
|
||||
static void add_category_to_global_list(vector<DirAndProfile>& cat)
|
||||
{
|
||||
g_vLocalProfile.insert(g_vLocalProfile.end(), cat.begin(), cat.end());
|
||||
}
|
||||
|
||||
void ProfileManager::RefreshLocalProfilesFromDisk()
|
||||
{
|
||||
UnloadAllLocalProfiles();
|
||||
|
||||
vector<RString> vsProfileID;
|
||||
GetDirListing( USER_PROFILES_DIR + "*", vsProfileID, true, true );
|
||||
FOREACH_CONST( RString, vsProfileID, p )
|
||||
vector<RString> profile_ids;
|
||||
GetDirListing(USER_PROFILES_DIR + "*", profile_ids, true, true);
|
||||
// Profiles have 3 types:
|
||||
// 1. Guest profiles:
|
||||
// Meant for use by guests, always at the top of the list.
|
||||
// 2. Normal profiles:
|
||||
// Meant for normal use, listed after guests.
|
||||
// e. Test profiles:
|
||||
// Meant for use when testing things, listed last.
|
||||
// If the user renames a profile directory manually, that should not be a
|
||||
// problem. -Kyz
|
||||
map<ProfileType, vector<DirAndProfile> > categorized_profiles;
|
||||
// The type data for a profile is in its own file so that loading isn't
|
||||
// slowed down by copying temporary profiles around to make sure the list
|
||||
// is sorted. The profiles are loaded at the end. -Kyz
|
||||
FOREACH_CONST(RString, profile_ids, id)
|
||||
{
|
||||
g_vLocalProfile.push_back( DirAndProfile() );
|
||||
DirAndProfile &dap = g_vLocalProfile.back();
|
||||
dap.sDir = *p + "/";
|
||||
dap.profile.LoadAllFromDir( dap.sDir, PREFSMAN->m_bSignProfileData );
|
||||
DirAndProfile derp;
|
||||
derp.sDir= *id + "/";
|
||||
derp.profile.LoadTypeFromDir(derp.sDir);
|
||||
map<ProfileType, vector<DirAndProfile> >::iterator category=
|
||||
categorized_profiles.find(derp.profile.m_Type);
|
||||
if(category == categorized_profiles.end())
|
||||
{
|
||||
categorized_profiles[derp.profile.m_Type].push_back(derp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool inserted= false;
|
||||
FOREACH(DirAndProfile, category->second, curr)
|
||||
{
|
||||
if(curr->profile.m_ListPriority > derp.profile.m_ListPriority)
|
||||
{
|
||||
category->second.insert(curr, derp);
|
||||
inserted= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!inserted)
|
||||
{
|
||||
category->second.push_back(derp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
add_category_to_global_list(categorized_profiles[ProfileType_Guest]);
|
||||
add_category_to_global_list(categorized_profiles[ProfileType_Normal]);
|
||||
add_category_to_global_list(categorized_profiles[ProfileType_Test]);
|
||||
FOREACH(DirAndProfile, g_vLocalProfile, curr)
|
||||
{
|
||||
curr->profile.LoadAllFromDir(curr->sDir, PREFSMAN->m_bSignProfileData);
|
||||
}
|
||||
}
|
||||
|
||||
const Profile *ProfileManager::GetLocalProfile( const RString &sProfileID ) const
|
||||
{
|
||||
@@ -433,14 +489,44 @@ bool ProfileManager::CreateLocalProfile( RString sName, RString &sProfileIDOut )
|
||||
|
||||
// Find a directory directory name that's a number greater than all
|
||||
// existing numbers. This preserves the "order by create date".
|
||||
int iMaxProfileNumber = -1;
|
||||
vector<RString> vs;
|
||||
GetLocalProfileIDs( vs );
|
||||
FOREACH_CONST( RString, vs, s )
|
||||
iMaxProfileNumber = StringToInt( *s );
|
||||
// Profile IDs are actually the directory names, so they can be any string,
|
||||
// and we have to handle the case where the user renames one.
|
||||
// Since the user can rename them, they might have any number, wrapping our
|
||||
// counter or setting it to a ridiculous value. That case must also be
|
||||
// handled. -Kyz
|
||||
int max_profile_number= -1;
|
||||
int first_free_number= 0;
|
||||
vector<RString> profile_ids;
|
||||
GetLocalProfileIDs(profile_ids);
|
||||
FOREACH_CONST(RString, profile_ids, id)
|
||||
{
|
||||
int tmp= 0;
|
||||
if((*id) >> tmp)
|
||||
{
|
||||
// The profile ids are already in order, so we don't have to handle the
|
||||
// case where 5 is encountered before 3.
|
||||
if(tmp == first_free_number)
|
||||
{
|
||||
++first_free_number;
|
||||
}
|
||||
max_profile_number= max(tmp, max_profile_number);
|
||||
}
|
||||
}
|
||||
|
||||
int iProfileNumber = iMaxProfileNumber + 1;
|
||||
RString sProfileID = ssprintf( "%08d", iProfileNumber );
|
||||
int profile_number = max_profile_number + 1;
|
||||
// Prevent profiles from going over the 8 digit limit.
|
||||
if(profile_number > MAX_ID || profile_number < 0)
|
||||
{
|
||||
profile_number= first_free_number;
|
||||
}
|
||||
ASSERT_M(profile_number >= 0 && profile_number <= MAX_ID,
|
||||
"Too many profiles, cannot assign ID to new profile.");
|
||||
RString profile_id = ssprintf( "%0" ID_DIGITS_STR "d", profile_number );
|
||||
|
||||
// make sure this id doesn't already exist
|
||||
ASSERT_M(GetLocalProfile(profile_id) == NULL,
|
||||
ssprintf("creating profile with ID \"%s\" that already exists",
|
||||
profile_id.c_str()));
|
||||
|
||||
// Create the new profile.
|
||||
Profile *pProfile = new Profile;
|
||||
@@ -448,7 +534,7 @@ bool ProfileManager::CreateLocalProfile( RString sName, RString &sProfileIDOut )
|
||||
pProfile->m_sCharacterID = CHARMAN->GetRandomCharacter()->m_sCharacterID;
|
||||
|
||||
// Save it to disk.
|
||||
RString sProfileDir = LocalProfileIDToDir( sProfileID );
|
||||
RString sProfileDir = LocalProfileIDToDir(profile_id);
|
||||
if( !pProfile->SaveAllToDir(sProfileDir, PREFSMAN->m_bSignProfileData) )
|
||||
{
|
||||
delete pProfile;
|
||||
@@ -456,12 +542,37 @@ bool ProfileManager::CreateLocalProfile( RString sName, RString &sProfileIDOut )
|
||||
return false;
|
||||
}
|
||||
|
||||
AddLocalProfileByID( pProfile, sProfileID );
|
||||
AddLocalProfileByID(pProfile, profile_id);
|
||||
|
||||
sProfileIDOut = sProfileID;
|
||||
sProfileIDOut = profile_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void InsertProfileIntoList(DirAndProfile& derp)
|
||||
{
|
||||
bool inserted= false;
|
||||
derp.profile.m_ListPriority= 0;
|
||||
FOREACH(DirAndProfile, g_vLocalProfile, curr)
|
||||
{
|
||||
if(curr->profile.m_Type > derp.profile.m_Type)
|
||||
{
|
||||
derp.profile.SaveTypeToDir(derp.sDir);
|
||||
g_vLocalProfile.insert(curr, derp);
|
||||
inserted= true;
|
||||
break;
|
||||
}
|
||||
else if(curr->profile.m_Type == derp.profile.m_Type)
|
||||
{
|
||||
++derp.profile.m_ListPriority;
|
||||
}
|
||||
}
|
||||
if(!inserted)
|
||||
{
|
||||
derp.profile.SaveTypeToDir(derp.sDir);
|
||||
g_vLocalProfile.push_back(derp);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileManager::AddLocalProfileByID( Profile *pProfile, RString sProfileID )
|
||||
{
|
||||
// make sure this id doesn't already exist
|
||||
@@ -469,11 +580,10 @@ void ProfileManager::AddLocalProfileByID( Profile *pProfile, RString sProfileID
|
||||
ssprintf("creating \"%s\" \"%s\" that already exists",
|
||||
pProfile->m_sDisplayName.c_str(), sProfileID.c_str()) );
|
||||
|
||||
// insert
|
||||
g_vLocalProfile.push_back( DirAndProfile() );
|
||||
DirAndProfile &dap = g_vLocalProfile.back();
|
||||
dap.sDir = LocalProfileIDToDir( sProfileID );
|
||||
dap.profile = *pProfile;
|
||||
DirAndProfile derp;
|
||||
derp.sDir= LocalProfileIDToDir(sProfileID);
|
||||
derp.profile= *pProfile;
|
||||
InsertProfileIntoList(derp);
|
||||
}
|
||||
|
||||
bool ProfileManager::RenameLocalProfile( RString sProfileID, RString sNewName )
|
||||
@@ -643,6 +753,58 @@ void ProfileManager::MergeLocalProfileIntoMachine(RString const& from_id, bool s
|
||||
LocalProfileIDToDir(from_id), MACHINE_PROFILE_DIR);
|
||||
}
|
||||
|
||||
void ProfileManager::ChangeProfileType(int index, ProfileType new_type)
|
||||
{
|
||||
if(index < 0 || static_cast<size_t>(index) >= g_vLocalProfile.size())
|
||||
{ return; }
|
||||
if(new_type == g_vLocalProfile[index].profile.m_Type)
|
||||
{ return; }
|
||||
DirAndProfile derp= g_vLocalProfile[index];
|
||||
g_vLocalProfile.erase(g_vLocalProfile.begin() + index);
|
||||
derp.profile.m_Type= new_type;
|
||||
InsertProfileIntoList(derp);
|
||||
}
|
||||
|
||||
void ProfileManager::MoveProfilePriority(int index, bool up)
|
||||
{
|
||||
if(index < 0 || static_cast<size_t>(index) >= g_vLocalProfile.size())
|
||||
{ return; }
|
||||
// Changing the priority is complicated a bit because the profiles might
|
||||
// all have the same priority. So this function has to assign priorities
|
||||
// to all the profiles of the same type.
|
||||
// bools are numbers, true evaluatues to 1.
|
||||
int swindex= index + ((up * -2) + 1);
|
||||
ProfileType type= g_vLocalProfile[index].profile.m_Type;
|
||||
int priority= 0;
|
||||
for(size_t i= 0; i < g_vLocalProfile.size(); ++i)
|
||||
{
|
||||
DirAndProfile* curr= &g_vLocalProfile[i];
|
||||
if(curr->profile.m_Type == type)
|
||||
{
|
||||
if(curr->profile.m_ListPriority != priority)
|
||||
{
|
||||
curr->profile.m_ListPriority= priority;
|
||||
if(i != index && i != swindex)
|
||||
{
|
||||
curr->profile.SaveTypeToDir(curr->sDir);
|
||||
}
|
||||
}
|
||||
++priority;
|
||||
}
|
||||
else if(curr->profile.m_Type > type)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Only swap if both indices are valid and the types match.
|
||||
if(swindex >= 0 && static_cast<size_t>(swindex) < g_vLocalProfile.size() &&
|
||||
g_vLocalProfile[swindex].profile.m_Type ==
|
||||
g_vLocalProfile[index].profile.m_Type)
|
||||
{
|
||||
g_vLocalProfile[index].swap(g_vLocalProfile[swindex]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// General
|
||||
//
|
||||
@@ -862,8 +1024,31 @@ public:
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
static int GetLocalProfileFromIndex( T* p, lua_State *L ) { Profile *pProfile = p->GetLocalProfileFromIndex(IArg(1)); ASSERT(pProfile != NULL); pProfile->PushSelf(L); return 1; }
|
||||
static int GetLocalProfileIDFromIndex( T* p, lua_State *L ) { lua_pushstring(L, p->GetLocalProfileIDFromIndex(IArg(1)) ); return 1; }
|
||||
static int GetLocalProfileFromIndex( T* p, lua_State *L )
|
||||
{
|
||||
int index= IArg(1);
|
||||
if(index >= p->GetNumLocalProfiles())
|
||||
{
|
||||
luaL_error(L, "Profile index %d out of range.", index);
|
||||
}
|
||||
Profile *pProfile = p->GetLocalProfileFromIndex(index);
|
||||
if(pProfile == NULL)
|
||||
{
|
||||
luaL_error(L, "No profile at index %d.", index);
|
||||
}
|
||||
pProfile->PushSelf(L);
|
||||
return 1;
|
||||
}
|
||||
static int GetLocalProfileIDFromIndex( T* p, lua_State *L )
|
||||
{
|
||||
int index= IArg(1);
|
||||
if(index >= p->GetNumLocalProfiles())
|
||||
{
|
||||
luaL_error(L, "Profile index %d out of range.", index);
|
||||
}
|
||||
lua_pushstring(L, p->GetLocalProfileIDFromIndex(index) );
|
||||
return 1;
|
||||
}
|
||||
static int GetLocalProfileIndexFromID( T* p, lua_State *L ) { lua_pushnumber(L, p->GetLocalProfileIndexFromID(SArg(1)) ); return 1; }
|
||||
static int GetNumLocalProfiles( T* p, lua_State *L ) { lua_pushnumber(L, p->GetNumLocalProfiles() ); return 1; }
|
||||
static int GetProfileDir( T* p, lua_State *L ) { lua_pushstring(L, p->GetProfileDir(Enum::Check<ProfileSlot>(L, 1)) ); return 1; }
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "Difficulty.h"
|
||||
#include "Preference.h"
|
||||
#include "Grade.h"
|
||||
#include "Profile.h"
|
||||
|
||||
class Profile;
|
||||
class Song;
|
||||
class Steps;
|
||||
class Style;
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
|
||||
void MergeLocalProfiles(RString const& from_id, RString const& to_id);
|
||||
void MergeLocalProfileIntoMachine(RString const& from_id, bool skip_totals);
|
||||
void ChangeProfileType(int index, ProfileType new_type);
|
||||
void MoveProfilePriority(int index, bool up);
|
||||
|
||||
// General data
|
||||
void IncrementToastiesCount( PlayerNumber pn );
|
||||
|
||||
@@ -34,6 +34,11 @@ enum ProfileAction
|
||||
ProfileAction_MergeToMachineSkipTotal,
|
||||
ProfileAction_MergeToP1,
|
||||
ProfileAction_MergeToP2,
|
||||
ProfileAction_ChangeToGuest,
|
||||
ProfileAction_ChangeToNormal,
|
||||
ProfileAction_ChangeToTest,
|
||||
ProfileAction_MoveUp,
|
||||
ProfileAction_MoveDown,
|
||||
NUM_ProfileAction
|
||||
};
|
||||
static const char *ProfileActionNames[] = {
|
||||
@@ -47,6 +52,11 @@ static const char *ProfileActionNames[] = {
|
||||
"MergeToMachineSkipTotal",
|
||||
"MergeToP1",
|
||||
"MergeToP2",
|
||||
"ChangeToGuest",
|
||||
"ChangeToNormal",
|
||||
"ChangeToTest",
|
||||
"MoveUp",
|
||||
"MoveDown",
|
||||
};
|
||||
XToString( ProfileAction );
|
||||
XToLocalizedString( ProfileAction );
|
||||
@@ -333,6 +343,29 @@ void ScreenOptionsManageProfiles::HandleScreenMessage( const ScreenMessage SM )
|
||||
PROFILEMAN->MergeLocalProfiles(GetLocalProfileIDWithFocus(),
|
||||
ProfileManager::m_sDefaultLocalProfileID[PLAYER_2].Get());
|
||||
break;
|
||||
case ProfileAction_ChangeToGuest:
|
||||
PROFILEMAN->ChangeProfileType(GetLocalProfileIndexWithFocus(),
|
||||
ProfileType_Guest);
|
||||
SCREENMAN->SetNewScreen(this->m_sName); // reload
|
||||
break;
|
||||
case ProfileAction_ChangeToNormal:
|
||||
PROFILEMAN->ChangeProfileType(GetLocalProfileIndexWithFocus(),
|
||||
ProfileType_Normal);
|
||||
SCREENMAN->SetNewScreen(this->m_sName); // reload
|
||||
break;
|
||||
case ProfileAction_ChangeToTest:
|
||||
PROFILEMAN->ChangeProfileType(GetLocalProfileIndexWithFocus(),
|
||||
ProfileType_Test);
|
||||
SCREENMAN->SetNewScreen(this->m_sName); // reload
|
||||
break;
|
||||
case ProfileAction_MoveUp:
|
||||
PROFILEMAN->MoveProfilePriority(GetLocalProfileIndexWithFocus(), true);
|
||||
SCREENMAN->SetNewScreen(this->m_sName); // reload
|
||||
break;
|
||||
case ProfileAction_MoveDown:
|
||||
PROFILEMAN->MoveProfilePriority(GetLocalProfileIndexWithFocus(), false);
|
||||
SCREENMAN->SetNewScreen(this->m_sName); // reload
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -411,6 +444,11 @@ void ScreenOptionsManageProfiles::ProcessMenuStart( const InputEventPlus & )
|
||||
ADD_ACTION( ProfileAction_MergeToMachineSkipTotal );
|
||||
ADD_ACTION( ProfileAction_MergeToP1 );
|
||||
ADD_ACTION( ProfileAction_MergeToP2 );
|
||||
ADD_ACTION( ProfileAction_ChangeToGuest );
|
||||
ADD_ACTION( ProfileAction_ChangeToNormal );
|
||||
ADD_ACTION( ProfileAction_ChangeToTest );
|
||||
ADD_ACTION( ProfileAction_MoveUp );
|
||||
ADD_ACTION( ProfileAction_MoveDown );
|
||||
}
|
||||
|
||||
int iWidth, iX, iY;
|
||||
|
||||
Reference in New Issue
Block a user