bootpage implementation done

implemented update dialog
made UpdateDialogField into a generic DialogField
This commit is contained in:
Hersi 2022-04-24 15:07:52 +02:00
parent e8552b44a4
commit 02f9a05e34
5 changed files with 226 additions and 40 deletions

View File

@ -1,3 +1,4 @@
require("common.globals")
require("common.class")
---@class Page

View File

@ -8,7 +8,7 @@ local ServiceField = require("titlescreen.fields.service.servicefield")
local CheckUpdateField = {
__tostring = function() return "CheckUpdateField" end,
PROGRESS_FREQ = 1 / 5, -- 5Hz
CHECK_UPDATE_MOCK_DELAY = 3, -- seconds
CHECK_UPDATE_TIMEOUT = 5, -- seconds
}
---Create a new CheckUpdateField instance
@ -24,6 +24,7 @@ function CheckUpdateField:new(o)
this._url = nil
this._version = nil
this._onUpdateAvailableFired = false
return this
end
@ -47,12 +48,16 @@ function CheckUpdateField:drawValue(deltaTime)
end
function CheckUpdateField:tick(deltaTime)
if self._timer > self.CHECK_UPDATE_MOCK_DELAY then
self._url, self._version = game.UpdateAvailable()
if self._url then
self.onUpdateAvailable(self._url, self._version)
else
self:getParentPage().viewHandler:clear() -- Exit out of bootscreen
if not self._onUpdateAvailableFired then
if self._timer > self.CHECK_UPDATE_TIMEOUT then
self._url, self._version = game.UpdateAvailable()
-- self._url = "" -- debug code to force onUpdateAvailable()
if self._url then
self.onUpdateAvailable(self._url, self._version)
self._onUpdateAvailableFired = true
else
self:getParentPage().viewHandler:clear() -- Exit out of bootscreen
end
end
end
self._timer = self._timer + deltaTime

View File

@ -0,0 +1,149 @@
require("common.class")
local ContainerField = require("components.pager.containerfield")
---@class DialogField: ContainerField
---@field _symbolMargin number
---@field _symbolSize number
local DialogField = {
__tostring = function() return "ContainerField" end,
BGCOLOR = {0, 0, 0, 255}, --{r, g, b, a}
DEFAULT_WIDTH = 400,
DEFAULT_HEIGHT = 200,
FONT_SIZE = 16,
FONT_FACE = "dfmarugoth.ttf",
FONT_COLOR = {255, 255, 255, 255},
BORDERCOLOR = {255, 255, 255, 255},
BORDERRADII = 12,
BORDERWIDTH = 2,
HEADER = {
title = "Title",
code = "0-0000-0000"
},
TEXT = {
"Top text,",
"Sample text,",
"Bottom text."
},
LEGEND = {
{
label = "BUTTON",
text = "DESCRIPTION"
},
},
}
---Create a new DialogField instance
---
---Inherits from ContainerField
---@param o ContainerField
---@return DialogField
function DialogField:new(o)
o = o or {}
o.aabbW = o.aabbW or self.DEFAULT_WIDTH
o.aabbH = o.aabbH or self.DEFAULT_HEIGHT
local this = Inherit(self, o, ContainerField)
this._symbolMargin = 8
this._symbolSize = 48
return this
end
---Draw the dialog symbol
---
---Default implementation is a yellow triangle with an exclamation mark
---@param deltaTime number # frametime in seconds
function DialogField:drawSymbol(deltaTime)
local symbolColor = {255, 255, 0, 255}
gfx.Save()
gfx.Translate(self._symbolMargin, self._symbolMargin)
gfx.FillColor(table.unpack(symbolColor))
gfx.BeginPath()
local symbolBottomY = math.sqrt(3) / 2 * self._symbolSize
gfx.MoveTo(0, symbolBottomY)
gfx.LineTo(self._symbolSize / 2, 0)
gfx.LineTo(self._symbolSize, symbolBottomY)
gfx.Fill()
-- exclamation mark
local excTopMargin = 10
local excBottomMargin = 4
local excThickness = 5
local excColor = {0, 0, 0, 255}
gfx.FillColor(table.unpack(excColor))
gfx.BeginPath()
gfx.Rect(
self._symbolSize / 2 - excThickness / 2, -- x
excTopMargin, -- y
excThickness, -- w
symbolBottomY - excTopMargin - excBottomMargin - 3 / 2 * excThickness -- h
)
gfx.Rect(
self._symbolSize / 2 - excThickness / 2, -- x
symbolBottomY - excBottomMargin - excThickness, -- y
excThickness, excThickness -- w, h
)
gfx.Fill()
gfx.Restore()
end
---@param deltaTime number # frametime in seconds
function DialogField:drawBackground(deltaTime)
local textMargin = 4
-- border
local borderH = self.aabbH - #self.LEGEND * self.FONT_SIZE - textMargin
gfx.BeginPath()
gfx.StrokeColor(table.unpack(self.BORDERCOLOR))
gfx.StrokeWidth(self.BORDERWIDTH)
gfx.FillColor(table.unpack(self.BGCOLOR))
gfx.RoundedRect(0, 0, self.aabbW, borderH, self.BORDERRADII)
gfx.Fill()
gfx.Stroke()
gfx.FontSize(self.FONT_SIZE)
gfx.LoadSkinFont(self.FONT_FACE)
-- draw symbol
self:drawSymbol(deltaTime)
-- legend
local legendX = 0
local legendY = borderH + textMargin
gfx.TextAlign(gfx.TEXT_ALIGN_TOP | gfx.TEXT_ALIGN_LEFT)
gfx.FillColor(table.unpack(self.FONT_COLOR))
for _, legend in ipairs(self.LEGEND) do
gfx.Text(legend.label .. " = " .. legend.text, legendX, legendY)
legendY = legendY + self.FONT_SIZE
end
-- header
local headerX = self._symbolSize + self._symbolMargin + 16
local headerY = self._symbolMargin
gfx.Save()
gfx.Translate(headerX, headerY)
gfx.Text(self.HEADER.title, 0, 0)
local separatorY = self.FONT_SIZE + textMargin
local separatorThickness = 1
gfx.StrokeWidth(separatorThickness)
gfx.BeginPath()
gfx.MoveTo(0, separatorY)
gfx.LineTo(self.aabbW - headerX - self._symbolMargin, separatorY)
gfx.Stroke()
local codeY = separatorY + textMargin
gfx.Text(self.HEADER.code, 0, codeY)
gfx.Restore()
end
---@param deltaTime number # frametime in seconds
function DialogField:drawForeground(deltaTime)
local textX = 12
local textY = 64
local lineHeight = self.FONT_SIZE + 4
for _, line in ipairs(self.TEXT) do
gfx.Text(line, textX, textY)
textY = textY + lineHeight
end
end
return DialogField

View File

@ -1,32 +0,0 @@
require("common.class")
local ContainerField = require("components.pager.containerfield")
---@class UpdateDialogField: ContainerField
local UpdateDialogField = {
__tostring = function() return "ContainerField" end,
BGCOLOR = {0, 0, 0, 255}, --{r, g, b, a}
BORDERCOLOR = {255, 255, 255, 255},
BORDERRADII = 4,
BORDERWIDTH = 1,
}
---Create a new UpdateDialogField instance
---
---Inherits from ContainerField
---@param o ContainerField
---@return UpdateDialogField
function UpdateDialogField:new(o)
o = o or {}
return Inherit(self, o, ContainerField)
end
function UpdateDialogField:drawBackground(deltaTime)
end
function UpdateDialogField:drawForeground(deltaTime)
end
return UpdateDialogField

View File

@ -2,8 +2,10 @@ require("common.class")
local Dim = require("common.dimensions")
local Page = require("components.pager.page")
local CheckUpdateField = require("titlescreen.fields.boot.checkupdatefield")
local DialogField = require("titlescreen.fields.boot.dialogfield")
---@class CheckUpdatePage: Page
---@field _focusedField CheckUpdateField
local CheckUpdatePage = {
__tostring = function() return "CheckUpdatePage" end,
}
@ -14,15 +16,76 @@ local CheckUpdatePage = {
function CheckUpdatePage:new(o)
local this = Inherit(self, o, Page)
local width = DialogField.DEFAULT_WIDTH
local height = DialogField.DEFAULT_HEIGHT
local posX = (Dim.design.width - width) / 2
local posY = (Dim.design.height - height) / 2
this._updateDialogField = DialogField:new{
posX = posX,
posY = posY,
aabbW = width,
aabbH = height,
HEADER = {
title = "Updates found",
code = "0-1000-0000"
},
TEXT = {
"An update is available to Unnamed SDVX Clone,",
"please update to receive the latest features."
},
LEGEND = {
{
label = "BACK BUTTON",
text = "ABORT UPDATE/START GAME"
},
{
label = "START BUTTON",
text = "GO TO SERVICE PAGE"
}
}
}
this._updateDialogField.handleButtonInput = function (self, button)
if not this.viewHandler then
return false
end
if button == game.BUTTON_BCK then
this.viewHandler:clear() -- Cancel update, close screen
return true
elseif button == game.BUTTON_STA then
-- NOTE: this is a huge ass hack, please rethink
local pageview = this.viewHandler
local MainMenuPage = require("titlescreen.pages.service.mainmenupage")
local VersionInfoPage = require("titlescreen.pages.service.versioninfopage")
pageview:replace(MainMenuPage:new())
pageview:navigate(VersionInfoPage:new())
return true
end
end
this._checkUpdateField = CheckUpdateField:new{posX = 32, posY = 64, label = "update check"}
this._checkUpdateField.onUpdateAvailable = function(url, version)
this:addField(this._updateDialogField)
this._focusedField = this._updateDialogField
end
this:addField(this._checkUpdateField)
this._focusedField = this._checkUpdateField
return this
end
function CheckUpdatePage:handleButtonInput(button)
if self._focusedField and self._focusedField:handleButtonInput(button) then
return -- stop processing input
end
if button == game.BUTTON_BCK then
self.viewHandler:back()
end
end
---@param deltaTime number # frametime in seconds
function CheckUpdatePage:drawBackground(deltaTime)
gfx.BeginPath()