moved titlescreen implementation to the new page system
added Screen middle-class to titlescreen/ added BootScreen implementation added "missing" input enums to globals PageView no longer requires a rootPage on construction added a mouse handler to Page ModeSelectPage no longer starts playing audio and animations on construction
This commit is contained in:
parent
ff8322ca28
commit
be9a1f9408
|
@ -1,5 +1,6 @@
|
|||
# IDE files
|
||||
.vscode
|
||||
docs/diagrams/export
|
||||
|
||||
# secret(?) assets
|
||||
_asset
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
@startuml titlescreen onScreenChange event
|
||||
!theme materia-outline
|
||||
skinparam DefaultFontName Courier
|
||||
skinparam Shadowing false
|
||||
|
||||
participant usc
|
||||
participant "titlescreen.lua" as main
|
||||
collections screens
|
||||
collections pages
|
||||
|
||||
activate main
|
||||
activate screens
|
||||
activate pages
|
||||
|
||||
hnote across
|
||||
Screen loaded and page displayed
|
||||
endhnote
|
||||
|
||||
pages -> screens : change screen event\n(eg. goes out of scope)
|
||||
deactivate pages
|
||||
screens --> main : onDeactivation(obj)
|
||||
deactivate screens
|
||||
|
||||
main -> main : handle replacing screen\nby inspecting `obj`
|
||||
|
||||
main -> screens : call current screen's init()
|
||||
activate screens
|
||||
|
||||
screens -> usc : set current screen as last screen value
|
||||
|
||||
screens -> pages : init()
|
||||
|
||||
activate pages
|
||||
|
||||
@enduml
|
|
@ -0,0 +1,48 @@
|
|||
@startuml titlescreen startup
|
||||
!theme materia-outline
|
||||
skinparam DefaultFontName Courier
|
||||
skinparam Shadowing false
|
||||
|
||||
participant usc
|
||||
participant "titlescreen.lua" as main
|
||||
collections screens
|
||||
collections pages
|
||||
|
||||
usc -> main : load titlescreen.lua
|
||||
|
||||
activate main
|
||||
|
||||
group construct screens
|
||||
main -> screens : create
|
||||
screens -> pages : create
|
||||
screens -> pages : set callbacks
|
||||
main -> screens : set callbacks
|
||||
main -> usc : get persistent states
|
||||
main <-- usc
|
||||
main -> screens : load persistent previous state values
|
||||
end
|
||||
|
||||
main -> usc : get last screen value
|
||||
main <-- usc
|
||||
|
||||
main -> main : set last screen value as current screen
|
||||
|
||||
main -> screens : call current screen's init()
|
||||
|
||||
activate screens
|
||||
|
||||
screens -> usc : set current screen as last screen value
|
||||
|
||||
screens -> pages : init()
|
||||
activate pages
|
||||
|
||||
loop main render loop
|
||||
main -> screens : call current screen's render()
|
||||
activate screens
|
||||
screens -> pages : render()
|
||||
activate pages
|
||||
deactivate screens
|
||||
deactivate pages
|
||||
end
|
||||
|
||||
@enduml
|
|
@ -9,19 +9,22 @@ local Page = {
|
|||
}
|
||||
|
||||
---Create a new Page instance
|
||||
---@param o? table # initial parameters
|
||||
---@param params? table # initial parameters
|
||||
---@return Page
|
||||
function Page.new(o)
|
||||
o = o or {}
|
||||
function Page.new(params)
|
||||
params = params or {}
|
||||
|
||||
--set instance members
|
||||
--set default parameters
|
||||
|
||||
o.content = o.content or {}
|
||||
o.viewHandler = o.viewHandler or nil
|
||||
params.content = params.content or {}
|
||||
params.viewHandler = params.viewHandler or nil
|
||||
|
||||
return CreateInstance(Page, o)
|
||||
return CreateInstance(Page, params)
|
||||
end
|
||||
|
||||
---Initialize Page
|
||||
function Page:init() end
|
||||
|
||||
---Add field to page
|
||||
---@param field Field
|
||||
function Page:addField(field)
|
||||
|
@ -49,6 +52,11 @@ end
|
|||
---@param delta number # in radians, `-2*pi` to `0` (turning CCW) and `0` to `2*pi` (turning CW)
|
||||
function Page:handleKnobInput(knob, delta) end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param button integer
|
||||
function Page:handleMouseInput(x, y, button) end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function Page:drawBackground(deltaTime) end
|
||||
|
||||
|
|
|
@ -15,21 +15,11 @@ local function popStack(t)
|
|||
end
|
||||
|
||||
---Create a new PageView instance
|
||||
---@param rootPage Page
|
||||
---@return PageView
|
||||
function PageView.new(rootPage)
|
||||
local o = {}
|
||||
|
||||
--set viewHandler as this instance for rootPage
|
||||
|
||||
rootPage.viewHandler = o
|
||||
|
||||
--set instance members
|
||||
|
||||
o.pageStack = {}
|
||||
pushStack(o.pageStack, rootPage)
|
||||
|
||||
return CreateInstance(PageView, o)
|
||||
function PageView.new()
|
||||
local self = CreateInstance(PageView, {})
|
||||
self.pageStack = {}
|
||||
return self
|
||||
end
|
||||
|
||||
---Get page from pageStack
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
---Drewol, what are you doing? Why is there no game.LOGGER_DEBUG?
|
||||
game.LOGGER_DEBUG = 0
|
||||
|
||||
-- add missing inputs
|
||||
game.MOUSE_LEFT = 0
|
||||
game.MOUSE_RIGHT = 1
|
||||
game.MOUSE_MIDDLE = 2
|
||||
|
||||
game.KNOB_LEFT = 0
|
||||
game.KNOB_RIGHT = 1
|
||||
|
|
|
@ -1,33 +1,43 @@
|
|||
require("common.globals")
|
||||
local Common = require("common.util")
|
||||
local Dim = require("common.dimensions")
|
||||
local Wallpaper = require("components.wallpaper")
|
||||
|
||||
local PageView = require("api.page.pageview")
|
||||
|
||||
local BootPage = require("titlescreen.pages.boot.bootpage")
|
||||
local ModeSelectPage = require("titlescreen.pages.modeselect.modeselectpage")
|
||||
local ServiceMenuPage = require("titlescreen.pages.service.mainmenupage")
|
||||
|
||||
local BootScreen = require('titlescreen.boot')
|
||||
local SplashScreen = require('titlescreen.splash')
|
||||
local TitleScreen = require('titlescreen.title')
|
||||
local ModeSelectScreen = require('titlescreen.modeselect')
|
||||
local ServiceScreen = require('titlescreen.service')
|
||||
|
||||
local bootScreen = require('titlescreen.boot')
|
||||
local splashScreen = require('titlescreen.splash')
|
||||
local titleScreen = require('titlescreen.title')
|
||||
local modeSelectScreen = require('titlescreen.modeselect')
|
||||
local serviceScreen = require('titlescreen.service')
|
||||
|
||||
local screens = {
|
||||
boot = {
|
||||
screen = bootScreen
|
||||
},
|
||||
splash = {
|
||||
screen = splashScreen
|
||||
},
|
||||
title = {
|
||||
screen = titleScreen
|
||||
},
|
||||
mode_select = {
|
||||
screen = modeSelectScreen
|
||||
},
|
||||
service = {
|
||||
screen = serviceScreen
|
||||
}
|
||||
[tostring(BootScreen)] = BootScreen.new(),
|
||||
--splash = splashScreen,
|
||||
--title = titleScreen,
|
||||
--[tostring(ModeSelectPage)] = ModeSelectPage.new(),
|
||||
--[tostring(ServiceMenuPage)] = ServiceMenuPage.new()
|
||||
}
|
||||
|
||||
local currentScreen = game.GetSkinSetting("animations_skipIntro") and screens.title or screens.boot -- 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 currentScreen = screens[tostring(BootScreen)]
|
||||
|
||||
---@param obj ScreenCallbackObject
|
||||
local function onDeactivationCallback(obj)
|
||||
currentScreen = screens[obj.hint]
|
||||
end
|
||||
|
||||
for _, value in pairs(screens) do
|
||||
value.onDeactivation = onDeactivationCallback
|
||||
end
|
||||
|
||||
local function deltaKnob(delta)
|
||||
-- what the hell does this do?
|
||||
if math.abs(delta) > 1.5 * math.pi then
|
||||
return delta + 2 * math.pi * Common.sign(delta) * -1
|
||||
end
|
||||
|
@ -35,44 +45,21 @@ local function deltaKnob(delta)
|
|||
end
|
||||
|
||||
local lastKnobs = nil
|
||||
local knobProgress = 0
|
||||
local knobThreshold = (2 * math.pi) / 360
|
||||
local function handleKnobs()
|
||||
if not currentScreen.screen.onKnobsChange then
|
||||
return
|
||||
end
|
||||
|
||||
if lastKnobs == nil then
|
||||
lastKnobs = {game.GetKnob(0), game.GetKnob(1)}
|
||||
lastKnobs = {game.GetKnob(game.KNOB_LEFT), game.GetKnob(game.KNOB_RIGHT)}
|
||||
else
|
||||
local newKnobs = {game.GetKnob(0), game.GetKnob(1)}
|
||||
|
||||
knobProgress = knobProgress - deltaKnob(lastKnobs[1] - newKnobs[1]) * 1.2
|
||||
knobProgress = knobProgress - deltaKnob(lastKnobs[2] - newKnobs[2]) * 1.2
|
||||
|
||||
local newKnobs = {game.GetKnob(game.KNOB_LEFT), game.GetKnob(game.KNOB_RIGHT)}
|
||||
local knobProgress = {deltaKnob(lastKnobs[1] - newKnobs[1]), deltaKnob(lastKnobs[2] - newKnobs[2])}
|
||||
lastKnobs = newKnobs
|
||||
|
||||
if math.abs(knobProgress) > 1 then
|
||||
if (knobProgress < 0) then
|
||||
-- Negative
|
||||
currentScreen.screen.onKnobsChange(-1)
|
||||
else
|
||||
-- Positive
|
||||
currentScreen.screen.onKnobsChange(1)
|
||||
if math.abs(knobProgress[1]) > knobThreshold then
|
||||
currentScreen:handleKnobInput(game.KNOB_LEFT, knobProgress[1])
|
||||
end
|
||||
knobProgress = knobProgress - Common.roundToZero(knobProgress)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function handleScreenResponse(res)
|
||||
if res and res.eventType == 'switch' then
|
||||
if not screens[res.toScreen] then
|
||||
game.Log('Undefined screen ' .. res.toScreen, game.LOGGER_ERROR)
|
||||
return
|
||||
end
|
||||
currentScreen = screens[res.toScreen]
|
||||
if currentScreen.screen.reset then
|
||||
currentScreen.screen.reset()
|
||||
if math.abs(knobProgress[2]) > knobThreshold then
|
||||
currentScreen:handleKnobInput(game.KNOB_RIGHT, knobProgress[2])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -80,18 +67,21 @@ end
|
|||
function render(deltaTime)
|
||||
handleKnobs()
|
||||
|
||||
handleScreenResponse(currentScreen.screen.render(deltaTime))
|
||||
Dim.updateResolution()
|
||||
|
||||
Wallpaper.render()
|
||||
|
||||
Dim.transformToScreenSpace()
|
||||
|
||||
currentScreen:render(deltaTime)
|
||||
end
|
||||
|
||||
function mouse_pressed(button)
|
||||
if (currentScreen.screen.onMousePressed) then
|
||||
currentScreen.screen.onMousePressed(button)
|
||||
end
|
||||
return 0
|
||||
local mouseX, mouseY = game.GetMousePos()
|
||||
currentScreen:handleMouseInput(mouseX, mouseY, button)
|
||||
return 0 --THIS '0' IS VERY IMPORTANT, IT WILL CRASH VERY HARD WITHOUT THIS
|
||||
end
|
||||
|
||||
function button_pressed(button)
|
||||
if (currentScreen.screen.onButtonPressed) then
|
||||
currentScreen.screen.onButtonPressed(button)
|
||||
end
|
||||
currentScreen:handleButtonInput(button)
|
||||
end
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
local Dim = require("common.dimensions")
|
||||
local Wallpaper = require("components.wallpaper")
|
||||
local BootPage = require("titlescreen.pages.boot.bootpage")
|
||||
local PageView = require("api.page.pageview")
|
||||
require "common.globals"
|
||||
require "common.class"
|
||||
local Screen = require "titlescreen.screen"
|
||||
local BootPage = require "titlescreen.pages.boot.bootpage"
|
||||
local PageView = require "api.page.pageview"
|
||||
local SplashScreen = require "titlescreen.splash"
|
||||
|
||||
local bootpage = BootPage.new()
|
||||
local pageview = PageView.new(bootpage)
|
||||
---@class BootScreen : Screen
|
||||
---@field bootpage BootPage
|
||||
local BootScreen = {
|
||||
__tostring = function() return "BootScreen" end
|
||||
}
|
||||
|
||||
local function render(deltaTime)
|
||||
Dim.updateResolution()
|
||||
---Create a new BootScreen instance
|
||||
---@param o? BootScreen
|
||||
---@return BootScreen
|
||||
function BootScreen.new(o)
|
||||
o = o or {}
|
||||
|
||||
Wallpaper.render()
|
||||
o.bootpage = o.bootpage or BootPage.new()
|
||||
|
||||
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
|
||||
return CreateInstance(BootScreen, o, Screen)
|
||||
end
|
||||
|
||||
local function onButtonPressed(button)
|
||||
pageview:get():handleButtonInput(button)
|
||||
function BootScreen:init()
|
||||
self.pageview:replace(self.bootpage)
|
||||
end
|
||||
|
||||
return {render = render, onButtonPressed = onButtonPressed}
|
||||
function BootScreen:deactivate()
|
||||
self.onDeactivation({reason = "deactivation", hint = tostring(SplashScreen)})
|
||||
end
|
||||
|
||||
return BootScreen
|
|
@ -349,11 +349,17 @@ local function tickTransitions(deltaTime)
|
|||
end
|
||||
end
|
||||
|
||||
local PageView = require "api.page.pageview"
|
||||
local ModeSelectPage = require "titlescreen.pages.modeselect.modeselectpage"
|
||||
local PageViewInstance = PageView.new(ModeSelectPage.new())
|
||||
|
||||
local function render(deltaTime)
|
||||
--[[
|
||||
if not playedBgm then
|
||||
game.PlaySample(resources.audiosamples.bgm, true)
|
||||
playedBgm = true
|
||||
end
|
||||
]]
|
||||
|
||||
game.SetSkinSetting("_currentScreen", "title")
|
||||
|
||||
|
@ -365,7 +371,8 @@ local function render(deltaTime)
|
|||
|
||||
tickTransitions(deltaTime)
|
||||
|
||||
draw_titlescreen(deltaTime)
|
||||
--draw_titlescreen(deltaTime)
|
||||
PageViewInstance:render(deltaTime)
|
||||
|
||||
if (triggerServiceMenu) then
|
||||
triggerServiceMenu = false
|
||||
|
@ -373,6 +380,10 @@ local function render(deltaTime)
|
|||
end
|
||||
end
|
||||
|
||||
local function reset()
|
||||
PageViewInstance:get():init()
|
||||
end
|
||||
|
||||
local function callButtonAction()
|
||||
if buttons[cursorIndex].action == nil then setButtonActions() end
|
||||
buttons[cursorIndex].action()
|
||||
|
@ -459,6 +470,7 @@ end
|
|||
|
||||
return {
|
||||
render = render,
|
||||
reset = reset,
|
||||
onKnobsChange = onKnobsChange,
|
||||
onButtonPressed = onButtonPressed,
|
||||
onMousePressed = onMousePressed,
|
||||
|
|
|
@ -5,6 +5,7 @@ local AudioSample = require "api.audiosample"
|
|||
local Animation = require "api.animation"
|
||||
local Page = require "api.page.page"
|
||||
|
||||
local Background = require "components.background"
|
||||
local Footer = require "components.footer"
|
||||
local Header = require "components.headers.modeSelectHeader"
|
||||
|
||||
|
@ -13,6 +14,7 @@ local crew = game.GetSkinSetting("single_idol")
|
|||
---@class ModeSelectPage: Page
|
||||
---@field _idolAnimationState AnimationState
|
||||
local ModeSelectPage = {
|
||||
__tostring = function () return "ModeSelectPage" end,
|
||||
images = {
|
||||
selectorBgImage = gfx.CreateSkinImage("titlescreen/selector_bg.png", 0),
|
||||
selectorArrowsImage = gfx.CreateSkinImage("titlescreen/selector_arrows.png", 0),
|
||||
|
@ -40,15 +42,18 @@ local ModeSelectPage = {
|
|||
}
|
||||
|
||||
function ModeSelectPage.new(o)
|
||||
local this = CreateInstance(ModeSelectPage, o, Page)
|
||||
local self = CreateInstance(ModeSelectPage, o, Page)
|
||||
|
||||
this._idolAnimationState = this.anims.idolAnimation:start()
|
||||
this.audiosamples.bgm:play()
|
||||
return self
|
||||
end
|
||||
|
||||
return this
|
||||
function ModeSelectPage:init()
|
||||
self._idolAnimationState = self.anims.idolAnimation:start()
|
||||
self.audiosamples.bgm:play()
|
||||
end
|
||||
|
||||
function ModeSelectPage:drawBackground(deltaTime)
|
||||
Background.draw(deltaTime)
|
||||
self._idolAnimationState:render(deltaTime)
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
require "common.globals"
|
||||
require "common.class"
|
||||
|
||||
local PageView = require "api.page.pageview"
|
||||
|
||||
---@class Screen
|
||||
---@field pageview PageView
|
||||
local Screen = {
|
||||
__tostring = function() return "Screen" end
|
||||
}
|
||||
|
||||
---Create a new Screen instance
|
||||
---@param o? Screen
|
||||
---@return Screen
|
||||
function Screen.new(o)
|
||||
local self = CreateInstance(Screen, o)
|
||||
self.pageview = PageView.new()
|
||||
return self
|
||||
end
|
||||
|
||||
---Initialize screen, override to push new page into pageview
|
||||
function Screen:init()
|
||||
|
||||
end
|
||||
|
||||
---@param button integer # options are under the `game` table prefixed with `BUTTON`
|
||||
function Screen:handleButtonInput(button)
|
||||
if self.pageview:get() then
|
||||
self.pageview:get():handleButtonInput(button)
|
||||
end
|
||||
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)
|
||||
function Screen:handleKnobInput(knob, delta)
|
||||
if self.pageview:get() then
|
||||
self.pageview:get():handleKnobInput(knob, delta)
|
||||
end
|
||||
end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param button integer # `0` = Left, `1` = Right, `2` = Middle
|
||||
function Screen:handleMouseInput(x, y, button)
|
||||
if self.pageview:get() then
|
||||
self.pageview:get():handleMouseInput(x, y, button)
|
||||
end
|
||||
end
|
||||
|
||||
---@class ScreenCallbackObject
|
||||
---@field reason string # short string representation what the cb object is about
|
||||
---@field hint any # hint object to help continue code flow in parent
|
||||
|
||||
---Event callback when screen gets deactivated (eg.: pageview is empty)
|
||||
---@param obj ScreenCallbackObject
|
||||
function Screen.onDeactivation(obj)
|
||||
|
||||
end
|
||||
|
||||
function Screen:deactivate()
|
||||
self.onDeactivation({reason = "deactivation"})
|
||||
end
|
||||
|
||||
---@param deltaTime number # frametime in seconds
|
||||
function Screen:render(deltaTime)
|
||||
if not self.pageview:get() then
|
||||
self:deactivate()
|
||||
end
|
||||
|
||||
self.pageview:render(deltaTime)
|
||||
end
|
||||
|
||||
return Screen
|
Loading…
Reference in New Issue