[opengl] merge (part 1?)

This commit is contained in:
Colby Klein
2011-03-16 23:27:50 -07:00
1907 changed files with 435325 additions and 434234 deletions
+23
View File
@@ -0,0 +1,23 @@
[patterns]
**.cpp = native
**.h = native
**.mm = native
**.txt = native
**.lua = native
**.sln = CRLF
**.ini = native
**.redir = native
**.sm = native
**.ssc = native
**.vcproj = CRLF
**.xsl = native
**.xml = native
**.jpg = BIN
**.png = BIN
**.jpeg = BIN
**.ogg = BIN
**.mp3 = BIN
**.wav = BIN
**.sh = LF
Makefile = LF
Makefile.am = LF
+22
View File
@@ -4,6 +4,7 @@ syntax: glob
*~
*.o
tests/*.err
ffmpeg-*
*.ncb
*.suo
*.obj
@@ -20,11 +21,26 @@ ___*
.cvsignore
.DS_Store
Thumbs.db
config.log
config.status
*.pbxuser
*.user
*.mode1v3
*.exe
*.vdi
Makefile
stepmania
Makefile.in
_build/*
aclocal.m4
autoconf/*
autom4te.cache/*
configure
src/Makefile.in
src/Makefile
src/config.h
src/config.h.in
src/stamp-h1
Docs/doxygen
PBProject/build
Xcode/build
@@ -38,6 +54,9 @@ src/libtommath/build-*
src/libtommath/Release-*
src/*.old
src/.deps
src/*.a
src/*.so
GtkModule.so
ver.cpp
lib*_link.a
Data/UserPrefs
@@ -60,3 +79,6 @@ Utils/temp*
syntax: regexp
.*\#.*\#$
glob:Cache/Banners/AdditionalSongs_Airspace Preview_Derailed_Derailed bn.png
syntax: regexp
Songs/.+/
+5
View File
@@ -13,6 +13,11 @@ _____________________________________________________________________________
sm-ssc v1.2.4 | 20110???
--------------------------------------------------------------------------------
20110316
--------
* [NotesLoaderSMA] Allow for preliminary support of loading SMA files. This
will become better once Split Timing is in place. [Wolfman2000]
20110313
--------
* [NotesWriterSM] Allow for either the #DESCRIPTION or #CREDIT tags to be used
+2 -1
View File
@@ -1,4 +1,4 @@
[Common]
[Common]
WindowTitle=StepMania
StepMania=StepMania
@@ -2319,3 +2319,4 @@ UnknownPreference=Unknown preference "%s"
ChoicesSizeMismatch=Choices and Values have different sizes (%d, %d)
NoDefaultInValues=Preference "%s" has no values matching default
TypeMismatch=Type mismatch between default (%s) and value %d (%s)
>>>>>>> other
+1 -1
View File
@@ -1023,7 +1023,7 @@ TapJudgmentsUnderField=false
HoldJudgmentsUnderField=false
ComboUnderField=ComboUnderField()
PenalizeTapScoreNone=false
JudgeHoldNotesOnSameRowTogether=(GAMESTATE:GetCurrentGame():GetName() == "pump")
JudgeHoldNotesOnSameRowTogether=false
HoldCheckpoints=(GAMESTATE:GetCurrentGame():GetName() == "pump")
CheckpointsUseTickcounts=(GAMESTATE:GetCurrentGame():GetName() == "pump")
; deprecated?
+38 -22
View File
@@ -25,6 +25,8 @@
1215D7A208C6559A00B87D8B /* ScreenGameplayNormal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1215D7A008C6559A00B87D8B /* ScreenGameplayNormal.cpp */; };
2B30D6821315EA7E00044B68 /* MouseDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B30D6801315EA7E00044B68 /* MouseDevice.cpp */; };
2B30D6831315EA7E00044B68 /* MouseDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B30D6811315EA7E00044B68 /* MouseDevice.h */; };
2B76698B132FF71500586512 /* NotesLoaderSMA.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B766989132FF71500586512 /* NotesLoaderSMA.h */; };
2B76698C132FF71500586512 /* NotesLoaderSMA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B76698A132FF71500586512 /* NotesLoaderSMA.cpp */; };
2BA7925E1304F20D002BD8E1 /* NotesLoaderSSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7925A1304F20D002BD8E1 /* NotesLoaderSSC.cpp */; };
2BA7925F1304F20D002BD8E1 /* NotesLoaderSSC.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */; };
2BA792601304F20D002BD8E1 /* NotesWriterSSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */; };
@@ -1774,6 +1776,8 @@
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
2B30D6801315EA7E00044B68 /* MouseDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseDevice.cpp; sourceTree = "<group>"; };
2B30D6811315EA7E00044B68 /* MouseDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MouseDevice.h; sourceTree = "<group>"; };
2B766989132FF71500586512 /* NotesLoaderSMA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderSMA.h; path = ../src/NotesLoaderSMA.h; sourceTree = SOURCE_ROOT; };
2B76698A132FF71500586512 /* NotesLoaderSMA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderSMA.cpp; path = ../src/NotesLoaderSMA.cpp; sourceTree = SOURCE_ROOT; };
2BA7925A1304F20D002BD8E1 /* NotesLoaderSSC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderSSC.cpp; path = ../src/NotesLoaderSSC.cpp; sourceTree = SOURCE_ROOT; };
2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderSSC.h; path = ../src/NotesLoaderSSC.h; sourceTree = SOURCE_ROOT; };
2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesWriterSSC.cpp; path = ../src/NotesWriterSSC.cpp; sourceTree = SOURCE_ROOT; };
@@ -3153,6 +3157,7 @@
AA6EFDC804770AF1005F316C /* DataStructures */,
AA6EFE5704770C7E005F316C /* FileTypes */,
AA6E00FE047711FF005F316C /* GlobalSingletons */,
2B766980132FF62B00586512 /* NoteParsing */,
29B97315FDCFA39411CA2CEA /* Other Source */,
AA8B6C7804AFD82B00D02EE9 /* pcre */,
AA6EFDBB04770A83005F316C /* Rage */,
@@ -3200,6 +3205,37 @@
name = Frameworks;
sourceTree = "<group>";
};
2B766980132FF62B00586512 /* NoteParsing */ = {
isa = PBXGroup;
children = (
AA6EFDED04770C79005F316C /* NotesLoader.cpp */,
AA6EFDEE04770C79005F316C /* NotesLoader.h */,
AA6EFDEF04770C79005F316C /* NotesLoaderBMS.cpp */,
AA6EFDF004770C79005F316C /* NotesLoaderBMS.h */,
AA6EFDF104770C79005F316C /* NotesLoaderDWI.cpp */,
AA6EFDF204770C79005F316C /* NotesLoaderDWI.h */,
AA6EFDF304770C79005F316C /* NotesLoaderKSF.cpp */,
AA6EFDF404770C79005F316C /* NotesLoaderKSF.h */,
3688B8510BD42DAA004186AD /* NotesLoaderMidi.cpp */,
3688B8520BD42DAA004186AD /* NotesLoaderMidi.h */,
EE2153A710A75BEE0074B01B /* NotesLoaderPMS.cpp */,
EE2153A810A75BEE0074B01B /* NotesLoaderPMS.h */,
AA6EFDF504770C79005F316C /* NotesLoaderSM.cpp */,
AA6EFDF604770C79005F316C /* NotesLoaderSM.h */,
2B76698A132FF71500586512 /* NotesLoaderSMA.cpp */,
2B766989132FF71500586512 /* NotesLoaderSMA.h */,
2BA7925A1304F20D002BD8E1 /* NotesLoaderSSC.cpp */,
2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */,
AA6EFDF704770C79005F316C /* NotesWriterDWI.cpp */,
AA6EFDF804770C79005F316C /* NotesWriterDWI.h */,
AA6EFDF904770C79005F316C /* NotesWriterSM.cpp */,
AA6EFDFA04770C79005F316C /* NotesWriterSM.h */,
2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */,
2BA7925D1304F20D002BD8E1 /* NotesWriterSSC.h */,
);
name = NoteParsing;
sourceTree = "<group>";
};
AA60E0BB067992D7008ADC41 /* Threads */ = {
isa = PBXGroup;
children = (
@@ -3774,28 +3810,6 @@
AA4F38C104E2D0B700D02EE9 /* NoteDataUtil.h */,
AA6EFDE704770C79005F316C /* NoteDataWithScoring.cpp */,
AA6EFDE804770C79005F316C /* NoteDataWithScoring.h */,
AA6EFDED04770C79005F316C /* NotesLoader.cpp */,
AA6EFDEE04770C79005F316C /* NotesLoader.h */,
AA6EFDEF04770C79005F316C /* NotesLoaderBMS.cpp */,
AA6EFDF004770C79005F316C /* NotesLoaderBMS.h */,
AA6EFDF104770C79005F316C /* NotesLoaderDWI.cpp */,
AA6EFDF204770C79005F316C /* NotesLoaderDWI.h */,
AA6EFDF304770C79005F316C /* NotesLoaderKSF.cpp */,
AA6EFDF404770C79005F316C /* NotesLoaderKSF.h */,
3688B8510BD42DAA004186AD /* NotesLoaderMidi.cpp */,
3688B8520BD42DAA004186AD /* NotesLoaderMidi.h */,
EE2153A710A75BEE0074B01B /* NotesLoaderPMS.cpp */,
EE2153A810A75BEE0074B01B /* NotesLoaderPMS.h */,
AA6EFDF504770C79005F316C /* NotesLoaderSM.cpp */,
AA6EFDF604770C79005F316C /* NotesLoaderSM.h */,
2BA7925A1304F20D002BD8E1 /* NotesLoaderSSC.cpp */,
2BA7925B1304F20D002BD8E1 /* NotesLoaderSSC.h */,
AA6EFDF704770C79005F316C /* NotesWriterDWI.cpp */,
AA6EFDF804770C79005F316C /* NotesWriterDWI.h */,
AA6EFDF904770C79005F316C /* NotesWriterSM.cpp */,
AA6EFDFA04770C79005F316C /* NotesWriterSM.h */,
2BA7925C1304F20D002BD8E1 /* NotesWriterSSC.cpp */,
2BA7925D1304F20D002BD8E1 /* NotesWriterSSC.h */,
AA6EFDFB04770C79005F316C /* NoteTypes.cpp */,
AA6EFDFC04770C79005F316C /* NoteTypes.h */,
AA80C75707F20D6600C99272 /* OptionRowHandler.cpp */,
@@ -4944,6 +4958,7 @@
2B30D6831315EA7E00044B68 /* MouseDevice.h in Headers */,
EE879B61132DEE720078FDDC /* RageDisplay_Legacy_Helpers.h in Headers */,
EE879B63132DEE720078FDDC /* RageDisplay_Legacy.h in Headers */,
2B76698B132FF71500586512 /* NotesLoaderSMA.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -6187,6 +6202,7 @@
EE879B60132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp in Sources */,
EE879B62132DEE720078FDDC /* RageDisplay_Legacy.cpp in Sources */,
EE879BC3132E06C50078FDDC /* glew.c in Sources */,
2B76698C132FF71500586512 /* NotesLoaderSMA.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+2 -1
View File
@@ -37,7 +37,7 @@ void Foreground::LoadFromSong( const Song *pSong )
LoadedBGA bga;
bga.m_bga = ActorUtil::MakeActor( pSong->GetSongDir() + sBGName, this );
bga.m_bga->PlayCommand( "On" );
bga.m_bga->PlayCommand( "Init" );
bga.m_fStartBeat = change.m_fStartBeat;
bga.m_bFinished = false;
@@ -80,6 +80,7 @@ void Foreground::Update( float fDeltaTime )
if( !bga.m_bga->GetVisible() )
{
bga.m_bga->SetVisible( true );
bga.m_bga->PlayCommand( "On" );
const float fStartSecond = m_pSong->m_Timing.GetElapsedTimeFromBeat( bga.m_fStartBeat );
lDeltaTime = GAMESTATE->m_fMusicSeconds - fStartSecond;
+2 -2
View File
@@ -415,8 +415,8 @@ void GameCommand::LoadOne( const Command& cmd )
if( cmd.m_vsArgs.size() == 3 )
{
m_bFadeMusic = true;
m_fMusicFadeOutVolume = (float)atof( cmd.m_vsArgs[1] );
m_fMusicFadeOutSeconds = (float)atof( cmd.m_vsArgs[2] );
m_fMusicFadeOutVolume = atof( cmd.m_vsArgs[1] );
m_fMusicFadeOutSeconds = atof( cmd.m_vsArgs[2] );
}
}
+11
View File
@@ -7,6 +7,7 @@
#include "GameState.h"
#include "TimingData.h"
#include "NotesLoaderSSC.h"
#include "NotesLoaderSM.h"
#include "PrefsManager.h"
#include "RageDisplay.h"
#include "AnnouncerManager.h"
@@ -150,6 +151,15 @@ static void StartMusic( MusicToPlay &ToPlay )
if( pStepsCabinetLights )
pStepsCabinetLights->GetNoteData( ToPlay.m_LightsData );
}
else if( SMLoader::LoadFromSMFile(ToPlay.m_sTimingFile, song) )
{
ToPlay.HasTiming = true;
ToPlay.m_TimingData = song.m_Timing;
// get cabinet lights if any
Steps *pStepsCabinetLights = SongUtil::GetOneSteps( &song, StepsType_lights_cabinet );
if( pStepsCabinetLights )
pStepsCabinetLights->GetNoteData( ToPlay.m_LightsData );
}
}
if( ToPlay.HasTiming )
@@ -704,6 +714,7 @@ void GameSoundManager::PlayMusic( PlayMusicParams params, PlayMusicParams Fallba
else
{
/* If no timing data was provided, look for it in the same place as the music file. */
// todo: allow loading .ssc files as well -aj
ToPlay.m_sTimingFile = SetExtension( params.sFile, "sm" );
}
+11
View File
@@ -100,6 +100,7 @@ InputFilter::InputFilter()
m_MouseCoords.fX = 0;
m_MouseCoords.fY = 0;
m_MouseCoords.fZ = 0;
// Register with Lua.
{
@@ -415,6 +416,10 @@ void InputFilter::UpdateCursorLocation(float _fX, float _fY)
m_MouseCoords.fY = _fY;
}
void InputFilter::UpdateMouseWheel(float _fZ)
{
m_MouseCoords.fZ = _fZ;
}
// lua start
#include "LuaBinding.h"
@@ -439,11 +444,17 @@ public:
lua_pushnumber( L, fY );
return 1;
}
static int GetMouseWheel( T* p, lua_State *L ){
float fZ = p->GetMouseWheel();
lua_pushnumber( L, fZ );
return 1;
}
LunaInputFilter()
{
ADD_METHOD( GetMouseX );
ADD_METHOD( GetMouseY );
ADD_METHOD( GetMouseWheel );
}
};
+3
View File
@@ -37,6 +37,7 @@ struct MouseCoordinates
{
float fX;
float fY;
float fZ;
};
class RageMutex;
@@ -70,8 +71,10 @@ public:
// cursor
void UpdateCursorLocation(float _fX, float _fY);
void UpdateMouseWheel(float _fZ);
float GetCursorX(){ return m_MouseCoords.fX; }
float GetCursorY(){ return m_MouseCoords.fY; }
float GetMouseWheel(){ return m_MouseCoords.fZ; }
// Lua
void PushSelf( lua_State *L );
+2 -1
View File
@@ -147,7 +147,8 @@ NoteTypes.cpp NoteTypes.h NotesLoader.cpp NotesLoader.h \
NotesLoaderBMS.cpp NotesLoaderBMS.h NotesLoaderDWI.cpp NotesLoaderDWI.h \
NotesLoaderKSF.cpp NotesLoaderKSF.h NotesLoaderMidi.cpp NotesLoaderMidi.h \
NotesLoaderPMS.cpp NotesLoaderPMS.h NotesLoaderSM.cpp NotesLoaderSM.h \
NotesLoaderSSC.cpp NotesLoaderSSC.h NotesWriterDWI.cpp NotesWriterDWI.h \
NotesLoaderSSC.cpp NotesLoaderSSC.h NotesLoaderSMA.cpp NotesLoaderSMA.h \
NotesWriterDWI.cpp NotesWriterDWI.h \
NotesWriterSM.cpp NotesWriterSM.h NotesWriterSSC.cpp NotesWriterSSC.h \
OptionRowHandler.cpp OptionRowHandler.h OptionsList.cpp OptionsList.h \
PlayerAI.cpp PlayerAI.h PlayerNumber.cpp PlayerNumber.h PlayerOptions.cpp PlayerOptions.h \
+1 -3
View File
@@ -1,9 +1,7 @@
/** @brief MsdFile - Read .SSC, .SM, .DWI, and .MSD files. */
#ifndef MSDFILE_H
#define MSDFILE_H
/** @brief The class that reads the various .SSC, .SM, .DWI, and .MSD files. */
/** @brief The class that reads the various .SSC, .SM, .SMA, .DWI, and .MSD files. */
class MsdFile
{
public:
+53 -2
View File
@@ -561,6 +561,40 @@ void NoteDataUtil::LoadTransformedSlidingWindow( const NoteData &in, NoteData &o
}
}
void PlaceAutoKeysound( NoteData &out, int row, TapNote akTap )
{
int iEmptyTrack = -1;
int iEmptyRow = row;
int iNewNumTracks = out.GetNumTracks();
bool bFoundEmptyTrack = false;
int iRowsToLook[3] = {0, -1, 1};
for( int j = 0; j < 3; j ++ )
{
int r = iRowsToLook[j] + row;
if( r < 0 )
continue;
for( int i = 0; i < iNewNumTracks; ++i )
{
if ( out.GetTapNote(i, r) == TAP_EMPTY && !out.IsHoldNoteAtRow(i, r) )
{
iEmptyTrack = i;
iEmptyRow = r;
bFoundEmptyTrack = true;
break;
}
}
if( bFoundEmptyTrack )
break;
}
if( iEmptyTrack != -1 )
{
akTap.type = TapNote::autoKeysound;
out.SetTapNote( iEmptyTrack, iEmptyRow, akTap );
}
}
void NoteDataUtil::LoadOverlapped( const NoteData &in, NoteData &out, int iNewNumTracks )
{
out.SetNumTracks( iNewNumTracks );
@@ -587,7 +621,7 @@ void NoteDataUtil::LoadOverlapped( const NoteData &in, NoteData &out, int iNewNu
for( int iTrackFrom = 0; iTrackFrom < in.GetNumTracks(); ++iTrackFrom )
{
const TapNote &tnFrom = in.GetTapNote( iTrackFrom, row );
if( tnFrom.type == TapNote::empty )
if( tnFrom.type == TapNote::empty || tnFrom.type == TapNote::autoKeysound )
continue;
// If this is a hold note, find the end.
@@ -609,8 +643,16 @@ void NoteDataUtil::LoadOverlapped( const NoteData &in, NoteData &out, int iNewNu
// If it's still in use, then we just don't have an available track.
if( iEndIndex - LastSourceRow[iTrackTo] < ShiftThreshold )
{
// If it has a keysound, put it in autokeysound track.
if( tnFrom.iKeysoundIndex >= 0 )
{
TapNote akTap = tnFrom;
PlaceAutoKeysound( out, row, akTap );
}
continue;
}
}
LastSourceTrack[iTrackTo] = iTrackFrom;
LastSourceRow[iTrackTo] = iEndIndex;
@@ -621,6 +663,16 @@ void NoteDataUtil::LoadOverlapped( const NoteData &in, NoteData &out, int iNewNu
out.SetTapNote( iTrackTo, iEndIndex, tnTail );
}
}
// find empty track for autokeysounds in 2 next rows, so you can hear most autokeysounds
for( int iTrackFrom = 0; iTrackFrom < in.GetNumTracks(); ++iTrackFrom )
{
const TapNote &tnFrom = in.GetTapNote( iTrackFrom, row );
if( tnFrom.type != TapNote::autoKeysound )
continue;
PlaceAutoKeysound( out, row, tnFrom );
}
}
}
@@ -1389,7 +1441,6 @@ void NoteDataUtil::Little( NoteData &inout, int iStartIndex, int iEndIndex )
{
if( i % ROWS_PER_BEAT == 0 )
continue;
inout.SetTapNote( t, i, TAP_EMPTY );
}
}
+6
View File
@@ -1,6 +1,7 @@
#include "global.h"
#include "NotesLoader.h"
#include "NotesLoaderSM.h"
#include "NotesLoaderSMA.h"
#include "NotesLoaderSSC.h"
#include "NotesLoaderDWI.h"
#include "NotesLoaderBMS.h"
@@ -42,6 +43,11 @@ bool NotesLoader::LoadFromDir( const RString &sPath, Song &out, set<RString> &Bl
SMLoader::GetApplicableFiles( sPath, list );
if (!list.empty() )
return SMLoader::LoadFromDir( sPath, out );
#if defined(_MSC_VER) || defined(MACOSX)
SMALoader::GetApplicableFiles( sPath, list );
if (!list.empty() )
return SMALoader::LoadFromDir( sPath, out );
#endif
DWILoader::GetApplicableFiles( sPath, list );
if( !list.empty() )
return DWILoader::LoadFromDir( sPath, out, BlacklistedImages );
+97 -104
View File
@@ -182,6 +182,7 @@ static StepsType DetermineStepsType( int iPlayer, const NoteData &nd, const RStr
// are more common.
//return StepsType_dance_solo;
return StepsType_beat_single5;
case 7:
case 8: return StepsType_beat_single7;
case 9: return StepsType_popn_nine;
default: return StepsType_Invalid;
@@ -404,8 +405,37 @@ static void SetTimeSigAdjustments( const MeasureToTimeSig_t &sigs, Song &out, Me
static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t &out )
{
// some convertors change some measure's time signature before any notes are there
// it is required because sometimes the BGA starts before the music and the measure size
// is the difference between the start of first bar and the BGA.
// something like #00002:1.55. that made all subsequent notes 192th.
// here, find the lowest measure for notes, and make this function skip the time signatures before it.
int iStartMeasureNo = 999;
NameToData_t::const_iterator it;
for( it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it )
{
const RString &sName = it->first;
if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1,5) ) )
continue;
// this is step or offset data. Looks like "#00705"
int iMeasureNo = atoi( sName.substr(1, 3).c_str() );
int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() );
RString nData = it->second;
int totalPairs = nData.size() / 2;
if( iBMSTrackNo != BMS_TRACK_TIME_SIG && iBMSTrackNo != 7 )
{
for( int i = 0; i < totalPairs; ++i )
{
RString sPair = nData.substr( i*2, 2 );
if (sPair == "00")
{
continue;
}
if( iMeasureNo < iStartMeasureNo ) iStartMeasureNo = iMeasureNo;
}
}
}
for( it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it )
{
const RString &sName = it->first;
if( sName.size() != 6 || sName[0] != '#' || !IsAnInt(sName.substr(1, 5)) )
@@ -414,6 +444,8 @@ static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t
// this is step or offset data. Looks like "#00705"
const RString &sData = it->second;
int iMeasureNo = atoi( sName.substr(1, 3).c_str() );
if( iMeasureNo < iStartMeasureNo )
continue;
int iBMSTrackNo = atoi( sName.substr(4, 2).c_str() );
if( iBMSTrackNo == BMS_TRACK_TIME_SIG )
out[iMeasureNo] = StringToFloat( sData );
@@ -494,8 +526,8 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
int row = iRowNo + lrintf( fPercentThroughMeasure * fBeatsPerMeasure * ROWS_PER_BEAT );
// some BMS files seem to have funky alignment, causing us to write gigantic cache files.
// Try to correct for this by quantizing.
row = Quantize( row, ROWS_PER_MEASURE/64 );
// Try to correct for this by quantizing. // not always
// row = Quantize( row, ROWS_PER_MEASURE/64 );
BmsTrack bmsTrack;
bool bIsHold;
@@ -520,33 +552,10 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
continue;
}
}
/* This handles the hold notes in the RDM TYPE 1 style,
* like how uBMplay handles it. Different BMS simulators
* support hold notes differently. see
* http://nvyu.net/rdm/ex.php for more info. */
else if( iHoldStarts[bmsTrack] != -1 )
{
// This is ending a hold.
const int iBegin = iHoldStarts[bmsTrack];
const int iEnd = row;
if( iBegin < iEnd )
{
TapNote &noteHead = TAP_ORIGINAL_HOLD_HEAD;
noteHead.iKeysoundIndex = iHoldHeads[bmsTrack].iKeysoundIndex;
ndNotes.AddHoldNote( bmsTrack, iBegin, iEnd, noteHead );
}
else
{
ndNotes.SetTapNote( bmsTrack, iBegin, iHoldHeads[bmsTrack] );
}
iHoldStarts[bmsTrack] = -1;
}
else if( bIsHold )
{
// Start of a hold.
iHoldStarts[bmsTrack] = row;
iHoldHeads[bmsTrack] = tn;
continue;
tn.type = TapNote::hold_head;
tn.subType = TapNote::hold_head_hold;
}
}
// Don't bother inserting empty taps.
@@ -556,6 +565,45 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
}
}
/* Handles hold notes like uBMPlay.
* Different BMS simulators support hold notes differently.
* See http://nvyu.net/rdm/ex.php for more info.
*/
for( int t=BMS_P1_KEY1; t<=BMS_P2_KEY7; t++ )
{
int iHoldHeadRow = -1;
TapNote tnHoldHead;
FOREACH_NONEMPTY_ROW_IN_TRACK( ndNotes, t, row )
{
TapNote tn = ndNotes.GetTapNote( t, row );
if ( tn.type == TapNote::hold_head || tn.type == TapNote::tap )
{
if ( iHoldHeadRow != -1 )
{
// Delete head and tail, and add the hold note there.
ndNotes.SetTapNote( t, row, TAP_EMPTY );
ndNotes.SetTapNote( t, iHoldHeadRow, TAP_EMPTY );
if ( iHoldHeadRow < row )
{
ndNotes.AddHoldNote( t, iHoldHeadRow, row, tnHoldHead );
}
iHoldHeadRow = -1;
}
else if ( tn.type == TapNote::hold_head )
{
// Head of the hold note, store it to find the tail.
iHoldHeadRow = row;
tnHoldHead = tn;
// Replace with a tap note.
tn.type = TapNote::tap;
tn.subType = TapNote::SubType_Invalid;
ndNotes.SetTapNote( t, row, tn );
}
}
}
}
out.m_StepsType = DetermineStepsType( iPlayer, ndNotes, sPath );
if( out.m_StepsType == StepsType_beat_single5 && GetTagFromMap( mapNameToData, "#title", sData ) )
{
@@ -683,9 +731,12 @@ static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameTo
{
TapNote tn = ndNotes.GetTapNote( t, row );
int iEmptyTrack = -1;
for ( int i=0; i<iNumNewTracks; i++ ) {
if ( ndNotes.GetTapNote(iTransformNewToOld[i], row) == TAP_EMPTY ) {
for( int i=0; i<iNumNewTracks; i++ )
{
if ( ndNotes.GetTapNote(iTransformNewToOld[i], row) == TAP_EMPTY )
{
iEmptyTrack = iTransformNewToOld[i];
break;
}
}
if( iEmptyTrack > -1 )
@@ -765,6 +816,11 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
RString nData = it->second;
RString sWavID = sName.Right(2);
// FIXME: garbled song names seem to crash the app.
// this might not be the best place to put this code.
if( !utf8_is_valid(nData) )
continue;
/* Due to bugs in some programs, many BMS files have a "WAV" extension
* on files in the BMS for files that actually have some other extension.
* Do a search. Don't do a wildcard search; if sData is "song.wav",
@@ -813,12 +869,15 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
{
RString sPair = nData.substr( i*2, 2 );
int iVal = 0;
if( sscanf( sPair, "%x", &iVal ) == 0 || iVal == 0 )
continue;
int iRow = iStepIndex + (i * iRowsPerMeasure) / totalPairs;
float fBeat = NoteRowToBeat( iRow );
int iVal = 0;
sscanf( sPair, "%x", &iVal );
if (sPair == "00")
{
continue;
}
switch( iBMSTrackNo )
{
@@ -842,30 +901,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) )
{
float fBPM = StringToFloat( sBPM );
if( PREFSMAN->m_bQuirksMode )
{
BPMSegment newSeg( BeatToNoteRow(fBeat), fBPM );
out.AddBPMSegment( newSeg );
if( fBPM > 0.0f )
LOG->Trace( "Inserting new positive BPM change at beat %f, BPM %f", fBeat, newSeg.GetBPM() );
else
LOG->Trace( "Inserting new negative BPM change at beat %f, BPM %f", fBeat, newSeg.GetBPM() );
}
else
{
if( fBPM > 0.0f )
{
BPMSegment newSeg( BeatToNoteRow(fBeat), fBPM );
out.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg.GetBPM() );
}
else
{
LOG->UserLog( "Song file", out.GetSongDir(), "has an invalid BPM change at beat %f, BPM %f",
fBeat, fBPM );
}
}
out.SetBPMAtBeat( fBeat, fBPM );
}
else
{
@@ -875,6 +911,10 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
}
case BMS_TRACK_STOP:
{
if( iVal == 0 )
{
break;
}
RString sTagToLookFor = ssprintf( "#stop%02x", iVal );
RString sBeats;
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBeats ) )
@@ -897,53 +937,6 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
}
}
switch( iBMSTrackNo )
{
case BMS_TRACK_BPM_REF:
{
// XXX: offset
int iBPMNo;
sscanf( sData, "%x", &iBPMNo ); // data is in hexadecimal
RString sBPM;
RString sTagToLookFor = ssprintf( "#bpm%02x", iBPMNo );
if( GetTagFromMap( mapNameToData, sTagToLookFor, sBPM ) )
{
float fBPM = StringToFloat( sBPM );
if( PREFSMAN->m_bQuirksMode )
{
BPMSegment newSeg( iStepIndex, fBPM );
out.AddBPMSegment( newSeg );
if( fBPM > 0.0f )
LOG->Trace( "Inserting new positive BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartRow), newSeg.GetBPM() );
else
LOG->Trace( "Inserting new negative BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartRow), newSeg.GetBPM() );
}
else
{
if( fBPM > 0.0f )
{
BPMSegment newSeg( iStepIndex, fBPM );
out.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartRow), newSeg.GetBPM() );
}
else
{
LOG->UserLog( "Song file", out.GetSongDir(), "has an invalid BPM change at beat %f, BPM %f.",
NoteRowToBeat(iStepIndex), fBPM );
}
}
}
else
{
LOG->UserLog( "Song file", out.GetSongDir(), "has tag \"%s\" which cannot be found.", sTagToLookFor.c_str() );
}
break;
}
}
}
// Now that we're done reading BPMs, factor out weird time signatures.
+1 -1
View File
@@ -424,7 +424,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
}
}
bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression )
bool SMLoader::LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression )
{
vector<RString> aBGChangeValues;
split( sBGChangeExpression, "=", aBGChangeValues, false );
+2
View File
@@ -2,6 +2,7 @@
#define NotesLoaderSM_H
#include "GameConstantsAndTypes.h"
#include "BackgroundUtil.h"
class MsdFile;
class Song;
@@ -23,6 +24,7 @@ namespace SMLoader
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot );
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression );
}
#endif
+764
View File
@@ -0,0 +1,764 @@
#include "global.h"
#include "NotesLoaderSMA.h"
#include "BackgroundUtil.h"
#include "GameManager.h"
#include "MsdFile.h"
#include "NoteTypes.h"
#include "NotesLoaderSM.h" // may need this.
#include "PrefsManager.h"
#include "RageFileManager.h"
#include "RageLog.h"
#include "RageUtil.h"
#include "Song.h"
#include "SongManager.h"
#include "Steps.h"
/**
* @brief A custom .edit file can only be so big before we have to reject it.
*/
const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60 KB
void SMALoader::LoadFromSMATokens(
RString sStepsType,
RString sDescription,
RString sDifficulty,
RString sMeter,
RString sRadarValues,
RString sNoteData,
Steps &out
)
{
// we're loading from disk, so this is by definition already saved:
out.SetSavedToDisk( true );
Trim( sStepsType );
Trim( sDescription );
Trim( sDifficulty );
Trim( sNoteData );
// LOG->Trace( "Steps::LoadFromSMTokens()" );
// insert stepstype hacks from GameManager.cpp here? -aj
out.m_StepsType = GAMEMAN->StringToStepsType( sStepsType );
out.SetDescription( sDescription );
out.SetCredit( sDescription ); // this is often used for both.
out.SetDifficulty( DwiCompatibleStringToDifficulty(sDifficulty) );
sDescription.MakeLower();
// Handle hacks that originated back when StepMania didn't have
// Difficulty_Challenge. (At least v1.64, possibly v3.0 final...)
if( out.GetDifficulty() == Difficulty_Hard )
{
// HACK: SMANIAC used to be Difficulty_Hard with a special description.
if( sDescription == "smaniac" )
out.SetDifficulty( Difficulty_Challenge );
// HACK: CHALLENGE used to be Difficulty_Hard with a special description.
if( sDescription == "challenge" )
out.SetDifficulty( Difficulty_Challenge );
}
out.SetMeter( atoi(sMeter) );
vector<RString> saValues;
split( sRadarValues, ",", saValues, true );
int categories = NUM_RadarCategory - 1; // Fakes aren't counted in the radar values.
if( saValues.size() == (unsigned)categories * NUM_PLAYERS )
{
RadarValues v[NUM_PLAYERS];
FOREACH_PlayerNumber( pn )
{
// Can't use the foreach anymore due to flexible radar lines.
for( RadarCategory rc = (RadarCategory)0; rc < categories;
enum_add<RadarCategory>( rc, 1 ) )
{
v[pn][rc] = StringToFloat( saValues[pn*categories + rc] );
}
}
out.SetCachedRadarValues( v );
}
out.SetSMNoteData( sNoteData );
out.TidyUpData();
}
bool SMALoader::LoadFromDir( const RString &sPath, Song &out )
{
vector<RString> aFileNames;
GetApplicableFiles( sPath, aFileNames );
if( aFileNames.size() > 1 )
{
LOG->UserLog( "Song", sPath, "has more than one SMA file. There can be only one!" );
return false;
}
ASSERT( aFileNames.size() == 1 );
return LoadFromSMAFile( sPath + aFileNames[0], out );
}
void SMALoader::TidyUpData( Song &song, bool bFromCache )
{
SMLoader::TidyUpData( song, bFromCache );
}
bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
{
LOG->Trace( "Song::LoadFromSMAFile(%s)", sPath.c_str() );
MsdFile msd;
if( !msd.ReadFile( sPath, true ) ) // unescape
{
LOG->UserLog( "Song file", sPath, "couldn't be opened: %s", msd.GetError().c_str() );
return false;
}
out.m_Timing.m_sFile = sPath;
LoadTimingFromSMAFile( msd, out.m_Timing );
for( unsigned i=0; i<msd.GetNumValues(); i++ )
{
int iNumParams = msd.GetNumParams(i);
const MsdFile::value_t &sParams = msd.GetValue(i);
RString sValueName = sParams[0];
sValueName.MakeUpper();
// handle the data
/* Don't use GetMainAndSubTitlesFromFullTitle; that's only for heuristically
* splitting other formats that *don't* natively support #SUBTITLE. */
if( sValueName=="TITLE" )
out.m_sMainTitle = sParams[1];
else if( sValueName=="SUBTITLE" )
out.m_sSubTitle = sParams[1];
else if( sValueName=="ARTIST" )
out.m_sArtist = sParams[1];
else if( sValueName=="TITLETRANSLIT" )
out.m_sMainTitleTranslit = sParams[1];
else if( sValueName=="SUBTITLETRANSLIT" )
out.m_sSubTitleTranslit = sParams[1];
else if( sValueName=="ARTISTTRANSLIT" )
out.m_sArtistTranslit = sParams[1];
else if( sValueName=="GENRE" )
out.m_sGenre = sParams[1];
else if( sValueName=="CREDIT" )
out.m_sCredit = sParams[1];
else if( sValueName=="BANNER" )
out.m_sBannerFile = sParams[1];
else if( sValueName=="BACKGROUND" )
out.m_sBackgroundFile = sParams[1];
// Save "#LYRICS" for later, so we can add an internal lyrics tag.
else if( sValueName=="LYRICSPATH" )
out.m_sLyricsFile = sParams[1];
else if( sValueName=="CDTITLE" )
out.m_sCDTitleFile = sParams[1];
else if( sValueName=="MUSIC" )
out.m_sMusicFile = sParams[1];
else if( sValueName=="INSTRUMENTTRACK" )
{
vector<RString> vs1;
split( sParams[1], ",", vs1 );
FOREACH_CONST( RString, vs1, s )
{
vector<RString> vs2;
split( *s, "=", vs2 );
if( vs2.size() >= 2 )
{
InstrumentTrack it = StringToInstrumentTrack( vs2[0] );
if( it != InstrumentTrack_Invalid )
out.m_sInstrumentTrackFile[it] = vs2[1];
}
}
}
else if( sValueName=="MUSICLENGTH" )
{
continue;
}
else if( sValueName=="LASTBEATHINT" )
out.m_fSpecifiedLastBeat = StringToFloat( sParams[1] );
else if( sValueName=="MUSICBYTES" )
; /* ignore */
/* We calculate these. Some SMs in circulation have bogus values for
* these, so make sure we always calculate it ourself. */
else if( sValueName=="FIRSTBEAT" )
{
;
}
else if( sValueName=="LASTBEAT" )
{
; }
else if( sValueName=="SONGFILENAME" )
{
;
}
else if( sValueName=="HASMUSIC" )
{
;
}
else if( sValueName=="HASBANNER" )
{
;
}
else if( sValueName=="SAMPLESTART" )
out.m_fMusicSampleStartSeconds = HHMMSSToSeconds( sParams[1] );
else if( sValueName=="SAMPLELENGTH" )
out.m_fMusicSampleLengthSeconds = HHMMSSToSeconds( sParams[1] );
// SamplePath is used when the song has a separate preview clip. -aj
//else if( sValueName=="SAMPLEPATH" )
//out.m_sMusicSamplePath = sParams[1];
else if( sValueName=="DISPLAYBPM" )
{
// #DISPLAYBPM:[xxx][xxx:xxx]|[*];
if( sParams[1] == "*" )
out.m_DisplayBPMType = Song::DISPLAY_RANDOM;
else
{
out.m_DisplayBPMType = Song::DISPLAY_SPECIFIED;
out.m_fSpecifiedBPMMin = StringToFloat( sParams[1] );
if( sParams[2].empty() )
out.m_fSpecifiedBPMMax = out.m_fSpecifiedBPMMin;
else
out.m_fSpecifiedBPMMax = StringToFloat( sParams[2] );
}
}
else if( sValueName=="SELECTABLE" )
{
if(!stricmp(sParams[1],"YES"))
out.m_SelectionDisplay = out.SHOW_ALWAYS;
else if(!stricmp(sParams[1],"NO"))
out.m_SelectionDisplay = out.SHOW_NEVER;
// ROULETTE from 3.9. It was removed since UnlockManager can serve
// the same purpose somehow. This, of course, assumes you're using
// unlocks. -aj
else if(!stricmp(sParams[1],"ROULETTE"))
out.m_SelectionDisplay = out.SHOW_ALWAYS;
/* The following two cases are just fixes to make sure simfiles that
* used 3.9+ features are not excluded here */
else if(!stricmp(sParams[1],"ES") || !stricmp(sParams[1],"OMES"))
out.m_SelectionDisplay = out.SHOW_ALWAYS;
else if( atoi(sParams[1]) > 0 )
out.m_SelectionDisplay = out.SHOW_ALWAYS;
else
LOG->UserLog( "Song file", sPath, "has an unknown #SELECTABLE value, \"%s\"; ignored.", sParams[1].c_str() );
}
else if( sValueName.Left(strlen("BGCHANGES"))=="BGCHANGES" || sValueName=="ANIMATIONS" )
{
BackgroundLayer iLayer = BACKGROUND_LAYER_1;
if( sscanf(sValueName, "BGCHANGES%d", &*ConvertValue<int>(&iLayer)) == 1 )
enum_add(iLayer, -1); // #BGCHANGES2 = BACKGROUND_LAYER_2
bool bValid = iLayer>=0 && iLayer<NUM_BackgroundLayer;
if( !bValid )
{
LOG->UserLog( "Song file", sPath, "has a #BGCHANGES tag \"%s\" that is out of range.", sValueName.c_str() );
}
else
{
vector<RString> aBGChangeExpressions;
split( sParams[1], ",", aBGChangeExpressions );
for( unsigned b=0; b<aBGChangeExpressions.size(); b++ )
{
BackgroundChange change;
if( LoadFromBGChangesString( change, aBGChangeExpressions[b] ) )
out.AddBackgroundChange( iLayer, change );
}
}
}
else if( sValueName=="FGCHANGES" )
{
vector<RString> aFGChangeExpressions;
split( sParams[1], ",", aFGChangeExpressions );
for( unsigned b=0; b<aFGChangeExpressions.size(); b++ )
{
BackgroundChange change;
if( LoadFromBGChangesString( change, aFGChangeExpressions[b] ) )
out.AddForegroundChange( change );
}
}
else if( sValueName=="KEYSOUNDS" )
{
split( sParams[1], ",", out.m_vsKeysoundFile );
}
// Attacks loaded from file
else if( sValueName=="ATTACKS" )
{
// 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 )
{
vector<RString> sBits;
split( sParams[j], "=", sBits, false );
// Need an identifer and a value for this to work
if( sBits.size() < 2 )
continue;
TrimLeft( sBits[0] );
TrimRight( sBits[0] );
if( !sBits[0].CompareNoCase("TIME") )
attack.fStartSecond = strtof( sBits[1], NULL );
else if( !sBits[0].CompareNoCase("LEN") )
attack.fSecsRemaining = strtof( sBits[1], NULL );
else if( !sBits[0].CompareNoCase("END") )
end = strtof( sBits[1], NULL );
else if( !sBits[0].CompareNoCase("MODS") )
{
attack.sModifiers = sBits[1];
if( end != -9999 )
{
attack.fSecsRemaining = end - attack.fStartSecond;
end = -9999;
}
if( attack.fSecsRemaining < 0.0f )
attack.fSecsRemaining = 0.0f;
out.m_Attacks.push_back( attack );
}
}
}
else if( sValueName=="NOTES" || sValueName=="NOTES2" )
{
if( iNumParams < 7 )
{
LOG->UserLog( "Song file", sPath, "has %d fields in a #NOTES tag, but should have at least 7.", iNumParams );
continue;
}
Steps* pNewNotes = new Steps;
LoadFromSMATokens(
sParams[1],
sParams[2],
sParams[3],
sParams[4],
sParams[5],
sParams[6],
*pNewNotes );
out.AddSteps( pNewNotes );
}
/*
* We used to check for timing data in this section. That has
* since been moved to a dedicated function.
*/
else if( sValueName=="OFFSET" || sValueName=="BPMS" || sValueName=="STOPS" || sValueName=="FREEZES" || sValueName=="DELAYS" || sValueName=="TIMESIGNATURES" || sValueName=="LEADTRACK" || sValueName=="TICKCOUNTS" )
;
else
LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() );
}
return true;
}
void SMALoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
{
GetDirListing( sPath + RString("*.sma"), out );
}
bool SMALoader::LoadTimingFromFile( const RString &fn, TimingData &out )
{
MsdFile msd;
if( !msd.ReadFile( fn, true ) ) // unescape
{
LOG->UserLog( "Song file", fn, "couldn't be loaded: %s", msd.GetError().c_str() );
return false;
}
out.m_sFile = fn;
LoadTimingFromSMAFile( msd, out );
return true;
}
void SMALoader::LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out )
{
out.m_fBeat0OffsetInSeconds = 0;
out.m_BPMSegments.clear();
out.m_StopSegments.clear();
out.m_WarpSegments.clear();
out.m_vTimeSignatureSegments.clear();
vector<WarpSegment> arrayWarpsFromNegativeBPMs;
//vector<WarpSegment> arrayWarpsFromNegativeStops;
int rowsPerMeasure = 0;
bool encountered = false;
for( unsigned i=0; i<msd.GetNumValues(); i++ )
{
const MsdFile::value_t &sParams = msd.GetValue(i);
RString sValueName = sParams[0];
sValueName.MakeUpper();
if( sValueName=="ROWSPERBEAT")
{
if( encountered )
{
break;
}
encountered = true;
rowsPerMeasure = atoi( sParams[1] );
}
else if( sValueName=="BEATSPERMEASURE" )
{
TimeSignatureSegment new_seg;
new_seg.m_iStartRow = 0;
new_seg.m_iNumerator = atoi( sParams[1] );
new_seg.m_iDenominator = 4;
out.AddTimeSignatureSegment( new_seg );
}
else if( sValueName=="OFFSET" )
{
out.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] );
}
else if( sValueName=="STOPS" )
{
vector<RString> arrayFreezeExpressions;
split( sParams[1], ",", arrayFreezeExpressions );
for( unsigned f=0; f<arrayFreezeExpressions.size(); f++ )
{
vector<RString> arrayFreezeValues;
split( arrayFreezeExpressions[f], "=", arrayFreezeValues );
if( arrayFreezeValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayFreezeExpressions[f].c_str() );
continue;
}
float fFreezeBeat = 0;
RString beat = arrayFreezeValues[0];
if( beat.Right(0).MakeUpper() == "R" )
{
beat = beat.Left(beat.size()-1);
fFreezeBeat = StringToFloat( beat ) / rowsPerMeasure;
}
else
{
fFreezeBeat = StringToFloat(beat);
}
//float fFreezeBeat = StringToFloat( arrayBPMChangeValues[0] );
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds );
// XXX: Remove Negatives Bug?
new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat);
new_seg.m_fStopSeconds = fFreezeSeconds;
if(fFreezeSeconds > 0.0f)
{
// LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
out.AddStopSegment( new_seg );
}
else
{
// negative stops (hi JS!) -aj
if( PREFSMAN->m_bQuirksMode )
{
// LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
out.AddStopSegment( new_seg );
}
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
}
}
}
else if( sValueName=="BPMS" )
{
vector<RString> arrayBPMChangeExpressions;
split( sParams[1], ",", arrayBPMChangeExpressions );
for( unsigned b=0; b<arrayBPMChangeExpressions.size(); b++ )
{
vector<RString> arrayBPMChangeValues;
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
// XXX: Hard to tell which file caused this.
if( arrayBPMChangeValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayBPMChangeExpressions[b].c_str() );
continue;
}
float fBeat = 0;
RString beat = arrayBPMChangeValues[0];
if( beat.Right(0).MakeUpper() == "R" )
{
beat = beat.Left(beat.size()-1);
fBeat = StringToFloat( beat ) / rowsPerMeasure;
}
else
{
fBeat = StringToFloat(beat);
}
//float fBeat = StringToFloat( arrayBPMChangeValues[0] );
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
// XXX: Remove Negatives Bug?
BPMSegment new_seg;
new_seg.m_iStartRow = BeatToNoteRow(fBeat);
new_seg.SetBPM( fNewBPM );
// convert negative BPMs into Warp segments
if( fNewBPM < 0.0f )
{
vector<RString> arrayNextBPMChangeValues;
// get next bpm in sequence
if((b+1) < arrayBPMChangeExpressions.size())
{
split( arrayBPMChangeExpressions[b+1], "=", arrayNextBPMChangeValues );
const float fNextPositiveBeat = StringToFloat( arrayNextBPMChangeValues[0] );
const float fNextPositiveBPM = StringToFloat( arrayNextBPMChangeValues[1] );
// tJumpPos = (tPosBPS-abs(negBPS)) + (gPosBPMPosition - fNegPosition)
float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat);
//float fWarpLengthBeats = fNextPositiveBeat + fDeltaBeat;
WarpSegment wsTemp(BeatToNoteRow(fBeat),fDeltaBeat);
arrayWarpsFromNegativeBPMs.push_back(wsTemp);
/*
LOG->Trace( ssprintf("==NotesLoSM negbpm==\nfnextposbeat = %f, fnextposbpm = %f,\nfdelta = %f, fwarpto = %f",
fNextPositiveBeat,
fNextPositiveBPM,
fDeltaBeat,
fWarpToBeat
) );
*/
/*
LOG->Trace( ssprintf("==Negative/Subtractive BPM in NotesLoader==\nNegBPM has noterow = %i, BPM = %f\nNextBPM @ noterow %i\nDelta value = %i noterows\nThis warp will have us end up at noterow %i",
BeatToNoteRow(fBeat), fNewBPM,
BeatToNoteRow(fNextPositiveBeat),
BeatToNoteRow(fDeltaBeat),
BeatToNoteRow(fWarpToBeat))
);
*/
//float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat);
/*
LOG->Trace( ssprintf("==NotesLoader Delta as NoteRows==\nfDeltaBeat = %f (beat)\nfDeltaBeat = (NextBPMSeg %f - abs(fBPS %f)) + (nextStartRow %i - thisRow %i)",
fDeltaBeat,(fNextPositiveBPM/60.0f),abs(fNewBPM/60.0f),BeatToNoteRow(fNextPositiveBeat),BeatToNoteRow(fBeat))
);
*/
out.AddBPMSegment( new_seg );
continue;
}
else
{
// last BPM is a negative one? ugh. -aj (MAX_NOTE_ROW exists btw)
out.AddBPMSegment( new_seg );
}
}
if(fNewBPM > 0.0f)
out.AddBPMSegment( new_seg );
else
{
out.m_bHasNegativeBpms = true;
// only add Negative BPMs in quirks mode -aj
if( PREFSMAN->m_bQuirksMode )
out.AddBPMSegment( new_seg );
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM );
}
}
}
// Note: Even though it is possible to have Negative BPMs and Stops in
// a song along with Warps, we should not support files that contain
// both styles of warp tricks (Negatives vs. #WARPS).
// If Warps have been populated from Negative BPMs, then go through that
// instead of using the data in the Warps tag. This should be above,
// but it breaks compiling so...
if(arrayWarpsFromNegativeBPMs.size() > 0)
{
// zomg we already have some warps...
for( unsigned j=0; j<arrayWarpsFromNegativeBPMs.size(); j++ )
{
out.AddWarpSegment( arrayWarpsFromNegativeBPMs[j] );
}
}
// warp sorting will need to take place.
//sort(out.m_WarpSegments.begin(), out.m_WarpSegments.end());
}
}
bool SMALoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong )
{
LOG->Trace( "SMALoader::LoadEditFromFile(%s)", sEditFilePath.c_str() );
int iBytes = FILEMAN->GetFileSizeInBytes( sEditFilePath );
if( iBytes > MAX_EDIT_STEPS_SIZE_BYTES )
{
LOG->UserLog( "Edit file", sEditFilePath, "is unreasonably large. It won't be loaded." );
return false;
}
MsdFile msd;
if( !msd.ReadFile( sEditFilePath, true ) ) // unescape
{
LOG->UserLog( "Edit file", sEditFilePath, "couldn't be opened: %s", msd.GetError().c_str() );
return false;
}
return LoadEditFromMsd( msd, sEditFilePath, slot, bAddStepsToSong );
}
bool SMALoader::LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot )
{
MsdFile msd;
msd.ReadFromString( sBuffer, true ); // unescape
return LoadEditFromMsd( msd, sEditFilePath, slot, true );
}
bool SMALoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong )
{
Song* pSong = NULL;
for( unsigned i=0; i<msd.GetNumValues(); i++ )
{
int iNumParams = msd.GetNumParams(i);
const MsdFile::value_t &sParams = msd.GetValue(i);
RString sValueName = sParams[0];
sValueName.MakeUpper();
// handle the data
if( sValueName=="SONG" )
{
if( pSong )
{
LOG->UserLog( "Edit file", sEditFilePath, "has more than one #SONG tag." );
return false;
}
RString sSongFullTitle = sParams[1];
sSongFullTitle.Replace( '\\', '/' );
pSong = SONGMAN->FindSong( sSongFullTitle );
if( pSong == NULL )
{
LOG->UserLog( "Edit file", sEditFilePath, "requires a song \"%s\" that isn't present.", sSongFullTitle.c_str() );
return false;
}
if( pSong->GetNumStepsLoadedFromProfile(slot) >= MAX_EDITS_PER_SONG_PER_PROFILE )
{
LOG->UserLog( "Song file", sSongFullTitle, "already has the maximum number of edits allowed for ProfileSlotP%d.", slot+1 );
return false;
}
}
else if( sValueName=="NOTES" )
{
if( pSong == NULL )
{
LOG->UserLog( "Edit file", sEditFilePath, "doesn't have a #SONG tag preceeding the first #NOTES tag." );
return false;
}
if( iNumParams < 7 )
{
LOG->UserLog( "Edit file", sEditFilePath, "has %d fields in a #NOTES tag, but should have at least 7.", iNumParams );
continue;
}
if( !bAddStepsToSong )
return true;
Steps* pNewNotes = new Steps;
LoadFromSMATokens(
sParams[1], sParams[2], sParams[3], sParams[4], sParams[5], sParams[6],
*pNewNotes);
pNewNotes->SetLoadedFromProfile( slot );
pNewNotes->SetDifficulty( Difficulty_Edit );
pNewNotes->SetFilename( sEditFilePath );
if( pSong->IsEditAlreadyLoaded(pNewNotes) )
{
LOG->UserLog( "Edit file", sEditFilePath, "is a duplicate of another edit that was already loaded." );
SAFE_DELETE( pNewNotes );
return false;
}
pSong->AddSteps( pNewNotes );
return true; // Only allow one Steps per edit file!
}
else
{
LOG->UserLog( "Edit file", sEditFilePath, "has an unexpected value \"%s\".", sValueName.c_str() );
}
}
return true;
}
bool SMALoader::LoadFromBGChangesString( BackgroundChange &change,
const RString &sBGChangeExpression )
{
return SMLoader::LoadFromBGChangesString(change, sBGChangeExpression);
}
/**
* @file
* @author Aldo Fregoso, Jason Felds (c) 2009-2011
* @section LICENSE
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+63
View File
@@ -0,0 +1,63 @@
#ifndef NOTES_LOADER_SMA_H
#define NOTES_LOADER_SMA_H
#include "GameConstantsAndTypes.h"
#include "BackgroundUtil.h"
class MsdFile;
class Song;
class Steps;
class TimingData;
/** @brief Reads a Song from a .SMA file. */
namespace SMALoader
{
void LoadFromSMATokens( RString sStepsType,
RString sDescription,
RString sDifficulty,
RString sMeter,
RString sRadarValues,
RString sNoteData,
Steps &out );
bool LoadFromDir( const RString &sPath, Song &out );
void TidyUpData( Song &song, bool bFromCache );
bool LoadFromSMAFile( const RString &sPath, Song &out );
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
bool LoadTimingFromFile( const RString &fn, TimingData &out );
void LoadTimingFromSMAFile( const MsdFile &msd, TimingData &out );
bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot );
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression );
};
#endif
/**
* @file
* @author Aldo Fregoso, Jason Felds (c) 2009-2011
* @section LICENSE
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+34 -9
View File
@@ -600,9 +600,7 @@ void Player::Load()
// parameters are invalid somehow... -aj
RageSoundLoadParams SoundParams;
//RageSoundParams p;
SoundParams.m_bSupportPan = true;
//p.StopMode = RageSoundParams::M_STOP;
float fBalance = GameSoundManager::GetPlayerBalance( pn );
for( unsigned i=0; i<m_vKeysounds.size(); i++ )
@@ -612,7 +610,7 @@ void Player::Load()
if( sound.GetLoadedFilePath() != sKeysoundFilePath )
sound.Load( sKeysoundFilePath, true, &SoundParams );
sound.SetProperty( "Pan", fBalance );
//sound.SetParams( p );
sound.SetStopModeFromString( "stop" );
}
if( m_pPlayerStageStats )
@@ -1300,16 +1298,22 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vector<TrackRowTap
tn.HoldResult.hns = hns;
// Stop the playing keysound for the hold note.
// I think this causes crashes too -aj
/*
m_vKeysounds[tn.iKeysoundIndex].SetProperty ("Volume", max(0.0, min(1.0, fLife * 5.0 - 4.0)));
// Possibly fixed.
if( tn.iKeysoundIndex >= 0 && tn.iKeysoundIndex < (int) m_vKeysounds.size() )
{
if( tn.subType == TapNote::hold_head_roll )
{
m_vKeysounds[tn.iKeysoundIndex].SetProperty ("Volume", max(0.0, min(1.0, fLife * 2.0)));
}
else
{
m_vKeysounds[tn.iKeysoundIndex].SetProperty ("Volume", max(0.0, min(1.0, fLife * 10.0 - 8.5)));
}
if (tn.HoldResult.fLife == 0)
{
m_vKeysounds[tn.iKeysoundIndex].StopPlaying();
}
}
*/
}
if( hns != HNS_None )
@@ -2427,10 +2431,29 @@ done_checking_hopo:
* even that doesn't seem quite right since it would then play the same (new) keysound twice which would
* sound wrong even though the notes were judged as being correct, above. Fixing the above problem would
* fix this one as well. */
if( iRowOfOverlappingNoteOrRow == -1 )
int iHeadRow;
if( iRowOfOverlappingNoteOrRow != -1 && score != TNS_None )
{
// just pressing a note, use that row.
// in other words, iRowOfOverlappingNoteOrRow = iRowOfOverlappingNoteOrRow
}
else if ( m_NoteData.IsHoldNoteAtRow( col, iSongRow, &iHeadRow ) )
{
// stepping on a hold, use it!
iRowOfOverlappingNoteOrRow = iHeadRow;
}
else
{
// or else find the closest note.
iRowOfOverlappingNoteOrRow = GetClosestNote( col, iSongRow, MAX_NOTE_ROW, MAX_NOTE_ROW, true );
}
if( iRowOfOverlappingNoteOrRow != -1 )
{
bool bShouldPlayNextKeysound = true;
if( bShouldPlayNextKeysound )
{
switch( pbt )
{
DEFAULT_FAIL(pbt);
@@ -2438,7 +2461,7 @@ done_checking_hopo:
for( int i=0; i<m_NoteData.GetNumTracks(); i++ )
{
const TapNote &tn = m_NoteData.GetTapNote( i, iRowOfOverlappingNoteOrRow );
if( tn.iKeysoundIndex >= 0 && tn.iKeysoundIndex < (int) m_vKeysounds.size() && (tn.type != TapNote::hold_head || (!tn.HoldResult.bActive || (tn.HoldResult.fOverlappedTime == 0))) )
if( tn.iKeysoundIndex >= 0 && tn.iKeysoundIndex < (int) m_vKeysounds.size() && (tn.type != TapNote::hold_head || (!tn.HoldResult.bActive || (tn.HoldResult.fOverlappedTime == 0 || (tn.HoldResult.hns == HNS_Held)))) )
{
m_vKeysounds[tn.iKeysoundIndex].Play();
m_vKeysounds[tn.iKeysoundIndex].SetProperty ("Volume", 1);
@@ -2448,13 +2471,15 @@ done_checking_hopo:
case ButtonType_Step:
case ButtonType_Hopo:
const TapNote &tn = m_NoteData.GetTapNote( col, iRowOfOverlappingNoteOrRow );
if( tn.iKeysoundIndex >= 0 && tn.iKeysoundIndex < (int) m_vKeysounds.size() && (tn.type != TapNote::hold_head || (!tn.HoldResult.bActive || (tn.HoldResult.fOverlappedTime == 0))) )
if( tn.iKeysoundIndex >= 0 && tn.iKeysoundIndex < (int) m_vKeysounds.size() && (tn.type != TapNote::hold_head || (!tn.HoldResult.bActive || (tn.HoldResult.fOverlappedTime == 0 || (tn.HoldResult.hns == HNS_Held)))) )
{
m_vKeysounds[tn.iKeysoundIndex].Play();
m_vKeysounds[tn.iKeysoundIndex].SetProperty ("Volume", 1);
}
break;
}
}
}
}
// XXX:
+3 -3
View File
@@ -179,16 +179,15 @@ public:
float m_fPerspectiveTilt, m_SpeedfPerspectiveTilt; // -1 = near, 0 = overhead, +1 = space
float m_fSkew, m_SpeedfSkew; // 0 = vanish point is in center of player, 1 = vanish point is in center of screen
float m_fRandomSpeed, m_SpeedfRandomSpeed;
/* If this is > 0, then the player must have life above this value at the end of
* the song to pass. This is independent of SongOptions::m_FailType. */
float m_fPassmark, m_SpeedfPassmark;
float m_fRandomSpeed, m_SpeedfRandomSpeed;
bool m_bTurns[NUM_TURNS];
bool m_bTransforms[NUM_TRANSFORMS];
bool m_bMuteOnError;
ScoreDisplay m_ScoreDisplay;
/** @brief How can the Player fail a song? */
enum FailType {
FAIL_IMMEDIATE=0, /**< fail immediately when life touches 0 */
@@ -198,6 +197,7 @@ public:
};
/** @brief The method for which a player can fail a song. */
FailType m_FailType;
ScoreDisplay m_ScoreDisplay;
/**
* @brief The Noteskin to use.
-1
View File
@@ -216,7 +216,6 @@ void ScreenDebugOverlay::Init()
RString sPageName = (*p)->GetPageName();
DeviceInput di;
di.x = di.y = NULL;
switch( (*p)->GetType() )
{
case IDebugLine::all_screens:
+24 -6
View File
@@ -800,7 +800,7 @@ void ScreenEdit::Init()
m_bHasUndo = false;
m_Undo.SetNumTracks( m_NoteDataEdit.GetNumTracks() );
m_bDirty = false;
m_bDirty = m_NoteDataEdit.IsEmpty(); // require the usage of saving if empty.
m_Player->Init( "Player", GAMESTATE->m_pPlayerState[PLAYER_1], NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
m_Player->CacheAllUsedNoteSkins();
@@ -2816,7 +2816,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
HandleMainMenuChoice( ScreenEdit::save_on_exit );
return;
case ANSWER_NO:
/* Don't save; just exit. */
// Don't save; just exit.
SCREENMAN->SendMessageToTopScreen( SM_DoExit );
return;
case ANSWER_CANCEL:
@@ -2848,15 +2848,32 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
// IMPORTANT: CopyFromLastSave before deleting the Steps below
CopyFromLastSave();
/* The user has been given a choice to save. Delete all unsaved
* steps before exiting the editor. */
/* The user has been given a choice to save.
* Delete all unsaved steps before exiting the editor. */
/* FIXME: This code causes all the steps to be deleted if you quit
* without saving. However, without this code, any new steps will get
* saved on quit. -aj */
// At this point, the last good song copy is in use.
Song *pSong = GAMESTATE->m_pCurSong;
const vector<Steps*> &apSteps = pSong->GetAllSteps();
vector<Steps*> apToDelete;
FOREACH_CONST( Steps *, apSteps, s )
{
if( (*s)->IsAutogen() || (*s)->GetSavedToDisk() )
// If we're not on the same style, let it go.
if( GAMESTATE->m_pCurSteps[PLAYER_1]->m_StepsType != (*s)->m_StepsType )
continue;
// If autogenned, it isn't being saved.
if( (*s)->IsAutogen() )
continue;
// If the notedata has content, let it go.
if( !(*s)->m_NoteData->IsEmpty() )
continue;
// It's hard to say if these steps were saved to disk or not.
/*
if( !(*s)->GetSavedToDisk() )
continue;
*/
apToDelete.push_back( *s );
}
FOREACH_CONST( Steps *, apToDelete, s )
@@ -2869,6 +2886,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
GAMESTATE->m_pCurSteps[PLAYER_1].Set( NULL );
}
m_Out.StartTransitioning( SM_GoToNextScreen );
}
else if( SM == SM_GainFocus )
@@ -4123,7 +4141,7 @@ void ScreenEdit::DoHelp()
// lua start
#include "LuaBinding.h"
/** @brief Allow Lua to have access to the ScreenEdit. */
/** @brief Allow Lua to have access to ScreenEdit. */
class LunaScreenEdit: public Luna<ScreenEdit>
{
public:
+2 -4
View File
@@ -45,7 +45,6 @@ void ScreenEditMenu::Init()
m_Selector.SetXY( 0, 0 );
this->AddChild( &m_Selector );
m_textExplanation.SetName( "Explanation" );
m_textExplanation.LoadFromFont( THEME->GetPathF(m_sName,"explanation") );
LOAD_ALL_COMMANDS_AND_SET_XY( m_textExplanation );
@@ -59,7 +58,6 @@ void ScreenEditMenu::Init()
this->AddChild( &m_textNumStepsLoadedFromProfile );
}
void ScreenEditMenu::HandleScreenMessage( const ScreenMessage SM )
{
if( SM == SM_RefreshSelector )
@@ -77,8 +75,8 @@ void ScreenEditMenu::HandleScreenMessage( const ScreenMessage SM )
pSong->DeleteSteps( pStepsToDelete );
SONGMAN->Invalidate( pSong );
/* Only save to the main .SM file if the steps we're deleting were loaded
* from it. */
/* Only save to the main .SM file if the steps we're deleting
* were loaded from it. */
if( bSaveSong )
{
pSong->Save();
+1 -1
View File
@@ -209,7 +209,7 @@ void ScreenEvaluation::Init()
}
}
ASSERT( !STATSMAN->m_vPlayedStageStats.empty() );
ASSERT_M( !STATSMAN->m_vPlayedStageStats.empty(), "PlayerStageStats is empty!" );
m_pStageStats = &STATSMAN->m_vPlayedStageStats.back();
ZERO( m_bSavedScreenshot );
+25 -7
View File
@@ -223,8 +223,15 @@ bool Song::LoadFromSongDir( RString sDir )
if( bUseCache )
{
// LOG->Trace( "Loading '%s' from cache file '%s'.", m_sSongDir.c_str(), GetCacheFilePath().c_str() );
SSCLoader::LoadFromSSCFile( sCacheFilePath, *this, true );
bool bLoadedFromSSC = SSCLoader::LoadFromSSCFile( sCacheFilePath, *this, true );
if( bLoadedFromSSC )
SSCLoader::TidyUpData( *this, true );
else
{
// load from .sm
SMLoader::LoadFromSMFile( sCacheFilePath, *this, true );
SMLoader::TidyUpData( *this, true );
}
}
else
{
@@ -738,26 +745,37 @@ void Song::TidyUpData()
* filename, and should always be the title of the song (unlike KSFs). */
m_sSongFileName = m_sSongDir;
vector<RString> asFileNames;
do
{
GetDirListing( m_sSongDir+"*.ssc", asFileNames );
if( !asFileNames.empty() )
{
m_sSongFileName += asFileNames[0];
break;
}
else
GetDirListing( m_sSongDir+"*.sma", asFileNames );
if (!asFileNames.empty() )
{
m_sSongFileName += SetExtension( asFileNames[0], "ssc" );
break;
}
GetDirListing( m_sSongDir+"*.sm", asFileNames );
if( !asFileNames.empty() )
{
m_sSongFileName += SetExtension( asFileNames[0], "ssc" );
else {
break;
}
GetDirListing( m_sSongDir+"*.dwi", asFileNames );
if( !asFileNames.empty() ) {
m_sSongFileName += SetExtension( asFileNames[0], "ssc" );
} else {
break;
}
m_sSongFileName += Basename(m_sSongDir);
m_sSongFileName += ".ssc";
}
}
}
} while(0);
}
// If no time signature specified, assume 4/4 time for the whole song.
+6 -6
View File
@@ -193,13 +193,13 @@ void SongManager::AddGroup( RString sDir, RString sGroupDirName )
* TODO: Once the files are implemented in Song, bring the extensions
* from there into here. -aj */
// Group background
/*
vector<RString> arrayGroupBackgrounds;
GetDirListing( sDir+sGroupDirName+"/*-bg.png", arrayGroupBanners );
GetDirListing( sDir+sGroupDirName+"/*-bg.jpg", arrayGroupBanners );
GetDirListing( sDir+sGroupDirName+"/*-bg.gif", arrayGroupBanners );
GetDirListing( sDir+sGroupDirName+"/*-bg.bmp", arrayGroupBanners );
//vector<RString> arrayGroupBackgrounds;
//GetDirListing( sDir+sGroupDirName+"/*-bg.png", arrayGroupBanners );
//GetDirListing( sDir+sGroupDirName+"/*-bg.jpg", arrayGroupBanners );
//GetDirListing( sDir+sGroupDirName+"/*-bg.gif", arrayGroupBanners );
//GetDirListing( sDir+sGroupDirName+"/*-bg.bmp", arrayGroupBanners );
/*
RString sBackgroundPath;
if( !arrayGroupBackgrounds.empty() )
sBackgroundPath = sDir+sGroupDirName+"/"+arrayGroupBackgrounds[0];
+6 -6
View File
@@ -22,10 +22,10 @@ public:
};
DrainType m_DrainType; // only used with LifeBar
int m_iBatteryLives;
float m_fMusicRate, m_SpeedfMusicRate;
float m_fHaste, m_SpeedfHaste;
bool m_bAssistClap;
bool m_bAssistMetronome;
float m_fMusicRate, m_SpeedfMusicRate;
float m_fHaste, m_SpeedfHaste;
enum AutosyncType {
AUTOSYNC_OFF,
AUTOSYNC_SONG,
@@ -34,10 +34,6 @@ public:
NUM_AUTOSYNC_TYPES
};
AutosyncType m_AutosyncType;
bool m_bStaticBackground;
bool m_bRandomBGOnly;
bool m_bSaveScore;
bool m_bSaveReplay;
enum SoundEffectType {
SOUNDEFFECT_OFF,
SOUNDEFFECT_SPEED,
@@ -45,6 +41,10 @@ public:
NUM_SOUNDEFFECT
};
SoundEffectType m_SoundEffectType;
bool m_bStaticBackground;
bool m_bRandomBGOnly;
bool m_bSaveScore;
bool m_bSaveReplay;
/**
* @brief Set up the SongOptions with reasonable defaults.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+21 -23
View File
@@ -469,7 +469,6 @@ struct VideoCardDefaults
}
} const g_VideoCardDefaults[] =
{
/*
VideoCardDefaults(
"Xbox",
"d3d",
@@ -478,10 +477,9 @@ struct VideoCardDefaults
2048,
true
),
*/
VideoCardDefaults(
"Voodoo *5",
"opengl", // received 3 reports of opengl crashing. -Chris
"d3d,opengl", // received 3 reports of opengl crashing. -Chris
640,480,
32,32,32,
2048,
@@ -489,7 +487,7 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"Voodoo|3dfx", // all other Voodoos: some drivers don't identify which one
"opengl",
"d3d,opengl",
640,480,
16,16,16,
256,
@@ -497,7 +495,7 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"Radeon.* 7|Wonder 7500|ArcadeVGA", // Radeon 7xxx, RADEON Mobility 7500
"opengl", // movie texture performance is terrible in OpenGL, but fine in D3D.
"d3d,opengl", // movie texture performance is terrible in OpenGL, but fine in D3D.
640,480,
16,16,16,
2048,
@@ -505,7 +503,7 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"GeForce|Radeon|Wonder 9|Quadro",
"opengl",
"opengl,d3d",
640,480,
32,32,32, // 32 bit textures are faster to load
2048,
@@ -513,7 +511,7 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"TNT|Vanta|M64",
"opengl",
"opengl,d3d",
640,480,
16,16,16, // Athlon 1.2+TNT demonstration w/ movies: 70fps w/ 32bit textures, 86fps w/ 16bit textures
2048,
@@ -521,13 +519,12 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"G200|G250|G400",
"opengl",
"d3d,opengl",
640,480,
16,16,16,
2048,
false // broken, causes black screen
),
/*
VideoCardDefaults(
"Savage",
"d3d",
@@ -551,10 +548,9 @@ struct VideoCardDefaults
256,
false
),
*/
VideoCardDefaults(
"RAGE MOBILITY-M1",
"opengl", // Vertex alpha is broken in OpenGL, but not D3D. -Chris
"d3d,opengl", // Vertex alpha is broken in OpenGL, but not D3D. -Chris
400,300, // lower resolution for 60fps
16,16,16,
256,
@@ -562,7 +558,7 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"Mobility M3", // ATI Rage Mobility 128 (AKA "M3")
"opengl", // bad movie texture performance in opengl
"d3d,opengl", // bad movie texture performance in opengl
640,480,
16,16,16,
1024,
@@ -570,7 +566,7 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"Intel.*82810|Intel.*82815",
"opengl",// OpenGL is 50%+ faster than D3D w/ latest Intel drivers. -Chris
"opengl,d3d",// OpenGL is 50%+ faster than D3D w/ latest Intel drivers. -Chris
512,384, // lower resolution for 60fps
16,16,16,
512,
@@ -578,15 +574,15 @@ struct VideoCardDefaults
),
VideoCardDefaults(
"Intel*Extreme Graphics",
"opengl", // OpenGL blue screens w/ XP drivers from 6-21-2002
"d3d", // OpenGL blue screens w/ XP drivers from 6-21-2002
640,480,
16,16,16, // slow at 32bpp
1024,
false
),
VideoCardDefaults(
"Intel.*", /* fallback: all unknown Intel cards to since Intel is notoriously bad at OpenGL */
"opengl",
"Intel.*", /* fallback: all unknown Intel cards to D3D, since Intel is notoriously bad at OpenGL */
"d3d,opengl",
640,480,
16,16,16,
2048,
@@ -599,17 +595,17 @@ struct VideoCardDefaults
// bug 764830: ASSERT fail after glDeleteTextures for "VIA Tech VT8361/VT8601 Graphics Controller"
// bug 791950: AV in glsis630!DrvSwapBuffers for "SiS 630/730"
"Trident Video Accelerator CyberBlade|VIA.*VT|SiS 6*",
"opengl",
"d3d,opengl",
640,480,
16,16,16,
2048,
false
),
VideoCardDefaults(
/* Unconfirmed texture problems on this; let's try since it's
/* Unconfirmed texture problems on this; let's try D3D, since it's
* a VIA/S3 chipset. */
"VIA/S3G KM400/KN400",
"opengl",
"d3d,opengl",
640,480,
16,16,16,
2048,
@@ -627,7 +623,7 @@ struct VideoCardDefaults
// Default graphics settings used for all cards that don't match above.
// This must be the very last entry!
"",
"opengl",
"opengl,d3d",
640,480,
32,32,32,
2048,
@@ -771,9 +767,10 @@ RageDisplay *CreateDisplay()
}
else if( sRenderer.CompareNoCase("d3d")==0 )
{
#if defined(SUPPORT_D3D)
pRet = new RageDisplay_D3D;
#endif
// TODO: ANGLE/RageDisplay_Modern
//#if defined(SUPPORT_D3D)
// pRet = new RageDisplay_D3D;
//#endif
}
else if( sRenderer.CompareNoCase("null")==0 )
{
@@ -1571,3 +1568,4 @@ void HandleInputEvents(float fDeltaTime)
* PERFORMANCE OF THIS SOFTWARE.
*/
>>>>>>> other
+8 -2
View File
@@ -21,6 +21,7 @@
#include "GameManager.h"
#include "NoteDataUtil.h"
#include "NotesLoaderSSC.h"
#include "NotesLoaderSM.h"
#include <algorithm>
@@ -229,13 +230,18 @@ void Steps::Decompress() const
if( !m_sFilename.empty() && m_sNoteDataCompressed.empty() )
{
/* We have data on disk and not in memory. Load it. */
// We have data on disk and not in memory. Load it.
Song s;
if( !SSCLoader::LoadFromSSCFile(m_sFilename, s, true) )
bool bLoadedFromSSC = SSCLoader::LoadFromSSCFile(m_sFilename, s, true);
if( !bLoadedFromSSC )
{
// try reading from .sm instead
if( !SMLoader::LoadFromSMFile(m_sFilename, s, true) )
{
LOG->Warn( "Couldn't load \"%s\"", m_sFilename.c_str() );
return;
}
}
/* Find the steps. */
StepsID ID;
+10 -11
View File
@@ -117,26 +117,25 @@ void TimingData::SetTimeSignatureAtRow( int iRow, int iNumerator, int iDenominat
if( m_vTimeSignatureSegments[i].m_iStartRow >= iRow)
break; // We found our segment.
}
TimeSignatureSegment &ts = m_vTimeSignatureSegments[i];
TimeSignatureSegment &prev = m_vTimeSignatureSegments[i-1];
if( i == m_vTimeSignatureSegments.size() || ts.m_iStartRow != iRow )
if ( i == m_vTimeSignatureSegments.size() || m_vTimeSignatureSegments[i].m_iStartRow != iRow )
{
// There is no TimeSignatureSegment at the specified beat.
// If the TimeSignatureSegment being set differs
// from the last TimeSignature, create a new TimeSignatureSegment.
if( i == 0 || ( prev.m_iNumerator != iNumerator || prev.m_iDenominator != iDenominator ) )
// No specific segmeent here: place one if it differs.
if( i == 0 ||
( m_vTimeSignatureSegments[i-1].m_iNumerator != iNumerator
|| m_vTimeSignatureSegments[i-1].m_iDenominator != iDenominator ) )
AddTimeSignatureSegment( TimeSignatureSegment(iRow, iNumerator, iDenominator) );
}
else // TimeSignatureSegment being modified is m_vTimeSignatureSegments[i]
{
if( i > 0 && prev.m_iNumerator == iNumerator
&& prev.m_iDenominator == iDenominator )
if( i > 0 && m_vTimeSignatureSegments[i-1].m_iNumerator == iNumerator
&& m_vTimeSignatureSegments[i-1].m_iDenominator == iDenominator )
m_vTimeSignatureSegments.erase( m_vTimeSignatureSegments.begin()+i,
m_vTimeSignatureSegments.begin()+i+1 );
else
{
ts.m_iNumerator = iNumerator;
ts.m_iDenominator = iDenominator;
m_vTimeSignatureSegments[i].m_iNumerator = iNumerator;
m_vTimeSignatureSegments[i].m_iDenominator = iDenominator;
}
}
}
+2 -2
View File
@@ -222,7 +222,7 @@ struct TimeSignatureSegment
* @param n the numerator for the segment.
*/
TimeSignatureSegment( int r, int n ): m_iStartRow(max(0, r)),
m_iNumerator(n), m_iDenominator(4) {}
m_iNumerator(max(1, n)), m_iDenominator(4) {}
/**
* @brief Creates a Time Signature Segment at the given row with a supplied numerator & denominator.
* @param r the starting row of the segment.
@@ -230,7 +230,7 @@ struct TimeSignatureSegment
* @param d the denonimator for the segment.
*/
TimeSignatureSegment( int r, int n, int d ): m_iStartRow(max(0, r)),
m_iNumerator(n), m_iDenominator(d) {}
m_iNumerator(max(1, n)), m_iDenominator(max(1, d)) {}
/**
* @brief The row in which the TimeSignatureSegment activates.
*/
@@ -509,18 +509,21 @@ void InputHandler_DInput::UpdateBuffered( DIDevice &device, const RageTimer &tm
switch(in.ofs)
{
case DIMOFS_X:
up = MOUSE_X_LEFT; down = MOUSE_X_RIGHT;
INPUTFILTER->UpdateCursorLocation((float)cursorPos.x,(float)cursorPos.y);
break;
case DIMOFS_Y:
up = MOUSE_Y_UP; down = MOUSE_Y_DOWN;
INPUTFILTER->UpdateCursorLocation((float)cursorPos.x,(float)cursorPos.y);
break;
case DIMOFS_Z:
INPUTFILTER->UpdateMouseWheel(l);
{
up = MOUSE_WHEELUP; down = MOUSE_WHEELDOWN;
l = SCALE( int(evtbuf[i].dwData), -120.0f, 120.0f, -1.0f, 1.0f );
ButtonPressed( DeviceInput(dev, up, max(-l,0), tm) );
ButtonPressed( DeviceInput(dev, down, max(+l,0), tm) );
l = SCALE( int(evtbuf[i].dwData), -120.0f, 120.0f, 1.0f, -1.0f );
DeviceInput diUp = DeviceInput(dev, up, max(-l,0), tm);
DeviceInput diDown = DeviceInput(dev, down, max(+l,0), tm);
ButtonPressed( diUp );
ButtonPressed( diDown );
}
break;
default: LOG->MapLog( "unknown input",
"Mouse '%s' is returning an unknown mouse offset [axis], %i",
@@ -552,6 +555,7 @@ void InputHandler_DInput::UpdateBuffered( DIDevice &device, const RageTimer &tm
}
break;
}
case in.HAT:
{
const int pos = TranslatePOV( evtbuf[i].dwData );
@@ -632,4 +632,3 @@ void LowLevelWindow_MacOSX::BeginConcurrentRendering()
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+2 -2
View File
@@ -104,11 +104,11 @@ void MouseDevice::GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementC
const Mouse& m = m_Mouse;
if( m.x_axis == cookie )
{
// INPUTFILTER->UpdateCursorLocation(m.x_axis,m.y_axis);
// INPUTFILTER->UpdateCursorLocation(value,m.y_axis);
}
else if( m.y_axis == cookie )
{
// INPUTFILTER->UpdateCursorLocation((float)m.x_axis,(float)m.y_axis);
// INPUTFILTER->UpdateCursorLocation(m.x_axis,value);
}
else if( m.z_axis == cookie )
{