diff --git a/extern/jsoncpp/include/json/value.h b/extern/jsoncpp/include/json/value.h index 58bfd88e7a..0cf4ca76cf 100644 --- a/extern/jsoncpp/include/json/value.h +++ b/extern/jsoncpp/include/json/value.h @@ -234,6 +234,13 @@ namespace Json { double asDouble() const; bool asBool() const; + bool TryGet( std::string &out ) const { if(!isString()) return false; out=asString(); return true; } + bool TryGet( int &out ) const { if(!isInt()) return false; out=asInt(); return true; } + bool TryGet( UInt &out ) const { if(!isUInt()) return false; out=asUInt(); return true; } + bool TryGet( double &out ) const { if(!isDouble()) return false; out=asDouble(); return true; } + bool TryGet( float &out ) const { if(!isDouble()) return false; out=(float)asDouble(); return true; } + bool TryGet( bool &out ) const { if(!isBool()) return false; out=asBool(); return true; } + bool isNull() const; bool isBool() const; bool isInt() const; diff --git a/src/JsonUtil.h b/src/JsonUtil.h index 8c17bb1af2..97136a4f14 100644 --- a/src/JsonUtil.h +++ b/src/JsonUtil.h @@ -1,9 +1,10 @@ +/** @brief Utilities for handling JSON data. */ #ifndef JsonUtil_H #define JsonUtil_H class RageFileBasic; -#include "../extern/jsoncpp/include/json/value.h" -/** @brief Utilities for handling JSON data. */ +#include "json/value.h" + namespace JsonUtil { bool LoadFromString( Json::Value &root, RString sData, RString &sErrorOut ); @@ -31,6 +32,86 @@ namespace JsonUtil fn(*v[i], root[i]); } + template + static void SerializeArray(const V &v, void fn(const T &, Json::Value &), Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + fn( *iter, root[i++] ); + } + + template + static void SerializeArrayValues(const V &v, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + root[i++] = *iter; + } + + template + static void SerializeArrayObjects(const V &v, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + iter->Serialize( root[i++] ); + } + + template + static void SerializeStringToObjectMap(const M &m, F fnEnumToString(E e), Json::Value &root) + { + for( typename M::const_iterator iter=m.begin(); iter!=m.end(); iter++ ) + iter->second.Serialize( root[ fnEnumToString(iter->first) ] ); + } + + template + static void SerializeStringToValueMap(const M &m, F fnToString(E e), Json::Value &root) + { + for( typename M::const_iterator iter=m.begin(); iter!=m.end(); iter++ ) + root[ fnToString(iter->first) ] = iter->second; + } + + template + static void SerializeValueToValueMap(const M &m, Json::Value &root) + { + for( typename M::const_iterator iter=m.begin(); iter!=m.end(); iter++ ) + root[ (iter->first) ] = iter->second; + } + + // Serialize a map that has a non-string key type + template + static void SerializeObjectToObjectMapAsArray(const V &v, const RString &sKeyName, const RString &sValueName, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + { + Json::Value &v = root[i++]; + iter->first.Serialize( v[sKeyName] ); + iter->second.Serialize( v[sValueName] ); + } + } + + template + static void SerializeObjectToValueMapAsArray(const V &v, const RString &sKeyName, const RString &sValueName, Json::Value &root) + { + root = Json::Value(Json::arrayValue); + root.resize( v.size() ); + int i=0; + for( typename V::const_iterator iter=v.begin(); iter!=v.end(); iter++ ) + { + Json::Value &v = root[i++]; + iter->first.Serialize( v[sKeyName] ); + v[sValueName] = iter->second; + } + } + template static void SerializeVectorValues(const vector &v, Json::Value &root) { @@ -48,6 +129,14 @@ namespace JsonUtil fn(v[i], root[i]); } + template + static void DeserializeArrayObjects( V &v, const Json::Value &root) + { + v.resize( root.size() ); + for( unsigned i=0; i static void DeserializeVectorPointers(vector &v, void fn(T &, const Json::Value &), const Json::Value &root) { @@ -61,6 +150,99 @@ namespace JsonUtil } } + template + static void DeserializeArrayValues(vector &v, const Json::Value &root) + { + v.clear(); + for( unsigned i=0; i + static void DeserializeArrayValuesIntoSet(S &s, const Json::Value &root) + { + s.clear(); + for( unsigned i=0; i + static void DeserializeArrayValuesIntoVector(vector &v, const Json::Value &root) + { + v.clear(); + for( unsigned i=0; i + static void DeserializeValueToValueMap(M &m, const Json::Value &root) + { + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + (*iter).TryGet( m[ iter.memberName() ] ); + } + + template + static void DeserializeStringToValueMap(M &m, F fnToValue(E e), const Json::Value &root) + { + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + (*iter).TryGet( m[ fnToValue(iter.memberName()) ] ); + } + + template + static void DeserializeStringToObjectMap(M &m, F fnToValue(E e), const Json::Value &root) + { + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + m[ fnToValue(iter.memberName()) ].Deserialize( *iter ); + } + + // Serialize a map that has a non-string key type + template + static void DeserializeObjectToObjectMapAsArray(map &m, const RString &sKeyName, const RString &sValueName, const Json::Value &root) + { + m.clear(); + ASSERT( root.type() == Json::arrayValue ); + for( Json::Value::const_iterator iter = root.begin(); iter != root.end(); iter++ ) + { + ASSERT( (*iter).type() == Json::objectValue ); + K k; + if( !k.Deserialize( (*iter)[sKeyName] ) ) + continue; + V v; + if( !v.Deserialize( (*iter)[sValueName] ) ) + continue; + m[k] = v; + } + } + + template + static void DeserializeObjectToValueMapAsArray(map &m, const RString &sKeyName, const RString &sValueName, const Json::Value &root) + { + for( unsigned i=0; i static void DeserializeVectorValues(vector &v, const Json::Value &root) { diff --git a/src/NotesLoaderJson.cpp b/src/NotesLoaderJson.cpp new file mode 100644 index 0000000000..ba7e6647f1 --- /dev/null +++ b/src/NotesLoaderJson.cpp @@ -0,0 +1,238 @@ +#include "global.h" +#include "NotesLoaderJson.h" +#include "Json/Value.h" +#include "TimingData.h" +#include "RageUtil.h" +#include "JsonUtil.h" +#include "BackgroundUtil.h" +#include "NoteData.h" +#include "Song.h" +#include "Steps.h" +#include "GameManager.h" + +void NotesLoaderJson::GetApplicableFiles( const RString &sPath, vector &out ) +{ + GetDirListing( sPath + RString("*.json"), out ); +} + +void Deserialize(BPMSegment &seg, const Json::Value &root) +{ + seg.m_iStartRow = BeatToNoteRow((float)root["Beat"].asDouble()); + seg.m_fBPS = (float)(root["BPM"].asDouble() / 60); +} + +static void Deserialize(StopSegment &seg, const Json::Value &root) +{ + seg.m_iStartRow = BeatToNoteRow((float)(root["Beat"].asDouble())); + seg.m_fStopSeconds = (float)root["Seconds"].asDouble(); +} + +static void Deserialize(TimingData &td, const Json::Value &root) +{ + JsonUtil::DeserializeVectorObjects( td.m_BPMSegments, Deserialize, root["BpmSegments"] ); + JsonUtil::DeserializeVectorObjects( td.m_StopSegments, Deserialize, root["StopSegments"] ); +} + +static void Deserialize(LyricSegment &o, const Json::Value &root) +{ + o.m_fStartTime = (float)root["StartTime"].asDouble(); + o.m_sLyric = root["Lyric"].asString(); + o.m_Color.FromString( root["Color"].asString() ); +} + +static void Deserialize(BackgroundDef &o, const Json::Value &root) +{ + o.m_sEffect = root["Effect"].asString(); + o.m_sFile1 = root["File1"].asString(); + o.m_sFile2 = root["File2"].asString(); + o.m_sColor1 = root["Color1"].asString(); +} + +static void Deserialize(BackgroundChange &o, const Json::Value &root ) +{ + Deserialize( o.m_def, root["Def"] ); + o.m_fStartBeat = (float)root["StartBeat"].asDouble(); + o.m_fRate = (float)root["Rate"].asDouble(); + o.m_sTransition = root["Transition"].asString(); +} + +static void Deserialize( TapNote &o, const Json::Value &root ) +{ + //if( o.type != TapNote::tap ) + if( root.isInt() ) + o.type = (TapNote::Type)root["Type"].asInt(); + //if( o.type == TapNote::hold_head ) + o.subType = (TapNote::SubType)root["SubType"].asInt(); + //root["Source"] = (int)source; + //if( !o.sAttackModifiers.empty() ) + o.sAttackModifiers = root["AttackModifiers"].asString(); + //if( o.fAttackDurationSeconds > 0 ) + o.fAttackDurationSeconds = (float)root["AttackDurationSeconds"].asDouble(); + //if( o.bKeysound ) + o.iKeysoundIndex = root["KeysoundIndex"].asInt(); + //if( o.iDuration > 0 ) + o.iDuration = root["Duration"].asInt(); + //if( o.pn != PLAYER_INVALID ) + o.pn = (PlayerNumber)root["PlayerNumber"].asInt(); +} + +static void Deserialize( StepsType st, NoteData &nd, const Json::Value &root ) +{ + int iTracks = nd.GetNumTracks(); + nd.SetNumTracks( iTracks ); + for( unsigned i=0; iStringToStepsType(root["StepsType"].asString()); + + o.Decompress(); + + NoteData nd; + Deserialize( o.m_StepsType, nd, root["NoteData"] ); + o.SetNoteData( nd ); + //o.SetHash( root["Hash"].asInt() ); + o.SetDescription( root["Description"].asString() ); + o.SetDifficulty( StringToDifficulty(root["Difficulty"].asString()) ); + o.SetMeter( root["Meter"].asInt() ); + + RadarValues rv[NUM_PLAYERS]; + FOREACH_PlayerNumber( pn ) + { + Deserialize( rv[pn], root["RadarValues"] ); + } + o.SetCachedRadarValues( rv ); +} + +static void Deserialize( Song &out, const Json::Value &root ) +{ + out.SetSongDir( root["SongDir"].asString() ); + out.m_sGroupName = root["GroupName"].asString(); + out.m_sMainTitle = root["Title"].asString(); + out.m_sSubTitle = root["SubTitle"].asString(); + out.m_sArtist = root["Artist"].asString(); + out.m_sMainTitleTranslit = root["TitleTranslit"].asString(); + out.m_sSubTitleTranslit = root["SubTitleTranslit"].asString(); + out.m_sGenre = root["Genre"].asString(); + out.m_sCredit = root["Credit"].asString(); + out.m_sBannerFile = root["Banner"].asString(); + out.m_sBackgroundFile = root["Background"].asString(); + out.m_sLyricsFile = root["LyricsFile"].asString(); + out.m_sCDTitleFile = root["CDTitle"].asString(); + out.m_sMusicFile = root["Music"].asString(); + out.m_Timing.m_fBeat0OffsetInSeconds = (float)root["Offset"].asDouble(); + out.m_fMusicSampleStartSeconds = (float)root["SampleStart"].asDouble(); + out.m_fMusicSampleLengthSeconds = (float)root["SampleLength"].asDouble(); + RString sSelectable = root["Selectable"].asString(); + if( !stricmp(sSelectable,"YES") ) + out.m_SelectionDisplay = out.SHOW_ALWAYS; + else if(!stricmp(sSelectable,"NO")) + out.m_SelectionDisplay = out.SHOW_NEVER; + + out.m_fFirstBeat = (float)root["FirstBeat"].asDouble(); + out.m_fLastBeat = (float)root["LastBeat"].asDouble(); + out.m_sSongFileName = root["SongFileName"].asString(); + out.m_bHasMusic = root["HasMusic"].asBool(); + out.m_bHasBanner = root["HasBanner"].asBool(); + out.m_fMusicLengthSeconds = (float)root["MusicLengthSeconds"].asDouble(); + + RString sDisplayBPMType = root["DisplayBpmType"].asString(); + if( sDisplayBPMType == "*" ) + out.m_DisplayBPMType = DISPLAY_BPM_RANDOM; + else + out.m_DisplayBPMType = DISPLAY_BPM_SPECIFIED; + + if( out.m_DisplayBPMType == DISPLAY_BPM_SPECIFIED ) + { + out.m_fSpecifiedBPMMin = (float)root["SpecifiedBpmMin"].asDouble(); + out.m_fSpecifiedBPMMax = (float)root["SpecifiedBpmMax"].asDouble(); + } + + Deserialize( out.m_Timing, root["TimingData"] ); + JsonUtil::DeserializeVectorObjects( out.m_LyricSegments, Deserialize, root["LyricSegments"] ); + + { + const Json::Value &root2 = root["BackgroundChanges"]; + FOREACH_BackgroundLayer( bl ) + { + const Json::Value &root3 = root2[bl]; + vector &vBgc = out.GetBackgroundChanges(bl); + JsonUtil::DeserializeVectorObjects( vBgc, Deserialize, root3 ); + } + } + + { + vector &vBgc = out.GetForegroundChanges(); + JsonUtil::DeserializeVectorObjects( vBgc, Deserialize, root["ForegroundChanges"] ); + } + + JsonUtil::DeserializeArrayValuesIntoVector( out.m_vsKeysoundFile, root["KeySounds"] ); + + { + vector vpSteps; + JsonUtil::DeserializeVectorPointers( vpSteps, Deserialize, root["Charts"] ); + FOREACH( Steps*, vpSteps, iter ) + out.AddSteps( *iter ); + } + +} + +bool NotesLoaderJson::LoadFromJsonFile( const RString &sPath, Song &out ) +{ + Json::Value root; + if( !JsonUtil::LoadFromFileShowErrors(root,sPath) ) + return false; + + Deserialize(out, root); + + return true; +} + +bool NotesLoaderJson::LoadFromDir( const RString &sPath, Song &out ) +{ + return LoadFromJsonFile(sPath, out); +} + +/* + * (c) 2001-2004 Chris Danford, Glenn Maynard + * 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. + */ diff --git a/src/NotesLoaderJson.h b/src/NotesLoaderJson.h new file mode 100644 index 0000000000..c96629ffd8 --- /dev/null +++ b/src/NotesLoaderJson.h @@ -0,0 +1,41 @@ +/* JsonLoader - Reads a Song from a .json file. */ + +#ifndef NotesLoaderJson_H +#define NotesLoaderJson_H + +#include "NotesLoader.h" +class Song; + +namespace NotesLoaderJson +{ + void GetApplicableFiles( const RString &sPath, vector &out ); + bool LoadFromDir( const RString &sPath, Song &out ); + bool LoadFromJsonFile( const RString &sPath, Song &out ); +}; + +#endif + +/* + * (c) 2001-2004 Chris Danford, Glenn Maynard + * 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. + */ diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp new file mode 100644 index 0000000000..984e4f92da --- /dev/null +++ b/src/NotesWriterJson.cpp @@ -0,0 +1,230 @@ +#include "global.h" +#include "NotesWriterJson.h" +#include "TimingData.h" +#include "Json/Value.h" +#include "JsonUtil.h" +#include "Song.h" +#include "BackgroundUtil.h" +#include "Steps.h" +#include "NoteData.h" +#include "GameManager.h" + +void Serialize(const BPMSegment &seg, Json::Value &root) +{ + root["Beat"] = NoteRowToBeat(seg.m_iStartRow); + root["BPM"] = seg.m_fBPS * 60; +} + +static void Serialize(const StopSegment &seg, Json::Value &root) +{ + root["Beat"] = NoteRowToBeat(seg.m_iStartRow); + root["Seconds"] = seg.m_fStopSeconds; +} + +static void Serialize(const TimingData &td, Json::Value &root) +{ + JsonUtil::SerializeVectorObjects( td.m_BPMSegments, Serialize, root["BpmSegments"] ); + JsonUtil::SerializeVectorObjects( td.m_StopSegments, Serialize, root["StopSegments"] ); +} + +static void Serialize(const LyricSegment &o, Json::Value &root) +{ + root["StartTime"] = (float)o.m_fStartTime; + root["Lyric"] = o.m_sLyric; + root["Color"] = o.m_Color.ToString(); +} + +static void Serialize(const BackgroundDef &o, Json::Value &root) +{ + root["Effect"] = o.m_sEffect; + root["File1"] = o.m_sFile1; + root["File2"] = o.m_sFile2; + root["Color1"] = o.m_sColor1; +} + +static void Serialize(const BackgroundChange &o, Json::Value &root ) +{ + Serialize( o.m_def, root["Def"] ); + root["StartBeat"] = o.m_fStartBeat; + root["Rate"] = o.m_fRate; + root["Transition"] = o.m_sTransition; +} + +static void Serialize( const TapNote &o, Json::Value &root ) +{ + root = Json::Value(Json::objectValue); + + if( o.type != TapNote::tap ) + root["Type"] = (int)o.type; + if( o.type == TapNote::hold_head ) + root["SubType"] = (int)o.subType; + //root["Source"] = (int)source; + if( !o.sAttackModifiers.empty() ) + root["AttackModifiers"] = o.sAttackModifiers; + if( o.fAttackDurationSeconds > 0 ) + root["AttackDurationSeconds"] = o.fAttackDurationSeconds; + if( o.iKeysoundIndex != -1 ) + root["KeysoundIndex"] = o.iKeysoundIndex; + if( o.iDuration > 0 ) + root["Duration"] = o.iDuration; + if( o.pn != PLAYER_INVALID ) + root["PlayerNumber"] = (int)o.pn; +} + +static void Serialize( const NoteData &o, Json::Value &root ) +{ + root = Json::Value(Json::arrayValue); + int iNumTracks = o.GetNumTracks(); + for(int t=0; tfirst; + TapNote tn = begin->second; + root.resize( root.size()+1 ); + Json::Value &root2 = root[ root.size()-1 ]; + root2 = Json::Value(Json::arrayValue); + root2.resize(3); + root2[(unsigned)0] = NoteRowToBeat(iRow); + root2[1] = t; + Serialize( tn, root2[2] ); + } + } +} + +static void Serialize( const RadarValues &o, Json::Value &root ) +{ + FOREACH_ENUM( RadarCategory, rc ) + { + root[ RadarCategoryToString(rc) ] = o.m_Values.f[rc]; + } +} + +static void Serialize( const Steps &o, Json::Value &root ) +{ + root["StepsType"] = StringConversion::ToString(o.m_StepsType); + + o.Decompress(); + + NoteData nd; + o.GetNoteData( nd ); + Serialize( nd, root["NoteData"] ); + root["Hash"] = o.GetHash(); + root["Description"] = o.GetDescription(); + root["Difficulty"] = DifficultyToString(o.GetDifficulty()); + root["Meter"] = o.GetMeter(); + Serialize( o.GetRadarValues( PLAYER_1 ), root["RadarValues"] ); +} + + +bool NotesWriterJson::WriteSong( const RString &sFile, const Song &out, bool bWriteSteps ) +{ + Json::Value root; + root["SongDir"] = out.GetSongDir(); + root["GroupName"] = out.m_sGroupName; + root["Title"] = out.m_sMainTitle; + root["SubTitle"] = out.m_sSubTitle; + root["Artist"] = out.m_sArtist; + root["TitleTranslit"] = out.m_sMainTitleTranslit; + root["SubTitleTranslit"] = out.m_sSubTitleTranslit; + root["Genre"] = out.m_sGenre; + root["Credit"] = out.m_sCredit; + root["Banner"] = out.m_sBannerFile; + root["Background"] = out.m_sBackgroundFile; + root["LyricsFile"] = out.m_sLyricsFile; + root["CDTitle"] = out.m_sCDTitleFile; + root["Music"] = out.m_sMusicFile; + root["Offset"] = out.m_Timing.m_fBeat0OffsetInSeconds; + root["SampleStart"] = out.m_fMusicSampleStartSeconds; + root["SampleLength"] = out.m_fMusicSampleLengthSeconds; + if( out.m_SelectionDisplay == Song::SHOW_ALWAYS ) + root["Selectable"] = "YES"; + else if( out.m_SelectionDisplay == Song::SHOW_NEVER ) + root["Selectable"] = "NO"; + else + root["Selectable"] = "YES"; + + root["FirstBeat"] = out.m_fFirstBeat; + root["LastBeat"] = out.m_fLastBeat; + root["SongFileName"] = out.m_sSongFileName; + root["HasMusic"] = out.m_bHasMusic; + root["HasBanner"] = out.m_bHasBanner; + root["MusicLengthSeconds"] = out.m_fMusicLengthSeconds; + + root["DisplayBpmType"] = StringConversion::ToString(out.m_DisplayBPMType); + if( out.m_DisplayBPMType == DISPLAY_BPM_SPECIFIED ) + { + root["SpecifiedBpmMin"] = out.m_fSpecifiedBPMMin; + root["SpecifiedBpmMax"] = out.m_fSpecifiedBPMMax; + } + + Serialize( out.m_Timing, root["TimingData"] ); + JsonUtil::SerializeVectorObjects( out.m_LyricSegments, Serialize, root["LyricSegments"] ); + + { + Json::Value &root2 = root["BackgroundChanges"]; + FOREACH_BackgroundLayer( bl ) + { + Json::Value &root3 = root2[bl]; + const vector &vBgc = out.GetBackgroundChanges(bl); + JsonUtil::SerializeVectorObjects( vBgc, Serialize, root3 ); + } + } + + { + const vector &vBgc = out.GetForegroundChanges(); + JsonUtil::SerializeVectorObjects( vBgc, Serialize, root["ForegroundChanges"] ); + } + + JsonUtil::SerializeArrayValues( out.m_vsKeysoundFile, root["KeySounds"] ); + + if( bWriteSteps ) + { + vector vpSteps; + FOREACH_CONST( Steps*, out.GetAllSteps(), iter ) + { + if( (*iter)->IsAutogen() ) + continue; + vpSteps.push_back( *iter ); + } + JsonUtil::SerializeVectorPointers( vpSteps, Serialize, root["Charts"] ); + } + + return JsonUtil::WriteFile( root, sFile, false ); +} + +bool NotesWriterJson::WriteSteps( const RString &sFile, const Steps &out ) +{ + Json::Value root; + Serialize( out, root ); + return JsonUtil::WriteFile( root, sFile, false ); +} + +/* + * (c) 2001-2004 Chris Danford, Glenn Maynard + * 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. + */ diff --git a/src/NotesWriterJson.h b/src/NotesWriterJson.h new file mode 100644 index 0000000000..c873733f96 --- /dev/null +++ b/src/NotesWriterJson.h @@ -0,0 +1,40 @@ +/* NotesWriterJson - Writes a Song to a .json file. */ + +#ifndef NotesWriterJson_H +#define NotesWriterJson_H + +class Song; +class Steps; + +namespace NotesWriterJson +{ + static bool WriteSong( const RString &sFile, const Song &out, bool bWriteSteps ); + static bool WriteSteps( const RString &sFile, const Steps &out ); +}; + +#endif + +/* + * (c) 2001-2010 Chris Danford, Glenn Maynard + * 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. + */ diff --git a/src/Song.h b/src/Song.h index 9c105a5732..479457ec56 100644 --- a/src/Song.h +++ b/src/Song.h @@ -73,6 +73,7 @@ class Song RString m_sSongDir; public: void SetSongDir( const RString sDir ) { m_sSongDir = sDir; } + RString GetSongDir() { return m_sSongDir; } /** @brief When should this song be displayed in the music wheel? */ enum SelectionDisplay diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index 7d7f87a40d..2dfb5b7eb1 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -1575,6 +1575,14 @@ RelativePath="NotesLoaderDWI.h" > + + + + @@ -1755,6 +1763,14 @@ RelativePath="NotesWriterDWI.h" > + + + +