diff --git a/config.lua b/config.lua index b4f45ef..e44e40d 100644 --- a/config.lua +++ b/config.lua @@ -64,12 +64,15 @@ add_setting("UI", "area_based_gui_scale", false, { return true end, }) -add_setting("UI", "background_preview", true, { +add_setting("UI", "background_preview", "minimal", { + options = { "minimal", "full" }, onchange = function(value) - if value then + if value == "full" then require("ui.screens.levelselect.level").resume_preview() + require("ui.screens.levelselect.level").current_preview_active = false else require("game_handler").stop() + require("ui.screens.levelselect.level").current_preview_active = true end end, }) diff --git a/game_handler/assets.lua b/game_handler/assets.lua index 2b73ce6..57a4cb0 100644 --- a/game_handler/assets.lua +++ b/game_handler/assets.lua @@ -442,10 +442,12 @@ function assets.get_pack(version, id, headless) local style_module = require("compat.game" .. pack_data.game_version .. ".style") local set_function = style_module.select or style_module.set for level_id, level in pairs(pack_data.levels) do - -- get side count + -- get side count and rotation speed local sides = 6 + local rotation_speed = 0 if version == 192 then sides = level.sides or 6 + rotation_speed = level.rotation_speed or 0 else local lua_path = pack_data.path .. "/" .. level.lua_file if love.filesystem.getInfo(lua_path) then @@ -454,9 +456,15 @@ function assets.get_pack(version, id, headless) for match in code:gmatch("function.-onInit.-l_setSides%((.-)%).-end") do sides = tonumber(match) or sides end + -- match set rotation speed calls in the lua file to get the rotation speed + for match in code:gmatch("function.-onInit.-l_setRotationSpeed%((.-)%).-end") do + rotation_speed = tonumber(match) or rotation_speed + end end end sides = math.max(sides, 3) + -- convert to rad/s + rotation_speed = rotation_speed * math.pi * 10 / 3 -- get colors set_function(pack_data.styles[level.style_id]) @@ -491,6 +499,7 @@ function assets.get_pack(version, id, headless) r, g, b, a = style_module.get_second_color() end pack_data.preview_data[level_id] = { + rotation_speed = rotation_speed, sides = sides, background_colors = colors, pivot_color = main_color, diff --git a/main.lua b/main.lua index 5b2e2ce..ec91e44 100644 --- a/main.lua +++ b/main.lua @@ -198,6 +198,7 @@ local main = async(function() ui.open_screen("levelselect") end end) + local level = require("ui.screens.levelselect.level") -- function is called every frame by love return function() @@ -238,6 +239,9 @@ local main = async(function() love.graphics.origin() love.graphics.clear(0, 0, 0, 1) game_handler.draw() + if level.current_preview_active and not game_handler.is_running() then + level.current_preview:draw(true) + end ui.draw() love.graphics.present() end diff --git a/ui/elements/level_preview.lua b/ui/elements/level_preview.lua index f222e93..4891c9b 100644 --- a/ui/elements/level_preview.lua +++ b/ui/elements/level_preview.lua @@ -1,9 +1,7 @@ local element = require("ui.elements.element") -local game_handler = require("game_handler") +local preview = require("ui.screens.levelselect.level_preview") local signal = require("ui.anim.signal") local theme = require("ui.theme") -local threadify = require("threadify") -local download = threadify.require("ui.overlay.packs.download_thread") local level_preview = {} level_preview.__index = setmetatable(level_preview, { __index = element, @@ -13,9 +11,7 @@ local SIZE = 96 function level_preview:new(game_version, pack, level, options) local obj = element.new( setmetatable({ - game_version = game_version, - pack = pack, - level = level, + preview = preview:new(), background_color = theme.get("background_color"), border_color = theme.get("border_color"), border_thickness = theme.get("border_thickness"), @@ -25,20 +21,7 @@ function level_preview:new(game_version, pack, level, options) }, level_preview), options ) - if options.has_pack == nil then - options.has_pack = true - end - local promise - if options.has_pack then - promise = game_handler.get_preview_data(game_version, pack) - else - promise = download.get_preview_data(game_version, pack) - end - if promise then - promise:done(function(data) - obj.data = data[level] - end) - end + obj.preview:set(game_version, pack, level, options.has_pack) return obj end @@ -55,42 +38,14 @@ end function level_preview:draw_element() local half_size = SIZE * self.scale / 2 - if self.data then + if self.preview.data then love.graphics.translate(half_size, half_size) love.graphics.scale(self.scale, self.scale) - self.vertices = self.vertices or {} - local distance = 48 - local pivot_thickness = 2 - for i = 1, self.data.sides do - local angle1 = i * 2 * math.pi / self.data.sides - math.pi / 2 - local cos1 = math.cos(angle1) - local sin1 = math.sin(angle1) - local angle2 = angle1 + 2 * math.pi / self.data.sides - local cos2 = math.cos(angle2) - local sin2 = math.sin(angle2) - -- background - love.graphics.setColor(self.data.background_colors[i]) - love.graphics.polygon("fill", 0, 0, cos1 * distance, sin1 * distance, cos2 * distance, sin2 * distance) - self.vertices[(i - 1) * 2 + 1] = cos1 * distance - self.vertices[i * 2] = sin1 * distance - end - -- pivot - love.graphics.setColor(self.data.pivot_color) - local pivot_mult = 1 / 3 + 1 / distance - love.graphics.scale(pivot_mult, pivot_mult) - love.graphics.setLineWidth(pivot_thickness / pivot_mult) - love.graphics.polygon("line", self.vertices) - love.graphics.scale(1 / pivot_mult, 1 / pivot_mult) - -- cap - local cap_mult = 1 / 3 - love.graphics.scale(cap_mult, cap_mult) - love.graphics.setColor(self.data.cap_color) - love.graphics.polygon("fill", self.vertices) - love.graphics.scale(1 / cap_mult, 1 / cap_mult) + self.preview:draw() -- border love.graphics.setColor(self.border_color) love.graphics.setLineWidth(self.border_thickness) - love.graphics.polygon("line", self.vertices) + love.graphics.polygon("line", self.preview.vertices) else love.graphics.setColor(self.border_color) love.graphics.setLineWidth(self.scale * 5) diff --git a/ui/overlay/settings/init.lua b/ui/overlay/settings/init.lua index a1dae91..4a0d96f 100644 --- a/ui/overlay/settings/init.lua +++ b/ui/overlay/settings/init.lua @@ -135,6 +135,10 @@ local function create_setting(name, property, value) layout:init_bindings() end elseif property.options and #property.options > 0 then + if type(value) ~= "string" then + config.set(name, property.default) + value = property.default + end -- multiple choice dropdown setting local option_quads = {} local dropdown diff --git a/ui/screens/game/init.lua b/ui/screens/game/init.lua index 8f02716..1251f3d 100644 --- a/ui/screens/game/init.lua +++ b/ui/screens/game/init.lua @@ -4,6 +4,7 @@ local quad = require("ui.elements.quad") local game_handler = require("game_handler") local death_overlay = require("ui.overlay.death") local buttons = require("ui.screens.game.controls") +local config = require("config") local args = require("args") local timer = quad:new({ @@ -46,7 +47,7 @@ game_handler.onupdate = function() if game_handler.is_replaying() then if not args.render then -- TODO: show appropriate ui when replay ends (retry/back buttons would be wrong here) - back_to_menu() + back_to_menu(config.get("background_preview") ~= "full") end elseif not death_overlay.is_open then death_overlay:open() diff --git a/ui/screens/levelselect/level.lua b/ui/screens/levelselect/level.lua index 8f9bc26..12a65e4 100644 --- a/ui/screens/levelselect/level.lua +++ b/ui/screens/levelselect/level.lua @@ -1,3 +1,4 @@ +local preview = require("ui.screens.levelselect.level_preview") local level_preview = require("ui.elements.level_preview") local game_handler = require("game_handler") local config = require("config") @@ -8,18 +9,26 @@ local flex = require("ui.layout.flex") local options = require("ui.screens.levelselect.options") local theme = require("ui.theme") +local t = {} + +t.current_preview = preview:new() +t.current_preview_active = false local pending_promise local last_pack, last_level local set_preview_level = async(function(pack, level) last_pack = pack last_level = level - if config.get("background_preview") then + if config.get("background_preview") == "full" then if pending_promise then async.await(pending_promise) pending_promise = nil end game_handler.set_version(pack.game_version) pending_promise = game_handler.preview_start(pack.id, level.id, {}) + else + game_handler.stop() + t.current_preview:set(pack.game_version, pack.id, level.id) + t.current_preview_active = true end end) @@ -36,8 +45,6 @@ end) local level_element_selected -local t = {} - function t.resume_preview() if last_pack and last_level then set_preview_level(last_pack, last_level) @@ -49,11 +56,11 @@ function t.create(state, pack, level, extra_info) extra_info.song = extra_info.song or "no song" extra_info.composer = extra_info.composer or "no composer" local music = extra_info.song .. "\n" .. extra_info.composer - local preview = level_preview:new(pack.game_version, pack.id, level.id, { style = { padding = 4 } }) + local preview_elem = level_preview:new(pack.game_version, pack.id, level.id, { style = { padding = 4 } }) return quad:new({ child_element = flex:new({ flex:new({ - preview, + preview_elem, flex:new({ label:new(level.name, { font_size = 40, wrap = true, style = { padding = 5 } }), label:new(level.author, { font_size = 26, wrap = true, style = { padding = 5 } }),