bootpage implementation
This commit is contained in:
parent
eb55b8ffa0
commit
e8552b44a4
|
@ -0,0 +1,66 @@
|
|||
require("common.class")
|
||||
local Util = require("common.util")
|
||||
local ServiceField = require("titlescreen.fields.service.servicefield")
|
||||
|
||||
---@class CheckUpdateField: ServiceField
|
||||
---@field onUpdateAvailable nil|fun(url: string, version: string)
|
||||
---@field _timer number
|
||||
local CheckUpdateField = {
|
||||
__tostring = function() return "CheckUpdateField" end,
|
||||
PROGRESS_FREQ = 1 / 5, -- 5Hz
|
||||
CHECK_UPDATE_MOCK_DELAY = 3, -- seconds
|
||||
}
|
||||
|
||||
---Create a new CheckUpdateField instance
|
||||
---@param o? table # initial parameters
|
||||
---@return CheckUpdateField
|
||||
function CheckUpdateField:new(o)
|
||||
o = o or {}
|
||||
|
||||
o._timer = o._timer or 0
|
||||
o.onUpdateAvailable = o.onUpdateAvailable or nil
|
||||
|
||||
local this = Inherit(self, o, ServiceField)
|
||||
|
||||
this._url = nil
|
||||
this._version = nil
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
function CheckUpdateField:drawLabel(deltaTime)
|
||||
local text = self.label
|
||||
local progress = math.ceil(Util.lerp(self._timer % self.PROGRESS_FREQ,
|
||||
0, 0, self.PROGRESS_FREQ, 4
|
||||
))
|
||||
text = text .. string.rep(".", progress)
|
||||
|
||||
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, 0, 0)
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
self._timer = self._timer + deltaTime
|
||||
end
|
||||
|
||||
function CheckUpdateField:render(deltaTime)
|
||||
self:tick(deltaTime)
|
||||
ServiceField.render(self, deltaTime)
|
||||
end
|
||||
|
||||
return CheckUpdateField
|
|
@ -11,16 +11,24 @@ SelfTestStatusEnum = {
|
|||
ERROR = 5
|
||||
}
|
||||
|
||||
local function statusToString(status)
|
||||
local statusName = {"IDLE", "INPROGRESS", "OK", "PASS", "ERROR"}
|
||||
return statusName[status]
|
||||
end
|
||||
|
||||
---@class SelfTestField: ServiceField
|
||||
---@field checkTask nil|fun(obj: any): SelfTestStatusEnum # a function that will run asynchronously on activating the Field
|
||||
---@field status SelfTestStatusEnum
|
||||
---@field callback nil|fun(obj: any): SelfTestStatusEnum
|
||||
---@field onStatusChange nil|fun(status) # a callback function on finishing the checkTask
|
||||
---@field _thread thread
|
||||
---@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
|
||||
__tostring = function () return "SelfTestField" end,
|
||||
COLOR_INPROGRESS = {255, 255, 255, 255},
|
||||
COLOR_OK = {0, 255, 0, 255},
|
||||
COLOR_PASS = {255, 255, 0, 255},
|
||||
COLOR_ERROR = {255, 0, 0, 255},
|
||||
INPROGRESS_FREQ = 1 / 20, --20Hz
|
||||
}
|
||||
|
||||
---Create a new SelfTestField instance
|
||||
|
@ -30,18 +38,61 @@ function SelfTestField:new(o)
|
|||
o = o or {}
|
||||
|
||||
o.status = o.status or SelfTestStatusEnum.IDLE
|
||||
o.callback = o.callback or nil
|
||||
o._timer = 0
|
||||
o._thread = nil
|
||||
|
||||
assert((not o.onStatusChange) or (o.checkTask and o.onStatusChange),
|
||||
"Failed to construct SelfTestField, checkTask is mandatory when onStatusChange is defined!\n" .. debug.traceback()
|
||||
)
|
||||
|
||||
return Inherit(self, o, ServiceField)
|
||||
end
|
||||
|
||||
function SelfTestField:activate(obj)
|
||||
if self.callback then
|
||||
self.status = self.callback(obj) or SelfTestStatusEnum.INPROGRESS
|
||||
function SelfTestField:_closeThread()
|
||||
if self._thread and coroutine.status(self._thread) ~= "dead" then
|
||||
coroutine.close(self._thread)
|
||||
end
|
||||
end
|
||||
|
||||
function SelfTestField:_resumeThread()
|
||||
if self._thread and coroutine.status(self._thread) == "suspended" then
|
||||
local success, status = coroutine.resume(self._thread)
|
||||
game.Log(self.label .. ": success: " .. tostring(success) ..
|
||||
", status: " .. status .. " (" .. statusToString(status) .. ")",
|
||||
game.LOGGER_DEBUG
|
||||
)
|
||||
if success and status ~= self.status then
|
||||
self.status = status
|
||||
if self.onStatusChange then
|
||||
game.Log("SKIN CONFIG: onStatusChange(" .. status .. ") (" ..
|
||||
statusToString(status) .. ")",
|
||||
game.LOGGER_DEBUG
|
||||
)
|
||||
self.onStatusChange(status)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SelfTestField:activate(obj)
|
||||
self:_closeThread()
|
||||
|
||||
if self.checkTask then
|
||||
self._thread = coroutine.create(self.checkTask)
|
||||
self:_resumeThread()
|
||||
end
|
||||
end
|
||||
|
||||
function SelfTestField:deactivate(obj)
|
||||
self:_closeThread()
|
||||
end
|
||||
|
||||
function SelfTestField:tick(deltaTime)
|
||||
self:_resumeThread()
|
||||
|
||||
self._timer = self._timer + deltaTime
|
||||
end
|
||||
|
||||
function SelfTestField:drawValue(deltaTime)
|
||||
gfx.Translate(self.VALUE_OFFSETX, 0)
|
||||
|
||||
|
@ -54,18 +105,19 @@ function SelfTestField:drawValue(deltaTime)
|
|||
color = self.FONT_COLOR
|
||||
text = ""
|
||||
elseif self.status == SelfTestStatusEnum.INPROGRESS then
|
||||
self._timer = self._timer + deltaTime
|
||||
local progress = math.ceil(Util.lerp(self._timer % 1, 0, 0, 1, 4))
|
||||
color = self.SELFTEST_COLOR_INPROGRESS
|
||||
local progress = math.ceil(Util.lerp(self._timer % self.INPROGRESS_FREQ,
|
||||
0, 0, self.INPROGRESS_FREQ, 4
|
||||
))
|
||||
color = self.COLOR_INPROGRESS
|
||||
text = string.rep(".", progress)
|
||||
elseif self.status == SelfTestStatusEnum.OK then
|
||||
color = self.SELFTEST_COLOR_OK
|
||||
color = self.COLOR_OK
|
||||
text = "OK"
|
||||
elseif self.status == SelfTestStatusEnum.PASS then
|
||||
color = self.SELFTEST_COLOR_PASS
|
||||
color = self.COLOR_PASS
|
||||
text = "PASS"
|
||||
elseif self.status == SelfTestStatusEnum.ERROR then
|
||||
color = self.SELFTEST_COLOR_ERROR
|
||||
color = self.COLOR_ERROR
|
||||
text = "ERROR"
|
||||
end
|
||||
|
||||
|
@ -74,4 +126,9 @@ function SelfTestField:drawValue(deltaTime)
|
|||
gfx.Text(text, 0, 0)
|
||||
end
|
||||
|
||||
function SelfTestField:render(deltaTime)
|
||||
self:tick(deltaTime)
|
||||
ServiceField.render(self, deltaTime)
|
||||
end
|
||||
|
||||
return SelfTestField
|
|
@ -3,34 +3,11 @@ require("common.filereader")
|
|||
local Dim = require("common.dimensions")
|
||||
local Version = require("common.version")
|
||||
local Page = require("components.pager.page")
|
||||
local CheckUpdatePage = require("titlescreen.pages.boot.checkupdatepage")
|
||||
local ServiceField = require("titlescreen.fields.service.servicefield")
|
||||
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 = {
|
||||
__tostring = function() return "BootPage" end,
|
||||
|
@ -44,14 +21,71 @@ function BootPage:new(o)
|
|||
|
||||
local this = Inherit(self, o, Page)
|
||||
|
||||
this._networkResult = {}
|
||||
|
||||
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 = ""})
|
||||
|
||||
local valueOffX = 220
|
||||
this._mainIoTestField = SelfTestField:new{label = "MAIN I/O", VALUE_OFFSETX = valueOffX}
|
||||
this._mainIoTestField.checkTask = function(obj)
|
||||
return SelfTestStatusEnum.OK
|
||||
end
|
||||
this._mainIoTestField.onStatusChange = function(status)
|
||||
if status == SelfTestStatusEnum.OK then
|
||||
this._skinConfigTestField:activate()
|
||||
end
|
||||
end
|
||||
|
||||
this._skinConfigTestField = SelfTestField:new{label = "SKIN CONFIG", VALUE_OFFSETX = valueOffX}
|
||||
this._skinConfigTestField.checkTask = function(obj)
|
||||
local crewpath = "skins/" .. game.GetSkin() .. "/textures/crew/anim/" .. game.GetSkinSetting("single_idol")
|
||||
if not IsDir(crewpath) then
|
||||
return SelfTestStatusEnum.ERROR
|
||||
end
|
||||
return SelfTestStatusEnum.OK
|
||||
end
|
||||
this._skinConfigTestField.onStatusChange = function(status)
|
||||
if status == SelfTestStatusEnum.OK then
|
||||
this._networkTestField:activate()
|
||||
end
|
||||
end
|
||||
|
||||
this._networkTestField = SelfTestField:new{label = "NETWORK", VALUE_OFFSETX = valueOffX}
|
||||
-- set up async network check
|
||||
this._networkTestField.checkTask = function(obj)
|
||||
local status = SelfTestStatusEnum.INPROGRESS
|
||||
|
||||
if not IRData.Active then
|
||||
return SelfTestStatusEnum.PASS
|
||||
end
|
||||
|
||||
while status == SelfTestStatusEnum.INPROGRESS do
|
||||
if this._networkResult.statusCode == IRData.States.Success then
|
||||
status = SelfTestStatusEnum.OK
|
||||
elseif this._networkResult.statusCode then
|
||||
status = SelfTestStatusEnum.ERROR -- there's a response, but it's not success
|
||||
end
|
||||
|
||||
coroutine.yield(status)
|
||||
end
|
||||
|
||||
return status
|
||||
end
|
||||
this._networkTestField.onStatusChange = function(status)
|
||||
if status == SelfTestStatusEnum.INPROGRESS then
|
||||
IR.Heartbeat(function(res) this._networkResult = res end) -- IR doesn't like being called in a coroutine
|
||||
elseif status == SelfTestStatusEnum.PASS or status == SelfTestStatusEnum.OK then
|
||||
if this.viewHandler then
|
||||
this.viewHandler:navigate(CheckUpdatePage:new())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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})
|
||||
list:addField(this._mainIoTestField)
|
||||
list:addField(this._skinConfigTestField)
|
||||
list:addField(this._networkTestField)
|
||||
this:addField(list)
|
||||
|
||||
return this
|
||||
|
@ -65,12 +99,13 @@ function BootPage:drawBackground(deltaTime)
|
|||
gfx.Fill()
|
||||
end
|
||||
|
||||
local first = true
|
||||
function BootPage:render(deltaTime)
|
||||
if first then
|
||||
self._mainIoTestField:activate()
|
||||
first = false
|
||||
end
|
||||
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
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
require("common.class")
|
||||
local Dim = require("common.dimensions")
|
||||
local Page = require("components.pager.page")
|
||||
local CheckUpdateField = require("titlescreen.fields.boot.checkupdatefield")
|
||||
|
||||
---@class CheckUpdatePage: Page
|
||||
local CheckUpdatePage = {
|
||||
__tostring = function() return "CheckUpdatePage" end,
|
||||
}
|
||||
|
||||
---Create a new CheckUpdatePage instance
|
||||
---@param o? table # initial parameters
|
||||
---@return CheckUpdatePage
|
||||
function CheckUpdatePage:new(o)
|
||||
local this = Inherit(self, o, Page)
|
||||
|
||||
this._checkUpdateField = CheckUpdateField:new{posX = 32, posY = 64, label = "update check"}
|
||||
this._checkUpdateField.onUpdateAvailable = function(url, version)
|
||||
|
||||
end
|
||||
this:addField(this._checkUpdateField)
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function CheckUpdatePage:drawBackground(deltaTime)
|
||||
gfx.BeginPath()
|
||||
gfx.FillColor(0, 0, 0)
|
||||
gfx.Rect(0, 0, Dim.design.width, Dim.design.height)
|
||||
gfx.Fill()
|
||||
end
|
||||
|
||||
return CheckUpdatePage
|
Loading…
Reference in New Issue