2021-11-21 03:41:10 +01:00
|
|
|
local Numbers = require("common.numbers")
|
2021-11-06 00:28:19 +01:00
|
|
|
local DiffRectangle = require("components.diff_rectangle")
|
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
-- Horizontal alignment
|
|
|
|
TEXT_ALIGN_LEFT = 1
|
|
|
|
TEXT_ALIGN_CENTER = 2
|
|
|
|
TEXT_ALIGN_RIGHT = 4
|
|
|
|
-- Vertical alignment
|
|
|
|
TEXT_ALIGN_TOP = 8
|
|
|
|
TEXT_ALIGN_MIDDLE = 16
|
|
|
|
TEXT_ALIGN_BOTTOM = 32
|
|
|
|
TEXT_ALIGN_BASELINE = 64
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
local jacket = nil;
|
|
|
|
local selectedIndex = 1
|
|
|
|
local selectedDiff = 1
|
2021-11-18 00:26:25 +01:00
|
|
|
local challengeCache = {}
|
2021-07-25 20:10:06 +02:00
|
|
|
local doffset = 0
|
|
|
|
local soffset = 0
|
2021-11-17 22:28:26 +01:00
|
|
|
local diffColors = { { 0, 0, 255 }, { 0, 255, 0 }, { 255, 0, 0 }, { 255, 0, 255 } }
|
2021-07-25 20:10:06 +02:00
|
|
|
local timer = 0
|
|
|
|
local scrollmul = 0
|
|
|
|
local scrollmulOffset = 0 -- bc we have min/max the game doesn't know we have to account for extra
|
|
|
|
local effector = 0
|
2021-11-17 22:28:26 +01:00
|
|
|
local searchText = gfx.CreateLabel("", 5, 0)
|
2021-07-25 20:10:06 +02:00
|
|
|
local searchIndex = 1
|
2021-07-31 23:25:09 +02:00
|
|
|
|
|
|
|
local backgroundImage = gfx.CreateSkinImage("challenge_select/bg.png", 0)
|
2021-11-20 22:54:47 +01:00
|
|
|
local challengeCardBG = gfx.CreateSkinImage("challenge_select/small_box.png", 0)
|
2021-07-31 23:25:09 +02:00
|
|
|
|
2021-07-25 20:10:06 +02:00
|
|
|
local jacketFallback = gfx.CreateSkinImage("song_select/loading.png", 0)
|
|
|
|
local showGuide = game.GetSkinSetting("show_guide")
|
|
|
|
local legendTable = {
|
2021-11-17 22:28:26 +01:00
|
|
|
{
|
|
|
|
["labelSingleLine"] = gfx.CreateLabel("SCROLL INFO", 16, 0),
|
|
|
|
["labelMultiLine"] = gfx.CreateLabel("SCROLL\nINFO", 16, 0),
|
|
|
|
["image"] = gfx.CreateSkinImage("legend/knob-left.png", 0)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
["labelSingleLine"] = gfx.CreateLabel("CHALL SELECT", 16, 0),
|
|
|
|
["labelMultiLine"] = gfx.CreateLabel("CHALLENGE\nSELECT", 16, 0),
|
|
|
|
["image"] = gfx.CreateSkinImage("legend/knob-right.png", 0)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
["labelSingleLine"] = gfx.CreateLabel("FILTER CHALLS", 16, 0),
|
|
|
|
["labelMultiLine"] = gfx.CreateLabel("FILTER\nCHALLENGES", 16, 0),
|
|
|
|
["image"] = gfx.CreateSkinImage("legend/FX-L.png", 0)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
["labelSingleLine"] = gfx.CreateLabel("SORT CHALLS", 16, 0),
|
|
|
|
["labelMultiLine"] = gfx.CreateLabel("SORT\nCHALLENGES", 16, 0),
|
|
|
|
["image"] = gfx.CreateSkinImage("legend/FX-R.png", 0)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
["labelSingleLine"] = gfx.CreateLabel("GAME SETTINGS", 16, 0),
|
|
|
|
["labelMultiLine"] = gfx.CreateLabel("GAME\nSETTINGS", 16, 0),
|
|
|
|
["image"] = gfx.CreateSkinImage("legend/FX-LR.png", 0)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
["labelSingleLine"] = gfx.CreateLabel("PLAY", 16, 0),
|
|
|
|
["labelMultiLine"] = gfx.CreateLabel("PLAY", 16, 0),
|
|
|
|
["image"] = gfx.CreateSkinImage("legend/start.png", 0)
|
|
|
|
}
|
2021-07-25 20:10:06 +02:00
|
|
|
}
|
|
|
|
local grades = {
|
2021-11-17 22:28:26 +01:00
|
|
|
{ ["max"] = 6999999, ["image"] = gfx.CreateSkinImage("common/grades/D.png", 0) },
|
|
|
|
{ ["max"] = 7999999, ["image"] = gfx.CreateSkinImage("common/grades/C.png", 0) },
|
|
|
|
{ ["max"] = 8699999, ["image"] = gfx.CreateSkinImage("common/grades/B.png", 0) },
|
|
|
|
{ ["max"] = 8999999, ["image"] = gfx.CreateSkinImage("common/grades/A.png", 0) },
|
|
|
|
{ ["max"] = 9299999, ["image"] = gfx.CreateSkinImage("common/grades/A+.png", 0) },
|
|
|
|
{ ["max"] = 9499999, ["image"] = gfx.CreateSkinImage("common/grades/AA.png", 0) },
|
|
|
|
{ ["max"] = 9699999, ["image"] = gfx.CreateSkinImage("common/grades/AA+.png", 0) },
|
|
|
|
{ ["max"] = 9799999, ["image"] = gfx.CreateSkinImage("common/grades/AAA.png", 0) },
|
|
|
|
{ ["max"] = 9899999, ["image"] = gfx.CreateSkinImage("common/grades/AAA+.png", 0) },
|
|
|
|
{ ["max"] = 99999999, ["image"] = gfx.CreateSkinImage("common/grades/S.png", 0) }
|
2021-07-25 20:10:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
local badges = {
|
2021-11-17 22:28:26 +01:00
|
|
|
gfx.CreateSkinImage("song_select/medal/played.png", 1),
|
|
|
|
gfx.CreateSkinImage("song_select/medal/clear.png", 1),
|
|
|
|
gfx.CreateSkinImage("song_select/medal/hard.png", 1),
|
|
|
|
gfx.CreateSkinImage("song_select/medal/uc.png", 1),
|
|
|
|
gfx.CreateSkinImage("song_select/medal/puc.png", 1)
|
2021-07-25 20:10:06 +02:00
|
|
|
}
|
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
local passStates = {
|
|
|
|
gfx.CreateSkinImage("challenge_select/pass_states/not_played.png", 0),
|
|
|
|
gfx.CreateSkinImage("challenge_select/pass_states/failed.png", 0),
|
2021-11-21 03:41:10 +01:00
|
|
|
gfx.CreateSkinImage("challenge_select/pass_states/cleared.png", 0)
|
2021-11-20 22:54:47 +01:00
|
|
|
}
|
|
|
|
|
2021-11-20 23:51:53 +01:00
|
|
|
local scoreNumber = Numbers.load_number_image("score_num")
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local difficultyLabelImages = {
|
|
|
|
gfx.CreateSkinImage("diff/1 novice.png", 0),
|
|
|
|
gfx.CreateSkinImage("diff/2 advanced.png", 0),
|
|
|
|
gfx.CreateSkinImage("diff/3 exhaust.png", 0),
|
|
|
|
gfx.CreateSkinImage("diff/4 maximum.png", 0),
|
|
|
|
gfx.CreateSkinImage("diff/5 infinite.png", 0),
|
|
|
|
gfx.CreateSkinImage("diff/6 gravity.png", 0),
|
|
|
|
gfx.CreateSkinImage("diff/7 heavenly.png", 0),
|
|
|
|
gfx.CreateSkinImage("diff/8 vivid.png", 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
local difficultyLabelText = { "NOV", "ADV", "EXH", "MXM", "INF", "GRV", "HVN", "VVD" }
|
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
gfx.LoadSkinFont("divlit_custom.ttf")
|
2021-11-06 00:28:19 +01:00
|
|
|
gfx.LoadSkinFont("dfmarugoth.ttf");
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
game.LoadSkinSample("menu_click")
|
|
|
|
game.LoadSkinSample("click-02")
|
|
|
|
game.LoadSkinSample("woosh")
|
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
local wheelSize = 5
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
get_page_size = function()
|
2021-11-17 22:28:26 +01:00
|
|
|
return math.floor(wheelSize / 2)
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Responsive UI variables
|
|
|
|
-- Aspect Ratios
|
2021-11-20 22:54:47 +01:00
|
|
|
local aspectFloat = 1.0
|
2021-07-25 20:10:06 +02:00
|
|
|
local aspectRatio = "widescreen"
|
2021-11-20 22:54:47 +01:00
|
|
|
local landscapeWidescreenRatio = 16 / 9
|
|
|
|
local landscapeStandardRatio = 4 / 3
|
|
|
|
local portraitWidescreenRatio = 9 / 16
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
-- Responsive sizes
|
|
|
|
local fifthX = 0
|
2021-11-17 22:28:26 +01:00
|
|
|
local fourthX = 0
|
2021-07-25 20:10:06 +02:00
|
|
|
local thirdX = 0
|
2021-11-17 22:28:26 +01:00
|
|
|
local halfX = 0
|
|
|
|
local fullX = 0
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
local fifthY = 0
|
2021-11-17 22:28:26 +01:00
|
|
|
local fourthY = 0
|
2021-07-25 20:10:06 +02:00
|
|
|
local thirdY = 0
|
2021-11-17 22:28:26 +01:00
|
|
|
local halfY = 0
|
|
|
|
local fullY = 0
|
|
|
|
|
|
|
|
adjustScreen = function(x, y)
|
2021-11-20 22:54:47 +01:00
|
|
|
aspectFloat = x / y;
|
2021-11-17 22:28:26 +01:00
|
|
|
fifthX = x / 5
|
|
|
|
fourthX = x / 4
|
|
|
|
thirdX = x / 3
|
|
|
|
halfX = x / 2
|
|
|
|
fullX = x
|
|
|
|
|
|
|
|
fifthY = y / 5
|
|
|
|
fourthY = y / 4
|
|
|
|
thirdY = y / 3
|
|
|
|
halfY = y / 2
|
|
|
|
fullY = y
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
check_or_create_cache = function(challenge)
|
2021-11-18 00:26:25 +01:00
|
|
|
if not challengeCache[challenge.id] then
|
|
|
|
challengeCache[challenge.id] = {}
|
2021-11-17 22:28:26 +01:00
|
|
|
end
|
2021-07-25 20:10:06 +02:00
|
|
|
|
2021-11-18 00:26:25 +01:00
|
|
|
if not challengeCache[challenge.id]["title"] then
|
2021-11-21 03:41:10 +01:00
|
|
|
challengeCache[challenge.id]["title"] = challenge.title
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
if not challengeCache[challenge.id]["charts"] then
|
2021-11-18 00:26:25 +01:00
|
|
|
if challenge.missing_chart then
|
2021-11-20 22:54:47 +01:00
|
|
|
local missing_text = "*COULD NOT FIND ALL CHARTS!*"
|
2021-11-21 03:41:10 +01:00
|
|
|
challengeCache[challenge.id]["charts"] = { { ["title"] = missing_text, ["level"] = 0, ["difficulty"] = 0 } }
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
|
|
|
|
local charts = {}
|
|
|
|
for _, chart in ipairs(challenge.charts) do
|
2021-11-21 03:41:10 +01:00
|
|
|
table.insert(charts, { ["title"] = chart.title, ["level"] = chart.level, ["difficulty"] = chart.difficulty })
|
2021-11-20 22:54:47 +01:00
|
|
|
end
|
|
|
|
challengeCache[challenge.id]["charts"] = charts
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
|
2021-11-21 03:41:10 +01:00
|
|
|
if (not challengeCache[challenge.id]["percent"] or not challengeCache[challenge.id]["total_score"]
|
2021-11-20 22:54:47 +01:00
|
|
|
or challengeCache[challenge.id]["total_score"] ~= challenge.bestScore) then
|
|
|
|
challengeCache[challenge.id]["percent"] = math.max(0, (challenge.bestScore - 8000000) // 10000)
|
|
|
|
challengeCache[challenge.id]["total_score"] = challenge.bestScore
|
|
|
|
end
|
|
|
|
|
|
|
|
if not challengeCache[challenge.id]["pass_state"] then
|
2021-11-21 03:41:10 +01:00
|
|
|
local passState = math.min(challenge.topBadge, 2) + 1 -- challenge.topBadge -> [1, 3]
|
2021-11-20 22:54:47 +01:00
|
|
|
challengeCache[challenge.id]["pass_state"] = passStates[passState]
|
|
|
|
end
|
|
|
|
|
|
|
|
if not challengeCache[challenge.id]["jackets"] then
|
|
|
|
local jackets = {}
|
|
|
|
for i, chart in ipairs(challenge.charts) do
|
|
|
|
jackets[i] = gfx.LoadImageJob(chart.jacketPath, jacketFallback, 200, 200)
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
if #jackets == 0 then
|
|
|
|
jackets[1] = jacketFallback
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
challengeCache[challenge.id]["jackets"] = jackets
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-11-18 00:26:25 +01:00
|
|
|
draw_challenge = function(challenge, x, y, w, h, selected)
|
2021-11-21 03:17:22 +01:00
|
|
|
if not challenge then
|
|
|
|
return
|
|
|
|
end
|
2021-11-18 00:26:25 +01:00
|
|
|
|
|
|
|
check_or_create_cache(challenge)
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local _draw_card_bg = function()
|
2021-11-20 22:54:47 +01:00
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.ImageRect(x, y, w, h, challengeCardBG, 1, 0)
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local _draw_info = function()
|
2021-11-20 22:54:47 +01:00
|
|
|
local stateLabel = challengeCache[challenge.id]["pass_state"]
|
|
|
|
local stateLabelWidth, stateLabelHeight = gfx.ImageSize(stateLabel)
|
|
|
|
local stateLabelAspect = stateLabelWidth / stateLabelHeight
|
|
|
|
|
|
|
|
local stateWidth = w / 5
|
|
|
|
local stateHeight = stateWidth / stateLabelAspect
|
|
|
|
local stateOffsetX = x + w / 32
|
2021-11-21 03:41:10 +01:00
|
|
|
local stateOffsetY = y + h / 32
|
2021-11-20 22:54:47 +01:00
|
|
|
|
|
|
|
local titleMargin = 6
|
2021-11-21 03:41:10 +01:00
|
|
|
local titleFontSize = math.floor(0.11 * h) -- must be an integer
|
|
|
|
local titleMaxWidth = 6 / 9 * w
|
2021-11-21 03:17:22 +01:00
|
|
|
local titleCenterX = x + w - titleMargin - titleMaxWidth / 2 -- align right
|
2021-11-21 03:41:10 +01:00
|
|
|
local titleBaselineY = y + 0.025 * h -- align baseline
|
2021-11-20 22:54:47 +01:00
|
|
|
|
2021-11-21 03:41:10 +01:00
|
|
|
if selected then
|
|
|
|
stateWidth = stateWidth / 0.9
|
|
|
|
stateHeight = stateHeight / 0.9
|
|
|
|
stateOffsetY = y + h / 16
|
2021-11-20 22:54:47 +01:00
|
|
|
|
2021-11-21 03:41:10 +01:00
|
|
|
titleFontSize = math.floor(0.075 * h) -- must be an integer
|
|
|
|
titleMaxWidth = 3 / 5 * w
|
2021-11-21 03:17:22 +01:00
|
|
|
titleCenterX = x + w - titleMargin - titleMaxWidth / 2 -- align right
|
2021-11-21 03:41:10 +01:00
|
|
|
titleBaselineY = y + 0.09 * h -- align baseline
|
2021-11-17 22:28:26 +01:00
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
|
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.ImageRect(stateOffsetX, stateOffsetY, stateWidth, stateHeight, stateLabel, 1, 0)
|
|
|
|
|
2021-11-21 03:41:10 +01:00
|
|
|
local titleLabel = gfx.CreateLabel(challengeCache[challenge.id]["title"], titleFontSize, 0)
|
2021-11-20 22:54:47 +01:00
|
|
|
gfx.FontFace("divlit_custom.ttf")
|
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_BASELINE)
|
2021-11-21 03:41:10 +01:00
|
|
|
gfx.DrawLabel(titleLabel, titleCenterX, titleBaselineY, titleMaxWidth)
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local _draw_jacket = function()
|
2021-11-20 22:54:47 +01:00
|
|
|
local size = h * 0.68
|
|
|
|
local offsetX = x + w / 32
|
|
|
|
local offsetY = y + h - size - h * 0.05
|
|
|
|
|
|
|
|
if not selected then
|
|
|
|
size = h * 0.66
|
|
|
|
offsetX = x + w * 0.058
|
|
|
|
offsetY = y + h - size - h * 0.066
|
|
|
|
end
|
2021-11-21 03:17:22 +01:00
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.ImageRect(offsetX, offsetY, size, size, challengeCache[challenge.id]["jackets"][1], 1, 0)
|
|
|
|
end
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local _draw_stats = function()
|
2021-11-21 01:43:20 +01:00
|
|
|
local textSizeCorrection = h / gfx.ImageSize(scoreNumber[1])
|
2021-11-21 03:17:22 +01:00
|
|
|
|
|
|
|
local percentOffsetX = x + 6 / 12 * w
|
2021-11-21 01:43:20 +01:00
|
|
|
local percentOffsetY = y + 0.87 * h
|
|
|
|
local percentSize = 0.17 * textSizeCorrection
|
2021-11-20 23:51:53 +01:00
|
|
|
|
|
|
|
local scoreUpperOffsetX = 0
|
|
|
|
local scoreUpperOffsetY = 0
|
|
|
|
local scoreOffsetX = x + w * 0.74
|
|
|
|
local scoreOffsetY = y + h * 0.9
|
2021-11-21 01:43:20 +01:00
|
|
|
local scoreUpperSize = 0.2 * textSizeCorrection
|
|
|
|
local scoreSize = 0.125 * textSizeCorrection
|
2021-11-21 03:17:22 +01:00
|
|
|
|
2021-11-21 01:43:20 +01:00
|
|
|
local percent = challengeCache[challenge.id]["percent"]
|
|
|
|
local scoreUpper = math.floor(challengeCache[challenge.id]["total_score"] / 10000)
|
|
|
|
local score = challengeCache[challenge.id]["total_score"]
|
2021-11-20 23:51:53 +01:00
|
|
|
|
|
|
|
if selected then
|
2021-11-21 03:17:22 +01:00
|
|
|
percentOffsetX = x + 11 / 24 * w
|
|
|
|
percentOffsetY = y + 49 / 64 * h
|
2021-11-21 01:43:20 +01:00
|
|
|
percentSize = 0.12 * textSizeCorrection
|
2021-11-21 03:17:22 +01:00
|
|
|
|
2021-11-20 23:51:53 +01:00
|
|
|
scoreUpperOffsetX = x + w * 0.63
|
|
|
|
scoreUpperOffsetY = y + h * 0.82
|
|
|
|
scoreOffsetX = x + w * 0.755
|
|
|
|
scoreOffsetY = y + h * 0.835
|
2021-11-21 01:43:20 +01:00
|
|
|
scoreUpperSize = 0.12 * textSizeCorrection
|
|
|
|
scoreSize = 0.09 * textSizeCorrection
|
2021-11-20 23:51:53 +01:00
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
|
2021-11-21 01:43:20 +01:00
|
|
|
Numbers.draw_number(percentOffsetX, percentOffsetY, 1, percent, 3, scoreNumber, true, percentSize, 1)
|
2021-11-21 03:17:22 +01:00
|
|
|
-- TODO: Missing percentage character
|
2021-11-20 23:51:53 +01:00
|
|
|
|
|
|
|
if selected then
|
2021-11-21 03:17:22 +01:00
|
|
|
Numbers.draw_number(
|
|
|
|
scoreUpperOffsetX, scoreUpperOffsetY, 1, scoreUpper, 4, scoreNumber, true, scoreUpperSize, 1
|
|
|
|
)
|
2021-11-21 01:43:20 +01:00
|
|
|
Numbers.draw_number(scoreOffsetX, scoreOffsetY, 1, score, 4, scoreNumber, true, scoreSize, 1)
|
2021-11-20 23:51:53 +01:00
|
|
|
else
|
2021-11-21 01:43:20 +01:00
|
|
|
Numbers.draw_number(scoreOffsetX, scoreOffsetY, 1, score, 8, scoreNumber, true, scoreSize, 1)
|
2021-11-20 23:51:53 +01:00
|
|
|
end
|
2021-11-21 03:41:10 +01:00
|
|
|
|
|
|
|
-- TODO: Missing completion bar
|
|
|
|
|
|
|
|
-- TODO: Missing completion badge (COMP, HARD, UC, PUC)
|
|
|
|
-- TODO: Missing completion grade (S+, S, AAA+, etc.)
|
2021-11-20 22:54:47 +01:00
|
|
|
end
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local _draw_charts = function()
|
|
|
|
local diffIconHeight = 0.124 * h
|
|
|
|
local diffIconWidth = 140 / 31 * diffIconHeight -- only scaling, no stretching textures
|
|
|
|
-- diffIconWidth = 0.8 * diffIconWidth -- okay, maybe a little squishing must be done
|
2021-11-20 22:54:47 +01:00
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local paddingY = 0.18 * h
|
|
|
|
local offsetX = x + 0.252 * w
|
|
|
|
local offsetY = y + 0.246 * h
|
2021-11-20 22:54:47 +01:00
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local titleMargin = 6
|
2021-11-21 03:41:10 +01:00
|
|
|
local titleFontSize = math.floor(0.11 * h) -- must be an integer
|
2021-11-21 03:17:22 +01:00
|
|
|
local titleMaxWidth = 6 / 9 * w
|
|
|
|
local titleCenterX = x + w - titleMargin - titleMaxWidth / 2 -- align right
|
2021-11-18 00:26:25 +01:00
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
if selected then
|
|
|
|
diffIconHeight = h / 12
|
|
|
|
diffIconWidth = 140 / 31 * diffIconHeight -- only scaling, no stretching textures
|
|
|
|
-- diffIconWidth = 0.8 * diffIconWidth -- okay, maybe a little squishing must be done
|
|
|
|
|
|
|
|
paddingY = 0.122 * h
|
|
|
|
offsetX = x + 0.268 * w
|
|
|
|
offsetY = y + 0.256 * h
|
|
|
|
|
2021-11-21 03:41:10 +01:00
|
|
|
titleFontSize = math.floor(0.075 * h) -- must be an integer
|
2021-11-21 03:17:22 +01:00
|
|
|
titleMaxWidth = 3 / 5 * w
|
|
|
|
titleCenterX = x + w - titleMargin - titleMaxWidth / 2 -- align right
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
for i, chart in ipairs(challengeCache[challenge.id]["charts"]) do
|
|
|
|
local ypos = offsetY + paddingY * (i - 1)
|
2021-07-25 20:10:06 +02:00
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
draw_diff_icon(chart, offsetX, ypos, diffIconWidth, diffIconHeight, selected)
|
2021-07-25 20:10:06 +02:00
|
|
|
|
2021-11-21 03:41:10 +01:00
|
|
|
local chartTitleLabel = gfx.CreateLabel(chart.title, titleFontSize, 0)
|
2021-11-21 03:17:22 +01:00
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_MIDDLE)
|
2021-11-21 03:41:10 +01:00
|
|
|
gfx.DrawLabel(chartTitleLabel, titleCenterX, ypos + diffIconHeight / 2, titleMaxWidth)
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
2021-11-17 22:28:26 +01:00
|
|
|
end
|
2021-07-25 20:10:06 +02:00
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
if not selected then
|
|
|
|
_draw_card_bg()
|
|
|
|
end
|
2021-07-25 20:10:06 +02:00
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
_draw_info()
|
|
|
|
_draw_jacket()
|
|
|
|
_draw_stats()
|
|
|
|
_draw_charts()
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
gfx.ForceRender()
|
2021-11-20 22:54:47 +01:00
|
|
|
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
draw_diff_icon = function(diff, x, y, w, h)
|
|
|
|
-- cut out the transparent part of the diff background image
|
|
|
|
local boxWidth = 140 / 122 * w
|
|
|
|
local boxHeight = 31 / 27 * h
|
|
|
|
local boxOffsetX = x - (boxWidth - w) / 2
|
|
|
|
local boxOffsetY = y - (boxHeight - h) / 2
|
2021-11-17 22:28:26 +01:00
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local labelOffsetX = w / 12
|
|
|
|
local labelTextOffsetY = h / 12
|
2021-11-17 22:28:26 +01:00
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
gfx.BeginPath()
|
2021-11-21 03:17:22 +01:00
|
|
|
|
|
|
|
gfx.ImageRect(boxOffsetX, boxOffsetY, boxWidth, boxHeight, difficultyLabelImages[diff.difficulty + 1], 1, 0)
|
|
|
|
|
|
|
|
gfx.FontFace("dfmarugoth.ttf")
|
|
|
|
gfx.FontSize(math.floor(0.6 * h))
|
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT | gfx.TEXT_ALIGN_MIDDLE)
|
|
|
|
gfx.FastText(difficultyLabelText[diff.difficulty + 1], x + labelOffsetX, y + (h / 2) - labelTextOffsetY)
|
|
|
|
gfx.FontSize(math.floor(0.8 * h))
|
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT | gfx.TEXT_ALIGN_MIDDLE)
|
|
|
|
gfx.FastText(tostring(diff.level), x + w - labelOffsetX, y + (h / 2) - labelTextOffsetY)
|
2021-11-20 22:54:47 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
draw_selected = function(challenge, x, y, w, h)
|
2021-11-21 03:17:22 +01:00
|
|
|
if not challenge then
|
|
|
|
return
|
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
|
|
|
|
check_or_create_cache(challenge)
|
|
|
|
|
|
|
|
draw_challenge(challenge, x, y, w, h, true)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
draw_chalwheel = function(x, y, w, h)
|
|
|
|
local challengeAspect = 4.367
|
|
|
|
local selectedChallengeAspect = 3.305
|
|
|
|
|
|
|
|
local portraitAspectCorrection = portraitWidescreenRatio / aspectFloat
|
|
|
|
|
|
|
|
local width = math.floor(w * 0.839)
|
|
|
|
local height = math.floor((width / challengeAspect) * portraitAspectCorrection)
|
|
|
|
|
|
|
|
local selectedWidth = math.floor(w * 0.944)
|
|
|
|
local selectedHeight = math.floor((selectedWidth / selectedChallengeAspect) * portraitAspectCorrection)
|
|
|
|
|
2021-11-21 03:17:22 +01:00
|
|
|
local offsetX = w / 2 - width / 2 -- center
|
2021-11-20 22:54:47 +01:00
|
|
|
local centerY = h / 2 - height / 2
|
|
|
|
local selectedOffsetX = w / 2 - selectedWidth / 2
|
|
|
|
local selectedCenterY = h / 2 - selectedHeight / 2
|
|
|
|
local margin = h / 128
|
|
|
|
local centerMargin = h / 100
|
|
|
|
|
|
|
|
local imin = math.ceil(selectedIndex - wheelSize / 2)
|
|
|
|
local imax = math.floor(selectedIndex + wheelSize / 2)
|
|
|
|
for i = math.max(imin, 1), math.min(imax, #chalwheel.challenges) do
|
|
|
|
local current = selectedIndex - i
|
|
|
|
if not (current == 0) then
|
|
|
|
local challenge = chalwheel.challenges[i]
|
|
|
|
local xpos = x + offsetX
|
2021-11-21 03:17:22 +01:00
|
|
|
-- local offsetY = current * (height - (wheelSize / 2 * (current * aspectFloat)))
|
2021-11-20 22:54:47 +01:00
|
|
|
local offsetY = math.abs(current) * (height + margin) + (selectedHeight - height) / 2
|
|
|
|
local ypos = y + centerY
|
|
|
|
if current < 0 then
|
|
|
|
ypos = ypos + centerMargin + offsetY
|
|
|
|
else -- if current > 0 then
|
|
|
|
ypos = ypos - centerMargin - offsetY
|
|
|
|
end
|
|
|
|
draw_challenge(challenge, xpos, ypos, width, height)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- render selected song information
|
|
|
|
local xpos = x + selectedOffsetX
|
|
|
|
local ypos = y + selectedCenterY
|
|
|
|
draw_selected(chalwheel.challenges[selectedIndex], xpos, ypos, selectedWidth, selectedHeight)
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
2021-11-18 00:26:25 +01:00
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
draw_legend_pane = function(x, y, w, h, obj)
|
|
|
|
local xpos = x + 5
|
|
|
|
local ypos = y
|
|
|
|
local imageSize = h
|
2021-11-21 03:17:22 +01:00
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_MIDDLE + gfx.TEXT_ALIGN_LEFT)
|
|
|
|
gfx.ImageRect(x, y, imageSize, imageSize, obj.image, 1, 0)
|
|
|
|
xpos = xpos + imageSize + 5
|
|
|
|
gfx.FontSize(16);
|
|
|
|
if h < (w - (10 + imageSize)) / 2 then
|
|
|
|
gfx.DrawLabel(obj.labelSingleLine, xpos, y + (h / 2), w - (10 + imageSize))
|
|
|
|
else
|
|
|
|
gfx.DrawLabel(obj.labelMultiLine, xpos, y + (h / 2), w - (10 + imageSize))
|
|
|
|
end
|
|
|
|
gfx.ForceRender()
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
draw_legend = function(x, y, w, h)
|
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_MIDDLE + gfx.TEXT_ALIGN_LEFT);
|
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.FillColor(0, 0, 0, 170)
|
|
|
|
gfx.Rect(x, y, w, h)
|
|
|
|
gfx.Fill()
|
|
|
|
local xpos = 10;
|
|
|
|
local legendWidth = math.floor((w - 20) / #legendTable)
|
|
|
|
for i, v in ipairs(legendTable) do
|
|
|
|
local xOffset = draw_legend_pane(xpos + (legendWidth * (i - 1)), y + 5, legendWidth, h - 10, legendTable[i])
|
|
|
|
end
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
draw_search = function(x, y, w, h)
|
|
|
|
soffset = soffset + (searchIndex) - (chalwheel.searchInputActive and 0 or 1)
|
|
|
|
if searchIndex ~= (chalwheel.searchInputActive and 0 or 1) then
|
|
|
|
game.PlaySample("woosh")
|
|
|
|
end
|
|
|
|
searchIndex = chalwheel.searchInputActive and 0 or 1
|
|
|
|
|
|
|
|
gfx.BeginPath()
|
|
|
|
local bgfade = 1 - (searchIndex + soffset)
|
|
|
|
-- if not chalwheel.searchInputActive then bgfade = soffset end
|
|
|
|
gfx.FillColor(0, 0, 0, math.floor(200 * bgfade))
|
|
|
|
gfx.Rect(0, 0, resx, resy)
|
|
|
|
gfx.Fill()
|
|
|
|
gfx.ForceRender()
|
|
|
|
local xpos = x + (searchIndex + soffset) * w
|
2021-11-18 00:26:25 +01:00
|
|
|
gfx.UpdateLabel(searchText, string.format("Search: %s", chalwheel.searchText), 30)
|
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.RoundedRect(xpos, y, w, h, h / 2)
|
|
|
|
gfx.FillColor(30, 30, 30)
|
|
|
|
gfx.StrokeColor(0, 128, 255)
|
|
|
|
gfx.StrokeWidth(1)
|
|
|
|
gfx.Fill()
|
|
|
|
gfx.Stroke()
|
2021-11-21 03:17:22 +01:00
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
gfx.BeginPath();
|
|
|
|
gfx.LoadSkinFont("dfmarugoth.ttf");
|
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE);
|
|
|
|
gfx.DrawLabel(searchText, xpos + 10, y + (h / 2), w - 20)
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
render = function(deltaTime)
|
2021-11-17 22:28:26 +01:00
|
|
|
timer = (timer + deltaTime)
|
|
|
|
timer = timer % 2
|
|
|
|
resx, resy = game.GetResolution();
|
2021-11-18 00:26:25 +01:00
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.ImageRect(0, 0, resx, resy, backgroundImage, 1, 0)
|
|
|
|
adjustScreen(resx, resy);
|
2021-11-18 00:26:25 +01:00
|
|
|
|
2021-07-25 20:10:06 +02:00
|
|
|
gfx.BeginPath();
|
2021-11-06 00:28:19 +01:00
|
|
|
gfx.LoadSkinFont("dfmarugoth.ttf");
|
2021-07-25 20:10:06 +02:00
|
|
|
gfx.FontSize(40);
|
2021-11-17 22:28:26 +01:00
|
|
|
gfx.FillColor(255, 255, 255);
|
2021-11-18 00:26:25 +01:00
|
|
|
if chalwheel.challenges and chalwheel.challenges[1] then
|
2021-11-20 22:54:47 +01:00
|
|
|
-- draw chalwheel
|
|
|
|
draw_chalwheel(0, 0, fullX, fullY)
|
2021-11-17 22:28:26 +01:00
|
|
|
end
|
|
|
|
-- Draw Legend Information
|
2021-11-20 22:54:47 +01:00
|
|
|
--[[
|
2021-11-17 22:28:26 +01:00
|
|
|
if showGuide then
|
|
|
|
draw_legend(0, (fifthY / 3) * 14, fullX, (fifthY / 3) * 1)
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
2021-11-20 22:54:47 +01:00
|
|
|
--]]
|
2021-11-06 00:28:19 +01:00
|
|
|
|
2021-11-17 22:28:26 +01:00
|
|
|
-- draw text search
|
2021-11-06 00:28:19 +01:00
|
|
|
|
2021-11-20 22:54:47 +01:00
|
|
|
--[[
|
2021-11-17 22:28:26 +01:00
|
|
|
draw_search(fifthX * 2, 5, fifthX * 3, fifthY / 5)
|
2021-07-25 20:10:06 +02:00
|
|
|
|
|
|
|
doffset = doffset * 0.9
|
|
|
|
soffset = soffset * 0.8
|
2021-11-17 22:28:26 +01:00
|
|
|
if chalwheel.searchStatus then
|
|
|
|
gfx.BeginPath()
|
|
|
|
gfx.FillColor(255, 255, 255)
|
|
|
|
gfx.FontSize(20);
|
|
|
|
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
|
|
|
|
gfx.Text(chalwheel.searchStatus, 3, 3)
|
|
|
|
end
|
2021-11-06 00:28:19 +01:00
|
|
|
gfx.LoadSkinFont("dfmarugoth.ttf");
|
2021-07-25 20:10:06 +02:00
|
|
|
gfx.ResetTransform()
|
|
|
|
gfx.ForceRender()
|
2021-11-20 22:54:47 +01:00
|
|
|
--]]
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
set_index = function(newIndex, scrollamt)
|
|
|
|
if newIndex ~= selectedIndex then
|
|
|
|
game.PlaySample("menu_click")
|
|
|
|
scrollmulOffset = 0
|
|
|
|
end
|
|
|
|
selectedIndex = newIndex
|
|
|
|
scrollmul = scrollamt + scrollmulOffset
|
|
|
|
end;
|
|
|
|
|
|
|
|
local badgeRates = {
|
2021-11-17 22:28:26 +01:00
|
|
|
0.5, -- Played
|
|
|
|
1.0, -- Cleared
|
|
|
|
1.02, -- Hard clear
|
|
|
|
1.04, -- UC
|
|
|
|
1.1 -- PUC
|
2021-07-25 20:10:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
local gradeRates = {
|
2021-11-17 22:28:26 +01:00
|
|
|
{ ["min"] = 9900000, ["rate"] = 1.05 }, -- S
|
|
|
|
{ ["min"] = 9800000, ["rate"] = 1.02 }, -- AAA+
|
|
|
|
{ ["min"] = 9700000, ["rate"] = 1 }, -- AAA
|
|
|
|
{ ["min"] = 9500000, ["rate"] = 0.97 }, -- AA+
|
|
|
|
{ ["min"] = 9300000, ["rate"] = 0.94 }, -- AA
|
|
|
|
{ ["min"] = 9000000, ["rate"] = 0.91 }, -- A+
|
|
|
|
{ ["min"] = 8700000, ["rate"] = 0.88 }, -- A
|
|
|
|
{ ["min"] = 7500000, ["rate"] = 0.85 }, -- B
|
|
|
|
{ ["min"] = 6500000, ["rate"] = 0.82 }, -- C
|
|
|
|
{ ["min"] = 0, ["rate"] = 0.8 } -- D
|
2021-07-25 20:10:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
challenges_changed = function(withAll)
|
2021-11-17 22:28:26 +01:00
|
|
|
if not withAll then
|
|
|
|
return
|
|
|
|
end
|
2021-07-25 20:10:06 +02:00
|
|
|
end
|