[default->loading window] Catching up.
This commit is contained in:
+7
-6
@@ -722,12 +722,13 @@ void Actor::UpdateInternal( float fDeltaTime )
|
||||
// todo: account for SSC_FUTURES -aj
|
||||
switch( m_Effect )
|
||||
{
|
||||
case spin:
|
||||
m_current.rotation += m_fEffectDelta*m_vEffectMagnitude;
|
||||
wrap( m_current.rotation.x, 360 );
|
||||
wrap( m_current.rotation.y, 360 );
|
||||
wrap( m_current.rotation.z, 360 );
|
||||
break;
|
||||
case spin:
|
||||
m_current.rotation += m_fEffectDelta*m_vEffectMagnitude;
|
||||
wrap( m_current.rotation.x, 360 );
|
||||
wrap( m_current.rotation.y, 360 );
|
||||
wrap( m_current.rotation.z, 360 );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
UpdateTweening( fDeltaTime );
|
||||
|
||||
+27
-10
@@ -266,14 +266,23 @@ void AdjustSync::AutosyncTempo()
|
||||
|
||||
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fIntercept;
|
||||
const float fScaleBPM = 1.0f/(1.0f - fSlope);
|
||||
FOREACH( BPMSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_BPMSegments, i )
|
||||
i->SetBPM( i->GetBPM() * fScaleBPM );
|
||||
TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming;
|
||||
vector<TimingSegment *> &bpms = timing.allTimingSegments[SEGMENT_BPM];
|
||||
for (unsigned i = 0; i < bpms.size(); i++)
|
||||
{
|
||||
BPMSegment *b = static_cast<BPMSegment *>(bpms[i]);
|
||||
b->SetBPM(b->GetBPM() * fScaleBPM);
|
||||
}
|
||||
|
||||
/* We assume that the stops were measured as a number of beats.
|
||||
* Therefore, if we change the bpms, we need to make a similar
|
||||
* change to the stops. */
|
||||
FOREACH( StopSegment, GAMESTATE->m_pCurSong->m_SongTiming.m_StopSegments, i )
|
||||
i->SetPause(i->GetPause() * (1.0f - fSlope));
|
||||
vector<TimingSegment *> &stops = timing.allTimingSegments[SEGMENT_STOP_DELAY];
|
||||
for (unsigned i = 0; i < stops.size(); i++)
|
||||
{
|
||||
StopSegment *s = static_cast<StopSegment *>(stops[i]);
|
||||
s->SetPause(s->GetPause() * (1.0f - fSlope));
|
||||
}
|
||||
|
||||
SCREENMAN->SystemMessage( AUTOSYNC_CORRECTION_APPLIED.GetValue() );
|
||||
}
|
||||
@@ -343,10 +352,14 @@ void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo )
|
||||
}
|
||||
}
|
||||
|
||||
for( unsigned i=0; i< testing.m_BPMSegments.size(); i++ )
|
||||
vector<TimingSegment *> &bpmTest = testing.allTimingSegments[SEGMENT_BPM];
|
||||
vector<TimingSegment *> &bpmOrig = original.allTimingSegments[SEGMENT_BPM];
|
||||
for( unsigned i=0; i< bpmTest.size(); i++ )
|
||||
{
|
||||
float fOld = Quantize( original.m_BPMSegments[i].GetBPM(), 0.001f );
|
||||
float fNew = Quantize( testing.m_BPMSegments[i].GetBPM(), 0.001f );
|
||||
BPMSegment *bT = static_cast<BPMSegment *>(bpmTest[i]);
|
||||
BPMSegment *bO = static_cast<BPMSegment *>(bpmOrig[i]);
|
||||
float fOld = Quantize( bO->GetBPM(), 0.001f );
|
||||
float fNew = Quantize( bT->GetBPM(), 0.001f );
|
||||
float fDelta = fNew - fOld;
|
||||
|
||||
if( fabsf(fDelta) > 0.0001f )
|
||||
@@ -364,10 +377,14 @@ void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo )
|
||||
}
|
||||
}
|
||||
|
||||
for( unsigned i=0; i< testing.m_StopSegments.size(); i++ )
|
||||
vector<TimingSegment *> &stopTest = testing.allTimingSegments[SEGMENT_STOP_DELAY];
|
||||
vector<TimingSegment *> &stopOrig = original.allTimingSegments[SEGMENT_STOP_DELAY];
|
||||
for( unsigned i=0; i< stopTest.size(); i++ )
|
||||
{
|
||||
float fOld = Quantize( original.m_StopSegments[i].GetPause(), 0.001f );
|
||||
float fNew = Quantize( testing.m_StopSegments[i].GetPause(), 0.001f );
|
||||
StopSegment *sT = static_cast<StopSegment *>(stopTest[i]);
|
||||
StopSegment *sO = static_cast<StopSegment *>(stopOrig[i]);
|
||||
float fOld = Quantize( sO->GetPause(), 0.001f );
|
||||
float fNew = Quantize( sT->GetPause(), 0.001f );
|
||||
float fDelta = fNew - fOld;
|
||||
|
||||
if( fabsf(fDelta) > 0.0001f )
|
||||
|
||||
@@ -189,11 +189,11 @@ void BGAnimationLayer::LoadFromAniLayerFile( const RString& sPath )
|
||||
|
||||
switch( effect )
|
||||
{
|
||||
case EFFECT_STRETCH_SCROLL_LEFT: m_fTexCoordVelocityX = +0.5f; m_fTexCoordVelocityY = 0; break;
|
||||
case EFFECT_STRETCH_SCROLL_RIGHT: m_fTexCoordVelocityX = -0.5f; m_fTexCoordVelocityY = 0; break;
|
||||
case EFFECT_STRETCH_SCROLL_UP: m_fTexCoordVelocityX = 0; m_fTexCoordVelocityY = +0.5f; break;
|
||||
case EFFECT_STRETCH_SCROLL_DOWN: m_fTexCoordVelocityX = 0; m_fTexCoordVelocityY = -0.5f; break;
|
||||
break;
|
||||
case EFFECT_STRETCH_SCROLL_LEFT: m_fTexCoordVelocityX = +0.5f; m_fTexCoordVelocityY = 0; break;
|
||||
case EFFECT_STRETCH_SCROLL_RIGHT: m_fTexCoordVelocityX = -0.5f; m_fTexCoordVelocityY = 0; break;
|
||||
case EFFECT_STRETCH_SCROLL_UP: m_fTexCoordVelocityX = 0; m_fTexCoordVelocityY = +0.5f; break;
|
||||
case EFFECT_STRETCH_SCROLL_DOWN: m_fTexCoordVelocityX = 0; m_fTexCoordVelocityY = -0.5f; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+20
-14
@@ -421,35 +421,41 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
|
||||
const TimingData &timing = m_pSong->m_SongTiming;
|
||||
|
||||
// change BG every time signature change or 4 measures
|
||||
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter )
|
||||
const vector<TimingSegment *> &tSigs = timing.allTimingSegments[SEGMENT_TIME_SIG];
|
||||
|
||||
for (unsigned i = 0; i < tSigs.size(); i++)
|
||||
{
|
||||
vector<TimeSignatureSegment>::const_iterator next = iter;
|
||||
next++;
|
||||
int iSegmentEndRow = (next == timing.m_vTimeSignatureSegments.end()) ? iEndRow : next->GetRow();
|
||||
TimeSignatureSegment *ts = static_cast<TimeSignatureSegment *>(tSigs[i]);
|
||||
int iSegmentEndRow = (i + 1 == tSigs.size()) ? iEndRow : tSigs[i+1]->GetRow();
|
||||
|
||||
for( int i=max(iter->GetRow(),iStartRow); i<min(iEndRow,iSegmentEndRow); i+=4*iter->GetNoteRowsPerMeasure() )
|
||||
|
||||
for(int j=max(ts->GetRow(),iStartRow);
|
||||
j<min(iEndRow,iSegmentEndRow);
|
||||
j+=4*ts->GetNoteRowsPerMeasure())
|
||||
{
|
||||
// Don't fade. It causes frame rate dip, especially on slower machines.
|
||||
BackgroundDef bd = m_Layer[0].CreateRandomBGA( m_pSong, change.m_def.m_sEffect, m_RandomBGAnimations, this );
|
||||
BackgroundDef bd = m_Layer[0].CreateRandomBGA(m_pSong,
|
||||
change.m_def.m_sEffect,
|
||||
m_RandomBGAnimations, this);
|
||||
if( !bd.IsEmpty() )
|
||||
{
|
||||
BackgroundChange c = change;
|
||||
c.m_def = bd;
|
||||
c.m_fStartBeat = NoteRowToBeat(i);
|
||||
c.m_fStartBeat = NoteRowToBeat(j);
|
||||
m_Layer[0].m_aBGChanges.push_back( c );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// change BG every BPM change that is at the beginning of a measure
|
||||
for( unsigned i=0; i<timing.m_BPMSegments.size(); i++ )
|
||||
const vector<TimingSegment *> &bpms = timing.allTimingSegments[SEGMENT_BPM];
|
||||
for( unsigned i=0; i<bpms.size(); i++ )
|
||||
{
|
||||
const BPMSegment& bpmseg = timing.m_BPMSegments[i];
|
||||
|
||||
bool bAtBeginningOfMeasure = false;
|
||||
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter )
|
||||
for (unsigned j=0; j<tSigs.size(); j++)
|
||||
{
|
||||
if( (bpmseg.GetRow() - iter->GetRow()) % iter->GetNoteRowsPerMeasure() == 0 )
|
||||
TimeSignatureSegment *ts = static_cast<TimeSignatureSegment *>(tSigs[j]);
|
||||
if ((bpms[i]->GetRow() - ts->GetRow()) % ts->GetNoteRowsPerMeasure() == 0)
|
||||
{
|
||||
bAtBeginningOfMeasure = true;
|
||||
break;
|
||||
@@ -460,7 +466,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
|
||||
continue; // skip
|
||||
|
||||
// start so that we don't create a BGChange right on top of fEndBeat
|
||||
bool bInRange = bpmseg.GetRow() >= iStartRow && bpmseg.GetRow() < iEndRow;
|
||||
bool bInRange = bpms[i]->GetRow() >= iStartRow && bpms[i]->GetRow() < iEndRow;
|
||||
if( !bInRange )
|
||||
continue; // skip
|
||||
|
||||
@@ -470,7 +476,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
|
||||
BackgroundChange c = change;
|
||||
c.m_def.m_sFile1 = bd.m_sFile1;
|
||||
c.m_def.m_sFile2 = bd.m_sFile2;
|
||||
c.m_fStartBeat = bpmseg.GetBeat();
|
||||
c.m_fStartBeat = bpms[i]->GetBeat();
|
||||
m_Layer[0].m_aBGChanges.push_back( c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,25 @@ RString BackgroundChange::GetTextDescription() const
|
||||
return s;
|
||||
}
|
||||
|
||||
RString BackgroundChange::ToString() const
|
||||
{
|
||||
/* TODO: Technically we need to double-escape the filename
|
||||
* (because it might contain '=') and then unescape the value
|
||||
* returned by the MsdFile. */
|
||||
return ssprintf("%.3f=%s=%.3f=%d=%d=%d=%s=%s=%s=%s=%s",
|
||||
this->m_fStartBeat,
|
||||
SmEscape(this->m_def.m_sFile1).c_str(),
|
||||
this->m_fRate,
|
||||
this->m_sTransition == SBT_CrossFade, // backward compat
|
||||
this->m_def.m_sEffect == SBE_StretchRewind, // backward compat
|
||||
this->m_def.m_sEffect != SBE_StretchNoLoop, // backward compat
|
||||
this->m_def.m_sEffect.c_str(),
|
||||
this->m_def.m_sFile2.c_str(),
|
||||
this->m_sTransition.c_str(),
|
||||
SmEscape(RageColor::NormalizeColorString(this->m_def.m_sColor1)).c_str(),
|
||||
SmEscape(RageColor::NormalizeColorString(this->m_def.m_sColor2)).c_str());
|
||||
}
|
||||
|
||||
|
||||
const RString BACKGROUND_EFFECTS_DIR = "BackgroundEffects/";
|
||||
const RString BACKGROUND_TRANSITIONS_DIR = "BackgroundTransitions/";
|
||||
|
||||
@@ -64,6 +64,11 @@ struct BackgroundChange
|
||||
RString m_sTransition;
|
||||
|
||||
RString GetTextDescription() const;
|
||||
|
||||
/**
|
||||
* @brief Get the string representation of the change.
|
||||
* @return the string representation. */
|
||||
RString ToString() const;
|
||||
};
|
||||
/** @brief Shared background-related routines. */
|
||||
namespace BackgroundUtil
|
||||
|
||||
+6
-4
@@ -429,12 +429,14 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail )
|
||||
{
|
||||
trail.Init();
|
||||
|
||||
// XXX: Why are beginner and challenge excluded here? -Wolfman2000
|
||||
switch( cd )
|
||||
{
|
||||
case Difficulty_Beginner:
|
||||
return false;
|
||||
case Difficulty_Challenge:
|
||||
return false;
|
||||
case Difficulty_Beginner:
|
||||
return false;
|
||||
case Difficulty_Challenge:
|
||||
return false;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Construct a new Trail, add it to the cache, then return it.
|
||||
|
||||
@@ -131,10 +131,11 @@ DancingCharacters::DancingCharacters(): m_bDrawDangerLight(false),
|
||||
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pCharacter[p]->SetRotationY( MODEL_ROTATIONY_TWO_PLAYERS[p] );
|
||||
break;
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pCharacter[p]->SetRotationY( MODEL_ROTATIONY_TWO_PLAYERS[p] );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_pCharacter[p]->LoadMilkshapeAscii( pChar->GetModelPath() );
|
||||
|
||||
+4
-4
@@ -275,12 +275,12 @@ bool EditMenu::RowIsSelectable( EditMenuRow row )
|
||||
{
|
||||
switch( row )
|
||||
{
|
||||
case ROW_SOURCE_STEPS_TYPE:
|
||||
case ROW_SOURCE_STEPS:
|
||||
return false;
|
||||
case ROW_SOURCE_STEPS_TYPE:
|
||||
case ROW_SOURCE_STEPS:
|
||||
return false;
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -465,22 +465,21 @@ static bool AreStyleAndPlayModeCompatible( const Style *style, PlayMode pm )
|
||||
|
||||
switch( pm )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
// Can't play rave if there isn't enough room for two players.
|
||||
// This is correct for dance (ie, no rave for solo and doubles),
|
||||
// and should be okay for pump.. not sure about other game types.
|
||||
// Techno Motion scales down versus arrows, though, so allow this.
|
||||
if( style->m_iColsPerPlayer >= 6 && RString(GAMESTATE->m_pCurGame->m_szName) != "techno" )
|
||||
return false;
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
// Can't play rave if there isn't enough room for two players.
|
||||
// This is correct for dance (ie, no rave for solo and doubles),
|
||||
// and should be okay for pump.. not sure about other game types.
|
||||
// Techno Motion scales down versus arrows, though, so allow this.
|
||||
if( style->m_iColsPerPlayer >= 6 && RString(GAMESTATE->m_pCurGame->m_szName) != "techno" )
|
||||
return false;
|
||||
|
||||
// Don't allow battle modes if the style takes both sides.
|
||||
if( style->m_StyleType==StyleType_OnePlayerTwoSides ||
|
||||
style->m_StyleType==StyleType_TwoPlayersSharedSides )
|
||||
return false;
|
||||
// Don't allow battle modes if the style takes both sides.
|
||||
if( style->m_StyleType==StyleType_OnePlayerTwoSides ||
|
||||
style->m_StyleType==StyleType_TwoPlayersSharedSides )
|
||||
return false;
|
||||
default: return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameCommand::IsPlayable( RString *why ) const
|
||||
@@ -500,9 +499,10 @@ bool GameCommand::IsPlayable( RString *why ) const
|
||||
|
||||
switch( GAMESTATE->GetCoinMode() )
|
||||
{
|
||||
case CoinMode_Home:
|
||||
case CoinMode_Free:
|
||||
iCredits = NUM_PLAYERS; // not iNumCreditsPaid
|
||||
case CoinMode_Home:
|
||||
case CoinMode_Free:
|
||||
iCredits = NUM_PLAYERS; // not iNumCreditsPaid
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* With PREFSMAN->m_bDelayedCreditsReconcile disabled, enough credits must
|
||||
|
||||
@@ -60,8 +60,8 @@ struct MusicPlaying
|
||||
RageSound *m_Music;
|
||||
MusicPlaying( RageSound *Music )
|
||||
{
|
||||
m_Timing.AddBPMSegment( BPMSegment(0,120) );
|
||||
m_NewTiming.AddBPMSegment( BPMSegment(0,120) );
|
||||
m_Timing.AddSegment( SEGMENT_BPM, new BPMSegment(0,120) );
|
||||
m_NewTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0,120) );
|
||||
m_bHasTiming = false;
|
||||
m_bTimingDelayed = false;
|
||||
m_bApplyMusicRate = false;
|
||||
|
||||
+19
-16
@@ -747,7 +747,9 @@ void GameState::CancelStage()
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
m_iPlayerStageTokens[p] = PREFSMAN->m_iSongsPerPlay;
|
||||
m_iPlayerStageTokens[p] = PREFSMAN->m_iSongsPerPlay;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,12 +1171,12 @@ bool GameState::IsPlayerEnabled( PlayerNumber pn ) const
|
||||
// In rave, all players are present. Non-human players are CPU controlled.
|
||||
switch( m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
return true;
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
return true;
|
||||
default:
|
||||
return IsHumanPlayer(pn);
|
||||
}
|
||||
|
||||
return IsHumanPlayer( pn );
|
||||
}
|
||||
|
||||
bool GameState::IsMultiPlayerEnabled( MultiPlayer mp ) const
|
||||
@@ -1346,16 +1348,17 @@ StageResult GameState::GetStageResult( PlayerNumber pn ) const
|
||||
{
|
||||
switch( m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
if( fabsf(m_fTugLifePercentP1 - 0.5f) < 0.0001f )
|
||||
return RESULT_DRAW;
|
||||
switch( pn )
|
||||
{
|
||||
case PLAYER_1: return (m_fTugLifePercentP1>=0.5f)?RESULT_WIN:RESULT_LOSE;
|
||||
case PLAYER_2: return (m_fTugLifePercentP1<0.5f)?RESULT_WIN:RESULT_LOSE;
|
||||
default: ASSERT(0); return RESULT_LOSE;
|
||||
}
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
if( fabsf(m_fTugLifePercentP1 - 0.5f) < 0.0001f )
|
||||
return RESULT_DRAW;
|
||||
switch( pn )
|
||||
{
|
||||
case PLAYER_1: return (m_fTugLifePercentP1>=0.5f)?RESULT_WIN:RESULT_LOSE;
|
||||
case PLAYER_2: return (m_fTugLifePercentP1<0.5f)?RESULT_WIN:RESULT_LOSE;
|
||||
default: FAIL_M("Invalid player for battle! Aborting..."); return RESULT_LOSE;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
StageResult win = RESULT_WIN;
|
||||
|
||||
+11
-8
@@ -72,16 +72,19 @@ void Inventory::Load( PlayerState* pPlayerState )
|
||||
// don't load battle sounds if they're not going to be used
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
m_soundAcquireItem.Load( THEME->GetPathS("Inventory","aquire item") );
|
||||
for( unsigned i=0; i<g_Items.size(); i++ )
|
||||
case PLAY_MODE_BATTLE:
|
||||
{
|
||||
RageSound* pSound = new RageSound;
|
||||
pSound->Load( THEME->GetPathS("Inventory",ssprintf("use item %u",i+1)) );
|
||||
m_vpSoundUseItem.push_back( pSound );
|
||||
m_soundAcquireItem.Load( THEME->GetPathS("Inventory","aquire item") );
|
||||
for( unsigned i=0; i<g_Items.size(); i++ )
|
||||
{
|
||||
RageSound* pSound = new RageSound;
|
||||
pSound->Load( THEME->GetPathS("Inventory",ssprintf("use item %u",i+1)) );
|
||||
m_vpSoundUseItem.push_back( pSound );
|
||||
}
|
||||
m_soundItemEnding.Load( THEME->GetPathS("Inventory","item ending") );
|
||||
break;
|
||||
}
|
||||
m_soundItemEnding.Load( THEME->GetPathS("Inventory","item ending") );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,24 @@ namespace JsonUtil
|
||||
for(unsigned i=0; i<v.size(); i++)
|
||||
fn(*v[i], root[i]);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void SerializeVectorPointers(const vector<T*> &v, void fn(const T &, Json::Value &), Json::Value &root)
|
||||
{
|
||||
root = Json::Value(Json::arrayValue);
|
||||
root.resize(v.size());
|
||||
for(unsigned i=0; i<v.size(); i++)
|
||||
fn(*v[i], root[i]);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void SerializeVectorPointers(const vector<const T*> &v, void fn(const T *, Json::Value &), Json::Value &root)
|
||||
{
|
||||
root = Json::Value(Json::arrayValue);
|
||||
root.resize(v.size());
|
||||
for(unsigned i=0; i<v.size(); i++)
|
||||
fn(*v[i], root[i]);
|
||||
}
|
||||
|
||||
template<typename V, typename T>
|
||||
static void SerializeArray(const V &v, void fn(const T &, Json::Value &), Json::Value &root)
|
||||
@@ -149,6 +167,19 @@ namespace JsonUtil
|
||||
fn(*v[i], root[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void DeserializeVectorPointers(vector<T*> &v, void fn(T *, const Json::Value &), const Json::Value &root)
|
||||
{
|
||||
for(unsigned i=0; i<v.size(); i++)
|
||||
SAFE_DELETE(v[i]);
|
||||
v.resize(root.size());
|
||||
for(unsigned i=0; i<v.size(); i++)
|
||||
{
|
||||
v[i] = new T;
|
||||
fn(*v[i], root[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void DeserializeArrayValues(vector<T> &v, const Json::Value &root)
|
||||
|
||||
@@ -212,12 +212,13 @@ void LifeMeterBar::ChangeLife( float fDeltaLife )
|
||||
|
||||
switch( GAMESTATE->m_SongOptions.GetSong().m_DrainType )
|
||||
{
|
||||
case SongOptions::DRAIN_NORMAL:
|
||||
case SongOptions::DRAIN_NO_RECOVER:
|
||||
if( fDeltaLife > 0 )
|
||||
fDeltaLife *= m_fLifeDifficulty;
|
||||
else
|
||||
fDeltaLife /= m_fLifeDifficulty;
|
||||
case SongOptions::DRAIN_NORMAL:
|
||||
case SongOptions::DRAIN_NO_RECOVER:
|
||||
if( fDeltaLife > 0 )
|
||||
fDeltaLife *= m_fLifeDifficulty;
|
||||
else
|
||||
fDeltaLife /= m_fLifeDifficulty;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+32
-30
@@ -449,22 +449,23 @@ void MemoryCardManager::CheckStateChanges()
|
||||
{
|
||||
switch( new_device.m_State )
|
||||
{
|
||||
case UsbStorageDevice::STATE_NONE:
|
||||
state = MemoryCardState_NoCard;
|
||||
break;
|
||||
case UsbStorageDevice::STATE_NONE:
|
||||
state = MemoryCardState_NoCard;
|
||||
break;
|
||||
|
||||
case UsbStorageDevice::STATE_CHECKING:
|
||||
state = MemoryCardState_Checking;
|
||||
break;
|
||||
case UsbStorageDevice::STATE_CHECKING:
|
||||
state = MemoryCardState_Checking;
|
||||
break;
|
||||
|
||||
case UsbStorageDevice::STATE_ERROR:
|
||||
state = MemoryCardState_Error;
|
||||
sError = new_device.m_sError;
|
||||
break;
|
||||
case UsbStorageDevice::STATE_ERROR:
|
||||
state = MemoryCardState_Error;
|
||||
sError = new_device.m_sError;
|
||||
break;
|
||||
|
||||
case UsbStorageDevice::STATE_READY:
|
||||
state = MemoryCardState_Ready;
|
||||
break;
|
||||
case UsbStorageDevice::STATE_READY:
|
||||
state = MemoryCardState_Ready;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,23 +477,24 @@ void MemoryCardManager::CheckStateChanges()
|
||||
params.m_bIsCriticalSound = true;
|
||||
switch( state )
|
||||
{
|
||||
case MemoryCardState_NoCard:
|
||||
case MemoryCardState_Removed:
|
||||
if( LastState == MemoryCardState_Ready )
|
||||
{
|
||||
m_soundDisconnect.Play( ¶ms );
|
||||
MESSAGEMAN->Broadcast( (MessageID)(Message_CardRemovedP1+p) );
|
||||
}
|
||||
break;
|
||||
case MemoryCardState_Ready:
|
||||
m_soundReady.Play( ¶ms );
|
||||
break;
|
||||
case MemoryCardState_TooLate:
|
||||
m_soundTooLate.Play( ¶ms );
|
||||
break;
|
||||
case MemoryCardState_Error:
|
||||
m_soundError.Play( ¶ms );
|
||||
break;
|
||||
case MemoryCardState_NoCard:
|
||||
case MemoryCardState_Removed:
|
||||
if( LastState == MemoryCardState_Ready )
|
||||
{
|
||||
m_soundDisconnect.Play( ¶ms );
|
||||
MESSAGEMAN->Broadcast( (MessageID)(Message_CardRemovedP1+p) );
|
||||
}
|
||||
break;
|
||||
case MemoryCardState_Ready:
|
||||
m_soundReady.Play( ¶ms );
|
||||
break;
|
||||
case MemoryCardState_TooLate:
|
||||
m_soundTooLate.Play( ¶ms );
|
||||
break;
|
||||
case MemoryCardState_Error:
|
||||
m_soundError.Play( ¶ms );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_State[p] = state;
|
||||
|
||||
+173
-171
@@ -42,23 +42,23 @@ static SortOrder ForceAppropriateSort( PlayMode pm, SortOrder so )
|
||||
{
|
||||
switch( pm )
|
||||
{
|
||||
// in course modes, force a particular sort
|
||||
case PLAY_MODE_ONI: return SORT_ONI_COURSES;
|
||||
case PLAY_MODE_NONSTOP: return SORT_NONSTOP_COURSES;
|
||||
case PLAY_MODE_ENDLESS: return SORT_ENDLESS_COURSES;
|
||||
// in course modes, force a particular sort
|
||||
case PLAY_MODE_ONI: return SORT_ONI_COURSES;
|
||||
case PLAY_MODE_NONSTOP: return SORT_NONSTOP_COURSES;
|
||||
case PLAY_MODE_ENDLESS: return SORT_ENDLESS_COURSES;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// If we're not in a course mode, don't start in a course sort.
|
||||
switch( so )
|
||||
{
|
||||
case SORT_ONI_COURSES:
|
||||
case SORT_NONSTOP_COURSES:
|
||||
case SORT_ENDLESS_COURSES:
|
||||
so = SortOrder_Invalid;
|
||||
break;
|
||||
case SORT_ONI_COURSES:
|
||||
case SORT_NONSTOP_COURSES:
|
||||
case SORT_ENDLESS_COURSES:
|
||||
so = SortOrder_Invalid;
|
||||
default:
|
||||
return so;
|
||||
}
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
MusicWheelItem *MusicWheel::MakeItem()
|
||||
@@ -490,7 +490,7 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
{
|
||||
switch( so )
|
||||
{
|
||||
case SORT_MODE_MENU:
|
||||
case SORT_MODE_MENU:
|
||||
{
|
||||
arrayWheelItemDatas.clear(); // clear out the previous wheel items
|
||||
vector<RString> vsNames;
|
||||
@@ -510,22 +510,22 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SORT_PREFERRED:
|
||||
case SORT_ROULETTE:
|
||||
case SORT_GROUP:
|
||||
case SORT_TITLE:
|
||||
case SORT_BPM:
|
||||
case SORT_POPULARITY:
|
||||
case SORT_TOP_GRADES:
|
||||
case SORT_ARTIST:
|
||||
case SORT_GENRE:
|
||||
case SORT_BEGINNER_METER:
|
||||
case SORT_EASY_METER:
|
||||
case SORT_MEDIUM_METER:
|
||||
case SORT_HARD_METER:
|
||||
case SORT_CHALLENGE_METER:
|
||||
case SORT_LENGTH:
|
||||
case SORT_RECENT:
|
||||
case SORT_PREFERRED:
|
||||
case SORT_ROULETTE:
|
||||
case SORT_GROUP:
|
||||
case SORT_TITLE:
|
||||
case SORT_BPM:
|
||||
case SORT_POPULARITY:
|
||||
case SORT_TOP_GRADES:
|
||||
case SORT_ARTIST:
|
||||
case SORT_GENRE:
|
||||
case SORT_BEGINNER_METER:
|
||||
case SORT_EASY_METER:
|
||||
case SORT_MEDIUM_METER:
|
||||
case SORT_HARD_METER:
|
||||
case SORT_CHALLENGE_METER:
|
||||
case SORT_LENGTH:
|
||||
case SORT_RECENT:
|
||||
{
|
||||
// Make an array of Song*, then sort them
|
||||
vector<Song*> arraySongs;
|
||||
@@ -536,72 +536,72 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
// sort the songs
|
||||
switch( so )
|
||||
{
|
||||
case SORT_PREFERRED:
|
||||
// obey order specified by the preferred sort list
|
||||
break;
|
||||
case SORT_ROULETTE:
|
||||
{
|
||||
StepsType st;
|
||||
Difficulty dc;
|
||||
SongUtil::GetStepsTypeAndDifficultyFromSortOrder( SORT_EASY_METER, st, dc );
|
||||
SongUtil::SortSongPointerArrayByStepsTypeAndMeter( arraySongs, st, dc );
|
||||
if( (bool)PREFSMAN->m_bPreferredSortUsesGroups )
|
||||
stable_sort( arraySongs.begin(), arraySongs.end(), SongUtil::CompareSongPointersByGroup );
|
||||
bUseSections = false;
|
||||
break;
|
||||
}
|
||||
case SORT_GROUP:
|
||||
SongUtil::SortSongPointerArrayByGroupAndTitle( arraySongs );
|
||||
if(USE_SECTIONS_WITH_PREFERRED_GROUP)
|
||||
bUseSections = true;
|
||||
else
|
||||
bUseSections = GAMESTATE->m_sPreferredSongGroup == GROUP_ALL;
|
||||
break;
|
||||
case SORT_TITLE:
|
||||
SongUtil::SortSongPointerArrayByTitle( arraySongs );
|
||||
break;
|
||||
case SORT_BPM:
|
||||
SongUtil::SortSongPointerArrayByBPM( arraySongs );
|
||||
break;
|
||||
case SORT_POPULARITY:
|
||||
if( (int) arraySongs.size() > MOST_PLAYED_SONGS_TO_SHOW )
|
||||
arraySongs.erase( arraySongs.begin()+MOST_PLAYED_SONGS_TO_SHOW, arraySongs.end() );
|
||||
bUseSections = false;
|
||||
break;
|
||||
case SORT_TOP_GRADES:
|
||||
SongUtil::SortSongPointerArrayByGrades( arraySongs, true );
|
||||
break;
|
||||
case SORT_ARTIST:
|
||||
SongUtil::SortSongPointerArrayByArtist( arraySongs );
|
||||
break;
|
||||
case SORT_GENRE:
|
||||
SongUtil::SortSongPointerArrayByGenre( arraySongs );
|
||||
break;
|
||||
case SORT_LENGTH:
|
||||
SongUtil::SortSongPointerArrayByLength( arraySongs );
|
||||
break;
|
||||
case SORT_RECENT:
|
||||
SongUtil::SortByMostRecentlyPlayedForMachine( arraySongs );
|
||||
if( (int) arraySongs.size() > RECENT_SONGS_TO_SHOW )
|
||||
arraySongs.erase( arraySongs.begin()+RECENT_SONGS_TO_SHOW, arraySongs.end() );
|
||||
bUseSections = false;
|
||||
break;
|
||||
case SORT_BEGINNER_METER:
|
||||
case SORT_EASY_METER:
|
||||
case SORT_MEDIUM_METER:
|
||||
case SORT_HARD_METER:
|
||||
case SORT_CHALLENGE_METER:
|
||||
case SORT_DOUBLE_EASY_METER:
|
||||
case SORT_DOUBLE_MEDIUM_METER:
|
||||
case SORT_DOUBLE_HARD_METER:
|
||||
case SORT_DOUBLE_CHALLENGE_METER:
|
||||
StepsType st;
|
||||
Difficulty dc;
|
||||
SongUtil::GetStepsTypeAndDifficultyFromSortOrder( so, st, dc );
|
||||
SongUtil::SortSongPointerArrayByStepsTypeAndMeter( arraySongs, st, dc );
|
||||
break;
|
||||
default:
|
||||
ASSERT(0); // unhandled SortOrder
|
||||
case SORT_PREFERRED:
|
||||
// obey order specified by the preferred sort list
|
||||
break;
|
||||
case SORT_ROULETTE:
|
||||
{
|
||||
StepsType st;
|
||||
Difficulty dc;
|
||||
SongUtil::GetStepsTypeAndDifficultyFromSortOrder( SORT_EASY_METER, st, dc );
|
||||
SongUtil::SortSongPointerArrayByStepsTypeAndMeter( arraySongs, st, dc );
|
||||
if( (bool)PREFSMAN->m_bPreferredSortUsesGroups )
|
||||
stable_sort( arraySongs.begin(), arraySongs.end(), SongUtil::CompareSongPointersByGroup );
|
||||
bUseSections = false;
|
||||
break;
|
||||
}
|
||||
case SORT_GROUP:
|
||||
SongUtil::SortSongPointerArrayByGroupAndTitle( arraySongs );
|
||||
if(USE_SECTIONS_WITH_PREFERRED_GROUP)
|
||||
bUseSections = true;
|
||||
else
|
||||
bUseSections = GAMESTATE->m_sPreferredSongGroup == GROUP_ALL;
|
||||
break;
|
||||
case SORT_TITLE:
|
||||
SongUtil::SortSongPointerArrayByTitle( arraySongs );
|
||||
break;
|
||||
case SORT_BPM:
|
||||
SongUtil::SortSongPointerArrayByBPM( arraySongs );
|
||||
break;
|
||||
case SORT_POPULARITY:
|
||||
if( (int) arraySongs.size() > MOST_PLAYED_SONGS_TO_SHOW )
|
||||
arraySongs.erase( arraySongs.begin()+MOST_PLAYED_SONGS_TO_SHOW, arraySongs.end() );
|
||||
bUseSections = false;
|
||||
break;
|
||||
case SORT_TOP_GRADES:
|
||||
SongUtil::SortSongPointerArrayByGrades( arraySongs, true );
|
||||
break;
|
||||
case SORT_ARTIST:
|
||||
SongUtil::SortSongPointerArrayByArtist( arraySongs );
|
||||
break;
|
||||
case SORT_GENRE:
|
||||
SongUtil::SortSongPointerArrayByGenre( arraySongs );
|
||||
break;
|
||||
case SORT_LENGTH:
|
||||
SongUtil::SortSongPointerArrayByLength( arraySongs );
|
||||
break;
|
||||
case SORT_RECENT:
|
||||
SongUtil::SortByMostRecentlyPlayedForMachine( arraySongs );
|
||||
if( (int) arraySongs.size() > RECENT_SONGS_TO_SHOW )
|
||||
arraySongs.erase( arraySongs.begin()+RECENT_SONGS_TO_SHOW, arraySongs.end() );
|
||||
bUseSections = false;
|
||||
break;
|
||||
case SORT_BEGINNER_METER:
|
||||
case SORT_EASY_METER:
|
||||
case SORT_MEDIUM_METER:
|
||||
case SORT_HARD_METER:
|
||||
case SORT_CHALLENGE_METER:
|
||||
case SORT_DOUBLE_EASY_METER:
|
||||
case SORT_DOUBLE_MEDIUM_METER:
|
||||
case SORT_DOUBLE_HARD_METER:
|
||||
case SORT_DOUBLE_CHALLENGE_METER:
|
||||
StepsType st;
|
||||
Difficulty dc;
|
||||
SongUtil::GetStepsTypeAndDifficultyFromSortOrder( so, st, dc );
|
||||
SongUtil::SortSongPointerArrayByStepsTypeAndMeter( arraySongs, st, dc );
|
||||
break;
|
||||
default:
|
||||
FAIL_M("Unhandled sort order! Aborting...");
|
||||
}
|
||||
|
||||
// Build an array of WheelItemDatas from the sorted list of Song*'s
|
||||
@@ -610,13 +610,15 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
|
||||
switch( PREFSMAN->m_MusicWheelUsesSections )
|
||||
{
|
||||
case MusicWheelUsesSections_NEVER:
|
||||
bUseSections = false;
|
||||
break;
|
||||
case MusicWheelUsesSections_ABC_ONLY:
|
||||
if( so != SORT_TITLE && so != SORT_GROUP )
|
||||
case MusicWheelUsesSections_NEVER:
|
||||
bUseSections = false;
|
||||
break;
|
||||
break;
|
||||
case MusicWheelUsesSections_ABC_ONLY:
|
||||
if( so != SORT_TITLE && so != SORT_GROUP )
|
||||
bUseSections = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( bUseSections )
|
||||
@@ -630,13 +632,13 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
/* We're using sections, so use the section name as the top-level sort. */
|
||||
switch( so )
|
||||
{
|
||||
case SORT_PREFERRED:
|
||||
case SORT_TOP_GRADES:
|
||||
case SORT_BPM:
|
||||
break; // don't sort by section
|
||||
default:
|
||||
SongUtil::SortSongPointerArrayBySectionName(arraySongs, so);
|
||||
break;
|
||||
case SORT_PREFERRED:
|
||||
case SORT_TOP_GRADES:
|
||||
case SORT_BPM:
|
||||
break; // don't sort by section
|
||||
default:
|
||||
SongUtil::SortSongPointerArrayBySectionName(arraySongs, so);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,10 +733,10 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SORT_ALL_COURSES:
|
||||
case SORT_NONSTOP_COURSES:
|
||||
case SORT_ONI_COURSES:
|
||||
case SORT_ENDLESS_COURSES:
|
||||
case SORT_ALL_COURSES:
|
||||
case SORT_NONSTOP_COURSES:
|
||||
case SORT_ONI_COURSES:
|
||||
case SORT_ENDLESS_COURSES:
|
||||
{
|
||||
bool bOnlyPreferred = PREFSMAN->m_CourseSortOrder == COURSE_SORT_PREFERRED;
|
||||
|
||||
@@ -769,21 +771,21 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
|
||||
switch( PREFSMAN->m_CourseSortOrder )
|
||||
{
|
||||
case COURSE_SORT_SONGS:
|
||||
CourseUtil::SortCoursePointerArrayByDifficulty( apCourses );
|
||||
break;
|
||||
case COURSE_SORT_PREFERRED:
|
||||
break;
|
||||
case COURSE_SORT_METER:
|
||||
CourseUtil::SortCoursePointerArrayByAvgDifficulty( apCourses );
|
||||
break;
|
||||
case COURSE_SORT_METER_SUM:
|
||||
CourseUtil::SortCoursePointerArrayByTotalDifficulty( apCourses );
|
||||
break;
|
||||
case COURSE_SORT_RANK:
|
||||
CourseUtil::SortCoursePointerArrayByRanking( apCourses );
|
||||
break;
|
||||
default: ASSERT(0);
|
||||
case COURSE_SORT_SONGS:
|
||||
CourseUtil::SortCoursePointerArrayByDifficulty( apCourses );
|
||||
break;
|
||||
case COURSE_SORT_PREFERRED:
|
||||
break;
|
||||
case COURSE_SORT_METER:
|
||||
CourseUtil::SortCoursePointerArrayByAvgDifficulty( apCourses );
|
||||
break;
|
||||
case COURSE_SORT_METER_SUM:
|
||||
CourseUtil::SortCoursePointerArrayByTotalDifficulty( apCourses );
|
||||
break;
|
||||
case COURSE_SORT_RANK:
|
||||
CourseUtil::SortCoursePointerArrayByRanking( apCourses );
|
||||
break;
|
||||
default: FAIL_M("Impossible to sort the courses! Aborting...");
|
||||
}
|
||||
|
||||
// since we can't agree, make it an option
|
||||
@@ -810,9 +812,10 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
{
|
||||
switch( pCourse->GetPlayMode() )
|
||||
{
|
||||
case PLAY_MODE_ONI: sThisSection = "Oni"; break;
|
||||
case PLAY_MODE_NONSTOP: sThisSection = "Nonstop"; break;
|
||||
case PLAY_MODE_ENDLESS: sThisSection = "Endless"; break;
|
||||
case PLAY_MODE_ONI: sThisSection = "Oni"; break;
|
||||
case PLAY_MODE_NONSTOP: sThisSection = "Nonstop"; break;
|
||||
case PLAY_MODE_ENDLESS: sThisSection = "Endless"; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,6 +836,8 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// init music status icons
|
||||
@@ -1227,23 +1232,24 @@ bool MusicWheel::Select() // return true if this selection ends the screen
|
||||
|
||||
switch( m_WheelState )
|
||||
{
|
||||
case STATE_FLYING_OFF_BEFORE_NEXT_SORT:
|
||||
case STATE_ROULETTE_SLOWING_DOWN:
|
||||
return false;
|
||||
case STATE_ROULETTE_SPINNING:
|
||||
m_WheelState = STATE_ROULETTE_SLOWING_DOWN;
|
||||
m_iSwitchesLeftInSpinDown = ROULETTE_SLOW_DOWN_SWITCHES/2+1 + RandomInt( ROULETTE_SLOW_DOWN_SWITCHES/2 );
|
||||
m_fTimeLeftInState = 0.1f;
|
||||
return false;
|
||||
case STATE_RANDOM_SPINNING:
|
||||
m_fPositionOffsetFromSelection = max(m_fPositionOffsetFromSelection, 0.3f);
|
||||
m_WheelState = STATE_LOCKED;
|
||||
SCREENMAN->PlayStartSound();
|
||||
m_fLockedWheelVelocity = 0;
|
||||
// Set m_Moving to zero to stop the sounds from playing.
|
||||
m_Moving = 0;
|
||||
SCREENMAN->PostMessageToTopScreen( SM_SongChanged, 0 );
|
||||
return true;
|
||||
case STATE_FLYING_OFF_BEFORE_NEXT_SORT:
|
||||
case STATE_ROULETTE_SLOWING_DOWN:
|
||||
return false;
|
||||
case STATE_ROULETTE_SPINNING:
|
||||
m_WheelState = STATE_ROULETTE_SLOWING_DOWN;
|
||||
m_iSwitchesLeftInSpinDown = ROULETTE_SLOW_DOWN_SWITCHES/2+1 + RandomInt( ROULETTE_SLOW_DOWN_SWITCHES/2 );
|
||||
m_fTimeLeftInState = 0.1f;
|
||||
return false;
|
||||
case STATE_RANDOM_SPINNING:
|
||||
m_fPositionOffsetFromSelection = max(m_fPositionOffsetFromSelection, 0.3f);
|
||||
m_WheelState = STATE_LOCKED;
|
||||
SCREENMAN->PlayStartSound();
|
||||
m_fLockedWheelVelocity = 0;
|
||||
// Set m_Moving to zero to stop the sounds from playing.
|
||||
m_Moving = 0;
|
||||
SCREENMAN->PostMessageToTopScreen( SM_SongChanged, 0 );
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( !WheelBase::Select() )
|
||||
@@ -1251,29 +1257,25 @@ bool MusicWheel::Select() // return true if this selection ends the screen
|
||||
|
||||
switch( m_CurWheelItemData[m_iSelection]->m_Type )
|
||||
{
|
||||
case TYPE_ROULETTE:
|
||||
StartRoulette();
|
||||
return false;
|
||||
case TYPE_RANDOM:
|
||||
StartRandom();
|
||||
return false;
|
||||
case TYPE_SONG:
|
||||
case TYPE_COURSE:
|
||||
case TYPE_PORTAL:
|
||||
break;
|
||||
case TYPE_SORT:
|
||||
GetCurWheelItemData(m_iSelection)->m_pAction->ApplyToAllPlayers();
|
||||
ChangeSort( GAMESTATE->m_PreferredSortOrder );
|
||||
m_sLastModeMenuItem = GetCurWheelItemData(m_iSelection)->m_pAction->m_sName;
|
||||
return false;
|
||||
case TYPE_CUSTOM:
|
||||
GetCurWheelItemData(m_iSelection)->m_pAction->ApplyToAllPlayers();
|
||||
if( GetCurWheelItemData(m_iSelection)->m_pAction->m_sScreen != "" )
|
||||
return true;
|
||||
else
|
||||
case TYPE_ROULETTE:
|
||||
StartRoulette();
|
||||
return false;
|
||||
case TYPE_RANDOM:
|
||||
StartRandom();
|
||||
return false;
|
||||
case TYPE_SORT:
|
||||
GetCurWheelItemData(m_iSelection)->m_pAction->ApplyToAllPlayers();
|
||||
ChangeSort( GAMESTATE->m_PreferredSortOrder );
|
||||
m_sLastModeMenuItem = GetCurWheelItemData(m_iSelection)->m_pAction->m_sName;
|
||||
return false;
|
||||
case TYPE_CUSTOM:
|
||||
GetCurWheelItemData(m_iSelection)->m_pAction->ApplyToAllPlayers();
|
||||
if( GetCurWheelItemData(m_iSelection)->m_pAction->m_sScreen != "" )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
default: return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MusicWheel::StartRoulette()
|
||||
@@ -1517,11 +1519,11 @@ Song* MusicWheel::GetSelectedSong()
|
||||
{
|
||||
switch( m_CurWheelItemData[m_iSelection]->m_Type )
|
||||
{
|
||||
case TYPE_PORTAL:
|
||||
return GetPreferredSelectionForRandomOrPortal();
|
||||
case TYPE_PORTAL:
|
||||
return GetPreferredSelectionForRandomOrPortal();
|
||||
default:
|
||||
return GetCurWheelItemData(m_iSelection)->m_pSong;
|
||||
}
|
||||
|
||||
return GetCurWheelItemData(m_iSelection)->m_pSong;
|
||||
}
|
||||
|
||||
/* Find a random song. If possible, find one that has the preferred difficulties of
|
||||
|
||||
+6
-4
@@ -547,10 +547,12 @@ bool NoteData::RowNeedsAtLeastSimultaneousPresses( int iMinSimultaneousPresses,
|
||||
const TapNote &tn = GetTapNote(t, row);
|
||||
switch( tn.type )
|
||||
{
|
||||
case TapNote::mine:
|
||||
case TapNote::empty:
|
||||
case TapNote::fake:
|
||||
continue; // skip these types - they don't count
|
||||
case TapNote::mine:
|
||||
case TapNote::empty:
|
||||
case TapNote::fake:
|
||||
case TapNote::lift: // you don't "press" on a lift.
|
||||
continue; // skip these types - they don't count
|
||||
default: break;
|
||||
}
|
||||
++iNumNotesThisIndex;
|
||||
}
|
||||
|
||||
+11
-9
@@ -800,11 +800,12 @@ RadarStats CalculateRadarStatsFast( const NoteData &in, RadarStats &out )
|
||||
const TapNote &tn = in.GetTapNote(t, r);
|
||||
switch( tn.type )
|
||||
{
|
||||
case TapNote::mine:
|
||||
case TapNote::empty:
|
||||
case TapNote::fake:
|
||||
case TapNote::autoKeysound:
|
||||
continue; // skip these types - they don't count
|
||||
case TapNote::mine:
|
||||
case TapNote::empty:
|
||||
case TapNote::fake:
|
||||
case TapNote::autoKeysound:
|
||||
continue; // skip these types - they don't count
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( (itr = simultaneousMap.find(r)) == simultaneousMap.end() )
|
||||
@@ -830,10 +831,11 @@ RadarStats CalculateRadarStatsFast( const NoteData &in, RadarStats &out )
|
||||
{
|
||||
switch( in.GetTapNote(t, rr).type )
|
||||
{
|
||||
case TapNote::mine:
|
||||
case TapNote::empty:
|
||||
case TapNote::fake:
|
||||
continue; // skip these types - they don't count
|
||||
case TapNote::mine:
|
||||
case TapNote::empty:
|
||||
case TapNote::fake:
|
||||
continue; // skip these types - they don't count
|
||||
default: break;
|
||||
}
|
||||
if( (itr = simultaneousMap.find(rr)) == simultaneousMap.end() )
|
||||
simultaneousMap[rr] = 1;
|
||||
|
||||
+53
-42
@@ -849,27 +849,26 @@ void NoteField::DrawPrimitives()
|
||||
}
|
||||
|
||||
const TimingData *pTiming = GetDisplayedTiming(m_pPlayerState);
|
||||
|
||||
const vector<TimingSegment *> *segs = pTiming->allTimingSegments;
|
||||
unsigned i = 0;
|
||||
// Draw beat bars
|
||||
if( ( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) && pTiming != NULL )
|
||||
{
|
||||
const TimingData &timing = *pTiming;
|
||||
const vector<TimeSignatureSegment> &vTimeSignatureSegments = timing.m_vTimeSignatureSegments;
|
||||
const vector<TimingSegment *> &tSigs = segs[SEGMENT_TIME_SIG];
|
||||
int iMeasureIndex = 0;
|
||||
FOREACH_CONST( TimeSignatureSegment, vTimeSignatureSegments, iter )
|
||||
for (i = 0; i < tSigs.size(); i++)
|
||||
{
|
||||
vector<TimeSignatureSegment>::const_iterator next = iter;
|
||||
next++;
|
||||
int iSegmentEndRow = (next == vTimeSignatureSegments.end()) ? iLastRowToDraw : next->GetRow();
|
||||
|
||||
TimeSignatureSegment *ts = static_cast<TimeSignatureSegment *>(tSigs[i]);
|
||||
int iSegmentEndRow = (i + 1 == tSigs.size()) ? iLastRowToDraw : tSigs[i+1]->GetRow();
|
||||
|
||||
// beat bars every 16th note
|
||||
int iDrawBeatBarsEveryRows = BeatToNoteRow( ((float)iter->GetDen()) / 4 ) / 4;
|
||||
int iDrawBeatBarsEveryRows = BeatToNoteRow( ((float)ts->GetDen()) / 4 ) / 4;
|
||||
|
||||
// In 4/4, every 16th beat bar is a measure
|
||||
int iMeasureBarFrequency = iter->GetNum() * 4;
|
||||
int iMeasureBarFrequency = ts->GetNum() * 4;
|
||||
int iBeatBarsDrawn = 0;
|
||||
|
||||
for( int i=iter->GetRow(); i < iSegmentEndRow; i += iDrawBeatBarsEveryRows )
|
||||
for( int j=ts->GetRow(); j < iSegmentEndRow; j += iDrawBeatBarsEveryRows )
|
||||
{
|
||||
bool bMeasureBar = iBeatBarsDrawn % iMeasureBarFrequency == 0;
|
||||
BeatBarType type = quarter_beat;
|
||||
@@ -879,7 +878,7 @@ void NoteField::DrawPrimitives()
|
||||
type = beat;
|
||||
else if( iBeatBarsDrawn % 2 == 0 )
|
||||
type = half_beat;
|
||||
float fBeat = NoteRowToBeat(i);
|
||||
float fBeat = NoteRowToBeat(j);
|
||||
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
{
|
||||
@@ -902,8 +901,9 @@ void NoteField::DrawPrimitives()
|
||||
// Scroll text
|
||||
if( GAMESTATE->m_bIsUsingStepTiming )
|
||||
{
|
||||
FOREACH_CONST( ScrollSegment, timing.m_ScrollSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_SCROLL].size(); i++)
|
||||
{
|
||||
ScrollSegment *seg = static_cast<ScrollSegment *>(segs[SEGMENT_SCROLL][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -914,8 +914,9 @@ void NoteField::DrawPrimitives()
|
||||
}
|
||||
|
||||
// BPM text
|
||||
FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_BPM].size(); i++)
|
||||
{
|
||||
BPMSegment *seg = static_cast<BPMSegment *>(segs[SEGMENT_BPM][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -925,8 +926,9 @@ void NoteField::DrawPrimitives()
|
||||
}
|
||||
|
||||
// Freeze text
|
||||
FOREACH_CONST( StopSegment, timing.m_StopSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_STOP_DELAY].size(); i++)
|
||||
{
|
||||
StopSegment *seg = static_cast<StopSegment *>(segs[SEGMENT_STOP_DELAY][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -936,8 +938,9 @@ void NoteField::DrawPrimitives()
|
||||
}
|
||||
|
||||
// Warp text
|
||||
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_WARP].size(); i++)
|
||||
{
|
||||
WarpSegment *seg = static_cast<WarpSegment *>(segs[SEGMENT_WARP][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -948,8 +951,9 @@ void NoteField::DrawPrimitives()
|
||||
|
||||
|
||||
// Time Signature text
|
||||
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_TIME_SIG].size(); i++)
|
||||
{
|
||||
TimeSignatureSegment *seg = static_cast<TimeSignatureSegment *>(segs[SEGMENT_TIME_SIG][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -961,8 +965,9 @@ void NoteField::DrawPrimitives()
|
||||
if( GAMESTATE->m_bIsUsingStepTiming )
|
||||
{
|
||||
// Tickcount text
|
||||
FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_TICKCOUNT].size(); i++)
|
||||
{
|
||||
TickcountSegment *seg = static_cast<TickcountSegment *>(segs[SEGMENT_TICKCOUNT][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -975,8 +980,9 @@ void NoteField::DrawPrimitives()
|
||||
if( GAMESTATE->m_bIsUsingStepTiming )
|
||||
{
|
||||
// Combo text
|
||||
FOREACH_CONST( ComboSegment, timing.m_ComboSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_COMBO].size(); i++)
|
||||
{
|
||||
ComboSegment *seg = static_cast<ComboSegment *>(segs[SEGMENT_COMBO][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -987,8 +993,9 @@ void NoteField::DrawPrimitives()
|
||||
}
|
||||
|
||||
// Label text
|
||||
FOREACH_CONST( LabelSegment, timing.m_LabelSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_LABEL].size(); i++)
|
||||
{
|
||||
LabelSegment *seg = static_cast<LabelSegment *>(segs[SEGMENT_LABEL][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -999,8 +1006,10 @@ void NoteField::DrawPrimitives()
|
||||
|
||||
if( GAMESTATE->m_bIsUsingStepTiming )
|
||||
{
|
||||
FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, seg )
|
||||
// Speed text
|
||||
for (i = 0; i < segs[SEGMENT_SPEED].size(); i++)
|
||||
{
|
||||
SpeedSegment *seg = static_cast<SpeedSegment *>(segs[SEGMENT_SPEED][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -1011,11 +1020,12 @@ void NoteField::DrawPrimitives()
|
||||
}
|
||||
}
|
||||
|
||||
// Speed text
|
||||
// Fake text
|
||||
if( GAMESTATE->m_bIsUsingStepTiming )
|
||||
{
|
||||
FOREACH_CONST( FakeSegment, timing.m_FakeSegments, seg )
|
||||
for (i = 0; i < segs[SEGMENT_FAKE].size(); i++)
|
||||
{
|
||||
FakeSegment *seg = static_cast<FakeSegment *>(segs[SEGMENT_FAKE][i]);
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
@@ -1074,55 +1084,55 @@ void NoteField::DrawPrimitives()
|
||||
case EditMode_Full:
|
||||
{
|
||||
vector<BackgroundChange>::iterator iter[NUM_BackgroundLayer];
|
||||
FOREACH_BackgroundLayer( i )
|
||||
iter[i] = GAMESTATE->m_pCurSong->GetBackgroundChanges(i).begin();
|
||||
FOREACH_BackgroundLayer( j )
|
||||
iter[j] = GAMESTATE->m_pCurSong->GetBackgroundChanges(j).begin();
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
float fLowestBeat = FLT_MAX;
|
||||
vector<BackgroundLayer> viLowestIndex;
|
||||
|
||||
FOREACH_BackgroundLayer( i )
|
||||
FOREACH_BackgroundLayer( j )
|
||||
{
|
||||
if( iter[i] == GAMESTATE->m_pCurSong->GetBackgroundChanges(i).end() )
|
||||
if( iter[j] == GAMESTATE->m_pCurSong->GetBackgroundChanges(j).end() )
|
||||
continue;
|
||||
|
||||
float fBeat = iter[i]->m_fStartBeat;
|
||||
float fBeat = iter[j]->m_fStartBeat;
|
||||
if( fBeat < fLowestBeat )
|
||||
{
|
||||
fLowestBeat = fBeat;
|
||||
viLowestIndex.clear();
|
||||
viLowestIndex.push_back( i );
|
||||
viLowestIndex.push_back( j );
|
||||
}
|
||||
else if( fBeat == fLowestBeat )
|
||||
{
|
||||
viLowestIndex.push_back( i );
|
||||
viLowestIndex.push_back( j );
|
||||
}
|
||||
}
|
||||
|
||||
if( viLowestIndex.empty() )
|
||||
{
|
||||
FOREACH_BackgroundLayer( i )
|
||||
ASSERT( iter[i] == GAMESTATE->m_pCurSong->GetBackgroundChanges(i).end() );
|
||||
FOREACH_BackgroundLayer( j )
|
||||
ASSERT( iter[j] == GAMESTATE->m_pCurSong->GetBackgroundChanges(j).end() );
|
||||
break;
|
||||
}
|
||||
|
||||
if( IS_ON_SCREEN(fLowestBeat) )
|
||||
{
|
||||
vector<RString> vsBGChanges;
|
||||
FOREACH_CONST( BackgroundLayer, viLowestIndex, i )
|
||||
FOREACH_CONST( BackgroundLayer, viLowestIndex, bl )
|
||||
{
|
||||
ASSERT( iter[*i] != GAMESTATE->m_pCurSong->GetBackgroundChanges(*i).end() );
|
||||
const BackgroundChange& change = *iter[*i];
|
||||
ASSERT( iter[*bl] != GAMESTATE->m_pCurSong->GetBackgroundChanges(*bl).end() );
|
||||
const BackgroundChange& change = *iter[*bl];
|
||||
RString s = change.GetTextDescription();
|
||||
if( *i!=0 )
|
||||
s = ssprintf("%d: ",*i) + s;
|
||||
if( *bl!=0 )
|
||||
s = ssprintf("%d: ",*bl) + s;
|
||||
vsBGChanges.push_back( s );
|
||||
}
|
||||
DrawBGChangeText( fLowestBeat, join("\n",vsBGChanges) );
|
||||
}
|
||||
FOREACH_CONST( BackgroundLayer, viLowestIndex, i )
|
||||
iter[*i]++;
|
||||
FOREACH_CONST( BackgroundLayer, viLowestIndex, bl )
|
||||
iter[*bl]++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1166,9 +1176,9 @@ void NoteField::DrawPrimitives()
|
||||
ssprintf("NumTracks %d = ColsPerPlayer %d",m_pNoteData->GetNumTracks(),
|
||||
GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer));
|
||||
|
||||
for( int i=0; i<m_pNoteData->GetNumTracks(); i++ ) // for each arrow column
|
||||
for( int j=0; j<m_pNoteData->GetNumTracks(); j++ ) // for each arrow column
|
||||
{
|
||||
const int c = pStyle->m_iColumnDrawOrder[i];
|
||||
const int c = pStyle->m_iColumnDrawOrder[j];
|
||||
|
||||
bool bAnyUpcomingInThisCol = false;
|
||||
|
||||
@@ -1179,7 +1189,7 @@ void NoteField::DrawPrimitives()
|
||||
|
||||
for( ; begin != end; ++begin )
|
||||
{
|
||||
const TapNote &tn = begin->second; //m_pNoteData->GetTapNote(c, i);
|
||||
const TapNote &tn = begin->second; //m_pNoteData->GetTapNote(c, j);
|
||||
if( tn.type != TapNote::hold_head )
|
||||
continue; // skip
|
||||
|
||||
@@ -1255,6 +1265,7 @@ void NoteField::DrawPrimitives()
|
||||
//if (tn.subType == TapNote::hold_head_roll)
|
||||
continue; // skip
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Don't draw hidden (fully judged) steps.
|
||||
|
||||
+20
-10
@@ -217,16 +217,26 @@ inline const RString TapNoteTypeToString( TapNote::Type tn )
|
||||
{
|
||||
switch( tn )
|
||||
{
|
||||
case TapNote::empty: return RString("empty");
|
||||
case TapNote::tap: return RString("tap");
|
||||
case TapNote::hold_head: return RString("hold_head");
|
||||
case TapNote::hold_tail: return RString("hold_tail");
|
||||
case TapNote::mine: return RString("mine");
|
||||
case TapNote::lift: return RString("lift");
|
||||
case TapNote::attack: return RString("attack");
|
||||
case TapNote::autoKeysound: return RString("autoKeysound");
|
||||
case TapNote::fake: return RString("fake");
|
||||
default: return RString();
|
||||
case TapNote::empty:
|
||||
return RString("empty");
|
||||
case TapNote::tap:
|
||||
return RString("tap");
|
||||
case TapNote::hold_head:
|
||||
return RString("hold_head");
|
||||
case TapNote::hold_tail:
|
||||
return RString("hold_tail");
|
||||
case TapNote::mine:
|
||||
return RString("mine");
|
||||
case TapNote::lift:
|
||||
return RString("lift");
|
||||
case TapNote::attack:
|
||||
return RString("attack");
|
||||
case TapNote::autoKeysound:
|
||||
return RString("autoKeysound");
|
||||
case TapNote::fake:
|
||||
return RString("fake");
|
||||
default:
|
||||
return RString("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+83
-9
@@ -459,13 +459,16 @@ static bool SearchForKeysound( const RString &sPath, RString nDataOriginal, map<
|
||||
* Do a search. Don't do a wildcard search; if sData is "song.wav",
|
||||
* we might also have "song.png", which we shouldn't match. */
|
||||
RString nData = nDataOriginal;
|
||||
if( !IsAFile(out.GetSongDir()+nData) )
|
||||
RString dir = out.GetSongDir();
|
||||
if (dir.empty())
|
||||
dir = Dirname(sPath);
|
||||
if( !IsAFile(dir+nData) )
|
||||
{
|
||||
const char *exts[] = { "oga", "ogg", "wav", "mp3", NULL }; // XXX: stop duplicating these everywhere
|
||||
for( unsigned i = 0; exts[i] != NULL; ++i )
|
||||
{
|
||||
RString fn = SetExtension( nData, exts[i] );
|
||||
if( IsAFile(out.GetSongDir()+fn) )
|
||||
if( IsAFile(dir+fn) )
|
||||
{
|
||||
nData = fn;
|
||||
break;
|
||||
@@ -473,9 +476,9 @@ static bool SearchForKeysound( const RString &sPath, RString nDataOriginal, map<
|
||||
}
|
||||
}
|
||||
|
||||
if( !IsAFile(out.GetSongDir()+nData) )
|
||||
if( !IsAFile(dir+nData) )
|
||||
{
|
||||
LOG->UserLog( "Song file", out.GetSongDir(), "references key \"%s\" that can't be found", nData.c_str() );
|
||||
LOG->UserLog( "Song file", dir, "references key \"%s\" that can't be found", nData.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -573,8 +576,8 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
|
||||
|
||||
if( fBPM > 0.0f )
|
||||
{
|
||||
BPMSegment newSeg( 0, fBPM );
|
||||
out.m_Timing.AddBPMSegment( newSeg );
|
||||
BPMSegment * newSeg = new BPMSegment( 0, fBPM );
|
||||
out.m_Timing.AddSegment(SEGMENT_BPM, newSeg );
|
||||
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
|
||||
}
|
||||
else
|
||||
@@ -663,9 +666,9 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
|
||||
float fBeats = StringToFloat( sBeats ) / 48.0f;
|
||||
float fFreezeSecs = fBeats / fBPS;
|
||||
|
||||
StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs );
|
||||
out.m_Timing.AddStopSegment( newSeg );
|
||||
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.GetPause() );
|
||||
StopSegment * newSeg = new StopSegment( fBeat, fFreezeSecs );
|
||||
out.m_Timing.AddSegment( SEGMENT_STOP_DELAY, newSeg );
|
||||
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg->GetPause() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1067,6 +1070,75 @@ void BMSLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
GetDirListing( sPath + RString("*.bml"), out );
|
||||
}
|
||||
|
||||
bool BMSLoader::LoadNoteDataFromSimfile( const RString & cachePath, Steps & out )
|
||||
{
|
||||
Song dummy;
|
||||
// TODO: Simplify this copy/paste from LoadFromDir.
|
||||
|
||||
vector<NameToData_t> BMSData;
|
||||
BMSData.push_back(NameToData_t());
|
||||
ReadBMSFile(cachePath, BMSData.back());
|
||||
|
||||
RString commonSubstring;
|
||||
GetCommonTagFromMapList( BMSData, "#title", commonSubstring );
|
||||
|
||||
Steps *copy = dummy.CreateSteps();
|
||||
|
||||
copy->SetDifficulty( Difficulty_Medium );
|
||||
RString sTag;
|
||||
if( GetTagFromMap( BMSData[0], "#title", sTag ) && sTag.size() != commonSubstring.size() )
|
||||
{
|
||||
sTag = sTag.substr( commonSubstring.size(), sTag.size() - commonSubstring.size() );
|
||||
sTag.MakeLower();
|
||||
|
||||
if( sTag.find('l') != sTag.npos )
|
||||
{
|
||||
unsigned lPos = sTag.find('l');
|
||||
if( lPos > 2 && sTag.substr(lPos-2,4) == "solo" )
|
||||
{
|
||||
copy->SetDifficulty( Difficulty_Edit );
|
||||
}
|
||||
else
|
||||
{
|
||||
copy->SetDifficulty( Difficulty_Easy );
|
||||
}
|
||||
}
|
||||
else if( sTag.find('a') != sTag.npos )
|
||||
copy->SetDifficulty( Difficulty_Hard );
|
||||
else if( sTag.find('b') != sTag.npos )
|
||||
copy->SetDifficulty( Difficulty_Beginner );
|
||||
}
|
||||
if( commonSubstring == "" )
|
||||
{
|
||||
copy->SetDifficulty(Difficulty_Medium);
|
||||
RString localTag;
|
||||
if (GetTagFromMap(BMSData[0], "#title#", localTag))
|
||||
SearchForDifficulty(localTag, copy);
|
||||
}
|
||||
ReadGlobalTags( BMSData[0], dummy );
|
||||
if( commonSubstring.size() > 2 && commonSubstring[commonSubstring.size() - 2] == ' ' )
|
||||
{
|
||||
switch( commonSubstring[commonSubstring.size() - 1] )
|
||||
{
|
||||
case '[':
|
||||
case '(':
|
||||
case '<':
|
||||
commonSubstring = commonSubstring.substr(0, commonSubstring.size() - 2);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
map<RString, int> mapFilenameToKeysoundIndex;
|
||||
|
||||
|
||||
const bool ok = LoadFromBMSFile( cachePath, BMSData[0], *copy, dummy, mapFilenameToKeysoundIndex );
|
||||
if( ok )
|
||||
{
|
||||
out.SetNoteData(copy->GetNoteData());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool BMSLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
{
|
||||
LOG->Trace( "Song::LoadFromBMSDir(%s)", sDir.c_str() );
|
||||
@@ -1171,6 +1243,7 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
iMainDataIndex = i;
|
||||
|
||||
ReadGlobalTags( aBMSData[iMainDataIndex], out );
|
||||
out.m_sSongFileName = out.GetSongDir() + arrayBMSFileNames[iMainDataIndex];
|
||||
|
||||
// The brackets before the difficulty are in common substring, so remove them if it's found.
|
||||
if( commonSubstring.size() > 2 && commonSubstring[commonSubstring.size() - 2] == ' ' )
|
||||
@@ -1203,6 +1276,7 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
if( i == static_cast<unsigned>(iMainDataIndex) )
|
||||
out.m_SongTiming = pNewNotes->m_Timing;
|
||||
|
||||
pNewNotes->SetFilename(out.GetSongDir() + arrayBMSFileNames[i]);
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
#define NOTES_LOADER_BMS_H
|
||||
|
||||
class Song;
|
||||
class Steps;
|
||||
/** @brief Reads a Song from a set of .BMS files. */
|
||||
namespace BMSLoader
|
||||
{
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
bool LoadFromDir( const RString &sDir, Song &out );
|
||||
bool LoadNoteDataFromSimfile( const RString & cachePath, Steps &out );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+290
-213
@@ -170,6 +170,238 @@ Difficulty DwiCompatibleStringToDifficulty( const RString& sDC )
|
||||
else return Difficulty_Invalid;
|
||||
}
|
||||
|
||||
static StepsType GetTypeFromMode(const RString &mode)
|
||||
{
|
||||
if( mode == "SINGLE" )
|
||||
return StepsType_dance_single;
|
||||
else if( mode == "DOUBLE" )
|
||||
return StepsType_dance_double;
|
||||
else if( mode == "COUPLE" )
|
||||
return StepsType_dance_couple;
|
||||
else if( mode == "SOLO" )
|
||||
return StepsType_dance_solo;
|
||||
ASSERT_M(0, "Unrecognized DWI notes format " + mode + "!");
|
||||
return StepsType_Invalid; // just in case.
|
||||
}
|
||||
|
||||
static NoteData ParseNoteData(RString &step1, RString &step2,
|
||||
Steps &out, const RString &path)
|
||||
{
|
||||
g_mapDanceNoteToNoteDataColumn.clear();
|
||||
switch( out.m_StepsType )
|
||||
{
|
||||
case StepsType_dance_single:
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
|
||||
break;
|
||||
case StepsType_dance_double:
|
||||
case StepsType_dance_couple:
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_LEFT] = 4;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_DOWN] = 5;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_UP] = 6;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_RIGHT] = 7;
|
||||
break;
|
||||
case StepsType_dance_solo:
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPLEFT] = 1;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 2;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 3;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPRIGHT] = 4;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 5;
|
||||
break;
|
||||
DEFAULT_FAIL( out.m_StepsType );
|
||||
}
|
||||
|
||||
NoteData newNoteData;
|
||||
newNoteData.SetNumTracks( g_mapDanceNoteToNoteDataColumn.size() );
|
||||
|
||||
for( int pad=0; pad<2; pad++ ) // foreach pad
|
||||
{
|
||||
RString sStepData;
|
||||
switch( pad )
|
||||
{
|
||||
case 0:
|
||||
sStepData = step1;
|
||||
break;
|
||||
case 1:
|
||||
if( step2 == "" ) // no data
|
||||
continue; // skip
|
||||
sStepData = step2;
|
||||
break;
|
||||
DEFAULT_FAIL( pad );
|
||||
}
|
||||
|
||||
sStepData.Replace("\n", "");
|
||||
sStepData.Replace("\r", "");
|
||||
sStepData.Replace("\t", "");
|
||||
sStepData.Replace(" ", "");
|
||||
|
||||
double fCurrentBeat = 0;
|
||||
double fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
|
||||
|
||||
for( size_t i=0; i<sStepData.size(); )
|
||||
{
|
||||
char c = sStepData[i++];
|
||||
switch( c )
|
||||
{
|
||||
// begins a series
|
||||
case '(':
|
||||
fCurrentIncrementer = 1.0/16 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
case '[':
|
||||
fCurrentIncrementer = 1.0/24 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
case '{':
|
||||
fCurrentIncrementer = 1.0/64 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
case '`':
|
||||
fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
|
||||
// ends a series
|
||||
case ')':
|
||||
case ']':
|
||||
case '}':
|
||||
case '\'':
|
||||
case '>':
|
||||
fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
|
||||
default: // this is a note character
|
||||
{
|
||||
if( c == '!' )
|
||||
{
|
||||
LOG->UserLog(
|
||||
"Song file",
|
||||
path,
|
||||
"has an unexpected character: '!'." );
|
||||
continue;
|
||||
}
|
||||
|
||||
bool jump = false;
|
||||
if( c == '<' )
|
||||
{
|
||||
/* Arr. Is this a jump or a 1/192 marker? */
|
||||
if( Is192( sStepData, i ) )
|
||||
{
|
||||
fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* It's a jump.
|
||||
* We need to keep reading notes until we hit a >. */
|
||||
jump = true;
|
||||
i++;
|
||||
}
|
||||
|
||||
const int iIndex = BeatToNoteRow( (float)fCurrentBeat );
|
||||
i--;
|
||||
do {
|
||||
c = sStepData[i++];
|
||||
|
||||
if( jump && c == '>' )
|
||||
break;
|
||||
|
||||
int iCol1, iCol2;
|
||||
DWIcharToNoteCol(
|
||||
c,
|
||||
(GameController)pad,
|
||||
iCol1,
|
||||
iCol2,
|
||||
path );
|
||||
|
||||
if( iCol1 != -1 )
|
||||
newNoteData.SetTapNote(iCol1,
|
||||
iIndex,
|
||||
TAP_ORIGINAL_TAP);
|
||||
if( iCol2 != -1 )
|
||||
newNoteData.SetTapNote(iCol2,
|
||||
iIndex,
|
||||
TAP_ORIGINAL_TAP);
|
||||
|
||||
if(i>=sStepData.length())
|
||||
{
|
||||
break;
|
||||
//we ran out of data
|
||||
//while looking for the ending > mark
|
||||
}
|
||||
|
||||
if( sStepData[i] == '!' )
|
||||
{
|
||||
i++;
|
||||
const char holdChar = sStepData[i++];
|
||||
|
||||
DWIcharToNoteCol(holdChar,
|
||||
(GameController)pad,
|
||||
iCol1,
|
||||
iCol2,
|
||||
path );
|
||||
|
||||
if( iCol1 != -1 )
|
||||
newNoteData.SetTapNote(iCol1,
|
||||
iIndex,
|
||||
TAP_ORIGINAL_HOLD_HEAD);
|
||||
if( iCol2 != -1 )
|
||||
newNoteData.SetTapNote(iCol2,
|
||||
iIndex,
|
||||
TAP_ORIGINAL_HOLD_HEAD);
|
||||
}
|
||||
}
|
||||
while( jump );
|
||||
fCurrentBeat += fCurrentIncrementer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in iDuration. */
|
||||
for( int t=0; t<newNoteData.GetNumTracks(); ++t )
|
||||
{
|
||||
FOREACH_NONEMPTY_ROW_IN_TRACK( newNoteData, t, iHeadRow )
|
||||
{
|
||||
TapNote tn = newNoteData.GetTapNote( t, iHeadRow );
|
||||
if( tn.type != TapNote::hold_head )
|
||||
continue;
|
||||
|
||||
int iTailRow = iHeadRow;
|
||||
bool bFound = false;
|
||||
while( !bFound && newNoteData.GetNextTapNoteRowForTrack(t, iTailRow) )
|
||||
{
|
||||
const TapNote &TailTap = newNoteData.GetTapNote( t, iTailRow );
|
||||
if( TailTap.type == TapNote::empty )
|
||||
continue;
|
||||
|
||||
newNoteData.SetTapNote( t, iTailRow, TAP_EMPTY );
|
||||
tn.iDuration = iTailRow - iHeadRow;
|
||||
newNoteData.SetTapNote( t, iHeadRow, tn );
|
||||
bFound = true;
|
||||
}
|
||||
|
||||
if( !bFound )
|
||||
{
|
||||
/* The hold was never closed. */
|
||||
LOG->UserLog("Song file",
|
||||
path,
|
||||
"failed to close a hold note in \"%s\" on track %i",
|
||||
DifficultyToString(out.GetDifficulty()).c_str(),
|
||||
t);
|
||||
|
||||
newNoteData.SetTapNote( t, iHeadRow, TAP_EMPTY );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT( newNoteData.GetNumTracks() > 0 );
|
||||
return newNoteData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Look through the notes tag to extract the data.
|
||||
* @param sMode the steps type.
|
||||
@@ -192,216 +424,17 @@ static bool LoadFromDWITokens(
|
||||
{
|
||||
CHECKPOINT_M( "DWILoader::LoadFromDWITokens()" );
|
||||
|
||||
out.m_StepsType = StepsType_Invalid;
|
||||
out.m_StepsType = GetTypeFromMode(sMode);
|
||||
|
||||
if( sMode == "SINGLE" ) out.m_StepsType = StepsType_dance_single;
|
||||
else if( sMode == "DOUBLE" ) out.m_StepsType = StepsType_dance_double;
|
||||
else if( sMode == "COUPLE" ) out.m_StepsType = StepsType_dance_couple;
|
||||
else if( sMode == "SOLO" ) out.m_StepsType = StepsType_dance_solo;
|
||||
else
|
||||
{
|
||||
ASSERT_M(0, "Unrecognized DWI notes format " + sMode + "!");
|
||||
out.m_StepsType = StepsType_dance_single;
|
||||
}
|
||||
out.SetMeter(StringToInt(sNumFeet));
|
||||
|
||||
|
||||
g_mapDanceNoteToNoteDataColumn.clear();
|
||||
switch( out.m_StepsType )
|
||||
{
|
||||
case StepsType_dance_single:
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
|
||||
break;
|
||||
case StepsType_dance_double:
|
||||
case StepsType_dance_couple:
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_LEFT] = 4;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_DOWN] = 5;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_UP] = 6;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_RIGHT] = 7;
|
||||
break;
|
||||
case StepsType_dance_solo:
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPLEFT] = 1;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 2;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 3;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPRIGHT] = 4;
|
||||
g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 5;
|
||||
break;
|
||||
DEFAULT_FAIL( out.m_StepsType );
|
||||
}
|
||||
|
||||
int iNumFeet = StringToInt(sNumFeet);
|
||||
// out.SetDescription(sDescription); // Don't put garbage in the description.
|
||||
out.SetMeter(iNumFeet);
|
||||
out.SetDifficulty( DwiCompatibleStringToDifficulty(sDescription) );
|
||||
|
||||
NoteData newNoteData;
|
||||
newNoteData.SetNumTracks( g_mapDanceNoteToNoteDataColumn.size() );
|
||||
|
||||
for( int pad=0; pad<2; pad++ ) // foreach pad
|
||||
{
|
||||
RString sStepData;
|
||||
switch( pad )
|
||||
{
|
||||
case 0:
|
||||
sStepData = sStepData1;
|
||||
break;
|
||||
case 1:
|
||||
if( sStepData2 == "" ) // no data
|
||||
continue; // skip
|
||||
sStepData = sStepData2;
|
||||
break;
|
||||
DEFAULT_FAIL( pad );
|
||||
}
|
||||
|
||||
sStepData.Replace("\n", "");
|
||||
sStepData.Replace("\r", "");
|
||||
sStepData.Replace("\t", "");
|
||||
sStepData.Replace(" ", "");
|
||||
|
||||
double fCurrentBeat = 0;
|
||||
double fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
|
||||
|
||||
for( size_t i=0; i<sStepData.size(); )
|
||||
{
|
||||
char c = sStepData[i++];
|
||||
switch( c )
|
||||
{
|
||||
// begins a series
|
||||
case '(':
|
||||
fCurrentIncrementer = 1.0/16 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
case '[':
|
||||
fCurrentIncrementer = 1.0/24 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
case '{':
|
||||
fCurrentIncrementer = 1.0/64 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
case '`':
|
||||
fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
|
||||
// ends a series
|
||||
case ')':
|
||||
case ']':
|
||||
case '}':
|
||||
case '\'':
|
||||
case '>':
|
||||
fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
|
||||
default: // this is a note character
|
||||
{
|
||||
if( c == '!' )
|
||||
{
|
||||
LOG->UserLog( "Song file", sPath, "has an unexpected character: '!'." );
|
||||
continue;
|
||||
}
|
||||
|
||||
bool jump = false;
|
||||
if( c == '<' )
|
||||
{
|
||||
/* Arr. Is this a jump or a 1/192 marker? */
|
||||
if( Is192( sStepData, i ) )
|
||||
{
|
||||
fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* It's a jump. We need to keep reading notes until we hit a >. */
|
||||
jump = true;
|
||||
i++;
|
||||
}
|
||||
|
||||
const int iIndex = BeatToNoteRow( (float)fCurrentBeat );
|
||||
i--;
|
||||
do {
|
||||
c = sStepData[i++];
|
||||
|
||||
if( jump && c == '>' )
|
||||
break;
|
||||
|
||||
int iCol1, iCol2;
|
||||
DWIcharToNoteCol( c, (GameController)pad, iCol1, iCol2, sPath );
|
||||
|
||||
if( iCol1 != -1 )
|
||||
newNoteData.SetTapNote(iCol1, iIndex, TAP_ORIGINAL_TAP);
|
||||
if( iCol2 != -1 )
|
||||
newNoteData.SetTapNote(iCol2, iIndex, TAP_ORIGINAL_TAP);
|
||||
|
||||
if(i>=sStepData.length()) {
|
||||
break;//we ran out of data while looking for the ending > mark
|
||||
}
|
||||
|
||||
if( sStepData[i] == '!' )
|
||||
{
|
||||
i++;
|
||||
const char holdChar = sStepData[i++];
|
||||
|
||||
DWIcharToNoteCol( holdChar, (GameController)pad, iCol1, iCol2, sPath );
|
||||
|
||||
if( iCol1 != -1 )
|
||||
newNoteData.SetTapNote(iCol1, iIndex, TAP_ORIGINAL_HOLD_HEAD);
|
||||
if( iCol2 != -1 )
|
||||
newNoteData.SetTapNote(iCol2, iIndex, TAP_ORIGINAL_HOLD_HEAD);
|
||||
}
|
||||
}
|
||||
while( jump );
|
||||
fCurrentBeat += fCurrentIncrementer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in iDuration. */
|
||||
for( int t=0; t<newNoteData.GetNumTracks(); ++t )
|
||||
{
|
||||
FOREACH_NONEMPTY_ROW_IN_TRACK( newNoteData, t, iHeadRow )
|
||||
{
|
||||
TapNote tn = newNoteData.GetTapNote( t, iHeadRow );
|
||||
if( tn.type != TapNote::hold_head )
|
||||
continue;
|
||||
|
||||
int iTailRow = iHeadRow;
|
||||
bool bFound = false;
|
||||
while( !bFound && newNoteData.GetNextTapNoteRowForTrack(t, iTailRow) )
|
||||
{
|
||||
const TapNote &TailTap = newNoteData.GetTapNote( t, iTailRow );
|
||||
if( TailTap.type == TapNote::empty )
|
||||
continue;
|
||||
|
||||
newNoteData.SetTapNote( t, iTailRow, TAP_EMPTY );
|
||||
tn.iDuration = iTailRow - iHeadRow;
|
||||
newNoteData.SetTapNote( t, iHeadRow, tn );
|
||||
bFound = true;
|
||||
}
|
||||
|
||||
if( !bFound )
|
||||
{
|
||||
/* The hold was never closed. */
|
||||
LOG->UserLog( "Song file", sPath, "failed to close a hold note in \"%s\" on track %i",
|
||||
sDescription.c_str(), t );
|
||||
|
||||
newNoteData.SetTapNote( t, iHeadRow, TAP_EMPTY );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT( newNoteData.GetNumTracks() > 0 );
|
||||
|
||||
out.SetNoteData( newNoteData );
|
||||
|
||||
out.SetNoteData( ParseNoteData(sStepData1, sStepData2, out, sPath) );
|
||||
|
||||
out.TidyUpData();
|
||||
|
||||
out.SetSavedToDisk( true ); // we're loading from disk, so this is by definintion already saved
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -444,17 +477,55 @@ void DWILoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
GetDirListing( sPath + RString("*.dwi"), out );
|
||||
}
|
||||
|
||||
bool DWILoader::LoadNoteDataFromSimfile( const RString &path, Steps &out )
|
||||
{
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( path, false ) ) // don't unescape
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
path,
|
||||
"couldn't be opened: %s",
|
||||
msd.GetError().c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
for( unsigned i=0; i<msd.GetNumValues(); i++ )
|
||||
{
|
||||
int iNumParams = msd.GetNumParams(i);
|
||||
const MsdFile::value_t ¶ms = msd.GetValue(i);
|
||||
RString valueName = params[0];
|
||||
|
||||
if(valueName.EqualsNoCase("SINGLE") ||
|
||||
valueName.EqualsNoCase("DOUBLE") ||
|
||||
valueName.EqualsNoCase("COUPLE") ||
|
||||
valueName.EqualsNoCase("SOLO") )
|
||||
{
|
||||
if (out.m_StepsType != GetTypeFromMode(valueName))
|
||||
continue;
|
||||
if (out.GetDifficulty() != DwiCompatibleStringToDifficulty(params[1]))
|
||||
continue;
|
||||
if (out.GetMeter() != StringToInt(params[2]))
|
||||
continue;
|
||||
RString step1 = params[3];
|
||||
RString step2 = (iNumParams==5) ? params[4] : RString("");
|
||||
out.SetNoteData(ParseNoteData(step1, step2, out, path));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &BlacklistedImages )
|
||||
{
|
||||
vector<RString> aFileNames;
|
||||
GetApplicableFiles( sPath_, aFileNames );
|
||||
|
||||
|
||||
if( aFileNames.size() > 1 )
|
||||
{
|
||||
LOG->UserLog( "Song", sPath_, "has more than one DWI file. There should be only one!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* We should have exactly one; if we had none, we shouldn't have been called to begin with. */
|
||||
ASSERT( aFileNames.size() == 1 );
|
||||
const RString sPath = sPath_ + aFileNames[0];
|
||||
@@ -468,6 +539,8 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
|
||||
return false;
|
||||
}
|
||||
|
||||
out.m_sSongFileName = sPath;
|
||||
|
||||
for( unsigned i=0; i<msd.GetNumValues(); i++ )
|
||||
{
|
||||
int iNumParams = msd.GetNumParams(i);
|
||||
@@ -515,14 +588,16 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
|
||||
|
||||
if( PREFSMAN->m_bQuirksMode )
|
||||
{
|
||||
out.m_SongTiming.AddBPMSegment( BPMSegment(0, fBPM) );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, fBPM) );
|
||||
}
|
||||
else{
|
||||
if( fBPM > 0.0f )
|
||||
out.m_SongTiming.AddBPMSegment( BPMSegment(0, fBPM) );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, fBPM) );
|
||||
else
|
||||
LOG->UserLog( "Song file", sPath, "has an invalid BPM change at beat %f, BPM %f.",
|
||||
NoteRowToBeat(0), fBPM );
|
||||
LOG->UserLog("Song file",
|
||||
sPath,
|
||||
"has an invalid BPM change at beat %f, BPM %f.",
|
||||
0.0f, fBPM );
|
||||
}
|
||||
}
|
||||
else if( sValueName.EqualsNoCase("DISPLAYBPM") )
|
||||
@@ -576,7 +651,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
|
||||
int iFreezeRow = BeatToNoteRow( StringToFloat(arrayFreezeValues[0]) / 4.0f );
|
||||
float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ) / 1000.0f;
|
||||
|
||||
out.m_SongTiming.AddStopSegment( StopSegment(iFreezeRow, fFreezeSeconds) );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_STOP_DELAY, new StopSegment(iFreezeRow, fFreezeSeconds) );
|
||||
// LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds );
|
||||
}
|
||||
}
|
||||
@@ -600,8 +675,8 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
|
||||
float fBPM = StringToFloat( arrayBPMChangeValues[1] );
|
||||
if( fBPM > 0.0f )
|
||||
{
|
||||
BPMSegment bs( iStartIndex, fBPM );
|
||||
out.m_SongTiming.AddBPMSegment( bs );
|
||||
BPMSegment * bs = new BPMSegment( iStartIndex, fBPM );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_BPM, bs );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -627,7 +702,10 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
|
||||
sPath
|
||||
);
|
||||
if( pNewNotes->m_StepsType != StepsType_Invalid )
|
||||
{
|
||||
pNewNotes->SetFilename( sPath );
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
else
|
||||
delete pNewNotes;
|
||||
}
|
||||
@@ -662,7 +740,6 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
|
||||
// do nothing. We don't care about this value name
|
||||
}
|
||||
}
|
||||
out.TidyUpData();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <set>
|
||||
|
||||
class Song;
|
||||
class Steps;
|
||||
|
||||
/** @brief The DWILoader handles parsing the .dwi file. */
|
||||
namespace DWILoader
|
||||
@@ -24,6 +25,8 @@ namespace DWILoader
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromDir( const RString &sPath, Song &out, set<RString> &BlacklistedImages );
|
||||
|
||||
bool LoadNoteDataFromSimfile( const RString &path, Steps &out );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+23
-13
@@ -10,29 +10,39 @@
|
||||
#include "Steps.h"
|
||||
#include "GameManager.h"
|
||||
|
||||
void Deserialize(BPMSegment &seg, const Json::Value &root);
|
||||
|
||||
void NotesLoaderJson::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
{
|
||||
GetDirListing( sPath + RString("*.json"), out );
|
||||
}
|
||||
|
||||
void Deserialize(BPMSegment &seg, const Json::Value &root)
|
||||
static void Deserialize(TimingSegment &seg_, const Json::Value &root)
|
||||
{
|
||||
seg.SetBeat((float)(root["Beat"].asDouble()));
|
||||
seg.SetBPM((float)(root["BPM"].asDouble()));
|
||||
}
|
||||
|
||||
static void Deserialize(StopSegment &seg, const Json::Value &root)
|
||||
{
|
||||
seg.SetBeat((float)(root["Beat"].asDouble()));
|
||||
seg.SetPause((float)(root["Seconds"].asDouble()));
|
||||
TimingSegment *seg = &seg_;
|
||||
|
||||
float fBeat = root["Beat"].asDouble();
|
||||
seg->SetBeat(fBeat);
|
||||
switch (seg->GetType())
|
||||
{
|
||||
case SEGMENT_BPM:
|
||||
{
|
||||
float fBPM = root["BPM"].asDouble();
|
||||
static_cast<BPMSegment *>(seg)->SetBPM(fBPM);
|
||||
break;
|
||||
}
|
||||
case SEGMENT_STOP_DELAY:
|
||||
{
|
||||
float fStop = root["Seconds"].asDouble();
|
||||
static_cast<StopSegment *>(seg)->SetPause(fStop);
|
||||
break;
|
||||
}
|
||||
default: break; // The rest are unused.
|
||||
}
|
||||
}
|
||||
|
||||
static void Deserialize(TimingData &td, const Json::Value &root)
|
||||
{
|
||||
JsonUtil::DeserializeVectorObjects( td.m_BPMSegments, Deserialize, root["BpmSegments"] );
|
||||
JsonUtil::DeserializeVectorObjects( td.m_StopSegments, Deserialize, root["StopSegments"] );
|
||||
JsonUtil::DeserializeVectorPointers( td.allTimingSegments[SEGMENT_BPM], Deserialize, root["BpmSegments"] );
|
||||
JsonUtil::DeserializeVectorPointers( td.allTimingSegments[SEGMENT_STOP_DELAY], Deserialize, root["StopSegments"] );
|
||||
}
|
||||
|
||||
static void Deserialize(LyricSegment &o, const Json::Value &root)
|
||||
|
||||
+95
-85
@@ -17,10 +17,10 @@ static void HandleBunki( TimingData &timing, const float fEarlyBPM,
|
||||
const float beat = (fPos + fGap) * BeatsPerSecond;
|
||||
LOG->Trace( "BPM %f, BPS %f, BPMPos %f, beat %f",
|
||||
fEarlyBPM, BeatsPerSecond, fPos, beat );
|
||||
timing.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), fCurBPM) );
|
||||
timing.AddSegment( SEGMENT_BPM, new BPMSegment(beat, fCurBPM) );
|
||||
}
|
||||
|
||||
static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, bool bKIUCompliant )
|
||||
static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool bKIUCompliant )
|
||||
{
|
||||
LOG->Trace( "Steps::LoadFromKSFFile( '%s' )", sPath.c_str() );
|
||||
|
||||
@@ -54,13 +54,12 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
if (sValueName=="TITLE" || EndsWith(sValueName, "INTRO")
|
||||
|| EndsWith(sValueName, "FILE") )
|
||||
{
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
else if( sValueName=="BPM" )
|
||||
{
|
||||
BPM1 = StringToFloat(sParams[1]);
|
||||
stepsTiming.AddBPMSegment( BPMSegment(0, BPM1) );
|
||||
stepsTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, BPM1) );
|
||||
}
|
||||
else if( sValueName=="BPM2" )
|
||||
{
|
||||
@@ -137,7 +136,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
LOG->UserLog( "Song file", sPath, "has an invalid tick count: %d.", iTickCount );
|
||||
return false;
|
||||
}
|
||||
stepsTiming.AddTickcountSegment(TickcountSegment(0, iTickCount));
|
||||
stepsTiming.AddSegment( SEGMENT_TICKCOUNT, new TickcountSegment(0, iTickCount));
|
||||
}
|
||||
|
||||
else if( sValueName=="DIFFICULTY" )
|
||||
@@ -195,28 +194,43 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
out.SetDifficulty( Difficulty_Edit );
|
||||
if( !out.GetMeter() ) out.SetMeter( 25 );
|
||||
}
|
||||
else if( sFName.find("wild") != string::npos || sFName.find("wd") != string::npos || sFName.find("crazy+") != string::npos || sFName.find("cz+") != string::npos || sFName.find("hardcore") != string::npos )
|
||||
else if(sFName.find("wild") != string::npos ||
|
||||
sFName.find("wd") != string::npos ||
|
||||
sFName.find("crazy+") != string::npos ||
|
||||
sFName.find("cz+") != string::npos ||
|
||||
sFName.find("hardcore") != string::npos )
|
||||
{
|
||||
out.SetDifficulty( Difficulty_Challenge );
|
||||
if( !out.GetMeter() ) out.SetMeter( 20 );
|
||||
}
|
||||
else if( sFName.find("crazy") != string::npos || sFName.find("cz") != string::npos || sFName.find("nightmare") != string::npos || sFName.find("nm") != string::npos || sFName.find("crazydouble") != string::npos )
|
||||
else if(sFName.find("crazy") != string::npos ||
|
||||
sFName.find("cz") != string::npos ||
|
||||
sFName.find("nightmare") != string::npos ||
|
||||
sFName.find("nm") != string::npos ||
|
||||
sFName.find("crazydouble") != string::npos )
|
||||
{
|
||||
out.SetDifficulty( Difficulty_Hard );
|
||||
if( !out.GetMeter() ) out.SetMeter( 14 ); // Set the meters to the Pump scale, not DDR.
|
||||
}
|
||||
else if( sFName.find("hard") != string::npos || sFName.find("hd") != string::npos || sFName.find("freestyle") != string::npos || sFName.find("fs") != string::npos || sFName.find("double") != string::npos )
|
||||
else if(sFName.find("hard") != string::npos ||
|
||||
sFName.find("hd") != string::npos ||
|
||||
sFName.find("freestyle") != string::npos ||
|
||||
sFName.find("fs") != string::npos ||
|
||||
sFName.find("double") != string::npos )
|
||||
{
|
||||
out.SetDifficulty( Difficulty_Medium );
|
||||
if( !out.GetMeter() ) out.SetMeter( 8 );
|
||||
}
|
||||
else if( sFName.find("easy") != string::npos || sFName.find("ez") != string::npos || sFName.find("normal") != string::npos )
|
||||
else if(sFName.find("easy") != string::npos ||
|
||||
sFName.find("ez") != string::npos ||
|
||||
sFName.find("normal") != string::npos )
|
||||
{
|
||||
// I wonder if I should leave easy fall into the Beginner difficulty... -DaisuMaster
|
||||
out.SetDifficulty( Difficulty_Easy );
|
||||
if( !out.GetMeter() ) out.SetMeter( 4 );
|
||||
}
|
||||
else if( sFName.find("beginner") != string::npos || sFName.find("practice") != string::npos || sFName.find("pr") != string::npos )
|
||||
else if(sFName.find("beginner") != string::npos ||
|
||||
sFName.find("practice") != string::npos || sFName.find("pr") != string::npos )
|
||||
{
|
||||
out.SetDifficulty( Difficulty_Beginner );
|
||||
if( !out.GetMeter() ) out.SetMeter( 4 );
|
||||
@@ -230,10 +244,18 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
out.m_StepsType = StepsType_pump_single;
|
||||
|
||||
// Check for "halfdouble" before "double".
|
||||
if( sFName.find("halfdouble") != string::npos || sFName.find("half-double") != string::npos || sFName.find("h_double") != string::npos || sFName.find("hdb") != string::npos )
|
||||
if(sFName.find("halfdouble") != string::npos ||
|
||||
sFName.find("half-double") != string::npos ||
|
||||
sFName.find("h_double") != string::npos ||
|
||||
sFName.find("hdb") != string::npos )
|
||||
out.m_StepsType = StepsType_pump_halfdouble;
|
||||
// Handle bDoublesChart from above as well. -aj
|
||||
else if( sFName.find("double") != string::npos || sFName.find("nightmare") != string::npos || sFName.find("freestyle") != string::npos || sFName.find("db") != string::npos || sFName.find("nm") != string::npos || sFName.find("fs") != string::npos || bDoublesChart )
|
||||
else if(sFName.find("double") != string::npos ||
|
||||
sFName.find("nightmare") != string::npos ||
|
||||
sFName.find("freestyle") != string::npos ||
|
||||
sFName.find("db") != string::npos ||
|
||||
sFName.find("nm") != string::npos ||
|
||||
sFName.find("fs") != string::npos || bDoublesChart )
|
||||
out.m_StepsType = StepsType_pump_double;
|
||||
else if( sFName.find("_1") != string::npos )
|
||||
out.m_StepsType = StepsType_pump_single;
|
||||
@@ -280,19 +302,31 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
if( iHoldStartRow[t] == BeatToNoteRow(prevBeat) )
|
||||
notedata.SetTapNote( t, iHoldStartRow[t], TAP_ORIGINAL_TAP );
|
||||
else
|
||||
notedata.AddHoldNote( t, iHoldStartRow[t], BeatToNoteRow(prevBeat) , TAP_ORIGINAL_HOLD_HEAD );
|
||||
notedata.AddHoldNote(t,
|
||||
iHoldStartRow[t],
|
||||
BeatToNoteRow(prevBeat),
|
||||
TAP_ORIGINAL_HOLD_HEAD );
|
||||
}
|
||||
}
|
||||
/* have this row be the last moment in the song, unless
|
||||
* a future step ends later. */
|
||||
float curTime = stepsTiming.GetElapsedTimeFromBeat(fCurBeat);
|
||||
if (curTime > song.GetSpecifiedLastSecond())
|
||||
{
|
||||
song.SetSpecifiedLastSecond(curTime);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
else if( BeginsWith(sRowString, "|") )
|
||||
{
|
||||
/*
|
||||
if (bKIUCompliant)
|
||||
{
|
||||
// Log an error, ignore the line.
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
// gotta do something tricky here: if the bpm is below one then a couple of calculations
|
||||
// for scrollsegments will be made, example, bpm 0.2, tick 4000, the scrollsegment will
|
||||
// be 0. if the tickcount is non a stepmania standard then it will be adapted, a scroll
|
||||
@@ -300,6 +334,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
// eh better do it considering the tickcount (high tickcounts)
|
||||
|
||||
// I'm making some experiments, please spare me...
|
||||
//continue;
|
||||
|
||||
RString temp = sRowString.substr(2,sRowString.size()-3);
|
||||
float numTemp = StringToFloat(temp);
|
||||
@@ -307,53 +342,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
{
|
||||
// duh
|
||||
iTickCount = static_cast<int>(numTemp);
|
||||
//if( iTickCount > ROWS_PER_BEAT )
|
||||
|
||||
/* adapt tickcounts //
|
||||
// valid tickcounts for SM: 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 64, ROWS_PER_BEAT
|
||||
// put this inside the tickcount handling condition yes/no
|
||||
|
||||
if( iTickCount > ROWS_PER_BEAT ) // beyond 48
|
||||
{
|
||||
// clamp/scale/whatever and use scroll segments
|
||||
}
|
||||
else if( iTickCount > 32 || iTickCount < ROWS_PER_BEAT ) // ranging from 33 to 48, approximate to 32
|
||||
{
|
||||
fScrollRatio = 32;
|
||||
iTickCount = 32;
|
||||
}
|
||||
else if( iTickCount > 24 || iTickCount < 32 ) // ranging from 25 to 31, approximate to 24
|
||||
{
|
||||
fScrollRatio = 24;
|
||||
iTickCount = 24;
|
||||
}
|
||||
else if( iTickCount > 16 || iTickCount < 24 ) // ranging from 17 to 23, approximate to 16
|
||||
{
|
||||
fScrollRatio = 16;
|
||||
iTickCount = 16;
|
||||
}
|
||||
else if( iTickCount > 12 || iTickCount < 16 ) // ranging from 13 to 15, approximate to 12
|
||||
{
|
||||
fScrollRatio = 12;
|
||||
iTickCount = 12;
|
||||
}
|
||||
else if( iTickCount > 8 || iTickCount < 12 ) // ranging from 9 to 11, approximate to 8
|
||||
{
|
||||
fScrollRatio = 8;
|
||||
iTickCount = 8;
|
||||
}
|
||||
else if( iTickCount > 6 || iTickCount < 8 ) // 7, approximate to 6
|
||||
{
|
||||
fScrollRatio = 6 / iTickCountt;
|
||||
iTickCount = 6;
|
||||
}
|
||||
else if( iTickCount > 4 || iTickCount < 6 ) // 5, approximate to 4
|
||||
{
|
||||
fScrollRatio = iTickCount / 4;
|
||||
iTickCount = 4;
|
||||
}
|
||||
//*/
|
||||
|
||||
// I have been owned by the man -DaisuMaster
|
||||
stepsTiming.SetTickcountAtBeat( fCurBeat, clamp(iTickCount, 0, ROWS_PER_BEAT) );
|
||||
}
|
||||
else if (BeginsWith(sRowString, "|B"))
|
||||
@@ -392,7 +381,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
|
||||
{
|
||||
// scroll segments
|
||||
stepsTiming.SetScrollAtBeat( fCurBeat, numTemp );
|
||||
return true;
|
||||
//return true;
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -516,7 +505,21 @@ static void LoadTags( const RString &str, Song &out )
|
||||
out.m_sArtist = artist;
|
||||
}
|
||||
|
||||
static bool LoadGlobalData( const RString &sPath, Song &out, bool bKIUCompliant )
|
||||
static void ProcessTickcounts( const RString & value, int & ticks, TimingData & timing )
|
||||
{
|
||||
/* TICKCOUNT will be used below if there are DM compliant BPM changes
|
||||
* and stops. It will be called again in LoadFromKSFFile for the
|
||||
* actual steps. */
|
||||
ticks = StringToInt( value );
|
||||
ticks = ticks > 0 ? ticks : 4;
|
||||
// add a tickcount for those using the [Player]
|
||||
// CheckpointsUseTimeSignatures metric. -aj
|
||||
// It's not with timesigs now -DaisuMaster
|
||||
TickcountSegment * tcs = new TickcountSegment(0, ticks > ROWS_PER_BEAT ? ROWS_PER_BEAT : ticks);
|
||||
timing.AddSegment( SEGMENT_TICKCOUNT, tcs );
|
||||
}
|
||||
|
||||
static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant )
|
||||
{
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( sPath, false ) ) // don't unescape
|
||||
@@ -554,7 +557,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool bKIUCompliant
|
||||
else if( sValueName=="BPM" )
|
||||
{
|
||||
BPM1 = StringToFloat(sParams[1]);
|
||||
out.m_SongTiming.AddBPMSegment( BPMSegment(0, BPM1) );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, BPM1) );
|
||||
}
|
||||
else if( sValueName=="BPM2" )
|
||||
{
|
||||
@@ -590,21 +593,11 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool bKIUCompliant
|
||||
else if ( sValueName=="STARTTIME3" )
|
||||
{
|
||||
// STARTTIME3 only ensures this is a KIU compliant simfile.
|
||||
bKIUCompliant = true;
|
||||
//bKIUCompliant = true;
|
||||
}
|
||||
else if ( sValueName=="TICKCOUNT" )
|
||||
{
|
||||
/* TICKCOUNT will be used below if there are DM compliant BPM changes
|
||||
* and stops. It will be called again in LoadFromKSFFile for the
|
||||
* actual steps. */
|
||||
iTickCount = StringToInt( sParams[1] );
|
||||
iTickCount = iTickCount > 0 ? iTickCount : 4;
|
||||
// add a tickcount for those using the [Player]
|
||||
// CheckpointsUseTimeSignatures metric. -aj
|
||||
// It's not with timesigs now -DaisuMaster
|
||||
TickcountSegment tcs(0);
|
||||
tcs.SetTicks(iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount);
|
||||
out.m_SongTiming.AddTickcountSegment( tcs );
|
||||
ProcessTickcounts(sParams[1], iTickCount, out.m_SongTiming);
|
||||
}
|
||||
else if ( sValueName=="STEP" )
|
||||
{
|
||||
@@ -614,10 +607,10 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool bKIUCompliant
|
||||
TrimLeft( theSteps );
|
||||
split( theSteps, "\n", vNoteRows, true );
|
||||
}
|
||||
|
||||
else if( sValueName=="DIFFICULTY" )
|
||||
else if( sValueName=="DIFFICULTY" || sValueName=="PLAYER" )
|
||||
{
|
||||
/* DIFFICULTY is handled only in LoadFromKSFFile. Ignore it here. */
|
||||
/* DIFFICULTY and PLAYER are handled only in LoadFromKSFFile.
|
||||
Ignore those here. */
|
||||
continue;
|
||||
}
|
||||
// New cases noted in Aldo_MX's code:
|
||||
@@ -689,7 +682,6 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool bKIUCompliant
|
||||
}
|
||||
|
||||
// This is where the DMRequired test will take place.
|
||||
//if (BeginsWith(NoteRowString, "|T") || BeginsWith(NoteRowString, "|B") || BeginsWith(NoteRowString, "|D") || BeginsWith(NoteRowString, "|E") )
|
||||
if ( BeginsWith( NoteRowString, "|" ) )
|
||||
{
|
||||
// have a static timing for everything
|
||||
@@ -723,6 +715,22 @@ void KSFLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
GetDirListing( sPath + RString("*.ksf"), out );
|
||||
}
|
||||
|
||||
bool KSFLoader::LoadNoteDataFromSimfile( const RString & cachePath, Steps &out )
|
||||
{
|
||||
bool KIUCompliant = false;
|
||||
Song dummy;
|
||||
if (!LoadGlobalData(cachePath, dummy, KIUCompliant))
|
||||
return false;
|
||||
Steps *notes = dummy.CreateSteps();
|
||||
if (LoadFromKSFFile(cachePath, *notes, dummy, KIUCompliant))
|
||||
{
|
||||
KIUCompliant = true; // yeah, reusing a variable.
|
||||
out.SetNoteData(notes->GetNoteData());
|
||||
}
|
||||
delete notes;
|
||||
return KIUCompliant;
|
||||
}
|
||||
|
||||
bool KSFLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
{
|
||||
LOG->Trace( "KSFLoader::LoadFromDir(%s)", sDir.c_str() );
|
||||
@@ -733,7 +741,7 @@ bool KSFLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
// We shouldn't have been called to begin with if there were no KSFs.
|
||||
ASSERT( arrayKSFFileNames.size() );
|
||||
|
||||
//bool bKIUCompliant = false;
|
||||
bool bKIUCompliant = false;
|
||||
/* With Split Timing, there has to be a backup Song Timing in case
|
||||
* anything goes wrong. As these files are kept in alphabetical
|
||||
* order (hopefully), it is best to use the LAST file for timing
|
||||
@@ -751,22 +759,24 @@ bool KSFLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
// for directmove though, and we're just gathering basic info anyway, and
|
||||
// most of the time all the KSF files have the same info in the #TITLE:; section
|
||||
unsigned files = arrayKSFFileNames.size();
|
||||
if( !LoadGlobalData(out.GetSongDir() + arrayKSFFileNames[0], out, false) )
|
||||
RString dir = out.GetSongDir();
|
||||
if( !LoadGlobalData(dir + arrayKSFFileNames[files - 1], out, bKIUCompliant) )
|
||||
return false;
|
||||
|
||||
out.m_sSongFileName = dir + arrayKSFFileNames[files - 1];
|
||||
// load the Steps from the rest of the KSF files
|
||||
for( unsigned i=0; i<files; i++ )
|
||||
{
|
||||
Steps* pNewNotes = out.CreateSteps();
|
||||
if( !LoadFromKSFFile(out.GetSongDir() + arrayKSFFileNames[i], *pNewNotes, out, false) )
|
||||
if( !LoadFromKSFFile(dir + arrayKSFFileNames[i], *pNewNotes, out, bKIUCompliant) )
|
||||
{
|
||||
delete pNewNotes;
|
||||
continue;
|
||||
}
|
||||
|
||||
pNewNotes->SetFilename(dir + arrayKSFFileNames[i]);
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
out.TidyUpData();
|
||||
out.TidyUpData(false, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
#define NOTES_LOADER_KSF_H
|
||||
|
||||
class Song;
|
||||
class Steps;
|
||||
/** @brief Reads a Song from a set of .KSF files. */
|
||||
namespace KSFLoader
|
||||
{
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
bool LoadFromDir( const RString &sDir, Song &out );
|
||||
bool LoadNoteDataFromSimfile( const RString & cachePath, Steps &out );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+17
-13
@@ -677,21 +677,22 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
|
||||
|
||||
FOREACH_CONST( MidiFileIn::TempoChange, midi.tempoEvents_, iter )
|
||||
{
|
||||
BPMSegment bpmSeg;
|
||||
bpmSeg.SetRow( MidiCountToNoteRow( iter->count ) );
|
||||
BPMSegment * bpmSeg = NULL;
|
||||
bpmSeg->SetRow( MidiCountToNoteRow( iter->count ) );
|
||||
double fSecondsPerBeat = (iter->tickSeconds * GUITAR_MIDI_COUNTS_PER_BEAT);
|
||||
bpmSeg.SetBPS( float( 1. / fSecondsPerBeat ) );
|
||||
bpmSeg->SetBPS( float( 1. / fSecondsPerBeat ) );
|
||||
|
||||
songOut.m_SongTiming.AddBPMSegment( bpmSeg );
|
||||
songOut.m_SongTiming.AddSegment( SEGMENT_BPM, bpmSeg );
|
||||
}
|
||||
|
||||
FOREACH_CONST( MidiFileIn::TimeSignatureChange, midi.timeSignatureEvents_, iter )
|
||||
{
|
||||
TimeSignatureSegment seg(MidiCountToNoteRow( iter->count ),
|
||||
iter->numerator,
|
||||
iter->denominator);
|
||||
TimeSignatureSegment * seg =
|
||||
new TimeSignatureSegment(MidiCountToNoteRow( iter->count ),
|
||||
iter->numerator,
|
||||
iter->denominator);
|
||||
|
||||
songOut.m_SongTiming.AddTimeSignatureSegment( seg );
|
||||
songOut.m_SongTiming.AddSegment( SEGMENT_TIME_SIG, seg );
|
||||
}
|
||||
|
||||
|
||||
@@ -816,8 +817,8 @@ skip_track:
|
||||
// Check for termination of a sustain note
|
||||
switch( midiEventType )
|
||||
{
|
||||
case note_off:
|
||||
case note_on:
|
||||
case note_off:
|
||||
case note_on:
|
||||
if( bNonTerminatedNote )
|
||||
{
|
||||
if( length >= 240 )
|
||||
@@ -832,14 +833,15 @@ skip_track:
|
||||
|
||||
bNonTerminatedNote = false;
|
||||
bNoteHandled = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
switch( midiEventType )
|
||||
{
|
||||
case note_on:
|
||||
case note_on:
|
||||
{
|
||||
TapNote tn = TAP_ORIGINAL_TAP;
|
||||
|
||||
@@ -866,7 +868,9 @@ skip_track:
|
||||
|
||||
bNonTerminatedNote = true;
|
||||
bNoteHandled = true;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
countOfLastNote = count;
|
||||
@@ -955,7 +959,7 @@ bool MidiLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
if( !LoadFromMidi(sDir+vsFiles[0], out) )
|
||||
return false;
|
||||
|
||||
out.TidyUpData();
|
||||
out.TidyUpData(false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+84
-18
@@ -573,7 +573,7 @@ static bool LoadFromPMSFile( const RString &sPath, const NameToData_t &mapNameTo
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, MeasureToTimeSig_t &sigAdjustmentsOut, map<RString,int> &idToKeySoundIndexOut )
|
||||
static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToData, Song &out, MeasureToTimeSig_t &sigAdjustmentsOut, map<RString,int> &idToKeySoundIndexOut )
|
||||
{
|
||||
RString sData;
|
||||
if( GetTagFromMap(mapNameToData, "#title", sData) )
|
||||
@@ -590,8 +590,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
|
||||
|
||||
if( fBPM > 0.0f )
|
||||
{
|
||||
BPMSegment newSeg( 0, fBPM );
|
||||
out.m_SongTiming.AddBPMSegment( newSeg );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, fBPM) );
|
||||
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
|
||||
}
|
||||
else
|
||||
@@ -612,26 +611,29 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
|
||||
// this is keysound file name. Looks like "#WAV1A"
|
||||
RString nData = it->second;
|
||||
RString sWavID = sName.Right(2);
|
||||
RString dir = out.GetSongDir();
|
||||
if (dir.empty())
|
||||
dir = Dirname(sPath);
|
||||
|
||||
/* Due to bugs in some programs, many PMS files have a "WAV" extension
|
||||
* on files in the PMS for files that actually have some other extension.
|
||||
* Do a search. Don't do a wildcard search; if sData is "song.wav",
|
||||
* we might also have "song.png", which we shouldn't match. */
|
||||
if( !IsAFile(out.GetSongDir()+nData) )
|
||||
if( !IsAFile(dir+nData) )
|
||||
{
|
||||
const char *exts[] = { "oga", "ogg", "wav", "mp3", NULL }; // XXX: stop duplicating these everywhere
|
||||
for( unsigned i = 0; exts[i] != NULL; ++i )
|
||||
{
|
||||
RString fn = SetExtension( nData, exts[i] );
|
||||
if( IsAFile(out.GetSongDir()+fn) )
|
||||
if( IsAFile(dir+fn) )
|
||||
{
|
||||
nData = fn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !IsAFile(out.GetSongDir()+nData) )
|
||||
LOG->UserLog( "Song file", out.GetSongDir(), "references key \"%s\" that can't be found", nData.c_str() );
|
||||
if( !IsAFile(dir+nData) )
|
||||
LOG->UserLog( "Song file", dir, "references key \"%s\" that can't be found", nData.c_str() );
|
||||
|
||||
sWavID.MakeUpper(); // HACK: undo the MakeLower()
|
||||
out.m_vsKeysoundFile.push_back( nData );
|
||||
@@ -693,9 +695,9 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
|
||||
|
||||
if( fBPM > 0.0f )
|
||||
{
|
||||
BPMSegment newSeg( BeatToNoteRow(fBeat), fBPM );
|
||||
out.m_SongTiming.AddBPMSegment( newSeg );
|
||||
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg.GetBPM() );
|
||||
BPMSegment * newSeg = new BPMSegment( fBeat, fBPM );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_BPM, newSeg );
|
||||
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg->GetBPM() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -720,9 +722,9 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
|
||||
float fBeats = StringToFloat( sBeats ) / 48.0f;
|
||||
float fFreezeSecs = fBeats / fBPS;
|
||||
|
||||
StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs );
|
||||
out.m_SongTiming.AddStopSegment( newSeg );
|
||||
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.GetPause() );
|
||||
StopSegment * newSeg = new StopSegment( fBeat, fFreezeSecs );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_STOP_DELAY, newSeg );
|
||||
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg->GetPause() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -749,9 +751,11 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
|
||||
|
||||
if( fBPM > 0.0f )
|
||||
{
|
||||
BPMSegment newSeg( iStepIndex, fBPM );
|
||||
out.m_SongTiming.AddBPMSegment( newSeg );
|
||||
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", newSeg.GetBeat(), newSeg.GetBPM() );
|
||||
BPMSegment * newSeg = new BPMSegment( iStepIndex, fBPM );
|
||||
out.m_SongTiming.AddSegment( SEGMENT_BPM, newSeg );
|
||||
LOG->Trace("Inserting new BPM change at beat %f, BPM %f",
|
||||
newSeg->GetBeat(),
|
||||
newSeg->GetBPM() );
|
||||
|
||||
}
|
||||
else
|
||||
@@ -809,6 +813,64 @@ void PMSLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
GetDirListing( sPath + RString("*.pms"), out );
|
||||
}
|
||||
|
||||
bool PMSLoader::LoadNoteDataFromSimfile(const RString &cachePath, Steps &out)
|
||||
{
|
||||
Song dummy;
|
||||
// TODO: Simplify this copy/paste from LoadFromDir.
|
||||
|
||||
vector<NameToData_t> BMSData;
|
||||
BMSData.push_back(NameToData_t());
|
||||
ReadPMSFile(cachePath, BMSData.back());
|
||||
|
||||
RString commonSubstring;
|
||||
GetCommonTagFromMapList( BMSData, "#title", commonSubstring );
|
||||
|
||||
Steps *copy = dummy.CreateSteps();
|
||||
|
||||
copy->SetDifficulty( Difficulty_Medium );
|
||||
RString sTag;
|
||||
if( GetTagFromMap( BMSData[0], "#title", sTag ) && sTag.size() != commonSubstring.size() )
|
||||
{
|
||||
sTag = sTag.substr( commonSubstring.size(), sTag.size() - commonSubstring.size() );
|
||||
sTag.MakeLower();
|
||||
|
||||
if( sTag.find('l') != sTag.npos )
|
||||
{
|
||||
unsigned lPos = sTag.find('l');
|
||||
if( lPos > 2 && sTag.substr(lPos-2,4) == "solo" )
|
||||
{
|
||||
copy->SetDifficulty( Difficulty_Edit );
|
||||
}
|
||||
else
|
||||
{
|
||||
copy->SetDifficulty( Difficulty_Easy );
|
||||
}
|
||||
}
|
||||
else if( sTag.find('a') != sTag.npos )
|
||||
copy->SetDifficulty( Difficulty_Hard );
|
||||
else if( sTag.find('b') != sTag.npos )
|
||||
copy->SetDifficulty( Difficulty_Beginner );
|
||||
}
|
||||
if( commonSubstring == "" )
|
||||
{
|
||||
copy->SetDifficulty(Difficulty_Medium);
|
||||
RString unused;
|
||||
if (GetTagFromMap(BMSData[0], "#title#", sTag))
|
||||
SearchForDifficulty(unused, copy);
|
||||
}
|
||||
MeasureToTimeSig_t sigAdjustments;
|
||||
map<RString,int> idToKeysoundIndex;
|
||||
ReadGlobalTags( cachePath, BMSData[0], dummy, sigAdjustments, idToKeysoundIndex );
|
||||
|
||||
const bool ok = LoadFromPMSFile( cachePath, BMSData[0], *copy, sigAdjustments, idToKeysoundIndex );
|
||||
if( ok )
|
||||
{
|
||||
out.SetNoteData(copy->GetNoteData());
|
||||
}
|
||||
return ok;
|
||||
|
||||
}
|
||||
|
||||
bool PMSLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
{
|
||||
LOG->Trace( "Song::LoadFromPMSDir(%s)", sDir.c_str() );
|
||||
@@ -914,7 +976,8 @@ bool PMSLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
|
||||
MeasureToTimeSig_t sigAdjustments;
|
||||
map<RString,int> idToKeysoundIndex;
|
||||
ReadGlobalTags( aPMSData[iMainDataIndex], out, sigAdjustments, idToKeysoundIndex );
|
||||
ReadGlobalTags( sDir, aPMSData[iMainDataIndex], out, sigAdjustments, idToKeysoundIndex );
|
||||
out.m_sSongFileName = out.GetSongDir() + arrayPMSFileNames[iMainDataIndex];
|
||||
|
||||
// Override what that global tag said about the title if we have a good substring.
|
||||
// Prevents clobbering and catches "MySong (7keys)" / "MySong (Another) (7keys)"
|
||||
@@ -929,7 +992,10 @@ bool PMSLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
Steps* pNewNotes = apSteps[i];
|
||||
const bool ok = LoadFromPMSFile( out.GetSongDir() + arrayPMSFileNames[i], aPMSData[i], *pNewNotes, sigAdjustments, idToKeysoundIndex );
|
||||
if( ok )
|
||||
{
|
||||
pNewNotes->SetFilename(out.GetSongDir() + arrayPMSFileNames[i]);
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
else
|
||||
delete pNewNotes;
|
||||
}
|
||||
@@ -940,7 +1006,7 @@ bool PMSLoader::LoadFromDir( const RString &sDir, Song &out )
|
||||
ConvertString( out.m_sArtist, "utf-8,japanese" );
|
||||
ConvertString( out.m_sGenre, "utf-8,japanese" );
|
||||
|
||||
out.TidyUpData();
|
||||
out.TidyUpData(false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
#define NOTES_LOADER_PMS_H
|
||||
|
||||
class Song;
|
||||
class Steps;
|
||||
/** @brief Reads a Song from a set of .PMS files. */
|
||||
namespace PMSLoader
|
||||
{
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
bool LoadFromDir( const RString &sDir, Song &out );
|
||||
bool LoadNoteDataFromSimfile(const RString & cachePath, Steps & out);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+50
-58
@@ -10,6 +10,7 @@
|
||||
#include "Song.h"
|
||||
#include "SongManager.h"
|
||||
#include "Steps.h"
|
||||
#include "Attack.h"
|
||||
#include "PrefsManager.h"
|
||||
|
||||
void SMLoader::SetSongTitle(const RString & title)
|
||||
@@ -95,23 +96,6 @@ void SMLoader::LoadFromTokens(
|
||||
}
|
||||
|
||||
out.SetMeter( StringToInt(sMeter) );
|
||||
vector<RString> saValues;
|
||||
split( sRadarValues, ",", saValues, true );
|
||||
int categories = NUM_RadarCategory - 1; // Fakes aren't counted in the radar values.
|
||||
if( saValues.size() == (unsigned)categories * NUM_PLAYERS )
|
||||
{
|
||||
RadarValues v[NUM_PLAYERS];
|
||||
FOREACH_PlayerNumber( pn )
|
||||
{
|
||||
// Can't use the foreach anymore due to flexible radar lines.
|
||||
for( RadarCategory rc = (RadarCategory)0; rc < categories;
|
||||
enum_add<RadarCategory>( rc, 1 ) )
|
||||
{
|
||||
v[pn][rc] = StringToFloat( saValues[pn*categories + rc] );
|
||||
}
|
||||
}
|
||||
out.SetCachedRadarValues( v );
|
||||
}
|
||||
|
||||
out.SetSMNoteData( sNoteData );
|
||||
|
||||
@@ -149,7 +133,8 @@ void SMLoader::ProcessAttackString( vector<RString> & attacks, MsdFile::value_t
|
||||
{
|
||||
RString tmp = params[s];
|
||||
Trim(tmp);
|
||||
attacks.push_back( tmp );
|
||||
if (tmp.size() > 0)
|
||||
attacks.push_back( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,8 +236,8 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsP
|
||||
if( negBPM < 0 )
|
||||
{
|
||||
float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat);
|
||||
WarpSegment new_seg(negBeat, endBeat - negBeat);
|
||||
out.AddWarpSegment( new_seg );
|
||||
out.AddSegment(SEGMENT_WARP,
|
||||
new WarpSegment(negBeat, endBeat - negBeat));
|
||||
|
||||
negBeat = -1;
|
||||
negBPM = 1;
|
||||
@@ -267,13 +252,13 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsP
|
||||
// add in a warp.
|
||||
if( highspeedBeat > 0 )
|
||||
{
|
||||
WarpSegment new_seg(highspeedBeat, fBeat - highspeedBeat);
|
||||
out.AddWarpSegment( new_seg );
|
||||
out.AddSegment(SEGMENT_WARP,
|
||||
new WarpSegment(highspeedBeat, fBeat - highspeedBeat) );
|
||||
highspeedBeat = -1;
|
||||
}
|
||||
{
|
||||
BPMSegment new_seg( BeatToNoteRow( fBeat ), fNewBPM );
|
||||
out.AddBPMSegment( new_seg );
|
||||
out.AddSegment(SEGMENT_BPM,
|
||||
new BPMSegment(fBeat, fNewBPM));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,15 +295,14 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
|
||||
// Process the prior stop.
|
||||
if( negPause > 0 )
|
||||
{
|
||||
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
|
||||
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
|
||||
BPMSegment * oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
|
||||
float fSecondsPerBeat = 60 / oldBPM->GetBPM();
|
||||
float fSkipBeats = negPause / fSecondsPerBeat;
|
||||
|
||||
if( negBeat + fSkipBeats > fFreezeBeat )
|
||||
fSkipBeats = fFreezeBeat - negBeat;
|
||||
|
||||
WarpSegment ws( negBeat, fSkipBeats);
|
||||
out.AddWarpSegment( ws );
|
||||
out.AddSegment(SEGMENT_WARP, new WarpSegment(negBeat, fSkipBeats));
|
||||
|
||||
negBeat = -1;
|
||||
negPause = 0;
|
||||
@@ -331,8 +315,8 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
|
||||
}
|
||||
else if( fFreezeSeconds > 0.0f )
|
||||
{
|
||||
StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds );
|
||||
out.AddStopSegment( ss );
|
||||
out.AddSegment(SEGMENT_STOP_DELAY,
|
||||
new StopSegment(fFreezeBeat, fFreezeSeconds));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -340,12 +324,11 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
|
||||
// Process the prior stop if there was one.
|
||||
if( negPause > 0 )
|
||||
{
|
||||
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
|
||||
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
|
||||
BPMSegment * oldBPM = out.GetBPMSegmentAtBeat(negBeat);
|
||||
float fSecondsPerBeat = 60 / oldBPM->GetBPM();
|
||||
float fSkipBeats = negPause / fSecondsPerBeat;
|
||||
|
||||
WarpSegment ws( negBeat, fSkipBeats);
|
||||
out.AddWarpSegment( ws );
|
||||
out.AddSegment(SEGMENT_WARP, new WarpSegment(negBeat, fSkipBeats));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,15 +353,14 @@ void SMLoader::ProcessDelays( TimingData &out, const RString line, const int row
|
||||
const float fFreezeBeat = RowToBeat( arrayDelayValues[0], rowsPerBeat );
|
||||
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
|
||||
|
||||
StopSegment new_seg( fFreezeBeat, fFreezeSeconds, true );
|
||||
// XXX: Remove Negatives Bug?
|
||||
new_seg.SetBeat(fFreezeBeat);
|
||||
new_seg.SetPause(fFreezeSeconds);
|
||||
StopSegment * new_seg = new StopSegment(fFreezeBeat,
|
||||
fFreezeSeconds,
|
||||
true);
|
||||
|
||||
// LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
|
||||
|
||||
if(fFreezeSeconds > 0.0f)
|
||||
out.AddStopSegment( new_seg );
|
||||
out.AddSegment( SEGMENT_STOP_DELAY, new_seg );
|
||||
else
|
||||
LOG->UserLog(
|
||||
"Song file",
|
||||
@@ -409,7 +391,10 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString line, const
|
||||
|
||||
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
|
||||
|
||||
TimeSignatureSegment seg( fBeat, StringToInt( vs2[1] ), StringToInt( vs2[2] ));
|
||||
TimeSignatureSegment * seg =
|
||||
new TimeSignatureSegment(fBeat,
|
||||
StringToInt( vs2[1] ),
|
||||
StringToInt( vs2[2] ));
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
@@ -420,25 +405,25 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString line, const
|
||||
continue;
|
||||
}
|
||||
|
||||
if( seg.GetNum() < 1 )
|
||||
if( seg->GetNum() < 1 )
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
this->GetSongTitle(),
|
||||
"has an invalid time signature change with beat %f, iNumerator %i.",
|
||||
fBeat, seg.GetNum() );
|
||||
fBeat, seg->GetNum() );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( seg.GetDen() < 1 )
|
||||
if( seg->GetDen() < 1 )
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
this->GetSongTitle(),
|
||||
"has an invalid time signature change with beat %f, iDenominator %i.",
|
||||
fBeat, seg.GetDen() );
|
||||
fBeat, seg->GetDen() );
|
||||
continue;
|
||||
}
|
||||
|
||||
out.AddTimeSignatureSegment( seg );
|
||||
out.AddSegment( SEGMENT_TIME_SIG, seg );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,8 +448,8 @@ void SMLoader::ProcessTickcounts( TimingData &out, const RString line, const int
|
||||
const float fTickcountBeat = RowToBeat( arrayTickcountValues[0], rowsPerBeat );
|
||||
int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT);
|
||||
|
||||
TickcountSegment new_seg( fTickcountBeat, iTicks );
|
||||
out.AddTickcountSegment( new_seg );
|
||||
out.AddSegment( SEGMENT_TICKCOUNT,
|
||||
new TickcountSegment(fTickcountBeat, iTicks) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,8 +484,10 @@ void SMLoader::ProcessSpeeds( TimingData &out, const RString line, const int row
|
||||
|
||||
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
|
||||
|
||||
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ));
|
||||
seg.SetUnit(StringToInt(vs2[3]));
|
||||
SpeedSegment * seg = new SpeedSegment(fBeat,
|
||||
StringToFloat( vs2[1] ),
|
||||
StringToFloat( vs2[2] ));
|
||||
seg->SetUnit(StringToInt(vs2[3]));
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
@@ -511,16 +498,16 @@ void SMLoader::ProcessSpeeds( TimingData &out, const RString line, const int row
|
||||
continue;
|
||||
}
|
||||
|
||||
if( seg.GetLength() < 0 )
|
||||
if( seg->GetLength() < 0 )
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
this->GetSongTitle(),
|
||||
"has an speed change with beat %f, length %f.",
|
||||
fBeat, seg.GetLength() );
|
||||
fBeat, seg->GetLength() );
|
||||
continue;
|
||||
}
|
||||
|
||||
out.AddSpeedSegment( seg );
|
||||
out.AddSegment( SEGMENT_SPEED, seg );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,7 +533,7 @@ void SMLoader::ProcessFakes( TimingData &out, const RString line, const int rows
|
||||
const float fNewBeat = StringToFloat( arrayFakeValues[1] );
|
||||
|
||||
if(fNewBeat > 0)
|
||||
out.AddFakeSegment( FakeSegment(fBeat, fNewBeat) );
|
||||
out.AddSegment( SEGMENT_FAKE, new FakeSegment(fBeat, fNewBeat) );
|
||||
else
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
@@ -643,9 +630,8 @@ bool SMLoader::LoadFromBGChangesString( BackgroundChange &change, const RString
|
||||
return aBGChangeValues.size() >= 2;
|
||||
}
|
||||
|
||||
bool SMLoader::LoadNotedataFromSimfile( const RString &path, Steps &out )
|
||||
bool SMLoader::LoadNoteDataFromSimfile( const RString &path, Steps &out )
|
||||
{
|
||||
// stub: do this later.
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( path, true ) ) // unescape
|
||||
{
|
||||
@@ -696,7 +682,7 @@ bool SMLoader::LoadNotedataFromSimfile( const RString &path, Steps &out )
|
||||
RString noteData = sParams[6];
|
||||
Trim( noteData );
|
||||
out.SetSMNoteData( noteData );
|
||||
|
||||
out.TidyUpData();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -715,6 +701,7 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
|
||||
}
|
||||
|
||||
out.m_SongTiming.m_sFile = sPath;
|
||||
out.m_sSongFileName = sPath;
|
||||
|
||||
for( unsigned i=0; i<msd.GetNumValues(); i++ )
|
||||
{
|
||||
@@ -922,6 +909,7 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
|
||||
sParams[6],
|
||||
*pNewNotes );
|
||||
|
||||
pNewNotes->SetFilename(sPath);
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
// XXX: Does anyone know what LEADTRACK is for? -Wolfman2000
|
||||
@@ -932,7 +920,8 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
|
||||
}
|
||||
|
||||
// Ensure all warps from negative time changes are in order.
|
||||
sort(out.m_SongTiming.m_WarpSegments.begin(), out.m_SongTiming.m_WarpSegments.end());
|
||||
vector<TimingSegment *> &warps = out.m_SongTiming.allTimingSegments[SEGMENT_WARP];
|
||||
sort(warps.begin(), warps.end());
|
||||
TidyUpData( out, bFromCache );
|
||||
return true;
|
||||
}
|
||||
@@ -1107,7 +1096,10 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache )
|
||||
bg.push_back( BackgroundChange(lastBeat,song.m_sBackgroundFile) );
|
||||
} while(0);
|
||||
}
|
||||
song.TidyUpData( bFromCache );
|
||||
if (bFromCache)
|
||||
{
|
||||
song.TidyUpData( bFromCache, true );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ struct SMLoader
|
||||
* @brief Retrieve the relevant notedata from the simfile.
|
||||
* @param path the path where the simfile lives.
|
||||
* @param out the Steps we are loading the data into. */
|
||||
virtual bool LoadNotedataFromSimfile(const RString &path, Steps &out );
|
||||
virtual bool LoadNoteDataFromSimfile(const RString &path, Steps &out );
|
||||
|
||||
/**
|
||||
* @brief Attempt to load the specified sm file.
|
||||
|
||||
+18
-13
@@ -38,8 +38,8 @@ void SMALoader::ProcessMultipliers( TimingData &out, const int iRowsPerBeat, con
|
||||
const int iMisses = (size == 2 || size == 4 ?
|
||||
iCombos :
|
||||
StringToInt(arrayMultiplierValues[2]));
|
||||
ComboSegment new_seg( fComboBeat, iCombos, iMisses );
|
||||
out.AddComboSegment( new_seg );
|
||||
out.AddSegment(SEGMENT_COMBO,
|
||||
new ComboSegment( fComboBeat, iCombos, iMisses ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,9 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam )
|
||||
|
||||
const float fBeat = StringToFloat( vs2[0] );
|
||||
|
||||
TimeSignatureSegment seg( fBeat, StringToInt( vs2[1] ), 4 );
|
||||
TimeSignatureSegment * seg = new TimeSignatureSegment(fBeat,
|
||||
StringToInt(vs2[1]),
|
||||
4 );
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
@@ -75,16 +77,16 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam )
|
||||
continue;
|
||||
}
|
||||
|
||||
if( seg.GetNum() < 1 )
|
||||
if( seg->GetNum() < 1 )
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
this->GetSongTitle(),
|
||||
"has an invalid time signature change with beat %f, iNumerator %i.",
|
||||
fBeat, seg.GetNum() );
|
||||
fBeat, seg->GetNum() );
|
||||
continue;
|
||||
}
|
||||
|
||||
out.AddTimeSignatureSegment( seg );
|
||||
out.AddSegment( SEGMENT_TIME_SIG, seg );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,8 +125,10 @@ void SMALoader::ProcessSpeeds( TimingData &out, const RString line, const int ro
|
||||
|
||||
unsigned short tmp = ((backup != vs2[2]) ? 1 : 0);
|
||||
|
||||
SpeedSegment seg(fBeat, StringToFloat( vs2[1] ), StringToFloat(vs2[2]), tmp);
|
||||
//seg.SetUnit(tmp);
|
||||
SpeedSegment * seg = new SpeedSegment(fBeat,
|
||||
StringToFloat( vs2[1] ),
|
||||
StringToFloat(vs2[2]),
|
||||
tmp);
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
@@ -135,16 +139,16 @@ void SMALoader::ProcessSpeeds( TimingData &out, const RString line, const int ro
|
||||
continue;
|
||||
}
|
||||
|
||||
if( seg.GetLength() < 0 )
|
||||
if( seg->GetLength() < 0 )
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
this->GetSongTitle(),
|
||||
"has an speed change with beat %f, length %f.",
|
||||
fBeat, seg.GetLength() );
|
||||
fBeat, seg->GetLength() );
|
||||
continue;
|
||||
}
|
||||
|
||||
out.AddSpeedSegment( seg );
|
||||
out.AddSegment( SEGMENT_SPEED, seg );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +164,7 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
}
|
||||
|
||||
out.m_SongTiming.m_sFile = sPath; // songs still have their fallback timing.
|
||||
out.m_sSongFileName = sPath;
|
||||
|
||||
int state = SMA_GETTING_SONG_INFO;
|
||||
Steps* pNewNotes = NULL;
|
||||
@@ -446,7 +451,7 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
sParams[5],
|
||||
sParams[6],
|
||||
*pNewNotes );
|
||||
|
||||
pNewNotes->SetFilename(sPath);
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
else if( sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" )
|
||||
@@ -458,7 +463,7 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
sValueName.c_str() );
|
||||
}
|
||||
TidyUpData(out, false);
|
||||
out.TidyUpData();
|
||||
out.TidyUpData(false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+128
-22
@@ -37,10 +37,10 @@ void SSCLoader::ProcessWarps( TimingData &out, const RString sParam, const float
|
||||
// Early versions were absolute in beats. They should be relative.
|
||||
if( ( fVersion < VERSION_SPLIT_TIMING && fNewBeat > fBeat ) )
|
||||
{
|
||||
out.AddWarpSegment( WarpSegment(fBeat, fNewBeat - fBeat) );
|
||||
out.AddSegment( SEGMENT_WARP, new WarpSegment(fBeat, fNewBeat - fBeat) );
|
||||
}
|
||||
else if( fNewBeat > 0 )
|
||||
out.AddWarpSegment( WarpSegment(fBeat, fNewBeat) );
|
||||
out.AddSegment( SEGMENT_WARP, new WarpSegment(fBeat, fNewBeat) );
|
||||
else
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
@@ -73,7 +73,7 @@ void SSCLoader::ProcessLabels( TimingData &out, const RString sParam )
|
||||
RString sLabel = arrayLabelValues[1];
|
||||
TrimRight(sLabel);
|
||||
if( fBeat >= 0.0f )
|
||||
out.AddLabelSegment( LabelSegment(fBeat, sLabel) );
|
||||
out.AddSegment( SEGMENT_LABEL, new LabelSegment(fBeat, sLabel) );
|
||||
else
|
||||
{
|
||||
LOG->UserLog("Song file",
|
||||
@@ -106,8 +106,7 @@ void SSCLoader::ProcessCombos( TimingData &out, const RString line, const int ro
|
||||
const float fComboBeat = StringToFloat( arrayComboValues[0] );
|
||||
const int iCombos = StringToInt( arrayComboValues[1] );
|
||||
const int iMisses = (size == 2 ? iCombos : StringToInt(arrayComboValues[2]));
|
||||
ComboSegment new_seg( fComboBeat, iCombos, iMisses );
|
||||
out.AddComboSegment( new_seg );
|
||||
out.AddSegment( SEGMENT_COMBO, new ComboSegment( fComboBeat, iCombos, iMisses ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@ void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
|
||||
|
||||
const float fBeat = StringToFloat( vs2[0] );
|
||||
|
||||
ScrollSegment seg( fBeat, StringToFloat( vs2[1] ) );
|
||||
ScrollSegment * seg = new ScrollSegment(fBeat, StringToFloat( vs2[1] ) );
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
@@ -143,10 +142,99 @@ void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
|
||||
continue;
|
||||
}
|
||||
|
||||
out.AddScrollSegment( seg );
|
||||
out.AddSegment( SEGMENT_SCROLL, seg );
|
||||
}
|
||||
}
|
||||
|
||||
bool SSCLoader::LoadNoteDataFromSimfile( const RString & cachePath, Steps &out )
|
||||
{
|
||||
LOG->Trace( "Loading notes from %s", cachePath.c_str() );
|
||||
|
||||
MsdFile msd;
|
||||
if (!msd.ReadFile(cachePath, true))
|
||||
{
|
||||
LOG->UserLog("Unable to load any notes from",
|
||||
cachePath,
|
||||
"for this reason: %s",
|
||||
msd.GetError().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tryingSteps = false;
|
||||
float storedVersion = 0;
|
||||
const unsigned values = msd.GetNumValues();
|
||||
|
||||
for (unsigned i = 0; i < values; i++)
|
||||
{
|
||||
const MsdFile::value_t ¶ms = msd.GetValue(i);
|
||||
RString valueName = params[0];
|
||||
valueName.MakeUpper();
|
||||
RString matcher = params[1]; // mainly for debugging.
|
||||
Trim(matcher);
|
||||
|
||||
if (valueName=="VERSION")
|
||||
{
|
||||
storedVersion = StringToFloat(matcher);
|
||||
}
|
||||
if (tryingSteps)
|
||||
{
|
||||
if( valueName=="STEPSTYPE" )
|
||||
{
|
||||
if (out.m_StepsType != GAMEMAN->StringToStepsType(matcher))
|
||||
tryingSteps = false;
|
||||
}
|
||||
else if( valueName=="CHARTNAME")
|
||||
{
|
||||
if (storedVersion >= VERSION_CHART_NAME_TAG && out.GetChartName() != matcher)
|
||||
tryingSteps = false;
|
||||
}
|
||||
else if( valueName=="DESCRIPTION" )
|
||||
{
|
||||
if (storedVersion < VERSION_CHART_NAME_TAG)
|
||||
{
|
||||
if (out.GetChartName() != matcher)
|
||||
tryingSteps = false;
|
||||
}
|
||||
else if (out.GetDescription() != matcher)
|
||||
tryingSteps = false;
|
||||
}
|
||||
|
||||
else if( valueName=="DIFFICULTY" )
|
||||
{
|
||||
if (out.GetDifficulty() != StringToDifficulty(matcher))
|
||||
tryingSteps = false;
|
||||
}
|
||||
|
||||
else if( valueName=="METER" )
|
||||
{
|
||||
if (out.GetMeter() != StringToInt(matcher))
|
||||
tryingSteps = false;
|
||||
}
|
||||
|
||||
else if( valueName=="CREDIT" )
|
||||
{
|
||||
if (out.GetCredit() != matcher)
|
||||
tryingSteps = false;
|
||||
}
|
||||
|
||||
else if( valueName=="NOTES" || valueName=="NOTES2" )
|
||||
{
|
||||
out.SetSMNoteData(matcher);
|
||||
out.TidyUpData();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(valueName == "NOTEDATA")
|
||||
{
|
||||
tryingSteps = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache )
|
||||
{
|
||||
LOG->Trace( "Song::LoadFromSSCFile(%s)", sPath.c_str() );
|
||||
@@ -159,6 +247,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
}
|
||||
|
||||
out.m_SongTiming.m_sFile = sPath; // songs still have their fallback timing.
|
||||
out.m_sSongFileName = sPath;
|
||||
|
||||
int state = GETTING_SONG_INFO;
|
||||
const unsigned values = msd.GetNumValues();
|
||||
@@ -485,27 +574,35 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
|
||||
else if( sValueName=="RADARVALUES" )
|
||||
{
|
||||
vector<RString> saValues;
|
||||
split( sParams[1], ",", saValues, true );
|
||||
|
||||
int categories = NUM_RadarCategory;
|
||||
if( out.m_fVersion < VERSION_RADAR_FAKE )
|
||||
categories -= 1;
|
||||
|
||||
if( saValues.size() == (unsigned)categories * NUM_PLAYERS )
|
||||
if (bFromCache)
|
||||
{
|
||||
RadarValues v[NUM_PLAYERS];
|
||||
FOREACH_PlayerNumber( pn )
|
||||
vector<RString> saValues;
|
||||
split( sParams[1], ",", saValues, true );
|
||||
|
||||
int categories = NUM_RadarCategory;
|
||||
if( out.m_fVersion < VERSION_RADAR_FAKE )
|
||||
categories -= 1;
|
||||
|
||||
if( saValues.size() == (unsigned)categories * NUM_PLAYERS )
|
||||
{
|
||||
// Can't use the foreach anymore due to flexible radar lines.
|
||||
for( RadarCategory rc = (RadarCategory)0; rc < categories;
|
||||
enum_add<RadarCategory>( rc, +1 ) )
|
||||
RadarValues v[NUM_PLAYERS];
|
||||
FOREACH_PlayerNumber( pn )
|
||||
{
|
||||
v[pn][rc] = StringToFloat( saValues[pn*categories + rc] );
|
||||
// Can't use the foreach anymore due to flexible radar lines.
|
||||
for( RadarCategory rc = (RadarCategory)0; rc < categories;
|
||||
enum_add<RadarCategory>( rc, +1 ) )
|
||||
{
|
||||
v[pn][rc] = StringToFloat( saValues[pn*categories + rc] );
|
||||
}
|
||||
}
|
||||
pNewNotes->SetCachedRadarValues( v );
|
||||
}
|
||||
pNewNotes->SetCachedRadarValues( v );
|
||||
}
|
||||
else
|
||||
{
|
||||
// just recalc at time.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if( sValueName=="CREDIT" )
|
||||
@@ -520,6 +617,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
pNewNotes->m_Timing = stepsTiming;
|
||||
pNewNotes->SetSMNoteData( sParams[1] );
|
||||
pNewNotes->TidyUpData();
|
||||
pNewNotes->SetFilename(sPath);
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
|
||||
@@ -606,6 +704,14 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
pNewNotes->SetMaxBPM(StringToFloat(sParams[2]));
|
||||
}
|
||||
}
|
||||
else if( sValueName=="STEPFILENAME" )
|
||||
{
|
||||
state = GETTING_SONG_INFO;
|
||||
if( bHasOwnTiming )
|
||||
pNewNotes->m_Timing = stepsTiming;
|
||||
pNewNotes->SetFilename(sParams[1]);
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ const float VERSION_SPLIT_TIMING = 0.7f;
|
||||
const float VERSION_OFFSET_BEFORE_ATTACK = 0.72f;
|
||||
/** @brief The version that introduced the Chart Name tag. */
|
||||
const float VERSION_CHART_NAME_TAG = 0.74f;
|
||||
/** @brief The version that introduced the cache switch tag. */
|
||||
const float VERSION_CACHE_SWITCH_TAG = 0.77f;
|
||||
|
||||
/**
|
||||
* @brief The SSCLoader handles all of the parsing needed for .ssc files.
|
||||
@@ -65,6 +67,12 @@ struct SSCLoader : public SMLoader
|
||||
*/
|
||||
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the specific NoteData from the file.
|
||||
* @param cachePath the path to the cache file.
|
||||
* @param out the Steps to receive just the particular notedata.
|
||||
* @return true if successful, false otherwise. */
|
||||
virtual bool LoadNoteDataFromSimfile( const RString &cachePath, Steps &out );
|
||||
|
||||
void ProcessWarps( TimingData &, const RString, const float );
|
||||
void ProcessLabels( TimingData &, const RString );
|
||||
|
||||
+22
-16
@@ -123,9 +123,10 @@ static RString NotesToDWIString( const TapNote tnCols[6] )
|
||||
{
|
||||
switch( tnCols[col].type )
|
||||
{
|
||||
case TapNote::empty:
|
||||
case TapNote::mine:
|
||||
continue;
|
||||
case TapNote::empty:
|
||||
case TapNote::mine:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( tnCols[col].type == TapNote::hold_head )
|
||||
@@ -352,9 +353,13 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
|
||||
/* Write transliterations, if we have them, since DWI doesn't support UTF-8. */
|
||||
f.PutLine( ssprintf("#TITLE:%s;", DwiEscape(out.GetTranslitFullTitle()).c_str()) );
|
||||
f.PutLine( ssprintf("#ARTIST:%s;", DwiEscape(out.GetTranslitArtist()).c_str()) );
|
||||
ASSERT( out.m_SongTiming.m_BPMSegments[0].GetRow() == 0 );
|
||||
|
||||
const vector<TimingSegment *> &bpms = out.m_SongTiming.allTimingSegments[SEGMENT_BPM];
|
||||
|
||||
ASSERT_M(bpms[0]->GetRow() == 0,
|
||||
ssprintf("The first BPM Segment must be defined at row 0, not %d!", bpms[0]->GetRow()) );
|
||||
f.PutLine( ssprintf("#FILE:%s;", DwiEscape(out.m_sMusicFile).c_str()) );
|
||||
f.PutLine( ssprintf("#BPM:%.3f;", out.m_SongTiming.m_BPMSegments[0].GetBPM()) );
|
||||
f.PutLine( ssprintf("#BPM:%.3f;", static_cast<BPMSegment *>(bpms[0])->GetBPM()) );
|
||||
f.PutLine( ssprintf("#GAP:%ld;", -lrintf( out.m_SongTiming.m_fBeat0OffsetInSeconds*1000 )) );
|
||||
f.PutLine( ssprintf("#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds) );
|
||||
f.PutLine( ssprintf("#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds) );
|
||||
@@ -376,29 +381,30 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
|
||||
break;
|
||||
}
|
||||
|
||||
if( !out.m_SongTiming.m_StopSegments.empty() )
|
||||
const vector<TimingSegment *> &stops = out.m_SongTiming.allTimingSegments[SEGMENT_STOP_DELAY];
|
||||
if( !stops.empty() )
|
||||
{
|
||||
f.Write( "#FREEZE:" );
|
||||
|
||||
for( unsigned i=0; i<out.m_SongTiming.m_StopSegments.size(); i++ )
|
||||
for( unsigned i=0; i<stops.size(); i++ )
|
||||
{
|
||||
const StopSegment &fs = out.m_SongTiming.m_StopSegments[i];
|
||||
f.Write( ssprintf("%.3f=%.3f", fs.GetRow() * 4.0f / ROWS_PER_BEAT,
|
||||
roundf(fs.GetPause()*1000)) );
|
||||
if( i != out.m_SongTiming.m_StopSegments.size()-1 )
|
||||
const StopSegment *fs = static_cast<StopSegment *>(stops[i]);
|
||||
f.Write( ssprintf("%.3f=%.3f", fs->GetRow() * 4.0f / ROWS_PER_BEAT,
|
||||
roundf(fs->GetPause()*1000)) );
|
||||
if( i != stops.size()-1 )
|
||||
f.Write( "," );
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
}
|
||||
|
||||
if( out.m_SongTiming.m_BPMSegments.size() > 1)
|
||||
if( bpms.size() > 1)
|
||||
{
|
||||
f.Write( "#CHANGEBPM:" );
|
||||
for( unsigned i=1; i<out.m_SongTiming.m_BPMSegments.size(); i++ )
|
||||
for( unsigned i=1; i<bpms.size(); i++ )
|
||||
{
|
||||
const BPMSegment &bs = out.m_SongTiming.m_BPMSegments[i];
|
||||
f.Write( ssprintf("%.3f=%.3f", bs.GetRow() * 4.0f / ROWS_PER_BEAT, bs.GetBPM() ) );
|
||||
if( i != out.m_SongTiming.m_BPMSegments.size()-1 )
|
||||
const BPMSegment *bs = static_cast<BPMSegment *>(bpms[i]);
|
||||
f.Write( ssprintf("%.3f=%.3f", bs->GetRow() * 4.0f / ROWS_PER_BEAT, bs->GetBPM() ) );
|
||||
if( i != bpms.size()-1 )
|
||||
f.Write( "," );
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
|
||||
+11
-10
@@ -9,22 +9,23 @@
|
||||
#include "NoteData.h"
|
||||
#include "GameManager.h"
|
||||
|
||||
static void Serialize(const BPMSegment &seg, Json::Value &root)
|
||||
static void Serialize(const TimingSegment &seg, Json::Value &root)
|
||||
{
|
||||
root["Beat"] = seg.GetBeat();
|
||||
root["BPM"] = seg.GetBPM();
|
||||
}
|
||||
|
||||
static void Serialize(const StopSegment &seg, Json::Value &root)
|
||||
{
|
||||
root["Beat"] = seg.GetBeat();
|
||||
root["Seconds"] = seg.GetPause();
|
||||
if (seg.GetType() == SEGMENT_BPM)
|
||||
{
|
||||
root["BPM"] = static_cast<BPMSegment &>(const_cast<TimingSegment &>(seg)).GetBPM();
|
||||
}
|
||||
else
|
||||
{
|
||||
root["Seconds"] = static_cast<StopSegment &>(const_cast<TimingSegment &>(seg)).GetPause();
|
||||
}
|
||||
}
|
||||
|
||||
static void Serialize(const TimingData &td, Json::Value &root)
|
||||
{
|
||||
JsonUtil::SerializeVectorObjects( td.m_BPMSegments, Serialize, root["BpmSegments"] );
|
||||
JsonUtil::SerializeVectorObjects( td.m_StopSegments, Serialize, root["StopSegments"] );
|
||||
JsonUtil::SerializeVectorPointers( td.allTimingSegments[SEGMENT_BPM], Serialize, root["BpmSegments"] );
|
||||
JsonUtil::SerializeVectorPointers( td.allTimingSegments[SEGMENT_STOP_DELAY], Serialize, root["StopSegments"] );
|
||||
}
|
||||
|
||||
static void Serialize(const LyricSegment &o, Json::Value &root)
|
||||
|
||||
+25
-56
@@ -19,37 +19,13 @@
|
||||
|
||||
ThemeMetric<bool> USE_CREDIT ( "NotesWriterSM", "DescriptionUsesCreditField" );
|
||||
|
||||
/**
|
||||
* @brief Turn the BackgroundChange into a string.
|
||||
* @param bgc the BackgroundChange in question.
|
||||
* @return the converted string. */
|
||||
static RString BackgroundChangeToString( const BackgroundChange &bgc )
|
||||
{
|
||||
// TODO: Technically we need to double-escape the filename (because it might
|
||||
// contain '=') and then unescape the value returned by the MsdFile.
|
||||
RString s = ssprintf(
|
||||
"%.3f=%s=%.3f=%d=%d=%d=%s=%s=%s=%s=%s",
|
||||
bgc.m_fStartBeat,
|
||||
SmEscape(bgc.m_def.m_sFile1).c_str(),
|
||||
bgc.m_fRate,
|
||||
bgc.m_sTransition == SBT_CrossFade, // backward compat
|
||||
bgc.m_def.m_sEffect == SBE_StretchRewind, // backward compat
|
||||
bgc.m_def.m_sEffect != SBE_StretchNoLoop, // backward compat
|
||||
bgc.m_def.m_sEffect.c_str(),
|
||||
bgc.m_def.m_sFile2.c_str(),
|
||||
bgc.m_sTransition.c_str(),
|
||||
SmEscape(RageColor::NormalizeColorString(bgc.m_def.m_sColor1)).c_str(),
|
||||
SmEscape(RageColor::NormalizeColorString(bgc.m_def.m_sColor2)).c_str()
|
||||
);
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write out the common tags for .SM files.
|
||||
* @param f the file in question.
|
||||
* @param out the Song in question. */
|
||||
static void WriteGlobalTags( RageFile &f, Song &out )
|
||||
{
|
||||
TimingData &timing = out.m_SongTiming;
|
||||
f.PutLine( ssprintf( "#TITLE:%s;", SmEscape(out.m_sMainTitle).c_str() ) );
|
||||
f.PutLine( ssprintf( "#SUBTITLE:%s;", SmEscape(out.m_sSubTitle).c_str() ) );
|
||||
f.PutLine( ssprintf( "#ARTIST:%s;", SmEscape(out.m_sArtist).c_str() ) );
|
||||
@@ -99,44 +75,46 @@ static void WriteGlobalTags( RageFile &f, Song &out )
|
||||
|
||||
|
||||
f.Write( "#BPMS:" );
|
||||
for( unsigned i=0; i<out.m_SongTiming.m_BPMSegments.size(); i++ )
|
||||
vector<TimingSegment *> &bpms = timing.allTimingSegments[SEGMENT_BPM];
|
||||
for( unsigned i=0; i<bpms.size(); i++ )
|
||||
{
|
||||
const BPMSegment &bs = out.m_SongTiming.m_BPMSegments[i];
|
||||
const BPMSegment *bs = static_cast<BPMSegment *>(bpms[i]);
|
||||
|
||||
f.PutLine( ssprintf( "%.3f=%.3f", bs.GetBeat(), bs.GetBPM() ) );
|
||||
if( i != out.m_SongTiming.m_BPMSegments.size()-1 )
|
||||
f.PutLine( ssprintf( "%.3f=%.3f", bs->GetBeat(), bs->GetBPM() ) );
|
||||
if( i != bpms.size()-1 )
|
||||
f.Write( "," );
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
|
||||
unsigned wSize = out.m_SongTiming.m_WarpSegments.size();
|
||||
vector<TimingSegment *> &warps = timing.allTimingSegments[SEGMENT_WARP];
|
||||
unsigned wSize = warps.size();
|
||||
if( wSize > 0 )
|
||||
{
|
||||
for( unsigned i=0; i < wSize; i++ )
|
||||
{
|
||||
int iRow = out.m_SongTiming.m_WarpSegments[i].GetRow();
|
||||
const WarpSegment *ws = static_cast<WarpSegment *>(warps[i]);
|
||||
int iRow = ws->GetRow();
|
||||
float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow);
|
||||
float fSkip = fBPS * out.m_SongTiming.m_WarpSegments[i].GetLength();
|
||||
StopSegment ss(iRow, -fSkip, false);
|
||||
out.m_SongTiming.AddStopSegment( ss );
|
||||
float fSkip = fBPS * ws->GetLength();
|
||||
out.m_SongTiming.AddSegment(SEGMENT_STOP_DELAY,
|
||||
new StopSegment(iRow, -fSkip, false) );
|
||||
}
|
||||
}
|
||||
|
||||
f.Write( "#STOPS:" );
|
||||
for( unsigned i=0; i<out.m_SongTiming.m_StopSegments.size(); i++ )
|
||||
vector<TimingSegment *> &stops = timing.allTimingSegments[SEGMENT_STOP_DELAY];
|
||||
for( unsigned i=0; i<stops.size(); i++ )
|
||||
{
|
||||
const StopSegment &fs = out.m_SongTiming.m_StopSegments[i];
|
||||
float fBeat = fs.GetBeat();
|
||||
if (fs.GetDelay()) fBeat--;
|
||||
const StopSegment *fs = static_cast<StopSegment *>(stops[i]);
|
||||
float fBeat = fs->GetBeat();
|
||||
if (fs->GetDelay()) fBeat--;
|
||||
|
||||
f.PutLine( ssprintf( "%.3f=%.3f", fBeat, fs.GetPause() ) );
|
||||
if( i != out.m_SongTiming.m_StopSegments.size()-1 )
|
||||
f.PutLine( ssprintf( "%.3f=%.3f", fBeat, fs->GetPause() ) );
|
||||
if( i != stops.size()-1 )
|
||||
f.Write( "," );
|
||||
if( fs.GetPause() < 0 )
|
||||
if( fs->GetPause() < 0 )
|
||||
{
|
||||
out.m_SongTiming.m_StopSegments.erase(
|
||||
out.m_SongTiming.m_StopSegments.begin()+i,
|
||||
out.m_SongTiming.m_StopSegments.begin()+i+1 );
|
||||
stops.erase(stops.begin()+i,stops.begin()+i+1 );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
@@ -152,7 +130,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
|
||||
f.Write( ssprintf("#BGCHANGES%d:", b+1) );
|
||||
|
||||
FOREACH_CONST( BackgroundChange, out.GetBackgroundChanges(b), bgc )
|
||||
f.PutLine( BackgroundChangeToString(*bgc)+"," );
|
||||
f.PutLine( (*bgc).ToString() +"," );
|
||||
|
||||
/* If there's an animation plan at all, add a dummy "-nosongbg-" tag to indicate that
|
||||
* this file doesn't want a song BG entry added at the end. See SMLoader::TidyUpData.
|
||||
@@ -168,7 +146,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
|
||||
f.Write( "#FGCHANGES:" );
|
||||
FOREACH_CONST( BackgroundChange, out.GetForegroundChanges(), bgc )
|
||||
{
|
||||
f.PutLine( BackgroundChangeToString(*bgc)+"," );
|
||||
f.PutLine( (*bgc).ToString() +"," );
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
}
|
||||
@@ -182,16 +160,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
|
||||
f.Write( "#ATTACKS:" );
|
||||
for( unsigned a=0; a < out.m_sAttackString.size(); a++ )
|
||||
{
|
||||
RString sData = out.m_sAttackString[a];
|
||||
f.Write( ssprintf( "%s", sData.c_str() ) );
|
||||
|
||||
if( a != (out.m_sAttackString.size() - 1) )
|
||||
f.Write( ":" ); // Not the end, so write a divider ':'
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
f.PutLine( ssprintf("#ATTACKS:%s;", out.GetAttackString().c_str()) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+100
-83
@@ -16,31 +16,6 @@
|
||||
#include "Song.h"
|
||||
#include "Steps.h"
|
||||
|
||||
/**
|
||||
* @brief Turn the BackgroundChange into a string.
|
||||
* @param bgc the BackgroundChange in question.
|
||||
* @return the converted string. */
|
||||
static RString BackgroundChangeToString( const BackgroundChange &bgc )
|
||||
{
|
||||
// TODO: Technically we need to double-escape the filename (because it might contain '=') and then
|
||||
// unescape the value returned by the MsdFile.
|
||||
RString s = ssprintf(
|
||||
"%.3f=%s=%.3f=%d=%d=%d=%s=%s=%s=%s=%s",
|
||||
bgc.m_fStartBeat,
|
||||
SmEscape(bgc.m_def.m_sFile1).c_str(),
|
||||
bgc.m_fRate,
|
||||
bgc.m_sTransition == SBT_CrossFade, // backward compat
|
||||
bgc.m_def.m_sEffect == SBE_StretchRewind, // backward compat
|
||||
bgc.m_def.m_sEffect != SBE_StretchNoLoop, // backward compat
|
||||
bgc.m_def.m_sEffect.c_str(),
|
||||
bgc.m_def.m_sFile2.c_str(),
|
||||
bgc.m_sTransition.c_str(),
|
||||
SmEscape(RageColor::NormalizeColorString(bgc.m_def.m_sColor1)).c_str(),
|
||||
SmEscape(RageColor::NormalizeColorString(bgc.m_def.m_sColor2)).c_str()
|
||||
);
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn a vector of lines into a single line joined by newline characters.
|
||||
* @param lines the list of lines to join.
|
||||
@@ -90,45 +65,71 @@ static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSo
|
||||
TimingTagWriter w ( &lines );
|
||||
|
||||
timing.TidyUpData();
|
||||
unsigned i = 0;
|
||||
|
||||
w.Init( "BPMS" );
|
||||
FOREACH_CONST( BPMSegment, timing.m_BPMSegments, bs )
|
||||
vector<TimingSegment *> &bpms = timing.allTimingSegments[SEGMENT_BPM];
|
||||
for (; i < bpms.size(); i++)
|
||||
{
|
||||
BPMSegment *bs = static_cast<BPMSegment *>(bpms[i]);
|
||||
w.Write( bs->GetRow(), bs->GetBPM() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
w.Init( "STOPS" );
|
||||
FOREACH_CONST( StopSegment, timing.m_StopSegments, ss )
|
||||
vector<TimingSegment *> &stops = timing.allTimingSegments[SEGMENT_STOP_DELAY];
|
||||
for (i = 0; i < stops.size(); i++)
|
||||
{
|
||||
StopSegment *ss = static_cast<StopSegment *>(stops[i]);
|
||||
if( !ss->GetDelay() )
|
||||
w.Write( ss->GetRow(), ss->GetPause() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
w.Init( "DELAYS" );
|
||||
FOREACH_CONST( StopSegment, timing.m_StopSegments, ss )
|
||||
for (i = 0; i < stops.size(); i++)
|
||||
{
|
||||
StopSegment *ss = static_cast<StopSegment *>(stops[i]);
|
||||
if( ss->GetDelay() )
|
||||
w.Write( ss->GetRow(), ss->GetPause() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
w.Init( "WARPS" );
|
||||
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws )
|
||||
vector<TimingSegment *> &warps = timing.allTimingSegments[SEGMENT_WARP];
|
||||
for (i = 0; i < warps.size(); i++)
|
||||
{
|
||||
WarpSegment *ws = static_cast<WarpSegment *>(warps[i]);
|
||||
w.Write( ws->GetRow(), ws->GetLength() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
ASSERT( !timing.m_vTimeSignatureSegments.empty() );
|
||||
vector<TimingSegment *> &tSigs = timing.allTimingSegments[SEGMENT_TIME_SIG];
|
||||
ASSERT( !tSigs.empty() );
|
||||
w.Init( "TIMESIGNATURES" );
|
||||
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter )
|
||||
w.Write( iter->GetRow(), iter->GetNum(), iter->GetDen() );
|
||||
for (i = 0; i < tSigs.size(); i++)
|
||||
{
|
||||
TimeSignatureSegment *ts = static_cast<TimeSignatureSegment *>(tSigs[i]);
|
||||
w.Write( ts->GetRow(), ts->GetNum(), ts->GetDen() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
ASSERT( !timing.m_TickcountSegments.empty() );
|
||||
vector<TimingSegment *> &ticks = timing.allTimingSegments[SEGMENT_TICKCOUNT];
|
||||
ASSERT( !ticks.empty() );
|
||||
w.Init( "TICKCOUNTS" );
|
||||
FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, ts )
|
||||
for (i = 0; i < ticks.size(); i++)
|
||||
{
|
||||
TickcountSegment *ts = static_cast<TickcountSegment *>(ticks[i]);
|
||||
w.Write( ts->GetRow(), ts->GetTicks() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
ASSERT( !timing.m_ComboSegments.empty() );
|
||||
vector<TimingSegment *> &combos = timing.allTimingSegments[SEGMENT_COMBO];
|
||||
ASSERT( !combos.empty() );
|
||||
w.Init( "COMBOS" );
|
||||
FOREACH_CONST( ComboSegment, timing.m_ComboSegments, cs )
|
||||
for (i = 0; i < combos.size(); i++)
|
||||
{
|
||||
ComboSegment *cs = static_cast<ComboSegment *>(combos[i]);
|
||||
if (cs->GetCombo() == cs->GetMissCombo())
|
||||
w.Write( cs->GetRow(), cs->GetCombo() );
|
||||
else
|
||||
@@ -137,38 +138,71 @@ static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSo
|
||||
w.Finish();
|
||||
|
||||
// Song Timing should only have the initial value.
|
||||
vector<TimingSegment *> &speeds = timing.allTimingSegments[SEGMENT_SPEED];
|
||||
w.Init( "SPEEDS" );
|
||||
FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss )
|
||||
for (i = 0; i < speeds.size(); i++)
|
||||
{
|
||||
SpeedSegment *ss = static_cast<SpeedSegment *>(speeds[i]);
|
||||
w.Write( ss->GetRow(), ss->GetRatio(), ss->GetLength(), ss->GetUnit() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
w.Init( "SCROLLS" );
|
||||
FOREACH_CONST( ScrollSegment, timing.m_ScrollSegments, ss )
|
||||
vector<TimingSegment *> &scrolls = timing.allTimingSegments[SEGMENT_SCROLL];
|
||||
for (i = 0; i < scrolls.size(); i++)
|
||||
{
|
||||
ScrollSegment *ss = static_cast<ScrollSegment *>(scrolls[i]);
|
||||
w.Write( ss->GetRow(), ss->GetRatio() );
|
||||
}
|
||||
w.Finish();
|
||||
|
||||
if( !bIsSong )
|
||||
{
|
||||
vector<TimingSegment *> &fakes = timing.allTimingSegments[SEGMENT_FAKE];
|
||||
w.Init( "FAKES" );
|
||||
FOREACH_CONST( FakeSegment, timing.m_FakeSegments, fs )
|
||||
for (i = 0; i < fakes.size(); i++)
|
||||
{
|
||||
FakeSegment *fs = static_cast<FakeSegment *>(fakes[i]);
|
||||
w.Write( fs->GetRow(), fs->GetLength() );
|
||||
}
|
||||
w.Finish();
|
||||
}
|
||||
|
||||
w.Init( "LABELS" );
|
||||
FOREACH_CONST( LabelSegment, timing.m_LabelSegments, ls )
|
||||
vector<TimingSegment *> &labels = timing.allTimingSegments[SEGMENT_LABEL];
|
||||
for (i = 0; i < labels.size(); i++)
|
||||
{
|
||||
LabelSegment *ls = static_cast<LabelSegment *>(labels[i]);
|
||||
w.Write( ls->GetRow(), ls->GetLabel().c_str() );
|
||||
}
|
||||
w.Finish();
|
||||
}
|
||||
|
||||
static void WriteTimingTags( RageFile &f, const TimingData &timing, bool bIsSong = false )
|
||||
{
|
||||
|
||||
vector<RString> lines;
|
||||
|
||||
GetTimingTags( lines, timing, bIsSong );
|
||||
|
||||
f.PutLine( JoinLineList( lines ) );
|
||||
f.PutLine(ssprintf("#BPMS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_BPM)).c_str()));
|
||||
f.PutLine(ssprintf("#STOPS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_STOP_DELAY, false)).c_str()));
|
||||
f.PutLine(ssprintf("#DELAYS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_STOP_DELAY, true)).c_str()));
|
||||
f.PutLine(ssprintf("#WARPS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_WARP)).c_str()));
|
||||
f.PutLine(ssprintf("#TIMESIGNATURES:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_TIME_SIG)).c_str()));
|
||||
f.PutLine(ssprintf("#TICKCOUNTS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_TICKCOUNT)).c_str()));
|
||||
f.PutLine(ssprintf("#COMBOS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_COMBO)).c_str()));
|
||||
f.PutLine(ssprintf("#SPEEDS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_SPEED)).c_str()));
|
||||
f.PutLine(ssprintf("#SCROLLS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_SCROLL)).c_str()));
|
||||
if (!bIsSong)
|
||||
f.PutLine(ssprintf("#FAKES:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_FAKE)).c_str()));
|
||||
f.PutLine(ssprintf("#LABELS:%s;",
|
||||
join(",\r\n", timing.ToVectorString(SEGMENT_LABEL)).c_str()));
|
||||
|
||||
}
|
||||
|
||||
@@ -195,10 +229,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
|
||||
f.PutLine( ssprintf( "#MUSIC:%s;", SmEscape(out.m_sMusicFile).c_str() ) );
|
||||
|
||||
{
|
||||
vector<RString> vs;
|
||||
FOREACH_ENUM( InstrumentTrack, it )
|
||||
if( out.HasInstrumentTrack(it) )
|
||||
vs.push_back( InstrumentTrackToString(it) + "=" + out.m_sInstrumentTrackFile[it] );
|
||||
vector<RString> vs = out.GetInstrumentTracksToVectorString();
|
||||
if( !vs.empty() )
|
||||
{
|
||||
RString s = join( ",", vs );
|
||||
@@ -212,7 +243,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
|
||||
f.Write( "#SELECTABLE:" );
|
||||
switch(out.m_SelectionDisplay)
|
||||
{
|
||||
default: ASSERT(0); // fall through
|
||||
default: ASSERT_M(0, "An invalid selectable value was found for this song!"); // fall through
|
||||
case Song::SHOW_ALWAYS: f.Write( "YES" ); break;
|
||||
//case Song::SHOW_NONSTOP: f.Write( "NONSTOP" ); break;
|
||||
case Song::SHOW_NEVER: f.Write( "NO" ); break;
|
||||
@@ -250,7 +281,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
|
||||
f.Write( ssprintf("#BGCHANGES%d:", b+1) );
|
||||
|
||||
FOREACH_CONST( BackgroundChange, out.GetBackgroundChanges(b), bgc )
|
||||
f.PutLine( BackgroundChangeToString(*bgc)+"," );
|
||||
f.PutLine( (*bgc).ToString() +"," );
|
||||
|
||||
/* If there's an animation plan at all, add a dummy "-nosongbg-" tag to
|
||||
* indicate that this file doesn't want a song BG entry added at the end.
|
||||
@@ -266,7 +297,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
|
||||
f.Write( "#FGCHANGES:" );
|
||||
FOREACH_CONST( BackgroundChange, out.GetForegroundChanges(), bgc )
|
||||
{
|
||||
f.PutLine( BackgroundChangeToString(*bgc)+"," );
|
||||
f.PutLine( (*bgc).ToString() +"," );
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
}
|
||||
@@ -280,16 +311,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
|
||||
f.Write( "#ATTACKS:" );
|
||||
for( unsigned a=0; a < out.m_sAttackString.size(); a++ )
|
||||
{
|
||||
RString sData = out.m_sAttackString[a];
|
||||
f.Write( ssprintf( "%s", sData.c_str() ) );
|
||||
|
||||
if( a != (out.m_sAttackString.size() - 1) )
|
||||
f.Write( ":" ); // Not the end, so write a divider ':'
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
f.PutLine( ssprintf("#ATTACKS:%s;", out.GetAttackString().c_str()) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,7 +329,7 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
|
||||
lines.push_back( ssprintf("//---------------%s - %s----------------",
|
||||
GAMEMAN->GetStepsTypeInfo(in.m_StepsType).szName, SmEscape(in.GetDescription()).c_str()) );
|
||||
lines.push_back( "#NOTEDATA:;" ); // our new separator.
|
||||
lines.push_back( ssprintf( "#CHARTNAME:%s:", SmEscape(in.GetChartName()).c_str()));
|
||||
lines.push_back( ssprintf( "#CHARTNAME:%s;", SmEscape(in.GetChartName()).c_str()));
|
||||
lines.push_back( ssprintf( "#STEPSTYPE:%s;", GAMEMAN->GetStepsTypeInfo(in.m_StepsType).szName ) );
|
||||
lines.push_back( ssprintf( "#DESCRIPTION:%s;", SmEscape(in.GetDescription()).c_str() ) );
|
||||
lines.push_back( ssprintf( "#CHARTSTYLE:%s;", SmEscape(in.GetChartStyle()).c_str() ) );
|
||||
@@ -328,17 +350,7 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
|
||||
|
||||
GetTimingTags( lines, in.m_Timing );
|
||||
|
||||
RString attacks = "";
|
||||
for( unsigned a=0; a < in.m_sAttackString.size(); a++ )
|
||||
{
|
||||
RString sData = in.m_sAttackString[a];
|
||||
attacks += sData;
|
||||
|
||||
if( a != (in.m_sAttackString.size() - 1) )
|
||||
attacks += ":\r\n"; // Not the end, so write a divider ':'
|
||||
}
|
||||
Trim(attacks, ":"); // just in case something screwy happens.
|
||||
lines.push_back( ssprintf( "#ATTACKS:%s;", attacks.c_str()));
|
||||
lines.push_back( ssprintf("#ATTACKS:%s;", in.GetAttackString().c_str()));
|
||||
|
||||
switch( in.GetDisplayBPM() )
|
||||
{
|
||||
@@ -359,16 +371,21 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
|
||||
lines.push_back( ssprintf( "#DISPLAYBPM:*;" ) );
|
||||
break;
|
||||
}
|
||||
|
||||
RString sNoteData;
|
||||
in.GetSMNoteData( sNoteData );
|
||||
if (bSavingCache)
|
||||
{
|
||||
lines.push_back(ssprintf("#STEPFILENAME:%s;", in.GetFilename().c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
RString sNoteData;
|
||||
in.GetSMNoteData( sNoteData );
|
||||
|
||||
lines.push_back( song.m_vsKeysoundFile.empty() ? "#NOTES:" : "#NOTES2:" );
|
||||
|
||||
TrimLeft(sNoteData);
|
||||
split( sNoteData, "\n", lines, true );
|
||||
lines.push_back( ";" );
|
||||
lines.push_back( song.m_vsKeysoundFile.empty() ? "#NOTES:" : "#NOTES2:" );
|
||||
|
||||
TrimLeft(sNoteData);
|
||||
split( sNoteData, "\n", lines, true );
|
||||
lines.push_back( ";" );
|
||||
}
|
||||
return JoinLineList( lines );
|
||||
}
|
||||
|
||||
|
||||
+17
-13
@@ -426,15 +426,18 @@ void OptionRow::AfterImportOptions( PlayerNumber pn )
|
||||
|
||||
switch( m_pHand->m_Def.m_selectType )
|
||||
{
|
||||
case SELECT_ONE:
|
||||
// Make sure the row actually has a selection.
|
||||
int iSelection = GetOneSelection(pn, true);
|
||||
if( iSelection == -1 )
|
||||
case SELECT_ONE:
|
||||
{
|
||||
ASSERT( !m_vbSelected[pn].empty() );
|
||||
m_vbSelected[pn][0] = true;
|
||||
// Make sure the row actually has a selection.
|
||||
int iSelection = GetOneSelection(pn, true);
|
||||
if( iSelection == -1 )
|
||||
{
|
||||
ASSERT( !m_vbSelected[pn].empty() );
|
||||
m_vbSelected[pn][0] = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ResetFocusFromSelection( pn );
|
||||
@@ -503,7 +506,7 @@ void OptionRow::UpdateText( PlayerNumber p )
|
||||
{
|
||||
switch( m_pHand->m_Def.m_layoutType )
|
||||
{
|
||||
case LAYOUT_SHOW_ONE_IN_ROW:
|
||||
case LAYOUT_SHOW_ONE_IN_ROW:
|
||||
{
|
||||
unsigned pn = m_pHand->m_Def.m_bOneChoiceForAllPlayers ? 0 : p;
|
||||
int iChoiceWithFocus = m_iChoiceInRowWithFocus[pn];
|
||||
@@ -519,7 +522,7 @@ void OptionRow::UpdateText( PlayerNumber p )
|
||||
|
||||
m_textItems[index]->SetText( sText );
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,10 +760,11 @@ void OptionRow::ResetFocusFromSelection( PlayerNumber pn )
|
||||
int iSelection = -1;
|
||||
switch( m_pHand->m_Def.m_selectType )
|
||||
{
|
||||
case SELECT_ONE:
|
||||
// Import the focus from the selected option.
|
||||
iSelection = GetOneSelection( pn, true );
|
||||
break;
|
||||
case SELECT_ONE:
|
||||
// Import the focus from the selected option.
|
||||
iSelection = GetOneSelection( pn, true );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// HACK: Set focus to one item in the row, which is "go down"
|
||||
|
||||
+65
-59
@@ -137,13 +137,14 @@ void PaneDisplay::SetContent( PaneCategory c )
|
||||
{
|
||||
switch( c )
|
||||
{
|
||||
case PaneCategory_MachineHighName:
|
||||
str = EMPTY_MACHINE_HIGH_SCORE_NAME;
|
||||
break;
|
||||
case PaneCategory_MachineHighScore:
|
||||
case PaneCategory_ProfileHighScore:
|
||||
str = NOT_AVAILABLE;
|
||||
break;
|
||||
case PaneCategory_MachineHighName:
|
||||
str = EMPTY_MACHINE_HIGH_SCORE_NAME;
|
||||
break;
|
||||
case PaneCategory_MachineHighScore:
|
||||
case PaneCategory_ProfileHighScore:
|
||||
str = NOT_AVAILABLE;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,13 +158,14 @@ void PaneDisplay::SetContent( PaneCategory c )
|
||||
{
|
||||
switch( c )
|
||||
{
|
||||
case PaneCategory_MachineHighName:
|
||||
str = EMPTY_MACHINE_HIGH_SCORE_NAME;
|
||||
break;
|
||||
case PaneCategory_MachineHighScore:
|
||||
case PaneCategory_ProfileHighScore:
|
||||
str = NOT_AVAILABLE;
|
||||
break;
|
||||
case PaneCategory_MachineHighName:
|
||||
str = EMPTY_MACHINE_HIGH_SCORE_NAME;
|
||||
break;
|
||||
case PaneCategory_MachineHighScore:
|
||||
case PaneCategory_ProfileHighScore:
|
||||
str = NOT_AVAILABLE;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +186,9 @@ void PaneDisplay::SetContent( PaneCategory c )
|
||||
ProfileSlot slot = ProfileSlot_Machine;
|
||||
switch( c )
|
||||
{
|
||||
case PaneCategory_ProfileHighScore:
|
||||
slot = (ProfileSlot) m_PlayerNumber;
|
||||
case PaneCategory_ProfileHighScore:
|
||||
slot = (ProfileSlot) m_PlayerNumber;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( pSteps )
|
||||
@@ -201,55 +204,58 @@ void PaneDisplay::SetContent( PaneCategory c )
|
||||
|
||||
switch( c )
|
||||
{
|
||||
case PaneCategory_NumSteps: val = rv[RadarCategory_TapsAndHolds]; break;
|
||||
case PaneCategory_Jumps: val = rv[RadarCategory_Jumps]; break;
|
||||
case PaneCategory_Holds: val = rv[RadarCategory_Holds]; break;
|
||||
case PaneCategory_Rolls: val = rv[RadarCategory_Rolls]; break;
|
||||
case PaneCategory_Mines: val = rv[RadarCategory_Mines]; break;
|
||||
case PaneCategory_Hands: val = rv[RadarCategory_Hands]; break;
|
||||
case PaneCategory_Lifts: val = rv[RadarCategory_Lifts]; break;
|
||||
case PaneCategory_Fakes: val = rv[RadarCategory_Fakes]; break;
|
||||
case PaneCategory_ProfileHighScore:
|
||||
case PaneCategory_MachineHighName: // set val for color
|
||||
case PaneCategory_MachineHighScore:
|
||||
CHECKPOINT;
|
||||
val = pHSL->GetTopScore().GetPercentDP();
|
||||
break;
|
||||
case PaneCategory_NumSteps: val = rv[RadarCategory_TapsAndHolds]; break;
|
||||
case PaneCategory_Jumps: val = rv[RadarCategory_Jumps]; break;
|
||||
case PaneCategory_Holds: val = rv[RadarCategory_Holds]; break;
|
||||
case PaneCategory_Rolls: val = rv[RadarCategory_Rolls]; break;
|
||||
case PaneCategory_Mines: val = rv[RadarCategory_Mines]; break;
|
||||
case PaneCategory_Hands: val = rv[RadarCategory_Hands]; break;
|
||||
case PaneCategory_Lifts: val = rv[RadarCategory_Lifts]; break;
|
||||
case PaneCategory_Fakes: val = rv[RadarCategory_Fakes]; break;
|
||||
case PaneCategory_ProfileHighScore:
|
||||
case PaneCategory_MachineHighName: // set val for color
|
||||
case PaneCategory_MachineHighScore:
|
||||
CHECKPOINT;
|
||||
val = pHSL->GetTopScore().GetPercentDP();
|
||||
break;
|
||||
default: break;
|
||||
};
|
||||
|
||||
if( val != RADAR_VAL_UNKNOWN )
|
||||
{
|
||||
switch( c )
|
||||
{
|
||||
case PaneCategory_MachineHighName:
|
||||
if( pHSL->vHighScores.empty() )
|
||||
{
|
||||
str = EMPTY_MACHINE_HIGH_SCORE_NAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
str = pHSL->GetTopScore().GetName();
|
||||
if( str.empty() )
|
||||
str = "????";
|
||||
}
|
||||
break;
|
||||
case PaneCategory_MachineHighScore:
|
||||
case PaneCategory_ProfileHighScore:
|
||||
// Don't show or save machine high scores for edits loaded from a player profile.
|
||||
if( bIsPlayerEdit )
|
||||
str = NOT_AVAILABLE;
|
||||
else
|
||||
str = PlayerStageStats::FormatPercentScore( val );
|
||||
break;
|
||||
case PaneCategory_NumSteps:
|
||||
case PaneCategory_Jumps:
|
||||
case PaneCategory_Holds:
|
||||
case PaneCategory_Rolls:
|
||||
case PaneCategory_Mines:
|
||||
case PaneCategory_Hands:
|
||||
case PaneCategory_Lifts:
|
||||
case PaneCategory_Fakes:
|
||||
str = ssprintf( COUNT_FORMAT.GetValue(), val );
|
||||
case PaneCategory_MachineHighName:
|
||||
if( pHSL->vHighScores.empty() )
|
||||
{
|
||||
str = EMPTY_MACHINE_HIGH_SCORE_NAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
str = pHSL->GetTopScore().GetName();
|
||||
if( str.empty() )
|
||||
str = "????";
|
||||
}
|
||||
break;
|
||||
case PaneCategory_MachineHighScore:
|
||||
case PaneCategory_ProfileHighScore:
|
||||
// Don't show or save machine high scores for edits loaded from a player profile.
|
||||
if( bIsPlayerEdit )
|
||||
str = NOT_AVAILABLE;
|
||||
else
|
||||
str = PlayerStageStats::FormatPercentScore( val );
|
||||
break;
|
||||
case PaneCategory_NumSteps:
|
||||
case PaneCategory_Jumps:
|
||||
case PaneCategory_Holds:
|
||||
case PaneCategory_Rolls:
|
||||
case PaneCategory_Mines:
|
||||
case PaneCategory_Hands:
|
||||
case PaneCategory_Lifts:
|
||||
case PaneCategory_Fakes:
|
||||
str = ssprintf( COUNT_FORMAT.GetValue(), val );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+43
-37
@@ -628,8 +628,8 @@ void Player::Load()
|
||||
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_RAVE:
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
case PLAY_MODE_BATTLE:
|
||||
{
|
||||
// ugly, ugly, ugly. Works only w/ dance.
|
||||
// Why does this work only with dance? - Steve
|
||||
@@ -659,8 +659,9 @@ void Player::Load()
|
||||
count++;
|
||||
count %= 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
int iDrawDistanceAfterTargetsPixels = GAMESTATE->IsEditing() ? -100 : DRAW_DISTANCE_AFTER_TARGET_PIXELS;
|
||||
@@ -2879,41 +2880,46 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
||||
int iTrack = iter.Track();
|
||||
switch( tn.type )
|
||||
{
|
||||
case TapNote::hold_head:
|
||||
tn.HoldResult.fLife = INITIAL_HOLD_LIFE;
|
||||
if( !REQUIRE_STEP_ON_HOLD_HEADS )
|
||||
case TapNote::hold_head:
|
||||
{
|
||||
tn.HoldResult.fLife = INITIAL_HOLD_LIFE;
|
||||
if( !REQUIRE_STEP_ON_HOLD_HEADS )
|
||||
{
|
||||
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
|
||||
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iTrack, pn );
|
||||
if( PREFSMAN->m_fPadStickSeconds > 0.f )
|
||||
{
|
||||
float fSecsHeld = INPUTMAPPER->GetSecsHeld( GameI, m_pPlayerState->m_mp );
|
||||
if( fSecsHeld >= PREFSMAN->m_fPadStickSeconds )
|
||||
Step( iTrack, -1, now - PREFSMAN->m_fPadStickSeconds, true, false );
|
||||
}
|
||||
else if( INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp) )
|
||||
{
|
||||
Step( iTrack, -1, now, true, false );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TapNote::mine:
|
||||
{
|
||||
// Hold the panel while crossing a mine will cause the mine to explode
|
||||
// TODO: Remove use of PlayerNumber.
|
||||
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
|
||||
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iTrack, pn );
|
||||
if( PREFSMAN->m_fPadStickSeconds > 0.f )
|
||||
if( PREFSMAN->m_fPadStickSeconds > 0 )
|
||||
{
|
||||
float fSecsHeld = INPUTMAPPER->GetSecsHeld( GameI, m_pPlayerState->m_mp );
|
||||
if( fSecsHeld >= PREFSMAN->m_fPadStickSeconds )
|
||||
Step( iTrack, -1, now - PREFSMAN->m_fPadStickSeconds, true, false );
|
||||
}
|
||||
else if( INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp) )
|
||||
else
|
||||
{
|
||||
Step( iTrack, -1, now, true, false );
|
||||
if( INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp) )
|
||||
Step( iTrack, iRow, now, true, false );
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TapNote::mine:
|
||||
// Hold the panel while crossing a mine will cause the mine to explode
|
||||
// TODO: Remove use of PlayerNumber.
|
||||
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
|
||||
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iTrack, pn );
|
||||
if( PREFSMAN->m_fPadStickSeconds > 0 )
|
||||
{
|
||||
float fSecsHeld = INPUTMAPPER->GetSecsHeld( GameI, m_pPlayerState->m_mp );
|
||||
if( fSecsHeld >= PREFSMAN->m_fPadStickSeconds )
|
||||
Step( iTrack, -1, now - PREFSMAN->m_fPadStickSeconds, true, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp) )
|
||||
Step( iTrack, iRow, now, true, false );
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( iRow != iLastSeenRow )
|
||||
@@ -2956,21 +2962,21 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
||||
}
|
||||
else if( CHECKPOINTS_USE_TIME_SIGNATURES )
|
||||
{
|
||||
TimeSignatureSegment & tSignature = m_Timing->GetTimeSignatureSegmentAtRow( iLastRowCrossed );
|
||||
TimeSignatureSegment * tSignature = m_Timing->GetTimeSignatureSegmentAtRow( iLastRowCrossed );
|
||||
|
||||
// Most songs are in 4/4 time. The frequency for checking tick counts should reflect that.
|
||||
iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature.GetDen() / (tSignature.GetNum() * 4);
|
||||
iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature->GetDen() / (tSignature->GetNum() * 4);
|
||||
}
|
||||
|
||||
if( iCheckpointFrequencyRows > 0 )
|
||||
{
|
||||
// "the first row after the start of the range that lands on a beat"
|
||||
int iFirstCheckpointInRange = QuantizeUp(m_iFirstUncrossedRow,
|
||||
iCheckpointFrequencyRows);
|
||||
int iFirstCheckpointInRange = ((m_iFirstUncrossedRow+iCheckpointFrequencyRows-1)
|
||||
/iCheckpointFrequencyRows) * iCheckpointFrequencyRows;
|
||||
|
||||
// "the last row or first row earlier that lands on a beat"
|
||||
int iLastCheckpointInRange = QuantizeDown(iLastRowCrossed,
|
||||
iCheckpointFrequencyRows);
|
||||
int iLastCheckpointInRange = ((iLastRowCrossed)/iCheckpointFrequencyRows)
|
||||
* iCheckpointFrequencyRows;
|
||||
|
||||
for( int r = iFirstCheckpointInRange; r <= iLastCheckpointInRange; r += iCheckpointFrequencyRows )
|
||||
{
|
||||
@@ -2992,12 +2998,12 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
||||
int iTrack = nIter.Track();
|
||||
|
||||
// "the first row after the hold head that lands on a beat"
|
||||
int iFirstCheckpointOfHold = QuantizeUp(iStartRow,
|
||||
iCheckpointFrequencyRows);
|
||||
int iFirstCheckpointOfHold = ((iStartRow+iCheckpointFrequencyRows)/iCheckpointFrequencyRows)
|
||||
* iCheckpointFrequencyRows;
|
||||
|
||||
// "the end row or the first earlier row that lands on a beat"
|
||||
int iLastCheckpointOfHold = QuantizeDown(iEndRow,
|
||||
iCheckpointFrequencyRows);
|
||||
int iLastCheckpointOfHold = ((iEndRow)/iCheckpointFrequencyRows)
|
||||
* iCheckpointFrequencyRows;
|
||||
|
||||
// count the end of the hold as a checkpoint
|
||||
bool bHoldOverlapsRow = iFirstCheckpointOfHold <= r && r <= iLastCheckpointOfHold;
|
||||
|
||||
+14
-11
@@ -274,6 +274,7 @@ float PlayerStageStats::GetCurMaxPercentDancePoints() const
|
||||
return fCurMaxPercentDancePoints;
|
||||
}
|
||||
|
||||
// TODO: Make this use lua. Let more judgments be possible. -Wolfman2000
|
||||
int PlayerStageStats::GetLessonScoreActual() const
|
||||
{
|
||||
int iScore = 0;
|
||||
@@ -282,14 +283,15 @@ int PlayerStageStats::GetLessonScoreActual() const
|
||||
{
|
||||
switch( tns )
|
||||
{
|
||||
case TNS_AvoidMine:
|
||||
case TNS_W5:
|
||||
case TNS_W4:
|
||||
case TNS_W3:
|
||||
case TNS_W2:
|
||||
case TNS_W1:
|
||||
iScore += m_iTapNoteScores[tns];
|
||||
break;
|
||||
case TNS_AvoidMine:
|
||||
case TNS_W5:
|
||||
case TNS_W4:
|
||||
case TNS_W3:
|
||||
case TNS_W2:
|
||||
case TNS_W1:
|
||||
iScore += m_iTapNoteScores[tns];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,9 +299,10 @@ int PlayerStageStats::GetLessonScoreActual() const
|
||||
{
|
||||
switch( hns )
|
||||
{
|
||||
case HNS_Held:
|
||||
iScore += m_iHoldNoteScores[hns];
|
||||
break;
|
||||
case HNS_Held:
|
||||
iScore += m_iHoldNoteScores[hns];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-25
@@ -340,7 +340,7 @@ GLhandleARB CompileShader( GLenum ShaderType, RString sFile, vector<RString> asD
|
||||
GLhandleARB LoadShader( GLenum ShaderType, RString sFile, vector<RString> asDefines )
|
||||
{
|
||||
// Don't do anything here if not the hardware/driver can't do it!
|
||||
if (!GLEW_ARB_fragment_program && GLEW_ARB_shading_language_100 && ShaderType == GL_FRAGMENT_SHADER_ARB)
|
||||
if (!GLEW_ARB_fragment_shader && ShaderType == GL_FRAGMENT_SHADER_ARB)
|
||||
return 0;
|
||||
if (!GLEW_ARB_vertex_shader && ShaderType == GL_VERTEX_SHADER_ARB)
|
||||
return 0;
|
||||
@@ -1625,6 +1625,7 @@ void RageDisplay_Legacy::SetTextureMode( TextureUnit tu, TextureMode tm )
|
||||
glTexEnvi(GL_TEXTURE_ENV, GLenum(GL_OPERAND1_ALPHA_EXT), GL_SRC_ALPHA);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GLenum(GL_SOURCE1_ALPHA_EXT), GL_TEXTURE);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1662,21 +1663,22 @@ void RageDisplay_Legacy::SetTextureFiltering( TextureUnit tu, bool b )
|
||||
|
||||
void RageDisplay_Legacy::SetEffectMode( EffectMode effect )
|
||||
{
|
||||
if (!GLEW_ARB_fragment_program && !GLEW_ARB_shading_language_100)
|
||||
if (!GLEW_ARB_fragment_shader)
|
||||
return;
|
||||
|
||||
GLhandleARB hShader = 0;
|
||||
switch (effect)
|
||||
{
|
||||
case EffectMode_Normal: hShader = 0; break;
|
||||
case EffectMode_Unpremultiply: hShader = g_bUnpremultiplyShader; break;
|
||||
case EffectMode_ColorBurn: hShader = g_bColorBurnShader; break;
|
||||
case EffectMode_ColorDodge: hShader = g_bColorDodgeShader; break;
|
||||
case EffectMode_VividLight: hShader = g_bVividLightShader; break;
|
||||
case EffectMode_HardMix: hShader = g_hHardMixShader; break;
|
||||
case EffectMode_Overlay: hShader = g_hOverlayShader; break;
|
||||
case EffectMode_Screen: hShader = g_hScreenShader; break;
|
||||
case EffectMode_YUYV422: hShader = g_hYUYV422Shader; break;
|
||||
case EffectMode_Normal: hShader = 0; break;
|
||||
case EffectMode_Unpremultiply: hShader = g_bUnpremultiplyShader; break;
|
||||
case EffectMode_ColorBurn: hShader = g_bColorBurnShader; break;
|
||||
case EffectMode_ColorDodge: hShader = g_bColorDodgeShader; break;
|
||||
case EffectMode_VividLight: hShader = g_bVividLightShader; break;
|
||||
case EffectMode_HardMix: hShader = g_hHardMixShader; break;
|
||||
case EffectMode_Overlay: hShader = g_hOverlayShader; break;
|
||||
case EffectMode_Screen: hShader = g_hScreenShader; break;
|
||||
case EffectMode_YUYV422: hShader = g_hYUYV422Shader; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
DebugFlushGLErrors();
|
||||
@@ -1703,18 +1705,17 @@ bool RageDisplay_Legacy::IsEffectModeSupported( EffectMode effect )
|
||||
{
|
||||
switch( effect )
|
||||
{
|
||||
case EffectMode_Normal: return true;
|
||||
case EffectMode_Unpremultiply: return g_bUnpremultiplyShader != 0;
|
||||
case EffectMode_ColorBurn: return g_bColorBurnShader != 0;
|
||||
case EffectMode_ColorDodge: return g_bColorDodgeShader != 0;
|
||||
case EffectMode_VividLight: return g_bVividLightShader != 0;
|
||||
case EffectMode_HardMix: return g_hHardMixShader != 0;
|
||||
case EffectMode_Overlay: return g_hOverlayShader != 0;
|
||||
case EffectMode_Screen: return g_hScreenShader != 0;
|
||||
case EffectMode_YUYV422: return g_hYUYV422Shader != 0;
|
||||
case EffectMode_Normal: return true;
|
||||
case EffectMode_Unpremultiply: return g_bUnpremultiplyShader != 0;
|
||||
case EffectMode_ColorBurn: return g_bColorBurnShader != 0;
|
||||
case EffectMode_ColorDodge: return g_bColorDodgeShader != 0;
|
||||
case EffectMode_VividLight: return g_bVividLightShader != 0;
|
||||
case EffectMode_HardMix: return g_hHardMixShader != 0;
|
||||
case EffectMode_Overlay: return g_hOverlayShader != 0;
|
||||
case EffectMode_Screen: return g_hScreenShader != 0;
|
||||
case EffectMode_YUYV422: return g_hYUYV422Shader != 0;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RageDisplay_Legacy::SetBlendMode( BlendMode mode )
|
||||
@@ -2648,11 +2649,9 @@ void RageDisplay_Legacy::SetSphereEnvironmentMapping(TextureUnit tu, bool b)
|
||||
}
|
||||
}
|
||||
|
||||
GLint iCelTexture1, iCelTexture2 = 0;
|
||||
|
||||
void RageDisplay_Legacy::SetCelShaded( int stage )
|
||||
{
|
||||
if (!GLEW_ARB_fragment_program && !GL_ARB_shading_language_100)
|
||||
if (!GLEW_ARB_fragment_shader)
|
||||
return; // not supported
|
||||
|
||||
switch (stage)
|
||||
|
||||
+10
-9
@@ -576,15 +576,16 @@ void RageSound::ApplyParams()
|
||||
|
||||
switch( GetStopMode() )
|
||||
{
|
||||
case RageSoundParams::M_LOOP:
|
||||
m_pSource->SetProperty( "Loop", 1.0f );
|
||||
break;
|
||||
case RageSoundParams::M_STOP:
|
||||
m_pSource->SetProperty( "Stop", 1.0f );
|
||||
break;
|
||||
case RageSoundParams::M_CONTINUE:
|
||||
m_pSource->SetProperty( "Continue", 1.0f );
|
||||
break;
|
||||
case RageSoundParams::M_LOOP:
|
||||
m_pSource->SetProperty( "Loop", 1.0f );
|
||||
break;
|
||||
case RageSoundParams::M_STOP:
|
||||
m_pSource->SetProperty( "Stop", 1.0f );
|
||||
break;
|
||||
case RageSoundParams::M_CONTINUE:
|
||||
m_pSource->SetProperty( "Continue", 1.0f );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,17 +67,18 @@ RageSoundReader_FileReader *RageSoundReader_FileReader::TryOpenFile( RageFileBas
|
||||
bKeepTrying = (ret != OPEN_FATAL_ERROR);
|
||||
switch( ret )
|
||||
{
|
||||
case OPEN_UNKNOWN_FILE_FORMAT:
|
||||
bKeepTrying = true;
|
||||
error = "Unknown file format";
|
||||
break;
|
||||
case OPEN_UNKNOWN_FILE_FORMAT:
|
||||
bKeepTrying = true;
|
||||
error = "Unknown file format";
|
||||
break;
|
||||
|
||||
case OPEN_FATAL_ERROR:
|
||||
/* The file matched, but failed to load. We know it's this type of data;
|
||||
* don't bother trying the other file types. */
|
||||
bKeepTrying = false;
|
||||
error = err;
|
||||
break;
|
||||
case OPEN_FATAL_ERROR:
|
||||
/* The file matched, but failed to load. We know it's this type of data;
|
||||
* don't bother trying the other file types. */
|
||||
bKeepTrying = false;
|
||||
error = err;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -57,16 +57,17 @@ static RageSurface *TryOpenFile( RString sPath, bool bHeaderOnly, RString &error
|
||||
bKeepTrying = (result != RageSurfaceUtils::OPEN_FATAL_ERROR);
|
||||
switch( result )
|
||||
{
|
||||
case RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT:
|
||||
bKeepTrying = true;
|
||||
error = "Unknown file format";
|
||||
break;
|
||||
case RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT:
|
||||
bKeepTrying = true;
|
||||
error = "Unknown file format";
|
||||
break;
|
||||
|
||||
case RageSurfaceUtils::OPEN_FATAL_ERROR:
|
||||
/* The file matched, but failed to load. We know it's this type of data;
|
||||
* don't bother trying the other file types. */
|
||||
bKeepTrying = false;
|
||||
break;
|
||||
case RageSurfaceUtils::OPEN_FATAL_ERROR:
|
||||
/* The file matched, but failed to load. We know it's this type of data;
|
||||
* don't bother trying the other file types. */
|
||||
bKeepTrying = false;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -1731,6 +1731,13 @@ bool StringToFloat( const RString &sString, float &fOut )
|
||||
return sString.size() && *endPtr == '\0' && isfinite( fOut );
|
||||
}
|
||||
|
||||
RString FloatToString( const float &num )
|
||||
{
|
||||
stringstream ss;
|
||||
ss << num;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
const wchar_t INVALID_CHAR = 0xFFFD; /* U+FFFD REPLACEMENT CHARACTER */
|
||||
|
||||
wstring RStringToWstring( const RString &s )
|
||||
|
||||
@@ -416,6 +416,7 @@ int StringToInt( const RString &sString );
|
||||
* @return the string we are after. */
|
||||
RString IntToString( const int &iNum );
|
||||
float StringToFloat( const RString &sString );
|
||||
RString FloatToString( const float &num );
|
||||
bool StringToFloat( const RString &sString, float &fOut );
|
||||
|
||||
RString WStringToRString( const wstring &sString );
|
||||
|
||||
@@ -429,14 +429,14 @@ void ScoreKeeperNormal::HandleTapNoteScoreInternal( TapNoteScore tns, TapNoteSco
|
||||
|
||||
// update judged row totals. Respect Combo segments here.
|
||||
TimingData &td = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing;
|
||||
ComboSegment &cs = td.GetComboSegmentAtRow(row);
|
||||
ComboSegment *cs = td.GetComboSegmentAtRow(row);
|
||||
if (tns == TNS_CheckpointHit || tns >= m_MinScoreToContinueCombo)
|
||||
{
|
||||
m_pPlayerStageStats->m_iTapNoteScores[tns] += cs.GetCombo();
|
||||
m_pPlayerStageStats->m_iTapNoteScores[tns] += cs->GetCombo();
|
||||
}
|
||||
else if (tns == TNS_CheckpointMiss || tns < m_MinScoreToMaintainCombo)
|
||||
{
|
||||
m_pPlayerStageStats->m_iTapNoteScores[tns] += cs.GetMissCombo();
|
||||
m_pPlayerStageStats->m_iTapNoteScores[tns] += cs->GetMissCombo();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -464,13 +464,13 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH
|
||||
TimingData td = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing;
|
||||
if( iNumBreakCombo == 0 )
|
||||
{
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).GetCombo() );
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow )->GetCombo() );
|
||||
m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo * multiplier;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pPlayerStageStats->m_iCurCombo = 0;
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow(iRow).GetMissCombo());
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow(iRow)->GetMissCombo());
|
||||
m_pPlayerStageStats->m_iCurMissCombo += ( m_MissComboIsPerRow ? 1 : iNumBreakCombo ) * multiplier;
|
||||
}
|
||||
}
|
||||
@@ -485,7 +485,7 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn
|
||||
if ( tns >= m_MinScoreToContinueCombo )
|
||||
{
|
||||
m_pPlayerStageStats->m_iCurMissCombo = 0;
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).GetCombo() );
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow )->GetCombo() );
|
||||
m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow * multiplier;
|
||||
}
|
||||
else if ( tns < m_MinScoreToMaintainCombo )
|
||||
@@ -494,7 +494,7 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn
|
||||
|
||||
if( tns <= m_MaxScoreToIncrementMissCombo )
|
||||
{
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow(iRow).GetMissCombo());
|
||||
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow(iRow)->GetMissCombo());
|
||||
m_pPlayerStageStats->m_iCurMissCombo += ( m_MissComboIsPerRow ? 1 : iNumTapsInRow ) * multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,10 @@ void ScoreKeeperRave::HandleHoldScore( const TapNote &tn )
|
||||
float fPercentToMove = 0;
|
||||
switch( tapScore )
|
||||
{
|
||||
case TNS_HitMine: fPercentToMove = g_fSuperMeterPercentChange[SE_HitMine]; break;
|
||||
case TNS_HitMine:
|
||||
fPercentToMove = g_fSuperMeterPercentChange[SE_HitMine];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
AddSuperMeterDelta( fPercentToMove );
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ void Screen::Input( const InputEventPlus &input )
|
||||
case GAME_BUTTON_START: this->MenuStart ( input ); return;
|
||||
case GAME_BUTTON_SELECT:this->MenuSelect( input ); return;
|
||||
case GAME_BUTTON_COIN: this->MenuCoin ( input ); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-29
@@ -75,34 +75,36 @@ void ScreenAttract::AttractInput( const InputEventPlus &input, ScreenWithMenuEle
|
||||
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_BACK:
|
||||
if( !(bool)BACK_GOES_TO_START_SCREEN )
|
||||
break;
|
||||
// fall through
|
||||
case GAME_BUTTON_START:
|
||||
case GAME_BUTTON_COIN:
|
||||
switch( GAMESTATE->GetCoinMode() )
|
||||
{
|
||||
case CoinMode_Pay:
|
||||
LOG->Trace("ScreenAttract::AttractInput: COIN_PAY (%i/%i, %i)", GAMESTATE->m_iCoins.Get(), PREFSMAN->m_iCoinsPerCredit.Get(), GAMESTATE->GetNumSidesJoined() );
|
||||
if( GAMESTATE->m_iCoins < PREFSMAN->m_iCoinsPerCredit && GAMESTATE->GetNumSidesJoined() == 0 )
|
||||
break; // don't fall through
|
||||
case GAME_BUTTON_BACK:
|
||||
if( !BACK_GOES_TO_START_SCREEN )
|
||||
break;
|
||||
// fall through
|
||||
case CoinMode_Home:
|
||||
case CoinMode_Free:
|
||||
if( pScreen->IsTransitioning() )
|
||||
return;
|
||||
case GAME_BUTTON_START:
|
||||
case GAME_BUTTON_COIN:
|
||||
switch( GAMESTATE->GetCoinMode() )
|
||||
{
|
||||
case CoinMode_Pay:
|
||||
LOG->Trace("ScreenAttract::AttractInput: COIN_PAY (%i/%i, %i)",
|
||||
GAMESTATE->m_iCoins.Get(),
|
||||
PREFSMAN->m_iCoinsPerCredit.Get(),
|
||||
GAMESTATE->GetNumSidesJoined() );
|
||||
if( GAMESTATE->m_iCoins < PREFSMAN->m_iCoinsPerCredit && GAMESTATE->GetNumSidesJoined() == 0 )
|
||||
break; // don't fall through
|
||||
// fall through
|
||||
case CoinMode_Home:
|
||||
case CoinMode_Free:
|
||||
if( pScreen->IsTransitioning() )
|
||||
return;
|
||||
|
||||
// HandleGlobalInputs() already played the coin sound. Don't play it again.
|
||||
if( input.MenuI != GAME_BUTTON_COIN )
|
||||
SCREENMAN->PlayStartSound();
|
||||
// HandleGlobalInputs() already played the coin sound. Don't play it again.
|
||||
if( input.MenuI != GAME_BUTTON_COIN )
|
||||
SCREENMAN->PlayStartSound();
|
||||
|
||||
pScreen->Cancel( SM_GoToStartScreen );
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
break;
|
||||
pScreen->Cancel( SM_GoToStartScreen );
|
||||
break;
|
||||
default: FAIL_M("Invalid Coin Mode! Aborting...");
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( pScreen->IsTransitioning() )
|
||||
@@ -110,10 +112,11 @@ void ScreenAttract::AttractInput( const InputEventPlus &input, ScreenWithMenuEle
|
||||
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_LEFT:
|
||||
case GAME_BUTTON_RIGHT:
|
||||
SCREENMAN->PostMessageToTopScreen( SM_BeginFadingOut, 0 );
|
||||
break;
|
||||
case GAME_BUTTON_LEFT:
|
||||
case GAME_BUTTON_RIGHT:
|
||||
SCREENMAN->PostMessageToTopScreen( SM_BeginFadingOut, 0 );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Screen::Input( input );
|
||||
|
||||
+15
-12
@@ -63,18 +63,21 @@ void ScreenContinue::Input( const InputEventPlus &input )
|
||||
{
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_START:
|
||||
case GAME_BUTTON_UP:
|
||||
case GAME_BUTTON_DOWN:
|
||||
case GAME_BUTTON_LEFT:
|
||||
case GAME_BUTTON_RIGHT:
|
||||
float fSeconds = floorf(m_MenuTimer->GetSeconds()) - 0.0001f;
|
||||
fSeconds = max( fSeconds, 0.0001f ); // don't set to 0
|
||||
m_MenuTimer->SetSeconds( fSeconds );
|
||||
Message msg("HurryTimer");
|
||||
msg.SetParam( "PlayerNumber", input.pn );
|
||||
this->HandleMessage( msg );
|
||||
return; // handled
|
||||
case GAME_BUTTON_START:
|
||||
case GAME_BUTTON_UP:
|
||||
case GAME_BUTTON_DOWN:
|
||||
case GAME_BUTTON_LEFT:
|
||||
case GAME_BUTTON_RIGHT:
|
||||
{
|
||||
float fSeconds = floorf(m_MenuTimer->GetSeconds()) - 0.0001f;
|
||||
fSeconds = max( fSeconds, 0.0001f ); // don't set to 0
|
||||
m_MenuTimer->SetSeconds( fSeconds );
|
||||
Message msg("HurryTimer");
|
||||
msg.SetParam( "PlayerNumber", input.pn );
|
||||
this->HandleMessage( msg );
|
||||
return; // handled
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -813,12 +813,11 @@ class DebugLineProfileSlot : public IDebugLine
|
||||
{
|
||||
switch( g_ProfileSlot )
|
||||
{
|
||||
case ProfileSlot_Machine: return "Machine";
|
||||
case ProfileSlot_Player1: return "Player 1";
|
||||
case ProfileSlot_Player2: return "Player 2";
|
||||
case ProfileSlot_Machine: return "Machine";
|
||||
case ProfileSlot_Player1: return "Player 1";
|
||||
case ProfileSlot_Player2: return "Player 2";
|
||||
default: return RString();
|
||||
}
|
||||
|
||||
return RString();
|
||||
}
|
||||
virtual bool IsEnabled() { return IsSelectProfilePersistent(); }
|
||||
virtual RString GetPageName() const { return "Profiles"; }
|
||||
|
||||
+48
-117
@@ -257,6 +257,7 @@ void ScreenEdit::InitEditMappings()
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_DELETE_SHIFT_PAUSES][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_DELETE_SHIFT_PAUSES][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_COLUMN_0][0] = DeviceInput(DEVICE_KEYBOARD, KEY_C1);
|
||||
@@ -812,7 +813,7 @@ void ScreenEdit::Init()
|
||||
|
||||
InitEditMappings();
|
||||
|
||||
currentCycleSegment = "label";
|
||||
currentCycleSegment = SEGMENT_LABEL;
|
||||
|
||||
// save the originals for reverting later
|
||||
CopyToLastSave();
|
||||
@@ -1261,7 +1262,7 @@ void ScreenEdit::UpdateTextInfo()
|
||||
sText += ssprintf( MAIN_TITLE_FORMAT.GetValue(), MAIN_TITLE.GetValue().c_str(), m_pSong->m_sMainTitle.c_str() );
|
||||
if( m_pSong->m_sSubTitle.size() )
|
||||
sText += ssprintf( SUBTITLE_FORMAT.GetValue(), SUBTITLE.GetValue().c_str(), m_pSong->m_sSubTitle.c_str() );
|
||||
sText += ssprintf( SEGMENT_TYPE_FORMAT.GetValue(), SEGMENT_TYPE.GetValue().c_str(), currentCycleSegment.c_str() );
|
||||
sText += ssprintf( SEGMENT_TYPE_FORMAT.GetValue(), SEGMENT_TYPE.GetValue().c_str(), TimingSegmentTypeToString(currentCycleSegment).c_str() );
|
||||
sText += ssprintf( TAP_NOTE_TYPE_FORMAT.GetValue(), TAP_NOTE_TYPE.GetValue().c_str(), TapNoteTypeToString( m_selectedTap.type ).c_str() );
|
||||
break;
|
||||
}
|
||||
@@ -1465,7 +1466,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
}
|
||||
TimingData &sTiming = GetAppropriateTiming();
|
||||
float playerBeat = GetAppropriatePosition().m_fSongBeat;
|
||||
int beatsPerMeasure = sTiming.GetTimeSignatureSegmentAtBeat( playerBeat ).GetNum();
|
||||
int beatsPerMeasure = sTiming.GetTimeSignatureSegmentAtBeat( playerBeat )->GetNum();
|
||||
|
||||
switch( EditB )
|
||||
{
|
||||
@@ -1559,60 +1560,15 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
}
|
||||
case EDIT_BUTTON_CYCLE_SEGMENT_LEFT:
|
||||
{
|
||||
if (this->currentCycleSegment == "label")
|
||||
this->currentCycleSegment = "fake";
|
||||
else if (this->currentCycleSegment == "fake")
|
||||
this->currentCycleSegment = "scroll";
|
||||
else if (this->currentCycleSegment == "scroll")
|
||||
this->currentCycleSegment = "speed";
|
||||
else if (this->currentCycleSegment == "speed")
|
||||
this->currentCycleSegment = "combo";
|
||||
else if (this->currentCycleSegment == "combo")
|
||||
this->currentCycleSegment = "tickcount";
|
||||
else if (this->currentCycleSegment == "tickcount")
|
||||
this->currentCycleSegment = "timeSig";
|
||||
else if (this->currentCycleSegment == "timeSig")
|
||||
this->currentCycleSegment = "warp";
|
||||
else if (this->currentCycleSegment == "warp")
|
||||
this->currentCycleSegment = "delay";
|
||||
else if (this->currentCycleSegment == "delay")
|
||||
this->currentCycleSegment = "stop";
|
||||
else if (this->currentCycleSegment == "stop")
|
||||
this->currentCycleSegment = "bpm";
|
||||
else if (this->currentCycleSegment == "bpm")
|
||||
this->currentCycleSegment = "label";
|
||||
// fallback gracefully instead of assert.
|
||||
else this->currentCycleSegment = "label";
|
||||
int tmp = enum_add2( this->currentCycleSegment, -1 );
|
||||
wrap( *ConvertValue<int>(&tmp), NUM_TimingSegmentType );
|
||||
break;
|
||||
}
|
||||
case EDIT_BUTTON_CYCLE_SEGMENT_RIGHT:
|
||||
{
|
||||
if (this->currentCycleSegment == "label")
|
||||
this->currentCycleSegment = "bpm";
|
||||
else if (this->currentCycleSegment == "bpm")
|
||||
this->currentCycleSegment = "stop";
|
||||
else if (this->currentCycleSegment == "stop")
|
||||
this->currentCycleSegment = "delay";
|
||||
else if (this->currentCycleSegment == "delay")
|
||||
this->currentCycleSegment = "warp";
|
||||
else if (this->currentCycleSegment == "warp")
|
||||
this->currentCycleSegment = "timeSig";
|
||||
else if (this->currentCycleSegment == "timeSig")
|
||||
this->currentCycleSegment = "tickcount";
|
||||
else if (this->currentCycleSegment == "tickcount")
|
||||
this->currentCycleSegment = "combo";
|
||||
else if (this->currentCycleSegment == "combo")
|
||||
this->currentCycleSegment = "speed";
|
||||
else if (this->currentCycleSegment == "speed")
|
||||
this->currentCycleSegment = "scroll";
|
||||
else if (this->currentCycleSegment == "scroll")
|
||||
this->currentCycleSegment = "fake";
|
||||
else if (this->currentCycleSegment == "fake")
|
||||
this->currentCycleSegment = "label";
|
||||
// fallback gracefully instead of assert.
|
||||
else this->currentCycleSegment = "label";
|
||||
break;
|
||||
}
|
||||
int tmp = enum_add2( this->currentCycleSegment, +1 );
|
||||
wrap( *ConvertValue<int>(&tmp), NUM_TimingSegmentType );
|
||||
break; }
|
||||
case EDIT_BUTTON_SCROLL_SPEED_UP:
|
||||
case EDIT_BUTTON_SCROLL_SPEED_DOWN:
|
||||
{
|
||||
@@ -1729,56 +1685,18 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
break;
|
||||
case EDIT_BUTTON_SEGMENT_NEXT:
|
||||
{
|
||||
// TODO: Work around Stops and Delays. We MAY have to separate them.
|
||||
TimingData &timing = GetAppropriateTiming();
|
||||
if (this->currentCycleSegment == "label")
|
||||
ScrollTo(timing.GetNextLabelSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "bpm")
|
||||
ScrollTo(timing.GetNextBPMSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "stop")
|
||||
ScrollTo(timing.GetNextStopSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "delay")
|
||||
ScrollTo(timing.GetNextDelaySegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "warp")
|
||||
ScrollTo(timing.GetNextWarpSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "timeSig")
|
||||
ScrollTo(timing.GetNextTimeSignatureSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "tickcount")
|
||||
ScrollTo(timing.GetNextTickcountSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "combo")
|
||||
ScrollTo(timing.GetNextComboSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "speed")
|
||||
ScrollTo(timing.GetNextSpeedSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "scroll")
|
||||
ScrollTo(timing.GetNextScrollSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "fake")
|
||||
ScrollTo(timing.GetNextFakeSegmentBeatAtBeat(GetBeat()));
|
||||
ScrollTo(timing.GetNextSegmentBeatAtBeat(this->currentCycleSegment,
|
||||
GetBeat()));
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_SEGMENT_PREV:
|
||||
{
|
||||
// TODO: Work around Stops and Delays. We MAY have to separate them.
|
||||
TimingData &timing = GetAppropriateTiming();
|
||||
if (this->currentCycleSegment == "label")
|
||||
ScrollTo(timing.GetPreviousLabelSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "bpm")
|
||||
ScrollTo(timing.GetPreviousBPMSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "stop")
|
||||
ScrollTo(timing.GetPreviousStopSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "delay")
|
||||
ScrollTo(timing.GetPreviousDelaySegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "warp")
|
||||
ScrollTo(timing.GetPreviousWarpSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "timeSig")
|
||||
ScrollTo(timing.GetPreviousTimeSignatureSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "tickcount")
|
||||
ScrollTo(timing.GetPreviousTickcountSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "combo")
|
||||
ScrollTo(timing.GetPreviousComboSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "speed")
|
||||
ScrollTo(timing.GetPreviousSpeedSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "scroll")
|
||||
ScrollTo(timing.GetPreviousScrollSegmentBeatAtBeat(GetBeat()));
|
||||
else if (this->currentCycleSegment == "fake")
|
||||
ScrollTo(timing.GetPreviousFakeSegmentBeatAtBeat(GetBeat()));
|
||||
ScrollTo(timing.GetPreviousSegmentBeatAtBeat(this->currentCycleSegment,
|
||||
GetBeat()));
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_SNAP_NEXT:
|
||||
@@ -1972,24 +1890,26 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
fDelta *= 40;
|
||||
}
|
||||
unsigned i;
|
||||
for( i=0; i<GetAppropriateTiming().m_StopSegments.size(); i++ )
|
||||
vector<TimingSegment *> &stops = GetAppropriateTiming().allTimingSegments[SEGMENT_STOP_DELAY];
|
||||
for( i=0; i<stops.size(); i++ )
|
||||
{
|
||||
if( GetAppropriateTiming().m_StopSegments[i].GetRow() == GetRow() )
|
||||
if( stops[i]->GetRow() == GetRow() )
|
||||
break;
|
||||
}
|
||||
|
||||
if( i == GetAppropriateTiming().m_StopSegments.size() ) // there is no StopSegment at the current beat
|
||||
if( i == stops.size() ) // there is no StopSegment at the current beat
|
||||
{
|
||||
// create a new StopSegment
|
||||
if( fDelta > 0 )
|
||||
GetAppropriateTiming().AddStopSegment( StopSegment( GetRow(), fDelta) );
|
||||
GetAppropriateTiming().AddSegment(SEGMENT_STOP_DELAY,
|
||||
new StopSegment( GetRow(), fDelta) );
|
||||
}
|
||||
else // StopSegment being modified is m_SongTiming.m_StopSegments[i]
|
||||
{
|
||||
vector<StopSegment> &s = GetAppropriateTiming().m_StopSegments;
|
||||
s[i].SetPause(s[i].GetPause() + fDelta);
|
||||
if( s[i].GetPause() <= 0 )
|
||||
s.erase( s.begin()+i, s.begin()+i+1);
|
||||
StopSegment *s = static_cast<StopSegment *>(stops[i]);
|
||||
s->SetPause(s->GetPause() + fDelta);
|
||||
if( s->GetPause() <= 0 )
|
||||
stops.erase( stops.begin()+i, stops.begin()+i+1);
|
||||
}
|
||||
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
|
||||
SetDirty( true );
|
||||
@@ -2468,6 +2388,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
GAMESTATE->m_bIsUsingStepTiming = !GAMESTATE->m_bIsUsingStepTiming;
|
||||
m_soundSwitchTiming.Play();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2575,6 +2496,7 @@ void ScreenEdit::InputRecordPaused( const InputEventPlus &input, EditButton Edit
|
||||
case EDIT_BUTTON_RETURN_TO_EDIT:
|
||||
TransitionEditState( STATE_EDITING );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2623,6 +2545,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB )
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2665,6 +2588,7 @@ void ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB )
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2731,6 +2655,7 @@ void ScreenEdit::TransitionEditState( EditState em )
|
||||
|
||||
CheckNumberOfNotesAndUndo();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2831,6 +2756,7 @@ void ScreenEdit::TransitionEditState( EditState em )
|
||||
m_NoteFieldRecord.m_iEndMarker = m_iStopPlayingAt;
|
||||
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Show/hide depending on edit state (em)
|
||||
@@ -2857,6 +2783,7 @@ void ScreenEdit::TransitionEditState( EditState em )
|
||||
{
|
||||
case STATE_PLAYING:
|
||||
case STATE_RECORDING:
|
||||
{
|
||||
const float fStartSeconds = GetAppropriateTiming().GetElapsedTimeFromBeat( GetBeat() );
|
||||
LOG->Trace( "Starting playback at %f", fStartSeconds );
|
||||
|
||||
@@ -2867,6 +2794,8 @@ void ScreenEdit::TransitionEditState( EditState em )
|
||||
m_pSoundMusic->SetProperty( "AccurateSync", true );
|
||||
m_pSoundMusic->Play( &p );
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_EditState = em;
|
||||
@@ -3646,7 +3575,7 @@ void ScreenEdit::DisplayTimingMenu()
|
||||
{
|
||||
float fBeat = GetBeat();
|
||||
TimingData &pTime = GetAppropriateTiming();
|
||||
bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat ).GetBeat() == fBeat;
|
||||
bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat )->GetBeat() == fBeat;
|
||||
|
||||
g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.6f", pTime.m_fBeat0OffsetInSeconds) );
|
||||
g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetBPMAtBeat( fBeat ) ) );
|
||||
@@ -4316,6 +4245,7 @@ void ScreenEdit::HandleAlterMenuChoice(AlterMenuChoice c, const vector<int> &iAn
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4589,6 +4519,7 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec
|
||||
ssprintf("%.6f", pSong->m_fSpecifiedBPMMax), 20,
|
||||
ScreenTextEntry::FloatValidate, ChangeMaxBPM, NULL );
|
||||
break;
|
||||
default: break;
|
||||
};
|
||||
SetDirty(true);
|
||||
}
|
||||
@@ -4645,11 +4576,11 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
|
||||
break;
|
||||
case time_signature:
|
||||
{
|
||||
TimeSignatureSegment &ts = GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() );
|
||||
TimeSignatureSegment * ts = GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() );
|
||||
ScreenTextEntry::TextEntry(
|
||||
SM_BackFromTimeSignatureChange,
|
||||
ENTER_TIME_SIGNATURE_VALUE,
|
||||
ssprintf( "%d/%d", ts.GetNum(), ts.GetDen() ),
|
||||
ssprintf( "%d/%d", ts->GetNum(), ts->GetDen() ),
|
||||
8
|
||||
);
|
||||
break;
|
||||
@@ -4664,12 +4595,12 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
|
||||
break;
|
||||
case combo:
|
||||
{
|
||||
ComboSegment &cs = GetAppropriateTiming().GetComboSegmentAtBeat(GetBeat());
|
||||
ComboSegment *cs = GetAppropriateTiming().GetComboSegmentAtBeat(GetBeat());
|
||||
ScreenTextEntry::TextEntry(SM_BackFromComboChange,
|
||||
ENTER_COMBO_VALUE,
|
||||
ssprintf( "%d/%d",
|
||||
cs.GetCombo(),
|
||||
cs.GetMissCombo()),
|
||||
cs->GetCombo(),
|
||||
cs->GetMissCombo()),
|
||||
7);
|
||||
break;
|
||||
}
|
||||
@@ -4693,7 +4624,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
|
||||
ScreenTextEntry::TextEntry(
|
||||
SM_BackFromSpeedPercentChange,
|
||||
ENTER_SPEED_PERCENT_VALUE,
|
||||
ssprintf( "%.6f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetRatio() ),
|
||||
ssprintf( "%.6f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() )->GetRatio() ),
|
||||
10
|
||||
);
|
||||
break;
|
||||
@@ -4701,7 +4632,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
|
||||
ScreenTextEntry::TextEntry(
|
||||
SM_BackFromScrollChange,
|
||||
ENTER_SCROLL_VALUE,
|
||||
ssprintf( "%.6f", GetAppropriateTiming().GetScrollSegmentAtBeat( GetBeat() ).GetRatio() ),
|
||||
ssprintf( "%.6f", GetAppropriateTiming().GetScrollSegmentAtBeat( GetBeat() )->GetRatio() ),
|
||||
10
|
||||
);
|
||||
break;
|
||||
@@ -4709,7 +4640,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
|
||||
ScreenTextEntry::TextEntry(
|
||||
SM_BackFromSpeedWaitChange,
|
||||
ENTER_SPEED_WAIT_VALUE,
|
||||
ssprintf( "%.6f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetLength() ),
|
||||
ssprintf( "%.6f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() )->GetLength() ),
|
||||
10
|
||||
);
|
||||
break;
|
||||
@@ -4980,8 +4911,8 @@ void ScreenEdit::CheckNumberOfNotesAndUndo()
|
||||
if( EDIT_MODE.GetValue() != EditMode_Home )
|
||||
return;
|
||||
|
||||
TimeSignatureSegment &curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat );
|
||||
int rowsPerMeasure = curTime.GetDen() * curTime.GetNum();
|
||||
TimeSignatureSegment * curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat );
|
||||
int rowsPerMeasure = curTime->GetDen() * curTime->GetNum();
|
||||
|
||||
for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure )
|
||||
{
|
||||
@@ -5035,7 +4966,7 @@ float ScreenEdit::GetMaximumBeatForNewNote() const
|
||||
* beats. */
|
||||
TimingData &timing = s.m_SongTiming;
|
||||
float playerBeat = GetAppropriatePosition().m_fSongBeat;
|
||||
int beatsPerMeasure = timing.GetTimeSignatureSegmentAtBeat( playerBeat ).GetNum();
|
||||
int beatsPerMeasure = timing.GetTimeSignatureSegmentAtBeat( playerBeat )->GetNum();
|
||||
fEndBeat += beatsPerMeasure;
|
||||
fEndBeat = ftruncf( fEndBeat, (float)beatsPerMeasure );
|
||||
|
||||
|
||||
+1
-1
@@ -286,7 +286,7 @@ protected:
|
||||
TapNote m_selectedTap;
|
||||
|
||||
/** @brief The type of segment users will jump back and forth between. */
|
||||
RString currentCycleSegment;
|
||||
TimingSegmentType currentCycleSegment;
|
||||
|
||||
void UpdateTextInfo();
|
||||
BitmapText m_textInfo; // status information that changes
|
||||
|
||||
+24
-19
@@ -193,33 +193,38 @@ void ScreenEditMenu::MenuStart( const InputEventPlus &input )
|
||||
|
||||
switch( m_Selector.EDIT_MODE )
|
||||
{
|
||||
case EditMode_Full:
|
||||
{
|
||||
RString sDir = pSong->GetSongDir();
|
||||
RString sTempFile = sDir + TEMP_FILE_NAME;
|
||||
RageFile file;
|
||||
if( !file.Open( sTempFile, RageFile::WRITE ) )
|
||||
case EditMode_Full:
|
||||
{
|
||||
ScreenPrompt::Prompt( SM_None, SONG_DIR_READ_ONLY );
|
||||
return;
|
||||
}
|
||||
RString sDir = pSong->GetSongDir();
|
||||
RString sTempFile = sDir + TEMP_FILE_NAME;
|
||||
RageFile file;
|
||||
if( !file.Open( sTempFile, RageFile::WRITE ) )
|
||||
{
|
||||
ScreenPrompt::Prompt( SM_None, SONG_DIR_READ_ONLY );
|
||||
return;
|
||||
}
|
||||
|
||||
file.Close();
|
||||
FILEMAN->Remove( sTempFile );
|
||||
break;
|
||||
}
|
||||
file.Close();
|
||||
FILEMAN->Remove( sTempFile );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch( action )
|
||||
{
|
||||
case EditMenuAction_Delete:
|
||||
ASSERT( pSteps );
|
||||
if( pSteps->IsAutogen() )
|
||||
case EditMenuAction_Delete:
|
||||
{
|
||||
SCREENMAN->PlayInvalidSound();
|
||||
SCREENMAN->SystemMessage( DELETED_AUTOGEN_STEPS.GetValue() );
|
||||
return;
|
||||
ASSERT( pSteps );
|
||||
if( pSteps->IsAutogen() )
|
||||
{
|
||||
SCREENMAN->PlayInvalidSound();
|
||||
SCREENMAN->SystemMessage( DELETED_AUTOGEN_STEPS.GetValue() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Do work
|
||||
|
||||
@@ -93,10 +93,11 @@ void ScreenEnding::Init()
|
||||
m_sprRemoveMemoryCard[p].Load( THEME->GetPathG("ScreenEnding",ssprintf("remove card P%d",p+1)) );
|
||||
switch( MEMCARDMAN->GetCardState(p) )
|
||||
{
|
||||
case MemoryCardState_Removed:
|
||||
case MemoryCardState_NoCard:
|
||||
m_sprRemoveMemoryCard[p].SetVisible( false );
|
||||
break;
|
||||
case MemoryCardState_Removed:
|
||||
case MemoryCardState_NoCard:
|
||||
m_sprRemoveMemoryCard[p].SetVisible( false );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_sprRemoveMemoryCard[p] );
|
||||
this->AddChild( &m_sprRemoveMemoryCard[p] );
|
||||
@@ -114,9 +115,10 @@ void ScreenEnding::Input( const InputEventPlus &input )
|
||||
{
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_START:
|
||||
SCREENMAN->PostMessageToTopScreen( SM_BeginFadingOut, 0 );
|
||||
break;
|
||||
case GAME_BUTTON_START:
|
||||
SCREENMAN->PostMessageToTopScreen( SM_BeginFadingOut, 0 );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-24
@@ -182,25 +182,26 @@ void ScreenEvaluation::Init()
|
||||
{
|
||||
switch( rc )
|
||||
{
|
||||
case RadarCategory_Stream:
|
||||
case RadarCategory_Voltage:
|
||||
case RadarCategory_Air:
|
||||
case RadarCategory_Freeze:
|
||||
case RadarCategory_Chaos:
|
||||
ss.m_player[p].m_radarPossible[rc] = randomf( 0, 1 );
|
||||
ss.m_player[p].m_radarActual[rc] = randomf( 0, ss.m_player[p].m_radarPossible[rc] );
|
||||
break;
|
||||
case RadarCategory_TapsAndHolds:
|
||||
case RadarCategory_Jumps:
|
||||
case RadarCategory_Holds:
|
||||
case RadarCategory_Mines:
|
||||
case RadarCategory_Hands:
|
||||
case RadarCategory_Rolls:
|
||||
case RadarCategory_Lifts:
|
||||
case RadarCategory_Fakes:
|
||||
ss.m_player[p].m_radarPossible[rc] = 1 + (rand() % 200);
|
||||
ss.m_player[p].m_radarActual[rc] = rand() % (int)(ss.m_player[p].m_radarPossible[rc]);
|
||||
break;
|
||||
case RadarCategory_Stream:
|
||||
case RadarCategory_Voltage:
|
||||
case RadarCategory_Air:
|
||||
case RadarCategory_Freeze:
|
||||
case RadarCategory_Chaos:
|
||||
ss.m_player[p].m_radarPossible[rc] = randomf( 0, 1 );
|
||||
ss.m_player[p].m_radarActual[rc] = randomf( 0, ss.m_player[p].m_radarPossible[rc] );
|
||||
break;
|
||||
case RadarCategory_TapsAndHolds:
|
||||
case RadarCategory_Jumps:
|
||||
case RadarCategory_Holds:
|
||||
case RadarCategory_Mines:
|
||||
case RadarCategory_Hands:
|
||||
case RadarCategory_Rolls:
|
||||
case RadarCategory_Lifts:
|
||||
case RadarCategory_Fakes:
|
||||
ss.m_player[p].m_radarPossible[rc] = 1 + (rand() % 200);
|
||||
ss.m_player[p].m_radarActual[rc] = rand() % (int)(ss.m_player[p].m_radarPossible[rc]);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
; // filled in by ScreenGameplay on start of notes
|
||||
@@ -651,11 +652,12 @@ void ScreenEvaluation::Init()
|
||||
|
||||
switch( best_grade )
|
||||
{
|
||||
case Grade_Tier01:
|
||||
case Grade_Tier02:
|
||||
case Grade_Tier03:
|
||||
this->PostScreenMessage( SM_PlayCheer, CHEER_DELAY_SECONDS );
|
||||
break;
|
||||
case Grade_Tier01:
|
||||
case Grade_Tier02:
|
||||
case Grade_Tier03:
|
||||
this->PostScreenMessage( SM_PlayCheer, CHEER_DELAY_SECONDS );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+294
-260
@@ -151,10 +151,11 @@ void PlayerInfo::Load( PlayerNumber pn, MultiPlayer mp, bool bShowNoteField, int
|
||||
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pSecondaryScoreDisplay = new ScoreDisplayRave;
|
||||
m_pSecondaryScoreDisplay->SetName( "ScoreDisplayRave" );
|
||||
break;
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pSecondaryScoreDisplay = new ScoreDisplayRave;
|
||||
m_pSecondaryScoreDisplay->SetName( "ScoreDisplayRave" );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_pSecondaryScoreDisplay )
|
||||
@@ -164,9 +165,10 @@ void PlayerInfo::Load( PlayerNumber pn, MultiPlayer mp, bool bShowNoteField, int
|
||||
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pSecondaryScoreKeeper = new ScoreKeeperRave( pPlayerState, pPlayerStageStats );
|
||||
break;
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pSecondaryScoreKeeper = new ScoreKeeperRave( pPlayerState, pPlayerStageStats );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_ptextPlayerOptions = NULL;
|
||||
@@ -393,9 +395,33 @@ void ScreenGameplay::Init()
|
||||
/* Called once per stage (single song or single course). */
|
||||
GAMESTATE->BeginStage();
|
||||
|
||||
int player = 1;
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
unsigned int count = pi->m_vpStepsQueue.size();
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
Steps *curSteps = pi->m_vpStepsQueue[i];
|
||||
if (curSteps->IsNoteDataEmpty())
|
||||
{
|
||||
if (curSteps->GetNoteDataFromSimfile())
|
||||
{
|
||||
LOG->Trace("Notes should be loaded for player %d", player);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG->Trace("Error loading notes for player %d", player);
|
||||
}
|
||||
}
|
||||
}
|
||||
player++;
|
||||
}
|
||||
|
||||
if(!GAMESTATE->IsCourseMode() && !GAMESTATE->m_bDemonstrationOrJukebox)
|
||||
{
|
||||
// fill in difficulty of CPU players with that of the first human player
|
||||
// this should not need to worry about step content.
|
||||
FOREACH_PotentialCpuPlayer(p)
|
||||
GAMESTATE->m_pCurSteps[p].Set( GAMESTATE->m_pCurSteps[ GAMESTATE->GetFirstHumanPlayer() ] );
|
||||
|
||||
@@ -498,13 +524,14 @@ void ScreenGameplay::Init()
|
||||
// Add combined life meter
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pCombinedLifeMeter = new CombinedLifeMeterTug;
|
||||
m_pCombinedLifeMeter->SetName( "CombinedLife" );
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY( *m_pCombinedLifeMeter );
|
||||
this->AddChild( m_pCombinedLifeMeter );
|
||||
break;
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
m_pCombinedLifeMeter = new CombinedLifeMeterTug;
|
||||
m_pCombinedLifeMeter->SetName( "CombinedLife" );
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY( *m_pCombinedLifeMeter );
|
||||
this->AddChild( m_pCombinedLifeMeter );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Before the lifemeter loads, if Networking is required
|
||||
@@ -517,25 +544,26 @@ void ScreenGameplay::Init()
|
||||
// Add individual life meter
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_REGULAR:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
FOREACH_PlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
if( !GAMESTATE->IsPlayerEnabled(pi->m_pn) && !SHOW_LIFE_METER_FOR_DISABLED_PLAYERS )
|
||||
continue; // skip
|
||||
case PLAY_MODE_REGULAR:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
FOREACH_PlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
if( !GAMESTATE->IsPlayerEnabled(pi->m_pn) && !SHOW_LIFE_METER_FOR_DISABLED_PLAYERS )
|
||||
continue; // skip
|
||||
|
||||
pi->m_pLifeMeter = LifeMeter::MakeLifeMeter( GAMESTATE->m_SongOptions.GetStage().m_LifeType );
|
||||
pi->m_pLifeMeter->Load( pi->GetPlayerState(), pi->GetPlayerStageStats() );
|
||||
pi->m_pLifeMeter->SetName( ssprintf("Life%s",pi->GetName().c_str()) );
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY( pi->m_pLifeMeter );
|
||||
this->AddChild( pi->m_pLifeMeter );
|
||||
}
|
||||
break;
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
break;
|
||||
pi->m_pLifeMeter = LifeMeter::MakeLifeMeter( GAMESTATE->m_SongOptions.GetStage().m_LifeType );
|
||||
pi->m_pLifeMeter->Load( pi->GetPlayerState(), pi->GetPlayerStageStats() );
|
||||
pi->m_pLifeMeter->SetName( ssprintf("Life%s",pi->GetName().c_str()) );
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY( pi->m_pLifeMeter );
|
||||
this->AddChild( pi->m_pLifeMeter );
|
||||
}
|
||||
break;
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_bShowScoreboard = false;
|
||||
@@ -694,11 +722,12 @@ void ScreenGameplay::Init()
|
||||
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
m_soundBattleTrickLevel1.Load( THEME->GetPathS(m_sName,"battle trick level1"), true );
|
||||
m_soundBattleTrickLevel2.Load( THEME->GetPathS(m_sName,"battle trick level2"), true );
|
||||
m_soundBattleTrickLevel3.Load( THEME->GetPathS(m_sName,"battle trick level3"), true );
|
||||
break;
|
||||
case PLAY_MODE_BATTLE:
|
||||
m_soundBattleTrickLevel1.Load( THEME->GetPathS(m_sName,"battle trick level1"), true );
|
||||
m_soundBattleTrickLevel2.Load( THEME->GetPathS(m_sName,"battle trick level2"), true );
|
||||
m_soundBattleTrickLevel3.Load( THEME->GetPathS(m_sName,"battle trick level3"), true );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,9 +1001,10 @@ void ScreenGameplay::SetupSong( int iSongIndex )
|
||||
RString sType;
|
||||
switch( GAMESTATE->m_SongOptions.GetCurrent().m_SoundEffectType )
|
||||
{
|
||||
case SongOptions::SOUNDEFFECT_OFF: sType = "SoundEffectControl_Off"; break;
|
||||
case SongOptions::SOUNDEFFECT_SPEED: sType = "SoundEffectControl_Speed"; break;
|
||||
case SongOptions::SOUNDEFFECT_PITCH: sType = "SoundEffectControl_Pitch"; break;
|
||||
case SongOptions::SOUNDEFFECT_OFF: sType = "SoundEffectControl_Off"; break;
|
||||
case SongOptions::SOUNDEFFECT_SPEED: sType = "SoundEffectControl_Speed"; break;
|
||||
case SongOptions::SOUNDEFFECT_PITCH: sType = "SoundEffectControl_Pitch"; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
pi->m_SoundEffectControl.Load( sType, pi->GetPlayerState(), &pi->m_NoteData );
|
||||
@@ -1606,246 +1636,250 @@ void ScreenGameplay::Update( float fDeltaTime )
|
||||
|
||||
switch( m_DancingState )
|
||||
{
|
||||
case STATE_DANCING:
|
||||
/* Set STATSMAN->m_CurStageStats.bFailed for failed players. In, FAIL_IMMEDIATE, send
|
||||
* SM_BeginFailed if all players failed, and kill dead Oni players. */
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
case STATE_DANCING:
|
||||
{
|
||||
PlayerNumber pn = pi->GetStepsAndTrailIndex();
|
||||
|
||||
PlayerOptions::FailType ft = GAMESTATE->GetPlayerFailType( pi->GetPlayerState() );
|
||||
SongOptions::LifeType lt = GAMESTATE->m_SongOptions.GetCurrent().m_LifeType;
|
||||
|
||||
if( ft == PlayerOptions::FAIL_OFF || ft == PlayerOptions::FAIL_AT_END )
|
||||
continue;
|
||||
|
||||
// check for individual fail
|
||||
if( pi->m_pLifeMeter == NULL || !pi->m_pLifeMeter->IsFailing() )
|
||||
continue; /* isn't failing */
|
||||
if( pi->GetPlayerStageStats()->m_bFailed )
|
||||
continue; /* failed and is already dead */
|
||||
|
||||
LOG->Trace("Player %d failed", (int)pn);
|
||||
pi->GetPlayerStageStats()->m_bFailed = true; // fail
|
||||
|
||||
/* Set STATSMAN->m_CurStageStats.bFailed for failed players. In, FAIL_IMMEDIATE, send
|
||||
* SM_BeginFailed if all players failed, and kill dead Oni players. */
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
Message msg("PlayerFailed");
|
||||
msg.SetParam( "PlayerNumber", pi->m_pn );
|
||||
MESSAGEMAN->Broadcast( msg );
|
||||
}
|
||||
PlayerNumber pn = pi->GetStepsAndTrailIndex();
|
||||
|
||||
PlayerOptions::FailType ft = GAMESTATE->GetPlayerFailType( pi->GetPlayerState() );
|
||||
SongOptions::LifeType lt = GAMESTATE->m_SongOptions.GetCurrent().m_LifeType;
|
||||
|
||||
if( ft == PlayerOptions::FAIL_OFF || ft == PlayerOptions::FAIL_AT_END )
|
||||
continue;
|
||||
|
||||
// check for individual fail
|
||||
if( pi->m_pLifeMeter == NULL || !pi->m_pLifeMeter->IsFailing() )
|
||||
continue; /* isn't failing */
|
||||
if( pi->GetPlayerStageStats()->m_bFailed )
|
||||
continue; /* failed and is already dead */
|
||||
|
||||
LOG->Trace("Player %d failed", (int)pn);
|
||||
pi->GetPlayerStageStats()->m_bFailed = true; // fail
|
||||
|
||||
// Check for and do Oni die.
|
||||
bool bAllowOniDie = false;
|
||||
switch( lt )
|
||||
{
|
||||
case SongOptions::LIFE_BATTERY:
|
||||
bAllowOniDie = true;
|
||||
break;
|
||||
}
|
||||
if( bAllowOniDie && ft == PlayerOptions::FAIL_IMMEDIATE )
|
||||
{
|
||||
if( !STATSMAN->m_CurStageStats.AllFailed() ) // if not the last one to fail
|
||||
{
|
||||
// kill them!
|
||||
SOUND->PlayOnceFromDir( THEME->GetPathS(m_sName,"oni die") );
|
||||
pi->ShowOniGameOver();
|
||||
pi->m_NoteData.Init(); // remove all notes and scoring
|
||||
pi->m_pPlayer->FadeToFail(); // tell the NoteField to fade to white
|
||||
Message msg("PlayerFailed");
|
||||
msg.SetParam( "PlayerNumber", pi->m_pn );
|
||||
MESSAGEMAN->Broadcast( msg );
|
||||
}
|
||||
|
||||
// Check for and do Oni die.
|
||||
bool bAllowOniDie = false;
|
||||
switch( lt )
|
||||
{
|
||||
case SongOptions::LIFE_BATTERY:
|
||||
bAllowOniDie = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if( bAllowOniDie && ft == PlayerOptions::FAIL_IMMEDIATE )
|
||||
{
|
||||
if( !STATSMAN->m_CurStageStats.AllFailed() ) // if not the last one to fail
|
||||
{
|
||||
// kill them!
|
||||
SOUND->PlayOnceFromDir( THEME->GetPathS(m_sName,"oni die") );
|
||||
pi->ShowOniGameOver();
|
||||
pi->m_NoteData.Init(); // remove all notes and scoring
|
||||
pi->m_pPlayer->FadeToFail(); // tell the NoteField to fade to white
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool bAllFailed = true;
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
PlayerOptions::FailType ft = GAMESTATE->GetPlayerFailType( pi->GetPlayerState() );
|
||||
switch( ft )
|
||||
bool bAllFailed = true;
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
case PlayerOptions::FAIL_IMMEDIATE:
|
||||
if( pi->m_pLifeMeter == NULL || (pi->m_pLifeMeter && !pi->m_pLifeMeter->IsFailing()) )
|
||||
bAllFailed = false;
|
||||
break;
|
||||
case PlayerOptions::FAIL_IMMEDIATE_CONTINUE:
|
||||
case PlayerOptions::FAIL_AT_END:
|
||||
bAllFailed = false; // wait until the end of the song to fail.
|
||||
break;
|
||||
case PlayerOptions::FAIL_OFF:
|
||||
bAllFailed = false; // never fail.
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
if( bAllFailed )
|
||||
{
|
||||
m_pSoundMusic->StopPlaying();
|
||||
SCREENMAN->PostMessageToTopScreen( SM_NotesEnded, 0 );
|
||||
// todo: stop lyrics (m_LyricDisplay) from animating -aj
|
||||
}
|
||||
|
||||
// Update living players' alive time
|
||||
// HACK: Don't scale alive time when using tab/tilde. Instead of accumulating time from a timer,
|
||||
// this time should instead be tied to the music position.
|
||||
float fUnscaledDeltaTime = m_timerGameplaySeconds.GetDeltaTime();
|
||||
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
if( !pi->GetPlayerStageStats()->m_bFailed )
|
||||
pi->GetPlayerStageStats()->m_fAliveSeconds += fUnscaledDeltaTime * GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate;
|
||||
|
||||
// update fGameplaySeconds
|
||||
STATSMAN->m_CurStageStats.m_fGameplaySeconds += fUnscaledDeltaTime;
|
||||
float curBeat = GAMESTATE->m_Position.m_fSongBeat;
|
||||
Song &s = *GAMESTATE->m_pCurSong;
|
||||
|
||||
if( curBeat >= s.GetFirstBeat() && curBeat < s.GetLastBeat() )
|
||||
{
|
||||
STATSMAN->m_CurStageStats.m_fStepsSeconds += fUnscaledDeltaTime;
|
||||
|
||||
if( GAMESTATE->m_SongOptions.GetCurrent().m_fHaste != 0.0f )
|
||||
{
|
||||
float fHasteRate = GetHasteRate();
|
||||
GAMESTATE->m_fAccumulatedHasteSeconds += (fUnscaledDeltaTime * fHasteRate) - fUnscaledDeltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for end of song
|
||||
{
|
||||
float fSecondsToStartFadingOutMusic, fSecondsToStartTransitioningOut;
|
||||
GetMusicEndTiming( fSecondsToStartFadingOutMusic, fSecondsToStartTransitioningOut );
|
||||
|
||||
bool bAllReallyFailed = STATSMAN->m_CurStageStats.AllFailed();
|
||||
if( bAllReallyFailed )
|
||||
fSecondsToStartTransitioningOut += BEGIN_FAILED_DELAY;
|
||||
|
||||
if( GAMESTATE->m_Position.m_fMusicSeconds >= fSecondsToStartTransitioningOut && !m_NextSong.IsTransitioning() )
|
||||
this->PostScreenMessage( SM_NotesEnded, 0 );
|
||||
}
|
||||
|
||||
// update 2d dancing characters
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
DancingCharacters *pCharacter = NULL;
|
||||
if( m_pSongBackground )
|
||||
pCharacter = m_pSongBackground->GetDancingCharacters();
|
||||
if( pCharacter != NULL )
|
||||
{
|
||||
TapNoteScore tns = pi->m_pPlayer->GetLastTapNoteScore();
|
||||
|
||||
ANIM_STATES_2D state = AS2D_MISS;
|
||||
|
||||
switch( tns )
|
||||
PlayerOptions::FailType ft = GAMESTATE->GetPlayerFailType( pi->GetPlayerState() );
|
||||
switch( ft )
|
||||
{
|
||||
case TNS_W4:
|
||||
case TNS_W3:
|
||||
state = AS2D_GOOD;
|
||||
case PlayerOptions::FAIL_IMMEDIATE:
|
||||
if( pi->m_pLifeMeter == NULL || (pi->m_pLifeMeter && !pi->m_pLifeMeter->IsFailing()) )
|
||||
bAllFailed = false;
|
||||
break;
|
||||
case TNS_W2:
|
||||
case TNS_W1:
|
||||
state = AS2D_GREAT;
|
||||
case PlayerOptions::FAIL_IMMEDIATE_CONTINUE:
|
||||
case PlayerOptions::FAIL_AT_END:
|
||||
bAllFailed = false; // wait until the end of the song to fail.
|
||||
break;
|
||||
case PlayerOptions::FAIL_OFF:
|
||||
bAllFailed = false; // never fail.
|
||||
break;
|
||||
default:
|
||||
state = AS2D_MISS;
|
||||
break;
|
||||
}
|
||||
|
||||
if( state == AS2D_GREAT && pi->GetPlayerState()->m_HealthState == HealthState_Hot )
|
||||
state = AS2D_FEVER;
|
||||
|
||||
pCharacter->Change2DAnimState( pi->m_pn, state );
|
||||
}
|
||||
}
|
||||
|
||||
// Check for enemy death in enemy battle
|
||||
static float fLastSeenEnemyHealth = 1;
|
||||
if( fLastSeenEnemyHealth != GAMESTATE->m_fOpponentHealthPercent )
|
||||
{
|
||||
fLastSeenEnemyHealth = GAMESTATE->m_fOpponentHealthPercent;
|
||||
|
||||
if( GAMESTATE->m_fOpponentHealthPercent == 0 )
|
||||
{
|
||||
// HACK: Load incorrect directory on purpose for now.
|
||||
PlayAnnouncer( "gameplay battle damage level3", 0 );
|
||||
|
||||
GAMESTATE->RemoveAllActiveAttacks();
|
||||
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
if( !GAMESTATE->IsCpuPlayer(pi->m_pn) )
|
||||
continue;
|
||||
|
||||
SOUND->PlayOnceFromDir( THEME->GetPathS(m_sName,"oni die") );
|
||||
pi->ShowOniGameOver();
|
||||
pi->m_NoteData.Init(); // remove all notes and scoring
|
||||
pi->m_pPlayer->FadeToFail(); // tell the NoteField to fade to white
|
||||
FAIL_M("Invalid fail type! Aborting...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update give up
|
||||
bool bGiveUpTimerFired = !m_GiveUpTimer.IsZero() && m_GiveUpTimer.Ago() > 2.5f;
|
||||
|
||||
|
||||
bool bAllHumanHaveBigMissCombo = true;
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
if (pi->GetPlayerState()->m_PlayerOptions.GetCurrent().m_FailType == PlayerOptions::FAIL_OFF ||
|
||||
pi->GetPlayerState()->m_HealthState < HealthState_Dead )
|
||||
{
|
||||
bAllHumanHaveBigMissCombo = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bAllHumanHaveBigMissCombo) // possible to get in here.
|
||||
{
|
||||
bAllHumanHaveBigMissCombo = FAIL_ON_MISS_COMBO.GetValue() != -1 && STATSMAN->m_CurStageStats.GetMinimumMissCombo() >= FAIL_ON_MISS_COMBO;
|
||||
}
|
||||
if( bGiveUpTimerFired || bAllHumanHaveBigMissCombo )
|
||||
{
|
||||
STATSMAN->m_CurStageStats.m_bGaveUp = true;
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
pi->GetPlayerStageStats()->m_bFailed |= bAllHumanHaveBigMissCombo;
|
||||
pi->GetPlayerStageStats()->m_bDisqualified |= bGiveUpTimerFired; // Don't disqualify if failing for miss combo. The player should still be eligable for a high score on courses.
|
||||
}
|
||||
|
||||
AbortGiveUp( false );
|
||||
|
||||
if( GIVING_UP_GOES_TO_PREV_SCREEN )
|
||||
{
|
||||
BeginBackingOutFromGameplay();
|
||||
}
|
||||
else
|
||||
if( bAllFailed )
|
||||
{
|
||||
m_pSoundMusic->StopPlaying();
|
||||
this->PostScreenMessage( SM_NotesEnded, 0 );
|
||||
SCREENMAN->PostMessageToTopScreen( SM_NotesEnded, 0 );
|
||||
// todo: stop lyrics (m_LyricDisplay) from animating -aj
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if it's time to play a ScreenGameplay comment
|
||||
m_fTimeSinceLastDancingComment += fDeltaTime;
|
||||
// Update living players' alive time
|
||||
// HACK: Don't scale alive time when using tab/tilde. Instead of accumulating time from a timer,
|
||||
// this time should instead be tied to the music position.
|
||||
float fUnscaledDeltaTime = m_timerGameplaySeconds.GetDeltaTime();
|
||||
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_REGULAR:
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
if( GAMESTATE->OneIsHot() )
|
||||
PlayAnnouncer( "gameplay comment hot", SECONDS_BETWEEN_COMMENTS );
|
||||
else if( GAMESTATE->AllAreInDangerOrWorse() )
|
||||
PlayAnnouncer( "gameplay comment danger", SECONDS_BETWEEN_COMMENTS );
|
||||
else
|
||||
PlayAnnouncer( "gameplay comment good", SECONDS_BETWEEN_COMMENTS );
|
||||
break;
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
PlayAnnouncer( "gameplay comment oni", SECONDS_BETWEEN_COMMENTS );
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||
if( !pi->GetPlayerStageStats()->m_bFailed )
|
||||
pi->GetPlayerStageStats()->m_fAliveSeconds += fUnscaledDeltaTime * GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate;
|
||||
|
||||
// update fGameplaySeconds
|
||||
STATSMAN->m_CurStageStats.m_fGameplaySeconds += fUnscaledDeltaTime;
|
||||
float curBeat = GAMESTATE->m_Position.m_fSongBeat;
|
||||
Song &s = *GAMESTATE->m_pCurSong;
|
||||
|
||||
if( curBeat >= s.GetFirstBeat() && curBeat < s.GetLastBeat() )
|
||||
{
|
||||
STATSMAN->m_CurStageStats.m_fStepsSeconds += fUnscaledDeltaTime;
|
||||
|
||||
if( GAMESTATE->m_SongOptions.GetCurrent().m_fHaste != 0.0f )
|
||||
{
|
||||
float fHasteRate = GetHasteRate();
|
||||
GAMESTATE->m_fAccumulatedHasteSeconds += (fUnscaledDeltaTime * fHasteRate) - fUnscaledDeltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for end of song
|
||||
{
|
||||
float fSecondsToStartFadingOutMusic, fSecondsToStartTransitioningOut;
|
||||
GetMusicEndTiming( fSecondsToStartFadingOutMusic, fSecondsToStartTransitioningOut );
|
||||
|
||||
bool bAllReallyFailed = STATSMAN->m_CurStageStats.AllFailed();
|
||||
if( bAllReallyFailed )
|
||||
fSecondsToStartTransitioningOut += BEGIN_FAILED_DELAY;
|
||||
|
||||
if( GAMESTATE->m_Position.m_fMusicSeconds >= fSecondsToStartTransitioningOut && !m_NextSong.IsTransitioning() )
|
||||
this->PostScreenMessage( SM_NotesEnded, 0 );
|
||||
}
|
||||
|
||||
// update 2d dancing characters
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
DancingCharacters *pCharacter = NULL;
|
||||
if( m_pSongBackground )
|
||||
pCharacter = m_pSongBackground->GetDancingCharacters();
|
||||
if( pCharacter != NULL )
|
||||
{
|
||||
TapNoteScore tns = pi->m_pPlayer->GetLastTapNoteScore();
|
||||
|
||||
ANIM_STATES_2D state = AS2D_MISS;
|
||||
|
||||
switch( tns )
|
||||
{
|
||||
case TNS_W4:
|
||||
case TNS_W3:
|
||||
state = AS2D_GOOD;
|
||||
break;
|
||||
case TNS_W2:
|
||||
case TNS_W1:
|
||||
state = AS2D_GREAT;
|
||||
break;
|
||||
default:
|
||||
state = AS2D_MISS;
|
||||
break;
|
||||
}
|
||||
|
||||
if( state == AS2D_GREAT && pi->GetPlayerState()->m_HealthState == HealthState_Hot )
|
||||
state = AS2D_FEVER;
|
||||
|
||||
pCharacter->Change2DAnimState( pi->m_pn, state );
|
||||
}
|
||||
}
|
||||
|
||||
// Check for enemy death in enemy battle
|
||||
static float fLastSeenEnemyHealth = 1;
|
||||
if( fLastSeenEnemyHealth != GAMESTATE->m_fOpponentHealthPercent )
|
||||
{
|
||||
fLastSeenEnemyHealth = GAMESTATE->m_fOpponentHealthPercent;
|
||||
|
||||
if( GAMESTATE->m_fOpponentHealthPercent == 0 )
|
||||
{
|
||||
// HACK: Load incorrect directory on purpose for now.
|
||||
PlayAnnouncer( "gameplay battle damage level3", 0 );
|
||||
|
||||
GAMESTATE->RemoveAllActiveAttacks();
|
||||
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
if( !GAMESTATE->IsCpuPlayer(pi->m_pn) )
|
||||
continue;
|
||||
|
||||
SOUND->PlayOnceFromDir( THEME->GetPathS(m_sName,"oni die") );
|
||||
pi->ShowOniGameOver();
|
||||
pi->m_NoteData.Init(); // remove all notes and scoring
|
||||
pi->m_pPlayer->FadeToFail(); // tell the NoteField to fade to white
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update give up
|
||||
bool bGiveUpTimerFired = !m_GiveUpTimer.IsZero() && m_GiveUpTimer.Ago() > 2.5f;
|
||||
|
||||
|
||||
bool bAllHumanHaveBigMissCombo = true;
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
if (pi->GetPlayerState()->m_PlayerOptions.GetCurrent().m_FailType == PlayerOptions::FAIL_OFF ||
|
||||
pi->GetPlayerState()->m_HealthState < HealthState_Dead )
|
||||
{
|
||||
bAllHumanHaveBigMissCombo = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bAllHumanHaveBigMissCombo) // possible to get in here.
|
||||
{
|
||||
bAllHumanHaveBigMissCombo = FAIL_ON_MISS_COMBO.GetValue() != -1 && STATSMAN->m_CurStageStats.GetMinimumMissCombo() >= FAIL_ON_MISS_COMBO;
|
||||
}
|
||||
if( bGiveUpTimerFired || bAllHumanHaveBigMissCombo )
|
||||
{
|
||||
STATSMAN->m_CurStageStats.m_bGaveUp = true;
|
||||
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
|
||||
{
|
||||
pi->GetPlayerStageStats()->m_bFailed |= bAllHumanHaveBigMissCombo;
|
||||
pi->GetPlayerStageStats()->m_bDisqualified |= bGiveUpTimerFired; // Don't disqualify if failing for miss combo. The player should still be eligable for a high score on courses.
|
||||
}
|
||||
|
||||
AbortGiveUp( false );
|
||||
|
||||
if( GIVING_UP_GOES_TO_PREV_SCREEN )
|
||||
{
|
||||
BeginBackingOutFromGameplay();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSoundMusic->StopPlaying();
|
||||
this->PostScreenMessage( SM_NotesEnded, 0 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if it's time to play a ScreenGameplay comment
|
||||
m_fTimeSinceLastDancingComment += fDeltaTime;
|
||||
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_REGULAR:
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
if( GAMESTATE->OneIsHot() )
|
||||
PlayAnnouncer( "gameplay comment hot", SECONDS_BETWEEN_COMMENTS );
|
||||
else if( GAMESTATE->AllAreInDangerOrWorse() )
|
||||
PlayAnnouncer( "gameplay comment danger", SECONDS_BETWEEN_COMMENTS );
|
||||
else
|
||||
PlayAnnouncer( "gameplay comment good", SECONDS_BETWEEN_COMMENTS );
|
||||
break;
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
PlayAnnouncer( "gameplay comment oni", SECONDS_BETWEEN_COMMENTS );
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
PlayTicks();
|
||||
|
||||
@@ -248,10 +248,12 @@ void ScreenJukebox::Input( const InputEventPlus &input )
|
||||
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_LEFT:
|
||||
case GAME_BUTTON_RIGHT:
|
||||
SCREENMAN->PostMessageToTopScreen( SM_NotesEnded, 0 );
|
||||
return;
|
||||
case GAME_BUTTON_LEFT:
|
||||
case GAME_BUTTON_RIGHT:
|
||||
SCREENMAN->PostMessageToTopScreen( SM_NotesEnded, 0 );
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ScreenAttract::AttractInput( input, this );
|
||||
|
||||
@@ -54,7 +54,7 @@ void ScreenNetSelectMusic::Init()
|
||||
|
||||
m_StepsDisplays[p].SetName( ssprintf("StepsDisplayP%d",p+1) );
|
||||
m_StepsDisplays[p].Load( "StepsDisplayNet", NULL );
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_StepsDisplays[p] );
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY( m_StepsDisplays[p] );
|
||||
this->AddChild( &m_StepsDisplays[p] );
|
||||
}
|
||||
|
||||
@@ -66,20 +66,13 @@ void ScreenNetSelectMusic::Init()
|
||||
this->AddChild( &m_MusicWheel );
|
||||
this->MoveToHead( &m_MusicWheel );
|
||||
|
||||
// todo: handle me theme-side -aj
|
||||
m_BPMDisplay.SetName( "BPMDisplay" );
|
||||
m_BPMDisplay.LoadFromFont( THEME->GetPathF("BPMDisplay","bpm") );
|
||||
m_BPMDisplay.Load();
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_BPMDisplay );
|
||||
this->AddChild( &m_BPMDisplay );
|
||||
|
||||
// todo: handle me theme-side -aj
|
||||
FOREACH_EnabledPlayer( p )
|
||||
{
|
||||
m_ModIconRow[p].SetName( ssprintf("ModIconsP%d",p+1) );
|
||||
m_ModIconRow[p].Load( "ModIconRowSelectMusic", p );
|
||||
m_ModIconRow[p].SetFromGameState();
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_ModIconRow[p] );
|
||||
LOAD_ALL_COMMANDS_AND_SET_XY( m_ModIconRow[p] );
|
||||
this->AddChild( &m_ModIconRow[p] );
|
||||
}
|
||||
|
||||
@@ -435,8 +428,6 @@ void ScreenNetSelectMusic::TweenOffScreen()
|
||||
|
||||
OFF_COMMAND( m_MusicWheel );
|
||||
|
||||
OFF_COMMAND( m_BPMDisplay );
|
||||
|
||||
FOREACH_EnabledPlayer (pn)
|
||||
{
|
||||
OFF_COMMAND( m_StepsDisplays[pn] );
|
||||
@@ -495,7 +486,6 @@ void ScreenNetSelectMusic::MusicChanged()
|
||||
{
|
||||
if( GAMESTATE->m_pCurSong == NULL )
|
||||
{
|
||||
m_BPMDisplay.NoBPM();
|
||||
FOREACH_EnabledPlayer (pn)
|
||||
UpdateDifficulties( pn );
|
||||
|
||||
@@ -504,7 +494,6 @@ void ScreenNetSelectMusic::MusicChanged()
|
||||
// SOUND->PlayMusic( m_sSectionMusicPath, NULL, true, 0, -1 );
|
||||
return;
|
||||
}
|
||||
m_BPMDisplay.SetBpmFromSong( GAMESTATE->m_pCurSong );
|
||||
|
||||
FOREACH_EnabledPlayer (pn)
|
||||
{
|
||||
|
||||
+40
-32
@@ -465,12 +465,13 @@ void ScreenOptions::TweenCursor( PlayerNumber pn )
|
||||
bool bCanGoRight = false;
|
||||
switch( row.GetRowDef().m_layoutType )
|
||||
{
|
||||
case LAYOUT_SHOW_ONE_IN_ROW:
|
||||
bCanGoLeft = iChoiceWithFocus > 0;
|
||||
bCanGoRight = iChoiceWithFocus >= 0 && iChoiceWithFocus < (int) row.GetRowDef().m_vsChoices.size()-1;
|
||||
break;
|
||||
case LAYOUT_SHOW_ALL_IN_ROW:
|
||||
break;
|
||||
case LAYOUT_SHOW_ONE_IN_ROW:
|
||||
bCanGoLeft = iChoiceWithFocus > 0;
|
||||
bCanGoRight = iChoiceWithFocus >= 0 && iChoiceWithFocus < (int) row.GetRowDef().m_vsChoices.size()-1;
|
||||
break;
|
||||
case LAYOUT_SHOW_ALL_IN_ROW:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
cursor.SetCanGo( bCanGoLeft, bCanGoRight );
|
||||
|
||||
@@ -505,13 +506,15 @@ void ScreenOptions::Input( const InputEventPlus &input )
|
||||
{
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_START:
|
||||
case GAME_BUTTON_SELECT:
|
||||
case GAME_BUTTON_MENURIGHT:
|
||||
case GAME_BUTTON_MENULEFT:
|
||||
INPUTMAPPER->ResetKeyRepeat( GAME_BUTTON_START, input.pn );
|
||||
INPUTMAPPER->ResetKeyRepeat( GAME_BUTTON_RIGHT, input.pn );
|
||||
INPUTMAPPER->ResetKeyRepeat( GAME_BUTTON_LEFT, input.pn );
|
||||
case GAME_BUTTON_START:
|
||||
case GAME_BUTTON_SELECT:
|
||||
case GAME_BUTTON_MENURIGHT:
|
||||
case GAME_BUTTON_MENULEFT:
|
||||
INPUTMAPPER->ResetKeyRepeat( GAME_BUTTON_START, input.pn );
|
||||
INPUTMAPPER->ResetKeyRepeat( GAME_BUTTON_RIGHT, input.pn );
|
||||
INPUTMAPPER->ResetKeyRepeat( GAME_BUTTON_LEFT, input.pn );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,12 +739,13 @@ void ScreenOptions::AfterChangeValueOrRow( PlayerNumber pn )
|
||||
BitmapText *pText = NULL;
|
||||
switch( m_InputMode )
|
||||
{
|
||||
case INPUTMODE_INDIVIDUAL:
|
||||
pText = &m_textExplanation[pn];
|
||||
break;
|
||||
case INPUTMODE_SHARE_CURSOR:
|
||||
pText = &m_textExplanationTogether;
|
||||
break;
|
||||
case INPUTMODE_INDIVIDUAL:
|
||||
pText = &m_textExplanation[pn];
|
||||
break;
|
||||
case INPUTMODE_SHARE_CURSOR:
|
||||
pText = &m_textExplanationTogether;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if( pText->GetText() != text )
|
||||
{
|
||||
@@ -787,8 +791,8 @@ void ScreenOptions::MenuStart( const InputEventPlus &input )
|
||||
* GAME_BUTTON_RIGHT are being held. */
|
||||
switch( m_OptionsNavigation )
|
||||
{
|
||||
case NAV_THREE_KEY:
|
||||
case NAV_TOGGLE_THREE_KEY:
|
||||
case NAV_THREE_KEY:
|
||||
case NAV_TOGGLE_THREE_KEY:
|
||||
{
|
||||
bool bHoldingLeftAndRight =
|
||||
INPUTMAPPER->IsBeingPressed( GAME_BUTTON_RIGHT, pn ) &&
|
||||
@@ -800,6 +804,7 @@ void ScreenOptions::MenuStart( const InputEventPlus &input )
|
||||
return;
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
this->ProcessMenuStart( input );
|
||||
@@ -1170,23 +1175,26 @@ void ScreenOptions::AfterChangeRow( PlayerNumber pn )
|
||||
OptionRow &row = *m_pRows[iRow];
|
||||
switch( m_OptionsNavigation )
|
||||
{
|
||||
case NAV_TOGGLE_FIVE_KEY:
|
||||
if( row.GetRowDef().m_layoutType != LAYOUT_SHOW_ONE_IN_ROW )
|
||||
case NAV_TOGGLE_FIVE_KEY:
|
||||
{
|
||||
int iSelectionDist = -1;
|
||||
for( unsigned i = 0; i < row.GetTextItemsSize(); ++i )
|
||||
if( row.GetRowDef().m_layoutType != LAYOUT_SHOW_ONE_IN_ROW )
|
||||
{
|
||||
int iWidth, iX, iY;
|
||||
GetWidthXY( pn, m_iCurrentRow[pn], i, iWidth, iX, iY );
|
||||
const int iDist = abs( iX-m_iFocusX[pn] );
|
||||
if( iSelectionDist == -1 || iDist < iSelectionDist )
|
||||
int iSelectionDist = -1;
|
||||
for( unsigned i = 0; i < row.GetTextItemsSize(); ++i )
|
||||
{
|
||||
iSelectionDist = iDist;
|
||||
row.SetChoiceInRowWithFocus( pn, i );
|
||||
int iWidth, iX, iY;
|
||||
GetWidthXY( pn, m_iCurrentRow[pn], i, iWidth, iX, iY );
|
||||
const int iDist = abs( iX-m_iFocusX[pn] );
|
||||
if( iSelectionDist == -1 || iDist < iSelectionDist )
|
||||
{
|
||||
iSelectionDist = iDist;
|
||||
row.SetChoiceInRowWithFocus( pn, i );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( row.GetFirstItemGoesDown() )
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include "SpecialFiles.h"
|
||||
#include "SpecialFiles.h"
|
||||
#include "ScreenPrompt.h"
|
||||
#include "SongManager.h"
|
||||
|
||||
// main page (type list)
|
||||
REGISTER_SCREEN_CLASS( ScreenOptionsExportPackage );
|
||||
|
||||
void ScreenOptionsExportPackage::Init()
|
||||
@@ -24,51 +26,130 @@ void ScreenOptionsExportPackage::Init()
|
||||
|
||||
void ScreenOptionsExportPackage::BeginScreen()
|
||||
{
|
||||
// Fill m_vsPossibleDirsToExport
|
||||
// todo: Split these out over multiple screens so the scroller
|
||||
// isn't so overloaded. (See ScreenOptionsToggleSongs) -freem
|
||||
// Fill m_vsPackageTypes:
|
||||
m_vsPackageTypes.push_back("Themes");
|
||||
m_vsPackageTypes.push_back("NoteSkins");
|
||||
m_vsPackageTypes.push_back("Courses");
|
||||
m_vsPackageTypes.push_back("Songs");
|
||||
// announcers, characters, others?
|
||||
|
||||
vector<OptionRowHandler*> OptionRowHandlers;
|
||||
FOREACH_CONST( RString, m_vsPackageTypes, s )
|
||||
{
|
||||
// Add themes
|
||||
{
|
||||
GetDirListing( SpecialFiles::THEMES_DIR + "*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
OptionRowHandler *pHand = OptionRowHandlerUtil::MakeNull();
|
||||
OptionRowDefinition &def = pHand->m_Def;
|
||||
|
||||
// Add NoteSkins
|
||||
{
|
||||
vector<RString> vs;
|
||||
GetDirListing( SpecialFiles::NOTESKINS_DIR + "*", vs, true, true );
|
||||
FOREACH_CONST( RString, vs, s )
|
||||
GetDirListing( *s + "*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
def.m_sName = *s;
|
||||
def.m_bAllowExplanation = false;
|
||||
//def.m_sExplanationName = "# files, # MB, # subdirs";
|
||||
def.m_bAllowThemeTitle = false;
|
||||
def.m_bAllowThemeItems = false;
|
||||
def.m_layoutType = LAYOUT_SHOW_ALL_IN_ROW;
|
||||
def.m_bOneChoiceForAllPlayers = true;
|
||||
def.m_vsChoices.clear();
|
||||
def.m_vsChoices.push_back( "" );
|
||||
OptionRowHandlers.push_back( pHand );
|
||||
}
|
||||
ScreenOptions::InitMenu( OptionRowHandlers );
|
||||
|
||||
ScreenOptions::BeginScreen();
|
||||
}
|
||||
|
||||
void ScreenOptionsExportPackage::ProcessMenuStart( const InputEventPlus &input )
|
||||
{
|
||||
if( IsTransitioning() )
|
||||
return;
|
||||
|
||||
// switch to the subpage with the specified type
|
||||
//int iCurRow = m_iCurrentRow[GAMESTATE->GetMasterPlayerNumber()];
|
||||
int iRow = GetCurrentRow();
|
||||
if( m_pRows[iRow]->GetRowType() == OptionRow::RowType_Exit )
|
||||
{
|
||||
ScreenOptions::ProcessMenuStart( input );
|
||||
return;
|
||||
}
|
||||
|
||||
ExportPackages::m_sPackageType = m_vsPackageTypes[iRow];
|
||||
SCREENMAN->SetNewScreen("ScreenOptionsExportPackageSubPage");
|
||||
}
|
||||
|
||||
void ScreenOptionsExportPackage::ImportOptions( int iRow, const vector<PlayerNumber> &vpns )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ScreenOptionsExportPackage::ExportOptions( int iRow, const vector<PlayerNumber> &vpns )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// subpage (has all folders for the specified type)
|
||||
REGISTER_SCREEN_CLASS( ScreenOptionsExportPackageSubPage );
|
||||
void ScreenOptionsExportPackageSubPage::Init()
|
||||
{
|
||||
ScreenOptions::Init();
|
||||
|
||||
SetNavigation( NAV_THREE_KEY_MENU );
|
||||
SetInputMode( INPUTMODE_SHARE_CURSOR );
|
||||
}
|
||||
|
||||
void ScreenOptionsExportPackageSubPage::BeginScreen()
|
||||
{
|
||||
// Check type and fill m_vsPossibleDirsToExport
|
||||
const RString *s_packageType = &ExportPackages::m_sPackageType;
|
||||
if( *s_packageType == "Themes" )
|
||||
{
|
||||
// add themes
|
||||
GetDirListing( SpecialFiles::THEMES_DIR + "*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
else if( *s_packageType == "NoteSkins" )
|
||||
{
|
||||
// add noteskins
|
||||
vector<RString> vs;
|
||||
GetDirListing( SpecialFiles::NOTESKINS_DIR + "*", vs, true, true );
|
||||
FOREACH_CONST( RString, vs, s )
|
||||
GetDirListing( *s + "*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
else if( *s_packageType == "Courses" )
|
||||
{
|
||||
// Add courses. Only support courses that are in a group folder.
|
||||
// Support for courses not in a group folder should be phased out.
|
||||
vector<RString> vs;
|
||||
GetDirListing( SpecialFiles::COURSES_DIR + "*", vs, true, true );
|
||||
StripCvsAndSvn( vs );
|
||||
StripMacResourceForks( vs );
|
||||
FOREACH_CONST( RString, vs, s )
|
||||
{
|
||||
vector<RString> vs;
|
||||
GetDirListing( SpecialFiles::COURSES_DIR + "*", vs, true, true );
|
||||
StripCvsAndSvn( vs );
|
||||
StripMacResourceForks( vs );
|
||||
FOREACH_CONST( RString, vs, s )
|
||||
{
|
||||
m_vsPossibleDirsToExport.push_back( *s );
|
||||
GetDirListing( *s + "/*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
m_vsPossibleDirsToExport.push_back( *s );
|
||||
GetDirListing( *s + "/*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
|
||||
// Add songs
|
||||
{
|
||||
vector<RString> vs;
|
||||
GetDirListing( SpecialFiles::SONGS_DIR + "*", vs, true, true );
|
||||
FOREACH_CONST( RString, vs, s )
|
||||
{
|
||||
m_vsPossibleDirsToExport.push_back( *s );
|
||||
GetDirListing( *s + "/*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
}
|
||||
|
||||
StripCvsAndSvn( m_vsPossibleDirsToExport );
|
||||
StripMacResourceForks( m_vsPossibleDirsToExport );
|
||||
}
|
||||
else if( *s_packageType == "Songs" )
|
||||
{
|
||||
// Add song groups
|
||||
vector<RString> asAllGroups;
|
||||
SONGMAN->GetSongGroupNames(asAllGroups);
|
||||
FOREACH_CONST( RString, asAllGroups , s )
|
||||
{
|
||||
m_vsPossibleDirsToExport.push_back(*s);
|
||||
}
|
||||
}
|
||||
else if( *s_packageType == "SubGroup" )
|
||||
{
|
||||
//ExportPackages::m_sFolder
|
||||
/*
|
||||
vector<RString> vs;
|
||||
GetDirListing( SpecialFiles::SONGS_DIR + "*", vs, true, true );
|
||||
FOREACH_CONST( RString, vs, s )
|
||||
{
|
||||
m_vsPossibleDirsToExport.push_back( *s );
|
||||
GetDirListing( *s + "/*", m_vsPossibleDirsToExport, true, true );
|
||||
}
|
||||
*/
|
||||
}
|
||||
StripCvsAndSvn( m_vsPossibleDirsToExport );
|
||||
StripMacResourceForks( m_vsPossibleDirsToExport );
|
||||
|
||||
vector<OptionRowHandler*> OptionRowHandlers;
|
||||
FOREACH_CONST( RString, m_vsPossibleDirsToExport, s )
|
||||
@@ -142,7 +223,7 @@ static bool ExportPackage( RString sPackageName, RString sDirToExport, RString &
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScreenOptionsExportPackage::ProcessMenuStart( const InputEventPlus &input )
|
||||
void ScreenOptionsExportPackageSubPage::ProcessMenuStart( const InputEventPlus &input )
|
||||
{
|
||||
if( IsTransitioning() )
|
||||
return;
|
||||
@@ -154,6 +235,17 @@ void ScreenOptionsExportPackage::ProcessMenuStart( const InputEventPlus &input )
|
||||
return;
|
||||
}
|
||||
|
||||
if( ExportPackages::m_sPackageType == "Courses"
|
||||
|| ExportPackages::m_sPackageType == "NoteSkins"
|
||||
|| ExportPackages::m_sPackageType == "Songs" )
|
||||
{
|
||||
// find folder name
|
||||
ExportPackages::m_sPackageType = "SubGroup";
|
||||
ExportPackages::m_sFolder = m_vsPossibleDirsToExport[iCurRow];
|
||||
SCREENMAN->SetNewScreen("ScreenOptionsExportPackageSubPage");
|
||||
return;
|
||||
}
|
||||
|
||||
RString sDirToExport = m_vsPossibleDirsToExport[ iCurRow ];
|
||||
RString sPackageName = ReplaceInvalidFileNameChars( sDirToExport + ".smzip" );
|
||||
|
||||
@@ -164,12 +256,12 @@ void ScreenOptionsExportPackage::ProcessMenuStart( const InputEventPlus &input )
|
||||
ScreenPrompt::Prompt( SM_None, ssprintf("Failed to export package: %s",sError.c_str()) );
|
||||
}
|
||||
|
||||
void ScreenOptionsExportPackage::ImportOptions( int iRow, const vector<PlayerNumber> &vpns )
|
||||
void ScreenOptionsExportPackageSubPage::ImportOptions( int iRow, const vector<PlayerNumber> &vpns )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ScreenOptionsExportPackage::ExportOptions( int iRow, const vector<PlayerNumber> &vpns )
|
||||
void ScreenOptionsExportPackageSubPage::ExportOptions( int iRow, const vector<PlayerNumber> &vpns )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
|
||||
class Course;
|
||||
|
||||
// Can this be done any better? -aj
|
||||
namespace ExportPackages
|
||||
{
|
||||
RString m_sPackageType;
|
||||
RString m_sFolder; // used for more subpages
|
||||
}
|
||||
|
||||
/** @brief A menu for exporting packages. */
|
||||
class ScreenOptionsExportPackage : public ScreenOptions
|
||||
{
|
||||
@@ -13,6 +20,21 @@ public:
|
||||
void Init();
|
||||
virtual void BeginScreen();
|
||||
|
||||
protected:
|
||||
virtual void ImportOptions( int iRow, const vector<PlayerNumber> &vpns );
|
||||
virtual void ExportOptions( int iRow, const vector<PlayerNumber> &vpns );
|
||||
|
||||
virtual void ProcessMenuStart( const InputEventPlus &input );
|
||||
|
||||
vector<RString> m_vsPackageTypes;
|
||||
};
|
||||
|
||||
class ScreenOptionsExportPackageSubPage : public ScreenOptions
|
||||
{
|
||||
public:
|
||||
void Init();
|
||||
virtual void BeginScreen();
|
||||
|
||||
protected:
|
||||
virtual void ImportOptions( int iRow, const vector<PlayerNumber> &vpns );
|
||||
virtual void ExportOptions( int iRow, const vector<PlayerNumber> &vpns );
|
||||
|
||||
+26
-22
@@ -118,12 +118,13 @@ void ScreenPrompt::Input( const InputEventPlus &input )
|
||||
{
|
||||
switch( input.DeviceI.button )
|
||||
{
|
||||
case KEY_LEFT:
|
||||
this->MenuLeft( input );
|
||||
return;
|
||||
case KEY_RIGHT:
|
||||
this->MenuRight( input );
|
||||
return;
|
||||
case KEY_LEFT:
|
||||
this->MenuLeft( input );
|
||||
return;
|
||||
case KEY_RIGHT:
|
||||
this->MenuRight( input );
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,12 +199,13 @@ void ScreenPrompt::End( bool bCancelled )
|
||||
{
|
||||
switch( m_Answer )
|
||||
{
|
||||
case ANSWER_YES:
|
||||
m_smSendOnPop = SM_Success;
|
||||
break;
|
||||
case ANSWER_NO:
|
||||
m_smSendOnPop = SM_Failure;
|
||||
break;
|
||||
case ANSWER_YES:
|
||||
m_smSendOnPop = SM_Success;
|
||||
break;
|
||||
case ANSWER_NO:
|
||||
m_smSendOnPop = SM_Failure;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( bCancelled )
|
||||
@@ -218,14 +220,15 @@ void ScreenPrompt::End( bool bCancelled )
|
||||
|
||||
switch( m_Answer )
|
||||
{
|
||||
case ANSWER_YES:
|
||||
if( g_pOnYes )
|
||||
g_pOnYes(g_pCallbackData);
|
||||
break;
|
||||
case ANSWER_NO:
|
||||
if( g_pOnNo )
|
||||
g_pOnNo(g_pCallbackData);
|
||||
break;
|
||||
case ANSWER_YES:
|
||||
if( g_pOnYes )
|
||||
g_pOnYes(g_pCallbackData);
|
||||
break;
|
||||
case ANSWER_NO:
|
||||
if( g_pOnNo )
|
||||
g_pOnNo(g_pCallbackData);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
s_LastAnswer = bCancelled ? ANSWER_CANCEL : m_Answer;
|
||||
@@ -251,8 +254,9 @@ void ScreenPrompt::TweenOffScreen()
|
||||
// lua start
|
||||
/*
|
||||
#include "LuaBinding.h"
|
||||
|
||||
/** @brief Allow Lua to have access to the ScreenPrompt.
|
||||
|
||||
// use proper doxygen when lua is enabled.
|
||||
@brief Allow Lua to have access to the ScreenPrompt.
|
||||
class LunaScreenPrompt: public Luna<ScreenPrompt>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -212,14 +212,15 @@ float ScreenRanking::SetPage( const PageToShow &pts )
|
||||
bool bShowTime = false;
|
||||
switch( RANKING_TYPE )
|
||||
{
|
||||
case RankingType_Category:
|
||||
bShowScores = true;
|
||||
break;
|
||||
case RankingType_SpecificTrail:
|
||||
bShowScores = !pts.pCourse->IsOni();
|
||||
bShowPoints = pts.pCourse->IsOni();
|
||||
bShowTime = pts.pCourse->IsOni();
|
||||
break;
|
||||
case RankingType_Category:
|
||||
bShowScores = true;
|
||||
break;
|
||||
case RankingType_SpecificTrail:
|
||||
bShowScores = !pts.pCourse->IsOni();
|
||||
bShowPoints = pts.pCourse->IsOni();
|
||||
bShowTime = pts.pCourse->IsOni();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
for( int l=0; l<NUM_RANKING_LINES; l++ )
|
||||
|
||||
@@ -205,10 +205,11 @@ void ScreenSelectCharacter::BeforeRowChange( PlayerNumber pn )
|
||||
PlayerNumber pnAffected = GetAffectedPlayerNumber(pn);
|
||||
switch( m_SelectionRow[pn] )
|
||||
{
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
m_sprCardArrows[pnAffected].StopEffect();
|
||||
break;
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
m_sprCardArrows[pnAffected].StopEffect();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,10 +218,11 @@ void ScreenSelectCharacter::AfterRowChange( PlayerNumber pn )
|
||||
PlayerNumber pnAffected = GetAffectedPlayerNumber(pn);
|
||||
switch( m_SelectionRow[pn] )
|
||||
{
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
m_sprCardArrows[pnAffected].SetEffectGlowShift();
|
||||
break;
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
m_sprCardArrows[pnAffected].SetEffectGlowShift();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,15 +299,18 @@ void ScreenSelectCharacter::Move( PlayerNumber pn, int deltaValue )
|
||||
PlayerNumber pnAffected = GetAffectedPlayerNumber(pn);
|
||||
switch( m_SelectionRow[pn] )
|
||||
{
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
vector<Character*> apCharacters;
|
||||
CHARMAN->GetCharacters( apCharacters );
|
||||
m_iSelectedCharacter[pnAffected] += deltaValue;
|
||||
wrap( m_iSelectedCharacter[pnAffected], apCharacters.size() );
|
||||
AfterValueChange(pn);
|
||||
m_soundChange.Play();
|
||||
break;
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
{
|
||||
vector<Character*> apCharacters;
|
||||
CHARMAN->GetCharacters( apCharacters );
|
||||
m_iSelectedCharacter[pnAffected] += deltaValue;
|
||||
wrap( m_iSelectedCharacter[pnAffected], apCharacters.size() );
|
||||
AfterValueChange(pn);
|
||||
m_soundChange.Play();
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,12 +337,13 @@ void ScreenSelectCharacter::MakeSelection( PlayerNumber pn )
|
||||
BeforeRowChange(pn);
|
||||
switch( m_SelectionRow[pn] )
|
||||
{
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
m_SelectionRow[pn] = GAMESTATE->AnyPlayersAreCpu() ? CHOOSING_CPU_CHARACTER : FINISHED_CHOOSING;
|
||||
break;
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
m_SelectionRow[pn] = FINISHED_CHOOSING;
|
||||
break;
|
||||
case CHOOSING_HUMAN_CHARACTER:
|
||||
m_SelectionRow[pn] = GAMESTATE->AnyPlayersAreCpu() ? CHOOSING_CPU_CHARACTER : FINISHED_CHOOSING;
|
||||
break;
|
||||
case CHOOSING_CPU_CHARACTER:
|
||||
m_SelectionRow[pn] = FINISHED_CHOOSING;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
AfterRowChange(pn);
|
||||
AfterValueChange(pn);
|
||||
|
||||
+16
-15
@@ -528,21 +528,22 @@ void ScreenSelectMusic::Input( const InputEventPlus &input )
|
||||
{
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_LEFT:
|
||||
ChangeSteps( input.pn, -1 );
|
||||
m_bAcceptSelectRelease[input.pn] = false;
|
||||
break;
|
||||
case GAME_BUTTON_RIGHT:
|
||||
ChangeSteps( input.pn, +1 );
|
||||
m_bAcceptSelectRelease[input.pn] = false;
|
||||
break;
|
||||
case GAME_BUTTON_START:
|
||||
m_bAcceptSelectRelease[input.pn] = false;
|
||||
if( MODE_MENU_AVAILABLE )
|
||||
m_MusicWheel.NextSort();
|
||||
else
|
||||
m_soundLocked.Play();
|
||||
break;
|
||||
case GAME_BUTTON_LEFT:
|
||||
ChangeSteps( input.pn, -1 );
|
||||
m_bAcceptSelectRelease[input.pn] = false;
|
||||
break;
|
||||
case GAME_BUTTON_RIGHT:
|
||||
ChangeSteps( input.pn, +1 );
|
||||
m_bAcceptSelectRelease[input.pn] = false;
|
||||
break;
|
||||
case GAME_BUTTON_START:
|
||||
m_bAcceptSelectRelease[input.pn] = false;
|
||||
if( MODE_MENU_AVAILABLE )
|
||||
m_MusicWheel.NextSort();
|
||||
else
|
||||
m_soundLocked.Play();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else if( input.type == IET_FIRST_PRESS && input.MenuI != GAME_BUTTON_SELECT )
|
||||
|
||||
+38
-26
@@ -212,17 +212,21 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input )
|
||||
}
|
||||
switch( input.type )
|
||||
{
|
||||
case IET_RELEASE: fDelta *= 0; break;
|
||||
case IET_REPEAT:
|
||||
if( INPUTFILTER->GetSecsHeld(input.DeviceI) < 1.0f )
|
||||
fDelta *= 0;
|
||||
else
|
||||
fDelta *= 10;
|
||||
case IET_RELEASE: fDelta *= 0; break;
|
||||
case IET_REPEAT:
|
||||
{
|
||||
if( INPUTFILTER->GetSecsHeld(input.DeviceI) < 1.0f )
|
||||
fDelta *= 0;
|
||||
else
|
||||
fDelta *= 10;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
if( GAMESTATE->m_pCurSong != NULL )
|
||||
{
|
||||
BPMSegment& seg = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat );
|
||||
seg.SetBPS( seg.GetBPS() + fDelta );
|
||||
BPMSegment * seg = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat );
|
||||
seg->SetBPS( seg->GetBPS() + fDelta );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -237,31 +241,39 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input )
|
||||
}
|
||||
switch( input.type )
|
||||
{
|
||||
case IET_RELEASE: fDelta *= 0; break;
|
||||
case IET_REPEAT:
|
||||
if( INPUTFILTER->GetSecsHeld(input.DeviceI) < 1.0f )
|
||||
fDelta *= 0;
|
||||
else
|
||||
fDelta *= 10;
|
||||
case IET_RELEASE: fDelta *= 0; break;
|
||||
case IET_REPEAT:
|
||||
{
|
||||
if( INPUTFILTER->GetSecsHeld(input.DeviceI) < 1.0f )
|
||||
fDelta *= 0;
|
||||
else
|
||||
fDelta *= 10;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch( a )
|
||||
{
|
||||
case ChangeGlobalOffset:
|
||||
case ChangeGlobalOffset:
|
||||
{
|
||||
PREFSMAN->m_fGlobalOffsetSeconds.Set( PREFSMAN->m_fGlobalOffsetSeconds + fDelta );
|
||||
break;
|
||||
|
||||
case ChangeSongOffset:
|
||||
if( GAMESTATE->m_pCurSong != NULL )
|
||||
{
|
||||
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta;
|
||||
const vector<Steps *>& vpSteps = GAMESTATE->m_pCurSong->GetAllSteps();
|
||||
FOREACH( Steps*, const_cast<vector<Steps *>&>(vpSteps), s )
|
||||
{
|
||||
(*s)->m_Timing.m_fBeat0OffsetInSeconds += fDelta;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ChangeSongOffset:
|
||||
{
|
||||
if( GAMESTATE->m_pCurSong != NULL )
|
||||
{
|
||||
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta;
|
||||
const vector<Steps *>& vpSteps = GAMESTATE->m_pCurSong->GetAllSteps();
|
||||
FOREACH( Steps*, const_cast<vector<Steps *>&>(vpSteps), s )
|
||||
{
|
||||
(*s)->m_Timing.m_fBeat0OffsetInSeconds += fDelta;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+11
-6
@@ -95,14 +95,19 @@ void ScreenTestInput::Input( const InputEventPlus &input )
|
||||
RString sMessage = input.DeviceI.ToString();
|
||||
switch( input.type )
|
||||
{
|
||||
case IET_FIRST_PRESS:
|
||||
case IET_RELEASE:
|
||||
switch( input.type )
|
||||
case IET_FIRST_PRESS:
|
||||
case IET_RELEASE:
|
||||
{
|
||||
case IET_FIRST_PRESS: sMessage += "Pressed"; break;
|
||||
case IET_RELEASE: sMessage += "Released"; break;
|
||||
switch( input.type )
|
||||
{
|
||||
case IET_FIRST_PRESS: sMessage += "Pressed"; break;
|
||||
case IET_RELEASE: sMessage += "Released"; break;
|
||||
default: break;
|
||||
}
|
||||
MESSAGEMAN->Broadcast( sMessage );
|
||||
break;
|
||||
}
|
||||
MESSAGEMAN->Broadcast( sMessage );
|
||||
default: break;
|
||||
}
|
||||
|
||||
Screen::Input( input ); // default handler
|
||||
|
||||
@@ -59,12 +59,13 @@ void ScreenTestLights::Update( float fDeltaTime )
|
||||
|
||||
switch( LIGHTSMAN->GetLightsMode() )
|
||||
{
|
||||
case LIGHTSMODE_TEST_AUTO_CYCLE:
|
||||
s += AUTO_CYCLE.GetValue()+"\n";
|
||||
break;
|
||||
case LIGHTSMODE_TEST_MANUAL_CYCLE:
|
||||
s += MANUAL_CYCLE.GetValue()+"\n";
|
||||
break;
|
||||
case LIGHTSMODE_TEST_AUTO_CYCLE:
|
||||
s += AUTO_CYCLE.GetValue()+"\n";
|
||||
break;
|
||||
case LIGHTSMODE_TEST_MANUAL_CYCLE:
|
||||
s += MANUAL_CYCLE.GetValue()+"\n";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( cl == CabinetLight_Invalid )
|
||||
|
||||
+44
-43
@@ -137,68 +137,69 @@ void ScreenTestSound::Input( const InputEventPlus &input )
|
||||
case DEVICE_KEYBOARD:
|
||||
switch( input.DeviceI.button )
|
||||
{
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5': selected = input.DeviceI.button - '0'-1; break;
|
||||
case 'p':
|
||||
{
|
||||
/* We want to be able to read the position of copied sounds; if we let
|
||||
* RageSound copy itself, then the copy will be owned by RageSoundManager
|
||||
* and we won't be allowed to touch it. Copy it ourself. */
|
||||
RageSound *pCopy = new RageSound( s[selected].s );
|
||||
m_sSoundCopies[selected].push_back( pCopy );
|
||||
pCopy->Play();
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
for( int i = 0; i < nsounds; ++i )
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5': selected = input.DeviceI.button - '0'-1; break;
|
||||
case 'p':
|
||||
{
|
||||
/* Stop copied sounds. */
|
||||
vector<RageSound *> &snds = m_sSoundCopies[i];
|
||||
for( unsigned j = 0; j < snds.size(); ++j )
|
||||
snds[j]->Stop();
|
||||
/* We want to be able to read the position of copied sounds; if we let
|
||||
* RageSound copy itself, then the copy will be owned by RageSoundManager
|
||||
* and we won't be allowed to touch it. Copy it ourself. */
|
||||
RageSound *pCopy = new RageSound( s[selected].s );
|
||||
m_sSoundCopies[selected].push_back( pCopy );
|
||||
pCopy->Play();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
case 's':
|
||||
{
|
||||
for( int i = 0; i < nsounds; ++i )
|
||||
{
|
||||
/* Stop copied sounds. */
|
||||
vector<RageSound *> &snds = m_sSoundCopies[i];
|
||||
for( unsigned j = 0; j < snds.size(); ++j )
|
||||
snds[j]->Stop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
{
|
||||
RageSoundParams p = s[selected].s.GetParams();
|
||||
p.StopMode = RageSoundParams::M_LOOP;
|
||||
s[selected].s.SetParams( p );
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'a':
|
||||
case 'a':
|
||||
{
|
||||
RageSoundParams p = s[selected].s.GetParams();
|
||||
p.StopMode = RageSoundParams::M_STOP;
|
||||
s[selected].s.SetParams( p );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
case 'c':
|
||||
{
|
||||
RageSoundParams p = s[selected].s.GetParams();
|
||||
p.StopMode = RageSoundParams::M_CONTINUE;
|
||||
s[selected].s.SetParams( p );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* case KEY_LEFT:
|
||||
obj.SetX(obj.GetX() - 10);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
obj.SetX(obj.GetX() + 10);
|
||||
break;
|
||||
case KEY_UP:
|
||||
obj.SetY(obj.GetY() - 10);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
obj.SetY(obj.GetY() + 10);
|
||||
break;
|
||||
/* case KEY_LEFT:
|
||||
obj.SetX(obj.GetX() - 10);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
obj.SetX(obj.GetX() + 10);
|
||||
break;
|
||||
case KEY_UP:
|
||||
obj.SetY(obj.GetY() - 10);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
obj.SetY(obj.GetY() + 10);
|
||||
break;
|
||||
*/
|
||||
default: break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -200,10 +200,11 @@ void ScreenTextEntry::Input( const InputEventPlus &input )
|
||||
{
|
||||
switch( input.type )
|
||||
{
|
||||
case IET_FIRST_PRESS:
|
||||
case IET_REPEAT:
|
||||
BackspaceInAnswer();
|
||||
break;
|
||||
case IET_FIRST_PRESS:
|
||||
case IET_REPEAT:
|
||||
BackspaceInAnswer();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( input.type == IET_FIRST_PRESS )
|
||||
|
||||
+102
-108
@@ -41,7 +41,7 @@
|
||||
* @brief The internal version of the cache for StepMania.
|
||||
*
|
||||
* Increment this value to invalidate the current cache. */
|
||||
const int FILE_CACHE_VERSION = 191;
|
||||
const int FILE_CACHE_VERSION = 196;
|
||||
|
||||
/** @brief How long does a song sample last by default? */
|
||||
const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f;
|
||||
@@ -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,38 +827,47 @@ 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)
|
||||
{
|
||||
NoteData dummy;
|
||||
dummy.SetNumTracks(tempNoteData.GetNumTracks());
|
||||
pSteps->SetNoteData(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
this->firstSecond = localFirst;
|
||||
// Yes, for some reason we can have freaky stuff take place here.
|
||||
this->firstSecond = (localFirst < localLast) ? localFirst : 0;
|
||||
this->lastSecond = localLast;
|
||||
}
|
||||
|
||||
@@ -1005,11 +958,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 +979,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 +1007,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 +1024,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 +1250,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 )
|
||||
{
|
||||
|
||||
+23
-6
@@ -20,7 +20,7 @@ void FixupPath( RString &path, const RString &sSongPath );
|
||||
RString GetSongAssetPath( RString sPath, const RString &sSongPath );
|
||||
|
||||
/** @brief The version of the .ssc file format. */
|
||||
const static float STEPFILE_VERSION_NUMBER = 0.76f;
|
||||
const static float STEPFILE_VERSION_NUMBER = 0.77f;
|
||||
|
||||
/** @brief How many edits for this song can each profile have? */
|
||||
const int MAX_EDITS_PER_SONG_PER_PROFILE = 15;
|
||||
@@ -91,14 +91,19 @@ public:
|
||||
// This one takes the effort to reuse Steps pointers as best as it can
|
||||
bool ReloadFromSongDir( RString sDir );
|
||||
|
||||
/** @brief Call this after loading a song to clean up invalid data. */
|
||||
void TidyUpData( bool bFromCache = false );
|
||||
/**
|
||||
* @brief Call this after loading a song to clean up invalid data.
|
||||
* @param fromCache was this data loaded from the cache file?
|
||||
* @param duringCache was this data loaded during the cache process? */
|
||||
void TidyUpData( bool fromCache = false, bool duringCache = false );
|
||||
|
||||
/**
|
||||
* @brief Get the new radar values, and determine the last second at the same time.
|
||||
*
|
||||
* This is called by TidyUpData, after saving the Song. */
|
||||
void ReCalculateRadarValuesAndLastSecond( bool bFromCache = false );
|
||||
* This is called by TidyUpData, after saving the Song.
|
||||
* @param fromCache was this data loaded from the cache file?
|
||||
* @param duringCache was this data loaded during the cache process? */
|
||||
void ReCalculateRadarValuesAndLastSecond(bool fromCache = false, bool duringCache = false);
|
||||
/**
|
||||
* @brief Translate any titles that aren't in english.
|
||||
*
|
||||
@@ -180,7 +185,6 @@ public:
|
||||
RString GetDisplaySubTitle() const;
|
||||
RString GetDisplayArtist() const;
|
||||
|
||||
// Returns the transliterated titles, if any; otherwise returns the main titles.
|
||||
/**
|
||||
* @brief Retrieve the transliterated title, or the main title if there is no translit.
|
||||
* @return the proper title. */
|
||||
@@ -315,12 +319,20 @@ private:
|
||||
*
|
||||
* This must be sorted before gameplay. */
|
||||
AutoPtrCopyOnWrite<VBackgroundChange> m_ForegroundChanges;
|
||||
|
||||
vector<RString> GetChangesToVectorString(const vector<BackgroundChange> & changes) const;
|
||||
public:
|
||||
const vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl ) const;
|
||||
vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl );
|
||||
const vector<BackgroundChange> &GetForegroundChanges() const;
|
||||
vector<BackgroundChange> &GetForegroundChanges();
|
||||
|
||||
vector<RString> GetBGChanges1ToVectorString() const;
|
||||
vector<RString> GetBGChanges2ToVectorString() const;
|
||||
vector<RString> GetFGChanges1ToVectorString() const;
|
||||
|
||||
vector<RString> GetInstrumentTracksToVectorString() const;
|
||||
|
||||
/**
|
||||
* @brief The list of LyricSegments.
|
||||
*
|
||||
@@ -426,6 +438,11 @@ public:
|
||||
|
||||
CachedObject<Song> m_CachedObject;
|
||||
|
||||
RString GetAttackString() const
|
||||
{
|
||||
return join(":", this->m_sAttackString);
|
||||
}
|
||||
|
||||
// Lua
|
||||
void PushSelf( lua_State *L );
|
||||
|
||||
|
||||
+6
-5
@@ -499,7 +499,7 @@ RageColor SongManager::GetSongColor( const Song* pSong ) const
|
||||
int i = m_vPreferredSongSort.size();
|
||||
return SONG_GROUP_COLOR.GetValue( i%NUM_SONG_GROUP_COLORS );
|
||||
}
|
||||
else
|
||||
else // TODO: Have a better fallback plan with colors?
|
||||
{
|
||||
/* XXX: Previously, this matched all notes, which set a song to "extra"
|
||||
* if it had any 10-foot steps at all, even edits or doubles.
|
||||
@@ -518,9 +518,10 @@ RageColor SongManager::GetSongColor( const Song* pSong ) const
|
||||
const Steps* pSteps = vpSteps[i];
|
||||
switch( pSteps->GetDifficulty() )
|
||||
{
|
||||
case Difficulty_Challenge:
|
||||
case Difficulty_Edit:
|
||||
continue;
|
||||
case Difficulty_Challenge:
|
||||
case Difficulty_Edit:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
|
||||
//if(pSteps->m_StepsType != st)
|
||||
@@ -529,7 +530,7 @@ RageColor SongManager::GetSongColor( const Song* pSong ) const
|
||||
if( pSteps->GetMeter() >= EXTRA_COLOR_METER )
|
||||
return (RageColor)EXTRA_COLOR;
|
||||
}
|
||||
if( pSong->m_sMainTitle == "DVNO")
|
||||
if( pSong->m_sMainTitle == "DVNO") // XXX: What IS this? An easter egg? -Wolfman2000
|
||||
{
|
||||
return RageColor(1.0f,0.8f,0.0f,1.0f);
|
||||
}
|
||||
|
||||
+4
-3
@@ -166,9 +166,10 @@ void StageStats::FinalizeScores( bool bSummary )
|
||||
{
|
||||
switch( GAMESTATE->m_PlayMode )
|
||||
{
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
return; // don't save scores in battle
|
||||
case PLAY_MODE_BATTLE:
|
||||
case PLAY_MODE_RAVE:
|
||||
return; // don't save scores in battle
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( PREFSMAN->m_sTestInitialScreen.Get() != "" )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="sm-ssc"
|
||||
Name="StepMania"
|
||||
ProjectGUID="{AF209DBD-24BD-4356-8DFE-41751B221195}"
|
||||
RootNamespace="StepMania"
|
||||
Keyword="MFCProj"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>sm-ssc</ProjectName>
|
||||
<ProjectName>StepMania</ProjectName>
|
||||
<ProjectGuid>{AF209DBD-24BD-4356-8DFE-41751B221195}</ProjectGuid>
|
||||
<RootNamespace>StepMania</RootNamespace>
|
||||
<Keyword>MFCProj</Keyword>
|
||||
@@ -67,15 +67,15 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='FastDebug|Win32'">$(TargetDir)</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='FastDebug|Win32'">$(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='FastDebug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='FastDebug|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='FastDebug|Win32'">true</LinkIncremental>
|
||||
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='FastDebug|Win32'">true</GenerateManifest>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release-SSE2|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
|
||||
+25
-23
@@ -1060,13 +1060,14 @@ int main(int argc, char* argv[])
|
||||
GAMESTATE->m_bDopefish = true;
|
||||
|
||||
{
|
||||
/* Now that THEME is loaded, load the icon for the current theme into
|
||||
* the loading window. */
|
||||
/* Now that THEME is loaded, load the icon and splash for the current
|
||||
* theme into the loading window. */
|
||||
RString sError;
|
||||
RageSurface *pIcon = RageSurfaceUtils::LoadFile( THEME->GetPathG( "Common", "window icon" ), sError );
|
||||
if( pIcon )
|
||||
pLoadingWindow->SetIcon( pIcon );
|
||||
delete pIcon;
|
||||
pLoadingWindow->SetSplash( THEME->GetPathG("Common","splash") );
|
||||
}
|
||||
|
||||
if( PREFSMAN->m_iSoundWriteAhead )
|
||||
@@ -1296,28 +1297,29 @@ bool HandleGlobalInputs( const InputEventPlus &input )
|
||||
|
||||
switch( input.MenuI )
|
||||
{
|
||||
case GAME_BUTTON_OPERATOR:
|
||||
/* Global operator key, to get quick access to the options menu. Don't
|
||||
* do this if we're on a "system menu", which includes the editor
|
||||
* (to prevent quitting without storing changes). */
|
||||
if( SCREENMAN->AllowOperatorMenuButton() )
|
||||
{
|
||||
SCREENMAN->SystemMessage( SERVICE_SWITCH_PRESSED );
|
||||
SCREENMAN->PopAllScreens();
|
||||
GAMESTATE->Reset();
|
||||
SCREENMAN->SetNewScreen( CommonMetrics::OPERATOR_MENU_SCREEN );
|
||||
}
|
||||
return true;
|
||||
case GAME_BUTTON_OPERATOR:
|
||||
/* Global operator key, to get quick access to the options menu. Don't
|
||||
* do this if we're on a "system menu", which includes the editor
|
||||
* (to prevent quitting without storing changes). */
|
||||
if( SCREENMAN->AllowOperatorMenuButton() )
|
||||
{
|
||||
SCREENMAN->SystemMessage( SERVICE_SWITCH_PRESSED );
|
||||
SCREENMAN->PopAllScreens();
|
||||
GAMESTATE->Reset();
|
||||
SCREENMAN->SetNewScreen( CommonMetrics::OPERATOR_MENU_SCREEN );
|
||||
}
|
||||
return true;
|
||||
|
||||
case GAME_BUTTON_COIN:
|
||||
// Handle a coin insertion.
|
||||
if( GAMESTATE->IsEditing() ) // no coins while editing
|
||||
{
|
||||
LOG->Trace( "Ignored coin insertion (editing)" );
|
||||
break;
|
||||
}
|
||||
StepMania::InsertCoin();
|
||||
return false; // Attract needs to know because it goes to TitleMenu on > 1 credit
|
||||
case GAME_BUTTON_COIN:
|
||||
// Handle a coin insertion.
|
||||
if( GAMESTATE->IsEditing() ) // no coins while editing
|
||||
{
|
||||
LOG->Trace( "Ignored coin insertion (editing)" );
|
||||
break;
|
||||
}
|
||||
StepMania::InsertCoin();
|
||||
return false; // Attract needs to know because it goes to TitleMenu on > 1 credit
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* Re-added for StepMania 3.9 theming veterans, plus it's just faster than
|
||||
|
||||
+58
-30
@@ -24,6 +24,11 @@
|
||||
#include "NoteDataUtil.h"
|
||||
#include "NotesLoaderSSC.h"
|
||||
#include "NotesLoaderSM.h"
|
||||
#include "NotesLoaderSMA.h"
|
||||
#include "NotesLoaderDWI.h"
|
||||
#include "NotesLoaderKSF.h"
|
||||
#include "NotesLoaderBMS.h"
|
||||
#include "NotesLoaderPMS.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -78,6 +83,50 @@ unsigned Steps::GetHash() const
|
||||
return m_iHash;
|
||||
}
|
||||
|
||||
bool Steps::IsNoteDataEmpty() const
|
||||
{
|
||||
return this->m_sNoteDataCompressed.empty();
|
||||
}
|
||||
|
||||
bool Steps::GetNoteDataFromSimfile()
|
||||
{
|
||||
// Replace the line below with the Steps' cache file.
|
||||
RString stepFile = this->GetFilename();
|
||||
RString extension = GetExtension(stepFile);
|
||||
if (extension.empty() || extension == "ssc") // remember cache files.
|
||||
{
|
||||
SSCLoader loader;
|
||||
return loader.LoadNoteDataFromSimfile(stepFile, *this);
|
||||
}
|
||||
else if (extension == "sm")
|
||||
{
|
||||
SMLoader loader;
|
||||
return loader.LoadNoteDataFromSimfile(stepFile, *this);
|
||||
}
|
||||
else if (extension == "sma")
|
||||
{
|
||||
SMALoader loader;
|
||||
return loader.LoadNoteDataFromSimfile(stepFile, *this);
|
||||
}
|
||||
else if (extension == "dwi")
|
||||
{
|
||||
return DWILoader::LoadNoteDataFromSimfile(stepFile, *this);
|
||||
}
|
||||
else if (extension == "ksf")
|
||||
{
|
||||
return KSFLoader::LoadNoteDataFromSimfile(stepFile, *this);
|
||||
}
|
||||
else if (extension == "bms" || extension == "bml" || extension == "bme")
|
||||
{
|
||||
return BMSLoader::LoadNoteDataFromSimfile(stepFile, *this);
|
||||
}
|
||||
else if (extension == "pms")
|
||||
{
|
||||
return PMSLoader::LoadNoteDataFromSimfile(stepFile, *this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Steps::SetNoteData( const NoteData& noteDataNew )
|
||||
{
|
||||
ASSERT( noteDataNew.GetNumTracks() == GAMEMAN->GetStepsTypeInfo(m_StepsType).iNumTracks );
|
||||
@@ -89,7 +138,6 @@ void Steps::SetNoteData( const NoteData& noteDataNew )
|
||||
|
||||
m_sNoteDataCompressed = RString();
|
||||
m_iHash = 0;
|
||||
m_sFilename = RString(); // We can no longer read from the file because it has changed in memory.
|
||||
}
|
||||
|
||||
void Steps::GetNoteData( NoteData& noteDataOut ) const
|
||||
@@ -121,7 +169,6 @@ void Steps::SetSMNoteData( const RString ¬es_comp_ )
|
||||
|
||||
m_sNoteDataCompressed = notes_comp_;
|
||||
m_iHash = 0;
|
||||
m_sFilename = RString(); // We can no longer read from the file because it has changed in memory.
|
||||
}
|
||||
|
||||
/* XXX: this function should pull data from m_sFilename, like Decompress() */
|
||||
@@ -250,6 +297,11 @@ void Steps::CalculateRadarValues( float fMusicLengthSeconds )
|
||||
}
|
||||
|
||||
void Steps::Decompress() const
|
||||
{
|
||||
const_cast<Steps *>(this)->Decompress();
|
||||
}
|
||||
|
||||
void Steps::Decompress()
|
||||
{
|
||||
if( m_bNoteDataIsFilled )
|
||||
return; // already decompressed
|
||||
@@ -279,38 +331,14 @@ void Steps::Decompress() const
|
||||
|
||||
if( !m_sFilename.empty() && m_sNoteDataCompressed.empty() )
|
||||
{
|
||||
// We have data on disk and not in memory. Load it.
|
||||
Song s;
|
||||
SSCLoader loaderSSC;
|
||||
bool bLoadedFromSSC = loaderSSC.LoadFromSimfile(m_sFilename, s, true);
|
||||
if( !bLoadedFromSSC )
|
||||
// We have NoteData on disk and not in memory. Load it.
|
||||
if (!this->GetNoteDataFromSimfile())
|
||||
{
|
||||
// try reading from .sm instead
|
||||
SMLoader loaderSM;
|
||||
if( !loaderSM.LoadFromSimfile(m_sFilename, s, true) )
|
||||
{
|
||||
LOG->Warn( "Couldn't load \"%s\"", m_sFilename.c_str() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the steps. */
|
||||
StepsID ID;
|
||||
ID.FromSteps( this );
|
||||
|
||||
/* We're using a StepsID to search in a different copy of a Song than
|
||||
* the one it was created with. Clear the cache before doing this,
|
||||
* or search results will come from cache and point to the original
|
||||
* copy. */
|
||||
CachedObject<Steps>::ClearCacheAll();
|
||||
Steps *pSteps = ID.ToSteps( &s, true );
|
||||
if( pSteps == NULL )
|
||||
{
|
||||
LOG->Warn( "Couldn't find %s in \"%s\"", ID.ToString().c_str(), m_sFilename.c_str() );
|
||||
LOG->Warn("Couldn't load \"%s\"", m_sFilename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
pSteps->GetSMNoteData( m_sNoteDataCompressed );
|
||||
this->GetSMNoteData( m_sNoteDataCompressed );
|
||||
}
|
||||
|
||||
if( m_sNoteDataCompressed.empty() )
|
||||
|
||||
+18
@@ -49,6 +49,7 @@ public:
|
||||
|
||||
void Compress() const;
|
||||
void Decompress() const;
|
||||
void Decompress();
|
||||
/**
|
||||
* @brief Determine if these steps were created by the autogenerator.
|
||||
* @return true if they were, false otherwise.
|
||||
@@ -138,6 +139,18 @@ public:
|
||||
void SetNoteData( const NoteData& noteDataNew );
|
||||
void SetSMNoteData( const RString ¬es_comp );
|
||||
void GetSMNoteData( RString ¬es_comp_out ) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve the NoteData from the original source.
|
||||
* @return true if successful, false for failure. */
|
||||
bool GetNoteDataFromSimfile();
|
||||
|
||||
/**
|
||||
* @brief Determine if we are missing any note data.
|
||||
*
|
||||
* This takes advantage of the fact that we usually compress our data.
|
||||
* @return true if our notedata is empty, false otherwise. */
|
||||
bool IsNoteDataEmpty() const;
|
||||
|
||||
void TidyUpData();
|
||||
void CalculateRadarValues( float fMusicLengthSeconds );
|
||||
@@ -200,6 +213,11 @@ public:
|
||||
|
||||
void GetDisplayBpms( DisplayBpms &addTo) const;
|
||||
|
||||
RString GetAttackString() const
|
||||
{
|
||||
return join(":", this->m_sAttackString);
|
||||
}
|
||||
|
||||
private:
|
||||
inline const Steps *Real() const { return parent ? parent : this; }
|
||||
void DeAutogen( bool bCopyNoteData = true ); /* If this Steps is autogenerated, make it a real Steps. */
|
||||
|
||||
+513
-1127
File diff suppressed because it is too large
Load Diff
+71
-644
@@ -16,14 +16,41 @@ struct lua_State;
|
||||
class TimingData
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Sets up initial timing data.
|
||||
*/
|
||||
TimingData();
|
||||
void AddSegment(TimingSegmentType tst, TimingSegment * seg);
|
||||
|
||||
int GetSegmentIndexAtRow(TimingSegmentType tst,
|
||||
int row, bool isDelay = false) const;
|
||||
|
||||
int GetSegmentIndexAtBeat(TimingSegmentType tst,
|
||||
float beat, bool isDelay = false) const
|
||||
{
|
||||
return this->GetSegmentIndexAtRow(tst, BeatToNoteRow(beat), isDelay);
|
||||
}
|
||||
|
||||
float GetNextSegmentBeatAtRow(TimingSegmentType tst,
|
||||
int row, bool isDelay = false) const;
|
||||
|
||||
float GetNextSegmentBeatAtBeat(TimingSegmentType tst,
|
||||
float beat, bool isDelay = false) const
|
||||
{
|
||||
return this->GetNextSegmentBeatAtRow(tst, BeatToNoteRow(beat), isDelay);
|
||||
}
|
||||
|
||||
float GetPreviousSegmentBeatAtRow(TimingSegmentType tst,
|
||||
int row, bool isDelay = false) const;
|
||||
|
||||
float GetPreviousSegmentBeatAtBeat(TimingSegmentType tst,
|
||||
float beat, bool isDelay = false) const
|
||||
{
|
||||
return this->GetPreviousSegmentBeatAtRow(tst, BeatToNoteRow(beat), isDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets up initial timing data with a defined offset.
|
||||
* @param fOffset the offset from the 0th beat. */
|
||||
TimingData(float fOffset);
|
||||
TimingData(float fOffset = 0);
|
||||
|
||||
~TimingData();
|
||||
/**
|
||||
* @brief Gets the actual BPM of the song,
|
||||
* while respecting a limit.
|
||||
@@ -63,62 +90,13 @@ public:
|
||||
* @param iNoteRow the row that has a BPMSegment.
|
||||
* @return the BPMSegment in question.
|
||||
*/
|
||||
BPMSegment& GetBPMSegmentAtRow( int iNoteRow );
|
||||
BPMSegment* GetBPMSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the BPMSegment at the specified beat.
|
||||
* @param fBeat the beat that has a BPMSegment.
|
||||
* @return the BPMSegment in question.
|
||||
*/
|
||||
BPMSegment& GetBPMSegmentAtBeat( float fBeat ) { return GetBPMSegmentAtRow( (int)BeatToNoteRow(fBeat)); }
|
||||
/**
|
||||
* @brief Retrieve the index of the BPMSegments at the specified row.
|
||||
* @param iNoteRow the row that has a BPMSegment.
|
||||
* @return the BPMSegment's index in question.
|
||||
*/
|
||||
int GetBPMSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the BPMSegments at the specified beat.
|
||||
* @param fBeat the beat that has a BPMSegment.
|
||||
* @return the BPMSegment's index in question.
|
||||
*/
|
||||
int GetBPMSegmentIndexAtBeat( float fBeat ) const { return GetBPMSegmentIndexAtRow( BeatToNoteRow(fBeat)); }
|
||||
/**
|
||||
* @brief Add the BPMSegment to the TimingData.
|
||||
* @param seg the new BPMSegment.
|
||||
*/
|
||||
void AddBPMSegment( const BPMSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a BPMSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a BPMSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextBPMSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a BPMSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a BPMSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextBPMSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextBPMSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a BPMSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a BPMSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousBPMSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a BPMSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a BPMSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousBPMSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousBPMSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
BPMSegment* GetBPMSegmentAtBeat( float fBeat ) { return GetBPMSegmentAtRow( (int)BeatToNoteRow(fBeat)); }
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Stop/Delay at the given row.
|
||||
@@ -209,145 +187,40 @@ public:
|
||||
* @param iNoteRow the row that has a StopSegment.
|
||||
* @return the StopSegment in question.
|
||||
*/
|
||||
StopSegment& GetStopSegmentAtRow( int iNoteRow ) { return GetStopSegmentAtRow( iNoteRow, false ); }
|
||||
StopSegment* GetStopSegmentAtRow( int iNoteRow ) { return GetStopSegmentAtRow( iNoteRow, false ); }
|
||||
/**
|
||||
* @brief Retrieve the StopSegment at the specified beat.
|
||||
* @param fBeat the beat that has a StopSegment.
|
||||
* @return the StopSegment in question.
|
||||
*/
|
||||
StopSegment& GetStopSegmentAtBeat( float fBeat ) { return GetStopSegmentAtRow( BeatToNoteRow(fBeat), false); }
|
||||
StopSegment* GetStopSegmentAtBeat( float fBeat ) { return GetStopSegmentAtRow( BeatToNoteRow(fBeat), false); }
|
||||
/**
|
||||
* @brief Retrieve the StopSegment at the specified row.
|
||||
* @param iNoteRow the row that has a StopSegment.
|
||||
* @param bDelay If true, this is actually a DelaySegment.
|
||||
* @return the StopSegment in question.
|
||||
*/
|
||||
StopSegment& GetStopSegmentAtRow( int iNoteRow, bool bDelay );
|
||||
StopSegment* GetStopSegmentAtRow( int iNoteRow, bool bDelay );
|
||||
/**
|
||||
* @brief Retrieve the StopSegment at the specified beat.
|
||||
* @param fBeat the beat that has a StopSegment.
|
||||
* @param bDelay If true, this is actually a DelaySegment.
|
||||
* @return the StopSegment in question.
|
||||
*/
|
||||
StopSegment& GetStopSegmentAtBeat( float fBeat, bool bDelay ) { return GetStopSegmentAtRow( BeatToNoteRow(fBeat), bDelay ); }
|
||||
StopSegment* GetStopSegmentAtBeat( float fBeat, bool bDelay ) { return GetStopSegmentAtRow( BeatToNoteRow(fBeat), bDelay ); }
|
||||
/**
|
||||
* @brief Retrieve the DelaySegment at the specified row.
|
||||
* @param iNoteRow the row that has a DelaySegment.
|
||||
* @return the DelaySegment in question.
|
||||
*/
|
||||
StopSegment& GetDelaySegmentAtRow( int iNoteRow ) { return GetStopSegmentAtRow( iNoteRow, true ); }
|
||||
StopSegment* GetDelaySegmentAtRow( int iNoteRow ) { return GetStopSegmentAtRow( iNoteRow, true ); }
|
||||
/**
|
||||
* @brief Retrieve the DelaySegment at the specified beat.
|
||||
* @param fBeat the beat that has a DelaySegment.
|
||||
* @return the DelaySegment in question.
|
||||
*/
|
||||
StopSegment& GetDelaySegmentAtBeat( float fBeat ) { return GetStopSegmentAtRow( BeatToNoteRow(fBeat), true); }
|
||||
/**
|
||||
* @brief Retrieve the index of the StopSegments at the specified row.
|
||||
* @param iNoteRow the row that has a StopSegment.
|
||||
* @return the StopSegment's index in question.
|
||||
*/
|
||||
int GetStopSegmentIndexAtRow( int iNoteRow ) const { return GetStopSegmentIndexAtRow( iNoteRow, false ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the StopSegments at the specified beat.
|
||||
* @param fBeat the beat that has a StopSegment.
|
||||
* @return the StopSegment's index in question.
|
||||
*/
|
||||
int GetStopSegmentIndexAtBeat( float fBeat ) const { return GetStopSegmentIndexAtRow( BeatToNoteRow(fBeat), false ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the StopSegments at the specified row.
|
||||
* @param iNoteRow the row that has a StopSegment.
|
||||
* @param bDelay If true, it's a Delay Segment. Otherwise, it's a StopSegment.
|
||||
* @return the StopSegment's index in question.
|
||||
*/
|
||||
int GetStopSegmentIndexAtRow( int iNoteRow, bool bDelay ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the StopSegments at the specified beat.
|
||||
* @param fBeat the beat that has a StopSegment.
|
||||
* @param bDelay If true, it's a Delay Segment. Otherwise, it's a StopSegment.
|
||||
* @return the StopSegment's index in question.
|
||||
*/
|
||||
int GetStopSegmentIndexAtBeat( float fBeat, bool bDelay ) const { return GetStopSegmentIndexAtRow( BeatToNoteRow(fBeat), bDelay ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the Delay Segments at the specified row.
|
||||
* @param iNoteRow the row that has a Delay Segment.
|
||||
* @return the StopSegment's index in question.
|
||||
*/
|
||||
int GetDelaySegmentIndexAtRow( int iNoteRow ) const { return GetStopSegmentIndexAtRow( iNoteRow, true ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the Delay Segments at the specified beat.
|
||||
* @param fBeat the beat that has a Delay Segment.
|
||||
* @return the StopSegment's index in question.
|
||||
*/
|
||||
int GetDelaySegmentIndexAtBeat( float fBeat ) const { return GetStopSegmentIndexAtRow( BeatToNoteRow(fBeat), true ); }
|
||||
/**
|
||||
* @brief Add the StopSegment to the TimingData.
|
||||
* @param seg the new StopSegment.
|
||||
*/
|
||||
void AddStopSegment( const StopSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a StopSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a StopSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextStopSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a StopSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a StopSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextStopSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextStopSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a StopSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a StopSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousStopSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a StopSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a StopSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousStopSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousStopSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a DelaySegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a DelaySegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextDelaySegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a DelaySegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a DelaySegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextDelaySegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextDelaySegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a DelaySegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a DelaySegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousDelaySegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a DelaySegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a DelaySegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousDelaySegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousDelaySegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
StopSegment* GetDelaySegmentAtBeat( float fBeat ) { return GetStopSegmentAtRow( BeatToNoteRow(fBeat), true); }
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Time Signature's numerator at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -415,68 +288,19 @@ public:
|
||||
* @param iNoteRow the row that has a TimeSignatureSegment.
|
||||
* @return the TimeSignatureSegment in question.
|
||||
*/
|
||||
TimeSignatureSegment& GetTimeSignatureSegmentAtRow( int iNoteRow );
|
||||
TimeSignatureSegment* GetTimeSignatureSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the TimeSignatureSegment at the specified beat.
|
||||
* @param fBeat the beat that has a TimeSignatureSegment.
|
||||
* @return the TimeSignatureSegment in question.
|
||||
*/
|
||||
TimeSignatureSegment& GetTimeSignatureSegmentAtBeat( float fBeat ) { return GetTimeSignatureSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the TimeSignatureSegments at the specified row.
|
||||
* @param iNoteRow the row that has a TimeSignatureSegment.
|
||||
* @return the TimeSignatureSegment's index in question.
|
||||
*/
|
||||
int GetTimeSignatureSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the TimeSignatureSegments at the specified beat.
|
||||
* @param fBeat the beat that has a TimeSignatureSegment.
|
||||
* @return the TimeSignatureSegment's index in question.
|
||||
*/
|
||||
int GetTimeSignatureSegmentIndexAtBeat( float fBeat ) const { return GetTimeSignatureSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Add the TimeSignatureSegment to the TimingData.
|
||||
* @param seg the new TimeSignatureSegment.
|
||||
*/
|
||||
void AddTimeSignatureSegment( const TimeSignatureSegment &seg );
|
||||
TimeSignatureSegment* GetTimeSignatureSegmentAtBeat( float fBeat ) { return GetTimeSignatureSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Determine the beat to warp to.
|
||||
* @param iRow The row you start on.
|
||||
* @return the beat you warp to.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a TimeSignatureSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a TimeSignatureSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextTimeSignatureSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a TimeSignatureSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a TimeSignatureSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextTimeSignatureSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextTimeSignatureSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a TimeSignatureSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a TimeSignatureSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousTimeSignatureSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a TimeSignatureSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a TimeSignatureSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousTimeSignatureSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousTimeSignatureSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
|
||||
float GetWarpAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Determine the beat to warp to.
|
||||
@@ -501,25 +325,13 @@ public:
|
||||
* @param iRow the row to focus on.
|
||||
* @return the WarpSegment in question.
|
||||
*/
|
||||
WarpSegment& GetWarpSegmentAtRow( int iRow );
|
||||
WarpSegment* GetWarpSegmentAtRow( int iRow );
|
||||
/**
|
||||
* @brief Retrieve the WarpSegment at the specified beat.
|
||||
* @param fBeat the beat to focus on.
|
||||
* @return the WarpSegment in question.
|
||||
*/
|
||||
WarpSegment& GetWarpSegmentAtBeat( float fBeat ) { return GetWarpSegmentAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the WarpSegment at the specified row.
|
||||
* @param iRow the row to focus on.
|
||||
* @return the index in question.
|
||||
*/
|
||||
int GetWarpSegmentIndexAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the WarpSegment at the specified beat.
|
||||
* @param fBeat the beat to focus on.
|
||||
* @return the index in question.
|
||||
*/
|
||||
int GetWarpSegmentIndexAtBeat( float fBeat ) const { return GetWarpSegmentIndexAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
WarpSegment* GetWarpSegmentAtBeat( float fBeat ) { return GetWarpSegmentAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
/**
|
||||
* @brief Checks if the row is inside a warp.
|
||||
* @param iRow the row to focus on.
|
||||
@@ -532,43 +344,6 @@ public:
|
||||
* @return true if the row is inside a warp, false otherwise.
|
||||
*/
|
||||
bool IsWarpAtBeat( float fBeat ) const { return IsWarpAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
/**
|
||||
* @brief Add the WarpSegment to the TimingData.
|
||||
* @param seg the new WarpSegment.
|
||||
*/
|
||||
void AddWarpSegment( const WarpSegment &seg );
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a WarpSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a WarpSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextWarpSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a WarpSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a WarpSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextWarpSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextWarpSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a WarpSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a WarpSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousWarpSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a WarpSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a WarpSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousWarpSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousWarpSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Tickcount at the given row.
|
||||
@@ -599,62 +374,13 @@ public:
|
||||
* @param iNoteRow the row that has a TickcountSegment.
|
||||
* @return the TickcountSegment in question.
|
||||
*/
|
||||
TickcountSegment& GetTickcountSegmentAtRow( int iNoteRow );
|
||||
TickcountSegment* GetTickcountSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the TickcountSegment at the specified beat.
|
||||
* @param fBeat the beat that has a TickcountSegment.
|
||||
* @return the TickcountSegment in question.
|
||||
*/
|
||||
TickcountSegment& GetTickcountSegmentAtBeat( float fBeat ) { return GetTickcountSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the TickcountSegments at the specified row.
|
||||
* @param iNoteRow the row that has a TickcountSegment.
|
||||
* @return the TickcountSegment's index in question.
|
||||
*/
|
||||
int GetTickcountSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the TickcountSegments at the specified beat.
|
||||
* @param fBeat the beat that has a TickcountSegment.
|
||||
* @return the TickcountSegment's index in question.
|
||||
*/
|
||||
int GetTickcountSegmentIndexAtBeat( float fBeat ) const { return GetTickcountSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Add the TickcountSegment to the TimingData.
|
||||
* @param seg the new TickcountSegment.
|
||||
*/
|
||||
void AddTickcountSegment( const TickcountSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a TickcountSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a TickcountSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextTickcountSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a TickcountSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a TickcountSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextTickcountSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextTickcountSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a TickcountSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a TickcountSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousTickcountSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a TickcountSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a TickcountSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousTickcountSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousTickcountSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
TickcountSegment* GetTickcountSegmentAtBeat( float fBeat ) { return GetTickcountSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Combo at the given row.
|
||||
@@ -735,62 +461,13 @@ public:
|
||||
* @param iNoteRow the row that has a ComboSegment.
|
||||
* @return the ComboSegment in question.
|
||||
*/
|
||||
ComboSegment& GetComboSegmentAtRow( int iNoteRow );
|
||||
ComboSegment* GetComboSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the ComboSegment at the specified beat.
|
||||
* @param fBeat the beat that has a ComboSegment.
|
||||
* @return the ComboSegment in question.
|
||||
*/
|
||||
ComboSegment& GetComboSegmentAtBeat( float fBeat ) { return GetComboSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the ComboSegments at the specified row.
|
||||
* @param iNoteRow the row that has a ComboSegment.
|
||||
* @return the ComboSegment's index in question.
|
||||
*/
|
||||
int GetComboSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the ComboSegments at the specified beat.
|
||||
* @param fBeat the beat that has a ComboSegment.
|
||||
* @return the ComboSegment's index in question.
|
||||
*/
|
||||
int GetComboSegmentIndexAtBeat( float fBeat ) const { return GetComboSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Add the ComboSegment to the TimingData.
|
||||
* @param seg the new ComboSegment.
|
||||
*/
|
||||
void AddComboSegment( const ComboSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a ComboSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a ComboSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextComboSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a ComboSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a ComboSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextComboSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextComboSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a ComboSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a ComboSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousComboSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a ComboSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a ComboSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousComboSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousComboSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
ComboSegment* GetComboSegmentAtBeat( float fBeat ) { return GetComboSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Label at the given row.
|
||||
@@ -821,70 +498,20 @@ public:
|
||||
* @param iNoteRow the row that has a LabelSegment.
|
||||
* @return the LabelSegment in question.
|
||||
*/
|
||||
LabelSegment& GetLabelSegmentAtRow( int iNoteRow );
|
||||
LabelSegment* GetLabelSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the LabelSegment at the specified beat.
|
||||
* @param fBeat the beat that has a LabelSegment.
|
||||
* @return the LabelSegment in question.
|
||||
*/
|
||||
LabelSegment& GetLabelSegmentAtBeat( float fBeat ) { return GetLabelSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the LabelSegments at the specified row.
|
||||
* @param iNoteRow the row that has a LabelSegment.
|
||||
* @return the LabelSegment's index in question.
|
||||
*/
|
||||
int GetLabelSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the LabelSegments at the specified beat.
|
||||
* @param fBeat the beat that has a LabelSegment.
|
||||
* @return the LabelSegment's index in question.
|
||||
*/
|
||||
int GetLabelSegmentIndexAtBeat( float fBeat ) const { return GetLabelSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Add the LabelSegment to the TimingData.
|
||||
* @param seg the new LabelSegment.
|
||||
*/
|
||||
void AddLabelSegment( const LabelSegment &seg );
|
||||
LabelSegment* GetLabelSegmentAtBeat( float fBeat ) { return GetLabelSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a LabelSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a LabelSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousLabelSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a LabelSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a LabelSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousLabelSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the requisite label already exists.
|
||||
* @param sLabel the label to check.
|
||||
* @return true if it exists, false otherwise. */
|
||||
bool DoesLabelExist( RString sLabel ) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a LabelSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a LabelSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextLabelSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a LabelSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a LabelSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextLabelSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Speed's percent at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -978,65 +605,16 @@ public:
|
||||
* @param iNoteRow the row that has a SpeedSegment.
|
||||
* @return the SpeedSegment in question.
|
||||
*/
|
||||
SpeedSegment& GetSpeedSegmentAtRow( int iNoteRow );
|
||||
SpeedSegment* GetSpeedSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the SpeedSegment at the specified beat.
|
||||
* @param fBeat the beat that has a SpeedSegment.
|
||||
* @return the SpeedSegment in question.
|
||||
*/
|
||||
SpeedSegment& GetSpeedSegmentAtBeat( float fBeat ) { return GetSpeedSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the SpeedSegments at the specified row.
|
||||
* @param iNoteRow the row that has a SpeedSegment.
|
||||
* @return the SpeedSegment's index in question.
|
||||
*/
|
||||
int GetSpeedSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the SpeedSegments at the specified beat.
|
||||
* @param fBeat the beat that has a SpeedSegment.
|
||||
* @return the SpeedSegment's index in question.
|
||||
*/
|
||||
int GetSpeedSegmentIndexAtBeat( float fBeat ) const { return GetSpeedSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
|
||||
/**
|
||||
* @brief Add the SpeedSegment to the TimingData.
|
||||
* @param seg the new SpeedSegment.
|
||||
*/
|
||||
void AddSpeedSegment( const SpeedSegment &seg );
|
||||
SpeedSegment* GetSpeedSegmentAtBeat( float fBeat ) { return GetSpeedSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
float GetDisplayedSpeedPercent( float fBeat, float fMusicSeconds ) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a SpeedSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a SpeedSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextSpeedSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a SpeedSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a SpeedSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextSpeedSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextSpeedSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a SpeedSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a SpeedSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousSpeedSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a SpeedSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a SpeedSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousSpeedSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousSpeedSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the scrolling factor at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -1068,64 +646,13 @@ public:
|
||||
* @param iNoteRow the row that has a ScrollSegment.
|
||||
* @return the ScrollSegment in question.
|
||||
*/
|
||||
ScrollSegment& GetScrollSegmentAtRow( int iNoteRow );
|
||||
ScrollSegment* GetScrollSegmentAtRow( int iNoteRow );
|
||||
/**
|
||||
* @brief Retrieve the ScrollSegment at the specified beat.
|
||||
* @param fBeat the beat that has a ScrollSegment.
|
||||
* @return the ScrollSegment in question.
|
||||
*/
|
||||
ScrollSegment& GetScrollSegmentAtBeat( float fBeat ) { return GetScrollSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Retrieve the index of the ScrollSegment at the specified row.
|
||||
* @param iNoteRow the row that has a ScrollSegment.
|
||||
* @return the ScrollSegment's index in question.
|
||||
*/
|
||||
int GetScrollSegmentIndexAtRow( int iNoteRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the ScrollSegment at the specified beat.
|
||||
* @param fBeat the beat that has a ScrollSegment.
|
||||
* @return the ScrollSegment's index in question.
|
||||
*/
|
||||
int GetScrollSegmentIndexAtBeat( float fBeat ) const { return GetScrollSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Add the ScrollSegment to the TimingData.
|
||||
* @param seg the new ScrollSegment.
|
||||
*/
|
||||
void AddScrollSegment( const ScrollSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a ScrollSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a ScrollSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextScrollSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a ScrollSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a ScrollSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextScrollSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextScrollSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a ScrollSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a ScrollSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousScrollSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a ScrollSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a ScrollSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousScrollSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousScrollSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
ScrollSegment* GetScrollSegmentAtBeat( float fBeat ) { return GetScrollSegmentAtRow( BeatToNoteRow(fBeat) ); }
|
||||
|
||||
/**
|
||||
* @brief Determine when the fakes end.
|
||||
@@ -1156,25 +683,13 @@ public:
|
||||
* @param iRow the row to focus on.
|
||||
* @return the FakeSegment in question.
|
||||
*/
|
||||
FakeSegment& GetFakeSegmentAtRow( int iRow );
|
||||
FakeSegment* GetFakeSegmentAtRow( int iRow );
|
||||
/**
|
||||
* @brief Retrieve the FakeSegment at the specified beat.
|
||||
* @param fBeat the beat to focus on.
|
||||
* @return the FakeSegment in question.
|
||||
*/
|
||||
FakeSegment& GetFakeSegmentAtBeat( float fBeat ) { return GetFakeSegmentAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
/**
|
||||
* @brief Retrieve the index of the FakeSegment at the specified row.
|
||||
* @param iRow the row to focus on.
|
||||
* @return the index in question.
|
||||
*/
|
||||
int GetFakeSegmentIndexAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the index of the FakeSegment at the specified beat.
|
||||
* @param fBeat the beat to focus on.
|
||||
* @return the index in question.
|
||||
*/
|
||||
int GetFakeSegmentIndexAtBeat( float fBeat ) const { return GetFakeSegmentIndexAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
FakeSegment* GetFakeSegmentAtBeat( float fBeat ) { return GetFakeSegmentAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
/**
|
||||
* @brief Checks if the row is inside a fake.
|
||||
* @param iRow the row to focus on.
|
||||
@@ -1187,43 +702,6 @@ public:
|
||||
* @return true if the row is inside a fake, false otherwise.
|
||||
*/
|
||||
bool IsFakeAtBeat( float fBeat ) const { return IsFakeAtRow( BeatToNoteRow( fBeat ) ); }
|
||||
/**
|
||||
* @brief Add the FakeSegment to the TimingData.
|
||||
* @param seg the new FakeSegment.
|
||||
*/
|
||||
void AddFakeSegment( const FakeSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next beat that contains a FakeSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the next beat with a FakeSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextFakeSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a FakeSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the next beat with a FakeSegment, or fBeat if there is none ahead.
|
||||
*/
|
||||
float GetNextFakeSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextFakeSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a FakeSegment.
|
||||
* @param iRow the present row.
|
||||
* @return the previous beat with a FakeSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousFakeSegmentBeatAtRow( int iRow ) const;
|
||||
/**
|
||||
* @brief Retrieve the previous beat that contains a FakeSegment.
|
||||
* @param fBeat the present beat.
|
||||
* @return the previous beat with a FakeSegment, or fBeat if there is none prior.
|
||||
*/
|
||||
float GetPreviousFakeSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousFakeSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Determine if this notes on this row can be judged.
|
||||
@@ -1303,36 +781,14 @@ public:
|
||||
*/
|
||||
bool operator==( const TimingData &other )
|
||||
{
|
||||
COMPARE( m_BPMSegments.size() );
|
||||
for( unsigned i=0; i<m_BPMSegments.size(); i++ )
|
||||
COMPARE( m_BPMSegments[i] );
|
||||
COMPARE( m_StopSegments.size() );
|
||||
for( unsigned i=0; i<m_StopSegments.size(); i++ )
|
||||
COMPARE( m_StopSegments[i] );
|
||||
COMPARE( m_WarpSegments.size() );
|
||||
for( unsigned i=0; i<m_WarpSegments.size(); i++ )
|
||||
COMPARE( m_WarpSegments[i] );
|
||||
COMPARE( m_vTimeSignatureSegments.size() );
|
||||
for( unsigned i=0; i<m_vTimeSignatureSegments.size(); i++)
|
||||
COMPARE( m_vTimeSignatureSegments[i] );
|
||||
COMPARE( m_TickcountSegments.size() );
|
||||
for( unsigned i=0; i<m_TickcountSegments.size(); i++ )
|
||||
COMPARE( m_TickcountSegments[i] );
|
||||
COMPARE( m_ComboSegments.size() );
|
||||
for( unsigned i=0; i<m_ComboSegments.size(); i++ )
|
||||
COMPARE( m_ComboSegments[i] );
|
||||
COMPARE( m_LabelSegments.size() );
|
||||
for( unsigned i=0; i<m_LabelSegments.size(); i++ )
|
||||
COMPARE( m_LabelSegments[i] );
|
||||
COMPARE( m_SpeedSegments.size() );
|
||||
for( unsigned i=0; i<m_SpeedSegments.size(); i++ )
|
||||
COMPARE( m_SpeedSegments[i] );
|
||||
COMPARE( m_ScrollSegments.size() );
|
||||
for( unsigned i=0; i<m_ScrollSegments.size(); i++ )
|
||||
COMPARE( m_ScrollSegments[i] );
|
||||
COMPARE( m_FakeSegments.size() );
|
||||
for( unsigned i=0; i<m_FakeSegments.size(); i++ )
|
||||
COMPARE( m_FakeSegments[i] );
|
||||
for (int i = 0; i < NUM_TimingSegmentType; i++)
|
||||
{
|
||||
COMPARE(allTimingSegments[i].size());
|
||||
for (unsigned j=0; j < allTimingSegments[i].size(); j++)
|
||||
{
|
||||
COMPARE(allTimingSegments[i][j]);
|
||||
}
|
||||
}
|
||||
COMPARE( m_fBeat0OffsetInSeconds );
|
||||
return true;
|
||||
}
|
||||
@@ -1361,45 +817,16 @@ public:
|
||||
*/
|
||||
RString m_sFile;
|
||||
// All of the following vectors must be sorted before gameplay.
|
||||
/**
|
||||
* @brief The collection of BPMSegments.
|
||||
*/
|
||||
vector<BPMSegment> m_BPMSegments;
|
||||
/**
|
||||
* @brief The collection of StopSegments & DelaySegments.
|
||||
*/
|
||||
vector<StopSegment> m_StopSegments;
|
||||
/**
|
||||
* @brief The collection of TimeSignatureSegments.
|
||||
*/
|
||||
vector<TimeSignatureSegment> m_vTimeSignatureSegments;
|
||||
/**
|
||||
* @brief The collection of WarpSegments.
|
||||
*/
|
||||
vector<WarpSegment> m_WarpSegments;
|
||||
/**
|
||||
* @brief The collection of TickcountSegments.
|
||||
*/
|
||||
vector<TickcountSegment> m_TickcountSegments;
|
||||
/**
|
||||
* @brief The collection of ComboSegments.
|
||||
*/
|
||||
vector<ComboSegment> m_ComboSegments;
|
||||
/**
|
||||
* @brief The collection of LabelSegments.
|
||||
*/
|
||||
vector<LabelSegment> m_LabelSegments;
|
||||
/** @brief The collection of SpeedSegments. */
|
||||
vector<SpeedSegment> m_SpeedSegments;
|
||||
/** @brief The collection of ScrollSegments. */
|
||||
vector<ScrollSegment> m_ScrollSegments;
|
||||
/** @brief The collection of FakeSegments. */
|
||||
vector<FakeSegment> m_FakeSegments;
|
||||
|
||||
|
||||
vector<TimingSegment *> allTimingSegments[NUM_TimingSegmentType];
|
||||
|
||||
/**
|
||||
* @brief The initial offset of a song.
|
||||
*/
|
||||
float m_fBeat0OffsetInSeconds;
|
||||
|
||||
vector<RString> ToVectorString(TimingSegmentType tst, bool isDelay = false, int dec = 6) const;
|
||||
};
|
||||
|
||||
#undef COMPARE
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
#include "global.h"
|
||||
#include "TimingSegments.h"
|
||||
#include "EnumHelper.h"
|
||||
|
||||
static const char *TimingSegmentTypeNames[] = {
|
||||
"BPM",
|
||||
"Stop/Delay", // TODO: separate when stops and delays are separate.
|
||||
"Time Sig",
|
||||
"Warp",
|
||||
"Label",
|
||||
"Tickcount",
|
||||
"Combo",
|
||||
"Speed",
|
||||
"Scroll",
|
||||
"Fake"
|
||||
};
|
||||
XToString( TimingSegmentType );
|
||||
|
||||
#define LTCOMPARE(x) if(this->x < other.x) return true; if(this->x > other.x) return false;
|
||||
|
||||
|
||||
+87
-3
@@ -18,9 +18,12 @@ enum TimingSegmentType
|
||||
SEGMENT_SPEED,
|
||||
SEGMENT_SCROLL,
|
||||
SEGMENT_FAKE,
|
||||
NUM_TimingSegmentTypes
|
||||
NUM_TimingSegmentType,
|
||||
TimingSegmentType_Invalid,
|
||||
};
|
||||
|
||||
const RString& TimingSegmentTypeToString( TimingSegmentType tst );
|
||||
|
||||
/**
|
||||
* @brief The base timing segment for all of the changing glory.
|
||||
*/
|
||||
@@ -74,7 +77,15 @@ struct TimingSegment
|
||||
* @return the starting beat. */
|
||||
float GetBeat() const;
|
||||
|
||||
virtual TimingSegmentType GetType() const = 0;
|
||||
virtual TimingSegmentType GetType() const
|
||||
{
|
||||
return TimingSegmentType_Invalid;
|
||||
}
|
||||
// TODO: Remove isDelay optional param and split Stops and Delays.
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
return FloatToString(this->GetBeat());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two DrivedSegments to see if one is less than the other.
|
||||
@@ -200,6 +211,13 @@ struct FakeSegment : public TimingSegment
|
||||
|
||||
TimingSegmentType GetType() const { return SEGMENT_FAKE; }
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
RString str = "%.0" + IntToString(dec)
|
||||
+ "f=%.0" + IntToString(dec) + "f";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetLength());
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief The number of beats the FakeSegment is alive for.
|
||||
@@ -254,6 +272,13 @@ struct WarpSegment : public TimingSegment
|
||||
|
||||
void Scale( int start, int length, int newLength );
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
RString str = "%.0" + IntToString(dec)
|
||||
+ "f=%.0" + IntToString(dec) + "f";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetLength());
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Compares two WarpSegments to see if one is less than the other.
|
||||
* @param other the other WarpSegment to compare to.
|
||||
@@ -320,6 +345,12 @@ struct TickcountSegment : public TimingSegment
|
||||
* @param i the tickcount. */
|
||||
void SetTicks(const int i);
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
const RString str = "%.0" + IntToString(dec) + "f=%i";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetTicks());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two TickcountSegments to see if one is less than the other.
|
||||
* @param other the other TickcountSegment to compare to.
|
||||
@@ -350,7 +381,7 @@ struct ComboSegment : public TimingSegment
|
||||
* It is best to override the values as soon as possible.
|
||||
*/
|
||||
ComboSegment() :
|
||||
TimingSegment(-1), combo(1) { }
|
||||
TimingSegment(-1), combo(1), missCombo(1) { }
|
||||
|
||||
ComboSegment(const ComboSegment &other) :
|
||||
TimingSegment(other.GetRow()),
|
||||
@@ -398,6 +429,17 @@ struct ComboSegment : public TimingSegment
|
||||
* @param i the miss combo. */
|
||||
void SetMissCombo(const int i);
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
RString str = "%.0" + IntToString(dec) + "f=%i";
|
||||
if (this->GetCombo() == this->GetMissCombo())
|
||||
{
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetCombo());
|
||||
}
|
||||
str += "=%i";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetCombo(), this->GetMissCombo());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two ComboSegments to see if one is less than the other.
|
||||
* @param other the other ComboSegment to compare to.
|
||||
@@ -456,6 +498,12 @@ struct LabelSegment : public TimingSegment
|
||||
* @param l the label. */
|
||||
void SetLabel(const RString l);
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
const RString str = "%.0" + IntToString(dec) + "f=%s";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetLabel().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if one is less than the other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
@@ -520,6 +568,13 @@ struct BPMSegment : public TimingSegment
|
||||
* @param l the label. */
|
||||
void SetBPS(const float newBPS);
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
const RString str = "%.0" + IntToString(dec)
|
||||
+ "f=%.0" + IntToString(dec) + "f";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetBPM());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two LabelSegments to see if one is less than the other.
|
||||
* @param other the other LabelSegment to compare to.
|
||||
@@ -598,6 +653,12 @@ struct TimeSignatureSegment : public TimingSegment
|
||||
* @param i the denominator. */
|
||||
void SetDen(const int i);
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
const RString str = "%.0" + IntToString(dec) + "f=%i=%i";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetNum(), this->GetDen());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the number of note rows per measure within the TimeSignatureSegment.
|
||||
*
|
||||
@@ -721,6 +782,15 @@ struct SpeedSegment : public TimingSegment
|
||||
void SetUnit(const int i);
|
||||
|
||||
void Scale( int start, int length, int newLength );
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
const RString str = "%.0" + IntToString(dec)
|
||||
+ "f=%.0" + IntToString(dec) + "f=%.0"
|
||||
+ IntToString(dec) + "f=%u";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetRatio(),
|
||||
this->GetLength(), this->GetUnit());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two SpeedSegments to see if one is less than the other.
|
||||
@@ -786,6 +856,13 @@ struct ScrollSegment : public TimingSegment
|
||||
* @param i the ratio. */
|
||||
void SetRatio(const float i);
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
const RString str = "%.0" + IntToString(dec)
|
||||
+ "f=%.0" + IntToString(dec) + "f";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetRatio());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two ScrollSegment to see if one is less than the other.
|
||||
* @param other the other ScrollSegment to compare to.
|
||||
@@ -861,6 +938,13 @@ struct StopSegment : public TimingSegment
|
||||
* @brief Set the behavior in this StopSegment.
|
||||
* @param i the behavior. */
|
||||
void SetDelay(const bool i);
|
||||
|
||||
virtual RString ToString(int dec) const
|
||||
{
|
||||
const RString str = "%.0" + IntToString(dec)
|
||||
+ "f=%.0" + IntToString(dec) + "f";
|
||||
return ssprintf(str.c_str(), this->GetBeat(), this->GetPause());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two StopSegments to see if one is less than the other.
|
||||
|
||||
+15
-10
@@ -268,18 +268,20 @@ static float GetArcadePoints( const Profile *pProfile )
|
||||
{
|
||||
switch(pm)
|
||||
{
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
fAP += pProfile->m_iNumSongsPlayedByPlayMode[pm];
|
||||
break;
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
{
|
||||
fAP += pProfile->m_iNumSongsPlayedByPlayMode[pm];
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return fAP;
|
||||
}
|
||||
|
||||
// TODO: Make this more flexible for games with many grade tiers. Lua-ize it? -Wolfman2000
|
||||
static float GetSongPoints( const Profile *pProfile )
|
||||
{
|
||||
float fSP = 0;
|
||||
@@ -297,6 +299,7 @@ static float GetSongPoints( const Profile *pProfile )
|
||||
case Grade_Tier07:/*D*/ fSP += 1* pProfile->m_iNumStagesPassedByGrade[g]; break;
|
||||
case Grade_Failed:
|
||||
case Grade_NoData:
|
||||
default:
|
||||
; // no points
|
||||
break;
|
||||
}
|
||||
@@ -306,11 +309,13 @@ static float GetSongPoints( const Profile *pProfile )
|
||||
{
|
||||
switch(pm)
|
||||
{
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
case PLAY_MODE_NONSTOP:
|
||||
case PLAY_MODE_ONI:
|
||||
case PLAY_MODE_ENDLESS:
|
||||
{
|
||||
fSP += pProfile->m_iNumSongsPlayedByPlayMode[pm];
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -347,6 +347,7 @@ RString InputHandler_MacOSX_HID::GetDeviceSpecificInputString( const DeviceInput
|
||||
case OTHER(48): return "non US backslash";
|
||||
case OTHER(49): return "application";
|
||||
case OTHER(50): return "prior";
|
||||
default: break;
|
||||
}
|
||||
#undef OTHER
|
||||
}
|
||||
@@ -365,6 +366,7 @@ RString InputHandler_MacOSX_HID::GetDeviceSpecificInputString( const DeviceInput
|
||||
case JOY_BUTTON_9: return "P2 MID";
|
||||
case JOY_BUTTON_10: return "P2 DL";
|
||||
case JOY_BUTTON_11: return "P2 DR";
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
|
||||
virtual void SetText( RString str ) = 0;
|
||||
virtual void SetIcon( const RageSurface *pIcon ) { }
|
||||
virtual void SetSplash( const RString sPath ) { }
|
||||
virtual void SetProgress( const int progress ) { m_progress=progress; }
|
||||
virtual void SetTotalWork( const int totalWork ) { m_totalWork=totalWork; }
|
||||
virtual void SetIndeterminate( bool indeterminate ) { m_indeterminate=indeterminate; }
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
RString Init();
|
||||
~LoadingWindow_Gtk();
|
||||
void SetText( RString str );
|
||||
void SetSplash( const RString str ) {}
|
||||
void SetProgress( const int progress );
|
||||
void SetTotalWork( const int totalWork );
|
||||
void SetIndeterminate( bool indeterminate );
|
||||
|
||||
@@ -9,6 +9,7 @@ public:
|
||||
LoadingWindow_MacOSX();
|
||||
~LoadingWindow_MacOSX();
|
||||
void SetText( RString str );
|
||||
void SetSplash( const RString path ) {}
|
||||
void SetProgress( const int progress );
|
||||
void SetTotalWork( const int totalWork );
|
||||
void SetIndeterminate( bool indeterminate );
|
||||
|
||||
@@ -7,6 +7,7 @@ class LoadingWindow_Null: public LoadingWindow
|
||||
{
|
||||
public:
|
||||
void SetText( RString str ) { }
|
||||
void SetSplash( const RString str ) { }
|
||||
};
|
||||
#define USE_LOADING_WINDOW_NULL
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ static HBITMAP g_hBitmap = NULL;
|
||||
|
||||
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
|
||||
/* Load a RageSurface into a GDI surface. */
|
||||
// Load a RageSurface into a GDI surface.
|
||||
static HBITMAP LoadWin32Surface( RageSurface *&s )
|
||||
{
|
||||
RageSurfaceUtils::ConvertSurface( s, s->w, s->h, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0 );
|
||||
@@ -37,14 +36,14 @@ static HBITMAP LoadWin32Surface( RageSurface *&s )
|
||||
HDC BitmapDC = CreateCompatibleDC( hScreen );
|
||||
SelectObject( BitmapDC, bitmap );
|
||||
|
||||
/* This is silly, but simple. We only do this once, on a small image. */
|
||||
// This is silly, but simple. We only do this once, on a small image.
|
||||
for( int y = 0; y < s->h; ++y )
|
||||
{
|
||||
unsigned const char *line = ((unsigned char *) s->pixels) + (y * s->pitch);
|
||||
for( int x = 0; x < s->w; ++x )
|
||||
{
|
||||
unsigned const char *data = line + (x*s->format->BytesPerPixel);
|
||||
|
||||
|
||||
SetPixelV( BitmapDC, x, y, RGB( data[3], data[2], data[1] ) );
|
||||
}
|
||||
}
|
||||
@@ -64,7 +63,7 @@ static HBITMAP LoadWin32Surface( RString sFile, HWND hWnd )
|
||||
if( pSurface == NULL )
|
||||
return NULL;
|
||||
|
||||
/* Resize the splash image to fit the dialog. Stretch to fit horizontally,
|
||||
/* Resize the splash image to fit the dialog. Stretch to fit horizontally,
|
||||
* maintaining aspect ratio. */
|
||||
{
|
||||
RECT r;
|
||||
@@ -84,7 +83,6 @@ static HBITMAP LoadWin32Surface( RString sFile, HWND hWnd )
|
||||
|
||||
INT_PTR CALLBACK LoadingWindow_Win32::DlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
|
||||
LoadingWindow_Win32 *self;
|
||||
|
||||
if(msg==WM_INITDIALOG) {
|
||||
@@ -171,7 +169,7 @@ INT_PTR CALLBACK LoadingWindow_Win32::DlgProc( HWND hWnd, UINT msg, WPARAM wPara
|
||||
|
||||
void LoadingWindow_Win32::SetIcon( const RageSurface *pIcon )
|
||||
{
|
||||
if( m_hIcon != NULL )
|
||||
if( g_hBitmap != NULL )
|
||||
DestroyIcon( m_hIcon );
|
||||
|
||||
m_hIcon = IconFromSurface( pIcon );
|
||||
@@ -179,6 +177,26 @@ void LoadingWindow_Win32::SetIcon( const RageSurface *pIcon )
|
||||
SetClassLong( hwnd, GCL_HICON, (LONG) m_hIcon );
|
||||
}
|
||||
|
||||
void LoadingWindow_Win32::SetSplash( const RString sPath )
|
||||
{
|
||||
if( g_hBitmap != NULL )
|
||||
{
|
||||
DeleteObject( g_hBitmap );
|
||||
g_hBitmap = NULL;
|
||||
}
|
||||
|
||||
g_hBitmap = LoadWin32Surface( sPath, hwnd );
|
||||
if( g_hBitmap != NULL )
|
||||
{
|
||||
SendDlgItemMessage(
|
||||
hwnd, IDC_SPLASH,
|
||||
STM_SETIMAGE,
|
||||
(WPARAM) IMAGE_BITMAP,
|
||||
(LPARAM) (HANDLE) g_hBitmap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LoadingWindow_Win32::LoadingWindow_Win32()
|
||||
{
|
||||
|
||||
@@ -194,7 +212,7 @@ LoadingWindow_Win32::LoadingWindow_Win32()
|
||||
#endif
|
||||
|
||||
m_hIcon = NULL;
|
||||
|
||||
|
||||
runMessageLoop=true;
|
||||
|
||||
guiReadyEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
|
||||
void SetText( RString sText );
|
||||
void SetIcon( const RageSurface *pIcon );
|
||||
void SetSplash( const RString sPath );
|
||||
void SetProgress( const int progress );
|
||||
void SetTotalWork( const int totalWork );
|
||||
void SetIndeterminate( bool indeterminate );
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -47,11 +49,11 @@ EXSTYLE WS_EX_APPWINDOW
|
||||
CAPTION "Stepmania"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
CTEXT "line1",IDC_STATIC_MESSAGE1,0,67,310,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CTEXT "line2",IDC_STATIC_MESSAGE2,0,76,310,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CTEXT "line3",IDC_STATIC_MESSAGE3,0,84,310,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CTEXT "line1",IDC_STATIC_MESSAGE1,7,43,303,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CTEXT "line2",IDC_STATIC_MESSAGE2,7,52,303,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CTEXT "line3",IDC_STATIC_MESSAGE3,7,61,303,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CONTROL "",IDC_SPLASH,"Static",SS_BITMAP,0,0,310,25
|
||||
CONTROL "",IDC_PROGRESS,"msctls_progress32",0x0,7,51,298,14
|
||||
CONTROL "",IDC_PROGRESS,"msctls_progress32",0x0,7,73,303,14
|
||||
END
|
||||
|
||||
IDD_DISASM_CRASH DIALOGEX 0, 0, 332, 114
|
||||
@@ -103,7 +105,7 @@ END
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_LOADING_DIALOG, DIALOG
|
||||
BEGIN
|
||||
@@ -213,7 +215,7 @@ BEGIN
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user