tldr; bootpage initial implementation, fixes for page management code
added supporting functions for BootPage removed init() from classes, it was stupid to begin with handleButtonInput() and handleKnobInput no longer optional added callback member to SelfTestField placement position value fixes use gfx.Translate instead of explicitly setting off-origin x,y values added MARGIN and PADDING calculations to fields removed unnecessary gfx.BeginPath() calls
This commit is contained in:
parent
868d5b9798
commit
f44ba3743b
|
@ -40,8 +40,8 @@ function ReadGameFileLines(path, mode)
|
|||
end
|
||||
|
||||
---Read a file in the game folder
|
||||
---@param path string
|
||||
---@param mode? openmode default "r"
|
||||
---@param path string # relative path to game file
|
||||
---@param mode? openmode # default "r"
|
||||
---@return nil|string|integer[]
|
||||
function ReadGameFile(path, mode)
|
||||
mode = mode or "r"
|
||||
|
@ -63,9 +63,9 @@ function ReadGameFile(path, mode)
|
|||
end
|
||||
|
||||
---Find patterns in file
|
||||
---@param path string
|
||||
---@param pattern string
|
||||
---@return table {{group1, group2, ...}, ...}
|
||||
---@param path string # relative path to game file
|
||||
---@param pattern string # search pattern
|
||||
---@return table # {{group1, group2, ...}, ...}
|
||||
function FindPatterns(path, pattern)
|
||||
local matches = {}
|
||||
for _, line in ipairs(ReadGameFileLines(path, "r")) do
|
||||
|
@ -76,3 +76,28 @@ function FindPatterns(path, pattern)
|
|||
return matches
|
||||
end
|
||||
|
||||
--- Check if a file or directory exists in this path
|
||||
---@param file string # relative path to game file
|
||||
---@return boolean # file exists
|
||||
---@return string # error message
|
||||
function IsFileExists(file)
|
||||
local gamepath, sep = getGamePath()
|
||||
file = gamepath .. sep .. file
|
||||
|
||||
local ok, err, code = os.rename(file, file)
|
||||
if not ok then
|
||||
if code == 13 then
|
||||
-- Permission denied, but it exists
|
||||
return true
|
||||
end
|
||||
end
|
||||
return ok, err
|
||||
end
|
||||
|
||||
--- Check if a directory exists in this path
|
||||
---@param path string # relative path to game directory
|
||||
---@return boolean # directory exists
|
||||
function IsDir(path)
|
||||
-- "/" works on both Unix and Windows
|
||||
return IsFileExists(path .. "/")
|
||||
end
|
||||
|
|
|
@ -17,15 +17,11 @@ function ContainerField:new(o)
|
|||
|
||||
o.content = o.content or {}
|
||||
|
||||
return Inherit(self, o, Field)
|
||||
end
|
||||
local this = Inherit(self, o, Field)
|
||||
|
||||
---Initialize members
|
||||
---@return ContainerField
|
||||
function ContainerField:init()
|
||||
Field.init(self)
|
||||
self:refreshFields()
|
||||
return self
|
||||
this:refreshFields()
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
---Add content to container
|
||||
|
@ -60,7 +56,7 @@ function ContainerField:render(deltaTime)
|
|||
gfx.Save()
|
||||
|
||||
gfx.Translate(self.posX, self.posY)
|
||||
gfx.Scissor(self.offX, self.offY, self.aabbW, self.aabbH)
|
||||
gfx.Scissor(0, 0, self.aabbW, self.aabbH)
|
||||
|
||||
self:drawBackground(deltaTime)
|
||||
self:drawContent(deltaTime)
|
||||
|
|
|
@ -4,18 +4,10 @@ require("common.class")
|
|||
---@field parent Page|ContainerField
|
||||
---@field posX number
|
||||
---@field posY number
|
||||
---@field offX number
|
||||
---@field offY number
|
||||
---@field aabbW number
|
||||
---@field aabbH number
|
||||
local Field = {
|
||||
__tostring = function() return "Field" end,
|
||||
---@type nil|fun(button: integer): boolean
|
||||
---return true if further button input processing should be stopped, otherwise false
|
||||
handleButtonInput = nil,
|
||||
---@type nil|fun(knob: integer, delta: number): boolean
|
||||
---return true if further knob input processing should be stopped, otherwise false
|
||||
handleKnobInput = nil,
|
||||
}
|
||||
|
||||
---Create a new Field instance
|
||||
|
@ -29,20 +21,12 @@ function Field:new(o)
|
|||
o.parent = o.parent or nil
|
||||
o.posX = o.posX or 0
|
||||
o.posY = o.posY or 0
|
||||
o.offX = o.offX or 0
|
||||
o.offY = o.offY or 0
|
||||
o.aabbW = o.aabbW or 0
|
||||
o.aabbH = o.aabbH or 0
|
||||
|
||||
return Base(self, o)
|
||||
end
|
||||
|
||||
---Initialize members
|
||||
---@return Field
|
||||
function Field:init()
|
||||
return self
|
||||
end
|
||||
|
||||
---Get the containing top-level parent page
|
||||
---@return Field|Page
|
||||
function Field:getParentPage()
|
||||
|
@ -62,8 +46,23 @@ function Field:focus(obj) end
|
|||
---@param obj? any # message object for the field
|
||||
function Field:deactivate(obj) end
|
||||
|
||||
---@param button integer # options are under the `game` table prefixed with `BUTTON`
|
||||
---@return boolean # true if further button input processing should be stopped, otherwise false
|
||||
function Field:handleButtonInput(button)
|
||||
return false
|
||||
end
|
||||
|
||||
---@param knob integer # `0` = Left, `1` = Right
|
||||
---@param delta number # in radians, `-2*pi` to `0` (turning CCW) and `0` to `2*pi` (turning CW)
|
||||
---@return boolean # true if further button input processing should be stopped, otherwise false
|
||||
function Field:handleKnobInput(knob, delta)
|
||||
return false
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function Field:drawContent(deltaTime)
|
||||
-- dummy field content
|
||||
|
||||
gfx.ResetScissor()
|
||||
|
||||
local offX = -50
|
||||
|
@ -104,7 +103,8 @@ function Field:render(deltaTime)
|
|||
gfx.Save()
|
||||
|
||||
gfx.Translate(self.posX, self.posY)
|
||||
gfx.Scissor(self.offX, self.offY, self.aabbW, self.aabbH)
|
||||
gfx.Scissor(0, 0, self.aabbW, self.aabbH)
|
||||
|
||||
self:drawContent(deltaTime)
|
||||
|
||||
gfx.Restore()
|
||||
|
|
|
@ -5,9 +5,6 @@ require("common.class")
|
|||
---@field viewHandler nil|PageView
|
||||
local Page = {
|
||||
__tostring = function() return "Page" end,
|
||||
drawBackground = nil, ---@type nil|fun(deltaTime: number)
|
||||
drawHeader = nil, ---@type nil|fun(deltaTime: number)
|
||||
drawFooter = nil, ---@type nil|fun(deltaTime: number)
|
||||
}
|
||||
|
||||
---Create a new Page instance
|
||||
|
@ -24,12 +21,6 @@ function Page:new(o)
|
|||
return Base(self, o)
|
||||
end
|
||||
|
||||
---Initialize members
|
||||
---@return Page
|
||||
function Page:init()
|
||||
return self
|
||||
end
|
||||
|
||||
---Add field to page
|
||||
---@param field Field
|
||||
function Page:addField(field)
|
||||
|
@ -58,26 +49,23 @@ end
|
|||
function Page:handleKnobInput(knob, delta) end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function Page:render(deltaTime)
|
||||
---background
|
||||
if self.drawBackground then
|
||||
self:drawBackground(deltaTime)
|
||||
end
|
||||
function Page:drawBackground(deltaTime) end
|
||||
|
||||
--render children
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function Page:drawContent(deltaTime)
|
||||
for _, child in ipairs(self.content) do
|
||||
child:render(deltaTime)
|
||||
end
|
||||
end
|
||||
|
||||
---header
|
||||
if self.drawHeader then
|
||||
self:drawHeader(deltaTime)
|
||||
end
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function Page:drawForeground(deltaTime) end
|
||||
|
||||
---footer
|
||||
if self.drawFooter then
|
||||
self:drawFooter(deltaTime)
|
||||
end
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function Page:render(deltaTime)
|
||||
self:drawBackground(deltaTime)
|
||||
self:drawContent(deltaTime)
|
||||
self:drawForeground(deltaTime)
|
||||
end
|
||||
|
||||
return Page
|
||||
|
|
|
@ -24,7 +24,7 @@ local screens = {
|
|||
}
|
||||
}
|
||||
|
||||
local currentScreen = game.GetSkinSetting("animations_skipIntro") and screens.title or screens.service -- show boot screen if skipIntro is not set
|
||||
local currentScreen = game.GetSkinSetting("animations_skipIntro") and screens.title or screens.boot -- show boot screen if skipIntro is not set
|
||||
|
||||
local function deltaKnob(delta)
|
||||
if math.abs(delta) > 1.5 * math.pi then
|
||||
|
|
|
@ -14,8 +14,15 @@ local function render(deltaTime)
|
|||
Dim.transformToScreenSpace()
|
||||
|
||||
pageview:render(deltaTime)
|
||||
|
||||
--pageview will be empty when you `back()` out of the root page
|
||||
if not pageview:get() then
|
||||
return {eventType = "switch", toScreen = "splash"}
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
render = render
|
||||
}
|
||||
local function onButtonPressed(button)
|
||||
pageview:get():handleButtonInput(button)
|
||||
end
|
||||
|
||||
return {render = render, onButtonPressed = onButtonPressed}
|
|
@ -13,35 +13,45 @@ SelfTestStatusEnum = {
|
|||
|
||||
---@class SelfTestField: ServiceField
|
||||
---@field status SelfTestStatusEnum
|
||||
---@field callback nil|fun(obj: any): SelfTestStatusEnum
|
||||
---@field _timer number
|
||||
local SelfTestField = {
|
||||
SELFTEST_COLOR_INPROGRESS = {255, 255, 255, 255},
|
||||
SELFTEST_COLOR_OK = {0, 255, 0, 255},
|
||||
SELFTEST_COLOR_PASS = {255, 255, 0, 255},
|
||||
SELFTEST_COLOR_ERROR = {255, 0, 0, 255},
|
||||
SELFTEST_INPROGRESS_FREQ = 1 / 20 --20Hz
|
||||
SELFTEST_INPROGRESS_FREQ = 1 / 20, --20Hz
|
||||
}
|
||||
|
||||
---Create a new SelfTestField instance
|
||||
---@param o ServiceField
|
||||
---@param o? table
|
||||
---@return SelfTestField
|
||||
function SelfTestField:new(o)
|
||||
o = o or {}
|
||||
|
||||
o.status = o.status or SelfTestStatusEnum.IDLE
|
||||
o.callback = o.callback or nil
|
||||
o._timer = 0
|
||||
|
||||
return Inherit(self, o, ServiceField)
|
||||
end
|
||||
|
||||
function SelfTestField:activate(obj)
|
||||
if self.callback then
|
||||
self.status = self.callback(obj) or SelfTestStatusEnum.INPROGRESS
|
||||
end
|
||||
end
|
||||
|
||||
function SelfTestField:drawValue(deltaTime)
|
||||
gfx.Translate(self.VALUE_OFFSETX, 0)
|
||||
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT | gfx.TEXT_ALIGN_TOP)
|
||||
gfx.FillColor(table.unpack(self.SERVICE_DEFAULT_FONT_COLOR))
|
||||
gfx.Text(":", self.valueOffX, 0)
|
||||
gfx.FillColor(table.unpack(self.FONT_COLOR))
|
||||
gfx.Text(": ", 0, 0)
|
||||
|
||||
local color, text
|
||||
if self.status == SelfTestStatusEnum.IDLE then
|
||||
color = self.SERVICE_DEFAULT_FONT_COLOR
|
||||
color = self.FONT_COLOR
|
||||
text = ""
|
||||
elseif self.status == SelfTestStatusEnum.INPROGRESS then
|
||||
self._timer = self._timer + deltaTime
|
||||
|
@ -58,9 +68,10 @@ function SelfTestField:drawValue(deltaTime)
|
|||
color = self.SELFTEST_COLOR_ERROR
|
||||
text = "ERROR"
|
||||
end
|
||||
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT | gfx.TEXT_ALIGN_TOP)
|
||||
gfx.FillColor(table.unpack(color))
|
||||
gfx.Text(text, self.valueOffX, 0)
|
||||
gfx.Text(text, 0, 0)
|
||||
end
|
||||
|
||||
return SelfTestField
|
|
@ -6,7 +6,7 @@ local ServiceField = require("titlescreen.fields.service.servicefield")
|
|||
local ColorGradientField = {
|
||||
__tostring = function() return "ColorGradientField" end,
|
||||
GRADIENT_X_OFFSET = 128,
|
||||
GRADIENT_WIDTH = 512,
|
||||
GRADIENT_WIDTH = 576,
|
||||
GRADIENT_STEPS = 32
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@ function ColorGradientField:new(o)
|
|||
o = o or {}
|
||||
|
||||
o.value = o.value or {0, 0, 0, 255}
|
||||
o.aabbH = o.aabbH or self.FONT_SIZE
|
||||
|
||||
return Inherit(self, o, ServiceField)
|
||||
end
|
||||
|
|
|
@ -29,13 +29,15 @@ function InputButtonField:deactivate(obj) end
|
|||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function InputButtonField:drawValue(deltaTime)
|
||||
gfx.Translate(self.VALUE_OFFSETX, 0)
|
||||
|
||||
if not self.button then
|
||||
gfx.Text("<BUTTON NOT SET>", self.valueOffX, 0)
|
||||
gfx.Text("<BUTTON NOT SET>", 0, 0)
|
||||
return
|
||||
end
|
||||
|
||||
self.value = game.GetButton(self.button) and "ON" or "OFF"
|
||||
gfx.Text(self.value, self.valueOffX, 0)
|
||||
gfx.Text(self.value, 0, 0)
|
||||
end
|
||||
|
||||
return InputButtonField
|
||||
|
|
|
@ -6,7 +6,7 @@ local ServiceField = require("titlescreen.fields.service.servicefield")
|
|||
---@field knob integer
|
||||
local InputKnobField = {
|
||||
__tostring = function() return "InputKnobField" end,
|
||||
SLIDER_SIZE = {256, ServiceField.FONT_SIZE}, --{w, h}
|
||||
SLIDER_SIZE = {200, 16}, --{w, h}
|
||||
SLIDER_BGCOLOR = {255, 0, 0, 255},
|
||||
SLIDER_FRAME_COLOR = ServiceField.FONT_COLOR,
|
||||
SLIDER_FRAME_WIDTH = 1,
|
||||
|
@ -37,13 +37,14 @@ function InputKnobField:deactivate(obj) end
|
|||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function InputKnobField:drawValue(deltaTime)
|
||||
gfx.Translate(self.VALUE_OFFSETX, 0)
|
||||
|
||||
if not self.knob then
|
||||
gfx.Text("<KNOB NOT SET>", self.valueOffX, 0)
|
||||
gfx.Text("<KNOB NOT SET>", 0, 0)
|
||||
return
|
||||
end
|
||||
|
||||
local knobAngle = game.GetKnob(self.knob)
|
||||
local sliderPosX = self.valueOffX + self.SLIDER_OFFSETX
|
||||
local sliderWidth = self.SLIDER_SIZE[1]
|
||||
local sliderHeight = self.SLIDER_SIZE[2]
|
||||
local sliderBgColor = self.SLIDER_BGCOLOR
|
||||
|
@ -54,19 +55,19 @@ function InputKnobField:drawValue(deltaTime)
|
|||
self.value = math.floor(Util.lerp(knobAngle,0, 0, 2 * math.pi, maxValue)) % maxValue
|
||||
|
||||
--draw value
|
||||
gfx.BeginPath()
|
||||
gfx.Text(self.value, self.valueOffX, 0)
|
||||
gfx.Text(self.value, 0, 0)
|
||||
|
||||
--draw slider
|
||||
gfx.Translate(self.SLIDER_OFFSETX, 0)
|
||||
gfx.BeginPath()
|
||||
gfx.Rect(sliderPosX, 0, sliderWidth, sliderHeight)
|
||||
gfx.Rect(0, 0, sliderWidth, sliderHeight)
|
||||
gfx.FillColor(table.unpack(sliderBgColor))
|
||||
gfx.StrokeColor(table.unpack(sliderFrameColor))
|
||||
gfx.StrokeWidth(sliderFrameWidth)
|
||||
gfx.Fill()
|
||||
gfx.Stroke()
|
||||
|
||||
local sliderIndicatorX = Util.lerp(self.value, 0, sliderPosX, maxValue, sliderWidth)
|
||||
local sliderIndicatorX = Util.lerp(self.value, 0, 0, maxValue, sliderWidth)
|
||||
local sliderIndicatorWidth = self.SLIDER_INDICATOR_WIDTH
|
||||
local sliderIndicatorColor = self.SLIDER_INDICATOR_COLOR
|
||||
--draw indicator
|
||||
|
@ -74,7 +75,6 @@ function InputKnobField:drawValue(deltaTime)
|
|||
gfx.Rect(sliderIndicatorX, sliderFrameWidth, sliderIndicatorWidth, sliderHeight - 2 * sliderFrameWidth)
|
||||
gfx.FillColor(table.unpack(sliderIndicatorColor))
|
||||
gfx.Fill()
|
||||
|
||||
end
|
||||
|
||||
return InputKnobField
|
||||
|
|
|
@ -4,8 +4,11 @@ local ServiceField = require("titlescreen.fields.service.servicefield")
|
|||
|
||||
---@class ListField: ContainerField, ServiceField
|
||||
---@field selectedIndex integer
|
||||
---@field locked boolean
|
||||
---@field PADDING number[]
|
||||
local ListField = {
|
||||
__tostring = function() return "ListField" end,
|
||||
MARGIN = {0, 0, 0, 0}, --{left, top, right, bottom}
|
||||
PADDING = {0, 0, 0, 0}, --{left, top, right, bottom}
|
||||
}
|
||||
|
||||
|
@ -17,20 +20,16 @@ function ListField:new(o)
|
|||
|
||||
--set instance members
|
||||
o.selectedIndex = o.selectedIndex or 1
|
||||
o.locked = o.locked or false
|
||||
|
||||
return Inherit(self, o, ContainerField, ServiceField)
|
||||
end
|
||||
local this = Inherit(self, o, ContainerField, ServiceField)
|
||||
|
||||
---Initialize members
|
||||
---@return ListField
|
||||
function ListField:init()
|
||||
ServiceField.init(self)
|
||||
ContainerField.init(self)
|
||||
local minW = self.MARGIN[1] + self.PADDING[1] + self.PADDING[3] + self.MARGIN[3]
|
||||
local minH = self.MARGIN[2] + self.PADDING[2] + self.PADDING[4] + self.MARGIN[4]
|
||||
self.aabbW = math.max(self.aabbW, minW)
|
||||
self.aabbH = math.max(self.aabbH, minH)
|
||||
return self
|
||||
local minW = this.MARGIN[1] + this.PADDING[1] + this.PADDING[3] + this.MARGIN[3]
|
||||
local minH = this.MARGIN[2] + this.PADDING[2] + this.PADDING[4] + this.MARGIN[4]
|
||||
this.aabbW = math.max(this.aabbW, minW)
|
||||
this.aabbH = math.max(this.aabbH, minH)
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
---@param obj? any # message object for the field
|
||||
|
@ -66,10 +65,6 @@ end
|
|||
---Add field to list container
|
||||
---@param field Field
|
||||
function ListField:addField(field)
|
||||
--place field to correct position
|
||||
field.posX = self.PADDING[1]
|
||||
field.posY = self.aabbH - self.PADDING[4]
|
||||
|
||||
--update size
|
||||
self.aabbH = self.aabbH + field.aabbH
|
||||
local fieldAabbW = self.PADDING[1] + field.aabbW + self.PADDING[3]
|
||||
|
@ -83,14 +78,8 @@ end
|
|||
|
||||
---Refresh content parameters
|
||||
function ListField:refreshFields()
|
||||
local posY = self.PADDING[1]
|
||||
local aabbH = self.MARGIN[2] + self.PADDING[2] + self.PADDING[4] + self.MARGIN[4]
|
||||
for _, child in ipairs(self.content) do
|
||||
--place field to correct position
|
||||
child.posX = self.PADDING[1]
|
||||
child.posY = posY
|
||||
posY = posY + child.aabbH
|
||||
|
||||
--update size
|
||||
aabbH = aabbH + child.aabbH
|
||||
local fieldAabbW = self.PADDING[1] + child.aabbW + self.PADDING[3]
|
||||
|
@ -107,20 +96,25 @@ end
|
|||
---@return boolean # true if further button input processing should be stopped, otherwise false
|
||||
function ListField:handleButtonInput(button)
|
||||
local field = self.content[self.selectedIndex]
|
||||
if field and field.handleButtonInput then
|
||||
if field:handleButtonInput(button) then
|
||||
return true
|
||||
end
|
||||
if field:handleButtonInput(button) then
|
||||
return true
|
||||
end
|
||||
|
||||
local direction = 0
|
||||
|
||||
if button == game.BUTTON_BCK then
|
||||
local viewHandler = self:getParentPage().viewHandler
|
||||
if viewHandler then
|
||||
viewHandler:back()
|
||||
end
|
||||
elseif button == game.BUTTON_BTA then
|
||||
return true
|
||||
end
|
||||
|
||||
if self.locked then
|
||||
return true
|
||||
end
|
||||
|
||||
local direction = 0
|
||||
|
||||
if button == game.BUTTON_BTA then
|
||||
direction = -1
|
||||
elseif button == game.BUTTON_BTB then
|
||||
direction = 1
|
||||
|
@ -142,4 +136,13 @@ function ListField:handleButtonInput(button)
|
|||
return true
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ListField:drawContent(deltaTime)
|
||||
gfx.Translate(self.PADDING[1] + self.MARGIN[1], self.PADDING[2] + self.MARGIN[2])
|
||||
for _, child in ipairs(self.content) do
|
||||
child:render(deltaTime)
|
||||
gfx.Translate(0, child.aabbH)
|
||||
end
|
||||
end
|
||||
|
||||
return ListField
|
||||
|
|
|
@ -12,17 +12,24 @@ ServiceFieldState = {
|
|||
---@class ServiceField: Field
|
||||
---@field label string
|
||||
---@field value any
|
||||
---@field valueOffX number
|
||||
---@field footer string|string[]
|
||||
---@field _state ServiceFieldState
|
||||
---@field FONT_SIZE number
|
||||
---@field FONT_FACE string
|
||||
---@field FONT_COLOR integer[] # {r, g, b, a}
|
||||
---@field FONT_ACTIVE_COLOR integer[] # {r, g, b, a}
|
||||
---@field FONT_FOCUSED_COLOR integer[] # {r, g, b, a}
|
||||
---@field MARGIN number[] # {left, top, right, bottom}
|
||||
---@field VALUE_OFFSETX number
|
||||
local ServiceField = {
|
||||
__tostring = function() return "ServiceField" end,
|
||||
FONT_SIZE = 24,
|
||||
FONT_FACE = "dfmarugoth.ttf",
|
||||
FONT_COLOR = {255, 255, 255, 255}, --{r, g, b, a}
|
||||
FONT_COLOR = {255, 255, 255, 255},
|
||||
FONT_ACTIVE_COLOR = {0, 255, 0, 255},
|
||||
FONT_FOCUSED_COLOR = {255, 0, 0, 255},
|
||||
MARGIN = {0, 0, 0, 4}, --{left, top, right, bottom}
|
||||
MARGIN = {0, 0, 0, 0},
|
||||
VALUE_OFFSETX = 500
|
||||
}
|
||||
|
||||
---Create a new ServiceField instance
|
||||
|
@ -31,14 +38,10 @@ local ServiceField = {
|
|||
function ServiceField:new(o)
|
||||
o = o or {}
|
||||
|
||||
local h = self.FONT_SIZE +
|
||||
self.MARGIN[2] +
|
||||
self.MARGIN[4]
|
||||
local h = self.FONT_SIZE + self.MARGIN[2] + self.MARGIN[4]
|
||||
|
||||
o.aabbH = o.aabbH or h
|
||||
o.aabbW = o.aabbW or Dim.design.width - 128 --:shrug:
|
||||
|
||||
o.valueOffX = o.valueOffX or Dim.design.width / 2
|
||||
o.aabbW = o.aabbW or Dim.design.width --:shrug:
|
||||
|
||||
o.label = o.label or "<UNDEFINED>"
|
||||
o.value = o.value or nil
|
||||
|
@ -46,25 +49,31 @@ function ServiceField:new(o)
|
|||
|
||||
o._state = ServiceFieldState.INACTIVE
|
||||
|
||||
return Inherit(self, o, Field)
|
||||
local this = Inherit(self, o, Field)
|
||||
|
||||
if this.aabbH < h then
|
||||
this.aabbH = h
|
||||
end
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
---@param obj? any message object for the field
|
||||
---@param obj? any # message object for the field
|
||||
function ServiceField:activate(obj)
|
||||
self._state = ServiceFieldState.ACTIVE
|
||||
end
|
||||
|
||||
---@param obj? any message object for the field
|
||||
---@param obj? any # message object for the field
|
||||
function ServiceField:focus(obj)
|
||||
self._state = ServiceFieldState.FOCUSED
|
||||
end
|
||||
|
||||
---@param obj? any message object for the field
|
||||
---@param obj? any # message object for the field
|
||||
function ServiceField:deactivate(obj)
|
||||
self._state = ServiceFieldState.INACTIVE
|
||||
end
|
||||
|
||||
---@param deltaTime number frametime in seconds
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServiceField:drawLabel(deltaTime)
|
||||
local color
|
||||
if self._state == ServiceFieldState.FOCUSED then
|
||||
|
@ -80,7 +89,7 @@ function ServiceField:drawLabel(deltaTime)
|
|||
gfx.Text(self.label, 0, 0)
|
||||
end
|
||||
|
||||
---@param deltaTime number frametime in seconds
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServiceField:drawValue(deltaTime)
|
||||
local text
|
||||
if type(self.value) == "string" then
|
||||
|
@ -89,15 +98,18 @@ function ServiceField:drawValue(deltaTime)
|
|||
text = "N/A"
|
||||
end
|
||||
|
||||
gfx.Translate(self.VALUE_OFFSETX, 0)
|
||||
gfx.FontSize(self.FONT_SIZE)
|
||||
gfx.LoadSkinFont(self.FONT_FACE)
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT | gfx.TEXT_ALIGN_TOP)
|
||||
gfx.FillColor(table.unpack(self.FONT_COLOR))
|
||||
gfx.Text(text, self.valueOffX, 0)
|
||||
gfx.Text(text, 0, 0)
|
||||
end
|
||||
|
||||
---@param deltaTime number frametime in seconds
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServiceField:drawContent(deltaTime)
|
||||
gfx.Translate(self.MARGIN[1], self.MARGIN[2])
|
||||
|
||||
self:drawLabel(deltaTime)
|
||||
self:drawValue(deltaTime)
|
||||
end
|
||||
|
|
|
@ -19,4 +19,8 @@ end
|
|||
---@param deltaTime number # frametime in seconds
|
||||
function ServiceLinkField:drawValue(deltaTime) end
|
||||
|
||||
function ServiceLinkField:handleButtonInput(button)
|
||||
return LinkField.handleButtonInput(self, button)
|
||||
end
|
||||
|
||||
return ServiceLinkField
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
require("common.class")
|
||||
local ServiceField = require("titlescreen.fields.service.servicefield")
|
||||
|
||||
---@class SpacerField: ServiceField
|
||||
local SpacerField = {}
|
||||
|
||||
---Create a new ServiceField instance
|
||||
---@param o? table # initial parameters
|
||||
---@return SpacerField
|
||||
function SpacerField:new(o)
|
||||
return Inherit(self, o, ServiceField)
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function SpacerField:drawContent(deltaTime)
|
||||
--empty, what did you think would be here?
|
||||
end
|
||||
|
||||
return SpacerField
|
|
@ -23,6 +23,15 @@ function UpdateField:new(o)
|
|||
return Inherit(self, o, ServiceField)
|
||||
end
|
||||
|
||||
---@param obj? any # message object for the field
|
||||
function UpdateField:activate(obj) end
|
||||
|
||||
---@param obj? any # message object for the field
|
||||
function UpdateField:focus(obj) end
|
||||
|
||||
---@param obj? any # message object for the field
|
||||
function UpdateField:deactivate(obj) end
|
||||
|
||||
---@param button integer # options are under the `game` table prefixed with `BUTTON`
|
||||
---@return boolean # true if further button input processing should be stopped, otherwise false
|
||||
function UpdateField:handleButtonInput(button)
|
||||
|
@ -41,7 +50,8 @@ function UpdateField:drawValue(deltaTime)
|
|||
self._timer = self._timer + deltaTime
|
||||
local url, version = game.UpdateAvailable()
|
||||
|
||||
gfx.BeginPath()
|
||||
gfx.Translate(self.VALUE_OFFSETX, 0)
|
||||
|
||||
gfx.FontSize(self.FONT_SIZE)
|
||||
gfx.LoadSkinFont(self.FONT_FACE)
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT | gfx.TEXT_ALIGN_TOP)
|
||||
|
@ -51,12 +61,11 @@ function UpdateField:drawValue(deltaTime)
|
|||
else
|
||||
gfx.FillColor(table.unpack(self.UPDATE_FLICKER_COLORS[2]))
|
||||
end
|
||||
gfx.Text("*UPDATE AVAILABLE (" .. version .. ")*", self.valueOffX, 0)
|
||||
gfx.Text("*UPDATE AVAILABLE (" .. version .. ")*", 0, 0)
|
||||
else
|
||||
gfx.FillColor(table.unpack(self.FONT_COLOR))
|
||||
gfx.Text(self.value or "<VERSION STRING NOT AVAILABLE>", self.valueOffX, 0)
|
||||
gfx.Text(self.value or "<VERSION STRING NOT AVAILABLE>", 0, 0)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return UpdateField
|
||||
|
|
|
@ -1,9 +1,35 @@
|
|||
require("common.class")
|
||||
require("common.filereader")
|
||||
local Dim = require("common.dimensions")
|
||||
local Version = require("common.version")
|
||||
local Page = require("components.pager.page")
|
||||
local ServiceField = require("titlescreen.fields.service.servicefield")
|
||||
local LinkField = require("components.pager.linkfield")
|
||||
local ListField = require("titlescreen.fields.service.listfield")
|
||||
local SelfTestField = require("titlescreen.fields.boot.selftestfield")
|
||||
|
||||
local function checkSkinConfig(obj)
|
||||
local crewpath = "textures/crew/anim/" .. game.GetSkinSetting("single_idol")
|
||||
if not IsDir(crewpath) then
|
||||
return SelfTestStatusEnum.ERROR
|
||||
end
|
||||
end
|
||||
|
||||
local networkStatus = SelfTestStatusEnum.IDLE
|
||||
local function irHeardbeat(res)
|
||||
if res.statusCode == IRData.States.Success then
|
||||
networkStatus = SelfTestStatusEnum.OK
|
||||
else
|
||||
networkStatus = SelfTestStatusEnum.ERROR
|
||||
end
|
||||
end
|
||||
|
||||
local function checkNetwork(obj)
|
||||
if not IRData.Active then
|
||||
return SelfTestStatusEnum.PASS
|
||||
end
|
||||
|
||||
IR.Heartbeat(irHeardbeat)
|
||||
end
|
||||
|
||||
---@class BootPage: Page
|
||||
local BootPage = {
|
||||
|
@ -16,27 +42,19 @@ local BootPage = {
|
|||
function BootPage:new(o)
|
||||
o = o or {}
|
||||
|
||||
return Inherit(self, o, Page)
|
||||
end
|
||||
local this = Inherit(self, o, Page)
|
||||
|
||||
---Initialize members
|
||||
---@return BootPage
|
||||
function BootPage:init()
|
||||
self:addField(ServiceField:new{
|
||||
label = Version.getLongVersion(),
|
||||
value = "",
|
||||
posX = 32,
|
||||
posY = 32
|
||||
})
|
||||
this:addField(ServiceField:new{posX = 32, posY = 32, label = Version.getLongVersion(), value = ""})
|
||||
this:addField(ServiceField:new{posX = 64, posY = 64, label = "UNNAMED SDVX CLONE STARTUP...", value = ""})
|
||||
|
||||
self:addField(ServiceField:new{
|
||||
label = "UNNAMED SDVX CLONE STARTUP...",
|
||||
value = "",
|
||||
posX = 64,
|
||||
posY = 64
|
||||
})
|
||||
local valueOffX = 220
|
||||
local list = ListField:new{posX = 64, posY = 96}
|
||||
list:addField(SelfTestField:new{label = "MAIN I/O", VALUE_OFFSETX = valueOffX, status = SelfTestStatusEnum.OK})
|
||||
list:addField(SelfTestField:new{label = "SKIN CONFIG", VALUE_OFFSETX = valueOffX, status = SelfTestStatusEnum.OK, callback = checkSkinConfig})
|
||||
list:addField(SelfTestField:new{label = "IR NETWORK", VALUE_OFFSETX = valueOffX, status = SelfTestStatusEnum.ERROR, callback = checkNetwork})
|
||||
this:addField(list)
|
||||
|
||||
return self
|
||||
return this
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
|
@ -47,4 +65,12 @@ function BootPage:drawBackground(deltaTime)
|
|||
gfx.Fill()
|
||||
end
|
||||
|
||||
function BootPage:render(deltaTime)
|
||||
Page.render(self, deltaTime)
|
||||
|
||||
local skinconfig = self.content[3].content[2] --this is hacktastic
|
||||
|
||||
local network = self.content[3].content[3] --this is also hacktastic
|
||||
end
|
||||
|
||||
return BootPage
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require("common.class")
|
||||
local ServiceField = require("titlescreen.fields.service.servicefield")
|
||||
local ServicePage = require("titlescreen.pages.service.servicepage")
|
||||
local ListField = require("titlescreen.fields.service.listfield")
|
||||
local ColorGradientField = require("titlescreen.fields.service.colorgradientfield")
|
||||
|
@ -8,7 +7,9 @@ local ColorGradientField = require("titlescreen.fields.service.colorgradientfiel
|
|||
local ColorCheckPage = {
|
||||
__tostring = function() return "ColorCheckPage" end,
|
||||
|
||||
GRADIENT_SPACING = ServiceField.FONT_SIZE + 8,
|
||||
PADDING = {56, 120, 0, 56}, --{left, top, right, bottom}
|
||||
|
||||
GRADIENT_SPACING = 32,
|
||||
SEPARATOR_LINE_COLOR = {255, 255, 255, 255},
|
||||
SEPARATOR_LINE_WIDTH = 4,
|
||||
|
||||
|
@ -29,25 +30,23 @@ function ColorCheckPage:new(o)
|
|||
"BACK BUTTON = EXIT"
|
||||
}
|
||||
|
||||
return Inherit(self, o, ServicePage)
|
||||
end
|
||||
|
||||
---Initialize members
|
||||
---@return ColorCheckPage
|
||||
function ColorCheckPage:init()
|
||||
ServicePage.init(self)
|
||||
local this = Inherit(self, o, ServicePage)
|
||||
|
||||
local height = self.GRADIENT_SPACING
|
||||
local list = ListField:new()
|
||||
list:addField(ColorGradientField:new{label = "RED", value = {255, 0, 0, 255}, aabbH = height})
|
||||
list:addField(ColorGradientField:new{label = "YELLOW", value = {255, 255, 0, 255}, aabbH = height})
|
||||
list:addField(ColorGradientField:new{label = "GREEN", value = {0, 255, 0, 255}, aabbH = height})
|
||||
list:addField(ColorGradientField:new{label = "CYAN", value = {0, 255, 255, 255}, aabbH = height})
|
||||
list:addField(ColorGradientField:new{label = "BLUE", value = {0, 0, 255, 255}, aabbH = height})
|
||||
list:addField(ColorGradientField:new{label = "MAGENTA", value = {255, 0, 255, 255}, aabbH = height})
|
||||
list:addField(ColorGradientField:new{label = "WHITE", value = {255, 255, 255, 255}, aabbH = height})
|
||||
list:refreshFields()
|
||||
|
||||
self:addField(ColorGradientField:new{label = "RED", value = {255, 0, 0, 255}, aabbH = height})
|
||||
self:addField(ColorGradientField:new{label = "YELLOW", value = {255, 255, 0, 255}, aabbH = height})
|
||||
self:addField(ColorGradientField:new{label = "GREEN", value = {0, 255, 0, 255}, aabbH = height})
|
||||
self:addField(ColorGradientField:new{label = "CYAN", value = {0, 255, 255, 255}, aabbH = height})
|
||||
self:addField(ColorGradientField:new{label = "BLUE", value = {0, 0, 255, 255}, aabbH = height})
|
||||
self:addField(ColorGradientField:new{label = "MAGENTA", value = {255, 0, 255, 255}, aabbH = height})
|
||||
self:addField(ColorGradientField:new{label = "WHITE", value = {255, 255, 255, 255}, aabbH = height})
|
||||
this:addField(list)
|
||||
this:refreshFields()
|
||||
|
||||
return self
|
||||
return this
|
||||
end
|
||||
|
||||
---@param button integer # options are under the `game` table prefixed with `BUTTON`
|
||||
|
@ -73,7 +72,7 @@ function ColorCheckPage:_drawArrows(deltaTime)
|
|||
local stepW = ColorGradientField.GRADIENT_WIDTH / ColorGradientField.GRADIENT_STEPS
|
||||
gfx.BeginPath()
|
||||
for i = 0, 3 do
|
||||
local posX = i * stepW
|
||||
local posX = ColorGradientField.GRADIENT_X_OFFSET + i * stepW
|
||||
gfx.MoveTo(posX + self.SEPARATOR_ARROW_MARGIN, self.SEPARATOR_ARROW_SIZE - self.SEPARATOR_ARROW_MARGIN)
|
||||
gfx.LineTo(posX + stepW / 2, self.SEPARATOR_ARROW_MARGIN)
|
||||
gfx.LineTo(posX + stepW - self.SEPARATOR_ARROW_MARGIN, self.SEPARATOR_ARROW_SIZE - self.SEPARATOR_ARROW_MARGIN)
|
||||
|
@ -97,14 +96,17 @@ end
|
|||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ColorCheckPage:drawBackground(deltaTime)
|
||||
ServicePage.drawBackground(self, deltaTime)
|
||||
gfx.Save()
|
||||
gfx.Translate(self.PADDING[1], self.PADDING[2])
|
||||
|
||||
gfx.Translate(ServicePage.PADDING[1], self.PADDING[2] + #self.content * self.GRADIENT_SPACING)
|
||||
local list = self.content[1]
|
||||
local posX = list.posX
|
||||
local posY = list.posY + list.aabbH
|
||||
gfx.Translate(posX, posY)
|
||||
self:_drawSeparator(deltaTime)
|
||||
|
||||
gfx.Translate(0, self.SEPARATOR_LINE_WIDTH)
|
||||
self:_drawArrows(deltaTime)
|
||||
|
||||
gfx.Translate(0, self.SEPARATOR_ARROW_SIZE)
|
||||
self:_drawArrowText(deltaTime)
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ require("common.class")
|
|||
local ServicePage = require("titlescreen.pages.service.servicepage")
|
||||
local InputButtonField = require("titlescreen.fields.service.inputbuttonfield")
|
||||
local InputKnobField = require("titlescreen.fields.service.inputknobfield")
|
||||
local ListField = require("titlescreen.fields.service.listfield")
|
||||
|
||||
---@class InputCheckPage: ServicePage
|
||||
local InputCheckPage = {
|
||||
|
@ -17,23 +18,24 @@ function InputCheckPage:new(o)
|
|||
o.title = o.title or "INPUT CHECK"
|
||||
o.footer = o.footer or "BACK BUTTON = EXIT"
|
||||
|
||||
return Inherit(self, o, ServicePage)
|
||||
end
|
||||
local this = Inherit(self, o, ServicePage)
|
||||
|
||||
---Initialize members
|
||||
---@return InputCheckPage
|
||||
function InputCheckPage:init()
|
||||
ServicePage.init(self)
|
||||
self:addField(InputButtonField:new{label="START BUTTON", button=game.BUTTON_STA})
|
||||
self:addField(InputButtonField:new{label="A BUTTON", button=game.BUTTON_BTA})
|
||||
self:addField(InputButtonField:new{label="B BUTTON", button=game.BUTTON_BTB})
|
||||
self:addField(InputButtonField:new{label="C BUTTON", button=game.BUTTON_BTC})
|
||||
self:addField(InputButtonField:new{label="D BUTTON", button=game.BUTTON_BTD})
|
||||
self:addField(InputButtonField:new{label="FX L BUTTON", button=game.BUTTON_FXL})
|
||||
self:addField(InputButtonField:new{label="FX R BUTTON", button=game.BUTTON_FXR})
|
||||
self:addField(InputKnobField:new{label="ANALOG VOLUME L", knob=0})
|
||||
self:addField(InputKnobField:new{label="ANALOG VOLUME R", knob=1})
|
||||
return self
|
||||
local list = ListField:new()
|
||||
list:addField(InputButtonField:new{label="START BUTTON", button=game.BUTTON_STA})
|
||||
list:addField(InputButtonField:new{label="A BUTTON", button=game.BUTTON_BTA})
|
||||
list:addField(InputButtonField:new{label="B BUTTON", button=game.BUTTON_BTB})
|
||||
list:addField(InputButtonField:new{label="C BUTTON", button=game.BUTTON_BTC})
|
||||
list:addField(InputButtonField:new{label="D BUTTON", button=game.BUTTON_BTD})
|
||||
list:addField(InputButtonField:new{label="FX L BUTTON", button=game.BUTTON_FXL})
|
||||
list:addField(InputButtonField:new{label="FX R BUTTON", button=game.BUTTON_FXR})
|
||||
list:addField(InputKnobField:new{label="ANALOG VOLUME L", knob=0})
|
||||
list:addField(InputKnobField:new{label="ANALOG VOLUME R", knob=1})
|
||||
list:refreshFields()
|
||||
|
||||
this:addField(list)
|
||||
this:refreshFields()
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
---@param button integer # options are under the `game` table prefixed with `BUTTON`
|
||||
|
|
|
@ -20,44 +20,19 @@ function MainMenuPage:new(o)
|
|||
|
||||
o.title = o.title or "MAIN MENU"
|
||||
|
||||
return Inherit(self, o, ServicePage)
|
||||
end
|
||||
local this = Inherit(self, o, ServicePage)
|
||||
|
||||
---Initialize members
|
||||
---@return MainMenuPage
|
||||
function MainMenuPage:init()
|
||||
ServicePage.init(self)
|
||||
local list = ListField:new()
|
||||
list:addField(ServiceLinkField:new{label = "INPUT CHECK", link = InputCheckPage:new()})
|
||||
list:addField(ServiceLinkField:new{label = "SCREEN CHECK", link = ScreenCheckPage:new()})
|
||||
list:addField(ServiceLinkField:new{label = "COLOR CHECK", link = ColorCheckPage:new()})
|
||||
list:addField(ServiceLinkField:new{label = "VERSION INFORMATION", link = VersionInfoPage:new()})
|
||||
list:refreshFields()
|
||||
|
||||
local posX = self.PADDING[1]
|
||||
local posY = self.PADDING[2]
|
||||
this:addField(list)
|
||||
this:refreshFields()
|
||||
|
||||
local list = ListField:new{
|
||||
posX = posX,
|
||||
posY = posY,
|
||||
}:init()
|
||||
|
||||
list:addField(ServiceLinkField:new{
|
||||
label = "INPUT CHECK",
|
||||
link = InputCheckPage:new():init(),
|
||||
})
|
||||
list:addField(ServiceLinkField:new{
|
||||
label = "SCREEN CHECK",
|
||||
link = ScreenCheckPage:new():init(),
|
||||
})
|
||||
list:addField(ServiceLinkField:new{
|
||||
label = "COLOR CHECK",
|
||||
link = ColorCheckPage:new():init(),
|
||||
})
|
||||
list:addField(ServiceLinkField:new{
|
||||
label = "VERSION INFORMATION",
|
||||
link = VersionInfoPage:new():init(),
|
||||
})
|
||||
|
||||
self:addField(list)
|
||||
|
||||
self:refreshFields()
|
||||
|
||||
return self
|
||||
return this
|
||||
end
|
||||
|
||||
return MainMenuPage
|
||||
|
|
|
@ -9,12 +9,19 @@ local ServiceField = require("titlescreen.fields.service.servicefield")
|
|||
---@field selectedIndex integer
|
||||
---@field footer string[]
|
||||
---@field content ServiceField[]
|
||||
---@field FONT_SIZE number
|
||||
---@field FONT_FACE string
|
||||
---@field FONT_COLOR integer[] # {r, g, b, a}
|
||||
---@field PADDING number[] # {left, top, right, bottom}
|
||||
---@field PAGE_PADDING number[] # {left, top, right, bottom}
|
||||
---@field FOOTER string|string[]
|
||||
---@field FOOTER_SPACING number
|
||||
local ServicePage = {
|
||||
__tostring = function() return "ServicePage" end,
|
||||
FONT_SIZE = ServiceField.FONT_SIZE,
|
||||
FONT_FACE = ServiceField.FONT_FACE,
|
||||
FONT_COLOR = ServiceField.FONT_COLOR, --{r, g, b, a}
|
||||
PADDING = {92, 128, 0, 56}, --{left, top, right, bottom}
|
||||
PADDING = {100, 128, 0, 56}, --{left, top, right, bottom}
|
||||
PAGE_PADDING = {16, 16, 16, 16}, --{left, top, right, bottom}
|
||||
FOOTER = {
|
||||
"A/B BUTTON = SELECT ITEM",
|
||||
|
@ -51,69 +58,16 @@ function ServicePage:refreshFields()
|
|||
Page.refreshFields(self)
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawBackground(deltaTime)
|
||||
gfx.BeginPath()
|
||||
gfx.FillColor(0, 0, 0)
|
||||
gfx.Rect(0, 0, Dim.design.width, Dim.design.height)
|
||||
gfx.Fill()
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawHeader(deltaTime)
|
||||
local pageTitleTopPadding = self.PAGE_PADDING[2]
|
||||
local lineHeight = self.FOOTER_SPACING
|
||||
gfx.BeginPath()
|
||||
gfx.FontSize(self.FONT_SIZE)
|
||||
gfx.LoadSkinFont(self.FONT_FACE)
|
||||
gfx.FillColor(table.unpack(self.FONT_COLOR))
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_TOP)
|
||||
if type(self.title) == "table" then
|
||||
for index, line in ipairs(self.title) do
|
||||
gfx.Text(line, Dim.design.width / 2, pageTitleTopPadding + (index-1) * lineHeight)
|
||||
end
|
||||
elseif type(self.title) == "string" then
|
||||
gfx.Text(self.title, Dim.design.width / 2, pageTitleTopPadding)
|
||||
end
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawFooter(deltaTime)
|
||||
local footer = self.content[self.selectedIndex] and self.content[self.selectedIndex].footer or self.footer
|
||||
|
||||
local pageFooterBottomPadding = self.PADDING[4]
|
||||
local lineHeight = self.FOOTER_SPACING
|
||||
gfx.BeginPath()
|
||||
gfx.FontSize(self.FONT_SIZE)
|
||||
gfx.LoadSkinFont(self.FONT_FACE)
|
||||
gfx.FillColor(table.unpack(self.FONT_COLOR))
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_BOTTOM)
|
||||
local yFooterBase
|
||||
if type(footer) == "table" then
|
||||
yFooterBase = Dim.design.height - pageFooterBottomPadding - #footer * lineHeight
|
||||
for index, line in ipairs(footer) do
|
||||
gfx.Text(line, Dim.design.width / 2, yFooterBase + (index-1) * lineHeight)
|
||||
end
|
||||
elseif type(footer) == "string" then
|
||||
yFooterBase = Dim.design.height - pageFooterBottomPadding
|
||||
gfx.Text(footer, Dim.design.width / 2, yFooterBase)
|
||||
end
|
||||
end
|
||||
|
||||
---@param button integer # options are under the `game` table prefixed with `BUTTON`
|
||||
function ServicePage:handleButtonInput(button)
|
||||
local field = self.content[self.selectedIndex]
|
||||
if field and field.handleButtonInput then
|
||||
-- if the field indicates that the button input has been handled in a
|
||||
-- way that requires no further processing, return from this function
|
||||
if field:handleButtonInput(button) then
|
||||
return
|
||||
end
|
||||
-- if the field indicates that the button input has been handled in a
|
||||
-- way that requires no further processing, return from this function
|
||||
if field:handleButtonInput(button) then
|
||||
return
|
||||
end
|
||||
|
||||
-- default behaviour
|
||||
|
||||
field:deactivate()
|
||||
-- default behaviour:
|
||||
|
||||
local direction = 0
|
||||
|
||||
|
@ -122,18 +76,20 @@ function ServicePage:handleButtonInput(button)
|
|||
self.viewHandler:back()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if button == game.BUTTON_BTA then
|
||||
elseif button == game.BUTTON_BTA then
|
||||
direction = -1
|
||||
elseif button == game.BUTTON_BTB then
|
||||
direction = 1
|
||||
end
|
||||
|
||||
self.selectedIndex = Util.modIndex(self.selectedIndex + direction, #self.content)
|
||||
if direction ~= 0 then
|
||||
field:deactivate()
|
||||
|
||||
field = self.content[self.selectedIndex]
|
||||
field:focus({direction = direction}) -- send direction as the message
|
||||
self.selectedIndex = Util.modIndex(self.selectedIndex + direction, #self.content)
|
||||
|
||||
field = self.content[self.selectedIndex]
|
||||
field:focus({direction = direction}) -- send direction as the message
|
||||
end
|
||||
end
|
||||
|
||||
---@param knob integer # `0` = Left, `1` = Right
|
||||
|
@ -144,4 +100,73 @@ function ServicePage:handleKnobInput(knob, delta)
|
|||
end
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawBackground(deltaTime)
|
||||
gfx.BeginPath()
|
||||
gfx.FillColor(0, 0, 0)
|
||||
gfx.Rect(0, 0, Dim.design.width, Dim.design.height)
|
||||
gfx.Fill()
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawContent(deltaTime)
|
||||
gfx.Save()
|
||||
gfx.Translate(self.PADDING[1], self.PADDING[2])
|
||||
local contentW = Dim.design.width - self.PADDING[1] - self.PADDING[3]
|
||||
local contentH = Dim.design.height - self.PADDING[2] - self.PADDING[4]
|
||||
gfx.Scissor(0, 0, contentW, contentH)
|
||||
Page.drawContent(self, deltaTime)
|
||||
gfx.Restore()
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawHeader(deltaTime)
|
||||
local lineHeight = self.FOOTER_SPACING
|
||||
gfx.BeginPath()
|
||||
gfx.FontSize(self.FONT_SIZE)
|
||||
gfx.LoadSkinFont(self.FONT_FACE)
|
||||
gfx.FillColor(table.unpack(self.FONT_COLOR))
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_TOP)
|
||||
if type(self.title) == "table" then
|
||||
for index, line in ipairs(self.title) do
|
||||
gfx.Text(line, Dim.design.width / 2, (index-1) * lineHeight)
|
||||
end
|
||||
elseif type(self.title) == "string" then
|
||||
gfx.Text(self.title, Dim.design.width / 2, 0)
|
||||
end
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawFooter(deltaTime)
|
||||
local footer = self.content[self.selectedIndex] and self.content[self.selectedIndex].footer or self.footer
|
||||
|
||||
local lineHeight = self.FOOTER_SPACING
|
||||
gfx.BeginPath()
|
||||
gfx.FontSize(self.FONT_SIZE)
|
||||
gfx.LoadSkinFont(self.FONT_FACE)
|
||||
gfx.FillColor(table.unpack(self.FONT_COLOR))
|
||||
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_BOTTOM)
|
||||
if type(footer) == "table" then
|
||||
local yFooterBase = -#footer * lineHeight
|
||||
for index, line in ipairs(footer) do
|
||||
gfx.Text(line, Dim.design.width / 2, yFooterBase + (index-1) * lineHeight)
|
||||
end
|
||||
elseif type(footer) == "string" then
|
||||
gfx.Text(footer, Dim.design.width / 2, 0)
|
||||
end
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function ServicePage:drawForeground(deltaTime)
|
||||
gfx.Save()
|
||||
gfx.Translate(0, self.PAGE_PADDING[2])
|
||||
self:drawHeader(deltaTime)
|
||||
gfx.Restore()
|
||||
|
||||
gfx.Save()
|
||||
gfx.Translate(0, Dim.design.height - self.PAGE_PADDING[4])
|
||||
self:drawFooter(deltaTime)
|
||||
gfx.Restore()
|
||||
end
|
||||
|
||||
return ServicePage
|
||||
|
|
|
@ -5,7 +5,7 @@ local Version = require("common.version")
|
|||
local ServicePage = require("titlescreen.pages.service.servicepage")
|
||||
local ServiceField = require("titlescreen.fields.service.servicefield")
|
||||
local UpdateField = require("titlescreen.fields.service.updatefield")
|
||||
local SpacerField = require("titlescreen.fields.service.spacerfield")
|
||||
local ListField = require("titlescreen.fields.service.listfield")
|
||||
|
||||
local function getGameLogValue(prefix, str)
|
||||
local pattern = prefix .. ":%s*([^\r\n]*)"
|
||||
|
@ -28,36 +28,27 @@ function VersionInfoPage:new(o)
|
|||
"START BUTTON = UPDATE",
|
||||
"BACK BUTTON = EXIT"
|
||||
}
|
||||
o.selectedIndex = o.selectedIndex or 3
|
||||
o.selectedIndex = o.selectedIndex or 1
|
||||
|
||||
return Inherit(self, o, ServicePage)
|
||||
end
|
||||
|
||||
---Initialize members
|
||||
---@return VersionInfoPage
|
||||
function VersionInfoPage:init()
|
||||
ServicePage.init(self)
|
||||
local this = Inherit(self, o, ServicePage)
|
||||
|
||||
local logStr = ReadGameFile("log_usc-game.exe.txt")
|
||||
|
||||
self:addField(ServiceField:new{label = "SKIN ID CODE", value = Version.getLongVersion()})
|
||||
local list = ListField:new{selectedIndex = 2, locked = true}
|
||||
list:addField(ServiceField:new{label = "SKIN ID CODE", value = Version.getLongVersion(), MARGIN = {0, 0, 0, 24}})
|
||||
list:addField(UpdateField:new{label = "USC VERSION", value = getGameLogValue("Version", logStr)})
|
||||
list:addField(ServiceField:new{label = "USC BRANCH", value = GameConfig["UpdateChannel"]})
|
||||
list:addField(ServiceField:new{label = "USC GIT COMMIT", value = getGameLogValue("Git commit", logStr), MARGIN = {0, 0, 0, 24}})
|
||||
list:addField(ServiceField:new{label = "GL VERSION", value = getGameLogValue("OpenGL Version", logStr)})
|
||||
list:addField(ServiceField:new{label = "GLSL VERSION", value = getGameLogValue("OpenGL Shading Language Version", logStr)})
|
||||
list:addField(ServiceField:new{label = "GL RENDERER", value = getGameLogValue("OpenGL Renderer", logStr)})
|
||||
list:addField(ServiceField:new{label = "GL VENDOR", value = getGameLogValue("OpenGL Vendor", logStr)})
|
||||
list:refreshFields()
|
||||
|
||||
self:addField(SpacerField:new())
|
||||
this:addField(list)
|
||||
this:refreshFields()
|
||||
|
||||
self:addField(UpdateField:new{label = "USC VERSION", value = getGameLogValue("Version", logStr)})
|
||||
self:addField(ServiceField:new{label = "USC BRANCH", value = GameConfig["UpdateChannel"]})
|
||||
self:addField(ServiceField:new{label = "USC GIT COMMIT", value = getGameLogValue("Git commit", logStr)})
|
||||
|
||||
self:addField(SpacerField:new())
|
||||
|
||||
self:addField(ServiceField:new{label = "GL VERSION", value = getGameLogValue("OpenGL Version", logStr)})
|
||||
self:addField(ServiceField:new{label = "GLSL VERSION", value = getGameLogValue("OpenGL Shading Language Version", logStr)})
|
||||
self:addField(ServiceField:new{label = "GL RENDERER", value = getGameLogValue("OpenGL Renderer", logStr)})
|
||||
self:addField(ServiceField:new{label = "GL VENDOR", value = getGameLogValue("OpenGL Vendor", logStr)})
|
||||
|
||||
self.content[self.selectedIndex]:focus()
|
||||
|
||||
return self
|
||||
return this
|
||||
end
|
||||
|
||||
---@param button integer # options are under the `game` table prefixed with `BUTTON`
|
||||
|
|
|
@ -30,7 +30,7 @@ local rootMenu = {
|
|||
|
||||
]]
|
||||
|
||||
local currentpage = MainMenuPage:new():init()
|
||||
local currentpage = MainMenuPage:new()
|
||||
|
||||
local pageview = PageView:new(currentpage)
|
||||
|
||||
|
|
Loading…
Reference in New Issue