Merge branch 'titlescreen-refactor' of git.hersi.changeip.net:hersi/ExperimentalGear into titlescreen-refactor
This commit is contained in:
commit
ca2d979fcf
|
@ -18,23 +18,34 @@ HitStat = {}
|
|||
---@field type integer -- `1 = Normal` default, `2 = Hard` default values halved
|
||||
HitWindow = {}
|
||||
|
||||
---@class Score
|
||||
---@field auto_flags integer # Autoplay flag
|
||||
---@class HiddenSudden
|
||||
---@field hiddenCutoff number
|
||||
---@field hiddenFade number
|
||||
---@field showCover boolean # Cover beatmap
|
||||
---@field suddenCutoff number
|
||||
---@field suddenFade number
|
||||
HiddenSudden = {}
|
||||
|
||||
---@class HighScore
|
||||
---@field auto_flags integer # Only Singleplayer, Autoplay flag
|
||||
---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain
|
||||
---@field flags integer # Only Multiplayer, Autoplay flag
|
||||
---@field gauge number # Ending gauge percentage, `0.0` to `1.0`
|
||||
---@field gauge_option integer # Gauge option e.g. ARS
|
||||
---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive
|
||||
---@field gauge_option integer # Only Singleplayer, Gauge option e.g. ARS
|
||||
---@field gauge_type integer # Only Singleplayer, `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive
|
||||
---@field goods integer # Total near hits
|
||||
---@field hitWindow HitWindow|nil # Hit windows of the score, only for singleplayer results screen
|
||||
---@field mirror integer # Mirror mode flag
|
||||
---@field hitWindow nil|HitWindow # Only Singleplayer, Hit windows of the score
|
||||
---@field isLocal boolean # Only Singleplayer, Whether this score was set locally
|
||||
---@field mirror integer # Only Singleplayer, Mirror mode flag
|
||||
---@field misses integer # Total errors
|
||||
---@field name nil|string # Only for multiplayer results, name of the player
|
||||
---@field name string # Only Multiplayer, player name
|
||||
---@field perfects integer # Total critical hits
|
||||
---@field random integer # Random mode flag
|
||||
---@field playerName string # Only Singleplayer, Player name
|
||||
---@field random integer # Only Singleplayer, Random mode flag
|
||||
---@field score integer # Result score
|
||||
---@field timestamp integer # Unix timestamp of the score
|
||||
---@field uid nil|string # Only for multiplayer results, UID of the player
|
||||
Score = {}
|
||||
HighScore = {};
|
||||
|
||||
---@class ChartResult : result
|
||||
---@field passed boolean # Whether or not challenge requirements were met for this chart
|
||||
|
@ -42,27 +53,30 @@ Score = {}
|
|||
ChartResult = {}
|
||||
|
||||
---@class ServerScoreOptions
|
||||
---@field gaugeType integer # An enum value representing the gauge type used. 0 = normal, 1 = hard. Further values are not currently specified.
|
||||
---@field autoFlags integer # A bitfield of elements of the game that are automated. Any non-zero value means that the score was at least partially auto.
|
||||
---@field gaugeOpt integer # Reserved
|
||||
---@field gaugeType integer # An enum value representing the gauge type used. 0 = normal, 1 = hard. Further values are not currently specified.
|
||||
---@field mirror boolean # Mirror mode enabled
|
||||
---@field random boolean # Note shuffle enabled
|
||||
---@field autoFlags integer # A bitfield of elements of the game that are automated. Any non-zero value means that the score was at least partially auto.
|
||||
ServerScoreOptions = {}
|
||||
|
||||
---@class ServerScore
|
||||
---@field score integer # Submitted score
|
||||
---@field gauge number # Submitted Gauge result
|
||||
---@field timestamp integer # Unix timestamp of the score
|
||||
---@field crit integer # Hits inside the critical window
|
||||
---@field near integer # Hits inside the near window
|
||||
---@field early integer # Hits inside the near window which were early
|
||||
---@field late integer # Hits inside the near window which were late
|
||||
---@field combo integer # Best combo reached
|
||||
---@field crit integer # Hits inside the critical window
|
||||
---@field early integer # Hits inside the near window which were early
|
||||
---@field error integer # Missed notes
|
||||
---@field gauge number # Submitted Gauge result
|
||||
---@field justSet boolean # This score belongs to the current player, and is the score that was just achieved
|
||||
---@field lamp integer # `badge`
|
||||
---@field late integer # Hits inside the near window which were late
|
||||
---@field near integer # Hits inside the near window
|
||||
---@field options ServerScoreOptions # The options in use. Includes gauge type, etc.
|
||||
---@field ranking integer # Online leaderboard ranking
|
||||
---@field score integer # Submitted score
|
||||
---@field timestamp integer # Unix timestamp of the score
|
||||
---@field username string # Online player name
|
||||
---@field windows table # {perfect, good, hold, miss, slam} hit windows in milliseconds
|
||||
---@field yours boolean # This score belongs to the current player
|
||||
---@field justSet boolean # This score belongs to the current player, and is the score that was just achieved
|
||||
ServerScore = {}
|
||||
|
||||
---@class result
|
||||
|
@ -92,16 +106,17 @@ ServerScore = {}
|
|||
---@field gaugeSamples number[] # Gauge values sampled (256 total) throughout the play
|
||||
---@field goods integer # Total near hits
|
||||
---@field grade string # Result grade
|
||||
---@field highScores Score[] # All scores
|
||||
---@field hidsud nil|HiddenSudden # Hidden-Sudden options
|
||||
---@field highScores HighScore[] # All scores
|
||||
---@field hitWindow HitWindow # Result hit windows
|
||||
---@field holdHitStats HitStat[]|nil # Hit stats for every hold object, only available for singleplayer if `isSelf = true`
|
||||
---@field holdHitStats nil|HitStat[] # Hit stats for every hold object, only available for singleplayer if `isSelf = true`
|
||||
---@field illustrator string # Chart jacket illustrator
|
||||
---@field irState integer # Current state of the IR score submission request (a USC-IR code, including extensions 0/10/60)
|
||||
---@field irDescription string # The description in the IR response (nil if irState is 0 or 10)
|
||||
---@field irScores ServerScore[]|nil # Score submission result, nil if irState != 20
|
||||
---@field isSelf boolean # Only for multiplayer, `false` if score is of another player
|
||||
---@field irDescription nil|string # The description in the IR response (nil if irState is 0 or 10)
|
||||
---@field irScores nil|ServerScore[] # Score submission result, nil if irState != 20
|
||||
---@field isSelf boolean # `false` if score is of another player
|
||||
---@field jacketPath string # Full filepath to the jacket image on the disk
|
||||
---@field laserHitStats HitStat[]|nil # Hit stats for every laser object, only available for singleplayer if `isSelf = true`
|
||||
---@field laserHitStats nil|HitStat[] # Hit stats for every laser object, only available for singleplayer if `isSelf = true`
|
||||
---@field lates integer # Total late hits
|
||||
---@field level integer # Chart or challenge level
|
||||
---@field maxCombo integer # Result max chain
|
||||
|
@ -112,7 +127,7 @@ ServerScore = {}
|
|||
---@field mirror boolean # Mirror mode bool
|
||||
---@field misses integer # Total errors
|
||||
---@field mission string # Only for practice mode
|
||||
---@field noteHitStats HitStat[]|nil # Hit stats for every chip hit, only available for singleplayer if `isSelf = true`
|
||||
---@field noteHitStats nil|HitStat[] # Hit stats for every chip hit, only available for singleplayer if `isSelf = true`
|
||||
---@field overallCrits integer # Only for challenge results, total number of critical hits across the charts
|
||||
---@field overallErrors integer # Only for challenge results, total number of error hits across the charts
|
||||
---@field overallNears integer # Only for challenge results, total number of near hits across the charts
|
||||
|
@ -125,8 +140,8 @@ ServerScore = {}
|
|||
---@field requirement_text string # Only for challenge results, the challenge requirements separated by newline character `"\n"`
|
||||
---@field retryCount integer # Only for practice mode
|
||||
---@field score integer # Result score
|
||||
---@field speedModType integer # Only for singleplayer, `0` = XMOD, `1` = MMOD, `2` = CMOD
|
||||
---@field speedModValue number # Only for singleplayer, `HiSpeed` for `XMOD`, `ModSpeed` otherwise
|
||||
---@field speedModType nil|integer # Only for singleplayer, `0` = XMOD, `1` = MMOD, `2` = CMOD
|
||||
---@field speedModValue nil|number # Only for singleplayer, `HiSpeed` for `XMOD`, `ModSpeed` otherwise
|
||||
---@field title string # Chart (with player name in multiplayer) or challenge title
|
||||
---@field uid nil|string # Only for multiplayer, UID of the player
|
||||
result = {}
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
-- songwheel `songwheel` table
|
||||
|
||||
---@class Song
|
||||
---@field artist string # Chart artist
|
||||
---@field difficulties Difficulty[] # Array of difficulties for the current song
|
||||
---@field bpm string # Chart BPM
|
||||
---@field id integer # Song id, unique static identifier
|
||||
---@field path string # Full filepath to the chart folder on the disk
|
||||
---@field title string # Chart title
|
||||
Song = {};
|
||||
|
||||
---@class Difficulty
|
||||
---@field difficulty integer # Difficulty index
|
||||
---@field effector string # Effector name
|
||||
---@field hash string # Difficulty hash
|
||||
---@field id integer # Difficulty id, unique static identifier
|
||||
---@field illustrator string # Difficulty jacket illustrator
|
||||
|
@ -11,31 +21,30 @@
|
|||
---@field topBadge integer # `0 = Never Played`, `1 = Played`, `2 = Cleared`, `3 = Hard Cleared`, `4 = Full Chain`, `5 = Perfect Chain`
|
||||
Difficulty = {}
|
||||
|
||||
---@class Song
|
||||
---@field artist string # Chart artist
|
||||
---@field difficulties Difficulty[] # Array of difficulties for the current song
|
||||
---@field bpm number # Chart BPM
|
||||
---@field id integer # Song id, unique static identifier
|
||||
---@field path string # Full filepath to the chart folder on the disk
|
||||
---@field title string # Chart title
|
||||
Song = {}
|
||||
---@class Score
|
||||
---@field auto_flags integer # Autoplay flag
|
||||
---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain
|
||||
---@field combo integer # Longest combo
|
||||
---@field earlies integer # Early hits
|
||||
---@field gauge number # Ending gauge percentage, `0.0` to `1.0`
|
||||
---@field gauge_option integer # Gauge option e.g. ARS
|
||||
---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive
|
||||
---@field goods integer # Total near hits
|
||||
---@field isLocal boolean # Whether this score was set locally
|
||||
---@field lates integer # Late hits
|
||||
---@field mirror integer # Mirror mode flag
|
||||
---@field misses integer # Total errors
|
||||
---@field perfects integer # Total critical hits
|
||||
---@field playerName string # Player name
|
||||
---@field random integer # Random mode flag
|
||||
---@field score integer # Result score
|
||||
---@field timestamp integer # Unix timestamp of the score
|
||||
Score = {};
|
||||
|
||||
---@class songwheel
|
||||
---@field allSongs Song[] # Array of all available songs
|
||||
---@field searchInputActive boolean # Search status
|
||||
---@field searchInputActive boolean # Whether the user is currently inputting search text
|
||||
---@field searchStatus string # Current song database status
|
||||
---@field searchText string # Search input text
|
||||
---@field searchText string # Current string used by the song search
|
||||
---@field songs Song[] # Array of songs with the current filters/sorting applied
|
||||
songwheel = {}
|
||||
|
||||
---Set difficulty index
|
||||
---@param diff integer diff index
|
||||
function set_diff(diff) end
|
||||
|
||||
---Function called by the game when ``songs`` or ``allSongs`` (if withAll == true) is changed.
|
||||
---@param allSongs boolean
|
||||
function songs_changed(allSongs) end
|
||||
|
||||
---Function called by the game to get how much to scroll when page up or page down are pressed.
|
||||
---Needs to be defined for the game to work properly.
|
||||
function get_page_size() end
|
||||
songwheel = {};
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
---@diagnostic disable: duplicate-set-field
|
||||
require "common.globals"
|
||||
require "api.logging"
|
||||
|
||||
require("core.string")
|
||||
|
||||
|
@ -35,7 +37,7 @@ end
|
|||
function filesys.exists(path)
|
||||
local ok, err, code = os.rename(path, path)
|
||||
if not ok then
|
||||
game.Log("err: "..err..", code: "..code, game.LOGGER_DEBUG)
|
||||
DetailedLog("err: "..err..", code: "..code, game.LOGGER_DEBUG)
|
||||
if code == 13 then
|
||||
-- Permission denied, but it exists
|
||||
return true
|
||||
|
@ -44,6 +46,20 @@ function filesys.exists(path)
|
|||
return ok, err
|
||||
end
|
||||
|
||||
---Returns a path relative to the current working directory from a texture path
|
||||
---@param path string # must be a path accepted by game.CreateSkinImage and such
|
||||
---@return string
|
||||
function FileSys.fromTexturePath(path)
|
||||
--skins/<skin>/textures/<path>
|
||||
local relpath = FileSys.join("skins", game.GetSkin(), "textures", FileSys.normpath(path))
|
||||
|
||||
if not FileSys.exists(FileSys.join(FileSys.getcwd(), relpath)) then
|
||||
DetailedLog("'"..relpath.."' does not exist", game.LOGGER_ERROR)
|
||||
end
|
||||
|
||||
return relpath
|
||||
end
|
||||
|
||||
---Return a string representing the current working directory
|
||||
---@return string
|
||||
function filesys.getcwd()
|
||||
|
@ -68,9 +84,10 @@ end
|
|||
|
||||
---Normalize `path`, collapse redundant separators and up references
|
||||
---@param path string
|
||||
---@param overrideSep? string
|
||||
---@return string
|
||||
function filesys.normpath(path)
|
||||
local sep = filesys.sep
|
||||
function filesys.normpath(path, overrideSep)
|
||||
local sep = overrideSep or filesys.sep
|
||||
|
||||
--remove multiple slashes
|
||||
path = path:gsub("("..sep..")"..sep.."+", "%1")
|
||||
|
@ -83,7 +100,7 @@ function filesys.normpath(path)
|
|||
local upRefPattern = "%w+"..sep.."%.%."..sep
|
||||
repeat
|
||||
path, count = path:gsub(upRefPattern, "")
|
||||
until count ~= 0
|
||||
until count == 0
|
||||
|
||||
--remove last slash
|
||||
path = path:gsub("(.-)"..sep.."$", "%1")
|
||||
|
|
|
@ -1,25 +1,16 @@
|
|||
require "api.logging"
|
||||
|
||||
require "common.class"
|
||||
|
||||
require "api.filesys"
|
||||
|
||||
require "api.graphics"
|
||||
|
||||
local Image = require "scripts.graphics.image"
|
||||
|
||||
---@class AnimationParams
|
||||
---@field fps number?
|
||||
---@field loop boolean?
|
||||
---@field loopPoint integer?
|
||||
---@field width number?
|
||||
---@field height number?
|
||||
---@field x number?
|
||||
---@field y number?
|
||||
---@field scaleX number?
|
||||
---@field scaleY number?
|
||||
---@field centered boolean?
|
||||
---@field blendOp integer?
|
||||
---@field color number[]?
|
||||
---@field alpha number?
|
||||
---@field stroke StrokeParams?
|
||||
---@class AnimationParam: Animation
|
||||
---@field animPath string
|
||||
---@field animFPS number
|
||||
|
||||
---@class Animation
|
||||
---@field frames Image[]
|
||||
|
@ -38,7 +29,7 @@ local Image = require "scripts.graphics.image"
|
|||
---@field color number[]?
|
||||
---@field alpha number?
|
||||
---@field stroke StrokeParams?
|
||||
local Animation = { };
|
||||
local Animation = { }
|
||||
|
||||
---@class AnimationState
|
||||
---@field animation Animation # The animation data this state is playing through
|
||||
|
@ -46,72 +37,61 @@ local Animation = { };
|
|||
---@field timer number # Timer used to determine when to change to the next frame
|
||||
---@field running boolean # Is the animation currently running and accepting updates?
|
||||
---@field callback function? # Called when the animation completes
|
||||
local AnimationState = { };
|
||||
local AnimationState = { }
|
||||
|
||||
---Load Animation Frames from path
|
||||
---@param animPath string
|
||||
---@return Image[]
|
||||
---@return integer
|
||||
local function loadSequentialAnimationFrames(animPath)
|
||||
local frames = { };
|
||||
local count = 0;
|
||||
local frames = { } ---@type Image[]
|
||||
local count = 0
|
||||
|
||||
local detectedFormat = nil;
|
||||
local anim_files = filesys.scandir(filesys.fromTexturePath(animPath))
|
||||
|
||||
while (true) do
|
||||
local frame = nil;
|
||||
if (detectedFormat) then
|
||||
frame = Image.new(detectedFormat:format(animPath, count + 1), true);
|
||||
else
|
||||
for i = 1, 4 do
|
||||
local format = '%s/%0' .. i .. 'd.png';
|
||||
frame = Image.new(format:format(animPath, count + 1), true);
|
||||
for index, frame_path in ipairs(anim_files) do
|
||||
frame_path = filesys.join(filesys.normpath(animPath), frame_path)
|
||||
DetailedLog("Frame "..index..": '"..frame_path.."'", game.LOGGER_DEBUG)
|
||||
local frame = Image.new(frame_path, true)
|
||||
|
||||
if (frame) then
|
||||
detectedFormat = format;
|
||||
break;
|
||||
end
|
||||
end
|
||||
if not frame then
|
||||
DetailedLog("Could not load frame image '"..frame_path.."'", game.LOGGER_ERROR)
|
||||
break
|
||||
end
|
||||
|
||||
if (not frame) then
|
||||
break;
|
||||
frames[index] = frame
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
count = count + 1;
|
||||
frames[count] = frame;
|
||||
end
|
||||
|
||||
return frames, count;
|
||||
return frames, count
|
||||
end
|
||||
|
||||
---Animation constructor
|
||||
---@param animPath string
|
||||
---@param params AnimationParams
|
||||
---@param params AnimationParam
|
||||
---@return Animation
|
||||
function Animation.new(animPath, params)
|
||||
function Animation.new(params)
|
||||
local self = CreateInstance(Animation, params)
|
||||
|
||||
local frames, frameCount = loadSequentialAnimationFrames(animPath);
|
||||
self.frames, self.frameCount = loadSequentialAnimationFrames(params.animPath)
|
||||
|
||||
local instance = {
|
||||
frames = frames,
|
||||
frameCount = frameCount,
|
||||
self.frameTime = 1 / (params.animFPS or 30)
|
||||
self.loop = params.loop or false
|
||||
self.loopPoint = params.loopPoint or 1
|
||||
|
||||
frameTime = 1 / (params.fps or 30),
|
||||
loop = params.loop or false,
|
||||
loopPoint = params.loopPoint or 1,
|
||||
};
|
||||
self.width = params.width
|
||||
self.height = params.height
|
||||
self.x = params.x
|
||||
self.y = params.y
|
||||
self.scaleX = params.scaleX
|
||||
self.scaleY = params.scaleY
|
||||
self.centered = params.centered
|
||||
self.blendOp = params.blendOp
|
||||
self.color = params.color
|
||||
self.alpha = params.alpha
|
||||
self.stroke = params.stroke
|
||||
|
||||
if (params.width ~= nil) then instance.width = params.width; end
|
||||
if (params.height ~= nil) then instance.height = params.height; end
|
||||
if (params.x ~= nil) then instance.x = params.x; end
|
||||
if (params.y ~= nil) then instance.y = params.y; end
|
||||
if (params.scaleX ~= nil) then instance.scaleX = params.scaleX; end
|
||||
if (params.scaleY ~= nil) then instance.scaleY = params.scaleY; end
|
||||
if (params.centered ~= nil) then instance.centered = params.centered; end
|
||||
if (params.blendOp ~= nil) then instance.blendOp = params.blendOp; end
|
||||
if (params.color ~= nil) then instance.color = params.color; end
|
||||
if (params.alpha ~= nil) then instance.alpha = params.alpha; end
|
||||
if (params.stroke ~= nil) then instance.stroke = params.stroke; end
|
||||
|
||||
return CreateInstance(Animation, instance);
|
||||
return self
|
||||
end
|
||||
|
||||
---Create an AnimationState to play this animation.
|
||||
|
@ -120,85 +100,85 @@ end
|
|||
---@return AnimationState
|
||||
function Animation:createState(callback)
|
||||
---@type AnimationState
|
||||
local state = { animation = self, callback = callback, frameIndex = 1, timer = 0, running = false };
|
||||
return CreateInstance(AnimationState, state);
|
||||
local state = { animation = self, callback = callback, frameIndex = 1, timer = 0, running = false }
|
||||
return CreateInstance(AnimationState, state)
|
||||
end
|
||||
|
||||
---Create an AnimationState to play this animation and start it.
|
||||
---@param callback function?
|
||||
---@return AnimationState
|
||||
function Animation:start(callback)
|
||||
local state = self:createState(callback);
|
||||
state:start();
|
||||
local state = self:createState(callback)
|
||||
state:start()
|
||||
|
||||
return state;
|
||||
return state
|
||||
end
|
||||
|
||||
---Start this AnimationState.
|
||||
---Does nothing if it's already running.
|
||||
function AnimationState:start()
|
||||
self.running = true;
|
||||
self.running = true
|
||||
end
|
||||
|
||||
---Restart this AnimationState.
|
||||
---The frame index is reset to 1.
|
||||
function AnimationState:restart()
|
||||
self.running = true;
|
||||
self.frameIndex = 1;
|
||||
self.timer = 0;
|
||||
self.running = true
|
||||
self.frameIndex = 1
|
||||
self.timer = 0
|
||||
end
|
||||
|
||||
---Stop this AnimationState.
|
||||
function AnimationState:stop()
|
||||
self.running = false;
|
||||
self.running = false
|
||||
end
|
||||
|
||||
---Updates this AnimationState and then renders it, passing on the given ImageParams to each frame.
|
||||
---@param deltaTime number
|
||||
---@param params? ImageParams
|
||||
function AnimationState:render(deltaTime, params)
|
||||
if (not self.running) then return; end;
|
||||
if (not self.running) then return end
|
||||
|
||||
self.timer = self.timer + deltaTime;
|
||||
self.timer = self.timer + deltaTime
|
||||
|
||||
while (self.timer > self.animation.frameTime) do
|
||||
self.timer = self.timer - self.animation.frameTime;
|
||||
self.frameIndex = self.frameIndex + 1;
|
||||
self.timer = self.timer - self.animation.frameTime
|
||||
self.frameIndex = self.frameIndex + 1
|
||||
|
||||
if (self.frameIndex > self.animation.frameCount) then
|
||||
if (self.animation.loop) then
|
||||
self.frameIndex = self.animation.loopPoint;
|
||||
self.frameIndex = self.animation.loopPoint
|
||||
else
|
||||
self.running = false;
|
||||
self.running = false
|
||||
|
||||
if (self.callback) then
|
||||
self.callback();
|
||||
self.callback()
|
||||
end
|
||||
|
||||
return;
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (params) then
|
||||
if (params.width == nil) then params.width = self.animation.width; end
|
||||
if (params.height == nil) then params.height = self.animation.height; end
|
||||
if (params.x == nil) then params.x = self.animation.x; end
|
||||
if (params.y == nil) then params.y = self.animation.y; end
|
||||
if (params.scaleX == nil) then params.scaleX = self.animation.scaleX; end
|
||||
if (params.scaleY == nil) then params.scaleY = self.animation.scaleY; end
|
||||
if (params.centered == nil) then params.centered = self.animation.centered; end
|
||||
if (params.blendOp == nil) then params.blendOp = self.animation.blendOp; end
|
||||
if (params.alpha == nil) then params.alpha = self.animation.alpha; end
|
||||
if (params.stroke == nil) then params.stroke = self.animation.stroke; end
|
||||
if (params.width == nil) then params.width = self.animation.width end
|
||||
if (params.height == nil) then params.height = self.animation.height end
|
||||
if (params.x == nil) then params.x = self.animation.x end
|
||||
if (params.y == nil) then params.y = self.animation.y end
|
||||
if (params.scaleX == nil) then params.scaleX = self.animation.scaleX end
|
||||
if (params.scaleY == nil) then params.scaleY = self.animation.scaleY end
|
||||
if (params.centered == nil) then params.centered = self.animation.centered end
|
||||
if (params.blendOp == nil) then params.blendOp = self.animation.blendOp end
|
||||
if (params.alpha == nil) then params.alpha = self.animation.alpha end
|
||||
if (params.stroke == nil) then params.stroke = self.animation.stroke end
|
||||
end
|
||||
|
||||
local frame = self.animation.frames[self.frameIndex];
|
||||
local frame = self.animation.frames[self.frameIndex]
|
||||
if (not frame) then
|
||||
-- TODO(local): what do
|
||||
else
|
||||
frame:render(params);
|
||||
frame:render(params)
|
||||
end
|
||||
end
|
||||
|
||||
return Animation;
|
||||
return Animation
|
||||
|
|
|
@ -4,50 +4,18 @@ local Display = require "scripts.graphics.display"
|
|||
local Wallpaper = require "components.wallpaper"
|
||||
|
||||
local PageView = require "api.page.pageview"
|
||||
local PageManager = require "api.page.pagemanager"
|
||||
local PageRegistry = require "api.page.pageregistry"
|
||||
|
||||
local BootPage = require "titlescreen.boot"
|
||||
local CheckUpdatePage = require "titlescreen.boot.checkupdatepage"
|
||||
|
||||
local SplashPage = require "titlescreen.splash"
|
||||
local KShootManiaPage = require "titlescreen.splash.kshootmaniapage"
|
||||
local USCPage = require "titlescreen.splash.uscpage"
|
||||
local TeamExceedPage = require "titlescreen.splash.teamexceedpage"
|
||||
local CreditsPage = require "titlescreen.splash.creditspage"
|
||||
|
||||
local TitlePage = require "titlescreen.title"
|
||||
|
||||
local MainMenuPage = require "titlescreen.mainmenu"
|
||||
|
||||
local ServiceMenuPage = require "titlescreen.service"
|
||||
local InputCheckPage = require "titlescreen.service.inputcheckpage"
|
||||
local ScreenCheckPage = require "titlescreen.service.screencheckpage"
|
||||
local ColorCheckPage = require "titlescreen.service.colorcheckpage"
|
||||
local VersionInfoPage = require "titlescreen.service.versioninfopage"
|
||||
|
||||
local pageView = PageView.new()
|
||||
|
||||
local pageManager = PageManager.get()
|
||||
|
||||
pageManager:storePage(CheckUpdatePage.new())
|
||||
pageManager:storePage(BootPage.new())
|
||||
|
||||
pageManager:storePage(KShootManiaPage.new())
|
||||
pageManager:storePage(USCPage.new())
|
||||
pageManager:storePage(TeamExceedPage.new())
|
||||
pageManager:storePage(CreditsPage.new())
|
||||
pageManager:storePage(SplashPage.new())
|
||||
|
||||
pageManager:storePage(TitlePage.new())
|
||||
|
||||
pageManager:storePage(MainMenuPage.new())
|
||||
|
||||
pageManager:storePage(InputCheckPage.new())
|
||||
pageManager:storePage(ScreenCheckPage.new())
|
||||
pageManager:storePage(ColorCheckPage.new())
|
||||
pageManager:storePage(VersionInfoPage.new())
|
||||
pageManager:storePage(ServiceMenuPage.new())
|
||||
|
||||
pageView.onNavigated = function(self, back)
|
||||
game.Log(tostring(self) .. " navigated " .. (back and "back " or "") .. "to: " .. tostring(pageView:get()),
|
||||
game.LOGGER_INFO
|
||||
|
@ -58,41 +26,40 @@ pageView.onEmptied = function(self)
|
|||
game.Log(tostring(self) .. " empty!", game.LOGGER_WARNING)
|
||||
end
|
||||
|
||||
local pages = PageManager.get().pages
|
||||
pageManager:getPage(BootPage).onInvalidation = function(self, toVersionPage)
|
||||
PageRegistry:getOrCreatePage(BootPage).onInvalidation = function(self, toVersionPage)
|
||||
if toVersionPage then
|
||||
pageView:replace(pageManager:getPage(ServiceMenuPage))
|
||||
pageView:replace(PageRegistry:getOrCreatePage(ServiceMenuPage))
|
||||
pageView:get():init()
|
||||
pageView:navigate(pageManager:getPage(VersionInfoPage))
|
||||
pageView:navigate(PageRegistry:getOrCreatePage(VersionInfoPage))
|
||||
pageView:get():init()
|
||||
else
|
||||
pageView:replace(pageManager:getPage(SplashPage))
|
||||
pageView:replace(PageRegistry:getOrCreatePage(SplashPage))
|
||||
pageView:get():init()
|
||||
end
|
||||
end
|
||||
|
||||
pageManager:getPage(SplashPage).onInvalidation = function(self)
|
||||
pageView:replace(pageManager:getPage(TitlePage))
|
||||
PageRegistry:getOrCreatePage(SplashPage).onInvalidation = function(self)
|
||||
pageView:replace(PageRegistry:getOrCreatePage(TitlePage))
|
||||
pageView:get():init()
|
||||
end
|
||||
|
||||
pageManager:getPage(TitlePage).onInvalidation = function(self, toServiceMenu)
|
||||
PageRegistry:getOrCreatePage(TitlePage).onInvalidation = function(self, toServiceMenu)
|
||||
if toServiceMenu then
|
||||
pageView:replace(pageManager:getPage(ServiceMenuPage))
|
||||
pageView:replace(PageRegistry:getOrCreatePage(ServiceMenuPage))
|
||||
pageView:get():init()
|
||||
else
|
||||
pageView:replace(pageManager:getPage(MainMenuPage))
|
||||
pageView:replace(PageRegistry:getOrCreatePage(MainMenuPage))
|
||||
pageView:get():init()
|
||||
end
|
||||
end
|
||||
|
||||
pageManager:getPage(ServiceMenuPage).onInvalidation = function(self)
|
||||
pageView:replace(pageManager:getPage(SplashPage))
|
||||
PageRegistry:getOrCreatePage(ServiceMenuPage).onInvalidation = function(self)
|
||||
pageView:replace(PageRegistry:getOrCreatePage(SplashPage))
|
||||
pageView:get():init()
|
||||
end
|
||||
|
||||
--local currentScreen = game.GetSkinSetting("animations_skipIntro") and screens.title or screens.boot -- show boot screen if skipIntro is not set
|
||||
pageView:replace(pages[BootPage.__name])
|
||||
pageView:replace(PageRegistry:getOrCreatePage(BootPage))
|
||||
pageView:get():init()
|
||||
|
||||
local function deltaKnob(delta)
|
||||
|
|
|
@ -4,7 +4,7 @@ require "common.filereader"
|
|||
local Display = require "scripts.graphics.display"
|
||||
local Version = require "common.version"
|
||||
|
||||
local PageManager = require "api.page.pagemanager"
|
||||
local PageRegistry = require "api.page.pageregistry"
|
||||
|
||||
local Page = require "api.page.page"
|
||||
local CheckUpdatePage = require "titlescreen.boot.checkupdatepage"
|
||||
|
@ -26,10 +26,10 @@ function BootPage.new(params)
|
|||
|
||||
local self = CreateInstance(BootPage, params, Page)
|
||||
|
||||
local pageManager = PageManager.get()
|
||||
local checkUpdatePage = PageRegistry:getOrCreatePage(CheckUpdatePage)
|
||||
self._networkResult = {}
|
||||
|
||||
pageManager:getPage(CheckUpdatePage).onInvalidation = function (page_self, reason)
|
||||
checkUpdatePage.onInvalidation = function (page_self, reason)
|
||||
self:onInvalidation(reason)
|
||||
end
|
||||
|
||||
|
@ -87,7 +87,7 @@ function BootPage.new(params)
|
|||
IR.Heartbeat(function(res) self._networkResult = res end) -- IR doesn't like being called in a coroutine
|
||||
elseif status == SelfTestStatus.PASS or status == SelfTestStatus.OK then
|
||||
if self.viewHandler then
|
||||
self.viewHandler:navigate(pageManager:getPage(CheckUpdatePage))
|
||||
self.viewHandler:navigate(checkUpdatePage)
|
||||
self.viewHandler:get():init()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
---Return a string representation of where this function was called from
|
||||
---@param affix? string
|
||||
---@param stack_level? integer
|
||||
---@return string
|
||||
function Where(affix, stack_level)
|
||||
stack_level = stack_level or 2
|
||||
|
||||
local fun_name = debug.getinfo(stack_level, "n").name
|
||||
|
||||
local current_file = debug.getinfo(stack_level, "S").source
|
||||
local current_line = debug.getinfo(stack_level, "l").currentline
|
||||
|
||||
--remove redundant path components
|
||||
current_file = current_file:gsub("([@=]?).*[\\/]skins[\\/]", "%1")
|
||||
|
||||
local where = current_file..":"..current_line
|
||||
|
||||
if fun_name then
|
||||
where = where.." ("..fun_name..")"
|
||||
end
|
||||
|
||||
if affix then
|
||||
where = where..affix
|
||||
end
|
||||
|
||||
return where
|
||||
end
|
||||
|
||||
---Same as game.Log, but prefixed with where the call happened
|
||||
---@param message string
|
||||
---@param severity integer
|
||||
function DetailedLog(message, severity)
|
||||
game.Log(Where(": ", 3)..message, severity)
|
||||
end
|
|
@ -1,36 +1,21 @@
|
|||
require "common.globals"
|
||||
require "common.class"
|
||||
|
||||
---@type PageRegistry
|
||||
local instance = nil
|
||||
require "api.logging"
|
||||
|
||||
---@class PageRegistry
|
||||
---@field pages Page[]
|
||||
local PageRegistry = {
|
||||
__name = "PageManager"
|
||||
__name = "PageManager",
|
||||
pages = {},
|
||||
}
|
||||
|
||||
---Create new PageManager instance
|
||||
---Reset and initialize PageManager global
|
||||
---@param params? PageRegistry
|
||||
---@return PageRegistry
|
||||
function PageRegistry.new(params)
|
||||
function PageRegistry:init(params)
|
||||
params = params or {}
|
||||
|
||||
local self = CreateInstance(PageRegistry, params)
|
||||
|
||||
self.pages = params.pages or {}
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Get PageManager instance
|
||||
---@return PageRegistry
|
||||
function PageRegistry.get()
|
||||
if not instance then
|
||||
instance = PageRegistry.new()
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
---Store page with default name
|
||||
|
@ -65,4 +50,17 @@ function PageRegistry:getPage(page)
|
|||
return nil
|
||||
end
|
||||
|
||||
---Get page by class
|
||||
---
|
||||
---Ensure valid page instance by creating and registering one, if not found
|
||||
---@param page Page
|
||||
function PageRegistry:getOrCreatePage(page)
|
||||
if not self:getPage(page) then
|
||||
page = page.new()
|
||||
self:register(page)
|
||||
end
|
||||
|
||||
return page
|
||||
end
|
||||
|
||||
return PageRegistry
|
||||
|
|
|
@ -485,11 +485,12 @@ local crew = game.GetSkinSetting("single_idol")
|
|||
local MainMenuPage = {
|
||||
__name = "MainMenuPage",
|
||||
ANIM = {
|
||||
idolAnimation = Animation.new("crew/anim/" .. crew, {
|
||||
fps = 30, loop = true,
|
||||
idolAnimation = Animation.new{
|
||||
animPath = "crew/anim/" .. crew,
|
||||
animFPS = 30, loop = true,
|
||||
centered = true, x = Display.design.width / 2, y = Display.design.height / 2,
|
||||
width = Display.design.width, height = Display.design.height,
|
||||
})
|
||||
}
|
||||
},
|
||||
AUDIO = {
|
||||
bgm = AudioSample.new{path = "titlescreen/bgm.wav", exclusive = true, loop = true},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require("common.class")
|
||||
|
||||
local PageManager = require "api.page.pagemanager"
|
||||
local PageRegistry = require "api.page.pageregistry"
|
||||
|
||||
local ServicePage = require("api.page.servicepage")
|
||||
local InputCheckPage = require("titlescreen.service.inputcheckpage")
|
||||
|
@ -18,7 +18,7 @@ local ServiceMenuPage = {
|
|||
|
||||
---Create a new MainMenuPage instance
|
||||
---@param params? MainMenuPage # initial parameters
|
||||
---@return MainMenuPage
|
||||
---@return ServiceMenuPage
|
||||
function ServiceMenuPage.new(params)
|
||||
params = params or {}
|
||||
|
||||
|
@ -26,12 +26,11 @@ function ServiceMenuPage.new(params)
|
|||
|
||||
local self = CreateInstance(ServiceMenuPage, params, ServicePage)
|
||||
|
||||
local pageManager = PageManager.get()
|
||||
local list = ListField.new()
|
||||
list:addField(ServiceLinkField.new{label = "INPUT CHECK", link = pageManager:getPage(InputCheckPage)})
|
||||
list:addField(ServiceLinkField.new{label = "SCREEN CHECK", link = pageManager:getPage(ScreenCheckPage)})
|
||||
list:addField(ServiceLinkField.new{label = "COLOR CHECK", link = pageManager:getPage(ColorCheckPage)})
|
||||
list:addField(ServiceLinkField.new{label = "VERSION INFORMATION", link = pageManager:getPage(VersionInfoPage)})
|
||||
list:addField(ServiceLinkField.new{label = "INPUT CHECK", link = PageRegistry:getOrCreatePage(InputCheckPage)})
|
||||
list:addField(ServiceLinkField.new{label = "SCREEN CHECK", link = PageRegistry:getOrCreatePage(ScreenCheckPage)})
|
||||
list:addField(ServiceLinkField.new{label = "COLOR CHECK", link = PageRegistry:getOrCreatePage(ColorCheckPage)})
|
||||
list:addField(ServiceLinkField.new{label = "VERSION INFORMATION", link = PageRegistry:getOrCreatePage(VersionInfoPage)})
|
||||
list:refreshFields()
|
||||
|
||||
self:addField(list)
|
||||
|
|
|
@ -4,7 +4,7 @@ local Display = require("scripts.graphics.display")
|
|||
require "common.globals"
|
||||
require "common.class"
|
||||
|
||||
local PageManager = require "api.page.pagemanager"
|
||||
local PageRegistry = require "api.page.pageregistry"
|
||||
|
||||
local Page = require "api.page.page"
|
||||
local KShootManiaPage = require "titlescreen.splash.kshootmaniapage"
|
||||
|
@ -29,14 +29,12 @@ local SplashPage = {
|
|||
function SplashPage.new(params)
|
||||
local self = CreateInstance(SplashPage, params, Page)
|
||||
|
||||
local pageManager = PageManager.get()
|
||||
|
||||
self.currentPage = 0 -- start on nil page
|
||||
self.content = {
|
||||
pageManager:getPage(KShootManiaPage),
|
||||
pageManager:getPage(USCPage),
|
||||
pageManager:getPage(TeamExceedPage),
|
||||
pageManager:getPage(CreditsPage),
|
||||
PageRegistry:getOrCreatePage(KShootManiaPage),
|
||||
PageRegistry:getOrCreatePage(USCPage),
|
||||
PageRegistry:getOrCreatePage(TeamExceedPage),
|
||||
PageRegistry:getOrCreatePage(CreditsPage),
|
||||
}
|
||||
|
||||
self._isTransitioning = true -- immediately transition to first page
|
||||
|
|
Loading…
Reference in New Issue