Merge with default
This commit is contained in:
@@ -91,6 +91,19 @@ bool AttackArray::ContainsTransformOrTurn() const
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<RString> AttackArray::ToVectorString() const
|
||||
{
|
||||
vector<RString> ret;
|
||||
FOREACH_CONST( Attack, *this, a )
|
||||
{
|
||||
ret.push_back(ssprintf("TIME=%f:LEN=%f:MODS=%s",
|
||||
a->fStartSecond,
|
||||
a->fSecsRemaining,
|
||||
a->sModifiers.c_str()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
|
||||
@@ -71,6 +71,11 @@ struct AttackArray : public vector<Attack>
|
||||
* @brief Determine if the list of attacks contains a transform or turn mod.
|
||||
* @return true if it does, or false otherwise. */
|
||||
bool ContainsTransformOrTurn() const;
|
||||
|
||||
/**
|
||||
* @brief Return a string representation used for simfiles.
|
||||
* @return the string representation. */
|
||||
vector<RString> ToVectorString() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1045,6 +1045,22 @@ void NoteField::DrawPrimitives()
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AttackArray &attacks = GAMESTATE->m_bIsUsingStepTiming ?
|
||||
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks :
|
||||
GAMESTATE->m_pCurSong->m_Attacks;
|
||||
FOREACH_CONST(Attack, attacks, a)
|
||||
{
|
||||
float fBeat = timing.GetBeatFromElapsedTime(a->fStartSecond);
|
||||
if (BeatToNoteRow(fBeat) >= iFirstRowToDraw &&
|
||||
BeatToNoteRow(fBeat) <= iLastRowToDraw &&
|
||||
IS_ON_SCREEN(fBeat))
|
||||
{
|
||||
this->DrawAttackText(fBeat, *a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !GAMESTATE->m_bIsUsingStepTiming )
|
||||
{
|
||||
|
||||
+17
-1
@@ -334,7 +334,23 @@ static inline float ToBeat(int row) { return NoteRowToBeat(row); }
|
||||
*/
|
||||
static inline float ToBeat(float beat) { return beat; }
|
||||
|
||||
|
||||
/**
|
||||
* @brief Scales the position.
|
||||
* @param T start - the starting row of the scaling region
|
||||
* @param T length - the length of the scaling region
|
||||
* @param T newLength - the new length of the scaling region
|
||||
* @param T position - the position to scale
|
||||
* @return T the scaled position
|
||||
*/
|
||||
template<typename T>
|
||||
inline T ScalePosition( T start, T length, T newLength, T position )
|
||||
{
|
||||
if( position < start )
|
||||
return position;
|
||||
if( position >= start + length )
|
||||
return position - length + newLength;
|
||||
return start + (position - start) * newLength / length;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+18
-12
@@ -10,7 +10,6 @@
|
||||
#include "Song.h"
|
||||
#include "SongManager.h"
|
||||
#include "Steps.h"
|
||||
#include "Attack.h"
|
||||
#include "PrefsManager.h"
|
||||
|
||||
void SMLoader::SetSongTitle(const RString & title)
|
||||
@@ -143,26 +142,31 @@ void SMLoader::ProcessBGChanges( Song &out, const RString &sValueName, const RSt
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::ProcessAttacks( Song &out, MsdFile::value_t sParams )
|
||||
void SMLoader::ProcessAttackString( vector<RString> & attacks, MsdFile::value_t params )
|
||||
{
|
||||
for( unsigned s=1; s < params.params.size(); ++s )
|
||||
{
|
||||
RString tmp = params[s];
|
||||
Trim(tmp);
|
||||
attacks.push_back( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::ProcessAttacks( AttackArray &attacks, MsdFile::value_t params )
|
||||
{
|
||||
// Build the RString vector here so we can write it to file again later
|
||||
for( unsigned s=1; s < sParams.params.size(); ++s )
|
||||
out.m_sAttackString.push_back( sParams[s] );
|
||||
|
||||
Attack attack;
|
||||
float end = -9999;
|
||||
|
||||
for( unsigned j=1; j < sParams.params.size(); ++j )
|
||||
for( unsigned j=1; j < params.params.size(); ++j )
|
||||
{
|
||||
vector<RString> sBits;
|
||||
split( sParams[j], "=", sBits, false );
|
||||
split( params[j], "=", sBits, false );
|
||||
|
||||
// Need an identifer and a value for this to work
|
||||
if( sBits.size() < 2 )
|
||||
continue;
|
||||
|
||||
TrimLeft( sBits[0] );
|
||||
TrimRight( sBits[0] );
|
||||
Trim( sBits[0] );
|
||||
|
||||
if( !sBits[0].CompareNoCase("TIME") )
|
||||
attack.fStartSecond = strtof( sBits[1], NULL );
|
||||
@@ -172,6 +176,7 @@ void SMLoader::ProcessAttacks( Song &out, MsdFile::value_t sParams )
|
||||
end = strtof( sBits[1], NULL );
|
||||
else if( !sBits[0].CompareNoCase("MODS") )
|
||||
{
|
||||
Trim(sBits[1]);
|
||||
attack.sModifiers = sBits[1];
|
||||
|
||||
if( end != -9999 )
|
||||
@@ -183,7 +188,7 @@ void SMLoader::ProcessAttacks( Song &out, MsdFile::value_t sParams )
|
||||
if( attack.fSecsRemaining < 0.0f )
|
||||
attack.fSecsRemaining = 0.0f;
|
||||
|
||||
out.m_Attacks.push_back( attack );
|
||||
attacks.push_back( attack );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -913,7 +918,8 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
|
||||
// Attacks loaded from file
|
||||
else if( sValueName=="ATTACKS" )
|
||||
{
|
||||
ProcessAttacks( out, sParams );
|
||||
ProcessAttackString(out.m_sAttackString, sParams);
|
||||
ProcessAttacks(out.m_Attacks, sParams);
|
||||
}
|
||||
|
||||
else if( sValueName=="NOTES" || sValueName=="NOTES2" )
|
||||
|
||||
+13
-1
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "BackgroundUtil.h"
|
||||
#include "Attack.h"
|
||||
#include "MsdFile.h" // we require the struct from here.
|
||||
|
||||
class Song;
|
||||
@@ -133,7 +134,18 @@ struct SMLoader
|
||||
|
||||
virtual void ProcessBGChanges( Song &out, const RString &sValueName,
|
||||
const RString &sPath, const RString &sParam );
|
||||
void ProcessAttacks( Song &out, MsdFile::value_t sParams );
|
||||
|
||||
/**
|
||||
* @brief Put the attacks in the attacks string.
|
||||
* @param attacks the attack string.
|
||||
* @param params the params from the simfile. */
|
||||
virtual void ProcessAttackString(vector<RString> &attacks, MsdFile::value_t params);
|
||||
|
||||
/**
|
||||
* @brief Put the attacks in the attacks array.
|
||||
* @param attacks the attacks array.
|
||||
* @param params the params from the simfile. */
|
||||
void ProcessAttacks( AttackArray &attacks, MsdFile::value_t params );
|
||||
void ProcessInstrumentTracks( Song &out, const RString &sParam );
|
||||
|
||||
/**
|
||||
|
||||
@@ -432,7 +432,8 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
// Attacks loaded from file
|
||||
else if( sValueName=="ATTACKS" )
|
||||
{
|
||||
SMLoader::ProcessAttacks( out, sParams );
|
||||
ProcessAttackString(out.m_sAttackString, sParams);
|
||||
ProcessAttacks(out.m_Attacks, sParams);
|
||||
}
|
||||
|
||||
else if( sValueName=="NOTES" || sValueName=="NOTES2" )
|
||||
|
||||
@@ -344,7 +344,8 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
// Attacks loaded from file
|
||||
else if( sValueName=="ATTACKS" )
|
||||
{
|
||||
SMLoader::ProcessAttacks( out, sParams );
|
||||
ProcessAttackString(out.m_sAttackString, sParams);
|
||||
ProcessAttacks(out.m_Attacks, sParams);
|
||||
}
|
||||
|
||||
else if( sValueName=="OFFSET" )
|
||||
@@ -559,7 +560,8 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
|
||||
|
||||
else if( sValueName=="ATTACKS" )
|
||||
{
|
||||
// Step Attacks aren't in yet.
|
||||
ProcessAttackString(pNewNotes->m_sAttackString, sParams);
|
||||
ProcessAttacks(pNewNotes->m_Attacks, sParams);
|
||||
}
|
||||
|
||||
else if( sValueName=="OFFSET" )
|
||||
|
||||
@@ -26,6 +26,8 @@ const float VERSION_RADAR_FAKE = 0.53f;
|
||||
const float VERSION_WARP_SEGMENT = 0.56f;
|
||||
/** @brief The version that formally introduced Split Timing. */
|
||||
const float VERSION_SPLIT_TIMING = 0.7f;
|
||||
/** @brief The version that moved the step's Offset higher up. */
|
||||
const float VERSION_OFFSET_BEFORE_ATTACK = 0.72f;
|
||||
|
||||
/**
|
||||
* @brief The SSCLoader handles all of the parsing needed for .ssc files.
|
||||
|
||||
+13
-4
@@ -317,12 +317,21 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
|
||||
lines.push_back( ssprintf( "#RADARVALUES:%s;", join(",",asRadarValues).c_str() ) );
|
||||
|
||||
lines.push_back( ssprintf( "#CREDIT:%s;", SmEscape(in.GetCredit()).c_str() ) );
|
||||
|
||||
lines.push_back( ssprintf( "#OFFSET:%.6f;", in.m_Timing.m_fBeat0OffsetInSeconds ) );
|
||||
|
||||
GetTimingTags( lines, in.m_Timing );
|
||||
|
||||
// For now, attacks are NOT in use for the step.
|
||||
lines.push_back( "#ATTACKS:;" );
|
||||
lines.push_back( ssprintf( "#OFFSET:%.6f;", in.m_Timing.m_fBeat0OffsetInSeconds ) );
|
||||
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()));
|
||||
|
||||
RString sNoteData;
|
||||
in.GetSMNoteData( sNoteData );
|
||||
|
||||
+4
-6
@@ -960,8 +960,10 @@ void Player::Update( float fDeltaTime )
|
||||
UpdateJudgedRows();
|
||||
|
||||
// Check for TapNote misses
|
||||
UpdateTapNotesMissedOlderThan( GetMaxStepDistanceSeconds() );
|
||||
|
||||
if (!GAMESTATE->m_bInStepEditor)
|
||||
{
|
||||
UpdateTapNotesMissedOlderThan( GetMaxStepDistanceSeconds() );
|
||||
}
|
||||
// process transforms that are waiting to be applied
|
||||
ApplyWaitingTransforms();
|
||||
}
|
||||
@@ -2973,10 +2975,6 @@ void Player::RandomizeNotes( int iNoteRow )
|
||||
|
||||
const int iSwapWith = RandomInt( iNumOfTracks );
|
||||
|
||||
// Make sure we're not swapping with ourselves.
|
||||
if( t == iSwapWith )
|
||||
continue;
|
||||
|
||||
// Make sure this is empty.
|
||||
if( m_NoteData.FindTapNote(iSwapWith, iNewNoteRow) != m_NoteData.end(iSwapWith) )
|
||||
continue;
|
||||
|
||||
+25
-6
@@ -37,7 +37,7 @@ void PlayerOptions::Init()
|
||||
m_fBlind = 0; m_SpeedfBlind = 1.0f;
|
||||
m_fCover = 0; m_SpeedfCover = 1.0f;
|
||||
m_fRandAttack = 0; m_SpeedfRandAttack = 1.0f;
|
||||
m_fSongAttack = 0; m_SpeedfSongAttack = 1.0f;
|
||||
m_fNoAttack = 0; m_SpeedfNoAttack = 1.0f;
|
||||
m_fPlayerAutoPlay = 0; m_SpeedfPlayerAutoPlay = 1.0f;
|
||||
m_bSetTiltOrSkew = false;
|
||||
m_fPerspectiveTilt = 0; m_SpeedfPerspectiveTilt = 1.0f;
|
||||
@@ -73,7 +73,7 @@ void PlayerOptions::Approach( const PlayerOptions& other, float fDeltaSeconds )
|
||||
APPROACH( fBlind );
|
||||
APPROACH( fCover );
|
||||
APPROACH( fRandAttack );
|
||||
APPROACH( fSongAttack );
|
||||
APPROACH( fNoAttack );
|
||||
APPROACH( fPlayerAutoPlay );
|
||||
APPROACH( fPerspectiveTilt );
|
||||
APPROACH( fSkew );
|
||||
@@ -180,7 +180,7 @@ void PlayerOptions::GetMods( vector<RString> &AddTo, bool bForceNoteSkin ) const
|
||||
AddPart( AddTo, m_fCover, "Cover" );
|
||||
|
||||
AddPart( AddTo, m_fRandAttack, "RandomAttacks" );
|
||||
AddPart( AddTo, m_fSongAttack, "SongAttacks" );
|
||||
AddPart( AddTo, m_fNoAttack, "NoAttacks" );
|
||||
AddPart( AddTo, m_fPlayerAutoPlay, "PlayerAutoPlay" );
|
||||
|
||||
AddPart( AddTo, m_fPassmark, "Passmark" );
|
||||
@@ -417,7 +417,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut
|
||||
else if( sBit == "blind" ) SET_FLOAT( fBlind )
|
||||
else if( sBit == "cover" ) SET_FLOAT( fCover )
|
||||
else if( sBit == "randomattacks" ) SET_FLOAT( fRandAttack )
|
||||
else if( sBit == "songattacks" ) SET_FLOAT( fSongAttack )
|
||||
else if( sBit == "noattacks" ) SET_FLOAT( fNoAttack )
|
||||
else if( sBit == "playerautoplay" ) SET_FLOAT( fPlayerAutoPlay )
|
||||
else if( sBit == "passmark" ) SET_FLOAT( fPassmark )
|
||||
else if( sBit == "overhead" ) { m_bSetTiltOrSkew = true; m_fSkew = 0; m_fPerspectiveTilt = 0; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed; }
|
||||
@@ -657,7 +657,7 @@ bool PlayerOptions::operator==( const PlayerOptions &other ) const
|
||||
COMPARE(m_fBlind);
|
||||
COMPARE(m_fCover);
|
||||
COMPARE(m_fRandAttack);
|
||||
COMPARE(m_fSongAttack);
|
||||
COMPARE(m_fNoAttack);
|
||||
COMPARE(m_fPlayerAutoPlay);
|
||||
COMPARE(m_fPerspectiveTilt);
|
||||
COMPARE(m_fSkew);
|
||||
@@ -712,6 +712,10 @@ bool PlayerOptions::IsEasierForSongAndSteps( Song* pSong, Steps* pSteps, PlayerN
|
||||
// This makes songs with sparse notes easier.
|
||||
if( m_bTransforms[TRANSFORM_ECHO] ) return true;
|
||||
|
||||
// Removing attacks is easier in general.
|
||||
if (m_fNoAttack || (!m_fRandAttack && pSteps->HasAttacks()))
|
||||
return true;
|
||||
|
||||
if( m_fCover ) return true;
|
||||
if( m_fPlayerAutoPlay ) return true;
|
||||
return false;
|
||||
@@ -957,7 +961,20 @@ public:
|
||||
DEFINE_METHOD( GetBlind, m_fBlind )
|
||||
DEFINE_METHOD( GetCover, m_fCover )
|
||||
DEFINE_METHOD( GetRandomAttacks, m_fRandAttack )
|
||||
DEFINE_METHOD( GetSongAttacks, m_fSongAttack )
|
||||
|
||||
static int GetStepAttacks( T *p, lua_State *L )
|
||||
{
|
||||
lua_pushnumber(L,
|
||||
(p->m_fNoAttack > 0 || p->m_fRandAttack > 0 ? 0 : 1 ));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This one is deprecated.
|
||||
static int GetSongAttacks( T *p, lua_State *L )
|
||||
{
|
||||
return GetStepAttacks(p, L);
|
||||
}
|
||||
DEFINE_METHOD( GetNoAttacks, m_fNoAttack )
|
||||
DEFINE_METHOD( GetSkew, m_fSkew )
|
||||
DEFINE_METHOD( GetPassmark, m_fPassmark )
|
||||
DEFINE_METHOD( GetRandomSpeed, m_fRandomSpeed )
|
||||
@@ -984,6 +1001,8 @@ public:
|
||||
// SetSkew
|
||||
ADD_METHOD( GetSongAttacks );
|
||||
// SetSongAttacks
|
||||
ADD_METHOD( GetStepAttacks );
|
||||
ADD_METHOD( GetNoAttacks );
|
||||
ADD_METHOD( GetCMod );
|
||||
ADD_METHOD( GetXMod );
|
||||
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ public:
|
||||
m_fBlind(0), m_SpeedfBlind(1.0f),
|
||||
m_fCover(0), m_SpeedfCover(1.0f),
|
||||
m_fRandAttack(0), m_SpeedfRandAttack(1.0f),
|
||||
m_fSongAttack(0), m_SpeedfSongAttack(1.0f),
|
||||
m_fNoAttack(0), m_SpeedfNoAttack(1.0f),
|
||||
m_fPlayerAutoPlay(0), m_SpeedfPlayerAutoPlay(1.0f),
|
||||
m_bSetTiltOrSkew(false),
|
||||
m_fPerspectiveTilt(0), m_SpeedfPerspectiveTilt(1.0f),
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
float m_fBlind, m_SpeedfBlind;
|
||||
float m_fCover, m_SpeedfCover; // hide the background per-player--can't think of a good name
|
||||
float m_fRandAttack, m_SpeedfRandAttack;
|
||||
float m_fSongAttack, m_SpeedfSongAttack;
|
||||
float m_fNoAttack, m_SpeedfNoAttack;
|
||||
float m_fPlayerAutoPlay, m_SpeedfPlayerAutoPlay;
|
||||
bool m_bSetTiltOrSkew; // true if the tilt or skew was set by FromString
|
||||
float m_fPerspectiveTilt, m_SpeedfPerspectiveTilt; // -1 = near, 0 = overhead, +1 = space
|
||||
|
||||
+1
-1
@@ -434,7 +434,7 @@ RString ConvertI64FormatString( const RString &sStr )
|
||||
RString ConvertI64FormatString( const RString &sStr ) { return sStr; }
|
||||
#endif
|
||||
|
||||
/* ISO-639-1 codes: http://www.loc.gov/standards/iso639-2/langcodes.html
|
||||
/* ISO-639-1 codes: http://www.loc.gov/standards/iso639-2/php/code_list.php
|
||||
* native forms: http://people.w3.org/rishida/names/languages.html
|
||||
* We don't use 3-letter codes, so we don't bother supporting them. */
|
||||
static const LanguageInfo g_langs[] =
|
||||
|
||||
+326
-29
@@ -68,6 +68,8 @@ AutoScreenMessage( SM_BackFromSongInformation );
|
||||
AutoScreenMessage( SM_BackFromBGChange );
|
||||
AutoScreenMessage( SM_BackFromInsertTapAttack );
|
||||
AutoScreenMessage( SM_BackFromInsertTapAttackPlayerOptions );
|
||||
AutoScreenMessage( SM_BackFromInsertStepAttack );
|
||||
AutoScreenMessage( SM_BackFromInsertStepAttackPlayerOptions );
|
||||
AutoScreenMessage( SM_BackFromInsertCourseAttack );
|
||||
AutoScreenMessage( SM_BackFromInsertCourseAttackPlayerOptions );
|
||||
AutoScreenMessage( SM_BackFromCourseModeMenu );
|
||||
@@ -144,13 +146,13 @@ void ScreenEdit::InitEditMappings()
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_PERIOD);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_COMMA);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_PERIOD);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SEGMENT_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_PERIOD);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SEGMENT_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SEGMENT_NEXT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_COMMA);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SEGMENT_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_COMMA);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SEGMENT_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SEGMENT_PREV][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT);
|
||||
@@ -244,8 +246,8 @@ void ScreenEdit::InitEditMappings()
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cb);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_COURSE_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cc);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_COURSE_ATTACK_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cv);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_ADD_STEP_MODS][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cc);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_STEP_ATTACK_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cv);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_INSERT_SHIFT_PAUSES][0] = DeviceInput(DEVICE_KEYBOARD, KEY_INSERT);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_INSERT_SHIFT_PAUSES][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
@@ -275,6 +277,14 @@ void ScreenEdit::InitEditMappings()
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_CYCLE_TAP_LEFT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cn);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_CYCLE_TAP_RIGHT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cm);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_CYCLE_SEGMENT_LEFT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cn);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_CYCLE_SEGMENT_LEFT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_CYCLE_SEGMENT_LEFT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_CYCLE_SEGMENT_RIGHT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cm);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_CYCLE_SEGMENT_RIGHT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_CYCLE_SEGMENT_RIGHT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
|
||||
m_EditMappingsDeviceInput.button [EDIT_BUTTON_SCROLL_SPEED_UP][0] = DeviceInput(DEVICE_KEYBOARD, KEY_UP);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SCROLL_SPEED_UP][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
|
||||
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SCROLL_SPEED_UP][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
|
||||
@@ -569,6 +579,8 @@ static MenuDef g_AreaMenu(
|
||||
MenuRowDef( ScreenEdit::shift_pauses_backward, "Shift all timing changes up", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::convert_pause_to_beat, "Convert pause to beats", true,
|
||||
EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::convert_delay_to_beat, "Convert delay to beats", true,
|
||||
EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::undo, "Undo", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::clear_clipboard, "Clear clipboard", true,
|
||||
EditMode_Practice, true, true, 0, NULL )
|
||||
@@ -631,6 +643,8 @@ static MenuDef g_TimingDataInformation(
|
||||
MenuRowDef( ScreenEdit::speed_mode, "Edit speed (mode)", true, EditMode_Full, true, true, 0, "Beats", "Seconds" ),
|
||||
MenuRowDef( ScreenEdit::scroll, "Edit scrolling factor", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::fake, "Edit fake", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::copy_timing, "Copy timing data", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::paste_timing, "Paste timing data", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::erase_step_timing, "Erase step timing", true, EditMode_Full, true, true, 0, NULL )
|
||||
);
|
||||
|
||||
@@ -768,6 +782,8 @@ void ScreenEdit::Init()
|
||||
ScreenWithMenuElements::Init();
|
||||
|
||||
InitEditMappings();
|
||||
|
||||
currentCycleSegment = "label";
|
||||
|
||||
// save the originals for reverting later
|
||||
CopyToLastSave();
|
||||
@@ -859,6 +875,8 @@ void ScreenEdit::Init()
|
||||
m_bRemoveNoteButtonDown = false;
|
||||
|
||||
m_Clipboard.SetNumTracks( m_NoteDataEdit.GetNumTracks() );
|
||||
|
||||
clipboardTiming = GAMESTATE->m_pCurSong->m_SongTiming; // always have a backup.
|
||||
|
||||
m_bHasUndo = false;
|
||||
m_Undo.SetNumTracks( m_NoteDataEdit.GetNumTracks() );
|
||||
@@ -1096,9 +1114,11 @@ static LocalizedString DIFFICULTY("ScreenEdit", "Difficulty");
|
||||
static LocalizedString ROUTINE_PLAYER("ScreenEdit", "Routine Player");
|
||||
static LocalizedString DESCRIPTION("ScreenEdit", "Description");
|
||||
static LocalizedString CHART_STYLE("ScreenEdit", "Chart Style");
|
||||
static LocalizedString STEP_AUTHOR("ScreenEdit", "Step Author");
|
||||
static LocalizedString MAIN_TITLE("ScreenEdit", "Main title");
|
||||
static LocalizedString SUBTITLE("ScreenEdit", "Subtitle");
|
||||
static LocalizedString TAP_NOTE_TYPE("ScreenEdit", "Tap Note");
|
||||
static LocalizedString SEGMENT_TYPE("ScreenEdit", "Segment");
|
||||
static LocalizedString TAP_STEPS("ScreenEdit", "Tap Steps");
|
||||
static LocalizedString JUMPS("ScreenEdit", "Jumps");
|
||||
static LocalizedString HANDS("ScreenEdit", "Hands");
|
||||
@@ -1124,9 +1144,11 @@ static ThemeMetric<RString> DIFFICULTY_FORMAT("ScreenEdit", "DifficultyFormat");
|
||||
static ThemeMetric<RString> ROUTINE_PLAYER_FORMAT("ScreenEdit", "RoutinePlayerFormat");
|
||||
static ThemeMetric<RString> DESCRIPTION_FORMAT("ScreenEdit", "DescriptionFormat");
|
||||
static ThemeMetric<RString> CHART_STYLE_FORMAT("ScreenEdit", "ChartStyleFormat");
|
||||
static ThemeMetric<RString> STEP_AUTHOR_FORMAT("ScreenEdit", "StepAuthorFormat");
|
||||
static ThemeMetric<RString> MAIN_TITLE_FORMAT("ScreenEdit", "MainTitleFormat");
|
||||
static ThemeMetric<RString> SUBTITLE_FORMAT("ScreenEdit", "SubtitleFormat");
|
||||
static ThemeMetric<RString> TAP_NOTE_TYPE_FORMAT("ScreenEdit", "TapNoteTypeFormat");
|
||||
static ThemeMetric<RString> SEGMENT_TYPE_FORMAT("ScreenEdit", "SegmentTypeFormat");
|
||||
static ThemeMetric<RString> NUM_STEPS_FORMAT("ScreenEdit", "NumStepsFormat");
|
||||
static ThemeMetric<RString> NUM_JUMPS_FORMAT("ScreenEdit", "NumJumpsFormat");
|
||||
static ThemeMetric<RString> NUM_HOLDS_FORMAT("ScreenEdit", "NumHoldsFormat");
|
||||
@@ -1192,12 +1214,14 @@ void ScreenEdit::UpdateTextInfo()
|
||||
if ( m_InputPlayerNumber != PLAYER_INVALID )
|
||||
sText += ssprintf( ROUTINE_PLAYER_FORMAT.GetValue(), ROUTINE_PLAYER.GetValue().c_str(), m_InputPlayerNumber + 1 );
|
||||
sText += ssprintf( DESCRIPTION_FORMAT.GetValue(), DESCRIPTION.GetValue().c_str(), m_pSteps->GetDescription().c_str() );
|
||||
sText += ssprintf( CHART_STYLE_FORMAT.GetValue(), CHART_STYLE.GetValue().c_str(), m_pSteps->GetChartStyle().c_str() );
|
||||
sText += ssprintf( STEP_AUTHOR_FORMAT.GetValue(), STEP_AUTHOR.GetValue().c_str(), m_pSteps->GetCredit().c_str() );
|
||||
//sText += ssprintf( CHART_STYLE_FORMAT.GetValue(), CHART_STYLE.GetValue().c_str(), m_pSteps->GetChartStyle().c_str() );
|
||||
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( TAP_NOTE_TYPE_FORMAT.GetValue(), TAP_NOTE_TYPE.GetValue().c_str(), TapNoteTypeToString( m_selectedTap.type ).c_str() );
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
GAMESTATE->SetProcessedTimingData(&m_pSteps->m_Timing);
|
||||
@@ -1453,6 +1477,62 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
}
|
||||
break;
|
||||
}
|
||||
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";
|
||||
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;
|
||||
}
|
||||
case EDIT_BUTTON_SCROLL_SPEED_UP:
|
||||
case EDIT_BUTTON_SCROLL_SPEED_DOWN:
|
||||
{
|
||||
@@ -1567,16 +1647,60 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
ScrollTo( NoteRowToBeat(iRow) );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_LABEL_NEXT:
|
||||
{
|
||||
ScrollTo( GetAppropriateTiming().GetNextLabelSegmentBeatAtBeat( GetBeat() ) );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_LABEL_PREV:
|
||||
{
|
||||
ScrollTo( GetAppropriateTiming().GetPreviousLabelSegmentBeatAtBeat( GetBeat() ) );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_SEGMENT_NEXT:
|
||||
{
|
||||
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()));
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_SEGMENT_PREV:
|
||||
{
|
||||
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()));
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_SNAP_NEXT:
|
||||
if( m_SnapDisplay.PrevSnapMode() )
|
||||
OnSnapModeChange();
|
||||
@@ -1654,6 +1778,9 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
// don't keep undo when changing Steps
|
||||
ClearUndo();
|
||||
|
||||
// get the second of the current step.
|
||||
float curSecond = GetAppropriateTiming().GetElapsedTimeFromBeat(GetBeat());
|
||||
|
||||
// save current steps
|
||||
Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
|
||||
ASSERT( pSteps );
|
||||
@@ -1706,6 +1833,8 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
int(vSteps.size()) );
|
||||
SCREENMAN->SystemMessage( s );
|
||||
m_soundSwitchSteps.Play();
|
||||
|
||||
ScrollTo( GetAppropriateTiming().GetBeatFromElapsedTime(curSecond) );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_BPM_UP:
|
||||
@@ -1988,6 +2117,35 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
EditMiniMenu( &g_CourseMode, SM_BackFromCourseModeMenu );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_OPEN_STEP_ATTACK_MENU:
|
||||
{
|
||||
TimingData &timing = GetAppropriateTiming();
|
||||
float startTime = timing.GetElapsedTimeFromBeat(GetBeat());
|
||||
AttackArray &attacks =
|
||||
(GAMESTATE->m_bIsUsingStepTiming ? m_pSteps->m_Attacks : m_pSong->m_Attacks);
|
||||
int index = FindAttackAtTime(attacks, startTime);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
const RString sDuration = ssprintf( "%.5f", attacks[index].fSecsRemaining );
|
||||
|
||||
g_InsertCourseAttack.rows[remove].bEnabled = true;
|
||||
if( g_InsertCourseAttack.rows[duration].choices.size() == 9 )
|
||||
g_InsertCourseAttack.rows[duration].choices.push_back( sDuration );
|
||||
else
|
||||
g_InsertCourseAttack.rows[duration].choices.back() = sDuration;
|
||||
g_InsertCourseAttack.rows[duration].iDefaultChoice = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( g_InsertCourseAttack.rows[duration].choices.size() == 10 )
|
||||
g_InsertCourseAttack.rows[duration].choices.pop_back();
|
||||
g_InsertCourseAttack.rows[duration].iDefaultChoice = 3;
|
||||
}
|
||||
EditMiniMenu( &g_InsertCourseAttack, SM_BackFromInsertStepAttack );
|
||||
|
||||
break;
|
||||
}
|
||||
case EDIT_BUTTON_OPEN_COURSE_ATTACK_MENU:
|
||||
{
|
||||
// TODO: Give Song/Step Timing switches/functions here?
|
||||
@@ -2019,6 +2177,44 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
EditMiniMenu( &g_InsertCourseAttack, SM_BackFromInsertCourseAttack );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_ADD_STEP_MODS:
|
||||
{
|
||||
float start = -1;
|
||||
float end = -1;
|
||||
PlayerOptions po;
|
||||
|
||||
if (m_NoteFieldEdit.m_iBeginMarker == -1) // not highlighted
|
||||
{
|
||||
po.FromString("");
|
||||
}
|
||||
else
|
||||
{
|
||||
TimingData &timing = GetAppropriateTiming();
|
||||
start = timing.GetElapsedTimeFromBeat(NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker));
|
||||
AttackArray &attacks =
|
||||
(GAMESTATE->m_bIsUsingStepTiming ? m_pSteps->m_Attacks : m_pSong->m_Attacks);
|
||||
int index = FindAttackAtTime(attacks, start);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
po.FromString("");
|
||||
}
|
||||
if (m_NoteFieldEdit.m_iEndMarker == -1)
|
||||
{
|
||||
end = m_pSong->m_fMusicLengthSeconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = timing.GetElapsedTimeFromBeat(NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker));
|
||||
}
|
||||
|
||||
}
|
||||
g_fLastInsertAttackPositionSeconds = start;
|
||||
g_fLastInsertAttackDurationSeconds = end - start;
|
||||
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.Assign( ModsLevel_Stage, po );
|
||||
SCREENMAN->AddNewScreenToTop( "ScreenPlayerOptions", SM_BackFromInsertStepAttackPlayerOptions );
|
||||
break;
|
||||
}
|
||||
case EDIT_BUTTON_ADD_COURSE_MODS:
|
||||
{
|
||||
float fStart, fEnd;
|
||||
@@ -2910,6 +3106,30 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
|
||||
m_NoteDataEdit.SetTapNote( g_iLastInsertTapAttackTrack, row, tn );
|
||||
CheckNumberOfNotesAndUndo();
|
||||
}
|
||||
else if (SM == SM_BackFromInsertStepAttack)
|
||||
{
|
||||
int iDurationChoice = ScreenMiniMenu::s_viLastAnswers[0];
|
||||
TimingData &timing = GetAppropriateTiming();
|
||||
g_fLastInsertAttackPositionSeconds = timing.GetElapsedTimeFromBeat( GetBeat() );
|
||||
g_fLastInsertAttackDurationSeconds = StringToFloat( g_InsertCourseAttack.rows[0].choices[iDurationChoice] );
|
||||
AttackArray &attacks = GAMESTATE->m_bIsUsingStepTiming ? m_pSteps->m_Attacks : m_pSong->m_Attacks;
|
||||
int iAttack = FindAttackAtTime(attacks, g_fLastInsertAttackPositionSeconds);
|
||||
|
||||
if (ScreenMiniMenu::s_iLastRowCode == ScreenEdit::remove )
|
||||
{
|
||||
ASSERT(iAttack >= 0);
|
||||
attacks.erase(attacks.begin() + iAttack);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerOptions po;
|
||||
if (iAttack >= 0)
|
||||
po.FromString(attacks[iAttack].sModifiers);
|
||||
|
||||
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.Assign( ModsLevel_Preferred, po );
|
||||
SCREENMAN->AddNewScreenToTop( "ScreenPlayerOptions", SM_BackFromInsertStepAttackPlayerOptions );
|
||||
}
|
||||
}
|
||||
else if( SM == SM_BackFromInsertCourseAttack )
|
||||
{
|
||||
int iDurationChoice = ScreenMiniMenu::s_viLastAnswers[0];
|
||||
@@ -2939,6 +3159,27 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
|
||||
SCREENMAN->AddNewScreenToTop( "ScreenPlayerOptions", SM_BackFromInsertCourseAttackPlayerOptions );
|
||||
}
|
||||
}
|
||||
else if (SM == SM_BackFromInsertStepAttackPlayerOptions)
|
||||
{
|
||||
PlayerOptions poChosen = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetPreferred();
|
||||
RString mods = poChosen.GetString();
|
||||
|
||||
if (g_fLastInsertAttackPositionSeconds >= 0)
|
||||
{
|
||||
Attack a(ATTACK_LEVEL_1,
|
||||
g_fLastInsertAttackPositionSeconds,
|
||||
g_fLastInsertAttackDurationSeconds,
|
||||
mods,
|
||||
false,
|
||||
false);
|
||||
AttackArray &attacks = GAMESTATE->m_bIsUsingStepTiming ? m_pSteps->m_Attacks : m_pSong->m_Attacks;
|
||||
int index = FindAttackAtTime(attacks, g_fLastInsertAttackPositionSeconds);
|
||||
if (index >= 0)
|
||||
attacks[index] = a;
|
||||
else
|
||||
attacks.push_back(a);
|
||||
}
|
||||
}
|
||||
else if( SM == SM_BackFromInsertCourseAttackPlayerOptions )
|
||||
{
|
||||
PlayerOptions poChosen = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetPreferred();
|
||||
@@ -3409,6 +3650,12 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
|
||||
|
||||
// copy edit into current Steps
|
||||
m_pSteps->SetNoteData( m_NoteDataEdit );
|
||||
|
||||
// don't forget the attacks.
|
||||
m_pSong->m_Attacks = GAMESTATE->m_pCurSong->m_Attacks;
|
||||
m_pSong->m_sAttackString = GAMESTATE->m_pCurSong->m_Attacks.ToVectorString();
|
||||
m_pSteps->m_Attacks = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks;
|
||||
m_pSteps->m_sAttackString = GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks.ToVectorString();
|
||||
|
||||
switch( EDIT_MODE.GetValue() )
|
||||
{
|
||||
@@ -3856,18 +4103,29 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
|
||||
break;
|
||||
|
||||
case convert_pause_to_beat:
|
||||
{
|
||||
// TODO: Convert both Delays and Stops at once.
|
||||
float fStopSeconds = GetAppropriateTiming().GetStopAtRow( BeatToNoteRow( GetBeat() ) );
|
||||
GetAppropriateTiming().SetStopAtBeat( GetBeat() , 0 );
|
||||
{
|
||||
float fStopSeconds = GetAppropriateTiming().GetStopAtRow(GetRow());
|
||||
GetAppropriateTiming().SetStopAtBeat( GetBeat() , 0 );
|
||||
|
||||
float fStopBeats = fStopSeconds * GetAppropriateTiming().GetBPMAtBeat( GetBeat() ) / 60;
|
||||
float fStopBeats = fStopSeconds * GetAppropriateTiming().GetBPMAtBeat( GetBeat() ) / 60;
|
||||
|
||||
// don't move the step from where it is, just move everything later
|
||||
NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow( GetBeat() ) + 1, BeatToNoteRow(fStopBeats) );
|
||||
GetAppropriateTiming().InsertRows( BeatToNoteRow( GetBeat() ) + 1, BeatToNoteRow(fStopBeats) );
|
||||
}
|
||||
// don't move the step from where it is, just move everything later
|
||||
NoteDataUtil::InsertRows( m_NoteDataEdit, GetRow() + 1, BeatToNoteRow(fStopBeats) );
|
||||
GetAppropriateTiming().InsertRows( GetRow() + 1, BeatToNoteRow(fStopBeats) );
|
||||
}
|
||||
break;
|
||||
case convert_delay_to_beat:
|
||||
{
|
||||
TimingData &timing = GetAppropriateTiming();
|
||||
float pause = timing.GetDelayAtRow(GetRow());
|
||||
timing.SetDelayAtRow(GetRow(), 0);
|
||||
|
||||
float pauseBeats = pause * timing.GetBPMAtBeat(GetBeat()) / 60;
|
||||
|
||||
NoteDataUtil::InsertRows(m_NoteDataEdit, GetRow(), BeatToNoteRow(pauseBeats));
|
||||
timing.InsertRows(GetRow(), BeatToNoteRow(pauseBeats));
|
||||
break;
|
||||
}
|
||||
case undo:
|
||||
Undo();
|
||||
break;
|
||||
@@ -4150,6 +4408,24 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
|
||||
);
|
||||
break;
|
||||
}
|
||||
case copy_timing:
|
||||
{
|
||||
clipboardTiming = GetAppropriateTiming();
|
||||
break;
|
||||
}
|
||||
case paste_timing:
|
||||
{
|
||||
if (GAMESTATE->m_bIsUsingStepTiming)
|
||||
{
|
||||
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing = clipboardTiming;
|
||||
}
|
||||
else
|
||||
{
|
||||
GAMESTATE->m_pCurSong->m_SongTiming = clipboardTiming;
|
||||
}
|
||||
SetDirty(true);
|
||||
break;
|
||||
}
|
||||
case erase_step_timing:
|
||||
ScreenPrompt::Prompt( SM_DoEraseStepTiming, CONFIRM_TIMING_ERASE , PROMPT_YES_NO, ANSWER_NO );
|
||||
break;
|
||||
@@ -4265,6 +4541,27 @@ void ScreenEdit::SetupCourseAttacks()
|
||||
FOREACH( Attack, Attacks, attack )
|
||||
GAMESTATE->m_pPlayerState[PLAYER_1]->LaunchAttack( *attack );
|
||||
}
|
||||
else
|
||||
{
|
||||
const PlayerOptions &p = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetCurrent();
|
||||
if (GAMESTATE->m_pCurSong && p.m_fNoAttack == 0 && p.m_fRandAttack == 0 )
|
||||
{
|
||||
AttackArray &attacks = GAMESTATE->m_bIsUsingStepTiming ?
|
||||
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks :
|
||||
GAMESTATE->m_pCurSong->m_Attacks;
|
||||
|
||||
if (attacks.size() > 0)
|
||||
{
|
||||
FOREACH(Attack, attacks, attack)
|
||||
{
|
||||
float fBeat = GetAppropriateTiming().GetBeatFromElapsedTime(attack->fStartSecond);
|
||||
if (fBeat >= GetBeat())
|
||||
GAMESTATE->m_pPlayerState[PLAYER_1]->LaunchAttack( *attack );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GAMESTATE->m_pPlayerState[PLAYER_1]->RebuildPlayerOptionsFromActiveAttacks();
|
||||
}
|
||||
|
||||
|
||||
+22
-3
@@ -60,6 +60,9 @@ enum EditButton
|
||||
EDIT_BUTTON_CYCLE_TAP_LEFT, /**< Rotate the available tap notes once to the "left". */
|
||||
EDIT_BUTTON_CYCLE_TAP_RIGHT, /**< Rotate the available tap notes once to the "right". */
|
||||
|
||||
EDIT_BUTTON_CYCLE_SEGMENT_LEFT, /**< Select one segment to the left for jumping. */
|
||||
EDIT_BUTTON_CYCLE_SEGMENT_RIGHT, /**< Select one segment to the right for jumping. */
|
||||
|
||||
EDIT_BUTTON_SCROLL_UP_LINE,
|
||||
EDIT_BUTTON_SCROLL_UP_PAGE,
|
||||
EDIT_BUTTON_SCROLL_UP_TS,
|
||||
@@ -73,8 +76,8 @@ enum EditButton
|
||||
EDIT_BUTTON_SCROLL_NEXT,
|
||||
EDIT_BUTTON_SCROLL_PREV,
|
||||
|
||||
EDIT_BUTTON_LABEL_NEXT, /**< Jump to the start of the next label downward. */
|
||||
EDIT_BUTTON_LABEL_PREV, /**< Jump to the start of the previous label upward. */
|
||||
EDIT_BUTTON_SEGMENT_NEXT, /**< Jump to the start of the next segment downward. */
|
||||
EDIT_BUTTON_SEGMENT_PREV, /**< Jump to the start of the previous segment upward. */
|
||||
|
||||
// These are modifiers to EDIT_BUTTON_SCROLL_*.
|
||||
EDIT_BUTTON_SCROLL_SELECT,
|
||||
@@ -95,8 +98,12 @@ enum EditButton
|
||||
EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU,
|
||||
EDIT_BUTTON_OPEN_COURSE_MENU,
|
||||
EDIT_BUTTON_OPEN_COURSE_ATTACK_MENU,
|
||||
|
||||
EDIT_BUTTON_OPEN_STEP_ATTACK_MENU, /**< Open up the Step Attacks menu. */
|
||||
EDIT_BUTTON_ADD_STEP_MODS, /**< Add a mod attack to the row. */
|
||||
|
||||
EDIT_BUTTON_OPEN_INPUT_HELP,
|
||||
|
||||
|
||||
EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP,
|
||||
EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP_AND_GENRE,
|
||||
|
||||
@@ -266,9 +273,18 @@ protected:
|
||||
* This is mainly to allow playing a chart with Song Timing. */
|
||||
TimingData backupStepTiming;
|
||||
|
||||
/**
|
||||
* @brief Have a backup of the TimingData of the player's choice.
|
||||
*
|
||||
* This will be used for copying and pasting as required. */
|
||||
TimingData clipboardTiming;
|
||||
|
||||
/** @brief The current TapNote that would be inserted. */
|
||||
TapNote m_selectedTap;
|
||||
|
||||
/** @brief The type of segment users will jump back and forth between. */
|
||||
RString currentCycleSegment;
|
||||
|
||||
void UpdateTextInfo();
|
||||
BitmapText m_textInfo; // status information that changes
|
||||
bool m_bTextInfoNeedsUpdate;
|
||||
@@ -404,6 +420,7 @@ public:
|
||||
shift_pauses_forward,
|
||||
shift_pauses_backward,
|
||||
convert_pause_to_beat,
|
||||
convert_delay_to_beat,
|
||||
undo,
|
||||
clear_clipboard,
|
||||
NUM_AREA_MENU_CHOICES
|
||||
@@ -539,6 +556,8 @@ public:
|
||||
speed_mode,
|
||||
scroll,
|
||||
fake,
|
||||
copy_timing,
|
||||
paste_timing,
|
||||
erase_step_timing,
|
||||
NUM_TIMING_DATA_INFORMATION_CHOICES
|
||||
};
|
||||
|
||||
@@ -820,11 +820,12 @@ void ScreenGameplay::InitSongQueues()
|
||||
{
|
||||
Steps *pSteps = GAMESTATE->m_pCurSteps[ pi->GetStepsAndTrailIndex() ];
|
||||
pi->m_vpStepsQueue.push_back( pSteps );
|
||||
|
||||
if( pi->GetPlayerState()->m_PlayerOptions.GetCurrent().m_fSongAttack != 0 &&
|
||||
GAMESTATE->m_pCurSong->m_Attacks.size() > 0 )
|
||||
const PlayerOptions &p = pi->GetPlayerState()->m_PlayerOptions.GetCurrent();
|
||||
|
||||
if (p.m_fNoAttack == 0 && p.m_fRandAttack == 0 &&
|
||||
pSteps->m_Attacks.size() > 0 )
|
||||
{
|
||||
pi->m_asModifiersQueue.push_back( GAMESTATE->m_pCurSong->m_Attacks );
|
||||
pi->m_asModifiersQueue.push_back( pSteps->m_Attacks );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -53,7 +53,6 @@ protected:
|
||||
Page GetPage( int iChoiceIndex ) const;
|
||||
Page GetCurrentPage() const;
|
||||
|
||||
ThemeMetric<bool> USE_TWO_SCROLLERS;
|
||||
ThemeMetric<bool> DO_SWITCH_ANYWAYS;
|
||||
ThemeMetric<bool> DOUBLE_PRESS_TO_SELECT;
|
||||
ThemeMetric<bool> SHOW_ICON;
|
||||
@@ -68,7 +67,6 @@ protected:
|
||||
ThemeMetric<float> PRE_SWITCH_PAGE_SECONDS;
|
||||
ThemeMetric<float> POST_SWITCH_PAGE_SECONDS;
|
||||
ThemeMetric1D<RString> OPTION_ORDER;
|
||||
ThemeMetric1D<RString> OPTION_ORDER2;
|
||||
ThemeMetric<bool> WRAP_CURSOR;
|
||||
ThemeMetric<bool> WRAP_SCROLLER;
|
||||
ThemeMetric<bool> LOOP_SCROLLER;
|
||||
|
||||
+4
-2
@@ -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 = 182;
|
||||
const int FILE_CACHE_VERSION = 185;
|
||||
|
||||
/** @brief How long does a song sample last by default? */
|
||||
const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f;
|
||||
@@ -154,7 +154,9 @@ Steps *Song::CreateSteps()
|
||||
|
||||
void Song::InitSteps(Steps *pSteps)
|
||||
{
|
||||
pSteps->m_Timing = m_SongTiming;
|
||||
pSteps->m_Timing = this->m_SongTiming;
|
||||
pSteps->m_sAttackString = this->m_sAttackString;
|
||||
pSteps->m_Attacks = this->m_Attacks;
|
||||
}
|
||||
|
||||
void Song::GetDisplayBpms( DisplayBpms &AddTo ) const
|
||||
|
||||
+1
-1
@@ -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.7f;
|
||||
const static float STEPFILE_VERSION_NUMBER = 0.72f;
|
||||
|
||||
/** @brief How many edits for this song can each profile have? */
|
||||
const int MAX_EDITS_PER_SONG_PER_PROFILE = 15;
|
||||
|
||||
+20
-1
@@ -40,6 +40,11 @@ Steps::~Steps()
|
||||
{
|
||||
}
|
||||
|
||||
bool Steps::HasAttacks() const
|
||||
{
|
||||
return !this->m_Attacks.empty();
|
||||
}
|
||||
|
||||
unsigned Steps::GetHash() const
|
||||
{
|
||||
if( parent )
|
||||
@@ -364,6 +369,8 @@ void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds
|
||||
noteData.SetNumTracks( GAMEMAN->GetStepsTypeInfo(ntTo).iNumTracks );
|
||||
parent = NULL;
|
||||
m_Timing = pSource->m_Timing;
|
||||
this->m_Attacks = pSource->m_Attacks;
|
||||
this->m_sAttackString = pSource->m_sAttackString;
|
||||
this->SetNoteData( noteData );
|
||||
this->SetDescription( pSource->GetDescription() );
|
||||
this->SetDifficulty( pSource->GetDifficulty() );
|
||||
@@ -463,7 +470,18 @@ public:
|
||||
DEFINE_METHOD( IsAPlayerEdit, IsAPlayerEdit() )
|
||||
DEFINE_METHOD( UsesSplitTiming, UsesSplitTiming() )
|
||||
|
||||
static int HasSignificantTimingChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasSignificantTimingChanges()); return 1; }
|
||||
static int HasSignificantTimingChanges( T* p, lua_State *L )
|
||||
{
|
||||
lua_pushboolean(L, p->HasSignificantTimingChanges());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int HasAttacks( T* p, lua_State *L )
|
||||
{
|
||||
lua_pushboolean(L, p->HasAttacks());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int GetRadarValues( T* p, lua_State *L )
|
||||
{
|
||||
@@ -500,6 +518,7 @@ public:
|
||||
ADD_METHOD( GetHash );
|
||||
ADD_METHOD( GetMeter );
|
||||
ADD_METHOD( HasSignificantTimingChanges );
|
||||
ADD_METHOD( HasAttacks );
|
||||
ADD_METHOD( GetRadarValues );
|
||||
ADD_METHOD( GetTimingData );
|
||||
//ADD_METHOD( GetSMNoteData );
|
||||
|
||||
+11
@@ -1,6 +1,7 @@
|
||||
#ifndef STEPS_H
|
||||
#define STEPS_H
|
||||
|
||||
#include "Attack.h"
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "PlayerNumber.h"
|
||||
#include "Grade.h"
|
||||
@@ -92,6 +93,11 @@ public:
|
||||
*/
|
||||
RString GetCredit() const { return Real()->m_sCredit; }
|
||||
|
||||
/** @brief The list of attacks. */
|
||||
AttackArray m_Attacks;
|
||||
/** @brief The stringified list of attacks. */
|
||||
vector<RString> m_sAttackString;
|
||||
|
||||
void SetFilename( RString fn ) { m_sFilename = fn; }
|
||||
RString GetFilename() const { return m_sFilename; }
|
||||
void SetSavedToDisk( bool b ) { DeAutogen(); m_bSavedToDisk = b; }
|
||||
@@ -128,6 +134,11 @@ public:
|
||||
* @brief Determine if the Steps have any major timing changes during gameplay.
|
||||
* @return true if it does, or false otherwise. */
|
||||
bool HasSignificantTimingChanges() const;
|
||||
|
||||
/**
|
||||
* @brief Determine if the Steps have any attacks.
|
||||
* @return true if it does, or false otherwise. */
|
||||
bool HasAttacks() const;
|
||||
|
||||
// Lua
|
||||
void PushSelf( lua_State *L );
|
||||
|
||||
+297
-118
@@ -753,6 +753,287 @@ int TimingData::GetTickcountAtRow( int iRow ) const
|
||||
return m_TickcountSegments[GetTickcountSegmentIndexAtRow( iRow )].GetTicks();
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousBPMSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_BPMSegments.size(); i++ )
|
||||
{
|
||||
if( m_BPMSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_BPMSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextBPMSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_BPMSegments.size(); i++ )
|
||||
{
|
||||
if( m_BPMSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_BPMSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousStopSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_StopSegments.size(); i++ )
|
||||
{
|
||||
const StopSegment &s = m_StopSegments[i];
|
||||
if( s.GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!s.GetDelay())
|
||||
backup = s.GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextStopSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_StopSegments.size(); i++ )
|
||||
{
|
||||
const StopSegment &s = m_StopSegments[i];
|
||||
if( s.GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!s.GetDelay())
|
||||
return s.GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousDelaySegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_StopSegments.size(); i++ )
|
||||
{
|
||||
const StopSegment &s = m_StopSegments[i];
|
||||
if( s.GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (s.GetDelay())
|
||||
backup = s.GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextDelaySegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_StopSegments.size(); i++ )
|
||||
{
|
||||
const StopSegment &s = m_StopSegments[i];
|
||||
if( s.GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (s.GetDelay())
|
||||
return s.GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousTimeSignatureSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ )
|
||||
{
|
||||
if( m_vTimeSignatureSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_vTimeSignatureSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextTimeSignatureSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ )
|
||||
{
|
||||
if( m_vTimeSignatureSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_vTimeSignatureSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
|
||||
float TimingData::GetPreviousTickcountSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_TickcountSegments.size(); i++ )
|
||||
{
|
||||
if( m_TickcountSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_TickcountSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextTickcountSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_TickcountSegments.size(); i++ )
|
||||
{
|
||||
if( m_TickcountSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_TickcountSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousComboSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_ComboSegments.size(); i++ )
|
||||
{
|
||||
if( m_ComboSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_ComboSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextComboSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_ComboSegments.size(); i++ )
|
||||
{
|
||||
if( m_ComboSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_ComboSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float TimingData::GetPreviousWarpSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_WarpSegments.size(); i++ )
|
||||
{
|
||||
if( m_WarpSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_WarpSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextWarpSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_WarpSegments.size(); i++ )
|
||||
{
|
||||
if( m_WarpSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_WarpSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousFakeSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_FakeSegments.size(); i++ )
|
||||
{
|
||||
if( m_FakeSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_FakeSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextFakeSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_FakeSegments.size(); i++ )
|
||||
{
|
||||
if( m_FakeSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_FakeSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousSpeedSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_SpeedSegments.size(); i++ )
|
||||
{
|
||||
if( m_SpeedSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_SpeedSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextSpeedSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_SpeedSegments.size(); i++ )
|
||||
{
|
||||
if( m_SpeedSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_SpeedSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousScrollSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
for (unsigned i = 0; i < m_ScrollSegments.size(); i++ )
|
||||
{
|
||||
if( m_ScrollSegments[i].GetRow() >= iRow )
|
||||
{
|
||||
break;
|
||||
}
|
||||
backup = m_ScrollSegments[i].GetBeat();
|
||||
}
|
||||
return (backup > -1) ? backup : NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetNextScrollSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_ScrollSegments.size(); i++ )
|
||||
{
|
||||
if( m_ScrollSegments[i].GetRow() <= iRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return m_ScrollSegments[i].GetBeat();
|
||||
}
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
float TimingData::GetPreviousLabelSegmentBeatAtRow( int iRow ) const
|
||||
{
|
||||
float backup = -1;
|
||||
@@ -1026,149 +1307,48 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool
|
||||
ASSERT( iStartIndex >= 0 );
|
||||
ASSERT( iStartIndex < iEndIndex );
|
||||
|
||||
int length = iEndIndex - iStartIndex;
|
||||
int newLength = lrintf( fScale * length );
|
||||
|
||||
for ( unsigned i = 0; i < m_BPMSegments.size(); i++ )
|
||||
{
|
||||
BPMSegment &b = m_BPMSegments[i];
|
||||
const int iSegStart = b.GetRow();
|
||||
if( iSegStart < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStart > iEndIndex )
|
||||
b.SetRow( b.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ) );
|
||||
else
|
||||
b.SetRow( lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex );
|
||||
}
|
||||
m_BPMSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for( unsigned i = 0; i < m_StopSegments.size(); i++ )
|
||||
{
|
||||
StopSegment &s = m_StopSegments[i];
|
||||
const int iSegStartRow = s.GetRow();
|
||||
if( iSegStartRow < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStartRow > iEndIndex )
|
||||
s.SetRow(s.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1)));
|
||||
else
|
||||
s.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex);
|
||||
}
|
||||
m_StopSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ )
|
||||
{
|
||||
TimeSignatureSegment &t = m_vTimeSignatureSegments[i];
|
||||
const int iSegStartRow = t.GetRow();
|
||||
if( iSegStartRow < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStartRow > iEndIndex )
|
||||
t.SetRow(t.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1)));
|
||||
else
|
||||
t.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex);
|
||||
}
|
||||
m_vTimeSignatureSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for( unsigned i = 0; i < m_WarpSegments.size(); i++ )
|
||||
{
|
||||
WarpSegment &w = m_WarpSegments[i];
|
||||
const int iSegStartRow = w.GetRow();
|
||||
const int iSegEndRow = iSegStartRow + BeatToNoteRow( w.GetLength() );
|
||||
if( iSegEndRow >= iStartIndex )
|
||||
{
|
||||
if( iSegEndRow > iEndIndex )
|
||||
w.SetLength(w.GetLength() +
|
||||
NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))));
|
||||
else
|
||||
w.SetLength(NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)));
|
||||
}
|
||||
if( iSegStartRow < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStartRow > iEndIndex )
|
||||
w.SetRow(w.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1)));
|
||||
else
|
||||
w.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex);
|
||||
}
|
||||
m_WarpSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for ( unsigned i = 0; i < m_TickcountSegments.size(); i++ )
|
||||
{
|
||||
TickcountSegment &t = m_TickcountSegments[i];
|
||||
const int iSegStart = t.GetRow();
|
||||
if( iSegStart < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStart > iEndIndex )
|
||||
t.SetRow(t.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ));
|
||||
else
|
||||
t.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex);
|
||||
}
|
||||
m_TickcountSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for ( unsigned i = 0; i < m_ComboSegments.size(); i++ )
|
||||
{
|
||||
ComboSegment &c = m_ComboSegments[i];
|
||||
const int iSegStart = c.GetRow();
|
||||
if( iSegStart < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStart > iEndIndex )
|
||||
c.SetRow(c.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ));
|
||||
else
|
||||
c.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex);
|
||||
}
|
||||
m_ComboSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for ( unsigned i = 0; i < m_LabelSegments.size(); i++ )
|
||||
{
|
||||
LabelSegment &l = m_LabelSegments[i];
|
||||
const int iSegStart = l.GetRow();
|
||||
if( iSegStart < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStart > iEndIndex )
|
||||
l.SetRow(l.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ));
|
||||
else
|
||||
l.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex);
|
||||
}
|
||||
m_LabelSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for ( unsigned i = 0; i < m_SpeedSegments.size(); i++ )
|
||||
{
|
||||
SpeedSegment &s = m_SpeedSegments[i];
|
||||
const int iSegStart = s.GetRow();
|
||||
if( iSegStart < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStart > iEndIndex )
|
||||
s.SetRow(s.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ));
|
||||
else
|
||||
s.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex);
|
||||
s.Scale( iStartIndex, length, newLength );
|
||||
if (s.GetUnit() == 0) // beats
|
||||
s.SetLength(s.GetLength() * fScale);
|
||||
}
|
||||
|
||||
for( unsigned i = 0; i < m_FakeSegments.size(); i++ )
|
||||
{
|
||||
FakeSegment &f = m_FakeSegments[i];
|
||||
const int iSegStartRow = f.GetRow();
|
||||
const int iSegEndRow = iSegStartRow + BeatToNoteRow( f.GetLength() );
|
||||
if( iSegEndRow >= iStartIndex )
|
||||
{
|
||||
if( iSegEndRow > iEndIndex )
|
||||
f.SetLength(f.GetLength()
|
||||
+ NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))));
|
||||
else
|
||||
f.SetLength(NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)));
|
||||
}
|
||||
if( iSegStartRow < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStartRow > iEndIndex )
|
||||
f.SetRow(f.GetRow()
|
||||
+ lrintf((iEndIndex - iStartIndex) * (fScale - 1)));
|
||||
else
|
||||
f.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex);
|
||||
}
|
||||
m_FakeSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
for( unsigned i = 0; i < m_ScrollSegments.size(); i++ )
|
||||
{
|
||||
ScrollSegment &s = m_ScrollSegments[i];
|
||||
const int iSegStartRow = s.GetRow();
|
||||
if( iSegStartRow < iStartIndex )
|
||||
continue;
|
||||
else if( iSegStartRow > iEndIndex )
|
||||
s.SetRow(s.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1)));
|
||||
else
|
||||
s.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex);
|
||||
}
|
||||
m_ScrollSegments[i].Scale( iStartIndex, length, newLength );
|
||||
|
||||
// adjust BPM changes to preserve timing
|
||||
if( bAdjustBPM )
|
||||
{
|
||||
int iNewEndIndex = lrintf( (iEndIndex - iStartIndex) * fScale ) + iStartIndex;
|
||||
int iNewEndIndex = iStartIndex + newLength;
|
||||
float fEndBPMBeforeScaling = GetBPMAtRow(iNewEndIndex);
|
||||
|
||||
// adjust BPM changes "between" iStartIndex and iNewEndIndex
|
||||
@@ -1186,7 +1366,6 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool
|
||||
// set BPM at iStartIndex and iNewEndIndex.
|
||||
SetBPMAtRow( iStartIndex, GetBPMAtRow(iStartIndex) * fScale );
|
||||
SetBPMAtRow( iNewEndIndex, fEndBPMBeforeScaling );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+327
-2
@@ -83,6 +83,38 @@ public:
|
||||
*/
|
||||
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) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Stop/Delay at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -249,6 +281,68 @@ public:
|
||||
*/
|
||||
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) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Time Signature's numerator at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -345,6 +439,39 @@ public:
|
||||
* @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.
|
||||
@@ -405,6 +532,39 @@ public:
|
||||
* @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.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -459,6 +619,38 @@ public:
|
||||
*/
|
||||
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) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Combo at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -513,6 +705,38 @@ public:
|
||||
*/
|
||||
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) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Label at the given row.
|
||||
* @param iNoteRow the row in question.
|
||||
@@ -578,7 +802,10 @@ public:
|
||||
* @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 GetPreviousLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); }
|
||||
float GetPreviousLabelSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetPreviousLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the requisite label already exists.
|
||||
@@ -597,7 +824,10 @@ public:
|
||||
* @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 GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); }
|
||||
float GetNextLabelSegmentBeatAtBeat( float fBeat ) const
|
||||
{
|
||||
return this->GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -720,6 +950,38 @@ public:
|
||||
|
||||
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.
|
||||
@@ -778,6 +1040,37 @@ public:
|
||||
*/
|
||||
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) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Determine when the fakes end.
|
||||
@@ -845,6 +1138,38 @@ public:
|
||||
*/
|
||||
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.
|
||||
* @param row the row to focus on.
|
||||
|
||||
+27
-2
@@ -5,7 +5,6 @@
|
||||
|
||||
BaseTimingSegment::~BaseTimingSegment() {}
|
||||
|
||||
|
||||
void BaseTimingSegment::SetRow(const int s)
|
||||
{
|
||||
this->startingRow = s;
|
||||
@@ -26,6 +25,11 @@ float BaseTimingSegment::GetBeat() const
|
||||
return NoteRowToBeat(GetRow());
|
||||
}
|
||||
|
||||
void BaseTimingSegment::Scale( int start, int length, int newLength )
|
||||
{
|
||||
SetRow( ScalePosition( start, length, newLength, GetRow() ) );
|
||||
}
|
||||
|
||||
|
||||
/* ======================================================
|
||||
Here comes the actual timing segments implementation!! */
|
||||
@@ -40,6 +44,16 @@ void FakeSegment::SetLength(const float b)
|
||||
this->lengthBeats = b;
|
||||
}
|
||||
|
||||
void FakeSegment::Scale( int start, int length, int newLength )
|
||||
{
|
||||
float startBeat = GetBeat();
|
||||
float endBeat = startBeat + GetLength();
|
||||
float newStartBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), startBeat );
|
||||
float newEndBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), endBeat );
|
||||
SetLength( newEndBeat - newStartBeat );
|
||||
TimingSegment<FakeSegment>::Scale( start, length, newLength );
|
||||
}
|
||||
|
||||
bool FakeSegment::operator<( const FakeSegment &other ) const
|
||||
{
|
||||
LTCOMPARE(GetRow());
|
||||
@@ -60,8 +74,19 @@ void WarpSegment::SetLength(const float b)
|
||||
this->lengthBeats = b;
|
||||
}
|
||||
|
||||
void WarpSegment::Scale( int start, int length, int newLength )
|
||||
{
|
||||
// XXX: this function is duplicated, there should be a better way
|
||||
float startBeat = GetBeat();
|
||||
float endBeat = startBeat + GetLength();
|
||||
float newStartBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), startBeat );
|
||||
float newEndBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), endBeat );
|
||||
SetLength( newEndBeat - newStartBeat );
|
||||
TimingSegment<WarpSegment>::Scale( start, length, newLength );
|
||||
}
|
||||
|
||||
bool WarpSegment::operator<( const WarpSegment &other ) const
|
||||
{
|
||||
{
|
||||
LTCOMPARE(GetRow());
|
||||
LTCOMPARE(GetLength());
|
||||
return false;
|
||||
|
||||
@@ -27,6 +27,14 @@ struct BaseTimingSegment
|
||||
|
||||
virtual ~BaseTimingSegment();
|
||||
|
||||
/**
|
||||
* @brief Scales itself.
|
||||
* @param start Starting row
|
||||
* @param length Length in rows
|
||||
* @param newLength The new length in rows
|
||||
*/
|
||||
virtual void Scale( int start, int length, int newLength );
|
||||
|
||||
/**
|
||||
* @brief Set the starting row of the BaseTimingSegment.
|
||||
*
|
||||
@@ -177,6 +185,8 @@ struct FakeSegment : public TimingSegment<FakeSegment>
|
||||
* @param b the length in beats. */
|
||||
void SetLength(const float b);
|
||||
|
||||
void Scale( int start, int length, int newLength );
|
||||
|
||||
/**
|
||||
* @brief Compares two FakeSegments to see if one is less than the other.
|
||||
* @param other the other FakeSegment to compare to.
|
||||
@@ -236,6 +246,8 @@ struct WarpSegment : public TimingSegment<WarpSegment>
|
||||
* @param b the length in beats. */
|
||||
void SetLength(const float b);
|
||||
|
||||
void Scale( int start, int length, int newLength );
|
||||
|
||||
/*
|
||||
* @brief Compares two WarpSegments to see if one is less than the other.
|
||||
* @param other the other WarpSegment to compare to.
|
||||
|
||||
+126
-6
@@ -7,6 +7,7 @@
|
||||
#include "RageUtil.h"
|
||||
#include "SongManager.h"
|
||||
#include "GameState.h"
|
||||
#include "GameConstantsAndTypes.h" // StepsTypeToString
|
||||
#include "ProfileManager.h"
|
||||
#include "Profile.h"
|
||||
#include "ThemeManager.h"
|
||||
@@ -24,6 +25,8 @@ UnlockManager* UNLOCKMAN = NULL; // global and accessable from anywhere in our p
|
||||
#define UNLOCK(x) THEME->GetMetricR("UnlockManager", ssprintf("Unlock%sCommand",x.c_str()));
|
||||
|
||||
static ThemeMetric<bool> AUTO_LOCK_CHALLENGE_STEPS( "UnlockManager", "AutoLockChallengeSteps" );
|
||||
static ThemeMetric<bool> AUTO_LOCK_EDIT_STEPS( "UnlockManager", "AutoLockEditSteps" );
|
||||
static ThemeMetric<bool> SONGS_NOT_ADDITIONAL( "UnlockManager", "SongsNotAdditional" );
|
||||
|
||||
static const char *UnlockRequirementNames[] =
|
||||
{
|
||||
@@ -44,6 +47,7 @@ static const char *UnlockRewardTypeNames[] =
|
||||
{
|
||||
"Song",
|
||||
"Steps",
|
||||
"StepsType",
|
||||
"Course",
|
||||
"Modifier",
|
||||
};
|
||||
@@ -171,6 +175,18 @@ bool UnlockManager::StepsIsLocked( const Song *pSong, const Steps *pSteps ) cons
|
||||
return p->IsLocked();
|
||||
}
|
||||
|
||||
bool UnlockManager::StepsTypeIsLocked(const Song *pSong, const Steps *pSteps, const StepsType *pSType) const
|
||||
{
|
||||
if( !PREFSMAN->m_bUseUnlockSystem )
|
||||
return false;
|
||||
|
||||
const UnlockEntry *p = FindStepsType( pSong, pSteps, pSType );
|
||||
if( p == NULL )
|
||||
return false;
|
||||
|
||||
return p->IsLocked();
|
||||
}
|
||||
|
||||
bool UnlockManager::ModifierIsLocked( const RString &sOneMod ) const
|
||||
{
|
||||
if( !PREFSMAN->m_bUseUnlockSystem )
|
||||
@@ -200,6 +216,19 @@ const UnlockEntry *UnlockManager::FindSteps( const Song *pSong, const Steps *pSt
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const UnlockEntry *UnlockManager::FindStepsType(const Song *pSong,
|
||||
const Steps *pSteps,
|
||||
const StepsType *pSType ) const
|
||||
{
|
||||
ASSERT( pSong && pSteps && pSType );
|
||||
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
||||
if(e->m_Song.ToSong() == pSong &&
|
||||
e->m_dc == pSteps->GetDifficulty() &&
|
||||
e->m_StepsType == pSteps->m_StepsType)
|
||||
return &(*e);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const UnlockEntry *UnlockManager::FindCourse( const Course *pCourse ) const
|
||||
{
|
||||
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
||||
@@ -309,6 +338,11 @@ bool UnlockEntry::IsValid() const
|
||||
case UnlockRewardType_Steps:
|
||||
return m_Song.IsValid() && m_dc != Difficulty_Invalid;
|
||||
|
||||
case UnlockRewardType_Steps_Type:
|
||||
{
|
||||
return m_Song.IsValid() && m_dc != Difficulty_Invalid && m_StepsType != StepsType_Invalid;
|
||||
}
|
||||
|
||||
case UnlockRewardType_Course:
|
||||
return m_Course.IsValid();
|
||||
|
||||
@@ -323,7 +357,9 @@ bool UnlockEntry::IsValid() const
|
||||
|
||||
UnlockEntryStatus UnlockEntry::GetUnlockEntryStatus() const
|
||||
{
|
||||
if( !m_sEntryID.empty() && PROFILEMAN->GetMachineProfile()->m_UnlockedEntryIDs.find(m_sEntryID) != PROFILEMAN->GetMachineProfile()->m_UnlockedEntryIDs.end() )
|
||||
set<RString> &ids = PROFILEMAN->GetMachineProfile()->m_UnlockedEntryIDs;
|
||||
if(!m_sEntryID.empty() &&
|
||||
ids.find(m_sEntryID) != ids.end() )
|
||||
return UnlockEntryStatus_Unlocked;
|
||||
|
||||
float fScores[NUM_UnlockRequirement];
|
||||
@@ -352,6 +388,21 @@ UnlockEntryStatus UnlockEntry::GetUnlockEntryStatus() const
|
||||
if( PROFILEMAN->GetMachineProfile()->HasPassedSteps(pSong, *s) )
|
||||
return UnlockEntryStatus_RequirementsMet;
|
||||
}
|
||||
|
||||
if (m_bRequirePassChallengeSteps && m_Song.IsValid())
|
||||
{
|
||||
Song *pSong = m_Song.ToSong();
|
||||
vector<Steps*> vp;
|
||||
SongUtil::GetSteps(pSong,
|
||||
vp,
|
||||
StepsType_Invalid,
|
||||
Difficulty_Challenge);
|
||||
FOREACH_CONST(Steps*, vp, s)
|
||||
{
|
||||
if (PROFILEMAN->GetMachineProfile()->HasPassedSteps(pSong, *s))
|
||||
return UnlockEntryStatus_RequirementsMet;
|
||||
}
|
||||
}
|
||||
|
||||
return UnlockEntryStatus_RequrementsNotMet;
|
||||
}
|
||||
@@ -367,10 +418,16 @@ RString UnlockEntry::GetDescription() const
|
||||
case UnlockRewardType_Song:
|
||||
return pSong ? pSong->GetDisplayFullTitle() : "";
|
||||
case UnlockRewardType_Steps:
|
||||
{
|
||||
StepsType st = GAMEMAN->GetHowToPlayStyleForGame( GAMESTATE->m_pCurGame )->m_StepsType; // TODO: Is this the best thing we can do here?
|
||||
return (pSong ? pSong->GetDisplayFullTitle() : "") + ", " + CustomDifficultyToLocalizedString( GetCustomDifficulty(st, m_dc, CourseType_Invalid) );
|
||||
}
|
||||
{
|
||||
StepsType st = GAMEMAN->GetHowToPlayStyleForGame( GAMESTATE->m_pCurGame )->m_StepsType; // TODO: Is this the best thing we can do here?
|
||||
return (pSong ? pSong->GetDisplayFullTitle() : "") + ", " + CustomDifficultyToLocalizedString( GetCustomDifficulty(st, m_dc, CourseType_Invalid) );
|
||||
}
|
||||
case UnlockRewardType_Steps_Type:
|
||||
{
|
||||
RString ret = (pSong ? pSong->GetDisplayFullTitle() : "");
|
||||
ret += "," + CustomDifficultyToLocalizedString( GetCustomDifficulty(m_StepsType, m_dc, CourseType_Invalid) );
|
||||
return ret + "," + StringConversion::ToString(m_StepsType); // yeah, bit strange.
|
||||
}
|
||||
case UnlockRewardType_Course:
|
||||
return m_Course.IsValid() ? m_Course.ToCourse()->GetDisplayFullTitle() : "";
|
||||
case UnlockRewardType_Modifier:
|
||||
@@ -388,6 +445,7 @@ RString UnlockEntry::GetBannerFile() const
|
||||
return "";
|
||||
case UnlockRewardType_Song:
|
||||
case UnlockRewardType_Steps:
|
||||
case UnlockRewardType_Steps_Type:
|
||||
return pSong ? pSong->GetBannerPath() : "";
|
||||
case UnlockRewardType_Course:
|
||||
return m_Course.ToCourse() ? m_Course.ToCourse()->GetBannerPath() : "";
|
||||
@@ -406,6 +464,7 @@ RString UnlockEntry::GetBackgroundFile() const
|
||||
return "";
|
||||
case UnlockRewardType_Song:
|
||||
case UnlockRewardType_Steps:
|
||||
case UnlockRewardType_Steps_Type:
|
||||
return pSong ? pSong->GetBackgroundPath() : "";
|
||||
case UnlockRewardType_Course:
|
||||
return "";
|
||||
@@ -462,7 +521,7 @@ void UnlockManager::Load()
|
||||
if( SongUtil::GetOneSteps(*s, StepsType_Invalid, Difficulty_Challenge) == NULL )
|
||||
continue;
|
||||
|
||||
if( SONGMAN->WasLoadedFromAdditionalSongs(*s) )
|
||||
if( SONGS_NOT_ADDITIONAL && SONGMAN->WasLoadedFromAdditionalSongs(*s) )
|
||||
continue;
|
||||
|
||||
UnlockEntry ue;
|
||||
@@ -474,6 +533,33 @@ void UnlockManager::Load()
|
||||
m_UnlockEntries.push_back( ue );
|
||||
}
|
||||
}
|
||||
|
||||
if (AUTO_LOCK_EDIT_STEPS)
|
||||
{
|
||||
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), s )
|
||||
{
|
||||
// no challenge steps to play: skip.
|
||||
if (SongUtil::GetOneSteps(*s, StepsType_Invalid, Difficulty_Challenge) == NULL)
|
||||
continue;
|
||||
|
||||
// no edit steps to unlock: skip.
|
||||
if (SongUtil::GetOneSteps(*s, StepsType_Invalid, Difficulty_Edit) == NULL)
|
||||
continue;
|
||||
|
||||
// don't add additional songs.
|
||||
if (SONGS_NOT_ADDITIONAL && SONGMAN->WasLoadedFromAdditionalSongs(*s))
|
||||
continue;
|
||||
|
||||
UnlockEntry ue;
|
||||
ue.m_sEntryID = "_edit_" + (*s)->GetSongDir();
|
||||
ue.m_Type = UnlockRewardType_Steps;
|
||||
ue.m_cmd.Load( (*s)->m_sGroupName+"/"+(*s)->GetTranslitFullTitle()+",edit" );
|
||||
ue.m_bRequirePassChallengeSteps = true;
|
||||
|
||||
m_UnlockEntries.push_back(ue);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that we don't have duplicate unlock IDs. This can cause problems
|
||||
// with UnlockCelebrate and with codes.
|
||||
@@ -507,6 +593,30 @@ void UnlockManager::Load()
|
||||
}
|
||||
|
||||
break;
|
||||
case UnlockRewardType_Steps_Type:
|
||||
{
|
||||
e->m_Song.FromSong( SONGMAN->FindSong( e->m_cmd.GetArg(0).s ) );
|
||||
if( !e->m_Song.IsValid() )
|
||||
{
|
||||
LOG->Warn( "Unlock: Cannot find song matching \"%s\"", e->m_cmd.GetArg(0).s.c_str() );
|
||||
break;
|
||||
}
|
||||
|
||||
e->m_dc = StringToDifficulty( e->m_cmd.GetArg(1).s );
|
||||
if( e->m_dc == Difficulty_Invalid )
|
||||
{
|
||||
LOG->Warn( "Unlock: Invalid difficulty \"%s\"", e->m_cmd.GetArg(1).s.c_str() );
|
||||
break;
|
||||
}
|
||||
|
||||
e->m_StepsType = GAMEMAN->StringToStepsType(e->m_cmd.GetArg(2).s);
|
||||
if (e->m_StepsType == StepsType_Invalid)
|
||||
{
|
||||
LOG->Warn( "Unlock: Invalid steps type \"%s\"", e->m_cmd.GetArg(2).s.c_str() );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UnlockRewardType_Course:
|
||||
e->m_Course.FromCourse( SONGMAN->FindCourse(e->m_cmd.GetArg(0).s) );
|
||||
if( !e->m_Course.IsValid() )
|
||||
@@ -529,6 +639,8 @@ void UnlockManager::Load()
|
||||
str += ssprintf( "%s = %f; ", UnlockRequirementToString(j).c_str(), e->m_fRequirement[j] );
|
||||
if( e->m_bRequirePassHardSteps )
|
||||
str += "RequirePassHardSteps; ";
|
||||
if (e->m_bRequirePassChallengeSteps)
|
||||
str += "RequirePassChallengeSteps; ";
|
||||
|
||||
str += ssprintf( "entryID = %s ", e->m_sEntryID.c_str() );
|
||||
str += e->IsLocked()? "locked":"unlocked";
|
||||
@@ -671,6 +783,11 @@ public:
|
||||
static int GetUnlockRewardType( T* p, lua_State *L ) { lua_pushnumber(L, p->m_Type ); return 1; }
|
||||
static int GetRequirement( T* p, lua_State *L ) { UnlockRequirement i = Enum::Check<UnlockRequirement>( L, 1 ); lua_pushnumber(L, p->m_fRequirement[i] ); return 1; }
|
||||
static int GetRequirePassHardSteps( T* p, lua_State *L ){ lua_pushboolean(L, p->m_bRequirePassHardSteps); return 1; }
|
||||
static int GetRequirePassChallengeSteps( T* p, lua_State *L )
|
||||
{
|
||||
lua_pushboolean(L, p->m_bRequirePassChallengeSteps);
|
||||
return 1;
|
||||
}
|
||||
static int GetSong( T* p, lua_State *L )
|
||||
{
|
||||
Song *pSong = p->m_Song.ToSong();
|
||||
@@ -701,6 +818,7 @@ public:
|
||||
|
||||
static int song( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Song; return 0; }
|
||||
static int steps( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Steps; return 0; }
|
||||
static int steps_type(T* p, lua_State *L) { GetArgs(p, L); p->m_Type = UnlockRewardType_Steps_Type; return 0; }
|
||||
static int course( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Course; return 0; }
|
||||
static int mod( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Modifier; return 0; }
|
||||
static int code( T* p, lua_State *L ) { p->m_sEntryID = SArg(1); return 0; }
|
||||
@@ -722,10 +840,12 @@ public:
|
||||
ADD_METHOD( GetUnlockRewardType );
|
||||
ADD_METHOD( GetRequirement );
|
||||
ADD_METHOD( GetRequirePassHardSteps );
|
||||
ADD_METHOD( GetRequirePassChallengeSteps );
|
||||
ADD_METHOD( GetSong );
|
||||
ADD_METHOD( GetCourse );
|
||||
ADD_METHOD( song );
|
||||
ADD_METHOD( steps );
|
||||
ADD_METHOD( steps_type );
|
||||
ADD_METHOD( course );
|
||||
ADD_METHOD( mod );
|
||||
ADD_METHOD( code );
|
||||
|
||||
+22
-13
@@ -16,16 +16,17 @@ class Steps;
|
||||
class Profile;
|
||||
struct lua_State;
|
||||
|
||||
/** @brief What is needed to unlock an item? */
|
||||
enum UnlockRequirement
|
||||
{
|
||||
UnlockRequirement_ArcadePoints,
|
||||
UnlockRequirement_DancePoints,
|
||||
UnlockRequirement_SongPoints,
|
||||
UnlockRequirement_ExtraCleared,
|
||||
UnlockRequirement_ExtraFailed,
|
||||
UnlockRequirement_Toasties,
|
||||
UnlockRequirement_StagesCleared,
|
||||
UnlockRequirement_NumUnlocked,
|
||||
UnlockRequirement_ArcadePoints, /**< Get a certain number of arcade points. */
|
||||
UnlockRequirement_DancePoints, /**< Get a certain number of dance points. */
|
||||
UnlockRequirement_SongPoints, /**< Get a certain number of song points. */
|
||||
UnlockRequirement_ExtraCleared, /**< Pass the extra stage. */
|
||||
UnlockRequirement_ExtraFailed, /**< Fail the extra stage. */
|
||||
UnlockRequirement_Toasties, /**< Get a number of toasties. */
|
||||
UnlockRequirement_StagesCleared, /**< Clear a number of stages. */
|
||||
UnlockRequirement_NumUnlocked, /**< Have a number of locked items already unlocked. */
|
||||
NUM_UnlockRequirement,
|
||||
UnlockRequirement_Invalid,
|
||||
};
|
||||
@@ -33,10 +34,11 @@ LuaDeclareType( UnlockRequirement );
|
||||
|
||||
|
||||
enum UnlockRewardType {
|
||||
UnlockRewardType_Song,
|
||||
UnlockRewardType_Steps,
|
||||
UnlockRewardType_Course,
|
||||
UnlockRewardType_Modifier,
|
||||
UnlockRewardType_Song, /**< A song is unlocked. */
|
||||
UnlockRewardType_Steps, /**< A step pattern for all styles is unlocked. */
|
||||
UnlockRewardType_Steps_Type, /**< A step pattern for a specific style is unlocked. */
|
||||
UnlockRewardType_Course, /**< A course is unlocked. */
|
||||
UnlockRewardType_Modifier, /**< A modifier is unlocked. */
|
||||
NUM_UnlockRewardType,
|
||||
UnlockRewardType_Invalid
|
||||
};
|
||||
@@ -60,7 +62,8 @@ public:
|
||||
* if not specified. */
|
||||
UnlockEntry(): m_Type(UnlockRewardType_Invalid), m_cmd(),
|
||||
m_Song(), m_dc(Difficulty_Invalid), m_Course(),
|
||||
m_bRequirePassHardSteps(false), m_bRoulette(false),
|
||||
m_StepsType(StepsType_Invalid), m_bRequirePassHardSteps(false),
|
||||
m_bRequirePassChallengeSteps(false), m_bRoulette(false),
|
||||
m_sEntryID(RString(""))
|
||||
{
|
||||
ZERO( m_fRequirement );
|
||||
@@ -74,9 +77,13 @@ public:
|
||||
SongID m_Song;
|
||||
Difficulty m_dc;
|
||||
CourseID m_Course;
|
||||
StepsType m_StepsType;
|
||||
|
||||
float m_fRequirement[NUM_UnlockRequirement]; // unlocked if any of of these are met
|
||||
/** @brief Must the hard steps be passed to unlock a higher level? */
|
||||
bool m_bRequirePassHardSteps;
|
||||
/** @brief Must the challenge steps be passed to unlock a higher level? */
|
||||
bool m_bRequirePassChallengeSteps;
|
||||
bool m_bRoulette;
|
||||
RString m_sEntryID;
|
||||
|
||||
@@ -117,6 +124,7 @@ public:
|
||||
float PointsUntilNextUnlock( UnlockRequirement t ) const;
|
||||
int SongIsLocked( const Song *pSong ) const;
|
||||
bool StepsIsLocked( const Song *pSong, const Steps *pSteps ) const;
|
||||
bool StepsTypeIsLocked( const Song *pSong, const Steps *pSteps, const StepsType *pSType ) const;
|
||||
int CourseIsLocked( const Course *course ) const;
|
||||
bool ModifierIsLocked( const RString &sOneMod ) const;
|
||||
|
||||
@@ -153,6 +161,7 @@ public:
|
||||
|
||||
const UnlockEntry *FindSong( const Song *pSong ) const;
|
||||
const UnlockEntry *FindSteps( const Song *pSong, const Steps *pSteps ) const;
|
||||
const UnlockEntry *FindStepsType( const Song *pSong, const Steps *pSteps, const StepsType *pSType ) const;
|
||||
const UnlockEntry *FindCourse( const Course *pCourse ) const;
|
||||
const UnlockEntry *FindModifier( const RString &sOneMod ) const;
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ void ArchHooks::MountInitialFilesystems( const RString &sDirOfExecutable )
|
||||
const char *szHome = getenv( "HOME" );
|
||||
RString sProductId = PRODUCT_ID;
|
||||
sProductId.MakeLower();
|
||||
RString sUserDataPath = ssprintf( "%s/.%s", szHome? szHome:".", sProductId.c_str() );
|
||||
RString sUserDataPath = ssprintf( "%s/.%s", szHome? szHome:".", "stepmania5" );
|
||||
FILEMAN->Mount( "dir", sUserDataPath + "/Cache", "/Cache" );
|
||||
FILEMAN->Mount( "dir", sUserDataPath + "/Logs", "/Logs" );
|
||||
FILEMAN->Mount( "dir", sUserDataPath + "/Save", "/Save" );
|
||||
|
||||
@@ -206,7 +206,7 @@ void RunChild()
|
||||
WriteToChild( hToStdin, &g_CrashInfo, sizeof(g_CrashInfo) );
|
||||
|
||||
// 2. Write info.
|
||||
const char *p = RageLog::GetInfo();
|
||||
const TCHAR *p = RageLog::GetInfo();
|
||||
int iSize = strlen( p );
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
WriteToChild( hToStdin, p, iSize );
|
||||
@@ -219,7 +219,7 @@ void RunChild()
|
||||
|
||||
// 4. Write RecentLogs.
|
||||
int cnt = 0;
|
||||
const char *ps[1024];
|
||||
const TCHAR *ps[1024];
|
||||
while( cnt < 1024 && (ps[cnt] = RageLog::GetRecentLog( cnt )) != NULL )
|
||||
++cnt;
|
||||
|
||||
@@ -232,7 +232,7 @@ void RunChild()
|
||||
}
|
||||
|
||||
// 5. Write CHECKPOINTs.
|
||||
static char buf[1024*32];
|
||||
static TCHAR buf[1024*32];
|
||||
Checkpoints::GetLogs( buf, sizeof(buf), "$$" );
|
||||
iSize = strlen( buf )+1;
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
@@ -255,7 +255,7 @@ void RunChild()
|
||||
if( !ReadFile( hFromStdout, &hMod, sizeof(hMod), &iActual, NULL) )
|
||||
break;
|
||||
|
||||
char szName[MAX_PATH];
|
||||
TCHAR szName[MAX_PATH];
|
||||
if( !CrashGetModuleBaseName(hMod, szName) )
|
||||
strcpy( szName, "???" );
|
||||
iSize = strlen( szName );
|
||||
|
||||
Reference in New Issue
Block a user