[default -> loading window] YAM
This commit is contained in:
@@ -8,6 +8,26 @@ ________________________________________________________________________________
|
||||
StepMania 5.0 Preview 2 | 20110???
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
2011/06/10
|
||||
----------
|
||||
* [ScreenEdit] Split the Area Menu into the Area Menu and Alter Menu. Use the
|
||||
"A" key to enter the Alter Menu when a selection of notes/rows are
|
||||
highlighted. Use the Enter key to enter the old Area Menu for the options that
|
||||
do not depend on selecting NoteData. [Wolfman2000]
|
||||
* [ScreenEdit] Allow converting selections to Delays, Warps, or Fakes as well
|
||||
as Stops. Remember, use the Alter Menu for this. [Wolfman2000]
|
||||
|
||||
2011/06/09
|
||||
----------
|
||||
* [ScreenSyncOverlay] Ensure that F11 / F12 work with all charts due to Split
|
||||
Timing. [Wolfman2000]
|
||||
|
||||
2011/06/08
|
||||
----------
|
||||
* Any notes in a fake segment or warp segment are completely ignored for
|
||||
scoring purposes. Now you can get 100% on your warping goodness!
|
||||
[Wolfman2000]
|
||||
|
||||
2011/06/06
|
||||
----------
|
||||
* [PlayerOptions] Removed the ScoreDisplay mod choices. Use lua to make your
|
||||
|
||||
+57
-5
@@ -39,11 +39,8 @@
|
||||
<Function name='FormatNumberAndSuffix'/>
|
||||
<Function name='FormatPercentScore'/>
|
||||
<Function name='GameCompatibleModes'/>
|
||||
<Function name='GamePrefAutoSetStyle'/>
|
||||
<Function name='GamePrefComboOnRolls'/>
|
||||
<Function name='GamePrefComboUnderField'/>
|
||||
<Function name='GamePrefDefaultFail'/>
|
||||
<Function name='GamePrefNotePosition'/>
|
||||
<Function name='GetCoursesToShowRanking'/>
|
||||
<Function name='GetCustomDifficulty'/>
|
||||
<Function name='GetDefaultOptionLines'/>
|
||||
@@ -57,6 +54,7 @@
|
||||
<Function name='GetGradeFromPercent'/>
|
||||
<Function name='GetLifeDifficulty'/>
|
||||
<Function name='GetOSName'/>
|
||||
<Function name='GetPlayerOrMachineProfile'/>
|
||||
<Function name='GetProTiming'/>
|
||||
<Function name='GetRandomSongBackground'/>
|
||||
<Function name='GetReal'/>
|
||||
@@ -130,7 +128,6 @@
|
||||
<Function name='PrintTable'/>
|
||||
<Function name='ProductID'/>
|
||||
<Function name='ProductVersion'/>
|
||||
<Function name='Profile'/>
|
||||
<Function name='RadarCategoryToLocalizedString'/>
|
||||
<Function name='ReadGamePrefFromFile'/>
|
||||
<Function name='ReadPrefFromFile'/>
|
||||
@@ -143,6 +140,8 @@
|
||||
<Function name='Saturation'/>
|
||||
<Function name='ScoreKeeperClass'/>
|
||||
<Function name='ScoreMissedHoldsAndRolls'/>
|
||||
<Function name='ScreenMetric'/>
|
||||
<Function name='ScreenString'/>
|
||||
<Function name='Second'/>
|
||||
<Function name='SecondsToHHMMSS'/>
|
||||
<Function name='SecondsToMMSS'/>
|
||||
@@ -1026,6 +1025,52 @@
|
||||
<Function name='SetPreference'/>
|
||||
<Function name='SetPreferenceToDefault'/>
|
||||
</Class>
|
||||
<Class name='Profile'>
|
||||
<Function name='GetCaloriesBurnedToday'/>
|
||||
<Function name='GetCharacter'/>
|
||||
<Function name='GetCoursesActual'/>
|
||||
<Function name='GetCoursesPercentComplete'/>
|
||||
<Function name='GetCoursesPossible'/>
|
||||
<Function name='GetDisplayName'/>
|
||||
<Function name='GetDisplayTotalCaloriesBurned'/>
|
||||
<Function name='GetGoalCalories'/>
|
||||
<Function name='GetGoalSeconds'/>
|
||||
<Function name='GetGoalType'/>
|
||||
<Function name='GetHighScoreList'/>
|
||||
<Function name='GetLastUsedHighScoreName'/>
|
||||
<Function name='GetMostPopularCourse'/>
|
||||
<Function name='GetMostPopularSong'/>
|
||||
<Function name='GetNumToasties'/>
|
||||
<Function name='GetNumTotalSongsPlayed'/>
|
||||
<Function name='GetSongNumTimesPlayed'/>
|
||||
<Function name='GetSongsActual'/>
|
||||
<Function name='GetSongsAndCoursesPercentCompleteAllDifficulties'/>
|
||||
<Function name='GetSongsPercentComplete'/>
|
||||
<Function name='GetSongsPossible'/>
|
||||
<Function name='GetTotalCaloriesBurned'/>
|
||||
<Function name='GetTotalGameplaySeconds'/>
|
||||
<Function name='GetTotalHands'/>
|
||||
<Function name='GetTotalHolds'/>
|
||||
<Function name='GetTotalJumps'/>
|
||||
<Function name='GetTotalLifts'/>
|
||||
<Function name='GetTotalMines'/>
|
||||
<Function name='GetTotalNumSongsPlayed'/>
|
||||
<Function name='GetTotalRolls'/>
|
||||
<Function name='GetTotalSessionSeconds'/>
|
||||
<Function name='GetTotalSessions'/>
|
||||
<Function name='GetTotalStepsWithTopGrade'/>
|
||||
<Function name='GetTotalTapsAndHolds'/>
|
||||
<Function name='GetTotalTrailsWithTopGrade'/>
|
||||
<Function name='GetUserData'/>
|
||||
<Function name='GetWeightPounds'/>
|
||||
<Function name='HasPassedAnyStepsInSong'/>
|
||||
<Function name='IsCodeUnlocked'/>
|
||||
<Function name='SetCharacter'/>
|
||||
<Function name='SetGoalCalories'/>
|
||||
<Function name='SetGoalSeconds'/>
|
||||
<Function name='SetGoalType'/>
|
||||
<Function name='SetWeightPounds'/>
|
||||
</Class>
|
||||
<Class name='ProfileManager'>
|
||||
<Function name='GetLocalProfile'/>
|
||||
<Function name='GetLocalProfileFromIndex'/>
|
||||
@@ -1093,6 +1138,13 @@
|
||||
</Class>
|
||||
<Class base='BitmapText' name='ScoreDisplayAliveTime'/>
|
||||
<Class base='BitmapText' name='ScoreDisplayCalories'/>
|
||||
<Class base='ActorFrame' name='Screen'>
|
||||
<Function name='GetNextScreenName'/>
|
||||
<Function name='GetPrevScreenName'/>
|
||||
<Function name='GetScreenType'/>
|
||||
<Function name='PostScreenMessage'/>
|
||||
<Function name='lockinput'/>
|
||||
</Class>
|
||||
<Class base='ScreenWithMenuElements' name='ScreenAttract'/>
|
||||
<Class base='ScreenWithMenuElements' name='ScreenEdit'>
|
||||
<Function name='GetEditState'/>
|
||||
@@ -2061,5 +2113,5 @@
|
||||
<Constant name='top' value=''VertAlign_Top''/>
|
||||
</Constants>
|
||||
<Version>StepMania 5 v5.0 Preview 1a</Version>
|
||||
<Date>2011-06-04</Date>
|
||||
<Date>2011-06-11</Date>
|
||||
</Lua>
|
||||
|
||||
+6
-1
@@ -395,7 +395,12 @@
|
||||
$type='bool' or
|
||||
$type='table' or
|
||||
$type='color' or
|
||||
$type='Enum'">
|
||||
$type='Enum' or
|
||||
$type='ThreadVariable' or
|
||||
$type='LuaOptionRow' or
|
||||
$type='ActorDef' or
|
||||
$type='chunk' or
|
||||
$type='various'">
|
||||
<span class="primitiveType">
|
||||
<xsl:value-of select="$type" />
|
||||
</span>
|
||||
|
||||
@@ -807,12 +807,16 @@ Clear Machine Edits=Clear Machine Edits
|
||||
Clear Machine Stats=Clear Machine Scores
|
||||
Clear USB edits=Clear USB edits
|
||||
Clear area=Clear area
|
||||
Clear clipboard=Clear clipboard
|
||||
CoinMode=Coin Mode
|
||||
CoinModeNoHome=Coin Mode
|
||||
CoinsPerCredit=Coins Per Credit
|
||||
Connection=Connection
|
||||
Convert pause to beats=Convert pause to beats
|
||||
Convert selection to pause=Convert selection to pause
|
||||
Convert selection to delay=Convert selection to delay
|
||||
Convert selection to warp=Convert selection to Warp Segment
|
||||
Convert selection to fake=Convert selection to Fake Segment
|
||||
Copy=Copy
|
||||
CourseSortOrder=Course Sort
|
||||
Create New=Create New
|
||||
@@ -1257,7 +1261,7 @@ Enter a new min BPM.=Enter the minimum displayed BPM.
|
||||
Enter a new max BPM.=Enter the maximum displayed BPM.
|
||||
More than %d notes per measure is not allowed. This change has been reverted.=More than %d notes per measure is not allowed. This change has been reverted.
|
||||
No backgrounds available=No backgrounds available
|
||||
EditHelpText=Up/Down:\n change beat\nLeft/Right:\n change snap\nNumber keys:\n add/remove\n tap note\nN and M keys:\n swap tap notes\nCreate hold note:\n Hold a number\n while moving\n Up or Down\nCreate roll note:\n Hold Shift,\n then create a\n hold note.\nSpace bar:\n Set area\n marker\nEnter:\n Area Menu\nEscape:\n Main Menu\nF4:\n Timing Menu\nF1:\n Show help\n
|
||||
EditHelpText=Up/Down:\n change beat\nLeft/Right:\n change snap\nNumber keys:\n add/remove\n tap note\nN and M keys:\n swap tap notes\nCreate hold note:\n Hold a number\n while moving\n Up or Down\nCreate roll note:\n Hold Shift,\n then create a\n hold note.\nSpace bar:\n Set area\n marker\nT key:\n Switch Timing\nEnter:\n Area Menu\nA Key: Alter Menu\nEscape:\n Main Menu\nF4:\n Timing Menu\nF1:\n Show help\n
|
||||
PlayRecordHelpText=Press START to end
|
||||
Save successful.=Save successful.
|
||||
Saved as SM and DWI.=Saved as SM and DWI.
|
||||
@@ -1269,6 +1273,7 @@ This change creates notes past the end of the music and is not allowed.=This cha
|
||||
This will destroy all unsaved changes.=This will destroy all unsaved changes.
|
||||
Undo=Undo
|
||||
You must be in Song Timing Mode to edit BG Changes.=You must be in Song Timing Mode to edit BG Changes.
|
||||
You must have an area selected to enter the Alter Menu.=You must have an area selected to enter the Alter Menu.
|
||||
|
||||
Current beat=Current beat
|
||||
Current second=Current second
|
||||
|
||||
@@ -21,3 +21,11 @@ local _screen = {
|
||||
cx = SCREEN_CENTER_X,
|
||||
cy = SCREEN_CENTER_Y
|
||||
}
|
||||
|
||||
if Screen.String then
|
||||
ScreenString = Screen.String
|
||||
end
|
||||
|
||||
if Screen.Metric then
|
||||
ScreenMetric = Screen.Metric
|
||||
end
|
||||
@@ -98,16 +98,15 @@ end
|
||||
|
||||
-- Get a metric from the currently-loading screen. This is only valid while loading
|
||||
-- an actor, such as from File or InitCommand attributes; not from commands.
|
||||
Screen = {
|
||||
Metric = function ( sName )
|
||||
local sClass = Var "LoadingScreen"
|
||||
return THEME:GetMetric( sClass, sName )
|
||||
end,
|
||||
String = function ( sName )
|
||||
local sClass = Var "LoadingScreen";
|
||||
return THEME:GetString( sClass, sName )
|
||||
end
|
||||
};
|
||||
Screen.Metric = function ( sName )
|
||||
local sClass = Var "LoadingScreen"
|
||||
return THEME:GetMetric( sClass, sName )
|
||||
end
|
||||
|
||||
Screen.String = function ( sName )
|
||||
local sClass = Var "LoadingScreen";
|
||||
return THEME:GetString( sClass, sName )
|
||||
end
|
||||
|
||||
function TextBannerAfterSet(self,param)
|
||||
local Title=self:GetChild("Title");
|
||||
|
||||
@@ -148,7 +148,9 @@ end
|
||||
-- MaskSource([clearzbuffer])
|
||||
-- Sets an actor up as the source for a mask. Clears zBuffer by default.
|
||||
function Actor:MaskSource(noclear)
|
||||
self:clearzbuffer(noclear or true)
|
||||
if noclear == true then
|
||||
self:clearzbuffer(true)
|
||||
end
|
||||
self:zwrite(true)
|
||||
self:blend('BlendMode_NoEffect')
|
||||
end
|
||||
|
||||
@@ -150,7 +150,7 @@ function InitUserPrefs()
|
||||
end;
|
||||
|
||||
function UserPrefScoringMode()
|
||||
local baseChoices = { 'DDR 1stMIX', 'DDR 4thMIX', 'DDR Extreme', 'DDR SuperNOVA', 'DDR SuperNOVA 2', 'MIGS' }; --'[SSC] Radar Master'
|
||||
local baseChoices = { 'DDR 1stMIX', 'DDR 4thMIX', 'DDR Extreme', 'DDR SuperNOVA', 'DDR SuperNOVA 2', 'MIGS', 'HYBRID' }; --'[SSC] Radar Master'
|
||||
local t = {
|
||||
Name = "UserPrefScoringMode";
|
||||
LayoutType = "ShowAllInRow";
|
||||
|
||||
@@ -122,6 +122,48 @@ r['DDR Extreme'] = function(params, pss)
|
||||
Shared.CurrentStep[pn] = 0; -- Reset for the next song.
|
||||
end;
|
||||
end;
|
||||
|
||||
-----------------------------------------------------------
|
||||
--HYBRID Scoring
|
||||
-----------------------------------------------------------
|
||||
r['HYBRID'] = function(params, pss)
|
||||
local multLookup =
|
||||
{
|
||||
['TapNoteScore_W1'] = 10,
|
||||
['TapNoteScore_W2'] = 9,
|
||||
['TapNoteScore_W3'] = 5
|
||||
};
|
||||
setmetatable(multLookup, ZeroIfNotFound);
|
||||
local radarValues = GetDirectRadar(params.Player);
|
||||
local totalItems = GetTotalItems(radarValues)
|
||||
- radarValues:GetValue('RadarCategory_Lifts');
|
||||
-- 1+2+3+...+totalItems の値
|
||||
local sTotal = (totalItems+1)*totalItems/2;
|
||||
-- [en] Score for one song
|
||||
-- [ja] 1つあたりのスコア
|
||||
local sOne = math.floor(100000000/sTotal);
|
||||
-- [ja] 端数は最後の1ステップで加算するのでその値を取得
|
||||
local sLast = 100000000-(sOne*sTotal);
|
||||
-- [ja] 現在何個目の譜面か
|
||||
pss:SetCurMaxScore(pss:GetCurMaxScore()+1);
|
||||
-- [en] current score
|
||||
-- [ja] 今回のスコア
|
||||
local vScore = sOne*(pss:GetCurMaxScore());
|
||||
if (params.HoldNoteScore == 'HoldNoteScore_Held') then
|
||||
vScore = vScore;
|
||||
else
|
||||
if (params.HoldNoteScore == 'HoldNoteScore_LetGo') then
|
||||
vScore = 0;
|
||||
else
|
||||
vScore = vScore*multLookup[params.TapNoteScore]/10;
|
||||
end;
|
||||
end;
|
||||
if ((vScore > 0) and (pss:GetCurMaxScore() == totalItems)) then
|
||||
vScore = vScore+sLast;
|
||||
end;
|
||||
pss:SetScore(pss:GetScore()+vScore);
|
||||
end;
|
||||
|
||||
-----------------------------------------------------------
|
||||
--DDR SuperNOVA(-esque) scoring
|
||||
-----------------------------------------------------------
|
||||
@@ -148,24 +190,47 @@ end;
|
||||
r['DDR SuperNOVA 2'] = function(params, pss)
|
||||
local multLookup =
|
||||
{
|
||||
['TapNoteScore_W1'] = 1,
|
||||
['TapNoteScore_W2'] = 1,
|
||||
['TapNoteScore_W3'] = 0.5
|
||||
['TapNoteScore_W1'] = 10,
|
||||
['TapNoteScore_W2'] = 10,
|
||||
['TapNoteScore_W3'] = 5
|
||||
};
|
||||
setmetatable(multLookup, ZeroIfNotFound);
|
||||
local radarValues = GetDirectRadar(params.Player);
|
||||
local totalItems = GetTotalItems(radarValues);
|
||||
local base = 100000 / totalItems;
|
||||
local hold = base * (params.HoldNoteScore == 'HoldNoteScore_Held' and 1 or 0);
|
||||
local maxScore = (base * multLookup['TapNoteScore_W1']) + hold;
|
||||
pss:SetCurMaxScore(pss:GetCurMaxScore() + (math.round(maxScore) * 10));
|
||||
local preW1 = base * multLookup[params.TapNoteScore];
|
||||
local buildScore = (preW1 - (IsW1Allowed(params.TapNoteScore) and 10 or 0)) + hold;
|
||||
pss:SetScore(pss:GetScore() + (math.round(buildScore) * 10));
|
||||
local numLifts = radarValues:GetCategory('RadarCategory_Lifts')
|
||||
local numFakes = radarValues:GetCategory('RadarCategory_Fakes')
|
||||
local totalItems = GetTotalItems(radarValues) - (numLifts + numFakes);
|
||||
|
||||
-- handle holds
|
||||
local maxAdd = 0
|
||||
if params.HoldNoteScore == 'HoldNoteScore_Held' then
|
||||
maxAdd = 10
|
||||
else
|
||||
if params.HoldNoteScore == 'HoldNoteScore_LetGo' then
|
||||
maxAdd = 0
|
||||
else
|
||||
maxAdd = multLookup[params.TapNoteScore]
|
||||
if params.TapNoteScore == 'TapNoteScore_W2' or 'TapNoteScore_W3' then
|
||||
-- [ja] 超最終手段
|
||||
pss:SetCurMaxScore( pss:GetCurMaxScore() + 1000000 )
|
||||
end
|
||||
end
|
||||
end
|
||||
pss:SetCurMaxScore(pss:GetCurMaxScore() + maxAdd);
|
||||
|
||||
--[[
|
||||
[ja] パフェ数取得 この方法で取得するとロングノートの場合2つカウントされる そのため使えない
|
||||
pss:GetTapNoteScores('TapNoteScore_W2')
|
||||
仕方がないのでパフェ数を 1000000 単位で GetCurMaxScore に記録
|
||||
その後、情報を分解して取り出す
|
||||
--]]
|
||||
|
||||
local vScore = pss:GetCurMaxScore() % 1000000
|
||||
local vSub = math.floor( pss:GetCurMaxScore()/1000000 )
|
||||
pss:SetScore( math.floor(10000*vScore/totalItems) * 10 - (vSub*10) );
|
||||
end;
|
||||
-----------------------------------------------------------
|
||||
--Radar Master (doesn't work in 1.2.1, disabled)
|
||||
--don't try to "fix it up", either. you *cannot* make it work in 1.2.1.
|
||||
--Radar Master (doesn't work in sm-ssc 1.2.1, disabled)
|
||||
--todo: get this working with StepMania 5
|
||||
-----------------------------------------------------------
|
||||
r['[SSC] Radar Master'] = function(params, pss)
|
||||
local masterTable = {
|
||||
|
||||
@@ -3752,6 +3752,9 @@ TitleX=SCREEN_CENTER_X-80
|
||||
[ScreenMiniMenuAreaMenu]
|
||||
Fallback="ScreenMiniMenu"
|
||||
|
||||
[ScreenMiniMenuAlterMenu]
|
||||
Fallback="ScreenMiniMenu"
|
||||
|
||||
[ScreenMiniMenuStepsInformation]
|
||||
Fallback="ScreenMiniMenu"
|
||||
|
||||
|
||||
@@ -5,7 +5,10 @@ t[#t+1] = Def.ActorFrame {
|
||||
Def.Sprite {
|
||||
OnCommand=function(self)
|
||||
if GAMESTATE:GetCurrentSong() then
|
||||
self:LoadBackground( GAMESTATE:GetCurrentSong():GetBackgroundPath() );
|
||||
local song = GAMESTATE:GetCurrentSong();
|
||||
if song:HasBackground() then
|
||||
self:LoadBackground(song:GetBackgroundPath());
|
||||
end;
|
||||
self:scaletoclipped( SCREEN_WIDTH+1,SCREEN_HEIGHT );
|
||||
(cmd(fadebottom,0.25;fadetop,0.25;croptop,48/480;cropbottom,48/480))(self);
|
||||
else
|
||||
|
||||
@@ -6,7 +6,10 @@ t[#t+1] = Def.ActorFrame {
|
||||
Condition=not GAMESTATE:IsCourseMode();
|
||||
OnCommand=function(self)
|
||||
if GAMESTATE:GetCurrentSong() then
|
||||
self:LoadBackground( GAMESTATE:GetCurrentSong():GetBackgroundPath() );
|
||||
local song = GAMESTATE:GetCurrentSong();
|
||||
if song:HasBackground() then
|
||||
self:LoadBackground(song:GetBackgroundPath());
|
||||
end;
|
||||
self:scaletoclipped( SCREEN_WIDTH+1,SCREEN_HEIGHT );
|
||||
(cmd(fadebottom,0.25;fadetop,0.25;croptop,48/480;cropbottom,48/480))(self);
|
||||
else
|
||||
|
||||
@@ -27,7 +27,6 @@ static ThemeMetric<float> LEFT_EDGE ("Background","LeftEdge");
|
||||
static ThemeMetric<float> TOP_EDGE ("Background","TopEdge");
|
||||
static ThemeMetric<float> RIGHT_EDGE ("Background","RightEdge");
|
||||
static ThemeMetric<float> BOTTOM_EDGE ("Background","BottomEdge");
|
||||
#define RECT_BACKGROUND RectF (LEFT_EDGE,TOP_EDGE,RIGHT_EDGE,BOTTOM_EDGE)
|
||||
static ThemeMetric<float> CLAMP_OUTPUT_PERCENT ("Background","ClampOutputPercent");
|
||||
static ThemeMetric<bool> SHOW_DANCING_CHARACTERS ("Background","ShowDancingCharacters");
|
||||
static ThemeMetric<bool> USE_STATIC_BG ("Background","UseStaticBackground");
|
||||
|
||||
@@ -142,8 +142,10 @@ static void StartMusic( MusicToPlay &ToPlay )
|
||||
{
|
||||
LOG->Trace( "Found '%s'", ToPlay.m_sTimingFile.c_str() );
|
||||
Song song;
|
||||
if( GetExtension(ToPlay.m_sTimingFile) == ".ssc" &&
|
||||
SSCLoader::LoadFromSSCFile(ToPlay.m_sTimingFile, song) )
|
||||
SSCLoader loaderSSC;
|
||||
SMLoader loaderSM;
|
||||
if(GetExtension(ToPlay.m_sTimingFile) == ".ssc" &&
|
||||
loaderSSC.LoadFromSimfile(ToPlay.m_sTimingFile, song) )
|
||||
{
|
||||
ToPlay.HasTiming = true;
|
||||
ToPlay.m_TimingData = song.m_SongTiming;
|
||||
@@ -152,8 +154,8 @@ static void StartMusic( MusicToPlay &ToPlay )
|
||||
if( pStepsCabinetLights )
|
||||
pStepsCabinetLights->GetNoteData( ToPlay.m_LightsData );
|
||||
}
|
||||
else if( GetExtension(ToPlay.m_sTimingFile) == ".sm" &&
|
||||
SMLoader::LoadFromSMFile(ToPlay.m_sTimingFile, song) )
|
||||
else if(GetExtension(ToPlay.m_sTimingFile) == ".sm" &&
|
||||
loaderSM.LoadFromSimfile(ToPlay.m_sTimingFile, song) )
|
||||
{
|
||||
ToPlay.HasTiming = true;
|
||||
ToPlay.m_TimingData = song.m_SongTiming;
|
||||
|
||||
@@ -106,6 +106,7 @@ static Preference<Premium> g_Premium( "Premium", Premium_Off );
|
||||
Preference<bool> GameState::m_bAutoJoin( "AutoJoin", false );
|
||||
|
||||
GameState::GameState() :
|
||||
processedTiming( NULL ),
|
||||
m_pCurGame( Message_CurrentGameChanged ),
|
||||
m_pCurStyle( Message_CurrentStyleChanged ),
|
||||
m_PlayMode( Message_PlayModeChanged ),
|
||||
@@ -200,6 +201,16 @@ void GameState::SetMasterPlayerNumber(const PlayerNumber p)
|
||||
this->masterPlayerNumber = p;
|
||||
}
|
||||
|
||||
TimingData * GameState::GetProcessedTimingData() const
|
||||
{
|
||||
return this->processedTiming;
|
||||
}
|
||||
|
||||
void GameState::SetProcessedTimingData(TimingData * t)
|
||||
{
|
||||
this->processedTiming = t;
|
||||
}
|
||||
|
||||
void GameState::ApplyGameCommand( const RString &sCommand, PlayerNumber pn )
|
||||
{
|
||||
GameCommand m;
|
||||
|
||||
@@ -37,6 +37,8 @@ class GameState
|
||||
{
|
||||
/** @brief The player number used with Styles where one player controls both sides. */
|
||||
PlayerNumber masterPlayerNumber;
|
||||
/** @brief The TimingData that is used for processing certain functions. */
|
||||
TimingData * processedTiming;
|
||||
public:
|
||||
/** @brief Set up the GameState with initial values. */
|
||||
GameState();
|
||||
@@ -149,6 +151,16 @@ public:
|
||||
* @brief Set the master player number.
|
||||
* @param p the master player number. */
|
||||
void SetMasterPlayerNumber(const PlayerNumber p);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the present timing data being processed.
|
||||
* @return the timing data pointer. */
|
||||
TimingData * GetProcessedTimingData() const;
|
||||
|
||||
/**
|
||||
* @brief Set the timing data to be used with processing.
|
||||
* @param t the timing data. */
|
||||
void SetProcessedTimingData(TimingData * t);
|
||||
|
||||
bool IsCourseMode() const;
|
||||
bool IsBattleMode() const; // not Rave
|
||||
|
||||
@@ -47,7 +47,7 @@ void GameplayAssist::PlayTicks( const NoteData &nd, const PlayerState *ps )
|
||||
if( nd.IsThereATapOrHoldHeadAtRow( r ) )
|
||||
iClapRow = r;
|
||||
|
||||
if( iClapRow != -1 && !timing.IsWarpAtRow( iClapRow ) && !timing.IsFakeAtRow( iClapRow ) )
|
||||
if( iClapRow != -1 && timing.IsJudgableAtRow(iClapRow))
|
||||
{
|
||||
const float fTickBeat = NoteRowToBeat( iClapRow );
|
||||
const float fTickSecond = timing.GetElapsedTimeFromBeatNoOffset( fTickBeat );
|
||||
|
||||
+21
-8
@@ -9,6 +9,7 @@
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "XmlFile.h"
|
||||
#include "GameState.h" // blame radar calculations.
|
||||
#include "Foreach.h"
|
||||
#include "RageUtil_AutoPtr.h"
|
||||
|
||||
@@ -467,7 +468,8 @@ int NoteData::GetNumTapNotes( int iStartIndex, int iEndIndex ) const
|
||||
{
|
||||
const TapNote &tn = GetTapNote(t, r);
|
||||
if( tn.type != TapNote::empty && tn.type != TapNote::mine
|
||||
&& tn.type != TapNote::lift && tn.type != TapNote::fake )
|
||||
&& tn.type != TapNote::lift && tn.type != TapNote::fake
|
||||
&& GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r) )
|
||||
iNumNotes++;
|
||||
}
|
||||
}
|
||||
@@ -485,7 +487,7 @@ int NoteData::GetNumRowsWithTap( int iStartIndex, int iEndIndex ) const
|
||||
{
|
||||
int iNumNotes = 0;
|
||||
FOREACH_NONEMPTY_ROW_ALL_TRACKS_RANGE( *this, r, iStartIndex, iEndIndex )
|
||||
if( IsThereATapAtRow(r) )
|
||||
if( IsThereATapAtRow(r) && GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r) )
|
||||
iNumNotes++;
|
||||
|
||||
return iNumNotes;
|
||||
@@ -498,7 +500,8 @@ int NoteData::GetNumMines( int iStartIndex, int iEndIndex ) const
|
||||
for( int t=0; t<GetNumTracks(); t++ )
|
||||
{
|
||||
FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( *this, t, r, iStartIndex, iEndIndex )
|
||||
if( GetTapNote(t, r).type == TapNote::mine )
|
||||
if( GetTapNote(t, r).type == TapNote::mine
|
||||
&& GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r))
|
||||
iNumMines++;
|
||||
}
|
||||
|
||||
@@ -509,7 +512,7 @@ int NoteData::GetNumRowsWithTapOrHoldHead( int iStartIndex, int iEndIndex ) cons
|
||||
{
|
||||
int iNumNotes = 0;
|
||||
FOREACH_NONEMPTY_ROW_ALL_TRACKS_RANGE( *this, r, iStartIndex, iEndIndex )
|
||||
if( IsThereATapOrHoldHeadAtRow(r) )
|
||||
if( IsThereATapOrHoldHeadAtRow(r) && GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r) )
|
||||
iNumNotes++;
|
||||
|
||||
return iNumNotes;
|
||||
@@ -560,7 +563,8 @@ int NoteData::GetNumRowsWithSimultaneousPresses( int iMinSimultaneousPresses, in
|
||||
{
|
||||
if( !RowNeedsAtLeastSimultaneousPresses(iMinSimultaneousPresses,r) )
|
||||
continue;
|
||||
|
||||
if (!GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r))
|
||||
continue;
|
||||
iNum++;
|
||||
}
|
||||
|
||||
@@ -576,7 +580,10 @@ int NoteData::GetNumRowsWithSimultaneousTaps( int iMinTaps, int iStartIndex, int
|
||||
for( int t=0; t<GetNumTracks(); t++ )
|
||||
{
|
||||
const TapNote &tn = GetTapNote(t, r);
|
||||
if( tn.type != TapNote::mine && tn.type != TapNote::empty && tn.type != TapNote::fake ) // mines don't count
|
||||
if( tn.type != TapNote::mine // mines don't count.
|
||||
&& tn.type != TapNote::empty
|
||||
&& tn.type != TapNote::fake
|
||||
&& GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r))
|
||||
iNumNotesThisIndex++;
|
||||
}
|
||||
if( iNumNotesThisIndex >= iMinTaps )
|
||||
@@ -598,6 +605,8 @@ int NoteData::GetNumHoldNotes( int iStartIndex, int iEndIndex ) const
|
||||
if( lBegin->second.type != TapNote::hold_head ||
|
||||
lBegin->second.subType != TapNote::hold_head_hold )
|
||||
continue;
|
||||
if (!GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(lBegin->first))
|
||||
continue;
|
||||
iNumHolds++;
|
||||
}
|
||||
}
|
||||
@@ -616,6 +625,8 @@ int NoteData::GetNumRolls( int iStartIndex, int iEndIndex ) const
|
||||
if( lBegin->second.type != TapNote::hold_head ||
|
||||
lBegin->second.subType != TapNote::hold_head_roll )
|
||||
continue;
|
||||
if (!GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(lBegin->first))
|
||||
continue;
|
||||
iNumRolls++;
|
||||
}
|
||||
}
|
||||
@@ -629,7 +640,8 @@ int NoteData::GetNumLifts( int iStartIndex, int iEndIndex ) const
|
||||
for( int t=0; t<GetNumTracks(); t++ )
|
||||
{
|
||||
FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( *this, t, r, iStartIndex, iEndIndex )
|
||||
if( GetTapNote(t, r).type == TapNote::lift )
|
||||
if( GetTapNote(t, r).type == TapNote::lift
|
||||
&& GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r))
|
||||
iNumLifts++;
|
||||
}
|
||||
|
||||
@@ -643,7 +655,8 @@ int NoteData::GetNumFakes( int iStartIndex, int iEndIndex ) const
|
||||
for( int t=0; t<GetNumTracks(); t++ )
|
||||
{
|
||||
FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( *this, t, r, iStartIndex, iEndIndex )
|
||||
if( GetTapNote(t, r).type == TapNote::fake )
|
||||
if( GetTapNote(t, r).type == TapNote::fake
|
||||
|| !GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r))
|
||||
iNumFakes++;
|
||||
}
|
||||
|
||||
|
||||
@@ -799,6 +799,11 @@ RadarStats CalculateRadarStatsFast( const NoteData &in, RadarStats &out )
|
||||
{
|
||||
FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( in, t, r, 0, MAX_NOTE_ROW )
|
||||
{
|
||||
/* This function deals strictly with taps, jumps, hands, and quads.
|
||||
* As such, all rows in here have to be judgable. */
|
||||
if (!GAMESTATE->GetProcessedTimingData()->IsJudgableAtRow(r))
|
||||
continue;
|
||||
|
||||
const TapNote &tn = in.GetTapNote(t, r);
|
||||
switch( tn.type )
|
||||
{
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ struct TapNote
|
||||
{
|
||||
if (type_ > TapNote::fake )
|
||||
{
|
||||
LOG->Trace(ssprintf("Invalid tap note type %d (most likely) due to random vanish issues. Assume it doesn't need judging.", type_ ) );
|
||||
LOG->Trace("Invalid tap note type %d (most likely) due to random vanish issues. Assume it doesn't need judging.", (int)type_ );
|
||||
type = TapNote::empty;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-7
@@ -32,20 +32,23 @@ bool NotesLoader::LoadFromDir( const RString &sPath, Song &out, set<RString> &Bl
|
||||
vector<RString> list;
|
||||
|
||||
BlacklistedImages.clear();
|
||||
SSCLoader::GetApplicableFiles( sPath, list );
|
||||
SSCLoader loaderSSC;
|
||||
loaderSSC.GetApplicableFiles( sPath, list );
|
||||
if( !list.empty() )
|
||||
{
|
||||
if( !SSCLoader::LoadFromDir( sPath, out ) )
|
||||
if( !loaderSSC.LoadFromDir( sPath, out ) )
|
||||
return false;
|
||||
SSCLoader::TidyUpData( out, false );
|
||||
loaderSSC.TidyUpData( out, false );
|
||||
return true;
|
||||
}
|
||||
SMALoader::GetApplicableFiles( sPath, list );
|
||||
SMALoader loaderSMA;
|
||||
loaderSMA.GetApplicableFiles( sPath, list );
|
||||
if (!list.empty() )
|
||||
return SMALoader::LoadFromDir( sPath, out );
|
||||
SMLoader::GetApplicableFiles( sPath, list );
|
||||
return loaderSMA.LoadFromDir( sPath, out );
|
||||
SMLoader loaderSM;
|
||||
loaderSM.GetApplicableFiles( sPath, list );
|
||||
if (!list.empty() )
|
||||
return SMLoader::LoadFromDir( sPath, out );
|
||||
return loaderSM.LoadFromDir( sPath, out );
|
||||
DWILoader::GetApplicableFiles( sPath, list );
|
||||
if( !list.empty() )
|
||||
return DWILoader::LoadFromDir( sPath, out, BlacklistedImages );
|
||||
|
||||
+134
-56
@@ -13,10 +13,39 @@
|
||||
#include "Attack.h"
|
||||
#include "PrefsManager.h"
|
||||
|
||||
/** @brief The maximum file size for edits. */
|
||||
const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60KB
|
||||
bool SMLoader::LoadFromDir( const RString &sPath, Song &out )
|
||||
{
|
||||
vector<RString> aFileNames;
|
||||
GetApplicableFiles( sPath, aFileNames );
|
||||
|
||||
if( aFileNames.size() > 1 )
|
||||
{
|
||||
// Need to break this up first.
|
||||
RString tmp = "Song " + sPath + " has more than one";
|
||||
LOG->UserLog(tmp, this->GetFileExtension(), "file. There can only be one!");
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT( aFileNames.size() == 1 );
|
||||
return LoadFromSimfile( sPath + aFileNames[0], out );
|
||||
}
|
||||
|
||||
void SMLoader::LoadFromSMTokens(
|
||||
float SMLoader::RowToBeat( RString line, const int rowsPerBeat )
|
||||
{
|
||||
RString backup = line;
|
||||
Trim(line, "r");
|
||||
Trim(line, "R");
|
||||
if( backup != line )
|
||||
{
|
||||
return StringToFloat( line ) / rowsPerBeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
return StringToFloat( line );
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::LoadFromTokens(
|
||||
RString sStepsType,
|
||||
RString sDescription,
|
||||
RString sDifficulty,
|
||||
@@ -34,7 +63,7 @@ void SMLoader::LoadFromSMTokens(
|
||||
Trim( sDifficulty );
|
||||
Trim( sNoteData );
|
||||
|
||||
// LOG->Trace( "Steps::LoadFromSMTokens()" );
|
||||
// LOG->Trace( "Steps::LoadFromTokens()" );
|
||||
|
||||
// insert stepstype hacks from GameManager.cpp here? -aj
|
||||
out.m_StepsType = GAMEMAN->StringToStepsType( sStepsType );
|
||||
@@ -79,11 +108,6 @@ void SMLoader::LoadFromSMTokens(
|
||||
out.TidyUpData();
|
||||
}
|
||||
|
||||
void SMLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
{
|
||||
GetDirListing( sPath + RString("*.sm"), out );
|
||||
}
|
||||
|
||||
void SMLoader::ProcessBGChanges( Song &out, const RString &sValueName, const RString &sPath, const RString &sParam )
|
||||
{
|
||||
BackgroundLayer iLayer = BACKGROUND_LAYER_1;
|
||||
@@ -171,10 +195,10 @@ void SMLoader::ProcessInstrumentTracks( Song &out, const RString &sParam )
|
||||
}
|
||||
}
|
||||
|
||||
bool SMLoader::ProcessBPMs( TimingData &out, const RString sParam )
|
||||
bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> arrayBPMChangeExpressions;
|
||||
split( sParam, ",", arrayBPMChangeExpressions );
|
||||
split( line, ",", arrayBPMChangeExpressions );
|
||||
|
||||
// prepare storage variables for negative BPMs -> Warps.
|
||||
float negBeat = -1;
|
||||
@@ -196,7 +220,7 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString sParam )
|
||||
|
||||
bNotEmpty = true;
|
||||
|
||||
const float fBeat = StringToFloat( arrayBPMChangeValues[0] );
|
||||
const float fBeat = RowToBeat( arrayBPMChangeValues[0], rowsPerBeat );
|
||||
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
|
||||
|
||||
if( fNewBPM < 0.0f )
|
||||
@@ -242,10 +266,10 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString sParam )
|
||||
return bNotEmpty;
|
||||
}
|
||||
|
||||
void SMLoader::ProcessStops( TimingData &out, const RString sParam )
|
||||
void SMLoader::ProcessStops( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> arrayFreezeExpressions;
|
||||
split( sParam, ",", arrayFreezeExpressions );
|
||||
split( line, ",", arrayFreezeExpressions );
|
||||
|
||||
// Prepare variables for negative stop conversion.
|
||||
float negBeat = -1;
|
||||
@@ -263,7 +287,7 @@ void SMLoader::ProcessStops( TimingData &out, const RString sParam )
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] );
|
||||
const float fFreezeBeat = RowToBeat( arrayFreezeValues[0], rowsPerBeat );
|
||||
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
|
||||
|
||||
// Process the prior stop.
|
||||
@@ -308,10 +332,10 @@ void SMLoader::ProcessStops( TimingData &out, const RString sParam )
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::ProcessDelays( TimingData &out, const RString sParam )
|
||||
void SMLoader::ProcessDelays( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> arrayDelayExpressions;
|
||||
split( sParam, ",", arrayDelayExpressions );
|
||||
split( line, ",", arrayDelayExpressions );
|
||||
|
||||
for( unsigned f=0; f<arrayDelayExpressions.size(); f++ )
|
||||
{
|
||||
@@ -325,7 +349,7 @@ void SMLoader::ProcessDelays( TimingData &out, const RString sParam )
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fFreezeBeat = StringToFloat( arrayDelayValues[0] );
|
||||
const float fFreezeBeat = RowToBeat( arrayDelayValues[0], rowsPerBeat );
|
||||
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
|
||||
|
||||
StopSegment new_seg( fFreezeBeat, fFreezeSeconds, true );
|
||||
@@ -342,10 +366,10 @@ void SMLoader::ProcessDelays( TimingData &out, const RString sParam )
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::ProcessTimeSignatures( TimingData &out, const RString sParam )
|
||||
void SMLoader::ProcessTimeSignatures( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> vs1;
|
||||
split( sParam, ",", vs1 );
|
||||
split( line, ",", vs1 );
|
||||
|
||||
FOREACH_CONST( RString, vs1, s1 )
|
||||
{
|
||||
@@ -358,9 +382,9 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString sParam )
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fBeat = StringToFloat( vs2[0] );
|
||||
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
|
||||
|
||||
TimeSignatureSegment seg( BeatToNoteRow( fBeat ), StringToInt( vs2[1] ), StringToInt( vs2[2] ));
|
||||
TimeSignatureSegment seg( fBeat, StringToInt( vs2[1] ), StringToInt( vs2[2] ));
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
@@ -384,10 +408,10 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString sParam )
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::ProcessTickcounts( TimingData &out, const RString sParam )
|
||||
void SMLoader::ProcessTickcounts( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> arrayTickcountExpressions;
|
||||
split( sParam, ",", arrayTickcountExpressions );
|
||||
split( line, ",", arrayTickcountExpressions );
|
||||
|
||||
for( unsigned f=0; f<arrayTickcountExpressions.size(); f++ )
|
||||
{
|
||||
@@ -401,14 +425,90 @@ void SMLoader::ProcessTickcounts( TimingData &out, const RString sParam )
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] );
|
||||
const float fTickcountBeat = RowToBeat( arrayTickcountValues[0], rowsPerBeat );
|
||||
int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT);
|
||||
|
||||
TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks );
|
||||
TickcountSegment new_seg( fTickcountBeat, iTicks );
|
||||
out.AddTickcountSegment( new_seg );
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::ProcessSpeeds( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> vs1;
|
||||
split( line, ",", vs1 );
|
||||
|
||||
FOREACH_CONST( RString, vs1, s1 )
|
||||
{
|
||||
vector<RString> vs2;
|
||||
split( *s1, "=", vs2 );
|
||||
|
||||
if( vs2[0] == 0 && vs2.size() == 2 ) // First one always seems to have 2.
|
||||
{
|
||||
vs2.push_back("0");
|
||||
}
|
||||
|
||||
if( vs2.size() == 3 ) // use beats by default.
|
||||
{
|
||||
vs2.push_back("0");
|
||||
}
|
||||
|
||||
if( vs2.size() < 4 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with %i values.", (int)vs2.size() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
|
||||
|
||||
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ));
|
||||
seg.SetUnit(StringToInt(vs2[3]));
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f.", fBeat );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( seg.GetLength() < 0 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, length %f.", fBeat, seg.GetLength() );
|
||||
continue;
|
||||
}
|
||||
|
||||
out.AddSpeedSegment( seg );
|
||||
}
|
||||
}
|
||||
|
||||
void SMLoader::ProcessFakes( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> arrayFakeExpressions;
|
||||
split( line, ",", arrayFakeExpressions );
|
||||
|
||||
for( unsigned b=0; b<arrayFakeExpressions.size(); b++ )
|
||||
{
|
||||
vector<RString> arrayFakeValues;
|
||||
split( arrayFakeExpressions[b], "=", arrayFakeValues );
|
||||
// XXX: Hard to tell which file caused this.
|
||||
if( arrayFakeValues.size() != 2 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #FAKES value \"%s\" (must have exactly one '='), ignored.",
|
||||
arrayFakeExpressions[b].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fBeat = RowToBeat( arrayFakeValues[0], rowsPerBeat );
|
||||
const float fNewBeat = StringToFloat( arrayFakeValues[1] );
|
||||
|
||||
if(fNewBeat > 0)
|
||||
out.AddFakeSegment( FakeSegment(fBeat, fNewBeat) );
|
||||
else
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Fake at beat %f, BPM %f.", fBeat, fNewBeat );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SMLoader::LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChangeExpression )
|
||||
{
|
||||
vector<RString> aBGChangeValues;
|
||||
@@ -495,7 +595,7 @@ bool SMLoader::LoadFromBGChangesString( BackgroundChange &change, const RString
|
||||
return aBGChangeValues.size() >= 2;
|
||||
}
|
||||
|
||||
bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache )
|
||||
bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache )
|
||||
{
|
||||
LOG->Trace( "Song::LoadFromSMFile(%s)", sPath.c_str() );
|
||||
|
||||
@@ -719,7 +819,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache
|
||||
}
|
||||
|
||||
Steps* pNewNotes = out.CreateSteps();
|
||||
LoadFromSMTokens(
|
||||
LoadFromTokens(
|
||||
sParams[1],
|
||||
sParams[2],
|
||||
sParams[3],
|
||||
@@ -743,33 +843,6 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SMLoader::LoadFromDir( const RString &sPath, Song &out )
|
||||
{
|
||||
vector<RString> aFileNames;
|
||||
GetApplicableFiles( sPath, aFileNames );
|
||||
|
||||
if( aFileNames.size() > 1 )
|
||||
{
|
||||
LOG->UserLog( "Song", sPath, "has more than one SM file. There can be only one (unless you are using TougaKiryuu's AnimeMix files somehow, which assume a different version of StepMania)!" );
|
||||
return false;
|
||||
/*
|
||||
for( unsigned i=0; i<aFileNames.size(); i++ )
|
||||
{
|
||||
if(!LoadFromSMFile( sPath + aFileNames[i], out ))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
ASSERT( aFileNames.size() == 1 );
|
||||
/* We should have at least one; if we had none, we shouldn't have been
|
||||
* called to begin with. */
|
||||
//ASSERT( aFileNames.size() >= 1 );
|
||||
|
||||
return LoadFromSMFile( sPath + aFileNames[0], out );
|
||||
}
|
||||
|
||||
bool SMLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong )
|
||||
{
|
||||
LOG->Trace( "SMLoader::LoadEditFromFile(%s)", sEditFilePath.c_str() );
|
||||
@@ -853,7 +926,7 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath
|
||||
return true;
|
||||
|
||||
Steps* pNewNotes = pSong->CreateSteps();
|
||||
LoadFromSMTokens(
|
||||
LoadFromTokens(
|
||||
sParams[1], sParams[2], sParams[3], sParams[4], sParams[5], sParams[6],
|
||||
*pNewNotes);
|
||||
|
||||
@@ -881,6 +954,11 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath
|
||||
|
||||
}
|
||||
|
||||
void SMLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
{
|
||||
GetDirListing( sPath + RString("*" + this->GetFileExtension() ), out );
|
||||
}
|
||||
|
||||
void SMLoader::TidyUpData( Song &song, bool bFromCache )
|
||||
{
|
||||
/*
|
||||
|
||||
+145
-21
@@ -15,33 +15,157 @@ class TimingData;
|
||||
* This was brought in from StepMania 4's recent betas. */
|
||||
const float FAST_BPM_WARP = 9999999.f;
|
||||
|
||||
/** @brief Reads a Song from an .SM file. */
|
||||
namespace SMLoader
|
||||
{
|
||||
void LoadFromSMTokens( 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 );
|
||||
/** @brief The maximum file size for edits. */
|
||||
const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60KB
|
||||
|
||||
bool LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache = false );
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &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 );
|
||||
/** @brief Reads a Song from an .SM file. */
|
||||
struct SMLoader
|
||||
{
|
||||
SMLoader() : fileExt(".sm") {}
|
||||
|
||||
SMLoader(RString ext) : fileExt(ext) {}
|
||||
|
||||
bool ProcessBPMs( TimingData &, const RString );
|
||||
void ProcessStops( TimingData &, const RString );
|
||||
void ProcessDelays( TimingData &, const RString );
|
||||
void ProcessTimeSignatures( TimingData &, const RString );
|
||||
void ProcessTickcounts( TimingData &, const RString );
|
||||
void ProcessBGChanges( Song &out, const RString &sValueName,
|
||||
virtual ~SMLoader() {}
|
||||
|
||||
/**
|
||||
* @brief Attempt to load a song from a specified path.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a reference to the Song that will retrieve the song information.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
virtual bool LoadFromDir( const RString &sPath, Song &out );
|
||||
/**
|
||||
* @brief Perform some cleanup on the loaded song.
|
||||
* @param song a reference to the song that may need cleaning up.
|
||||
* @param bFromCache a flag to determine if this song is loaded from a cache file.
|
||||
*/
|
||||
virtual void TidyUpData( Song &song, bool bFromCache );
|
||||
|
||||
/**
|
||||
* @brief Attempt to load the specified sm file.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a reference to the Song that will retrieve the song information.
|
||||
* @param bFromCache a check to see if we are getting certain information from the cache file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
virtual bool LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache = false );
|
||||
/**
|
||||
* @brief Retrieve the list of .sm files.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a vector of files found in the path.
|
||||
*/
|
||||
virtual void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
virtual bool LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
virtual bool LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot );
|
||||
virtual bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
virtual bool LoadFromBGChangesString(BackgroundChange &change,
|
||||
const RString &sBGChangeExpression );
|
||||
|
||||
/**
|
||||
* @brief Process the BPM Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose.
|
||||
* @return true if there was at least one segment found, false otherwise. */
|
||||
bool ProcessBPMs(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1);
|
||||
/**
|
||||
* @brief Process the Stop Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose. */
|
||||
void ProcessStops(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1);
|
||||
/**
|
||||
* @brief Process the Delay Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose. */
|
||||
void ProcessDelays(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1);
|
||||
/**
|
||||
* @brief Process the Time Signature Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose. */
|
||||
void ProcessTimeSignatures(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1);
|
||||
/**
|
||||
* @brief Process the Tickcount Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose. */
|
||||
void ProcessTickcounts(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1);
|
||||
|
||||
/**
|
||||
* @brief Process the Speed Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose. */
|
||||
virtual void ProcessSpeeds(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1);
|
||||
|
||||
virtual void ProcessCombos(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1) {}
|
||||
|
||||
/**
|
||||
* @brief Process the Fake Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose. */
|
||||
virtual void ProcessFakes(TimingData & out,
|
||||
const RString line,
|
||||
const int rowsPerBeat = -1);
|
||||
|
||||
virtual void ProcessBGChanges( Song &out, const RString &sValueName,
|
||||
const RString &sPath, const RString &sParam );
|
||||
void ProcessAttacks( Song &out, MsdFile::value_t sParams );
|
||||
void ProcessInstrumentTracks( Song &out, const RString &sParam );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a row value to the proper beat value.
|
||||
*
|
||||
* This is primarily used for assistance with converting SMA files.
|
||||
* @param line The line that contains the value.
|
||||
* @param rowsPerBeat the number of rows per beat according to the original file.
|
||||
* @return the converted beat value. */
|
||||
float RowToBeat(RString line, const int rowsPerBeat);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Process the different tokens we have available to get NoteData.
|
||||
* @param stepsType The current StepsType.
|
||||
* @param description The description of the chart.
|
||||
* @param difficulty The difficulty (in words) of the chart.
|
||||
* @param meter the difficulty (in numbers) of the chart.
|
||||
* @param radarValues the calculated radar values.
|
||||
* @param noteData the note data itself.
|
||||
* @param out the Steps getting the data. */
|
||||
virtual void LoadFromTokens(RString sStepsType,
|
||||
RString sDescription,
|
||||
RString sDifficulty,
|
||||
RString sMeter,
|
||||
RString sRadarValues,
|
||||
RString sNoteData,
|
||||
Steps &out);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the file extension associated with this loader.
|
||||
* @return the file extension. */
|
||||
RString GetFileExtension() const { return fileExt; }
|
||||
|
||||
private:
|
||||
/** @brief The file extension in use. */
|
||||
const RString fileExt;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+11
-415
@@ -14,240 +14,6 @@
|
||||
#include "Steps.h"
|
||||
#include "Attack.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
|
||||
|
||||
bool SMALoader::LoadFromBGChangesString( BackgroundChange &change,
|
||||
const RString &sBGChangeExpression )
|
||||
{
|
||||
return SMLoader::LoadFromBGChangesString(change, sBGChangeExpression);
|
||||
}
|
||||
|
||||
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. Only one SMA file is allowed per song." );
|
||||
return false;
|
||||
}
|
||||
ASSERT( aFileNames.size() == 1 );
|
||||
return LoadFromSMAFile( sPath + aFileNames[0], out );
|
||||
}
|
||||
|
||||
float SMALoader::RowToBeat( RString sLine, const int iRowsPerBeat )
|
||||
{
|
||||
if( sLine.find("R") || sLine.find("r") )
|
||||
{
|
||||
sLine = sLine.Left(sLine.size()-1);
|
||||
return StringToFloat( sLine ) / iRowsPerBeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
return StringToFloat( sLine );
|
||||
}
|
||||
}
|
||||
|
||||
bool SMALoader::ProcessBPMs( TimingData &out, const int iRowsPerBeat, const RString sParam )
|
||||
{
|
||||
vector<RString> arrayBPMChangeExpressions;
|
||||
split( sParam, ",", arrayBPMChangeExpressions );
|
||||
|
||||
// prepare storage variables for negative BPMs -> Warps.
|
||||
float negBeat = -1;
|
||||
float negBPM = 1;
|
||||
float highspeedBeat = -1;
|
||||
bool bNotEmpty = false;
|
||||
|
||||
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 #BPMs value \"%s\" (must have exactly one '='), ignored.",
|
||||
arrayBPMChangeExpressions[b].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
bNotEmpty = true;
|
||||
|
||||
const float fBeat = RowToBeat( arrayBPMChangeValues[0], iRowsPerBeat );
|
||||
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
|
||||
|
||||
if( fNewBPM < 0.0f )
|
||||
{
|
||||
out.m_bHasNegativeBpms = true;
|
||||
negBeat = fBeat;
|
||||
negBPM = fNewBPM;
|
||||
}
|
||||
else if( fNewBPM > 0.0f )
|
||||
{
|
||||
// add in a warp.
|
||||
if( negBPM < 0 )
|
||||
{
|
||||
float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat);
|
||||
WarpSegment new_seg(negBeat, endBeat - negBeat);
|
||||
out.AddWarpSegment( new_seg );
|
||||
|
||||
negBeat = -1;
|
||||
negBPM = 1;
|
||||
}
|
||||
// too fast. make it a warp.
|
||||
if( fNewBPM > FAST_BPM_WARP )
|
||||
{
|
||||
highspeedBeat = fBeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// add in a warp.
|
||||
if( highspeedBeat > 0 )
|
||||
{
|
||||
WarpSegment new_seg(highspeedBeat, fBeat - highspeedBeat);
|
||||
out.AddWarpSegment( new_seg );
|
||||
highspeedBeat = -1;
|
||||
}
|
||||
{
|
||||
BPMSegment new_seg( BeatToNoteRow( fBeat ), fNewBPM );
|
||||
out.AddBPMSegment( new_seg );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bNotEmpty;
|
||||
}
|
||||
|
||||
void SMALoader::ProcessStops( TimingData &out, const int iRowsPerBeat, const RString sParam )
|
||||
{
|
||||
vector<RString> arrayFreezeExpressions;
|
||||
split( sParam, ",", arrayFreezeExpressions );
|
||||
|
||||
// Prepare variables for negative stop conversion.
|
||||
float negBeat = -1;
|
||||
float negPause = 0;
|
||||
|
||||
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 #STOPS value \"%s\" (must have exactly one '='), ignored.",
|
||||
arrayFreezeExpressions[f].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fFreezeBeat = RowToBeat( arrayFreezeValues[0], iRowsPerBeat );
|
||||
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
|
||||
|
||||
// Process the prior stop.
|
||||
if( negPause > 0 )
|
||||
{
|
||||
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
|
||||
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
|
||||
float fSkipBeats = negPause / fSecondsPerBeat;
|
||||
|
||||
if( negBeat + fSkipBeats > fFreezeBeat )
|
||||
fSkipBeats = fFreezeBeat - negBeat;
|
||||
|
||||
WarpSegment ws( negBeat, fSkipBeats);
|
||||
out.AddWarpSegment( ws );
|
||||
|
||||
negBeat = -1;
|
||||
negPause = 0;
|
||||
}
|
||||
|
||||
if( fFreezeSeconds < 0.0f )
|
||||
{
|
||||
negBeat = fFreezeBeat;
|
||||
negPause = -fFreezeSeconds;
|
||||
}
|
||||
else if( fFreezeSeconds > 0.0f )
|
||||
{
|
||||
StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds );
|
||||
out.AddStopSegment( ss );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Process the prior stop if there was one.
|
||||
if( negPause > 0 )
|
||||
{
|
||||
BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
|
||||
float fSecondsPerBeat = 60 / oldBPM.GetBPM();
|
||||
float fSkipBeats = negPause / fSecondsPerBeat;
|
||||
|
||||
WarpSegment ws( negBeat, fSkipBeats);
|
||||
out.AddWarpSegment( ws );
|
||||
}
|
||||
}
|
||||
|
||||
void SMALoader::ProcessDelays( TimingData &out, const int iRowsPerBeat, const RString sParam )
|
||||
{
|
||||
vector<RString> arrayDelayExpressions;
|
||||
split( sParam, ",", arrayDelayExpressions );
|
||||
|
||||
for( unsigned f=0; f<arrayDelayExpressions.size(); f++ )
|
||||
{
|
||||
vector<RString> arrayDelayValues;
|
||||
split( arrayDelayExpressions[f], "=", arrayDelayValues );
|
||||
if( arrayDelayValues.size() != 2 )
|
||||
{
|
||||
// XXX: Hard to tell which file caused this.
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #DELAYS value \"%s\" (must have exactly one '='), ignored.",
|
||||
arrayDelayExpressions[f].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fFreezeBeat = RowToBeat( arrayDelayValues[0], iRowsPerBeat );
|
||||
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
|
||||
|
||||
StopSegment new_seg( fFreezeBeat, fFreezeSeconds, true );
|
||||
// XXX: Remove Negatives Bug?
|
||||
new_seg.SetBeat(fFreezeBeat);
|
||||
new_seg.SetPause(fFreezeSeconds);
|
||||
|
||||
// LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
|
||||
|
||||
if(fFreezeSeconds > 0.0f)
|
||||
out.AddStopSegment( new_seg );
|
||||
else
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
|
||||
}
|
||||
}
|
||||
|
||||
void SMALoader::ProcessTickcounts( TimingData &out, const int iRowsPerBeat, const RString sParam )
|
||||
{
|
||||
vector<RString> arrayTickcountExpressions;
|
||||
split( sParam, ",", arrayTickcountExpressions );
|
||||
|
||||
for( unsigned f=0; f<arrayTickcountExpressions.size(); f++ )
|
||||
{
|
||||
vector<RString> arrayTickcountValues;
|
||||
split( arrayTickcountExpressions[f], "=", arrayTickcountValues );
|
||||
if( arrayTickcountValues.size() != 2 )
|
||||
{
|
||||
// XXX: Hard to tell which file caused this.
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #TICKCOUNTS value \"%s\" (must have exactly one '='), ignored.",
|
||||
arrayTickcountExpressions[f].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fTickcountBeat = RowToBeat( arrayTickcountValues[0], iRowsPerBeat );
|
||||
int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT);
|
||||
|
||||
TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks );
|
||||
out.AddTickcountSegment( new_seg );
|
||||
}
|
||||
}
|
||||
|
||||
void SMALoader::ProcessMultipliers( TimingData &out, const int iRowsPerBeat, const RString sParam )
|
||||
{
|
||||
vector<RString> arrayMultiplierExpressions;
|
||||
@@ -306,15 +72,10 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam )
|
||||
}
|
||||
}
|
||||
|
||||
float BeatToSeconds(float fromBeat, RString toSomething)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RString sParam )
|
||||
void SMALoader::ProcessSpeeds( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> vs1;
|
||||
split( sParam, ",", vs1 );
|
||||
split( line, ",", vs1 );
|
||||
|
||||
FOREACH_CONST( RString, vs1, s1 )
|
||||
{
|
||||
@@ -335,7 +96,7 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fBeat = RowToBeat( vs2[0], iRowsPerBeat );
|
||||
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
|
||||
|
||||
RString backup = vs2[2];
|
||||
Trim(vs2[2], "s");
|
||||
@@ -362,57 +123,7 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS
|
||||
}
|
||||
}
|
||||
|
||||
void SMALoader::ProcessFakes( TimingData &out, const int iRowsPerBeat, const RString sParam )
|
||||
{
|
||||
vector<RString> arrayFakeExpressions;
|
||||
split( sParam, ",", arrayFakeExpressions );
|
||||
|
||||
for( unsigned b=0; b<arrayFakeExpressions.size(); b++ )
|
||||
{
|
||||
vector<RString> arrayFakeValues;
|
||||
split( arrayFakeExpressions[b], "=", arrayFakeValues );
|
||||
// XXX: Hard to tell which file caused this.
|
||||
if( arrayFakeValues.size() != 2 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #FAKES value \"%s\" (must have exactly one '='), ignored.",
|
||||
arrayFakeExpressions[b].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fBeat = RowToBeat( arrayFakeValues[0], iRowsPerBeat );
|
||||
const float fNewBeat = StringToFloat( arrayFakeValues[1] );
|
||||
|
||||
if(fNewBeat > 0)
|
||||
out.AddFakeSegment( FakeSegment(fBeat, fNewBeat) );
|
||||
else
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Fake at beat %f, BPM %f.", fBeat, fNewBeat );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SMALoader::LoadFromSMATokens(
|
||||
RString sStepsType,
|
||||
RString sDescription,
|
||||
RString sDifficulty,
|
||||
RString sMeter,
|
||||
RString sRadarValues,
|
||||
RString sNoteData,
|
||||
Steps &out
|
||||
)
|
||||
{
|
||||
SMLoader::LoadFromSMTokens( sStepsType, sDescription,
|
||||
sDifficulty, sMeter, sRadarValues,
|
||||
sNoteData, out );
|
||||
}
|
||||
|
||||
void SMALoader::TidyUpData( Song &song, bool bFromCache )
|
||||
{
|
||||
SMLoader::TidyUpData( song, bFromCache );
|
||||
}
|
||||
|
||||
bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
|
||||
bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache )
|
||||
{
|
||||
LOG->Trace( "Song::LoadFromSMAFile(%s)", sPath.c_str() );
|
||||
|
||||
@@ -635,28 +346,28 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
|
||||
{
|
||||
TimingData &timing = (state == SMA_GETTING_STEP_INFO
|
||||
? pNewNotes->m_Timing : out.m_SongTiming);
|
||||
ProcessBPMs( timing, iRowsPerBeat, sParams[1] );
|
||||
ProcessBPMs( timing, sParams[1], iRowsPerBeat );
|
||||
}
|
||||
|
||||
else if( sValueName=="STOPS" || sValueName=="FREEZES" )
|
||||
{
|
||||
TimingData &timing = (state == SMA_GETTING_STEP_INFO
|
||||
? pNewNotes->m_Timing : out.m_SongTiming);
|
||||
ProcessStops( timing, iRowsPerBeat, sParams[1] );
|
||||
ProcessStops( timing, sParams[1], iRowsPerBeat );
|
||||
}
|
||||
|
||||
else if( sValueName=="DELAYS" )
|
||||
{
|
||||
TimingData &timing = (state == SMA_GETTING_STEP_INFO
|
||||
? pNewNotes->m_Timing : out.m_SongTiming);
|
||||
ProcessDelays( timing, iRowsPerBeat, sParams[1] );
|
||||
ProcessDelays( timing, sParams[1], iRowsPerBeat );
|
||||
}
|
||||
|
||||
else if( sValueName=="TICKCOUNT" )
|
||||
{
|
||||
TimingData &timing = (state == SMA_GETTING_STEP_INFO
|
||||
? pNewNotes->m_Timing : out.m_SongTiming);
|
||||
ProcessTickcounts( timing, iRowsPerBeat, sParams[1] );
|
||||
ProcessTickcounts( timing, sParams[1], iRowsPerBeat );
|
||||
}
|
||||
|
||||
else if( sValueName=="SPEED" )
|
||||
@@ -665,7 +376,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
|
||||
? pNewNotes->m_Timing : out.m_SongTiming);
|
||||
RString tmp = sParams[1];
|
||||
Trim( tmp );
|
||||
ProcessSpeeds( timing, iRowsPerBeat, tmp );
|
||||
ProcessSpeeds( timing, tmp, iRowsPerBeat );
|
||||
}
|
||||
|
||||
else if( sValueName=="MULTIPLIER" )
|
||||
@@ -679,7 +390,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
|
||||
{
|
||||
TimingData &timing = (state == SMA_GETTING_STEP_INFO
|
||||
? pNewNotes->m_Timing : out.m_SongTiming);
|
||||
ProcessFakes( timing, iRowsPerBeat, sParams[1] );
|
||||
ProcessFakes( timing, sParams[1], iRowsPerBeat );
|
||||
}
|
||||
|
||||
else if( sValueName=="METERTYPE" )
|
||||
@@ -706,7 +417,7 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
|
||||
continue;
|
||||
}
|
||||
|
||||
LoadFromSMATokens(
|
||||
LoadFromTokens(
|
||||
sParams[1],
|
||||
sParams[2],
|
||||
sParams[3],
|
||||
@@ -727,121 +438,6 @@ bool SMALoader::LoadFromSMAFile( const RString &sPath, Song &out )
|
||||
return true;
|
||||
}
|
||||
|
||||
void SMALoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
{
|
||||
GetDirListing( sPath + RString("*.sma"), out );
|
||||
}
|
||||
|
||||
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 = pSong->CreateSteps();
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Aldo Fregoso, Jason Felds (c) 2009-2011
|
||||
|
||||
+12
-27
@@ -2,6 +2,7 @@
|
||||
#define NOTES_LOADER_SMA_H
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "NotesLoaderSM.h"
|
||||
#include "BackgroundUtil.h"
|
||||
|
||||
class MsdFile;
|
||||
@@ -20,37 +21,21 @@ enum SMALoadingStates
|
||||
};
|
||||
|
||||
/** @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 );
|
||||
struct SMALoader : public SMLoader
|
||||
{
|
||||
SMALoader() : SMLoader(".sma") {}
|
||||
|
||||
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 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 );
|
||||
virtual bool LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache = false );
|
||||
|
||||
|
||||
void ProcessBeatsPerMeasure( TimingData &out, const RString sParam );
|
||||
bool ProcessBPMs( TimingData &out, const int iRowsPerBeat, const RString sParam );
|
||||
void ProcessStops( TimingData &out, const int iRowsPerBeat, const RString sParam );
|
||||
void ProcessDelays( TimingData &out, const int iRowsPerBeat, const RString sParam );
|
||||
void ProcessTickcounts( TimingData &out, const int iRowsPerBeat, const RString sParam );
|
||||
void ProcessMultipliers( TimingData &out, const int iRowsPerBeat, const RString sParam );
|
||||
void ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RString sParam );
|
||||
void ProcessFakes( TimingData &out, const int iRowsPerBeat, const RString sParam );
|
||||
|
||||
float RowToBeat( RString sLine, const int iRowsPerBeat );
|
||||
/**
|
||||
* @brief Process the Speed Segments from the string.
|
||||
* @param out the TimingData being modified.
|
||||
* @param line the string in question.
|
||||
* @param rowsPerBeat the number of rows per beat for this purpose. */
|
||||
virtual void ProcessSpeeds( TimingData &out, const RString line, const int rowsPerBeat );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+11
-125
@@ -14,38 +14,6 @@
|
||||
#include "Attack.h"
|
||||
#include "PrefsManager.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
|
||||
|
||||
/**
|
||||
* @brief Attempt to load any background changes in use by this song.
|
||||
* @param change a reference to the background change.
|
||||
* @param sBGChangeExpression a reference to the list of changes to be made.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromBGSSCChangesString( BackgroundChange &change, const RString &sBGChangeExpression )
|
||||
{
|
||||
return SMLoader::LoadFromBGChangesString( change, sBGChangeExpression );
|
||||
}
|
||||
|
||||
bool SSCLoader::LoadFromDir( const RString &sPath, Song &out )
|
||||
{
|
||||
vector<RString> aFileNames;
|
||||
GetApplicableFiles( sPath, aFileNames );
|
||||
|
||||
if( aFileNames.size() > 1 )
|
||||
{
|
||||
LOG->UserLog( "Song", sPath, "has more than one SSC file. Only one SSC file is allowed per song." );
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT( aFileNames.size() == 1 ); // Ensure one was found entirely.
|
||||
|
||||
return LoadFromSSCFile( sPath + aFileNames[0], out );
|
||||
}
|
||||
|
||||
void SSCLoader::ProcessWarps( TimingData &out, const RString sParam, const float fVersion )
|
||||
{
|
||||
vector<RString> arrayWarpExpressions;
|
||||
@@ -108,10 +76,10 @@ void SSCLoader::ProcessLabels( TimingData &out, const RString sParam )
|
||||
}
|
||||
}
|
||||
|
||||
void SSCLoader::ProcessCombos( TimingData &out, const RString sParam )
|
||||
void SSCLoader::ProcessCombos( TimingData &out, const RString line, const int rowsPerBeat )
|
||||
{
|
||||
vector<RString> arrayComboExpressions;
|
||||
split( sParam, ",", arrayComboExpressions );
|
||||
split( line, ",", arrayComboExpressions );
|
||||
|
||||
for( unsigned f=0; f<arrayComboExpressions.size(); f++ )
|
||||
{
|
||||
@@ -130,53 +98,6 @@ void SSCLoader::ProcessCombos( TimingData &out, const RString sParam )
|
||||
}
|
||||
}
|
||||
|
||||
void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam )
|
||||
{
|
||||
vector<RString> vs1;
|
||||
split( sParam, ",", vs1 );
|
||||
|
||||
FOREACH_CONST( RString, vs1, s1 )
|
||||
{
|
||||
vector<RString> vs2;
|
||||
split( *s1, "=", vs2 );
|
||||
|
||||
if( vs2[0] == 0 && vs2.size() == 2 ) // First one always seems to have 2.
|
||||
{
|
||||
vs2.push_back("0");
|
||||
}
|
||||
|
||||
if( vs2.size() == 3 ) // use beats by default.
|
||||
{
|
||||
vs2.push_back("0");
|
||||
}
|
||||
|
||||
if( vs2.size() < 4 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with %i values.", (int)vs2.size() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fBeat = StringToFloat( vs2[0] );
|
||||
|
||||
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ));
|
||||
seg.SetUnit(StringToInt(vs2[3]));
|
||||
|
||||
if( fBeat < 0 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f.", fBeat );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( seg.GetLength() < 0 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, length %f.", fBeat, seg.GetLength() );
|
||||
continue;
|
||||
}
|
||||
|
||||
out.AddSpeedSegment( seg );
|
||||
}
|
||||
}
|
||||
|
||||
void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
|
||||
{
|
||||
vector<RString> vs1;
|
||||
@@ -207,37 +128,8 @@ void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
|
||||
}
|
||||
}
|
||||
|
||||
void SSCLoader::ProcessFakes( TimingData &out, const RString sParam )
|
||||
{
|
||||
vector<RString> arrayFakeExpressions;
|
||||
split( sParam, ",", arrayFakeExpressions );
|
||||
|
||||
for( unsigned b=0; b<arrayFakeExpressions.size(); b++ )
|
||||
{
|
||||
vector<RString> arrayFakeValues;
|
||||
split( arrayFakeExpressions[b], "=", arrayFakeValues );
|
||||
// XXX: Hard to tell which file caused this.
|
||||
if( arrayFakeValues.size() != 2 )
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #FAKES value \"%s\" (must have exactly one '='), ignored.",
|
||||
arrayFakeExpressions[b].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
const float fBeat = StringToFloat( arrayFakeValues[0] );
|
||||
const float fNewBeat = StringToFloat( arrayFakeValues[1] );
|
||||
|
||||
if(fNewBeat > 0)
|
||||
out.AddFakeSegment( FakeSegment(fBeat, fNewBeat) );
|
||||
else
|
||||
{
|
||||
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Fake at beat %f, BPM %f.", fBeat, fNewBeat );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache )
|
||||
bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache )
|
||||
{
|
||||
LOG->Trace( "Song::LoadFromSSCFile(%s)", sPath.c_str() );
|
||||
|
||||
@@ -421,7 +313,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
|
||||
for( unsigned b=0; b<aFGChangeExpressions.size(); b++ )
|
||||
{
|
||||
BackgroundChange change;
|
||||
if( LoadFromBGSSCChangesString( change, aFGChangeExpressions[b] ) )
|
||||
if( LoadFromBGChangesString( change, aFGChangeExpressions[b] ) )
|
||||
out.AddForegroundChange( change );
|
||||
}
|
||||
}
|
||||
@@ -665,11 +557,6 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
|
||||
return true;
|
||||
}
|
||||
|
||||
void SSCLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
{
|
||||
GetDirListing( sPath + RString("*.ssc"), out );
|
||||
}
|
||||
|
||||
bool SSCLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool bAddStepsToSong )
|
||||
{
|
||||
LOG->Trace( "SSCLoader::LoadEditFromFile(%s)", sEditFilePath.c_str() );
|
||||
@@ -883,9 +770,13 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat
|
||||
else
|
||||
{
|
||||
pNewNotes = pSong->CreateSteps();
|
||||
SMLoader::LoadFromSMTokens(
|
||||
sParams[1], sParams[2], sParams[3], sParams[4], sParams[5], sParams[6],
|
||||
*pNewNotes);
|
||||
LoadFromTokens(sParams[1],
|
||||
sParams[2],
|
||||
sParams[3],
|
||||
sParams[4],
|
||||
sParams[5],
|
||||
sParams[6],
|
||||
*pNewNotes);
|
||||
}
|
||||
|
||||
pNewNotes->SetLoadedFromProfile( slot );
|
||||
@@ -913,11 +804,6 @@ bool SSCLoader::LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePat
|
||||
return bSSCFormat;
|
||||
}
|
||||
|
||||
void SSCLoader::TidyUpData( Song &song, bool bFromCache )
|
||||
{
|
||||
SMLoader::TidyUpData(song, bFromCache);
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2011 Jason Felds
|
||||
* All rights reserved.
|
||||
|
||||
+9
-25
@@ -3,6 +3,7 @@
|
||||
#define NotesLoaderSSC_H
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "NotesLoaderSM.h"
|
||||
|
||||
class MsdFile;
|
||||
class Song;
|
||||
@@ -29,15 +30,10 @@ const float VERSION_SPLIT_TIMING = 0.7f;
|
||||
/**
|
||||
* @brief The SSCLoader handles all of the parsing needed for .ssc files.
|
||||
*/
|
||||
namespace SSCLoader
|
||||
struct SSCLoader : public SMLoader
|
||||
{
|
||||
/**
|
||||
* @brief Attempt to load a song from a specified path.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a reference to the Song that will retrieve the song information.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromDir( const RString &sPath, Song &out );
|
||||
SSCLoader() : SMLoader(".ssc") {}
|
||||
|
||||
/**
|
||||
* @brief Attempt to load the specified ssc file.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
@@ -45,13 +41,8 @@ namespace SSCLoader
|
||||
* @param bFromCache a check to see if we are getting certain information from the cache file.
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCache = false );
|
||||
/**
|
||||
* @brief Retrieve the list of .ssc files.
|
||||
* @param sPath a const reference to the path on the hard drive to check.
|
||||
* @param out a vector of files found in the path.
|
||||
*/
|
||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||
virtual bool LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache = false );
|
||||
|
||||
/**
|
||||
* @brief Attempt to load an edit from the hard drive.
|
||||
* @param sEditFilePath a path on the hard drive to check.
|
||||
@@ -69,21 +60,14 @@ namespace SSCLoader
|
||||
* @return its success or failure.
|
||||
*/
|
||||
bool LoadEditFromMsd( const MsdFile &msd, const RString &sEditFilePath, ProfileSlot slot, bool bAddStepsToSong );
|
||||
/**
|
||||
* @brief Perform some cleanup on the loaded song.
|
||||
* @param song a reference to the song that may need cleaning up.
|
||||
* @param bFromCache a flag to determine if this song is loaded from a cache file.
|
||||
*/
|
||||
void TidyUpData( Song &song, bool bFromCache );
|
||||
|
||||
|
||||
void ProcessWarps( TimingData &, const RString, const float );
|
||||
void ProcessLabels( TimingData &, const RString );
|
||||
void ProcessCombos( TimingData &, const RString );
|
||||
void ProcessSpeeds( TimingData &, const RString );
|
||||
virtual void ProcessCombos( TimingData &, const RString, const int = -1 );
|
||||
void ProcessScrolls( TimingData &, const RString );
|
||||
void ProcessFakes( TimingData &, const RString );
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
|
||||
+14
-9
@@ -1538,7 +1538,7 @@ int Player::GetClosestNoteDirectional( int col, int iStartRow, int iEndRow, bool
|
||||
// Is this the row we want?
|
||||
do {
|
||||
const TapNote &tn = begin->second;
|
||||
if( m_Timing->IsWarpAtRow( begin->first ) || m_Timing->IsFakeAtRow( begin->first ) )
|
||||
if (!m_Timing->IsJudgableAtRow( begin->first ))
|
||||
break;
|
||||
if( tn.type == TapNote::empty )
|
||||
break;
|
||||
@@ -1594,7 +1594,7 @@ int Player::GetClosestNonEmptyRowDirectional( int iStartRow, int iEndRow, bool b
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
if( m_Timing->IsWarpAtRow( iter.Row() ) || m_Timing->IsFakeAtRow( iter.Row() ) )
|
||||
if (!m_Timing->IsJudgableAtRow(iter.Row()))
|
||||
{
|
||||
++iter;
|
||||
continue;
|
||||
@@ -2118,7 +2118,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
|
||||
// Stepped too close to mine?
|
||||
if( !bRelease && ( REQUIRE_STEP_ON_MINES == !bHeld ) &&
|
||||
fSecondsFromExact <= GetWindowSeconds(TW_Mine) &&
|
||||
!m_Timing->IsWarpAtRow(iSongRow) && !m_Timing->IsFakeAtRow(iSongRow))
|
||||
m_Timing->IsJudgableAtRow(iSongRow))
|
||||
score = TNS_HitMine;
|
||||
break;
|
||||
|
||||
@@ -2616,7 +2616,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds )
|
||||
continue;
|
||||
|
||||
// Ignore all notes in WarpSegments or FakeSegments.
|
||||
if( m_Timing->IsWarpAtRow( iter.Row() ) || m_Timing->IsFakeAtRow( iter.Row() ) )
|
||||
if (!m_Timing->IsJudgableAtRow(iter.Row()))
|
||||
continue;
|
||||
|
||||
if( tn.type == TapNote::mine )
|
||||
@@ -2651,7 +2651,7 @@ void Player::UpdateJudgedRows()
|
||||
int iRow = iter.Row();
|
||||
|
||||
// Do not judge arrows in WarpSegments or FakeSegments
|
||||
if( m_Timing->IsWarpAtRow(iRow) || m_Timing->IsFakeAtRow(iRow) )
|
||||
if (!m_Timing->IsJudgableAtRow(iRow))
|
||||
continue;
|
||||
|
||||
if( iLastSeenRow != iRow )
|
||||
@@ -2852,7 +2852,8 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
||||
// check to see if there's a note at the crossed row
|
||||
if( m_pPlayerState->m_PlayerController != PC_HUMAN )
|
||||
{
|
||||
if( tn.type != TapNote::empty && tn.type != TapNote::fake && tn.result.tns == TNS_None )
|
||||
if(tn.type != TapNote::empty && tn.type != TapNote::fake && tn.result.tns == TNS_None
|
||||
&& this->m_Timing->IsJudgableAtRow(iRow) )
|
||||
{
|
||||
Step( iTrack, iRow, now, false, false );
|
||||
if( m_pPlayerState->m_PlayerController == PC_AUTOPLAY )
|
||||
@@ -2878,7 +2879,7 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
||||
}
|
||||
else if( CHECKPOINTS_USE_TIME_SIGNATURES )
|
||||
{
|
||||
TimeSignatureSegment tSignature = m_Timing->GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) );
|
||||
TimeSignatureSegment & tSignature = m_Timing->GetTimeSignatureSegmentAtRow( iLastRowCrossed );
|
||||
|
||||
// Most songs are in 4/4 time. The frequency for checking tick counts should reflect that.
|
||||
iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature.GetDen() / (tSignature.GetNum() * 4);
|
||||
@@ -2921,8 +2922,11 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
||||
bool bHoldOverlapsRow = iFirstCheckpointOfHold <= r && r <= iLastCheckpointOfHold;
|
||||
if( !bHoldOverlapsRow )
|
||||
continue;
|
||||
|
||||
|
||||
|
||||
viColsWithHold.push_back( iTrack );
|
||||
|
||||
if( tn.HoldResult.fLife > 0 )
|
||||
{
|
||||
++iNumHoldsHeldThisRow;
|
||||
@@ -2934,6 +2938,7 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
||||
++tn.HoldResult.iCheckpointsMissed;
|
||||
}
|
||||
}
|
||||
GAMESTATE->SetProcessedTimingData(this->m_Timing);
|
||||
|
||||
// TODO: Find a better way of handling hold checkpoints with other taps.
|
||||
if( !viColsWithHold.empty() && ( CHECKPOINTS_TAPS_SEPARATE_JUDGMENT || m_NoteData.GetNumTapNotesInRow( iLastRowCrossed ) == 0 ) )
|
||||
@@ -2990,7 +2995,7 @@ void Player::HandleTapRowScore( unsigned row )
|
||||
#endif
|
||||
|
||||
// Do not score rows in WarpSegments or FakeSegments
|
||||
if( m_Timing->IsWarpAtRow( row ) || m_Timing->IsFakeAtRow( row ) )
|
||||
if (!m_Timing->IsJudgableAtRow(row))
|
||||
return;
|
||||
|
||||
if( GAMESTATE->m_bDemonstrationOrJukebox )
|
||||
@@ -3094,7 +3099,7 @@ void Player::HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumH
|
||||
#endif
|
||||
|
||||
// WarpSegments and FakeSegments aren't judged in any way.
|
||||
if( m_Timing->IsWarpAtRow( iRow ) || m_Timing->IsFakeAtRow( iRow ) )
|
||||
if (!m_Timing->IsJudgableAtRow(iRow))
|
||||
return;
|
||||
|
||||
// don't accumulate combo if AutoPlay is on.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
RageSoundReader_Extend::RageSoundReader_Extend( RageSoundReader *pSource ):
|
||||
RageSoundReader_Filter( pSource )
|
||||
{
|
||||
ASSERT_M(pSource, "The music file was not found! Was it deleted or moved while the game was on?");
|
||||
m_iPositionFrames = pSource->GetNextSourceFrame();
|
||||
|
||||
m_StopMode = M_STOP;
|
||||
|
||||
@@ -120,6 +120,7 @@ void ScoreKeeperNormal::Load(
|
||||
* forced and not chosen by the user. */
|
||||
NoteDataUtil::TransformNoteData( nd, aa, pSteps->m_StepsType, pSong );
|
||||
RadarValues rvPre;
|
||||
GAMESTATE->SetProcessedTimingData(&pSteps->m_Timing);
|
||||
NoteDataUtil::CalculateRadarValues( nd, pSong->m_fMusicLengthSeconds, rvPre );
|
||||
|
||||
/* Apply user transforms to find out how the notes will really look.
|
||||
@@ -132,6 +133,7 @@ void ScoreKeeperNormal::Load(
|
||||
NoteDataUtil::TransformNoteData( nd, m_pPlayerState->m_PlayerOptions.GetStage(), pSteps->m_StepsType );
|
||||
RadarValues rvPost;
|
||||
NoteDataUtil::CalculateRadarValues( nd, pSong->m_fMusicLengthSeconds, rvPost );
|
||||
GAMESTATE->SetProcessedTimingData(NULL);
|
||||
|
||||
iTotalPossibleDancePoints += this->GetPossibleDancePoints( rvPre, rvPost );
|
||||
iTotalPossibleGradePoints += this->GetPossibleGradePoints( rvPre, rvPost );
|
||||
@@ -217,6 +219,8 @@ void ScoreKeeperNormal::OnNextSong( int iSongInCourseIndex, const Steps* pSteps,
|
||||
ASSERT( m_iMaxPossiblePoints >= 0 );
|
||||
m_iMaxScoreSoFar += m_iMaxPossiblePoints;
|
||||
|
||||
GAMESTATE->SetProcessedTimingData(const_cast<TimingData *>(&pSteps->m_Timing));
|
||||
|
||||
m_iNumTapsAndHolds = pNoteData->GetNumRowsWithTapOrHoldHead() + pNoteData->GetNumHoldNotes()
|
||||
+ pNoteData->GetNumRolls();
|
||||
|
||||
@@ -230,6 +234,8 @@ void ScoreKeeperNormal::OnNextSong( int iSongInCourseIndex, const Steps* pSteps,
|
||||
ASSERT( m_iPointBonus >= 0 );
|
||||
|
||||
m_iTapNotesHit = 0;
|
||||
|
||||
GAMESTATE->SetProcessedTimingData(NULL);
|
||||
}
|
||||
|
||||
static int GetScore(int p, int Z, int S, int n)
|
||||
|
||||
+343
-250
@@ -61,6 +61,7 @@ const float RECORD_HOLD_SECONDS = 0.3f;
|
||||
AutoScreenMessage( SM_UpdateTextInfo );
|
||||
AutoScreenMessage( SM_BackFromMainMenu );
|
||||
AutoScreenMessage( SM_BackFromAreaMenu );
|
||||
AutoScreenMessage( SM_BackFromAlterMenu );
|
||||
AutoScreenMessage( SM_BackFromStepsInformation );
|
||||
AutoScreenMessage( SM_BackFromOptions );
|
||||
AutoScreenMessage( SM_BackFromSongInformation );
|
||||
@@ -170,6 +171,7 @@ void ScreenEdit::InitEditMappings()
|
||||
m_EditMappingsMenuButton.button [EDIT_BUTTON_OPEN_EDIT_MENU][0] = GAME_BUTTON_START;
|
||||
m_EditMappingsMenuButton.button [EDIT_BUTTON_OPEN_EDIT_MENU][1] = GAME_BUTTON_BACK;
|
||||
|
||||
|
||||
// Escape, Enter = exit play/record
|
||||
m_PlayMappingsDeviceInput.button [EDIT_BUTTON_RETURN_TO_EDIT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_ENTER);
|
||||
m_PlayMappingsDeviceInput.button [EDIT_BUTTON_RETURN_TO_EDIT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_ESC);
|
||||
@@ -280,6 +282,7 @@ void ScreenEdit::InitEditMappings()
|
||||
m_EditMappingsMenuButton.button[EDIT_BUTTON_OPEN_EDIT_MENU][0] = GAME_BUTTON_START;
|
||||
m_EditMappingsMenuButton.button[EDIT_BUTTON_OPEN_EDIT_MENU][1] = GAME_BUTTON_BACK;
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_AREA_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_ENTER);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_ALTER_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Ca);
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_INPUT_HELP][0] = DeviceInput(DEVICE_KEYBOARD, KEY_F1);
|
||||
|
||||
m_EditMappingsDeviceInput.button[EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cb);
|
||||
@@ -505,27 +508,58 @@ static MenuDef g_MainMenu(
|
||||
MenuRowDef( ScreenEdit::exit, "Exit Edit Mode", true, EditMode_Practice, true, true, 0, NULL )
|
||||
);
|
||||
|
||||
static MenuDef g_AlterMenu(
|
||||
"ScreenMiniMenuAlterMenu",
|
||||
MenuRowDef(ScreenEdit::cut, "Cut", true,
|
||||
EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::copy, "Copy", true,
|
||||
EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::clear, "Clear area", true,
|
||||
EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::quantize, "Quantize", true,
|
||||
EditMode_Practice, true, true, 0,
|
||||
"4th","8th","12th","16th","24th","32nd","48th","64th","192nd"),
|
||||
MenuRowDef(ScreenEdit::turn, "Turn", true,
|
||||
EditMode_Practice, true, true, 0, "Left","Right","Mirror","Shuffle","SuperShuffle" ),
|
||||
MenuRowDef(ScreenEdit::transform, "Transform", true,
|
||||
EditMode_Practice, true, true, 0, "NoHolds","NoMines","Little","Wide",
|
||||
"Big","Quick","Skippy","Mines","Echo","Stomp","Planted","Floored",
|
||||
"Twister","NoJumps","NoHands","NoQuads","NoStretch" ),
|
||||
MenuRowDef(ScreenEdit::alter, "Alter", true,
|
||||
EditMode_Practice, true, true, 0, "Autogen To Fill Width","Backwards","Swap Sides",
|
||||
"Copy Left To Right","Copy Right To Left","Clear Left","Clear Right",
|
||||
"Collapse To One","Collapse Left","Shift Left","Shift Right" ),
|
||||
MenuRowDef(ScreenEdit::tempo, "Tempo", true,
|
||||
EditMode_Full, true, true, 0, "Compress 2x","Compress 3->2",
|
||||
"Compress 4->3","Expand 3->4","Expand 2->3","Expand 2x" ),
|
||||
MenuRowDef(ScreenEdit::play, "Play selection", true,
|
||||
EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::record, "Record in selection", true,
|
||||
EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::convert_to_pause, "Convert selection to pause", true,
|
||||
EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::convert_to_delay, "Convert selection to delay", true,
|
||||
EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::convert_to_warp, "Convert selection to warp", true,
|
||||
EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::convert_to_fake, "Convert selection to fake", true,
|
||||
EditMode_Full, true, true, 0, NULL )
|
||||
);
|
||||
|
||||
static MenuDef g_AreaMenu(
|
||||
"ScreenMiniMenuAreaMenu",
|
||||
MenuRowDef( ScreenEdit::cut, "Cut", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::copy, "Copy", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::paste_at_current_beat, "Paste at current beat", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::paste_at_begin_marker, "Paste at begin marker", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::clear, "Clear area", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::quantize, "Quantize", true, EditMode_Practice, true, true, 0, "4th","8th","12th","16th","24th","32nd","48th","64th","192nd"),
|
||||
MenuRowDef( ScreenEdit::turn, "Turn", true, EditMode_Practice, true, true, 0, "Left","Right","Mirror","Shuffle","SuperShuffle" ),
|
||||
MenuRowDef( ScreenEdit::transform, "Transform", true, EditMode_Practice, true, true, 0, "NoHolds","NoMines","Little","Wide","Big","Quick","Skippy","Mines","Echo","Stomp","Planted","Floored","Twister","NoJumps","NoHands","NoQuads","NoStretch" ),
|
||||
MenuRowDef( ScreenEdit::alter, "Alter", true, EditMode_Practice, true, true, 0, "Autogen To Fill Width","Backwards","Swap Sides","Copy Left To Right","Copy Right To Left","Clear Left","Clear Right","Collapse To One","Collapse Left","Shift Left","Shift Right" ),
|
||||
MenuRowDef( ScreenEdit::tempo, "Tempo", true, EditMode_Full, true, true, 0, "Compress 2x","Compress 3->2","Compress 4->3","Expand 3->4","Expand 2->3","Expand 2x" ),
|
||||
MenuRowDef( ScreenEdit::play, "Play selection", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::record, "Record in selection", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::insert_and_shift, "Insert beat and shift down", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::delete_and_shift, "Delete beat and shift up", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::shift_pauses_forward, "Shift all timing changes down", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::shift_pauses_backward, "Shift all timing changes up", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::convert_to_pause, "Convert selection to pause", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::convert_pause_to_beat, "Convert pause to beats", true, EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::undo, "Undo", true, EditMode_Practice, true, true, 0, NULL )
|
||||
MenuRowDef(ScreenEdit::convert_pause_to_beat, "Convert pause to beats", true,
|
||||
EditMode_Full, true, true, 0, NULL ),
|
||||
MenuRowDef( ScreenEdit::undo, "Undo", true, EditMode_Practice, true, true, 0, NULL ),
|
||||
MenuRowDef(ScreenEdit::clear_clipboard, "Clear clipboard", true,
|
||||
EditMode_Practice, true, true, 0, NULL )
|
||||
|
||||
);
|
||||
|
||||
static MenuDef g_StepsInformation(
|
||||
@@ -1152,6 +1186,9 @@ void ScreenEdit::UpdateTextInfo()
|
||||
sText += ssprintf( TAP_NOTE_TYPE_FORMAT.GetValue(), TAP_NOTE_TYPE.GetValue().c_str(), TapNoteTypeToString( m_selectedTap.type ).c_str() );
|
||||
break;
|
||||
}
|
||||
|
||||
GAMESTATE->SetProcessedTimingData(&m_pSteps->m_Timing);
|
||||
|
||||
sText += ssprintf( NUM_STEPS_FORMAT.GetValue(), TAP_STEPS.GetValue().c_str(), m_NoteDataEdit.GetNumTapNotes() );
|
||||
sText += ssprintf( NUM_JUMPS_FORMAT.GetValue(), JUMPS.GetValue().c_str(), m_NoteDataEdit.GetNumJumps() );
|
||||
sText += ssprintf( NUM_HANDS_FORMAT.GetValue(), HANDS.GetValue().c_str(), m_NoteDataEdit.GetNumHands() );
|
||||
@@ -1182,6 +1219,8 @@ void ScreenEdit::UpdateTextInfo()
|
||||
}
|
||||
|
||||
m_textInfo.SetText( sText );
|
||||
|
||||
GAMESTATE->SetProcessedTimingData(NULL);
|
||||
}
|
||||
|
||||
void ScreenEdit::DrawPrimitives()
|
||||
@@ -1294,7 +1333,7 @@ static int FindAttackAtTime( const AttackArray& attacks, float fStartTime )
|
||||
}
|
||||
|
||||
static LocalizedString BG_CHANGE_STEP_TIMING ( "ScreenEdit", "You must be in Song Timing Mode to edit BG Changes." );
|
||||
|
||||
static LocalizedString ALTER_MENU_NO_SELECTION ( "ScreenEdit", "You must have an area selected to enter the Alter Menu." );
|
||||
static LocalizedString SWITCHED_TO ( "ScreenEdit", "Switched to" );
|
||||
static LocalizedString NO_BACKGROUNDS_AVAILABLE ( "ScreenEdit", "No backgrounds available" );
|
||||
static ThemeMetric<bool> INVERT_SCROLL_BUTTONS ( "ScreenEdit", "InvertScrollSpeedButtons" );
|
||||
@@ -1556,24 +1595,27 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
case EDIT_BUTTON_OPEN_AREA_MENU:
|
||||
{
|
||||
// update enabled/disabled in g_AreaMenu
|
||||
bool bAreaSelected = m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1;
|
||||
g_AreaMenu.rows[cut].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[copy].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[paste_at_current_beat].bEnabled = !m_Clipboard.IsEmpty();
|
||||
g_AreaMenu.rows[paste_at_begin_marker].bEnabled = !m_Clipboard.IsEmpty() != 0 && m_NoteFieldEdit.m_iBeginMarker!=-1;
|
||||
g_AreaMenu.rows[clear].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[quantize].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[turn].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[transform].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[alter].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[tempo].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[play].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[record].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[convert_to_pause].bEnabled = bAreaSelected;
|
||||
g_AreaMenu.rows[undo].bEnabled = m_bHasUndo;
|
||||
EditMiniMenu( &g_AreaMenu, SM_BackFromAreaMenu );
|
||||
}
|
||||
break;
|
||||
case EDIT_BUTTON_OPEN_ALTER_MENU:
|
||||
{
|
||||
bool bAreaSelected = m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1;
|
||||
if (!bAreaSelected)
|
||||
{
|
||||
SCREENMAN->SystemMessage( ALTER_MENU_NO_SELECTION );
|
||||
SCREENMAN->PlayInvalidSound();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditMiniMenu(&g_AlterMenu, SM_BackFromAlterMenu);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case EDIT_BUTTON_OPEN_EDIT_MENU:
|
||||
EditMiniMenu( &g_MainMenu, SM_BackFromMainMenu );
|
||||
break;
|
||||
@@ -2039,7 +2081,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
|
||||
case EDIT_BUTTON_RECORD_SELECTION:
|
||||
if( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 )
|
||||
{
|
||||
HandleAreaMenuChoice( record );
|
||||
HandleAlterMenuChoice( record );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2639,6 +2681,10 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
|
||||
{
|
||||
HandleAreaMenuChoice( (AreaMenuChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers );
|
||||
}
|
||||
else if( SM == SM_BackFromAlterMenu )
|
||||
{
|
||||
HandleAlterMenuChoice( (AlterMenuChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers );
|
||||
}
|
||||
else if( SM == SM_BackFromStepsInformation )
|
||||
{
|
||||
HandleStepsInformationChoice( (StepsInformationChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers );
|
||||
@@ -3237,12 +3283,13 @@ static LocalizedString SAVE_CHANGES_BEFORE_EXITING ( "ScreenEdit", "Do you want
|
||||
|
||||
void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAnswers )
|
||||
{
|
||||
GAMESTATE->SetProcessedTimingData(&m_pSteps->m_Timing);
|
||||
switch( c )
|
||||
{
|
||||
DEFAULT_FAIL( c );
|
||||
case play_selection:
|
||||
if( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 )
|
||||
HandleAreaMenuChoice( play );
|
||||
HandleAlterMenuChoice( play );
|
||||
else if( m_NoteFieldEdit.m_iBeginMarker!=-1 )
|
||||
HandleMainMenuChoice( play_selection_start_to_end );
|
||||
else
|
||||
@@ -3455,36 +3502,277 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
|
||||
}
|
||||
break;
|
||||
};
|
||||
GAMESTATE->SetProcessedTimingData(NULL);
|
||||
}
|
||||
|
||||
void ScreenEdit::HandleAlterMenuChoice(AlterMenuChoice c, const vector<int> &iAnswers, bool bAllowUndo)
|
||||
{
|
||||
bool bSaveUndo = true;
|
||||
switch (c)
|
||||
{
|
||||
case play:
|
||||
case record:
|
||||
case cut:
|
||||
case copy:
|
||||
{
|
||||
bSaveUndo = false;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( bSaveUndo )
|
||||
SetDirty( true );
|
||||
|
||||
/* We call HandleAreaMenuChoice recursively. Only the outermost
|
||||
* HandleAreaMenuChoice should allow Undo so that the inner calls don't
|
||||
* also save Undo and mess up the outermost */
|
||||
if( !bAllowUndo )
|
||||
bSaveUndo = false;
|
||||
|
||||
if( bSaveUndo )
|
||||
SaveUndo();
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case cut:
|
||||
{
|
||||
HandleAlterMenuChoice( copy );
|
||||
HandleAlterMenuChoice( clear );
|
||||
}
|
||||
break;
|
||||
case copy:
|
||||
{
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_Clipboard.ClearAll();
|
||||
m_Clipboard.CopyRange( m_NoteDataEdit, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker );
|
||||
}
|
||||
break;
|
||||
case clear:
|
||||
{
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_NoteDataEdit.ClearRange( m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker );
|
||||
}
|
||||
break;
|
||||
case quantize:
|
||||
{
|
||||
NoteType nt = (NoteType)iAnswers[c];
|
||||
NoteDataUtil::SnapToNearestNoteType(m_NoteDataEdit, nt, nt,
|
||||
m_NoteFieldEdit.m_iBeginMarker,
|
||||
m_NoteFieldEdit.m_iEndMarker );
|
||||
break;
|
||||
}
|
||||
case turn:
|
||||
{
|
||||
const NoteData OldClipboard( m_Clipboard );
|
||||
HandleAlterMenuChoice( cut );
|
||||
|
||||
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
|
||||
TurnType tt = (TurnType)iAnswers[c];
|
||||
switch( tt )
|
||||
{
|
||||
DEFAULT_FAIL( tt );
|
||||
case left: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::left ); break;
|
||||
case right: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::right ); break;
|
||||
case mirror: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::mirror ); break;
|
||||
case shuffle: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::shuffle ); break;
|
||||
case super_shuffle: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::super_shuffle ); break;
|
||||
}
|
||||
|
||||
HandleAreaMenuChoice( paste_at_begin_marker );
|
||||
m_Clipboard = OldClipboard;
|
||||
}
|
||||
break;
|
||||
case transform:
|
||||
{
|
||||
int iBeginRow = m_NoteFieldEdit.m_iBeginMarker;
|
||||
int iEndRow = m_NoteFieldEdit.m_iEndMarker;
|
||||
TransformType tt = (TransformType)iAnswers[c];
|
||||
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
|
||||
|
||||
switch( tt )
|
||||
{
|
||||
DEFAULT_FAIL( tt );
|
||||
case noholds: NoteDataUtil::RemoveHoldNotes( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nomines: NoteDataUtil::RemoveMines( m_NoteDataEdit, iBeginRow, iBeginRow ); break;
|
||||
case little: NoteDataUtil::Little( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case wide: NoteDataUtil::Wide( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case big: NoteDataUtil::Big( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case quick: NoteDataUtil::Quick( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case skippy: NoteDataUtil::Skippy( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case add_mines: NoteDataUtil::AddMines( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case echo: NoteDataUtil::Echo( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case stomp: NoteDataUtil::Stomp( m_NoteDataEdit, st, iBeginRow, iEndRow ); break;
|
||||
case planted: NoteDataUtil::Planted( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case floored: NoteDataUtil::Floored( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case twister: NoteDataUtil::Twister( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nojumps: NoteDataUtil::RemoveJumps( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nohands: NoteDataUtil::RemoveHands( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case noquads: NoteDataUtil::RemoveQuads( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nostretch: NoteDataUtil::RemoveStretch( m_NoteDataEdit, st, iBeginRow, iBeginRow );break;
|
||||
}
|
||||
|
||||
// bake in the additions
|
||||
NoteDataUtil::ConvertAdditionsToRegular( m_NoteDataEdit );
|
||||
break;
|
||||
}
|
||||
case alter:
|
||||
{
|
||||
const NoteData OldClipboard( m_Clipboard );
|
||||
HandleAlterMenuChoice( cut );
|
||||
|
||||
AlterType at = (AlterType)iAnswers[c];
|
||||
switch( at )
|
||||
{
|
||||
DEFAULT_FAIL( at );
|
||||
case autogen_to_fill_width:
|
||||
{
|
||||
NoteData temp( m_Clipboard );
|
||||
int iMaxNonEmptyTrack = NoteDataUtil::GetMaxNonEmptyTrack( temp );
|
||||
if( iMaxNonEmptyTrack == -1 )
|
||||
break;
|
||||
temp.SetNumTracks( iMaxNonEmptyTrack+1 );
|
||||
NoteDataUtil::LoadTransformedSlidingWindow( temp, m_Clipboard, m_Clipboard.GetNumTracks() );
|
||||
NoteDataUtil::RemoveStretch( m_Clipboard, GAMESTATE->m_pCurSteps[0]->m_StepsType );
|
||||
}
|
||||
break;
|
||||
case backwards: NoteDataUtil::Backwards( m_Clipboard ); break;
|
||||
case swap_sides: NoteDataUtil::SwapSides( m_Clipboard ); break;
|
||||
case copy_left_to_right: NoteDataUtil::CopyLeftToRight( m_Clipboard ); break;
|
||||
case copy_right_to_left: NoteDataUtil::CopyRightToLeft( m_Clipboard ); break;
|
||||
case clear_left: NoteDataUtil::ClearLeft( m_Clipboard ); break;
|
||||
case clear_right: NoteDataUtil::ClearRight( m_Clipboard ); break;
|
||||
case collapse_to_one: NoteDataUtil::CollapseToOne( m_Clipboard ); break;
|
||||
case collapse_left: NoteDataUtil::CollapseLeft( m_Clipboard ); break;
|
||||
case shift_left: NoteDataUtil::ShiftLeft( m_Clipboard ); break;
|
||||
case shift_right: NoteDataUtil::ShiftRight( m_Clipboard ); break;
|
||||
}
|
||||
|
||||
HandleAreaMenuChoice( paste_at_begin_marker );
|
||||
m_Clipboard = OldClipboard;
|
||||
break;
|
||||
}
|
||||
case tempo:
|
||||
{
|
||||
// This affects all steps.
|
||||
AlterType at = (AlterType)iAnswers[c];
|
||||
float fScale = -1;
|
||||
|
||||
switch( at )
|
||||
{
|
||||
DEFAULT_FAIL( at );
|
||||
case compress_2x: fScale = 0.5f; break;
|
||||
case compress_3_2: fScale = 2.0f/3; break;
|
||||
case compress_4_3: fScale = 0.75f; break;
|
||||
case expand_4_3: fScale = 4.0f/3; break;
|
||||
case expand_3_2: fScale = 1.5f; break;
|
||||
case expand_2x: fScale = 2; break;
|
||||
}
|
||||
|
||||
int iStartIndex = m_NoteFieldEdit.m_iBeginMarker;
|
||||
int iEndIndex = m_NoteFieldEdit.m_iEndMarker;
|
||||
int iNewEndIndex = iEndIndex + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) );
|
||||
|
||||
// scale currently editing notes
|
||||
NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex );
|
||||
|
||||
// scale timing data
|
||||
GetAppropriateTiming().ScaleRegion(fScale,
|
||||
m_NoteFieldEdit.m_iBeginMarker,
|
||||
m_NoteFieldEdit.m_iEndMarker, true );
|
||||
|
||||
m_NoteFieldEdit.m_iEndMarker = iNewEndIndex;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case play:
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_iStartPlayingAt = m_NoteFieldEdit.m_iBeginMarker;
|
||||
m_iStopPlayingAt = m_NoteFieldEdit.m_iEndMarker;
|
||||
TransitionEditState( STATE_PLAYING );
|
||||
break;
|
||||
case record:
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_iStartPlayingAt = m_NoteFieldEdit.m_iBeginMarker;
|
||||
m_iStopPlayingAt = m_NoteFieldEdit.m_iEndMarker;
|
||||
TransitionEditState( STATE_RECORDING );
|
||||
break;
|
||||
case convert_to_pause:
|
||||
{
|
||||
ASSERT_M( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1, "Attempted to convert beats outside the notefield to pauses!" );
|
||||
float fMarkerStart = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
|
||||
float fMarkerEnd = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) );
|
||||
|
||||
// The length of the stop segment we're going to create. This includes time spent in any
|
||||
// stops in the selection, which will be deleted and subsumed into the new stop.
|
||||
float fStopLength = fMarkerEnd - fMarkerStart;
|
||||
|
||||
// be sure not to clobber the row at the start - a row at the end
|
||||
// can be dropped safely, though
|
||||
NoteDataUtil::DeleteRows( m_NoteDataEdit,
|
||||
m_NoteFieldEdit.m_iBeginMarker + 1,
|
||||
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker
|
||||
);
|
||||
GetAppropriateTiming().DeleteRows( m_NoteFieldEdit.m_iBeginMarker + 1,
|
||||
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker );
|
||||
GetAppropriateTiming().SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength );
|
||||
m_NoteFieldEdit.m_iBeginMarker = -1;
|
||||
m_NoteFieldEdit.m_iEndMarker = -1;
|
||||
break;
|
||||
}
|
||||
case convert_to_delay:
|
||||
{
|
||||
ASSERT_M( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1, "Attempted to convert beats outside the notefield to pauses!" );
|
||||
float fMarkerStart = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
|
||||
float fMarkerEnd = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) );
|
||||
|
||||
// The length of the delay segment we're going to create. This includes time spent in any
|
||||
// stops in the selection, which will be deleted and subsumed into the new stop.
|
||||
float fStopLength = fMarkerEnd - fMarkerStart;
|
||||
|
||||
NoteDataUtil::DeleteRows( m_NoteDataEdit,
|
||||
m_NoteFieldEdit.m_iBeginMarker,
|
||||
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker
|
||||
);
|
||||
GetAppropriateTiming().DeleteRows( m_NoteFieldEdit.m_iBeginMarker,
|
||||
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker );
|
||||
GetAppropriateTiming().SetDelayAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength );
|
||||
m_NoteFieldEdit.m_iBeginMarker = -1;
|
||||
m_NoteFieldEdit.m_iEndMarker = -1;
|
||||
break;
|
||||
}
|
||||
case convert_to_warp:
|
||||
{
|
||||
float startBeat = NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker);
|
||||
float lengthBeat = NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) - startBeat;
|
||||
GetAppropriateTiming().SetWarpAtBeat(startBeat,lengthBeat);
|
||||
SetDirty(true);
|
||||
break;
|
||||
}
|
||||
case convert_to_fake:
|
||||
{
|
||||
float startBeat = NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker);
|
||||
float lengthBeat = NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) - startBeat;
|
||||
GetAppropriateTiming().SetFakeAtBeat(startBeat,lengthBeat);
|
||||
SetDirty(true);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAnswers, bool bAllowUndo )
|
||||
{
|
||||
bool bSaveUndo = false;
|
||||
bool bSaveUndo = true;
|
||||
switch( c )
|
||||
{
|
||||
DEFAULT_FAIL( c );
|
||||
case cut:
|
||||
case copy:
|
||||
case play:
|
||||
case record:
|
||||
case clear_clipboard:
|
||||
case undo:
|
||||
bSaveUndo = false;
|
||||
break;
|
||||
case paste_at_current_beat:
|
||||
case paste_at_begin_marker:
|
||||
case clear:
|
||||
case quantize:
|
||||
case turn:
|
||||
case transform:
|
||||
case alter:
|
||||
case tempo:
|
||||
case insert_and_shift:
|
||||
case delete_and_shift:
|
||||
case shift_pauses_forward:
|
||||
case shift_pauses_backward:
|
||||
case convert_to_pause:
|
||||
case convert_pause_to_beat:
|
||||
bSaveUndo = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3503,19 +3791,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
|
||||
switch( c )
|
||||
{
|
||||
DEFAULT_FAIL( c );
|
||||
case cut:
|
||||
{
|
||||
HandleAreaMenuChoice( copy );
|
||||
HandleAreaMenuChoice( clear );
|
||||
}
|
||||
break;
|
||||
case copy:
|
||||
{
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_Clipboard.ClearAll();
|
||||
m_Clipboard.CopyRange( m_NoteDataEdit, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker );
|
||||
}
|
||||
break;
|
||||
|
||||
case paste_at_current_beat:
|
||||
case paste_at_begin_marker:
|
||||
{
|
||||
@@ -3536,172 +3812,6 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
|
||||
m_NoteDataEdit.CopyRange( m_Clipboard, 0, iRowsToCopy, iDestFirstRow );
|
||||
}
|
||||
break;
|
||||
case clear:
|
||||
{
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_NoteDataEdit.ClearRange( m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker );
|
||||
}
|
||||
break;
|
||||
case quantize:
|
||||
{
|
||||
NoteType nt = (NoteType)iAnswers[c];
|
||||
NoteDataUtil::SnapToNearestNoteType( m_NoteDataEdit, nt, nt, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker );
|
||||
}
|
||||
break;
|
||||
case turn:
|
||||
{
|
||||
const NoteData OldClipboard( m_Clipboard );
|
||||
HandleAreaMenuChoice( cut );
|
||||
|
||||
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
|
||||
TurnType tt = (TurnType)iAnswers[c];
|
||||
switch( tt )
|
||||
{
|
||||
DEFAULT_FAIL( tt );
|
||||
case left: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::left ); break;
|
||||
case right: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::right ); break;
|
||||
case mirror: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::mirror ); break;
|
||||
case shuffle: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::shuffle ); break;
|
||||
case super_shuffle: NoteDataUtil::Turn( m_Clipboard, st, NoteDataUtil::super_shuffle ); break;
|
||||
}
|
||||
|
||||
HandleAreaMenuChoice( paste_at_begin_marker );
|
||||
m_Clipboard = OldClipboard;
|
||||
}
|
||||
break;
|
||||
case transform:
|
||||
{
|
||||
int iBeginRow = m_NoteFieldEdit.m_iBeginMarker;
|
||||
int iEndRow = m_NoteFieldEdit.m_iEndMarker;
|
||||
TransformType tt = (TransformType)iAnswers[c];
|
||||
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
|
||||
|
||||
switch( tt )
|
||||
{
|
||||
DEFAULT_FAIL( tt );
|
||||
case noholds: NoteDataUtil::RemoveHoldNotes( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nomines: NoteDataUtil::RemoveMines( m_NoteDataEdit, iBeginRow, iBeginRow ); break;
|
||||
case little: NoteDataUtil::Little( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case wide: NoteDataUtil::Wide( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case big: NoteDataUtil::Big( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case quick: NoteDataUtil::Quick( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case skippy: NoteDataUtil::Skippy( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case add_mines: NoteDataUtil::AddMines( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case echo: NoteDataUtil::Echo( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case stomp: NoteDataUtil::Stomp( m_NoteDataEdit, st, iBeginRow, iEndRow ); break;
|
||||
case planted: NoteDataUtil::Planted( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case floored: NoteDataUtil::Floored( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case twister: NoteDataUtil::Twister( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nojumps: NoteDataUtil::RemoveJumps( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nohands: NoteDataUtil::RemoveHands( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case noquads: NoteDataUtil::RemoveQuads( m_NoteDataEdit, iBeginRow, iEndRow ); break;
|
||||
case nostretch: NoteDataUtil::RemoveStretch( m_NoteDataEdit, st, iBeginRow, iBeginRow );break;
|
||||
}
|
||||
|
||||
// bake in the additions
|
||||
NoteDataUtil::ConvertAdditionsToRegular( m_NoteDataEdit );
|
||||
}
|
||||
break;
|
||||
case alter:
|
||||
{
|
||||
const NoteData OldClipboard( m_Clipboard );
|
||||
HandleAreaMenuChoice( cut );
|
||||
|
||||
AlterType at = (AlterType)iAnswers[c];
|
||||
switch( at )
|
||||
{
|
||||
DEFAULT_FAIL( at );
|
||||
case autogen_to_fill_width:
|
||||
{
|
||||
NoteData temp( m_Clipboard );
|
||||
int iMaxNonEmptyTrack = NoteDataUtil::GetMaxNonEmptyTrack( temp );
|
||||
if( iMaxNonEmptyTrack == -1 )
|
||||
break;
|
||||
temp.SetNumTracks( iMaxNonEmptyTrack+1 );
|
||||
NoteDataUtil::LoadTransformedSlidingWindow( temp, m_Clipboard, m_Clipboard.GetNumTracks() );
|
||||
NoteDataUtil::RemoveStretch( m_Clipboard, GAMESTATE->m_pCurSteps[0]->m_StepsType );
|
||||
}
|
||||
break;
|
||||
case backwards: NoteDataUtil::Backwards( m_Clipboard ); break;
|
||||
case swap_sides: NoteDataUtil::SwapSides( m_Clipboard ); break;
|
||||
case copy_left_to_right: NoteDataUtil::CopyLeftToRight( m_Clipboard ); break;
|
||||
case copy_right_to_left: NoteDataUtil::CopyRightToLeft( m_Clipboard ); break;
|
||||
case clear_left: NoteDataUtil::ClearLeft( m_Clipboard ); break;
|
||||
case clear_right: NoteDataUtil::ClearRight( m_Clipboard ); break;
|
||||
case collapse_to_one: NoteDataUtil::CollapseToOne( m_Clipboard ); break;
|
||||
case collapse_left: NoteDataUtil::CollapseLeft( m_Clipboard ); break;
|
||||
case shift_left: NoteDataUtil::ShiftLeft( m_Clipboard ); break;
|
||||
case shift_right: NoteDataUtil::ShiftRight( m_Clipboard ); break;
|
||||
}
|
||||
|
||||
HandleAreaMenuChoice( paste_at_begin_marker );
|
||||
m_Clipboard = OldClipboard;
|
||||
}
|
||||
break;
|
||||
case tempo:
|
||||
{
|
||||
// This affects all steps.
|
||||
AlterType at = (AlterType)iAnswers[c];
|
||||
float fScale = -1;
|
||||
|
||||
switch( at )
|
||||
{
|
||||
DEFAULT_FAIL( at );
|
||||
case compress_2x: fScale = 0.5f; break;
|
||||
case compress_3_2: fScale = 2.0f/3; break;
|
||||
case compress_4_3: fScale = 0.75f; break;
|
||||
case expand_4_3: fScale = 4.0f/3; break;
|
||||
case expand_3_2: fScale = 1.5f; break;
|
||||
case expand_2x: fScale = 2; break;
|
||||
}
|
||||
|
||||
int iStartIndex = m_NoteFieldEdit.m_iBeginMarker;
|
||||
int iEndIndex = m_NoteFieldEdit.m_iEndMarker;
|
||||
int iNewEndIndex = iEndIndex + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) );
|
||||
|
||||
// scale currently editing notes
|
||||
NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex );
|
||||
|
||||
// scale timing data
|
||||
GetAppropriateTiming().ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true );
|
||||
|
||||
// scale all other steps.
|
||||
/*
|
||||
const vector<Steps*> sIter = m_pSong->GetAllSteps();
|
||||
RString sTempStyle, sTempDiff;
|
||||
for( unsigned i = 0; i < sIter.size(); i++ )
|
||||
{
|
||||
if( sIter[i]->IsAutogen() )
|
||||
continue;
|
||||
|
||||
// XXX: Edits are distinguished by description.
|
||||
// Compare vs m_pSteps.
|
||||
if( (sIter[i]->m_StepsType == GAMESTATE->m_pCurSteps[PLAYER_1]->m_StepsType) &&
|
||||
(sIter[i]->GetDifficulty() == GAMESTATE->m_pCurSteps[PLAYER_1]->GetDifficulty()) )
|
||||
continue;
|
||||
|
||||
NoteData ndTemp;
|
||||
sIter[i]->GetNoteData( ndTemp );
|
||||
NoteDataUtil::ScaleRegion( ndTemp, fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker );
|
||||
sIter[i]->SetNoteData( ndTemp );
|
||||
}
|
||||
*/
|
||||
m_NoteFieldEdit.m_iEndMarker = iNewEndIndex;
|
||||
|
||||
}
|
||||
break;
|
||||
case play:
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_iStartPlayingAt = m_NoteFieldEdit.m_iBeginMarker;
|
||||
m_iStopPlayingAt = m_NoteFieldEdit.m_iEndMarker;
|
||||
TransitionEditState( STATE_PLAYING );
|
||||
break;
|
||||
case record:
|
||||
ASSERT( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1 );
|
||||
m_iStartPlayingAt = m_NoteFieldEdit.m_iBeginMarker;
|
||||
m_iStopPlayingAt = m_NoteFieldEdit.m_iEndMarker;
|
||||
TransitionEditState( STATE_RECORDING );
|
||||
break;
|
||||
case insert_and_shift:
|
||||
NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow( GetBeat() ), BeatToNoteRow(1) );
|
||||
break;
|
||||
@@ -3714,29 +3824,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
|
||||
case shift_pauses_backward:
|
||||
GetAppropriateTiming().DeleteRows( GetRow() + 1, BeatToNoteRow(1) );
|
||||
break;
|
||||
case convert_to_pause:
|
||||
{
|
||||
ASSERT_M( m_NoteFieldEdit.m_iBeginMarker!=-1 && m_NoteFieldEdit.m_iEndMarker!=-1, "Attempted to convert beats outside the notefield to pauses!" );
|
||||
float fMarkerStart = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
|
||||
float fMarkerEnd = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) );
|
||||
|
||||
// The length of the stop segment we're going to create. This includes time spent in any
|
||||
// stops in the selection, which will be deleted and subsumed into the new stop.
|
||||
float fStopLength = fMarkerEnd - fMarkerStart;
|
||||
|
||||
// be sure not to clobber the row at the start - a row at the end
|
||||
// can be dropped safely, though
|
||||
NoteDataUtil::DeleteRows( m_NoteDataEdit,
|
||||
m_NoteFieldEdit.m_iBeginMarker + 1,
|
||||
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker
|
||||
);
|
||||
GetAppropriateTiming().DeleteRows( m_NoteFieldEdit.m_iBeginMarker + 1,
|
||||
m_NoteFieldEdit.m_iEndMarker-m_NoteFieldEdit.m_iBeginMarker );
|
||||
GetAppropriateTiming().SetStopAtRow( m_NoteFieldEdit.m_iBeginMarker, fStopLength );
|
||||
m_NoteFieldEdit.m_iBeginMarker = -1;
|
||||
m_NoteFieldEdit.m_iEndMarker = -1;
|
||||
break;
|
||||
}
|
||||
case convert_pause_to_beat:
|
||||
{
|
||||
// TODO: Convert both Delays and Stops at once.
|
||||
@@ -3753,6 +3841,11 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
|
||||
case undo:
|
||||
Undo();
|
||||
break;
|
||||
case clear_clipboard:
|
||||
{
|
||||
m_Clipboard.ClearAll();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if( bSaveUndo )
|
||||
|
||||
+41
-9
@@ -87,6 +87,7 @@ enum EditButton
|
||||
|
||||
EDIT_BUTTON_OPEN_EDIT_MENU,
|
||||
EDIT_BUTTON_OPEN_TIMING_MENU,
|
||||
EDIT_BUTTON_OPEN_ALTER_MENU,
|
||||
EDIT_BUTTON_OPEN_AREA_MENU,
|
||||
EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU,
|
||||
EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU,
|
||||
@@ -209,7 +210,12 @@ public:
|
||||
virtual void PushSelf( lua_State *L );
|
||||
|
||||
protected:
|
||||
virtual ScreenType GetScreenType() const { return m_EditState==STATE_PLAYING ? gameplay : ScreenWithMenuElements::GetScreenType(); }
|
||||
virtual ScreenType GetScreenType() const
|
||||
{
|
||||
return m_EditState==STATE_PLAYING ?
|
||||
gameplay :
|
||||
ScreenWithMenuElements::GetScreenType();
|
||||
}
|
||||
|
||||
void TransitionEditState( EditState em );
|
||||
void ScrollTo( float fDestinationBeat );
|
||||
@@ -268,7 +274,8 @@ protected:
|
||||
BitmapText m_textPlayRecordHelp;
|
||||
|
||||
// keep track of where we are and what we're doing
|
||||
float m_fTrailingBeat; // this approaches GAMESTATE->m_fSongBeat, which is the actual beat
|
||||
float m_fTrailingBeat;
|
||||
// the above approaches GAMESTATE->m_fSongBeat, which is the actual beat
|
||||
/**
|
||||
* @brief The location we were at when shift was pressed.
|
||||
*
|
||||
@@ -365,12 +372,10 @@ public:
|
||||
void HandleMainMenuChoice( MainMenuChoice c ) { const vector<int> v; HandleMainMenuChoice( c, v ); }
|
||||
MainMenuChoice m_CurrentAction;
|
||||
|
||||
enum AreaMenuChoice
|
||||
enum AlterMenuChoice
|
||||
{
|
||||
cut,
|
||||
copy,
|
||||
paste_at_current_beat,
|
||||
paste_at_begin_marker,
|
||||
clear,
|
||||
quantize,
|
||||
turn,
|
||||
@@ -379,17 +384,41 @@ public:
|
||||
tempo,
|
||||
play,
|
||||
record,
|
||||
convert_to_pause,
|
||||
convert_to_delay,
|
||||
convert_to_warp,
|
||||
convert_to_fake,
|
||||
NUM_ALTER_MENU_CHOICES
|
||||
|
||||
};
|
||||
|
||||
enum AreaMenuChoice
|
||||
{
|
||||
paste_at_current_beat,
|
||||
paste_at_begin_marker,
|
||||
insert_and_shift,
|
||||
delete_and_shift,
|
||||
shift_pauses_forward,
|
||||
shift_pauses_backward,
|
||||
convert_to_pause,
|
||||
convert_pause_to_beat,
|
||||
undo,
|
||||
clear_clipboard,
|
||||
NUM_AREA_MENU_CHOICES
|
||||
};
|
||||
void HandleAlterMenuChoice(AlterMenuChoice c,
|
||||
const vector<int> &iAnswers,
|
||||
bool bAllowUndo = true);
|
||||
void HandleAlterMenuChoice(AlterMenuChoice c,
|
||||
bool bAllowUndo = true)
|
||||
{
|
||||
const vector<int> v; HandleAlterMenuChoice(c, v, bAllowUndo);
|
||||
}
|
||||
|
||||
void HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAnswers, bool bAllowUndo = true );
|
||||
void HandleAreaMenuChoice( AreaMenuChoice c, bool bAllowUndo = true ) { const vector<int> v; HandleAreaMenuChoice( c, v, bAllowUndo ); }
|
||||
void HandleAreaMenuChoice( AreaMenuChoice c, bool bAllowUndo = true )
|
||||
{
|
||||
const vector<int> v; HandleAreaMenuChoice( c, v, bAllowUndo );
|
||||
}
|
||||
/** @brief How should the selected notes be transformed? */
|
||||
enum TurnType
|
||||
{
|
||||
@@ -511,7 +540,8 @@ public:
|
||||
NUM_TIMING_DATA_INFORMATION_CHOICES
|
||||
};
|
||||
|
||||
void HandleTimingDataInformationChoice ( TimingDataInformationChoice c, const vector<int> &iAnswers );
|
||||
void HandleTimingDataInformationChoice (TimingDataInformationChoice c,
|
||||
const vector<int> &iAnswers );
|
||||
|
||||
enum BGChangeChoice
|
||||
{
|
||||
@@ -581,7 +611,9 @@ public:
|
||||
MapEditButtonToMenuButton m_RecordPausedMappingsMenuButton;
|
||||
|
||||
void MakeFilteredMenuDef( const MenuDef* pDef, MenuDef &menu );
|
||||
void EditMiniMenu( const MenuDef* pDef, ScreenMessage SM_SendOnOK = SM_None, ScreenMessage SM_SendOnCancel = SM_None );
|
||||
void EditMiniMenu(const MenuDef* pDef,
|
||||
ScreenMessage SM_SendOnOK = SM_None,
|
||||
ScreenMessage SM_SendOnCancel = SM_None );
|
||||
private:
|
||||
/**
|
||||
* @brief Retrieve the appropriate TimingData based on GAMESTATE.
|
||||
|
||||
@@ -2294,12 +2294,14 @@ void ScreenGameplay::SaveStats()
|
||||
RadarValues rv;
|
||||
PlayerStageStats &pss = *pi->GetPlayerStageStats();
|
||||
const NoteData &nd = pi->m_pPlayer->GetNoteData();
|
||||
PlayerNumber pn = pi->m_pn;
|
||||
|
||||
GAMESTATE->SetProcessedTimingData(&GAMESTATE->m_pCurSteps[pn]->m_Timing);
|
||||
NoteDataUtil::CalculateRadarValues( nd, fMusicLen, rv );
|
||||
pss.m_radarPossible += rv;
|
||||
|
||||
NoteDataWithScoring::GetActualRadarValues( nd, pss, fMusicLen, rv );
|
||||
pss.m_radarActual += rv;
|
||||
GAMESTATE->SetProcessedTimingData(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,12 @@ void ScreenGameplaySyncMachine::Init()
|
||||
|
||||
RString sFile = THEME->GetPathO("ScreenGameplaySyncMachine","music");
|
||||
// Allow themers to use either a .ssc or .sm file for this. -aj
|
||||
SSCLoader loaderSSC;
|
||||
SMLoader loaderSM;
|
||||
if(sFile.Right(4) == ".ssc")
|
||||
SSCLoader::LoadFromSSCFile( sFile, m_Song );
|
||||
loaderSSC.LoadFromSimfile( sFile, m_Song );
|
||||
else
|
||||
SMLoader::LoadFromSMFile( sFile, m_Song );
|
||||
loaderSM.LoadFromSimfile( sFile, m_Song );
|
||||
|
||||
m_Song.SetSongDir( Dirname(sFile) );
|
||||
m_Song.TidyUpData();
|
||||
|
||||
@@ -135,10 +135,12 @@ void ScreenHowToPlay::Init()
|
||||
|
||||
// Allow themers to use either a .ssc or .sm file for this. -aj
|
||||
RString sStepsPath = THEME->GetPathO(m_sName, "steps");
|
||||
SSCLoader loaderSSC;
|
||||
SMLoader loaderSM;
|
||||
if( sStepsPath.Right(4) == ".ssc" )
|
||||
SSCLoader::LoadFromSSCFile( sStepsPath, m_Song, false );
|
||||
loaderSSC.LoadFromSimfile( sStepsPath, m_Song, false );
|
||||
else
|
||||
SMLoader::LoadFromSMFile( sStepsPath, m_Song, false );
|
||||
loaderSM.LoadFromSimfile( sStepsPath, m_Song, false );
|
||||
m_Song.AddAutoGenNotes();
|
||||
|
||||
const Style* pStyle = GAMESTATE->GetCurrentStyle();
|
||||
|
||||
@@ -145,7 +145,7 @@ void ScreenOptionsEditCourse::Init()
|
||||
sc.m_Tutorial = SongCriteria::Tutorial_No;
|
||||
sc.m_Locked = SongCriteria::Locked_Unlocked;
|
||||
|
||||
SongUtil::FilterSongs( sc, SONGMAN->GetAllSongs(), m_vpSongs );
|
||||
SongUtil::FilterSongs( sc, SONGMAN->GetAllSongs(), m_vpSongs, true );
|
||||
|
||||
SongUtil::SortSongPointerArrayByTitle( m_vpSongs );
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "global.h"
|
||||
|
||||
#if !defined(WITHOUT_NETWORKING)
|
||||
#include "ScreenPackagesSSC.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "RageDisplay.h"
|
||||
@@ -50,6 +52,7 @@ RString ScreenPackagesSSC::JSONParse( const RString &string_in )
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
* (c) 2009 Colby Klein
|
||||
* All rights reserved.
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "RageFileManager.h"
|
||||
#include "RageFile.h"
|
||||
#include "Sprite.h"
|
||||
|
||||
#if !defined(WITHOUT_NETWORKING)
|
||||
/** @brief Parses JSON for downloadable content. */
|
||||
class ScreenPackagesSSC : public ScreenWithMenuElements
|
||||
{
|
||||
@@ -24,6 +26,7 @@ public:
|
||||
private:
|
||||
RString JSONParse( const RString &string_in );
|
||||
};
|
||||
#endif // WITHOUT_NETWORKING?
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -197,7 +197,8 @@ static void CopyEdits( const RString &sFromProfileDir, const RString &sToProfile
|
||||
iNumErrored++;
|
||||
|
||||
// Test whether the song we need for this edit is present and ignore this edit if not present.
|
||||
if( !SSCLoader::LoadEditFromFile( sFromDir+*i, ProfileSlot_Machine, false ) )
|
||||
SSCLoader loaderSSC;
|
||||
if( !loaderSSC.LoadEditFromFile( sFromDir+*i, ProfileSlot_Machine, false ) )
|
||||
{
|
||||
iNumIgnored++;
|
||||
continue;
|
||||
|
||||
@@ -253,7 +253,14 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input )
|
||||
|
||||
case ChangeSongOffset:
|
||||
if( GAMESTATE->m_pCurSong != NULL )
|
||||
{
|
||||
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fDelta;
|
||||
const vector<Steps *>& vpSteps = GAMESTATE->m_pCurSong->GetAllSteps();
|
||||
FOREACH( Steps*, const_cast<vector<Steps *>&>(vpSteps), s )
|
||||
{
|
||||
(*s)->m_Timing.m_fBeat0OffsetInSeconds += fDelta;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-7
@@ -41,7 +41,7 @@
|
||||
* @brief The internal version of the cache for StepMania.
|
||||
*
|
||||
* Increment this value to invalidate the current cache. */
|
||||
const int FILE_CACHE_VERSION = 179;
|
||||
const int FILE_CACHE_VERSION = 180;
|
||||
|
||||
/** @brief How long does a song sample last by default? */
|
||||
const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f;
|
||||
@@ -235,12 +235,14 @@ bool Song::LoadFromSongDir( RString sDir )
|
||||
if( bUseCache )
|
||||
{
|
||||
// LOG->Trace( "Loading '%s' from cache file '%s'.", m_sSongDir.c_str(), GetCacheFilePath().c_str() );
|
||||
bool bLoadedFromSSC = SSCLoader::LoadFromSSCFile( sCacheFilePath, *this, true );
|
||||
SSCLoader loaderSSC;
|
||||
bool bLoadedFromSSC = loaderSSC.LoadFromSimfile( sCacheFilePath, *this, true );
|
||||
if( !bLoadedFromSSC )
|
||||
{
|
||||
// load from .sm
|
||||
SMLoader::LoadFromSMFile( sCacheFilePath, *this, true );
|
||||
SMLoader::TidyUpData( *this, true );
|
||||
SMLoader loaderSM;
|
||||
loaderSM.LoadFromSimfile( sCacheFilePath, *this, true );
|
||||
loaderSM.TidyUpData( *this, true );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1502,9 +1504,10 @@ public:
|
||||
static int GetBackgroundPath( T* p, lua_State *L )
|
||||
{
|
||||
RString s = p->GetBackgroundPath();
|
||||
if( s.empty() )
|
||||
s = "";
|
||||
lua_pushstring(L, s);
|
||||
if( !s.empty() )
|
||||
lua_pushstring(L, s);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
static int GetCDTitlePath( T* p, lua_State *L ) { RString s = p->GetCDTitlePath(); if( s.empty() ) return 0; LuaHelpers::Push(L, s); return 1; }
|
||||
|
||||
+6
-3
@@ -1692,12 +1692,15 @@ void SongManager::LoadStepEditsFromProfileDir( const RString &sProfileDir, Profi
|
||||
for( int i=0; i<size; i++ )
|
||||
{
|
||||
RString fn = vsFiles[i];
|
||||
|
||||
bool bLoadedFromSSC = SSCLoader::LoadEditFromFile( fn, slot, true );
|
||||
SSCLoader loaderSSC;
|
||||
bool bLoadedFromSSC = loaderSSC.LoadEditFromFile( fn, slot, true );
|
||||
// If we don't load the edit from a .ssc-style .edit, then we should
|
||||
// also try the .sm-style edit file. -aj
|
||||
if( !bLoadedFromSSC )
|
||||
SMLoader::LoadEditFromFile( fn, slot, true );
|
||||
{
|
||||
SMLoader loaderSM;
|
||||
loaderSM.LoadEditFromFile( fn, slot, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-2
@@ -871,13 +871,15 @@ void SongUtil::GetAllSongGenres( vector<RString> &vsOut )
|
||||
}
|
||||
}
|
||||
|
||||
void SongUtil::FilterSongs( const SongCriteria &sc, const vector<Song*> &in, vector<Song*> &out )
|
||||
void SongUtil::FilterSongs( const SongCriteria &sc, const vector<Song*> &in,
|
||||
vector<Song*> &out, bool doCareAboutGame )
|
||||
{
|
||||
out.reserve( in.size() );
|
||||
FOREACH_CONST( Song*, in, s )
|
||||
{
|
||||
if( sc.Matches( *s ) )
|
||||
if( sc.Matches( *s ) && (!doCareAboutGame || IsSongPlayable(*s) ) )
|
||||
{
|
||||
|
||||
out.push_back( *s );
|
||||
}
|
||||
}
|
||||
@@ -963,6 +965,21 @@ bool SongUtil::IsStepsPlayable( Song *pSong, Steps *pSteps )
|
||||
return find( vpSteps.begin(), vpSteps.end(), pSteps ) != vpSteps.end();
|
||||
}
|
||||
|
||||
bool SongUtil::IsSongPlayable( Song *s )
|
||||
{
|
||||
const vector<Steps*> & steps = s->GetAllSteps();
|
||||
// I'm sure there is a foreach loop, but I don't
|
||||
FOREACH( Steps*, const_cast<vector<Steps*>&>(steps), step )
|
||||
{
|
||||
if (IsStepsPlayable(s, *step))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SongUtil::GetStepsTypeAndDifficultyFromSortOrder( SortOrder so, StepsType &stOut, Difficulty &dcOut )
|
||||
{
|
||||
switch( so )
|
||||
|
||||
+14
-1
@@ -163,12 +163,25 @@ namespace SongUtil
|
||||
bool ValidateCurrentStepsCredit( const RString &sAnswer, RString &sErrorOut );
|
||||
|
||||
void GetAllSongGenres( vector<RString> &vsOut );
|
||||
void FilterSongs( const SongCriteria &sc, const vector<Song*> &in, vector<Song*> &out );
|
||||
/**
|
||||
* @brief Filter the selection of songs to only match certain criteria.
|
||||
* @param sc the intended song criteria.
|
||||
* @param in the starting batch of songs.
|
||||
* @param out the resulting batch.
|
||||
* @param doCareAboutGame a flag to see if we should only get playable steps. */
|
||||
void FilterSongs( const SongCriteria &sc, const vector<Song*> &in, vector<Song*> &out,
|
||||
bool doCareAboutGame = false );
|
||||
|
||||
void GetPlayableStepsTypes( const Song *pSong, set<StepsType> &vOut );
|
||||
void GetPlayableSteps( const Song *pSong, vector<Steps*> &vOut );
|
||||
bool IsStepsTypePlayable( Song *pSong, StepsType st );
|
||||
bool IsStepsPlayable( Song *pSong, Steps *pSteps );
|
||||
|
||||
/**
|
||||
* @brief Determine if the song has any playable steps in the present game.
|
||||
* @param s the current song.
|
||||
* @return true if the song has playable steps, false otherwise. */
|
||||
bool IsSongPlayable( Song *s );
|
||||
|
||||
bool GetStepsTypeAndDifficultyFromSortOrder( SortOrder so, StepsType &st, Difficulty &dc );
|
||||
}
|
||||
|
||||
+7
-2
@@ -14,6 +14,7 @@
|
||||
#include "global.h"
|
||||
#include "Steps.h"
|
||||
#include "StepsUtil.h"
|
||||
#include "GameState.h"
|
||||
#include "Song.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
@@ -192,6 +193,7 @@ void Steps::CalculateRadarValues( float fMusicLengthSeconds )
|
||||
FOREACH_PlayerNumber( pn )
|
||||
m_CachedRadarValues[pn].Zero();
|
||||
|
||||
GAMESTATE->SetProcessedTimingData(&this->m_Timing);
|
||||
if( tempNoteData.IsComposite() )
|
||||
{
|
||||
vector<NoteData> vParts;
|
||||
@@ -205,6 +207,7 @@ void Steps::CalculateRadarValues( float fMusicLengthSeconds )
|
||||
NoteDataUtil::CalculateRadarValues( tempNoteData, fMusicLengthSeconds, m_CachedRadarValues[0] );
|
||||
fill_n( m_CachedRadarValues + 1, NUM_PLAYERS-1, m_CachedRadarValues[0] );
|
||||
}
|
||||
GAMESTATE->SetProcessedTimingData(NULL);
|
||||
}
|
||||
|
||||
void Steps::Decompress() const
|
||||
@@ -239,11 +242,13 @@ void Steps::Decompress() const
|
||||
{
|
||||
// We have data on disk and not in memory. Load it.
|
||||
Song s;
|
||||
bool bLoadedFromSSC = SSCLoader::LoadFromSSCFile(m_sFilename, s, true);
|
||||
SSCLoader loaderSSC;
|
||||
bool bLoadedFromSSC = loaderSSC.LoadFromSimfile(m_sFilename, s, true);
|
||||
if( !bLoadedFromSSC )
|
||||
{
|
||||
// try reading from .sm instead
|
||||
if( !SMLoader::LoadFromSMFile(m_sFilename, s, true) )
|
||||
SMLoader loaderSM;
|
||||
if( !loaderSM.LoadFromSimfile(m_sFilename, s, true) )
|
||||
{
|
||||
LOG->Warn( "Couldn't load \"%s\"", m_sFilename.c_str() );
|
||||
return;
|
||||
|
||||
+1
-1
@@ -1746,7 +1746,7 @@ public:
|
||||
LuaHelpers::CreateTableFromArray(fBPMs, L);
|
||||
return 1;
|
||||
}
|
||||
static int HasNegativeBPMs( T* p, lua_State *L ) { lua_pushboolean(L, p->m_bHasNegativeBpms); return 1; }
|
||||
static int HasNegativeBPMs( T* p, lua_State *L ) { lua_pushboolean(L, p->HasWarps()); return 1; }
|
||||
// formerly in Song.cpp in sm-ssc private beta 1.x:
|
||||
static int GetBPMAtBeat( T* p, lua_State *L ) { lua_pushnumber(L, p->GetBPMAtBeat(FArg(1))); return 1; }
|
||||
static int GetBeatFromElapsedTime( T* p, lua_State *L ) { lua_pushnumber(L, p->GetBeatFromElapsedTime(FArg(1))); return 1; }
|
||||
|
||||
@@ -845,6 +845,20 @@ public:
|
||||
*/
|
||||
void AddFakeSegment( const FakeSegment &seg );
|
||||
|
||||
/**
|
||||
* @brief Determine if this notes on this row can be judged.
|
||||
* @param row the row to focus on.
|
||||
* @return true if the row can be judged, false otherwise. */
|
||||
bool IsJudgableAtRow( int row ) const
|
||||
{
|
||||
return !(IsWarpAtRow(row) || IsFakeAtRow(row));
|
||||
}
|
||||
/**
|
||||
* @brief Determine if this notes on this beat can be judged.
|
||||
* @param beat the beat to focus on.
|
||||
* @return true if the row can be judged, false otherwise. */
|
||||
bool IsJudgableAtBeat( float beat ) const { return IsJudgableAtRow( BeatToNoteRow( beat ) ); }
|
||||
|
||||
|
||||
|
||||
void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor );
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "Trail.h"
|
||||
#include "Foreach.h"
|
||||
#include "GameState.h"
|
||||
#include "Steps.h"
|
||||
#include "Song.h"
|
||||
#include "PlayerOptions.h"
|
||||
@@ -116,6 +117,7 @@ const RadarValues &Trail::GetRadarValues() const
|
||||
NoteData nd;
|
||||
pSteps->GetNoteData( nd );
|
||||
RadarValues rv_orig;
|
||||
GAMESTATE->SetProcessedTimingData(const_cast<TimingData *>(&pSteps->m_Timing));
|
||||
NoteDataUtil::CalculateRadarValues( nd, e->pSong->m_fMusicLengthSeconds, rv_orig );
|
||||
PlayerOptions po;
|
||||
po.FromString( e->Modifiers );
|
||||
@@ -124,6 +126,7 @@ const RadarValues &Trail::GetRadarValues() const
|
||||
NoteDataUtil::TransformNoteData( nd, e->Attacks, pSteps->m_StepsType, e->pSong );
|
||||
RadarValues transformed_rv;
|
||||
NoteDataUtil::CalculateRadarValues( nd, e->pSong->m_fMusicLengthSeconds, transformed_rv );
|
||||
GAMESTATE->SetProcessedTimingData(NULL);
|
||||
rv += transformed_rv;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user