From efd11c58512e06b1e12e439f8af203b3a687bf78 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Thu, 18 Sep 2014 17:28:53 -0600 Subject: [PATCH] Added character setting and minor documentation to ScreenOptionsCustomizeProfile. --- .../ScreenOptionsCustomizeProfile overlay.lua | 240 ++++++++++++++-- Themes/_fallback/Languages/en.ini | 1 + Themes/_fallback/Scripts/04 NumPadEntry.lua | 2 +- .../ScreenOptionsCustomizeProfile overlay.lua | 257 ++++++++++++++++-- 4 files changed, 457 insertions(+), 43 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua b/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua index 828b565dfd..28ce4cde7c 100644 --- a/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua @@ -2,8 +2,25 @@ -- Also, this might be rewritten to us a proper customizable lua menu system -- in the future. +-- Copy this file into your theme, then modify as needed to suit your theme. +-- Each of the things on this list has a comment marking it, so you can +-- quickly find it by searching. +-- Things you will want to change: +-- 1. The Numpad +-- 2. The Cursor +-- 3. The Menu Items +-- 4. The Menu Values +-- 4.1 The L/R indicators +-- 5. The Menu Fader + local profile= GAMESTATE:GetEditLocalProfile() +-- 1. The Numpad +-- This is what sets up how the numpad looks. See Scripts/04 NumPadEntry.lua +-- for a full description of how to customize a NumPad. +-- Note that if you provide a custom prompt actor for the NumPad, it must +-- have a SetCommand because the NumPad is used any time the player needs to +-- enter a number, and the prompt is updated by running its SetCommand. local number_entry= new_numpad_entry{ Name= "number_entry", InitCommand= cmd(diffusealpha, 0; xy, _screen.cx*1.5, _screen.cy), @@ -12,6 +29,15 @@ local number_entry= new_numpad_entry{ cursor_color= PlayerDarkColor(PLAYER_1), } +local function calc_list_pos(value, list) + for i, entry in ipairs(list) do + if entry.setting == value then + return i + end + end + return 1 +end + local function item_value_to_text(item, value) if item.item_type == "bool" then if value then @@ -19,10 +45,22 @@ local function item_value_to_text(item, value) else value= THEME:GetString("ScreenOptionsCustomizeProfile", item.false_text) end + elseif item.item_type == "list" then + local pos= calc_list_pos(value, item.list) + return item.list[pos].display_name end return value end +local char_list= {} +do + local all_chars= CHARMAN:GetAllCharacters() + for i, char in ipairs(char_list) do + char_list[#char_list+1]= { + setting= char:GetCharacterID(), display_name= char:GetDisplayName()} + end +end + local menu_items= { {name= "weight", get= "GetWeightPounds", set= "SetWeightPounds", item_type= "number", auto_done= 100}, @@ -35,8 +73,13 @@ local menu_items= { true_text= "use_heart", false_text= "use_steps"}, {name= "gender", get= "GetIsMale", set= "SetIsMale", item_type= "bool", true_text= "male", false_text= "female"}, - {name= "exit", item_type= "exit"} } +if #char_list > 0 then + menu_items[#menu_items+1]= { + name= "character", get= "GetCharacter", set= "SetCharacter", + item_type= "list", list= char_list} +end +menu_items[#menu_items+1]= {name= "exit", item_type= "exit"} local menu_cursor local menu_pos= 1 @@ -44,9 +87,13 @@ local menu_start= 72 local menu_x= 32 local value_x= 300 local fader -local cursor_on_menu= true +local cursor_on_menu= "main" local menu_item_actors= {} local menu_values= {} +local list_pos= 0 +local active_list= {} +local left_showing= false +local right_showing= false local function fade_actor_to(actor, alf) actor:stoptweening() @@ -55,10 +102,36 @@ local function fade_actor_to(actor, alf) end local function update_menu_cursor() - menu_cursor:stoptweening() - menu_cursor:linear(.1) - menu_cursor:y(menu_item_actors[menu_pos]:GetY()) - menu_cursor:SetWidth(menu_item_actors[menu_pos]:GetWidth() + 20) + local item= menu_item_actors[menu_pos] + menu_cursor:playcommand("Move", {item:GetX(), item:GetY()}) + menu_cursor:playcommand("Fit", item) +end + +local function update_list_cursor() + local valactor= menu_values[menu_pos] + valactor:playcommand("Set", {active_list[list_pos].display_name}) + if list_pos > 1 then + if not left_showing then + valactor:playcommand("ShowLeft") + left_showing= true + end + else + if left_showing then + valactor:playcommand("HideLeft") + left_showing= false + end + end + if list_pos < #active_list then + if not right_showing then + valactor:playcommand("ShowRight") + right_showing= true + end + else + if right_showing then + valactor:playcommand("HideRight") + right_showing= false + end + end end local function input(event) @@ -66,25 +139,34 @@ local function input(event) if not pn then return false end if event.type == "InputEventType_Release" then return false end local button= event.GameButton - if cursor_on_menu then + if cursor_on_menu == "main" then if button == "Start" then local item= menu_items[menu_pos] if item.item_type == "bool" then - local value= not Profile[item.get](profile) - menu_values[menu_pos]:settext(item_value_to_text(item, value)) - Profile[item.set](profile, value) + local value= not profile[item.get](profile) + menu_values[menu_pos]:playcommand( + "Set", {item_value_to_text(item, value)}) + profile[item.set](profile, value) elseif item.item_type == "number" then fade_actor_to(fader, .8) fade_actor_to(number_entry.container, 1) - number_entry.value= Profile[item.get](profile) + number_entry.value= profile[item.get](profile) number_entry.value_actor:playcommand("Set", {number_entry.value}) number_entry.auto_done_value= item.auto_done number_entry.max_value= item.max number_entry:update_cursor(number_entry.cursor_start) number_entry.prompt_actor:playcommand( "Set", {THEME:GetString("ScreenOptionsCustomizeProfile", item.name)}) - cursor_on_menu= false + cursor_on_menu= "numpad" + elseif item.item_type == "list" then + cursor_on_menu= "list" + active_list= menu_items[menu_pos].list + list_pos= calc_list_pos( + profile[menu_items[menu_pos].get](profile), active_list) + update_list_cursor() elseif item.item_type == "exit" then + local profile_id= GAMESTATE:GetEditLocalProfileID() + PROFILEMAN:SaveLocalProfile(profile_id) SCREENMAN:GetTopScreen():StartTransitioningScreen("SM_GoToNextScreen") SOUND:PlayOnce(THEME:GetPathS("Common", "Start")) end @@ -97,15 +179,34 @@ local function input(event) update_menu_cursor() end end - else + elseif cursor_on_menu == "numpad" then local done= number_entry:handle_input(button) if done then local item= menu_items[menu_pos] - Profile[item.set](profile, number_entry.value) - menu_values[menu_pos]:settext(item_value_to_text(item, number_entry.value)) + profile[item.set](profile, number_entry.value) + menu_values[menu_pos]:playcommand( + "Set", {item_value_to_text(item, number_entry.value)}) fade_actor_to(fader, 0) fade_actor_to(number_entry.container, 0) - cursor_on_menu= true + cursor_on_menu= "main" + end + elseif cursor_on_menu == "list" then + if button == "MenuLeft" or button == "MenuUp" then + if list_pos > 1 then list_pos= list_pos - 1 end + update_list_cursor() + menu_values[menu_pos]:playcommand("PressLeft") + elseif button == "MenuRight" or button == "MenuDown" then + if list_pos < #active_list then list_pos= list_pos + 1 end + update_list_cursor() + menu_values[menu_pos]:playcommand("PressRight") + elseif button == "Start" then + profile[menu_items[menu_pos].set](profile, active_list[list_pos].setting) + local valactor= menu_values[menu_pos] + left_showing= false + right_showing= false + valactor:playcommand("HideLeft") + valactor:playcommand("HideRight") + cursor_on_menu= "main" end end end @@ -117,6 +218,10 @@ local args= { SCREENMAN:GetTopScreen():AddInputCallback(input) end }, + -- 2. The Cursor + -- This is the cursor on the main portion of the menu. + -- It needs to have Move and Fit commands for when it's moved to a new + -- item on the list. Def.Quad{ Name= "menu_cursor", InitCommand= function(self) menu_cursor= self @@ -125,15 +230,37 @@ local args= { self:diffuse(PlayerColor(PLAYER_1)) self:xy(menu_x - 10, menu_start) end, + -- params contains the position to move to. + -- The -10 to x position is to give a bit of cursor on the left. + MoveCommand= function(self, params) + self:stoptweening() + self:linear(.1) + self:xy(params[1] - 10, params[2]) + end, + -- param is the actor to fit around. + -- The +20 to width is to give a bit of cursor on each side. + FitCommand= function(self, param) + self:SetWidth(param:GetWidth() + 20) + end }, } +-- Note that the "character" item in the menu only shows up if there are +-- characters to choose from. You might want to adjust positioning for that. for i, item in ipairs(menu_items) do local item_y= menu_start + ((i-1) * 24) + -- 3. The Menu Items + -- This creates the actor that will be used to show each item on the menu. args[#args+1]= Def.BitmapText{ Name= "menu_" .. item.name, Font= "Common Normal", Text= THEME:GetString("ScreenOptionsCustomizeProfile", item.name), InitCommand= function(self) + -- Note that the item adds itself to the list menu_item_actors. This + -- is so that when the cursor is moved, the appropriate item can be + -- easily fetched for positioning and sizing the cursor. + -- Note the ActorFrames have a width of 1 unless you set it, so when + -- you change this from an BitmapText to a ActorFrame, you will have + -- to make the FitCommand of your cursor look at the children. menu_item_actors[i]= self self:xy(menu_x, item_y) self:diffuse(Color.White) @@ -141,20 +268,87 @@ for i, item in ipairs(menu_items) do end } if item.get then - local value_text= item_value_to_text(item, Profile[item.get](profile)) - args[#args+1]= Def.BitmapText{ - Name= "value_" .. item.name, Font= "Common Normal", - Text= value_text, + local value_text= item_value_to_text(item, profile[item.get](profile)) + -- 4. The Menu Values + -- Each of the values needs to have a SetCommand so it can be updated + -- when the player changes it. + -- And ActorFrame is used because values for list items need to have + -- left/right indicators for when the player is making a choice. + local value_args= { + Name= "value_" .. item.name, InitCommand= function(self) + -- Note that the ActorFrame is being added to the list menu_values + -- so it can be easily fetched and updated when the value changes. menu_values[i]= self self:xy(value_x, menu_start + ((i-1) * 24)) - self:diffuse(Color.White) - self:horizalign(left) - end + end, + Def.BitmapText{ + Name= "val", Font= "Common Normal", Text= value_text, + InitCommand= function(self) + self:diffuse(Color.White) + self:horizalign(left) + end, + SetCommand= function(self, param) + self:settext(param[1]) + end, + } } + if item.item_type == "list" then + -- 4.1 The L/R indicators + -- The L/R indicators are there to tell the player when there is a + -- choice to the left or right of the choice they are on. + -- Note that they are placed inside the ActorFrame for the value, so + -- when commands are played on the ActorFrame, they are played for the + -- indicators too. + -- The commands are ShowLeft, HideLeft, PressLeft, and the same for + -- Right. + -- Note that the right indicator has a SetCommand so it sees when the + -- value changes and checks the new width to position itself. + -- Show/Hide is only played when the indicator changes state. + -- Command execution order: Set, Show/Hide (if change occurred), Press + value_args[#value_args+1]= Def.ActorMultiVertex{ + InitCommand= function(self) + self:SetVertices{ + {{-5, 0, 0}, Color.White}, {{0, -10, 0}, Color.White}, + {{0, 10, 0}, Color.White}} + self:SetDrawState{Mode= "DrawMode_Triangles"} + self:x(-8) + self:visible(false) + self:playcommand("Set", {value_text}) + end, + ShowLeftCommand= cmd(visible, true), + HideLeftCommand= cmd(visible, false), + PressLeftCommand= cmd(stoptweening; linear, .2; zoom, 2; linear, .2; + zoom, 1), + } + value_args[#value_args+1]= Def.ActorMultiVertex{ + InitCommand= function(self) + self:SetVertices{ + {{5, 0, 0}, Color.White}, {{0, -10, 0}, Color.White}, + {{0, 10, 0}, Color.White}} + self:SetDrawState{Mode= "DrawMode_Triangles"} + self:visible(false) + end, + SetCommand= function(self) + local valw= self:GetParent():GetChild("val"):GetWidth() + self:x(valw+8) + end, + ShowRightCommand= cmd(visible, true), + HideRightCommand= cmd(visible, false), + PressRightCommand= cmd(stoptweening; linear, .2; zoom, 2; linear, .2; + zoom, 1), + } + end + args[#args+1]= Def.ActorFrame(value_args) end end +-- 5. The Menu Fader +-- This is just something to tell the player that the menu is no longer +-- active because they are interacting with the numpad. +-- Default is to just fade this in over the top of the menu. If you want +-- something different, change the places in the input function that call +-- fade_actor_to to do what you want with the fader. args[#args+1]= Def.Quad{ Name= "fader", InitCommand= function(self) fader= self diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 0abdbfa0ef..8215804658 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -1625,6 +1625,7 @@ voomax=VO2Max birth_year=Birth Year gender=Gender calorie_calc=Calorie Calculation +character=Character exit=Exit use_heart=Use Heart Rate use_steps=Use Step Count diff --git a/Themes/_fallback/Scripts/04 NumPadEntry.lua b/Themes/_fallback/Scripts/04 NumPadEntry.lua index c989280eb4..1f52c416d7 100644 --- a/Themes/_fallback/Scripts/04 NumPadEntry.lua +++ b/Themes/_fallback/Scripts/04 NumPadEntry.lua @@ -457,7 +457,7 @@ local numpad_entry_mt= { end if cr_pos[1] > self.columns then cr_pos[1]= 1 - if button == "MenuLeft" then + if button == "MenuRight" then cr_pos[2]= cr_pos[2] + 1 end end diff --git a/Themes/default/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua b/Themes/default/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua index 24d02f4c43..3fa5eba18e 100644 --- a/Themes/default/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua +++ b/Themes/default/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua @@ -2,11 +2,28 @@ -- Also, this might be rewritten to us a proper customizable lua menu system -- in the future. +-- Copy this file into your theme, then modify as needed to suit your theme. +-- Each of the things on this list has a comment marking it, so you can +-- quickly find it by searching. +-- Things you will want to change: +-- 1. The Numpad +-- 2. The Cursor +-- 3. The Menu Items +-- 4. The Menu Values +-- 4.1 The L/R indicators +-- 5. The Menu Fader + local profile= GAMESTATE:GetEditLocalProfile() local cursor_width_padding = 16 local cursor_spacing_value = 30 +-- 1. The Numpad +-- This is what sets up how the numpad looks. See Scripts/04 NumPadEntry.lua +-- for a full description of how to customize a NumPad. +-- Note that if you provide a custom prompt actor for the NumPad, it must +-- have a SetCommand because the NumPad is used any time the player needs to +-- enter a number, and the prompt is updated by running its SetCommand. local number_entry= new_numpad_entry{ Name= "number_entry", InitCommand= cmd(diffusealpha, 0; xy, _screen.cx, _screen.cy * 1.5), @@ -74,6 +91,15 @@ local number_entry= new_numpad_entry{ } } +local function calc_list_pos(value, list) + for i, entry in ipairs(list) do + if entry.setting == value then + return i + end + end + return 1 +end + local function item_value_to_text(item, value) if item.item_type == "bool" then if value then @@ -81,10 +107,61 @@ local function item_value_to_text(item, value) else value= THEME:GetString("ScreenOptionsCustomizeProfile", item.false_text) end + elseif item.item_type == "list" then + local pos= calc_list_pos(value, item.list) + return item.list[pos].display_name end return value end +local char_list= {} +do + local all_chars= CHARMAN:GetAllCharacters() + for i, char in ipairs(char_list) do + char_list[#char_list+1]= { + setting= char:GetCharacterID(), display_name= char:GetDisplayName()} + end +end + +-- Uncomment this section if you need to test the behavior of actors in the +-- character list but don't have any duncing characters to test with. +--[=[ +local fake_profile_mt= {__index= {}} +local val_list= {} +local function get_set_pair(name, default) + fake_profile_mt.__index["Get"..name]= function(self) + return self[name] + end + fake_profile_mt.__index["Set"..name]= function(self, val) + self[name]= val + end + val_list[#val_list+1]= {name, default} +end +get_set_pair("WeightPounds", 0) +get_set_pair("Voomax", 0) +get_set_pair("BirthYear", 0) +get_set_pair("IgnoreStepCountCalories", false) +get_set_pair("IsMale", true) +get_set_pair("Character", "dietlinde") +fake_profile_mt.__index.init= function(self) + for i, vald in ipairs(val_list) do + self[vald[1]]= vald[2] + end +end + +profile= setmetatable({}, fake_profile_mt) +profile:init() + +char_list= { + {setting= "shake", display_name= "soda"}, + {setting= "freem", display_name= "inc"}, + {setting= "midi", display_name= "man"}, + {setting= "kyz", display_name= "zentun"}, + {setting= "mad", display_name= "matt"}, + {setting= "db", display_name= "k2"}, +} +--]=] + local menu_items= { {name= "weight", get= "GetWeightPounds", set= "SetWeightPounds", item_type= "number", auto_done= 100}, @@ -97,18 +174,30 @@ local menu_items= { true_text= "use_heart", false_text= "use_steps"}, {name= "gender", get= "GetIsMale", set= "SetIsMale", item_type= "bool", true_text= "male", false_text= "female"}, - {name= "exit", item_type= "exit"} } +if #char_list > 0 then + menu_items[#menu_items+1]= { + name= "character", get= "GetCharacter", set= "SetCharacter", + item_type= "list", list= char_list} +end +menu_items[#menu_items+1]= {name= "exit", item_type= "exit"} local menu_cursor local menu_pos= 1 local menu_start= SCREEN_TOP + 80 +if #menu_items > 6 then + menu_start= SCREEN_TOP + 68 +end local menu_x= SCREEN_CENTER_X * 0.25 local value_x= ( SCREEN_CENTER_X * 0.25 ) + 256 local fader -local cursor_on_menu= true +local cursor_on_menu= "main" local menu_item_actors= {} local menu_values= {} +local list_pos= 0 +local active_list= {} +local left_showing= false +local right_showing= false local function fade_actor_to(actor, alf) actor:stoptweening() @@ -122,30 +211,66 @@ local function update_menu_cursor() menu_cursor:playcommand("Fit", item) end +local function update_list_cursor() + local valactor= menu_values[menu_pos] + valactor:playcommand("Set", {active_list[list_pos].display_name}) + if list_pos > 1 then + if not left_showing then + valactor:playcommand("ShowLeft") + left_showing= true + end + else + if left_showing then + valactor:playcommand("HideLeft") + left_showing= false + end + end + if list_pos < #active_list then + if not right_showing then + valactor:playcommand("ShowRight") + right_showing= true + end + else + if right_showing then + valactor:playcommand("HideRight") + right_showing= false + end + end +end + local function input(event) local pn= event.PlayerNumber if not pn then return false end if event.type == "InputEventType_Release" then return false end local button= event.GameButton - if cursor_on_menu then + if cursor_on_menu == "main" then if button == "Start" then local item= menu_items[menu_pos] if item.item_type == "bool" then - local value= not Profile[item.get](profile) - menu_values[menu_pos]:settext(item_value_to_text(item, value)) - Profile[item.set](profile, value) + local value= not profile[item.get](profile) + menu_values[menu_pos]:playcommand( + "Set", {item_value_to_text(item, value)}) + profile[item.set](profile, value) elseif item.item_type == "number" then --fade_actor_to(fader, .8) fade_actor_to(number_entry.container, 1) - number_entry.value= Profile[item.get](profile) + number_entry.value= profile[item.get](profile) number_entry.value_actor:playcommand("Set", {number_entry.value}) number_entry.auto_done_value= item.auto_done number_entry.max_value= item.max number_entry:update_cursor(number_entry.cursor_start) number_entry.prompt_actor:playcommand( "Set", {THEME:GetString("ScreenOptionsCustomizeProfile", item.name)}) - cursor_on_menu= false + cursor_on_menu= "numpad" + elseif item.item_type == "list" then + cursor_on_menu= "list" + active_list= menu_items[menu_pos].list + list_pos= calc_list_pos( + profile[menu_items[menu_pos].get](profile), active_list) + update_list_cursor() elseif item.item_type == "exit" then + local profile_id= GAMESTATE:GetEditLocalProfileID() + PROFILEMAN:SaveLocalProfile(profile_id) SCREENMAN:GetTopScreen():StartTransitioningScreen("SM_GoToNextScreen") SOUND:PlayOnce(THEME:GetPathS("Common", "Start")) end @@ -158,15 +283,34 @@ local function input(event) update_menu_cursor() end end - else + elseif cursor_on_menu == "numpad" then local done= number_entry:handle_input(button) if done then local item= menu_items[menu_pos] - Profile[item.set](profile, number_entry.value) - menu_values[menu_pos]:settext(item_value_to_text(item, number_entry.value)) + profile[item.set](profile, number_entry.value) + menu_values[menu_pos]:playcommand( + "Set", {item_value_to_text(item, number_entry.value)}) --fade_actor_to(fader, 0) fade_actor_to(number_entry.container, 0) - cursor_on_menu= true + cursor_on_menu= "main" + end + elseif cursor_on_menu == "list" then + if button == "MenuLeft" or button == "MenuUp" then + if list_pos > 1 then list_pos= list_pos - 1 end + update_list_cursor() + menu_values[menu_pos]:playcommand("PressLeft") + elseif button == "MenuRight" or button == "MenuDown" then + if list_pos < #active_list then list_pos= list_pos + 1 end + update_list_cursor() + menu_values[menu_pos]:playcommand("PressRight") + elseif button == "Start" then + profile[menu_items[menu_pos].set](profile, active_list[list_pos].setting) + local valactor= menu_values[menu_pos] + left_showing= false + right_showing= false + valactor:playcommand("HideLeft") + valactor:playcommand("HideRight") + cursor_on_menu= "main" end end end @@ -178,6 +322,10 @@ local args= { SCREENMAN:GetTopScreen():AddInputCallback(input) end }, + -- 2. The Cursor + -- This is the cursor on the main portion of the menu. + -- It needs to have Move and Fit commands for when it's moved to a new + -- item on the list. Def.ActorFrame { Name= "menu_cursor", InitCommand= function(self) menu_cursor= self @@ -216,12 +364,22 @@ local args= { }, } +-- Note that the "character" item in the menu only shows up if there are +-- characters to choose from. You might want to adjust positioning for that. for i, item in ipairs(menu_items) do local item_y= menu_start + ((i-1) * 24) + -- 3. The Menu Items + -- This creates the actor that will be used to show each item on the menu. args[#args+1]= Def.BitmapText{ Name= "menu_" .. item.name, Font= "Common Normal", Text= THEME:GetString("ScreenOptionsCustomizeProfile", item.name), InitCommand= function(self) + -- Note that the item adds itself to the list menu_item_actors. This + -- is so that when the cursor is moved, the appropriate item can be + -- easily fetched for positioning and sizing the cursor. + -- Note the ActorFrames have a width of 1 unless you set it, so when + -- you change this from an BitmapText to a ActorFrame, you will have + -- to make the FitCommand of your cursor look at the children. menu_item_actors[i]= self self:xy(menu_x, item_y) self:diffuse(Color.White) @@ -229,17 +387,78 @@ for i, item in ipairs(menu_items) do end } if item.get then - local value_text= item_value_to_text(item, Profile[item.get](profile)) - args[#args+1]= Def.BitmapText{ - Name= "value_" .. item.name, Font= "Common Normal", - Text= value_text, + local value_text= item_value_to_text(item, profile[item.get](profile)) + -- 4. The Menu Values + -- Each of the values needs to have a SetCommand so it can be updated + -- when the player changes it. + -- And ActorFrame is used because values for list items need to have + -- left/right indicators for when the player is making a choice. + local value_args= { + Name= "value_" .. item.name, InitCommand= function(self) + -- Note that the ActorFrame is being added to the list menu_values + -- so it can be easily fetched and updated when the value changes. menu_values[i]= self self:xy(value_x, menu_start + ((i-1) * 24)) - self:diffuse(Color.White) - self:horizalign(left) - end + end, + Def.BitmapText{ + Name= "val", Font= "Common Normal", Text= value_text, + InitCommand= function(self) + self:diffuse(Color.White) + self:horizalign(left) + end, + SetCommand= function(self, param) + self:settext(param[1]) + end, + } } + if item.item_type == "list" then + -- 4.1 The L/R indicators + -- The L/R indicators are there to tell the player when there is a + -- choice to the left or right of the choice they are on. + -- Note that they are placed inside the ActorFrame for the value, so + -- when commands are played on the ActorFrame, they are played for the + -- indicators too. + -- The commands are ShowLeft, HideLeft, PressLeft, and the same for + -- Right. + -- Note that the right indicator has a SetCommand so it sees when the + -- value changes and checks the new width to position itself. + -- Show/Hide is only played when the indicator changes state. + -- Command execution order: Set, Show/Hide (if change occurred), Press + value_args[#value_args+1]= Def.ActorMultiVertex{ + InitCommand= function(self) + self:SetVertices{ + {{-5, 0, 0}, Color.White}, {{0, -10, 0}, Color.White}, + {{0, 10, 0}, Color.White}} + self:SetDrawState{Mode= "DrawMode_Triangles"} + self:x(-8) + self:visible(false) + self:playcommand("Set", {value_text}) + end, + ShowLeftCommand= cmd(visible, true), + HideLeftCommand= cmd(visible, false), + PressLeftCommand= cmd(stoptweening; linear, .2; zoom, 2; linear, .2; + zoom, 1), + } + value_args[#value_args+1]= Def.ActorMultiVertex{ + InitCommand= function(self) + self:SetVertices{ + {{5, 0, 0}, Color.White}, {{0, -10, 0}, Color.White}, + {{0, 10, 0}, Color.White}} + self:SetDrawState{Mode= "DrawMode_Triangles"} + self:visible(false) + end, + SetCommand= function(self) + local valw= self:GetParent():GetChild("val"):GetWidth() + self:x(valw+8) + end, + ShowRightCommand= cmd(visible, true), + HideRightCommand= cmd(visible, false), + PressRightCommand= cmd(stoptweening; linear, .2; zoom, 2; linear, .2; + zoom, 1), + } + end + args[#args+1]= Def.ActorFrame(value_args) end end