diff --git a/src/scene/tracker/cover.cpp b/src/scene/tracker/cover.cpp index 4c6943f..eda80c5 100644 --- a/src/scene/tracker/cover.cpp +++ b/src/scene/tracker/cover.cpp @@ -3,6 +3,7 @@ #include "ta_parameter.hpp" #include "playlist.hpp" #include "texture.hpp" +#include "framebuffer.hpp" namespace scene::tracker::cover { @@ -13,10 +14,13 @@ namespace scene::tracker::cover { float texture_height; float width; float height; + float scale; }; int cover_ix = -1; + float zoom_interp = 0.0; + static const cover covers[] = { [thebeach] = { .texture_offset = texture::offset::thebeach, @@ -26,6 +30,7 @@ namespace scene::tracker::cover { .texture_height = 1.0f / 128.0f, .width = 72, .height = 72, + .scale = 6, }, [silvertrees] = { .texture_offset = texture::offset::silvertrees, @@ -35,6 +40,7 @@ namespace scene::tracker::cover { .texture_height = 1.0f / 128.0f, .width = 72, .height = 72, + .scale = 6, }, [redtree] = { .texture_offset = texture::offset::redtree, @@ -44,6 +50,7 @@ namespace scene::tracker::cover { .texture_height = 1.0f / 128.0f, .width = 72, .height = 72, + .scale = 6, }, [mountain] = { .texture_offset = texture::offset::mountain, @@ -53,6 +60,7 @@ namespace scene::tracker::cover { .texture_height = 1.0f / 128.0f, .width = 72, .height = 72, + .scale = 6, }, [mossycottage] = { .texture_offset = texture::offset::mossycottage, @@ -62,6 +70,7 @@ namespace scene::tracker::cover { .texture_height = 1.0f / 128.0f, .width = 72, .height = 72, + .scale = 6, }, [clocks] = { .texture_offset = texture::offset::clocks, @@ -71,21 +80,39 @@ namespace scene::tracker::cover { .texture_height = 1.0f / 128.0f, .width = 72, .height = 72, + .scale = 6, }, }; + constexpr inline vec3 transform_position_fs(const cover& cover, + const vec2& p, + float z) + { + float width = cover.width * cover.scale; + float height = cover.height * cover.scale; + float x = (framebuffer.px_width - width) / 2; + float y = (framebuffer.px_height - height) / 2; + + return { + x + p.x * width, + y + p.y * height, + z}; + } + constexpr inline vec3 transform_position(const cover& cover, const vec2& p, float x, float y, float z) { - float x_offset = (128.0f - cover.width) * 0.5f; - float y_offset = (128.0f - cover.width) * 0.5f; + float width = 128; + float height = 128; + float x_offset = (128.0f - width) * 0.5f; + float y_offset = (128.0f - height) * 0.5f; if (x_offset < 0) x_offset = 0; if (y_offset < 0) y_offset = 0; return { - x + x_offset + p.x * cover.width, - y + y_offset + p.y * cover.height, + x + x_offset + p.x * width, + y + y_offset + p.y * height, z }; } @@ -106,7 +133,37 @@ namespace scene::tracker::cover { {0, 1}, }; - void draw(ta_multiwriter& multi, float x, float y) + static inline vec3 lerp(const vec3& a, const vec3& b, float f) + { + float dx = b.x - a.x; + float dy = b.y - a.y; + float dz = b.z - a.z; + + return { + a.x + dx * f, + a.y + dy * f, + a.z + dz * f, + }; + } + + const static float alpha = 207; + + void draw_shroud(ta_parameter_writer& writer) + { + global_polygon_translucent(writer); + + uint32_t a = ((uint32_t)(zoom_interp * alpha)) << 24; + float z = 1.0 / 3.5f; + + quad_type_0(writer, + {0, 0, z}, + {(float)framebuffer.px_width, 0, z}, + {(float)framebuffer.px_width, (float)framebuffer.px_height, z}, + {0, (float)framebuffer.px_height, z}, + a | 0x202020); + } + + void draw(ta_multiwriter& multi, float x, float y, bool zoom) { if (cover_ix < 0) return; @@ -122,14 +179,34 @@ namespace scene::tracker::cover { texture_size, texture_control_word::pixel_format::_565); - float z = 1.0 / 10.0f; + float z = 1.0 / 3.0f; int base_color = 0xffffff; - vec3 ap = transform_position(cover, vtx[0], x, y, z); - vec3 bp = transform_position(cover, vtx[1], x, y, z); - vec3 cp = transform_position(cover, vtx[2], x, y, z); - vec3 dp = transform_position(cover, vtx[3], x, y, z); + if (zoom) { + zoom_interp += 0.05; + if (zoom_interp > 1) + zoom_interp = 1; + } else { + zoom_interp -= 0.05; + if (zoom_interp < 0) + zoom_interp = 0; + } + + vec3 ap0 = transform_position(cover, vtx[0], x, y, z); + vec3 bp0 = transform_position(cover, vtx[1], x, y, z); + vec3 cp0 = transform_position(cover, vtx[2], x, y, z); + vec3 dp0 = transform_position(cover, vtx[3], x, y, z); + + vec3 ap1 = transform_position_fs(cover, vtx[0], z); + vec3 bp1 = transform_position_fs(cover, vtx[1], z); + vec3 cp1 = transform_position_fs(cover, vtx[2], z); + vec3 dp1 = transform_position_fs(cover, vtx[3], z); + + vec3 ap = lerp(ap0, ap1, zoom_interp); + vec3 bp = lerp(bp0, bp1, zoom_interp); + vec3 cp = lerp(cp0, cp1, zoom_interp); + vec3 dp = lerp(dp0, dp1, zoom_interp); vec2 at = transform_texture(cover, vtx[0]); vec2 bt = transform_texture(cover, vtx[1]); @@ -142,5 +219,8 @@ namespace scene::tracker::cover { cp, ct, dp, dt, base_color); + + if (zoom_interp > 0) + draw_shroud(multi.op); } } diff --git a/src/scene/tracker/cover.hpp b/src/scene/tracker/cover.hpp index 8d9821f..61e148a 100644 --- a/src/scene/tracker/cover.hpp +++ b/src/scene/tracker/cover.hpp @@ -14,5 +14,5 @@ namespace scene::tracker::cover { clocks, }; - void draw(ta_multiwriter& multi, float x, float y); + void draw(ta_multiwriter& multi, float x, float y, bool zoom); } diff --git a/src/scene/tracker/scene.cpp b/src/scene/tracker/scene.cpp index 9fc9276..9a15543 100644 --- a/src/scene/tracker/scene.cpp +++ b/src/scene/tracker/scene.cpp @@ -148,7 +148,11 @@ widget::left_aligned top(0, 0, 20, top_children, top_length); namespace scene::tracker { + const float cover_x = 480; + const float cover_y = 5; + static bool cover_zoom = false; static bool options = false; + static bool last_a[4] = {}; static bool last_start[4] = {}; const struct scene::scene scene = { @@ -183,14 +187,39 @@ namespace scene::tracker { playlist::next(); } + void update_pick(cursor::cursor& c) + { + widget::widget * w = top.pick(c.x, c.y); + if (w != nullptr) { + w->click(); + } + } + + static bool a_click(int i) + { + bool last = last_a[i]; + cursor::cursor& c = cursor::state[i]; + last_a[i] = c.a; + return c.a && c.a != last; + } + void update() { for (int i = 0; i < 4; i++) { cursor::cursor& c = cursor::state[i]; - if (c.active && c.a) { - widget::widget * w = top.pick(c.x, c.y); - if (w != nullptr) { - w->click(); + if (c.active) { + if (cover_zoom) { + if (a_click(i)) + cover_zoom = false; + } else { + if (c.x >= cover_x && c.x <= (cover_x + 128) && + c.y >= cover_y && c.y <= (cover_y + 128)) { + if (a_click(i)) + cover_zoom = true; + } else { + if (c.a) + update_pick(c); + } } } } @@ -271,7 +300,7 @@ namespace scene::tracker { tracklist::draw(multi, top.width + 5, 5); float y = top.y() + top.height + 5; channel_status::draw(multi, 5, y); - cover::draw(multi, 480, 5); + cover::draw(multi, cover_x, cover_y, cover_zoom); y += channel_status::height + 10; notes::draw(multi, 5, y);