[opengl] merge (part 1?)
This commit is contained in:
@@ -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
|
||||
@@ -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/.+/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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
@@ -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
@@ -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] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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" );
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 ¬eHead = 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.
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
+307
-301
File diff suppressed because it is too large
Load Diff
+379
-373
File diff suppressed because it is too large
Load Diff
+758
-714
File diff suppressed because it is too large
Load Diff
+21
-23
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user