Steps* pointers as possible. It is pointless to get rid of RevertFromDisk entirely because all of the unpleasant side effects it can have are possible using other tools in the editor.
253 lines
9.0 KiB
C++
253 lines
9.0 KiB
C++
/* Song - Holds all music metadata and steps for one song. */
|
|
|
|
#ifndef SONG_H
|
|
#define SONG_H
|
|
|
|
#include "TimingData.h"
|
|
#include "Difficulty.h"
|
|
#include "EnumHelper.h"
|
|
#include "RageUtil_AutoPtr.h"
|
|
#include "RageTypes.h"
|
|
|
|
class Steps;
|
|
class Style;
|
|
class NotesLoader;
|
|
class LyricsLoader;
|
|
class Profile;
|
|
class StepsID;
|
|
struct lua_State;
|
|
struct BackgroundChange;
|
|
|
|
const int MAX_EDITS_PER_SONG_PER_PROFILE = 5;
|
|
const int MAX_EDITS_PER_SONG = 5*NUM_ProfileSlot;
|
|
|
|
extern const int FILE_CACHE_VERSION;
|
|
|
|
enum BackgroundLayer
|
|
{
|
|
BACKGROUND_LAYER_1,
|
|
BACKGROUND_LAYER_2,
|
|
NUM_BackgroundLayer,
|
|
BACKGROUND_LAYER_Invalid
|
|
};
|
|
#define FOREACH_BackgroundLayer( bl ) FOREACH_ENUM( BackgroundLayer, bl )
|
|
|
|
struct LyricSegment
|
|
{
|
|
float m_fStartTime;
|
|
RString m_sLyric;
|
|
RageColor m_Color;
|
|
};
|
|
|
|
class Song
|
|
{
|
|
RString m_sSongDir;
|
|
public:
|
|
void SetSongDir( const RString sDir ) { m_sSongDir = sDir; }
|
|
|
|
/* Set when this song should be displayed in the music wheel: */
|
|
enum SelectionDisplay
|
|
{
|
|
SHOW_ALWAYS, /* all the time */
|
|
SHOW_ROULETTE, /* only when rouletting */
|
|
SHOW_NEVER /* never (unless song hiding is turned off) */
|
|
} m_SelectionDisplay;
|
|
|
|
Song();
|
|
~Song();
|
|
void Reset();
|
|
void DetachSteps();
|
|
|
|
// This one assumes the song is currently empty
|
|
bool LoadFromSongDir( RString sDir );
|
|
// This one takes the effort to reuse Steps pointers as best as it can
|
|
bool ReloadFromSongDir( RString sDir );
|
|
|
|
void TidyUpData(); // call after loading to clean up invalid data
|
|
void ReCalculateRadarValuesAndLastBeat(); // called by TidyUpData, and after saving
|
|
void TranslateTitles(); // called by TidyUpData
|
|
|
|
void SaveToSMFile( RString sPath, bool bSavingCache );
|
|
void Save(); // saves SM and DWI
|
|
void SaveToCacheFile();
|
|
void SaveToDWIFile();
|
|
|
|
const RString &GetSongFilePath() const;
|
|
RString GetCacheFilePath() const;
|
|
|
|
void AddAutoGenNotes();
|
|
void AutoGen( StepsType ntTo, StepsType ntFrom ); // create Steps of type ntTo from Steps of type ntFrom
|
|
void RemoveAutoGenNotes();
|
|
|
|
/* Directory this song data came from: */
|
|
const RString &GetSongDir() const { return m_sSongDir; }
|
|
|
|
/* Filename associated with this file. This will always have
|
|
* an .SM extension. If we loaded an .SM, this will point to
|
|
* it, but if we loaded any other type, this will point to a
|
|
* generated .SM filename. */
|
|
RString m_sSongFileName;
|
|
|
|
RString m_sGroupName;
|
|
|
|
ProfileSlot m_LoadedFromProfile; // ProfileSlot_Invalid if wasn't loaded from a profile
|
|
bool m_bIsSymLink;
|
|
|
|
RString m_sMainTitle, m_sSubTitle, m_sArtist;
|
|
RString m_sMainTitleTranslit, m_sSubTitleTranslit, m_sArtistTranslit;
|
|
|
|
/* If PREFSMAN->m_bShowNative is off, these are the same as GetTranslit* below.
|
|
* Otherwise, they return the main titles. */
|
|
RString GetDisplayMainTitle() const;
|
|
RString GetDisplaySubTitle() const;
|
|
RString GetDisplayArtist() const;
|
|
|
|
/* Returns the transliterated titles, if any; otherwise returns the main titles. */
|
|
RString GetTranslitMainTitle() const { return m_sMainTitleTranslit.size()? m_sMainTitleTranslit: m_sMainTitle; }
|
|
RString GetTranslitSubTitle() const { return m_sSubTitleTranslit.size()? m_sSubTitleTranslit: m_sSubTitle; }
|
|
RString GetTranslitArtist() const { return m_sArtistTranslit.size()? m_sArtistTranslit:m_sArtist; }
|
|
|
|
/* "title subtitle" */
|
|
RString GetDisplayFullTitle() const;
|
|
RString GetTranslitFullTitle() const;
|
|
|
|
RString m_sGenre;
|
|
|
|
/* This is read and saved, but never actually used. */
|
|
RString m_sCredit;
|
|
|
|
RString m_sMusicFile;
|
|
float m_fMusicLengthSeconds;
|
|
float m_fFirstBeat; // beat of first note
|
|
float m_fLastBeat; // beat of last note
|
|
float m_fSpecifiedLastBeat; // specified last beat of the song
|
|
float m_fMusicSampleStartSeconds;
|
|
float m_fMusicSampleLengthSeconds;
|
|
enum { DISPLAY_ACTUAL, DISPLAY_SPECIFIED, DISPLAY_RANDOM } m_DisplayBPMType;
|
|
float m_fSpecifiedBPMMin;
|
|
float m_fSpecifiedBPMMax; // if a range, then Min != Max
|
|
|
|
RString m_sBannerFile;
|
|
RString m_sLyricsFile;
|
|
RString m_sBackgroundFile;
|
|
RString m_sCDTitleFile;
|
|
|
|
RString GetMusicPath() const;
|
|
RString GetBannerPath() const;
|
|
RString GetLyricsPath() const;
|
|
RString GetBackgroundPath() const;
|
|
RString GetCDTitlePath() const;
|
|
|
|
/* For loading only: */
|
|
bool m_bHasMusic, m_bHasBanner;
|
|
|
|
bool HasMusic() const;
|
|
bool HasBanner() const;
|
|
bool HasBackground() const;
|
|
bool HasCDTitle() const;
|
|
bool HasMovieBackground() const;
|
|
bool HasBGChanges() const;
|
|
bool HasLyrics() const;
|
|
|
|
bool Matches(RString sGroup, RString sSong) const;
|
|
|
|
TimingData m_Timing;
|
|
|
|
typedef vector<BackgroundChange> VBackgroundChange;
|
|
private:
|
|
// AutoPtr instead of raw pointer so that the auto gen'd copy constructor works correctly.
|
|
AutoPtrCopyOnWrite<VBackgroundChange> m_BackgroundChanges[NUM_BackgroundLayer]; // these must be sorted before gameplay
|
|
AutoPtrCopyOnWrite<VBackgroundChange> m_ForegroundChanges; // this must be sorted before gameplay
|
|
public:
|
|
const vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl ) const;
|
|
vector<BackgroundChange> &GetBackgroundChanges( BackgroundLayer bl );
|
|
const vector<BackgroundChange> &GetForegroundChanges() const;
|
|
vector<BackgroundChange> &GetForegroundChanges();
|
|
|
|
vector<LyricSegment> m_LyricSegments; // this must be sorted before gameplay
|
|
|
|
void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); }
|
|
void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); }
|
|
void AddBackgroundChange( BackgroundLayer blLayer, BackgroundChange seg );
|
|
void AddForegroundChange( BackgroundChange seg );
|
|
void AddLyricSegment( LyricSegment seg );
|
|
|
|
void GetDisplayBpms( DisplayBpms &AddTo ) const;
|
|
const BackgroundChange &GetBackgroundAtBeat( BackgroundLayer iLayer, float fBeat ) const;
|
|
|
|
float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); }
|
|
void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); }
|
|
BPMSegment& GetBPMSegmentAtBeat( float fBeat ) { return m_Timing.GetBPMSegmentAtBeat( fBeat ); }
|
|
float GetBeatFromElapsedTime( float fElapsedTime ) const { return m_Timing.GetBeatFromElapsedTime( fElapsedTime ); }
|
|
float GetElapsedTimeFromBeat( float fBeat ) const { return m_Timing.GetElapsedTimeFromBeat( fBeat ); }
|
|
bool HasSignificantBpmChangesOrStops() const;
|
|
float GetStepsSeconds() const;
|
|
bool IsLong() const;
|
|
bool IsMarathon() const;
|
|
|
|
bool SongCompleteForStyle( const Style *st ) const;
|
|
bool HasStepsType( StepsType st ) const;
|
|
bool HasStepsTypeAndDifficulty( StepsType st, Difficulty dc ) const;
|
|
const vector<Steps*>& GetAllSteps() const { return m_vpSteps; }
|
|
const vector<Steps*>& GetStepsByStepsType( StepsType st ) const { return m_vpStepsByType[st]; }
|
|
bool IsEasy( StepsType st ) const;
|
|
bool IsTutorial() const;
|
|
bool HasEdits( StepsType st ) const;
|
|
SelectionDisplay GetDisplayed() const;
|
|
bool NormallyDisplayed() const;
|
|
bool NeverDisplayed() const;
|
|
bool RouletteDisplayed() const;
|
|
bool ShowInDemonstrationAndRanking() const;
|
|
|
|
void AddSteps( Steps* pSteps ); // we are responsible for deleting the memory pointed to by pSteps!
|
|
void DeleteSteps( const Steps* pSteps, bool bReAutoGen = true );
|
|
|
|
void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_Invalid );
|
|
bool WasLoadedFromProfile() const { return m_LoadedFromProfile != ProfileSlot_Invalid; }
|
|
void GetStepsLoadedFromProfile( ProfileSlot slot, vector<Steps*> &vpStepsOut ) const;
|
|
int GetNumStepsLoadedFromProfile( ProfileSlot slot ) const;
|
|
bool IsEditAlreadyLoaded( Steps* pSteps ) const;
|
|
|
|
// An array of keysound file names (e.g. "beep.wav").
|
|
// The index in this array corresponds to the index in TapNote. If you
|
|
// change the index in here, you must change all NoteData too.
|
|
// Any note that doesn't have a value in the range of this array
|
|
// means "this note doens't have a keysound".
|
|
vector<RString> m_vsKeysoundFile;
|
|
|
|
// Lua
|
|
void PushSelf( lua_State *L );
|
|
|
|
private:
|
|
|
|
vector<Steps*> m_vpSteps;
|
|
vector<Steps*> m_vpStepsByType[NUM_StepsType];
|
|
};
|
|
|
|
#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.
|
|
*/
|