Files

162 lines
7.3 KiB
Lua

-- Default song-select player UI: the difficulty cursor under the wheel and the difficulty banner
-- behind it. SongSelectPlayer keeps the state (selection, animations); this draws it.
--
-- Not a SongSelect class: SongSelectScript installs draw_selector / draw_background_diffs from here
-- when the skin's own SongSelect does not define them (or its hook returns false).
local M = {}
local S = tex.get_screen_scale()
local SELECTOR_OFFSET = 115 * S -- distance between the course columns
local BALLOON_OFFSET_1 = -220 * S -- balloon shift on the back / neiro slots
local BALLOON_OFFSET_2 = 70 * S -- distance between the back / neiro slots
local BG_DIFF_P2_OFFSET = 1025 * S
local DIFF_TEXT_X, DIFF_TEXT_Y, DIFF_TEXT_FONT = 125 * S, 203 * S, math.floor(61 * S)
local DIFF_NEIRO, DIFF_BACK, DIFF_EASY, DIFF_ONI, DIFF_URA = -1, -3, 0, 3, 4
local function diff_select_sprite(name)
return tex.get_texture("song_select/diff_select/" .. name)
end
-- pass 0 is drawn under the wheel by the skins that split the cursor; the default draws it once, over
function M.draw_selector(_self, player, is_half, fade_in, pass)
if pass ~= 1 or fade_in < 1.0 then return end
local st = player:selector_state()
local fade = st.panel and 0.5 or fade_in
local direction = st.move_right and 1 or -1
local selected, prev = st.selected, st.prev
local p = player:player_num() .. "p"
local suffix = is_half and "_half" or ""
local balloon = diff_select_sprite(p .. "_balloon" .. suffix)
local outline = diff_select_sprite(p .. "_outline" .. suffix)
local outline_back = diff_select_sprite(p .. "_outline_back" .. suffix)
if selected <= DIFF_NEIRO or prev == DIFF_NEIRO then
if prev == DIFF_NEIRO and selected >= DIFF_EASY then
if not st.move2_done then
local bx = ((prev + 3) * BALLOON_OFFSET_2) + BALLOON_OFFSET_1 + st.move2 * direction
tex.draw_texture(balloon, { x = bx, fade = fade })
tex.draw_texture(outline_back, { x = ((prev + 3) * BALLOON_OFFSET_2) + st.move2 * direction })
else
local difficulty = math.min(DIFF_ONI, selected)
tex.draw_texture(balloon, { x = difficulty * SELECTOR_OFFSET, fade = fade })
tex.draw_texture(outline, { x = difficulty * SELECTOR_OFFSET })
end
elseif not st.move2_done then
if selected ~= DIFF_BACK then
tex.draw_texture(outline_back, { x = ((prev + 3) * BALLOON_OFFSET_2) + st.move2 * direction })
local bx = ((prev + 3) * BALLOON_OFFSET_2) + BALLOON_OFFSET_1 + st.move2 * direction
tex.draw_texture(balloon, { x = bx, fade = fade })
else
tex.draw_texture(outline_back, { x = ((prev + 3) * BALLOON_OFFSET_2) + st.move2 * direction, fade = fade })
end
else
if selected ~= DIFF_BACK then
tex.draw_texture(outline_back, { x = (selected + 3) * BALLOON_OFFSET_2 })
tex.draw_texture(balloon, { x = ((selected + 3) * BALLOON_OFFSET_2) + BALLOON_OFFSET_1, fade = fade })
else
tex.draw_texture(outline_back, { x = (selected + 3) * BALLOON_OFFSET_2, fade = fade })
end
end
else
if prev == DIFF_NEIRO then return end
if not st.move1_done then
local difficulty = math.min(DIFF_ONI, prev)
local bx = (difficulty * SELECTOR_OFFSET) + st.move1 * direction
tex.draw_texture(balloon, { x = bx, fade = fade })
tex.draw_texture(outline, { x = bx })
else
local difficulty = math.min(DIFF_ONI, selected)
tex.draw_texture(balloon, { x = difficulty * SELECTOR_OFFSET, fade = fade })
tex.draw_texture(outline, { x = difficulty * SELECTOR_OFFSET })
end
end
end
-- the four banner labels (easy .. oni), rebuilt when the language changes
local labels, labels_lang
local function diff_label(index)
local lang = tex.language()
if lang ~= labels_lang then
labels = {}
for i, key in ipairs({ "diff_tower_easy", "diff_tower_normal", "diff_tower_hard", "diff_tower_oni" }) do
labels[i] = text.create_raw_text(tex.skin_text(key), DIFF_TEXT_FONT,
{ 255, 255, 255, 255 }, { 0, 0, 0, 255 }, false, 5.0, 2.0)
end
labels_lang = lang
end
return labels[index + 1]
end
local function global_sprite(name)
return tex.get_texture("song_select/global/" .. name)
end
-- called only while a song is selected and a course is chosen
function M.draw_background_diffs(_self, player)
local st = player:bg_diff_state()
local x_offset = (player:player_num() == 2) and BG_DIFF_P2_OFFSET or 0
local bounce_y, bounce_y2 = -st.bounce, st.bounce
local diff_frame = math.min(DIFF_URA, st.selected)
local diff_frame_oni = math.min(DIFF_ONI, st.selected)
tex.draw_texture(global_sprite("background_diff"),
{ frame = diff_frame, x = x_offset, y = bounce_y, y2 = bounce_y2, fade = math.min(0.5, st.fade_in) })
if st.highlight_on then
tex.draw_texture(global_sprite("background_diff"),
{ frame = diff_frame, x = x_offset, y = bounce_y, y2 = bounce_y2 })
end
tex.draw_texture(global_sprite("background_diff_highlight"),
{ frame = diff_frame_oni, x = x_offset, fade = st.highlight_fade })
tex.draw_texture(global_sprite("bg_diff_text_bg"),
{ scale = st.text_resize, center = true, x = x_offset, fade = math.min(0.5, st.text_fade_in) })
local label = diff_label(diff_frame_oni)
label:draw({
scale = st.text_resize,
center = true,
x = DIFF_TEXT_X + x_offset - label.width / 2.0,
y = DIFF_TEXT_Y - label.height / 2.0,
fade = st.text_fade_in,
})
end
-- The search overlay. A skin's SongSelect can set `search_box_layout = { x, y, width, height }` (pixels,
-- x/y offset from the screen centre) to move the text pill without drawing the overlay itself.
local search_text, search_text_str
function M.draw_search_box(self, box)
local sw, sh = tex.get_screen_width(), tex.get_screen_height()
tex.draw_rect(0, 0, sw, sh, 0, 0, 0, 153)
local background = tex.get_texture("song_select/diff_sort/background")
local info = tex.get_texture_info("diff_sort", "background")
if not background or not info then return end
local cx, cy = sw / 2.0, sh / 2.0
tex.draw_texture(background, {
scale = box.bg_resize, center = true,
x = cx - (info.width / 2 + info.x[1]), y = cy - (info.height / 2 + info.y[1]),
})
local layout = self.search_box_layout or { x = 0, y = 0, width = 400 * S, height = 60 * S }
local w, h = layout.width, layout.height
local x, y = cx - w / 2 + layout.x, cy - h / 2 + layout.y
local alpha = math.floor(255 * box.fade_in)
tex.draw_rounded_rect(x, y, w, h, h > 0 and math.min(40 / h, 1) or 0,
{ 255, 255, 255, alpha }, 3, { 119, 26, 45, alpha })
if box.search == "" then return end
if box.search ~= search_text_str then
search_text = text.create_raw_text(box.search, math.floor(30 * S),
{ 0, 0, 0, 255 }, { 0, 0, 0, 0 }, false, 0, 1.0)
search_text_str = box.search
end
search_text:draw({ x = x + w / 2 - search_text.width / 2, y = y + h / 2 - search_text.height / 2 })
end
return M