forked from Yonokid/YataiDONNijiiro
231 lines
9.5 KiB
Lua
231 lines
9.5 KiB
Lua
local WHITE, BLACK = { 255, 255, 255, 255 }, { 0, 0, 0, 255 }
|
|
|
|
local JP_THRESHOLD = {
|
|
dan_exam_text_more = "%s 以上",
|
|
dan_exam_text_less = "%s 未満",
|
|
dan_exam_text_gauge = "%s %以上",
|
|
dan_exam_text_gauge_less = "%s %未満",
|
|
}
|
|
|
|
local function exam_threshold_text(exam_type, range, num)
|
|
local gauge, less = exam_type == "gauge", range == "less"
|
|
local key = gauge and (less and "dan_exam_text_gauge_less" or "dan_exam_text_gauge")
|
|
or (less and "dan_exam_text_less" or "dan_exam_text_more")
|
|
local fmt = tex.skin_text(key)
|
|
if fmt == "" then fmt = JP_THRESHOLD[key] end
|
|
fmt = fmt:gsub("%%%%", "\1")
|
|
return (fmt:gsub("%%s", tostring(num)):gsub("\1", "%%"))
|
|
end
|
|
|
|
local function pad_for(outline, scale)
|
|
return math.floor(outline * scale) + 2
|
|
end
|
|
|
|
local EXAM_ICON_PATHS = {
|
|
gauge = "exam_gauge", combo = "exam_combo", hit = "exam_hit", judgebad = "exam_judgebad",
|
|
judgegood = "exam_judgegood", judgeperfect = "exam_judgeperfect", score = "exam_score",
|
|
renda = "exam_roll",
|
|
}
|
|
|
|
DanGameDraw = {}
|
|
DanGameDraw.__index = DanGameDraw
|
|
|
|
function DanGameDraw.new(title)
|
|
local self = setmetatable({}, DanGameDraw)
|
|
local function T(name) return tex.get_texture("game/dan_info/" .. name) end
|
|
local names = {
|
|
"exam_bg", "exam_overlay_1", "exam_overlay_2", "exam_fail", "exam_failed", "exam_less",
|
|
"exam_more", "exam_percent", "exam_badge", "exam_frame_back_all", "exam_frame_front_all",
|
|
"exam_border_counter", "value_counter", "exam_sub_bg", "exam_sub_track", "exam_sub_front",
|
|
"exam_sub_chip", "exam_sub_counter", "total_notes", "rank_plate", "frame",
|
|
}
|
|
self.t = {}
|
|
for _, n in ipairs(names) do self.t[n] = T(n) end
|
|
|
|
self.icons = {}
|
|
for exam_type, name in pairs(EXAM_ICON_PATHS) do
|
|
self.icons[exam_type] = T(name)
|
|
end
|
|
self.fill_bar = {}
|
|
for _, n in ipairs({ "exam_sub_red", "exam_red", "exam_sub_gold", "exam_gold", "exam_sub_max",
|
|
"exam_max", "exam_sub_rainbow", "exam_rainbow", "exam_rainbow_all",
|
|
"exam_sub_down80", "exam_down80" }) do
|
|
self.fill_bar[n] = T(n)
|
|
end
|
|
|
|
self.captions = {}
|
|
local ds = tex.get_skin_config("dan_title")
|
|
self.hori_name = text.create_raw_text(title, ds and ds.font_size or 40, WHITE, BLACK, false)
|
|
return self
|
|
end
|
|
|
|
function DanGameDraw:digit_counter(digits, margin_x, t, index, y, x_offset)
|
|
x_offset = x_offset or 0
|
|
local n = #digits
|
|
for j = 1, n do
|
|
tex.draw_texture(t, { frame = digits:byte(j) - 48, x = -(n - j + 1) * margin_x + x_offset,
|
|
y = y, index = index })
|
|
end
|
|
end
|
|
|
|
function DanGameDraw:caption(s, size, outline)
|
|
local key = s .. "\31" .. size .. "\31" .. math.floor(outline * 100)
|
|
local c = self.captions[key]
|
|
if not c then
|
|
c = text.create_raw_text(s, size, WHITE, BLACK, false, outline)
|
|
self.captions[key] = c
|
|
end
|
|
return c
|
|
end
|
|
|
|
function DanGameDraw:fill(state, w, fy, sub, all, frame_ms)
|
|
if w <= 0 or state == "empty" then return end
|
|
local fb = self.fill_bar
|
|
local rb = sub and "exam_sub_rainbow" or "exam_rainbow"
|
|
if not sub and all and fb.exam_rainbow_all then rb = "exam_rainbow_all" end
|
|
local d80 = sub and "exam_sub_down80" or "exam_down80"
|
|
local up50 = sub and "exam_sub_red" or "exam_red"
|
|
local up80 = sub and "exam_sub_gold" or "exam_gold"
|
|
local p100 = sub and "exam_sub_max" or "exam_max"
|
|
if state == "max" and fb[rb] then
|
|
local rb_tex = fb[rb]
|
|
local info = tex.get_texture_info("dan_info", rb)
|
|
local th, tw = info.height, info.width
|
|
local perd = tw * 0.5
|
|
local ph = perd - math.fmod(frame_ms / 1000.0 * (perd * 60.0 / 80.0), perd)
|
|
local avail = tw - ph
|
|
if w <= avail then
|
|
tex.draw_texture(rb_tex, { y = fy, x2 = w, src = { x = ph, y = 0, width = w, height = th } })
|
|
else
|
|
tex.draw_texture(rb_tex, { y = fy, x2 = avail, src = { x = ph, y = 0, width = avail, height = th } })
|
|
tex.draw_texture(rb_tex, { x = avail, y = fy, x2 = w - avail,
|
|
src = { x = 0, y = 0, width = w - avail, height = th } })
|
|
end
|
|
return
|
|
end
|
|
local id = p100
|
|
if state == "up_50" then id = up50
|
|
elseif state == "up_80" then id = up80
|
|
elseif state == "down_80" then id = fb[d80] and d80 or up80 end
|
|
tex.draw_texture(fb[id], { y = fy, x2 = w })
|
|
end
|
|
|
|
function DanGameDraw:exam_row(info, y, song_index, frame_ms)
|
|
local t = self.t
|
|
local dei = tex.get_skin_config("dan_exam_info_game") or tex.get_skin_config("dan_exam_info")
|
|
local bm = tex.get_skin_config("dan_exam_border_margin")
|
|
local border_margin = bm and bm.x or tex.get_skin_config("dan_score_box_margin").x
|
|
local vm = tex.get_skin_config("dan_value_counter_margin")
|
|
local value_margin = vm and vm.x or border_margin
|
|
|
|
tex.draw_texture(t.exam_bg, { y = y })
|
|
tex.draw_texture(t.exam_badge, { frame = info.gothrough and 0 or 1 + math.min(song_index, 2), y = y })
|
|
|
|
local all = info.gothrough
|
|
tex.draw_texture(all and t.exam_frame_back_all or t.exam_overlay_1, { y = y })
|
|
|
|
local wa = tex.get_skin_config("dan_exam_bar_all")
|
|
local bar_full = (all and wa) and wa.width or dei.width
|
|
|
|
if info.failed then
|
|
if t.exam_fail then tex.draw_texture(t.exam_fail, { y = y, x2 = bar_full }) end
|
|
else
|
|
self:fill(info.bar_state, bar_full * info.progress, y, false, all, frame_ms)
|
|
end
|
|
|
|
tex.draw_texture(all and t.exam_frame_front_all or t.exam_overlay_2, { y = y })
|
|
|
|
local icon = self.icons[info.exam_type]
|
|
if icon then tex.draw_texture(icon, { y = y }) end
|
|
|
|
local bt = tex.get_skin_config("dan_game_exam_border_text")
|
|
local cap, bt_ol
|
|
bt_ol = 4.0 / tex.get_screen_scale()
|
|
if bt then
|
|
if bt.outline >= 0 then bt_ol = bt.outline end
|
|
cap = self:caption(exam_threshold_text(info.exam_type, info.exam_range, info.red_value),
|
|
bt.font_size > 0 and bt.font_size or 36, bt_ol)
|
|
end
|
|
if cap then
|
|
local pad = pad_for(bt_ol, tex.get_screen_scale())
|
|
cap:draw({ x = bt.x - cap.width + pad, y = bt.y - pad + y })
|
|
else
|
|
if info.exam_range == "less" then tex.draw_texture(t.exam_less, { y = y })
|
|
elseif info.exam_range == "more" then tex.draw_texture(t.exam_more, { y = y }) end
|
|
|
|
local gauge_shift = 0
|
|
if info.exam_type == "gauge" then
|
|
tex.draw_texture(t.exam_percent, { y = y, index = 0 })
|
|
local gs = tex.get_skin_config("dan_exam_gauge_shift")
|
|
gauge_shift = -(gs and gs.x or border_margin)
|
|
end
|
|
self:digit_counter(tostring(info.red_value), border_margin, t.exam_border_counter, 0, y, gauge_shift)
|
|
end
|
|
|
|
if info.failed then
|
|
tex.draw_texture(t.exam_failed, { y = y })
|
|
else
|
|
local vl = tex.get_skin_config("dan_exam_value_left")
|
|
local live = tostring(info.counter_value)
|
|
if vl then
|
|
local vc = tex.get_texture_info("dan_info", "value_counter")
|
|
local json_x = (vc and vc.x[1]) or 920.0
|
|
for j = 1, #live do
|
|
tex.draw_texture(t.value_counter, { frame = live:byte(j) - 48,
|
|
x = vl.x + (j - 1) * value_margin - json_x, y = y })
|
|
end
|
|
if info.exam_type == "gauge" then
|
|
local pc = tex.get_texture_info("dan_info", "exam_percent")
|
|
local pjson = (pc and pc.x[2]) or 944.0
|
|
tex.draw_texture(t.exam_percent, { x = vl.x + #live * value_margin - pjson, y = y, index = 1 })
|
|
end
|
|
else
|
|
self:digit_counter(live, value_margin, t.value_counter, 0, y)
|
|
if info.exam_type == "gauge" then tex.draw_texture(t.exam_percent, { y = y, index = 1 }) end
|
|
end
|
|
end
|
|
|
|
if not all then
|
|
local sp = tex.get_skin_config("dan_exam_sub_row")
|
|
local sub_pitch = sp and sp.y or 50.0
|
|
local sub_margin = sp and sp.x or 20.0
|
|
local sb = tex.get_skin_config("dan_exam_sub_bar")
|
|
local sub_full = sb and sb.width or 234.0
|
|
for j = 0, 1 do
|
|
local sy = y + j * sub_pitch
|
|
tex.draw_texture(t.exam_sub_bg, { y = sy })
|
|
if j < info.song_count then -- not reached yet: stub only
|
|
tex.draw_texture(t.exam_sub_track, { y = sy })
|
|
self:fill(info.song_state[j + 1], sub_full * info.song_progress[j + 1], sy, true, all, frame_ms)
|
|
tex.draw_texture(t.exam_sub_front, { y = sy })
|
|
tex.draw_texture(t.exam_sub_chip, { frame = j, y = sy })
|
|
self:digit_counter(tostring(info.song_value[j + 1]), sub_margin, t.exam_sub_counter, 0, sy)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function DanGameDraw:draw(s)
|
|
local t = self.t
|
|
tex.draw_texture(t.total_notes, {})
|
|
|
|
local offset_y = (tex.get_skin_config("dan_exam_info_game") or tex.get_skin_config("dan_exam_info")).y
|
|
local slot = 0
|
|
for _, info in ipairs(s.rows) do
|
|
if info.exam_type ~= "gauge" then
|
|
if slot >= 3 then break end
|
|
self:exam_row(info, slot * offset_y, s.song_index, s.frame_ms)
|
|
slot = slot + 1
|
|
end
|
|
end
|
|
|
|
if s.dan_rank >= 0 and tex.get_option("dan_game_rank_plate") then
|
|
tex.draw_texture(t.rank_plate, { frame = s.dan_rank })
|
|
else
|
|
tex.draw_texture(t.frame, { frame = s.dan_color })
|
|
local hn = tex.get_skin_config("dan_game_hori_name")
|
|
local h = self.hori_name
|
|
h:draw({ x = hn.x - h.width / 2.0, y = hn.y, x2 = math.min(h.width, hn.width) - h.width })
|
|
end
|
|
end
|