Added ScreenHeartEntry to default theme.
This commit is contained in:
@@ -182,8 +182,7 @@ Branch = {
|
||||
GameplayScreen = function()
|
||||
return IsRoutine() and "ScreenGameplayShared" or "ScreenGameplay"
|
||||
end,
|
||||
AfterGameplay = function()
|
||||
-- pick an evaluation screen based on settings.
|
||||
EvaluationScreen= function()
|
||||
if IsNetSMOnline() then
|
||||
return "ScreenNetEvaluation"
|
||||
else
|
||||
@@ -191,6 +190,27 @@ Branch = {
|
||||
return "ScreenEvaluationNormal"
|
||||
end
|
||||
end,
|
||||
AfterGameplay = function()
|
||||
-- pick an evaluation screen based on settings.
|
||||
if THEME:GetMetric("ScreenHeartEntry", "HeartEntryEnabled") then
|
||||
local go_to_heart= false
|
||||
for i, pn in ipairs(GAMESTATE:GetEnabledPlayers()) do
|
||||
local profile= PROFILEMAN:GetProfile(pn)
|
||||
if profile and profile:GetIgnoreStepCountCalories() then
|
||||
go_to_heart= true
|
||||
end
|
||||
end
|
||||
if go_to_heart then
|
||||
return "ScreenHeartEntry"
|
||||
end
|
||||
return Branch.EvaluationScreen()
|
||||
else
|
||||
return Branch.EvaluationScreen()
|
||||
end
|
||||
end,
|
||||
AfterHeartEntry= function()
|
||||
return Branch.EvaluationScreen()
|
||||
end,
|
||||
AfterEvaluation = function()
|
||||
if GAMESTATE:IsCourseMode() then
|
||||
return "ScreenProfileSave"
|
||||
|
||||
@@ -3547,6 +3547,19 @@ Class="ScreenGameplayShared"
|
||||
Fallback="ScreenGameplay"
|
||||
PlayerType="PlayerShared"
|
||||
|
||||
[ScreenHeartEntry]
|
||||
Class="ScreenWithMenuElements"
|
||||
Fallback="ScreenWithMenuElements"
|
||||
PrevScreen=Branch.AfterHeartEntry()
|
||||
NextScreen=Branch.AfterHeartEntry()
|
||||
HeartEntryEnabled=false
|
||||
PlayMusic=false
|
||||
ShowHeader=false
|
||||
ShowFooter=false
|
||||
ShowCreditDisplay=false
|
||||
TimerSeconds=-1
|
||||
TimerOnCommand=visible,false
|
||||
|
||||
[ScreenEvaluation]
|
||||
Class="ScreenEvaluation"
|
||||
Fallback="ScreenWithMenuElements"
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
-- The positions of the numbers on the numpad.
|
||||
local numpad_poses= {
|
||||
{-24, -24}, {0, -24}, {24, -24},
|
||||
{-24, 0}, {0, 0}, {24, 0},
|
||||
{-24, 24}, {0, 24}, {24, 24},
|
||||
{-24, 48}, {0, 48}, {24, 48}}
|
||||
-- Some special escape sequences are converted to special characters.
|
||||
local done_text= "&start;"
|
||||
local back_text= "←"
|
||||
local numpad_nums= {7, 8, 9, 4, 5, 6, 1, 2, 3, 0, done_text, back_text}
|
||||
if MonthOfYear() == 3 and DayOfMonth() == 1 then
|
||||
for i= 1, #numpad_nums do
|
||||
local a= math.random(1, #numpad_nums)
|
||||
local b= math.random(1, #numpad_nums)
|
||||
numpad_nums[a], numpad_nums[b]= numpad_nums[b], numpad_nums[a]
|
||||
end
|
||||
end
|
||||
|
||||
-- Each of these will be filled with an entry for each player that is
|
||||
-- entering their heart rate.
|
||||
-- This way, the actors are stored in convenient tables, so we don't have to go
|
||||
-- through an inconvenient and inefficient chain of GetChild calls when we need
|
||||
-- to change one of them.
|
||||
local cursor_poses= {}
|
||||
local cursor_quads= {}
|
||||
local values= {}
|
||||
local value_texts= {}
|
||||
local done_status= {}
|
||||
|
||||
-- This creates the actor that will show the numpad, prompt, and value for a
|
||||
-- player. The PlayerNumber is passed in so that it can add its parts to the
|
||||
-- tables above.
|
||||
local function entry_pad(name, x, y, pn)
|
||||
local args= {
|
||||
Name= name, InitCommand= cmd(xy, x, y),
|
||||
-- The cursor actor. First in the frame so it will be behind the text.
|
||||
Def.Quad{
|
||||
Name= "cursor", InitCommand= function(self)
|
||||
self:setsize(16, 24)
|
||||
self:diffuse(PlayerDarkColor(pn))
|
||||
cursor_quads[pn]= self
|
||||
end
|
||||
},
|
||||
Def.BitmapText{
|
||||
Name= "rate_label", Font= "Common Normal",
|
||||
Text= THEME:GetString("ScreenHeartEntry", "Heart Rate"),
|
||||
InitCommand= cmd(xy, 0, -72; diffuse, Color.White)
|
||||
},
|
||||
Def.BitmapText{
|
||||
Name= "value", Font= "Common Normal", Text= "0",
|
||||
InitCommand= function(self)
|
||||
self:xy(0, -48)
|
||||
self:diffuse(PlayerColor(pn))
|
||||
value_texts[pn]= self
|
||||
end
|
||||
}
|
||||
}
|
||||
-- A loop is used to add each of the numbers on the numpad to shorten the
|
||||
-- code and make it easier to add numbers later.
|
||||
for i, num in ipairs(numpad_nums) do
|
||||
args[#args+1]= Def.BitmapText{
|
||||
Name= "num"..i, Font= "Common Normal", Text= num,
|
||||
InitCommand= cmd(xy, numpad_poses[i][1], numpad_poses[i][2]; diffuse, Color.White)
|
||||
}
|
||||
end
|
||||
return Def.ActorFrame(args)
|
||||
end
|
||||
|
||||
-- A function to update the cursor position for a player.
|
||||
local function update_cursor(pn)
|
||||
local pos= numpad_poses[cursor_poses[pn]]
|
||||
cursor_quads[pn]:stoptweening()
|
||||
cursor_quads[pn]:linear(.1)
|
||||
cursor_quads[pn]:xy(pos[1], pos[2])
|
||||
end
|
||||
|
||||
local function pad_input(pn, button)
|
||||
if button == "Start" then
|
||||
local num= numpad_nums[cursor_poses[pn]]
|
||||
local as_num= tonumber(num)
|
||||
if as_num then
|
||||
local new_value= (values[pn] * 10) + as_num
|
||||
if new_value < 300 then
|
||||
values[pn]= new_value
|
||||
if new_value > 100 then
|
||||
cursor_poses[pn]= 11
|
||||
update_cursor(pn)
|
||||
end
|
||||
value_texts[pn]:settext(values[pn])
|
||||
else
|
||||
SOUND:PlayOnce(THEME:GetPathS("Common", "Invalid"))
|
||||
end
|
||||
return false
|
||||
else
|
||||
if num == done_text then
|
||||
done_status[pn]= true
|
||||
return true
|
||||
elseif num == back_text then
|
||||
values[pn]= math.floor(values[pn]/10)
|
||||
value_texts[pn]:settext(values[pn])
|
||||
return false
|
||||
end
|
||||
end
|
||||
else
|
||||
local adds= {
|
||||
Left= {2, -1, -1},
|
||||
Right= {1, 1, -2},
|
||||
MenuLeft= {-1, -1, -1},
|
||||
MenuRight= {1, 1, 1},
|
||||
Up= {9, -3, -3, -3},
|
||||
Down= {3, 3, 3, -9}
|
||||
}
|
||||
adds.MenuUp= adds.Up
|
||||
adds.MenuDown= adds.Down
|
||||
local lr_buttons= {
|
||||
Left= true, Right= true, MenuLeft= true, MenuRight= true}
|
||||
if adds[button] then
|
||||
local index= 0
|
||||
if lr_buttons[button] then
|
||||
index= ((cursor_poses[pn] - 1) % 3) + 1
|
||||
else
|
||||
index= math.ceil(cursor_poses[pn] / 3)
|
||||
end
|
||||
local new_pos= cursor_poses[pn] + adds[button][index]
|
||||
if new_pos < 1 then new_pos= #numpad_nums end
|
||||
if new_pos > #numpad_nums then new_pos= 1 end
|
||||
cursor_poses[pn]= new_pos
|
||||
update_cursor(pn)
|
||||
return false
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function input(event)
|
||||
local pn= event.PlayerNumber
|
||||
Trace("input recieved")
|
||||
if not pn then return end
|
||||
Trace("has a pn")
|
||||
if event.type == "InputEventType_Release" then return end
|
||||
Trace("not a release")
|
||||
if not cursor_poses[pn] then return end
|
||||
Trace("has a cursor")
|
||||
local done= pad_input(pn, event.button)
|
||||
if done then
|
||||
local all_done= true
|
||||
for i, status in pairs(done_status) do
|
||||
if not status then all_done= false break end
|
||||
end
|
||||
if all_done then
|
||||
for pn, value in pairs(values) do
|
||||
local profile= PROFILEMAN:GetProfile(pn)
|
||||
if profile and profile:GetIgnoreStepCountCalories() then
|
||||
local calories= profile:CalculateCaloriesFromHeartRate(
|
||||
values[pn], GAMESTATE:GetLastGameplayDuration())
|
||||
profile:AddCaloriesToDailyTotal(calories)
|
||||
end
|
||||
end
|
||||
SOUND:PlayOnce(THEME:GetPathS("Common", "Start"))
|
||||
SCREENMAN:GetTopScreen():StartTransitioningScreen("SM_GoToNextScreen")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local heart_xs= {
|
||||
[PLAYER_1]= SCREEN_WIDTH * .25,
|
||||
[PLAYER_2]= SCREEN_WIDTH * .75,
|
||||
}
|
||||
|
||||
local timer_text
|
||||
local function timer_update(self)
|
||||
local time= math.floor((self:GetSecsIntoEffect() % 60) * 10) / 10
|
||||
if time < 10 then
|
||||
timer_text:settext(("0%.1f"):format(time))
|
||||
else
|
||||
timer_text:settext(("%.1f"):format(time))
|
||||
end
|
||||
end
|
||||
|
||||
local args= {
|
||||
Def.ActorFrame{
|
||||
Name= "timer",
|
||||
InitCommand= function(self)
|
||||
self:effectperiod(2^16)
|
||||
timer_text= self:GetChild("timer_text")
|
||||
self:SetUpdateFunction(timer_update)
|
||||
end,
|
||||
OnCommand= function(self)
|
||||
SCREENMAN:GetTopScreen():AddInputCallback(input)
|
||||
end,
|
||||
Def.BitmapText{
|
||||
Name= "timer_text", Font= "Common Normal", Text= "00.0",
|
||||
InitCommand= cmd(xy, SCREEN_CENTER_X, SCREEN_CENTER_Y; diffuse, Color.White)
|
||||
}
|
||||
},
|
||||
Def.BitmapText{
|
||||
Name= "explanation", Font= "Common Normal",
|
||||
Text= THEME:GetString("ScreenHeartEntry", "Enter Heart Rate"),
|
||||
InitCommand= cmd(xy, SCREEN_CENTER_X, SCREEN_CENTER_Y-120; diffuse, Color.White)},
|
||||
Def.BitmapText{
|
||||
Name= "song_len_label", Font= "Common Normal",
|
||||
Text= THEME:GetString("ScreenHeartEntry", "Song Length"),
|
||||
InitCommand= cmd(xy, SCREEN_CENTER_X, SCREEN_CENTER_Y-72; diffuse, Color.White)},
|
||||
Def.BitmapText{
|
||||
Name= "song_len", Font= "Common Normal",
|
||||
Text= SecondsToMMSS(GAMESTATE:GetLastGameplayDuration()),
|
||||
InitCommand= cmd(xy, SCREEN_CENTER_X, SCREEN_CENTER_Y-48; diffuse, Color.White)},
|
||||
}
|
||||
|
||||
for i, pn in ipairs(GAMESTATE:GetEnabledPlayers()) do
|
||||
local profile= PROFILEMAN:GetProfile(pn)
|
||||
if profile and profile:GetIgnoreStepCountCalories() then
|
||||
cursor_poses[pn]= 5
|
||||
values[pn]= 0
|
||||
done_status[pn]= false
|
||||
args[#args+1]= entry_pad(pn, heart_xs[pn], SCREEN_CENTER_Y, pn)
|
||||
end
|
||||
end
|
||||
|
||||
return Def.ActorFrame(args)
|
||||
@@ -85,6 +85,11 @@ HelpText=
|
||||
[ScreenGameplay]
|
||||
HelpText=
|
||||
|
||||
[ScreenHeartEntry]
|
||||
Enter Heart Rate=Enter Heart Rate
|
||||
Song Length=Song Length
|
||||
Heart Rate=Heart Rate
|
||||
|
||||
[ScreenEvaluation]
|
||||
HelpText=&BACK; Exit &START; Move On &MENULEFT;+&MENURIGHT; or &SELECT; Snapshot
|
||||
LifeDifficulty=Life Difficulty: %s
|
||||
|
||||
@@ -1628,6 +1628,9 @@ ActiveAttackListP2OffCommand=
|
||||
|
||||
[ScreenGameplayShared]
|
||||
|
||||
[ScreenHeartEntry]
|
||||
HeartEntryEnabled=true
|
||||
|
||||
[ScreenEvaluation]
|
||||
Class="ScreenEvaluation"
|
||||
Fallback="ScreenWithMenuElements"
|
||||
|
||||
@@ -2406,6 +2406,7 @@ public:
|
||||
p->m_Position.PushSelf(L);
|
||||
return 1;
|
||||
}
|
||||
DEFINE_METHOD( GetLastGameplayDuration, m_DanceDuration )
|
||||
DEFINE_METHOD( GetGameplayLeadIn, m_bGameplayLeadIn )
|
||||
DEFINE_METHOD( GetCoins, m_iCoins )
|
||||
DEFINE_METHOD( IsSideJoined, m_bSideIsJoined[Enum::Check<PlayerNumber>(L, 1)] )
|
||||
@@ -2815,6 +2816,7 @@ public:
|
||||
ADD_METHOD( GetSongFreeze );
|
||||
ADD_METHOD( GetSongDelay );*/
|
||||
ADD_METHOD( GetSongPosition );
|
||||
ADD_METHOD( GetLastGameplayDuration );
|
||||
ADD_METHOD( GetGameplayLeadIn );
|
||||
ADD_METHOD( GetCoins );
|
||||
ADD_METHOD( IsSideJoined );
|
||||
|
||||
@@ -267,6 +267,10 @@ public:
|
||||
float m_fLastHasteUpdateMusicSeconds;
|
||||
float m_fAccumulatedHasteSeconds;
|
||||
|
||||
// used by themes that support heart rate entry.
|
||||
RageTimer m_DanceStartTime;
|
||||
float m_DanceDuration;
|
||||
|
||||
// Random Attacks & Attack Mines
|
||||
vector<RString> m_RandomAttacks;
|
||||
|
||||
|
||||
@@ -2507,6 +2507,8 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
|
||||
else
|
||||
SOUND->PlayOnceFromAnnouncer( "gameplay here we go normal" );
|
||||
|
||||
GAMESTATE->m_DanceStartTime.Touch();
|
||||
|
||||
m_Go.StartTransitioning( SM_None );
|
||||
GAMESTATE->m_bGameplayLeadIn.Set( false );
|
||||
m_DancingState = STATE_DANCING; // STATE CHANGE! Now the user is allowed to press Back
|
||||
@@ -2556,6 +2558,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
|
||||
}
|
||||
else if( SM == SM_LeaveGameplay )
|
||||
{
|
||||
GAMESTATE->m_DanceDuration= GAMESTATE->m_DanceStartTime.Ago();
|
||||
// update dancing characters for win / lose
|
||||
DancingCharacters *pDancers = NULL;
|
||||
if( m_pSongBackground )
|
||||
|
||||
Reference in New Issue
Block a user