From f44ba3743b4399b1e868d52aa17a9934cf3acf4b Mon Sep 17 00:00:00 2001 From: Hersi Date: Fri, 15 Apr 2022 04:54:30 +0200 Subject: [PATCH] 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 --- scripts/common/filereader.lua | 35 +++- scripts/components/pager/containerfield.lua | 14 +- scripts/components/pager/field.lua | 34 ++-- scripts/components/pager/page.lua | 34 ++-- scripts/titlescreen.lua | 2 +- scripts/titlescreen/boot.lua | 13 +- .../titlescreen/fields/boot/selftestfield.lua | 23 ++- .../fields/service/colorgradientfield.lua | 3 +- .../fields/service/inputbuttonfield.lua | 6 +- .../fields/service/inputknobfield.lua | 16 +- .../titlescreen/fields/service/listfield.lua | 61 +++---- .../fields/service/servicefield.lua | 46 ++++-- .../fields/service/servicelinkfield.lua | 4 + .../fields/service/spacerfield.lua | 19 --- .../fields/service/updatefield.lua | 17 +- scripts/titlescreen/pages/boot/bootpage.lua | 64 +++++--- .../pages/service/colorcheckpage.lua | 44 ++--- .../pages/service/inputcheckpage.lua | 34 ++-- .../pages/service/mainmenupage.lua | 45 ++--- .../titlescreen/pages/service/servicepage.lua | 155 ++++++++++-------- .../pages/service/versioninfopage.lua | 41 ++--- scripts/titlescreen/service.lua | 2 +- 22 files changed, 385 insertions(+), 327 deletions(-) delete mode 100644 scripts/titlescreen/fields/service/spacerfield.lua diff --git a/scripts/common/filereader.lua b/scripts/common/filereader.lua index c450b93..3cd12f5 100644 --- a/scripts/common/filereader.lua +++ b/scripts/common/filereader.lua @@ -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 diff --git a/scripts/components/pager/containerfield.lua b/scripts/components/pager/containerfield.lua index 7c8b2b3..12f015a 100644 --- a/scripts/components/pager/containerfield.lua +++ b/scripts/components/pager/containerfield.lua @@ -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) diff --git a/scripts/components/pager/field.lua b/scripts/components/pager/field.lua index e9dd005..a97ff47 100644 --- a/scripts/components/pager/field.lua +++ b/scripts/components/pager/field.lua @@ -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() diff --git a/scripts/components/pager/page.lua b/scripts/components/pager/page.lua index 91304d4..43edab4 100644 --- a/scripts/components/pager/page.lua +++ b/scripts/components/pager/page.lua @@ -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 diff --git a/scripts/titlescreen.lua b/scripts/titlescreen.lua index ea538eb..d727a57 100644 --- a/scripts/titlescreen.lua +++ b/scripts/titlescreen.lua @@ -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 diff --git a/scripts/titlescreen/boot.lua b/scripts/titlescreen/boot.lua index 8ad3a48..4cfe557 100644 --- a/scripts/titlescreen/boot.lua +++ b/scripts/titlescreen/boot.lua @@ -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 -} \ No newline at end of file +local function onButtonPressed(button) + pageview:get():handleButtonInput(button) +end + +return {render = render, onButtonPressed = onButtonPressed} \ No newline at end of file diff --git a/scripts/titlescreen/fields/boot/selftestfield.lua b/scripts/titlescreen/fields/boot/selftestfield.lua index abc8bec..7a38175 100644 --- a/scripts/titlescreen/fields/boot/selftestfield.lua +++ b/scripts/titlescreen/fields/boot/selftestfield.lua @@ -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 \ No newline at end of file diff --git a/scripts/titlescreen/fields/service/colorgradientfield.lua b/scripts/titlescreen/fields/service/colorgradientfield.lua index b22c387..c242b3a 100644 --- a/scripts/titlescreen/fields/service/colorgradientfield.lua +++ b/scripts/titlescreen/fields/service/colorgradientfield.lua @@ -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 diff --git a/scripts/titlescreen/fields/service/inputbuttonfield.lua b/scripts/titlescreen/fields/service/inputbuttonfield.lua index 6adba48..c8f1571 100644 --- a/scripts/titlescreen/fields/service/inputbuttonfield.lua +++ b/scripts/titlescreen/fields/service/inputbuttonfield.lua @@ -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("