dan select: back chip, chip names, cursor and course rows #63
No files matched your search
Binary file not shown.
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"folder": {
|
||||||
|
"x": -44,
|
||||||
|
"y": 16
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -190,7 +190,7 @@
|
|||||||
},
|
},
|
||||||
"song_label": {
|
"song_label": {
|
||||||
"x": 430,
|
"x": 430,
|
||||||
"y": 230
|
"y": 246
|
||||||
},
|
},
|
||||||
"exam_seg_label": {
|
"exam_seg_label": {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
@@ -204,5 +204,9 @@
|
|||||||
"x": 100,
|
"x": 100,
|
||||||
"y": 505
|
"y": 505
|
||||||
},
|
},
|
||||||
"difficulty_ura": {}
|
"difficulty_ura": {},
|
||||||
|
"difficulty_level": {
|
||||||
|
"x": 538,
|
||||||
|
"y": 287
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
"combo_color_tiers": true,
|
"combo_color_tiers": true,
|
||||||
"gauge_cell_fade_in": true,
|
"gauge_cell_fade_in": true,
|
||||||
"dan_exam_grid": true,
|
"dan_exam_grid": true,
|
||||||
|
"dan_chip_name_black": true,
|
||||||
"disable_chara_3d": false
|
"disable_chara_3d": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -833,6 +834,19 @@
|
|||||||
"height": 88,
|
"height": 88,
|
||||||
"font_size": 42
|
"font_size": 42
|
||||||
},
|
},
|
||||||
|
"dan_back_label": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 89,
|
||||||
|
"width": 60,
|
||||||
|
"height": 88,
|
||||||
|
"font_size": 42,
|
||||||
|
"text": {
|
||||||
|
"en": "Back",
|
||||||
|
"ja": "戻る",
|
||||||
|
"zh": "返回",
|
||||||
|
"ko": "뒤로"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dan_result_chara": {
|
"dan_result_chara": {
|
||||||
"x": 187,
|
"x": 187,
|
||||||
"y": 934
|
"y": 934
|
||||||
|
|||||||
@@ -47,12 +47,14 @@ function DanSelect.new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- pos: selected chip x (the textures' own json positions carry the rest);
|
-- pos: selected chip x (the textures' own json positions carry the rest);
|
||||||
-- now_ms: engine clock; moved_ms: ms since the last ribbon step (-1 = never).
|
-- now_ms: engine clock; moved_ms: ms since the last ribbon step (-1 = never);
|
||||||
local function draw_cursor(self, pos, now_ms, moved_ms)
|
-- y: how far the selected chip has dropped (see draw_box below).
|
||||||
|
local function draw_cursor(self, pos, now_ms, moved_ms, y)
|
||||||
|
y = y or 0
|
||||||
if self.t_cursor then
|
if self.t_cursor then
|
||||||
local f = (now_ms * 0.06) % 60
|
local f = (now_ms * 0.06) % 60
|
||||||
local a = CUR:get("#259@0", f, "a") or 1
|
local a = CUR:get("#259@0", f, "a") or 1
|
||||||
tex.draw_texture(self.t_cursor, { x = pos, fade = a })
|
tex.draw_texture(self.t_cursor, { x = pos, y = y, fade = a })
|
||||||
end
|
end
|
||||||
if moved_ms and moved_ms >= 0 then
|
if moved_ms and moved_ms >= 0 then
|
||||||
local f = moved_ms * 0.06
|
local f = moved_ms * 0.06
|
||||||
@@ -61,10 +63,10 @@ local function draw_cursor(self, pos, now_ms, moved_ms)
|
|||||||
local a = ARW:get("#261@0", f, "a") or 0
|
local a = ARW:get("#261@0", f, "a") or 0
|
||||||
if a > 0 then
|
if a > 0 then
|
||||||
if self.t_arrow_r then
|
if self.t_arrow_r then
|
||||||
tex.draw_texture(self.t_arrow_r, { x = pos + drift, fade = a })
|
tex.draw_texture(self.t_arrow_r, { x = pos + drift, y = y, fade = a })
|
||||||
end
|
end
|
||||||
if self.t_arrow_l then
|
if self.t_arrow_l then
|
||||||
tex.draw_texture(self.t_arrow_l, { x = pos - drift, fade = a })
|
tex.draw_texture(self.t_arrow_l, { x = pos - drift, y = y, fade = a })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -73,6 +75,15 @@ end
|
|||||||
|
|
||||||
if HAS_CLIPS then DanSelect.draw_cursor = draw_cursor end
|
if HAS_CLIPS then DanSelect.draw_cursor = draw_cursor end
|
||||||
|
|
||||||
|
-- The level is the cabinet's own art, one "star + number" image per level
|
||||||
|
-- (yellow_box/difficulty_level, frames 1..10 and 10+), in place of the parent's star and
|
||||||
|
-- level digits, which are held back.
|
||||||
|
local function draw_level(level, x, y, f)
|
||||||
|
local id = tex.get_texture("dan_select/yellow_box/difficulty_level")
|
||||||
|
if not id or level < 1 then return end
|
||||||
|
tex.draw_texture(id, { frame = math.min(level, 11) - 1, x = x, y = y, fade = f })
|
||||||
|
end
|
||||||
|
|
||||||
-- The course's clear stamp (yellow_box/clear_mark) sits over the dan plate and Don, as the
|
-- The course's clear stamp (yellow_box/clear_mark) sits over the dan plate and Don, as the
|
||||||
-- cabinet's stamp_detail does (it is above don_1p). The parent draws it with the box, under
|
-- cabinet's stamp_detail does (it is above don_1p). The parent draws it with the box, under
|
||||||
-- both, so it is held back there and drawn with the title, which the engine draws after
|
-- both, so it is held back there and drawn with the title, which the engine draws after
|
||||||
@@ -82,16 +93,35 @@ local held_stamp -- shared: the boxes and the title can be drawn through diffe
|
|||||||
if parent_open then
|
if parent_open then
|
||||||
function DanSelect:draw_dan_open(box)
|
function DanSelect:draw_dan_open(box)
|
||||||
local stamp = tex.get_texture("dan_select/yellow_box/clear_mark")
|
local stamp = tex.get_texture("dan_select/yellow_box/clear_mark")
|
||||||
if not stamp or box.clear_mark <= 0 then return parent_open(self, box) end
|
local level = tex.get_texture("dan_select/yellow_box/difficulty_level")
|
||||||
|
local hide = {}
|
||||||
|
if level then
|
||||||
|
for _, n in ipairs({ "difficulty_star", "difficulty_num", "difficulty_x" }) do
|
||||||
|
local t = tex.get_texture("dan_select/yellow_box/" .. n)
|
||||||
|
if t then hide[#hide + 1] = t end
|
||||||
|
end
|
||||||
|
end
|
||||||
local draw = tex.draw_texture
|
local draw = tex.draw_texture
|
||||||
tex.draw_texture = function(id, p)
|
tex.draw_texture = function(id, p)
|
||||||
if id == stamp then return end
|
if id == stamp then return end
|
||||||
|
for _, t in ipairs(hide) do -- handles compare with ==, not as table keys
|
||||||
|
if id == t then return end
|
||||||
|
end
|
||||||
return draw(id, p)
|
return draw(id, p)
|
||||||
end
|
end
|
||||||
local ok, err = pcall(parent_open, self, box)
|
local ok, err = pcall(parent_open, self, box)
|
||||||
tex.draw_texture = draw
|
tex.draw_texture = draw
|
||||||
if not ok then error(err, 0) end
|
if not ok then error(err, 0) end
|
||||||
held_stamp = { id = stamp, frame = box.clear_mark - 1, fade = box.open_fade.attribute }
|
local f = box.open_fade.attribute
|
||||||
|
local off = tex.get_skin_config("dan_yellow_box_offset") or { x = 0, y = 0 }
|
||||||
|
if level then
|
||||||
|
for i = 0, box:song_count() - 1 do
|
||||||
|
draw_level(box:song_level(i), i * (off.x or 0), i * (off.y or 0), f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if stamp and box.clear_mark > 0 then
|
||||||
|
held_stamp = { id = stamp, frame = box.clear_mark - 1, fade = f }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function DanSelect:draw_title()
|
function DanSelect:draw_title()
|
||||||
@@ -101,3 +131,135 @@ if parent_open then
|
|||||||
if s then tex.draw_texture(s.id, { frame = s.frame, fade = s.fade }) end
|
if s then tex.draw_texture(s.id, { frame = s.frame, fade = s.fade }) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- The back entry is one more chip in the top strip (back/folder, laid out like box/folder);
|
||||||
|
-- the parent's opening board is its own layout, so nothing opens under it here.
|
||||||
|
-- Its label comes from skin_config dan_back_label, so it follows the language setting. It is set
|
||||||
|
-- like the dan chip names (black, no outline: dan_chip_name_black), vertical for CJK and
|
||||||
|
-- across, squeezed to the chip, for other languages.
|
||||||
|
local CJK = { ja = true, zh = true, ko = true, tw = true, cn = true }
|
||||||
|
local back_label
|
||||||
|
local function get_back_label()
|
||||||
|
if back_label == nil then
|
||||||
|
local cfg = tex.get_skin_config("dan_back_label")
|
||||||
|
if not cfg then back_label = false; return false end
|
||||||
|
local lang = tex.language()
|
||||||
|
local vertical = CJK[lang] or CJK[lang:sub(1, 2)] or false
|
||||||
|
back_label = {
|
||||||
|
cfg = cfg,
|
||||||
|
vertical = vertical,
|
||||||
|
main = text.create_raw_text(tex.skin_text("dan_back_label"), cfg.font_size,
|
||||||
|
{ 0, 0, 0, 255 }, { 0, 0, 0, 255 }, vertical, 0, 2),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return back_label
|
||||||
|
end
|
||||||
|
|
||||||
|
local function draw_back_label(bx, fade, y)
|
||||||
|
local label = get_back_label()
|
||||||
|
if not label then return end
|
||||||
|
local cfg, main = label.cfg, label.main
|
||||||
|
local sx, sy = 1, 1
|
||||||
|
if label.vertical then
|
||||||
|
sy = math.min(1, cfg.height / main.height)
|
||||||
|
else
|
||||||
|
sx = math.min(1, cfg.width / main.width) -- width: chip face less the border
|
||||||
|
end
|
||||||
|
local w, h = main.width * sx, main.height * sy
|
||||||
|
main:draw({ x = bx + cfg.x - w / 2, y = cfg.y + (cfg.height - h) / 2 + y,
|
||||||
|
x2 = w - main.width, y2 = h - main.height, fade = fade })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The selected chip drops below the strip, as the cabinet's does, easing there and back.
|
||||||
|
-- Only draw_cursor (called after every box) is told where the cursor is, so the boxes are
|
||||||
|
-- held back in draw_box and drawn from draw_cursor.
|
||||||
|
local SELECTED_DROP = 22
|
||||||
|
local DROP_MS = 60 -- time constant of the ease
|
||||||
|
local drop = {} -- chip key -> current drop
|
||||||
|
local held_boxes = {}
|
||||||
|
local last_ms
|
||||||
|
|
||||||
|
local function chip_key(box)
|
||||||
|
return box.is_back and "\0back" or box.text_name
|
||||||
|
end
|
||||||
|
|
||||||
|
local function chip_drop(box)
|
||||||
|
return drop[chip_key(box)] or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function draw_chip_name(box, bx, y, fade)
|
||||||
|
local name = box:chip_name()
|
||||||
|
if not name then return end
|
||||||
|
local nb = tex.get_skin_config("dan_chip_name") or { x = 0, y = 0 }
|
||||||
|
name:draw({
|
||||||
|
x = bx + nb.x - name.width / 2,
|
||||||
|
y = nb.y + y,
|
||||||
|
y2 = math.min(name.height, nb.height or name.height) - name.height,
|
||||||
|
fade = fade,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- the chip as the parent draws it (folder, stamp, name), at its drop
|
||||||
|
function DanSelect:draw_dan_closed(box)
|
||||||
|
local bx, fade, y = box:box_x(), box.fade.attribute, chip_drop(box)
|
||||||
|
local id = tex.get_texture("dan_select/box/folder")
|
||||||
|
if id then tex.draw_texture(id, { frame = box.dan_color, x = bx, y = y, fade = fade }) end
|
||||||
|
local mark = box.clear_mark > 0 and tex.get_texture("dan_select/box/clear_mark")
|
||||||
|
if mark then tex.draw_texture(mark, { frame = box.clear_mark - 1, x = bx, y = y, fade = fade }) end
|
||||||
|
draw_chip_name(box, bx, y, fade)
|
||||||
|
end
|
||||||
|
|
||||||
|
function DanSelect:draw_back_box(box)
|
||||||
|
local bx, fade, y = box:box_x(), box.fade.attribute, chip_drop(box)
|
||||||
|
local id = tex.get_texture("dan_select/back/folder")
|
||||||
|
if id then tex.draw_texture(id, { x = bx, y = y, fade = fade }) end
|
||||||
|
draw_back_label(bx, fade, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The cursor's glow goes over the chip, its emblem and name (they grey under it, as on the
|
||||||
|
-- cabinet) but not over the clear stamp, which is drawn again on top of it.
|
||||||
|
local function draw_chip_front(box)
|
||||||
|
if box.is_back or box.clear_mark <= 0 then return end
|
||||||
|
local mark = tex.get_texture("dan_select/box/clear_mark")
|
||||||
|
if mark then
|
||||||
|
tex.draw_texture(mark, { frame = box.clear_mark - 1, x = box:box_x(), y = chip_drop(box),
|
||||||
|
fade = box.fade.attribute })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local parent_draw_box = DanSelect.draw_box
|
||||||
|
function DanSelect:draw_box(box)
|
||||||
|
held_boxes[#held_boxes + 1] = box
|
||||||
|
end
|
||||||
|
|
||||||
|
local cursor_parent = DanSelect.draw_cursor
|
||||||
|
function DanSelect:draw_cursor(pos, now_ms, moved_ms)
|
||||||
|
local boxes = held_boxes
|
||||||
|
held_boxes = {}
|
||||||
|
local k = last_ms and math.min(1, math.max(0, now_ms - last_ms) / DROP_MS) or 1
|
||||||
|
last_ms = now_ms
|
||||||
|
local selected
|
||||||
|
for _, box in ipairs(boxes) do
|
||||||
|
local key = chip_key(box)
|
||||||
|
local is_sel = math.abs(box:box_x() - pos) < 1
|
||||||
|
if is_sel then selected = box end
|
||||||
|
local d = drop[key] or 0
|
||||||
|
d = d + ((is_sel and SELECTED_DROP or 0) - d) * k
|
||||||
|
drop[key] = (math.abs(d) >= 0.05) and d or nil
|
||||||
|
end
|
||||||
|
-- draw every box even if one fails, then report the first failure
|
||||||
|
local err
|
||||||
|
for _, box in ipairs(boxes) do
|
||||||
|
local ok, e = pcall(parent_draw_box, self, box)
|
||||||
|
if not ok and not err then err = e end
|
||||||
|
end
|
||||||
|
if err then error(err, 0) end
|
||||||
|
local y = selected and chip_drop(selected) or 0
|
||||||
|
if cursor_parent then
|
||||||
|
cursor_parent(self, pos, now_ms, moved_ms, y)
|
||||||
|
elseif self.t_cursor then
|
||||||
|
tex.draw_texture(self.t_cursor, { x = pos, y = y })
|
||||||
|
end
|
||||||
|
if selected then draw_chip_front(selected) end
|
||||||
|
return true
|
||||||
|
end
|
||||||
Reference in new issue
Block a user