Instead of using the MODS_GROUP_ASSIGN über-macro, add members for assigning, both to an individual field and for the entire group. Also add FromString and generic zero argument Call members. For the templated Assign, Call, and Toggle[1] members, use the macros to make getting pointers to data/function members easier.

1. Toggle just toggles a boolean. This would seem to have strange effects that are not consistent with the others. Calling Toggle with ModsLevel_Song and then following that by calling it with ModsLevel_Stage will cause Stage and Song groups to be opposite w.r.t. that bool. This is only used in two places. Perhaps Assign() with the value of the smallest ModsLevel used--that is the level passed to Toggle currently--toggled should be used instead.
This commit is contained in:
Steve Checkoway
2006-08-05 04:46:11 +00:00
parent f2b9618423
commit 7dd10c92f4
+50 -9
View File
@@ -3,6 +3,8 @@
#ifndef ModLevel_H #ifndef ModLevel_H
#define ModLevel_H #define ModLevel_H
#include "EnumHelper.h"
enum ModsLevel enum ModsLevel
{ {
ModsLevel_Preferred, // user-chosen player options. Does not include any forced mods. ModsLevel_Preferred, // user-chosen player options. Does not include any forced mods.
@@ -11,25 +13,22 @@ enum ModsLevel
NUM_ModsLevel, NUM_ModsLevel,
}; };
#define MODS_GROUP_ASSIGN( modsGroup, modsLevel, assignment ) \ #define MODS_GROUP_ASSIGN( group, level, member, val ) \
{ \ (group).Assign( (level), &(group).GroupType::member, (val) )
for( int i=(ModsLevel)(modsLevel); i<NUM_ModsLevel; i++ ) \ #define MODS_GROUP_CALL( group, level, fun ) (group).Call( (level), &(group).GroupType::fun )
(modsGroup).m_[i] assignment; \ #define MODS_GROUP_TOGGLE( group, level, member ) (group).Call( (level), &(group).GroupType::member )
if( modsLevel != ModsLevel_Song ) \
(modsGroup).m_current assignment; \
}
template<class T> template<class T>
struct ModsGroup struct ModsGroup
{ {
typedef T GroupType;
T m_[NUM_ModsLevel]; T m_[NUM_ModsLevel];
RageTimer m_timer; RageTimer m_timer;
T m_current; // approaches ModsLevel_Song T m_current; // approaches ModsLevel_Song
void Init() void Init()
{ {
MODS_GROUP_ASSIGN( *this, (ModsLevel)0, .Init() ); Call( ModsLevel_Preferred, &T::Init );
m_current.Init();
} }
void Update( float fDelta ) void Update( float fDelta )
@@ -40,6 +39,48 @@ struct ModsGroup
m_current.Approach( m_[ModsLevel_Song], fDelta ); m_current.Approach( m_[ModsLevel_Song], fDelta );
} }
template<typename U>
void Assign( ModsLevel level, U T::*member, const U &val )
{
if( level != ModsLevel_Song )
m_current.*member = val;
for( ; level < NUM_ModsLevel; enum_add(level, 1) )
m_[level].*member = val;
}
void Assign( ModsLevel level, const T &val )
{
if( level != ModsLevel_Song )
m_current = val;
for( ; level < NUM_ModsLevel; enum_add(level, 1) )
m_[level] = val;
}
void Call( ModsLevel level, void (T::*fun)() )
{
if( level != ModsLevel_Song )
(m_current.*fun)();
for( ; level < NUM_ModsLevel; enum_add(level, 1) )
(m_[level].*fun)();
}
void FromString( ModsLevel level, const RString &str )
{
if( level != ModsLevel_Song )
m_current.FromString( str );
for( ; level < NUM_ModsLevel; enum_add(level, 1) )
m_[level].FromString( str );
}
// This seems like a very strange thing to do.
void Toggle( ModsLevel level, bool T::*member )
{
if( level != ModsLevel_Song )
m_current.*member ^= 1;
for( ; level < NUM_ModsLevel; enum_add(level, 1) )
m_[level].*member ^= 1;
}
const T &GetPreferred() const { return m_[ModsLevel_Preferred]; } const T &GetPreferred() const { return m_[ModsLevel_Preferred]; }
const T &GetStage() const { return m_[ModsLevel_Stage]; } const T &GetStage() const { return m_[ModsLevel_Stage]; }
const T &GetSong() const { return m_[ModsLevel_Song]; } const T &GetSong() const { return m_[ModsLevel_Song]; }