From 8fca894929db69d8496cc630540818216477f99f Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:24:37 -0400 Subject: [PATCH 01/14] start doing bg stuff --- lovely/backgrounds.toml | 126 ++++++++++++++++++++ lovely/screenshader_rendering.toml | 3 + src/core.lua | 3 +- src/game_object.lua | 6 + src/game_objects/backgrounds.lua | 179 +++++++++++++++++++++++++++++ src/utils/backgrounds.lua | 36 ++++++ 6 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 lovely/backgrounds.toml create mode 100644 src/game_objects/backgrounds.lua create mode 100644 src/utils/backgrounds.lua diff --git a/lovely/backgrounds.toml b/lovely/backgrounds.toml new file mode 100644 index 000000000..c04bffaf9 --- /dev/null +++ b/lovely/backgrounds.toml @@ -0,0 +1,126 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -1 + +# Add canvasses for background drawing +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = ''' +G.CANVAS = love.graphics.newCanvas(w*G.CANV_SCALE, h*G.CANV_SCALE, {type = '2d', readable = true}) +G.CANVAS:setFilter('linear', 'linear') +''' +position = "after" +payload = ''' + +''' +match_indent = true + +# Handle the vanilla background shaders +# Sprite:draw +[[patches]] +[patches.pattern] +target = "engine/sprite.lua" +pattern = ''' +elseif _shader == 'vortex' then + G.SHADERS['vortex']:send('vortex_amt', G.TIMERS.REAL - (G.vortex_time or 0)) +''' +position = "after" +payload = ''' +elseif _shader == 'background' then + G.SHADERS['splash']:send('time', G.TIMERS.REAL_SHADER) + G.SHADERS['splash']:send('spin_time', G.TIMERS.BACKGROUND) + G.SHADERS['splash']:send('colour_1', G.C.BACKGROUND.C) + G.SHADERS['splash']:send('colour_2', G.C.BACKGROUND.L) + G.SHADERS['splash']:send('colour_3', G.C.BACKGROUND.D) + G.SHADERS['splash']:send('contrast', G.C.BACKGROUND.contrast) + G.SHADERS['splash']:send('spin_amount', G.ARGS.spin and G.ARGS.spin.amount or 0) +elseif shader == 'splash' then + G.SHADERS['splash']:send('time', G.TIMERS.REAL) + G.SHADERS['splash']:send('vort_speed', 0.4) + G.SHADERS['splash']:send('colour_1', G.C.BLUE) + G.SHADERS['splash']:send('colour_2', G.C.WHITE) + G.SHADERS['splash']:send('mid_flash', SMODS.splash_flash) + G.SHADERS['splash']:send('vort_offset', (2*90.15315131*os.time())%100000) +''' +match_indent = true + +# Make splash_args global +# Game:main_menu, Game:demo_cta +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = ''' +local splash_args = {mid_flash = change_context == 'splash' and 1.6 or 0.} + ease_value(splash_args, 'mid_flash', -(change_context == 'splash' and 1.6 or 0), nil, nil, nil, 4) +''' +position = "after" +payload = ''' +SMODS.splash_flash = change_context == 'splash' and 1.6 or 0 +ease_value(SMODS, 'splash_flash', -(change_context == 'splash' and 1.6 or 0), nil, nil, nil, 4) +''' +match_indent = true + +# Draw custom bgs +# Game:draw +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = ''' +if G.SPLASH_BACK then + if G.debug_background_toggle then + love.graphics.clear({0,1,0,1}) + else + love.graphics.push() + G.SPLASH_BACK:translate_container() + G.SPLASH_BACK:draw() + love.graphics.pop() + end + end +''' +position = "after" +payload = ''' +if SMODS.PRIMARY_BG_CANVAS then + if G.debug_background_toggle then + love.graphics.clear({0,1,0,1}) + else + love.graphics.push() + SMODS.draw_background() + love.graphics.pop() + end +end + +''' +match_indent = true + +# Create SMODS bg stuff +# Game:main_menu, Game:demo_cta, Game:sandbox +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = '''if G.SPLASH_BACK then G.SPLASH_BACK:remove(); G.SPLASH_BACK = nil end''' +position = "after" +payload = ''' +SMODS.create_bg_canvasses() +''' +match_indent = true + +# Game:start_run +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = ''' +G.SPLASH_BACK:set_alignment({ + major = G.play, + type = 'cm', + bond = 'Strong', + offset = {x=0,y=0} + }) +''' +position = "after" +payload = ''' +SMODS.create_bg_canvasses() +''' +match_indent = true + diff --git a/lovely/screenshader_rendering.toml b/lovely/screenshader_rendering.toml index b96b020fd..e20ad9126 100644 --- a/lovely/screenshader_rendering.toml +++ b/lovely/screenshader_rendering.toml @@ -69,5 +69,8 @@ position = "after" payload = ''' G.SHADER_CANVAS_A = SMODS.create_canvas() G.SHADER_CANVAS_B = SMODS.create_canvas() +-- easier to just stick this here +SMODS.BG_CANVAS_1.canvas = SMODS.create_canvas() +SMODS.BG_CANVAS_2.canvas = SMODS.create_canvas() ''' match_indent = true \ No newline at end of file diff --git a/src/core.lua b/src/core.lua index 9102d8599..948d63975 100644 --- a/src/core.lua +++ b/src/core.lua @@ -6,7 +6,8 @@ for _, path in ipairs { "src/overrides.lua", "src/game_object.lua", "src/compat_0_9_8.lua", - "src/utils/weights.lua" + "src/utils/weights.lua", + "src/utils/backgrounds.lua", } do assert(load(SMODS.NFS.read(SMODS.path..path), ('=[SMODS _ "%s"]'):format(path)))() end diff --git a/src/game_object.lua b/src/game_object.lua index e067134fd..f01ecf56b 100644 --- a/src/game_object.lua +++ b/src/game_object.lua @@ -399,6 +399,12 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. assert(load(SMODS.NFS.read(SMODS.path..'src/game_objects/attributes.lua'), ('=[SMODS _ "src/game_objects/attributes.lua"]')))() + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Background + ------------------------------------------------------------------------------------------------- + + assert(load(SMODS.NFS.read(SMODS.path..'src/game_objects/backgrounds.lua'), ('=[SMODS _ "src/game_objects/backgrounds.lua"]')))() + ------------------------------------------------------------------------------------------------- ----- INTERNAL API CODE GameObject._Loc_Pre ------------------------------------------------------------------------------------------------- diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua new file mode 100644 index 000000000..bfcf03741 --- /dev/null +++ b/src/game_objects/backgrounds.lua @@ -0,0 +1,179 @@ +-- bg draw steps; allows for creating multilayered backgrounds +SMODS.BackgroundDrawSteps = {} +SMODS.BackgroundDrawStep = SMODS.GameObject:extend { + obj_table = SMODS.BackgroundDrawSteps, + obj_buffer = {}, + required_params = { + 'key', + 'order', + 'func', + }, + -- func = function(bg) end, + set = "Background Draw Step", + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + SMODS.BackgroundDrawStep.super.register(self) + end, + inject = function() end, + post_inject_class = function(self) + table.sort(self.obj_buffer, function(_self, _other) return self.obj_table[_self].order < self.obj_table[_other].order end) + end, +} + +SMODS.BackgroundDrawStep { + key = "base", + order = -math.huge, + func = function(self) + if self.children.base then + self.children.base:draw_shader(self.shader or "dissolve") + end + end, +} + + +SMODS.BackgroundCanvas = Moveable:extend() + +function SMODS.BackgroundCanvas:init(X, Y, W, H, prototype, alpha) + Moveable.init(self, X, Y, W, H) + + self.states.collide.can = false + self.states.hover.can = false + self.states.drag.can = false + self.states.click.can = false + + self.alpha = alpha + self.canvas = SMODS.create_canvas() + self.children = {} + + if prototype then + self:set_active_bg(prototype) + end +end + +function SMODS.BackgroundCanvas:draw() + if self.alpha == 0 then return end + local fading = self.alpha ~= 1 + if fading then love.graphics.setCanvas(self.canvas) end + for _, k in ipairs(SMODS.DrawStep.obj_buffer) do + SMODS.BackgroundDrawSteps[k].func(self) + end + if fading then + love.graphics.setCanvas() + love.graphics.draw(self.canvas, 0, 0) + end +end + +function SMODS.BackgroundCanvas:set_sprites() + self.children = self.children or {} + local obj = self.prototype + + local atlas = obj.atlas or 'ui_1' + local pos = obj.pos or {x = obj.atlas and 2 or 0, y = 0} + self.children.base = SMODS.create_sprite(self.T.x, self.T.y, self.T.w, self.T.h, atlas, pos) + self.children.base:set_alignment({ + major = self, + type = 'cm', + bond = 'Glued', + offset = {x=0,y=0} + }) + + if obj.set_sprites and type(obj.set_sprites) == 'function' then + obj:set_sprites(self) + end +end + +function SMODS.BackgroundCanvas:set_active_bg(prototype) + self.prototype = prototype + self.shader = prototype.shader + + if prototype.set_active and type(prototype.set_active) == "function" then + prototype:set_active(self) + end + + for _, v in pairs(self.children) do v:remove(); v = nil end + self:set_sprites() +end + +function SMODS.BackgroundCanvas:remove() + for _, v in pairs(self.children) do v:remove(); v = nil end + Moveable.remove(self) +end + +function SMODS.BackgroundCanvas:update() + local obj = self.prototype + if obj.update and type(obj.update) == 'function' then + obj:update(self) + end +end + +function SMODS.BackgroundCanvas:ease_alpha(target, delay) + if target == self.alpha then return end + target = math.min(1, math.max(target, 0)) + G.E_MANAGER:add_event(Event({ + trigger = "ease", + ref_table = self, + ref_value = "alpha", + ease_to = target, + delay = delay or 2, + })) +end + +SMODS.Backgrounds = {} +SMODS.Background = SMODS.GameObject:extend { + obj_table = SMODS.Backgrounds, + set = 'Background', + obj_buffer = {}, + required_params = { + 'key', + }, + send_vars = nil, -- same as Shader.send_vars + select_background = nil, -- should this bg be used, works like SMODS.Sounds:select_music_track + + set_sprites = nil, -- sets sprites + set_active = nil, -- runs when bg becomes active + update = nil, -- runs on update + + inject = function(self) + -- assert(self.shader or self.path, "Background " .. self.key .. " not given shader key or path") + if self.path and (not self.shader) then + SMODS.Shader.inject(self) + self.shader = self.key + end + end, + get_current_background = function(self) + local track + local maxp = -math.huge + for _, v in ipairs(self.obj_buffer) do + local s = self.obj_table[v] + if type(s.select_background) == 'function' then + local res = s:select_background() + if res then + if type(res) ~= 'number' then res = 0 end + if res > maxp then track, maxp = v, res end + end + end + end + return track + end +} + +SMODS.splash_flash = 0 +SMODS.Background { + key = "splash", + shader = "splash", + select_background = function(self) + if not G.STAGES.RUN then return -math.huge end + if bwomp then return true end + end +} + +SMODS.Background { + key = "background", + shader = "background", + select_background = function(self) + if G.STAGES.RUN then return -math.huge end + end +} \ No newline at end of file diff --git a/src/utils/backgrounds.lua b/src/utils/backgrounds.lua new file mode 100644 index 000000000..f622e0935 --- /dev/null +++ b/src/utils/backgrounds.lua @@ -0,0 +1,36 @@ +function SMODS.create_bg_canvasses() + if SMODS.BG_CANVAS_1 then SMODS.BG_CANVAS_1:remove(); SMODS.BG_CANVAS_1 = nil end + if SMODS.BG_CANVAS_2 then SMODS.BG_CANVAS_2:remove(); SMODS.BG_CANVAS_2 = nil end + + local w, h = G.CANVAS:getDimensions() + SMODS.BG_CANVAS_1 = SMODS.BackgroundCanvas(-30, -13, w, h, SMODS.Background:get_current_background()) + SMODS.BG_CANVAS_2 = SMODS.BackgroundCanvas(-30, -13, w, h, nil, 0) + + SMODS.PRIMARY_BG_CANVAS = SMODS.BG_CANVAS_1 +end + +SMODS.PRIMARY_BG_CANVAS = SMODS.BG_CANVAS_1 + +function SMODS.switch_background(key) + local w, h = G.CANVAS:getDimensions() + SMODS.BG_CANVAS_1 = SMODS.BG_CANVAS_1 or SMODS.BackgroundCanvas(-30, -13, w, h) + SMODS.BG_CANVAS_2 = SMODS.BG_CANVAS_2 or SMODS.BackgroundCanvas(-30, -13, w, h) + + local new_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_2 or SMODS.BG_CANVAS_1 + local old_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_1 or SMODS.BG_CANVAS_2 + + -- set new canvas + SMODS.PRIMARY_BG_CANVAS = new_canvas + new_canvas:set_active_bg(SMODS.Backgrounds[key]) + + -- fade out old canvas + old_canvas:ease_alpha(0, 2) +end + +function SMODS.draw_background() + local primary_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_1 or SMODS.BG_CANVAS_2 + local secondary_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_2 or SMODS.BG_CANVAS_1 + + primary_canvas:draw() + secondary_canvas:draw() +end \ No newline at end of file From 3cea34acd1fb4b78fd27b8f401c6a7512a05dd09 Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:32:45 -0400 Subject: [PATCH 02/14] fix crashes --- lovely/backgrounds.toml | 14 -------------- lovely/screenshader_rendering.toml | 10 ++++++++++ src/game_objects/backgrounds.lua | 4 ++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/lovely/backgrounds.toml b/lovely/backgrounds.toml index c04bffaf9..2ca175625 100644 --- a/lovely/backgrounds.toml +++ b/lovely/backgrounds.toml @@ -3,20 +3,6 @@ version = "1.0.0" dump_lua = true priority = -1 -# Add canvasses for background drawing -[[patches]] -[patches.pattern] -target = "main.lua" -pattern = ''' -G.CANVAS = love.graphics.newCanvas(w*G.CANV_SCALE, h*G.CANV_SCALE, {type = '2d', readable = true}) -G.CANVAS:setFilter('linear', 'linear') -''' -position = "after" -payload = ''' - -''' -match_indent = true - # Handle the vanilla background shaders # Sprite:draw [[patches]] diff --git a/lovely/screenshader_rendering.toml b/lovely/screenshader_rendering.toml index e20ad9126..19629dddf 100644 --- a/lovely/screenshader_rendering.toml +++ b/lovely/screenshader_rendering.toml @@ -69,7 +69,17 @@ position = "after" payload = ''' G.SHADER_CANVAS_A = SMODS.create_canvas() G.SHADER_CANVAS_B = SMODS.create_canvas() + -- easier to just stick this here +if not SMODS.BG_CANVAS_1 then + SMODS.BG_CANVAS_1 = SMODS.BackgroundCanvas(-30, -13, w, h, SMODS.Background:get_current_background()) +end +if not SMODS.BG_CANVAS_2 then + SMODS.BG_CANVAS_2 = SMODS.BackgroundCanvas(-30, -13, w, h, nil, 0) +end + +SMODS.PRIMARY_BG_CANVAS = SMODS.PRIMARY_BG_CANVAS or SMODS.BG_CANVAS_1 + SMODS.BG_CANVAS_1.canvas = SMODS.create_canvas() SMODS.BG_CANVAS_2.canvas = SMODS.create_canvas() ''' diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index bfcf03741..12341e3b3 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -57,7 +57,7 @@ function SMODS.BackgroundCanvas:draw() if self.alpha == 0 then return end local fading = self.alpha ~= 1 if fading then love.graphics.setCanvas(self.canvas) end - for _, k in ipairs(SMODS.DrawStep.obj_buffer) do + for _, k in ipairs(SMODS.BackgroundDrawStep.obj_buffer) do SMODS.BackgroundDrawSteps[k].func(self) end if fading then @@ -104,7 +104,7 @@ end function SMODS.BackgroundCanvas:update() local obj = self.prototype - if obj.update and type(obj.update) == 'function' then + if obj and obj.update and type(obj.update) == 'function' then obj:update(self) end end From 7176adace566023aff8161d5b87d52716b124354 Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:35:55 -0400 Subject: [PATCH 03/14] cmt --- src/game_objects/backgrounds.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 12341e3b3..8a04a0f59 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -33,7 +33,7 @@ SMODS.BackgroundDrawStep { end, } - +-- DO NOT CREATE NEW INSTANCES OF THIS SMODS.BackgroundCanvas = Moveable:extend() function SMODS.BackgroundCanvas:init(X, Y, W, H, prototype, alpha) From f6b644c2ed305a6945884f759a5f0d6e1e6fb7ae Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:25:24 -0400 Subject: [PATCH 04/14] fix vort_offset bug --- lovely/backgrounds.toml | 62 ++++++++++++++++++++++---------- src/game_objects/backgrounds.lua | 34 ++++++++++-------- src/utils/backgrounds.lua | 4 +-- 3 files changed, 66 insertions(+), 34 deletions(-) diff --git a/lovely/backgrounds.toml b/lovely/backgrounds.toml index 2ca175625..923256e31 100644 --- a/lovely/backgrounds.toml +++ b/lovely/backgrounds.toml @@ -15,20 +15,20 @@ elseif _shader == 'vortex' then position = "after" payload = ''' elseif _shader == 'background' then - G.SHADERS['splash']:send('time', G.TIMERS.REAL_SHADER) - G.SHADERS['splash']:send('spin_time', G.TIMERS.BACKGROUND) - G.SHADERS['splash']:send('colour_1', G.C.BACKGROUND.C) - G.SHADERS['splash']:send('colour_2', G.C.BACKGROUND.L) - G.SHADERS['splash']:send('colour_3', G.C.BACKGROUND.D) - G.SHADERS['splash']:send('contrast', G.C.BACKGROUND.contrast) - G.SHADERS['splash']:send('spin_amount', G.ARGS.spin and G.ARGS.spin.amount or 0) -elseif shader == 'splash' then + G.SHADERS['background']:send('time', G.TIMERS.REAL_SHADER) + G.SHADERS['background']:send('spin_time', G.TIMERS.BACKGROUND) + G.SHADERS['background']:send('colour_1', G.C.BACKGROUND.C) + G.SHADERS['background']:send('colour_2', G.C.BACKGROUND.L) + G.SHADERS['background']:send('colour_3', G.C.BACKGROUND.D) + G.SHADERS['background']:send('contrast', G.C.BACKGROUND.contrast) + G.SHADERS['background']:send('spin_amount', G.ARGS.spin and G.ARGS.spin.amount or 0) +elseif _shader == 'splash' then G.SHADERS['splash']:send('time', G.TIMERS.REAL) - G.SHADERS['splash']:send('vort_speed', 0.4) - G.SHADERS['splash']:send('colour_1', G.C.BLUE) - G.SHADERS['splash']:send('colour_2', G.C.WHITE) - G.SHADERS['splash']:send('mid_flash', SMODS.splash_flash) - G.SHADERS['splash']:send('vort_offset', (2*90.15315131*os.time())%100000) + G.SHADERS['splash']:send('vort_speed', G.STATE == G.STATES.SPLASH and 1 or 0.4) + G.SHADERS['splash']:send('colour_1', G.STATE == G.STATES.SPLASH and G.C.BLUE or G.C.RED) + G.SHADERS['splash']:send('colour_2', G.STATE == G.STATES.SPLASH and G.C.WHITE or G.C.BLUE) + G.SHADERS['splash']:send('mid_flash', SMODS.splash_mid_flash) + G.SHADERS['splash']:send('vort_offset', G.STATE == G.STATES.SPLASH and SMODS.splash_vort_offset or 0) ''' match_indent = true @@ -43,11 +43,24 @@ local splash_args = {mid_flash = change_context == 'splash' and 1.6 or 0.} ''' position = "after" payload = ''' -SMODS.splash_flash = change_context == 'splash' and 1.6 or 0 -ease_value(SMODS, 'splash_flash', -(change_context == 'splash' and 1.6 or 0), nil, nil, nil, 4) +SMODS.splash_mid_flash = change_context == 'splash' and 1.6 or 0 +ease_value(SMODS, 'splash_mid_flash', -(change_context == 'splash' and 1.6 or 0), nil, nil, nil, 4) ''' match_indent = true +# Make vort_offset global +# Game:splash_screen +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = '''--Prep the splash screen shaders for both the background(colour swirl) and the foreground(white flash), starting at black''' +position = "after" +payload = ''' +SMODS.vort_offset = ((2*90.15315131*os.time())%100000) +''' +match_indent = true + + # Draw custom bgs # Game:draw [[patches]] @@ -69,17 +82,30 @@ position = "after" payload = ''' if SMODS.PRIMARY_BG_CANVAS then if G.debug_background_toggle then - love.graphics.clear({0,1,0,1}) else - love.graphics.push() SMODS.draw_background() - love.graphics.pop() end end ''' match_indent = true +# Get current bg +# Game:update +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = '''modulate_sound(dt)''' +position = "after" +payload = ''' +local cur_bg = SMODS.Background:get_current_background() +if SMODS.PRIMARY_BG_CANVAS and SMODS.PRIMARY_BG_CANVAS.prototype and SMODS.PRIMARY_BG_CANVAS.prototype.key ~= cur_bg.key then + SMODS.switch_background(cur_bg) +end + +''' +match_indent = true + # Create SMODS bg stuff # Game:main_menu, Game:demo_cta, Game:sandbox [[patches]] diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 8a04a0f59..0553481bb 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -9,7 +9,7 @@ SMODS.BackgroundDrawStep = SMODS.GameObject:extend { 'func', }, -- func = function(bg) end, - set = "Background Draw Step", + set = "Background Draw Steps", register = function(self) if self.registered then sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) @@ -38,13 +38,14 @@ SMODS.BackgroundCanvas = Moveable:extend() function SMODS.BackgroundCanvas:init(X, Y, W, H, prototype, alpha) Moveable.init(self, X, Y, W, H) + prototype = prototype or SMODS.Backgrounds.splash self.states.collide.can = false self.states.hover.can = false self.states.drag.can = false self.states.click.can = false - self.alpha = alpha + self.alpha = alpha or 1 self.canvas = SMODS.create_canvas() self.children = {} @@ -54,14 +55,14 @@ function SMODS.BackgroundCanvas:init(X, Y, W, H, prototype, alpha) end function SMODS.BackgroundCanvas:draw() - if self.alpha == 0 then return end + if self.alpha <= 0 then return end local fading = self.alpha ~= 1 if fading then love.graphics.setCanvas(self.canvas) end for _, k in ipairs(SMODS.BackgroundDrawStep.obj_buffer) do SMODS.BackgroundDrawSteps[k].func(self) end if fading then - love.graphics.setCanvas() + love.graphics.setCanvas(G.CANVAS) love.graphics.draw(self.canvas, 0, 0) end end @@ -70,8 +71,8 @@ function SMODS.BackgroundCanvas:set_sprites() self.children = self.children or {} local obj = self.prototype - local atlas = obj.atlas or 'ui_1' - local pos = obj.pos or {x = obj.atlas and 2 or 0, y = 0} + local atlas = obj.atlas_key or 'ui_1' + local pos = obj.pos or {x = obj.atlas_key and 2 or 0, y = 0} self.children.base = SMODS.create_sprite(self.T.x, self.T.y, self.T.w, self.T.h, atlas, pos) self.children.base:set_alignment({ major = self, @@ -88,6 +89,7 @@ end function SMODS.BackgroundCanvas:set_active_bg(prototype) self.prototype = prototype self.shader = prototype.shader + print(prototype.shader) if prototype.set_active and type(prototype.set_active) == "function" then prototype:set_active(self) @@ -124,10 +126,11 @@ end SMODS.Backgrounds = {} SMODS.Background = SMODS.GameObject:extend { obj_table = SMODS.Backgrounds, - set = 'Background', obj_buffer = {}, + set = "Background", required_params = { 'key', + 'select_background' }, send_vars = nil, -- same as Shader.send_vars select_background = nil, -- should this bg be used, works like SMODS.Sounds:select_music_track @@ -144,7 +147,7 @@ SMODS.Background = SMODS.GameObject:extend { end end, get_current_background = function(self) - local track + local bg local maxp = -math.huge for _, v in ipairs(self.obj_buffer) do local s = self.obj_table[v] @@ -152,21 +155,24 @@ SMODS.Background = SMODS.GameObject:extend { local res = s:select_background() if res then if type(res) ~= 'number' then res = 0 end - if res > maxp then track, maxp = v, res end + if res > maxp then bg, maxp = v, res end end end end - return track + return bg or (G.STAGE == G.STAGES.RUN and SMODS.Backgrounds["background"] or SMODS.Backgrounds["splash"]) end } -SMODS.splash_flash = 0 +local minfloat = -1.78e308 + +SMODS.splash_mid_flash = 0 +SMODS.splash_vort_offset = 0 SMODS.Background { key = "splash", shader = "splash", select_background = function(self) - if not G.STAGES.RUN then return -math.huge end - if bwomp then return true end + --if G.STAGE ~= G.STAGES.RUN then return -minfloat end + if bwomp then return 0 end end } @@ -174,6 +180,6 @@ SMODS.Background { key = "background", shader = "background", select_background = function(self) - if G.STAGES.RUN then return -math.huge end + --if G.STAGE == G.STAGES.RUN then return -minfloat end end } \ No newline at end of file diff --git a/src/utils/backgrounds.lua b/src/utils/backgrounds.lua index f622e0935..ae6d0cec5 100644 --- a/src/utils/backgrounds.lua +++ b/src/utils/backgrounds.lua @@ -11,7 +11,7 @@ end SMODS.PRIMARY_BG_CANVAS = SMODS.BG_CANVAS_1 -function SMODS.switch_background(key) +function SMODS.switch_background(bg) local w, h = G.CANVAS:getDimensions() SMODS.BG_CANVAS_1 = SMODS.BG_CANVAS_1 or SMODS.BackgroundCanvas(-30, -13, w, h) SMODS.BG_CANVAS_2 = SMODS.BG_CANVAS_2 or SMODS.BackgroundCanvas(-30, -13, w, h) @@ -21,7 +21,7 @@ function SMODS.switch_background(key) -- set new canvas SMODS.PRIMARY_BG_CANVAS = new_canvas - new_canvas:set_active_bg(SMODS.Backgrounds[key]) + new_canvas:set_active_bg(bg) -- fade out old canvas old_canvas:ease_alpha(0, 2) From 82174ac24e75c1878066db7b5c81dc73ebf3c624 Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:49:51 -0400 Subject: [PATCH 05/14] fix fade --- src/game_objects/backgrounds.lua | 8 ++++---- src/utils/backgrounds.lua | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 0553481bb..0dc952035 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -63,7 +63,9 @@ function SMODS.BackgroundCanvas:draw() end if fading then love.graphics.setCanvas(G.CANVAS) + love.graphics.setColor(1,1,1,self.alpha) love.graphics.draw(self.canvas, 0, 0) + love.graphics.setColor(1,1,1,1) end end @@ -159,12 +161,10 @@ SMODS.Background = SMODS.GameObject:extend { end end end - return bg or (G.STAGE == G.STAGES.RUN and SMODS.Backgrounds["background"] or SMODS.Backgrounds["splash"]) + return SMODS.Backgrounds[bg or (G.STAGE == G.STAGES.RUN and "background" or "splash")] end } -local minfloat = -1.78e308 - SMODS.splash_mid_flash = 0 SMODS.splash_vort_offset = 0 SMODS.Background { @@ -172,7 +172,7 @@ SMODS.Background { shader = "splash", select_background = function(self) --if G.STAGE ~= G.STAGES.RUN then return -minfloat end - if bwomp then return 0 end + if G.bwomp then return 0 end end } diff --git a/src/utils/backgrounds.lua b/src/utils/backgrounds.lua index ae6d0cec5..92ca63a6b 100644 --- a/src/utils/backgrounds.lua +++ b/src/utils/backgrounds.lua @@ -25,6 +25,7 @@ function SMODS.switch_background(bg) -- fade out old canvas old_canvas:ease_alpha(0, 2) + new_canvas.alpha = 1 end function SMODS.draw_background() From d0c40145928ee39f617447204e8dc7627bb83222 Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Thu, 16 Apr 2026 16:07:40 -0400 Subject: [PATCH 06/14] cleanup testing/commented lines --- src/game_objects/backgrounds.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 0dc952035..2cc4c0eb1 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -171,8 +171,6 @@ SMODS.Background { key = "splash", shader = "splash", select_background = function(self) - --if G.STAGE ~= G.STAGES.RUN then return -minfloat end - if G.bwomp then return 0 end end } @@ -180,6 +178,5 @@ SMODS.Background { key = "background", shader = "background", select_background = function(self) - --if G.STAGE == G.STAGES.RUN then return -minfloat end end } \ No newline at end of file From 97e56051f52cf221df09f4542a8ebf27b357c41b Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Fri, 17 Apr 2026 08:16:30 -0400 Subject: [PATCH 07/14] remove redundant function --- src/game_objects/backgrounds.lua | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 2cc4c0eb1..4763962bb 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -57,7 +57,9 @@ end function SMODS.BackgroundCanvas:draw() if self.alpha <= 0 then return end local fading = self.alpha ~= 1 - if fading then love.graphics.setCanvas(self.canvas) end + if fading then + love.graphics.setCanvas(self.canvas) + end for _, k in ipairs(SMODS.BackgroundDrawStep.obj_buffer) do SMODS.BackgroundDrawSteps[k].func(self) end @@ -91,12 +93,6 @@ end function SMODS.BackgroundCanvas:set_active_bg(prototype) self.prototype = prototype self.shader = prototype.shader - print(prototype.shader) - - if prototype.set_active and type(prototype.set_active) == "function" then - prototype:set_active(self) - end - for _, v in pairs(self.children) do v:remove(); v = nil end self:set_sprites() end @@ -138,7 +134,6 @@ SMODS.Background = SMODS.GameObject:extend { select_background = nil, -- should this bg be used, works like SMODS.Sounds:select_music_track set_sprites = nil, -- sets sprites - set_active = nil, -- runs when bg becomes active update = nil, -- runs on update inject = function(self) From d0ac6ef9c7aa31a1c72795a93bb0570de58fce92 Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Fri, 17 Apr 2026 08:24:24 -0400 Subject: [PATCH 08/14] add SMODS.BackgroundCanvas:clean_up_children --- src/game_objects/backgrounds.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 4763962bb..46da2f73c 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -90,15 +90,19 @@ function SMODS.BackgroundCanvas:set_sprites() end end +function SMODS.BackgroundCanvas:clean_up_children() + for _, v in pairs(self.children) do v:remove(); v = nil end +end + function SMODS.BackgroundCanvas:set_active_bg(prototype) self.prototype = prototype self.shader = prototype.shader - for _, v in pairs(self.children) do v:remove(); v = nil end + self:clean_up_children() self:set_sprites() end function SMODS.BackgroundCanvas:remove() - for _, v in pairs(self.children) do v:remove(); v = nil end + self:clean_up_children() Moveable.remove(self) end From 1363c3f37b86b8cd4cc5a870700327c5faeb537b Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:42:28 -0400 Subject: [PATCH 09/14] add support for custom bg fade time and ease type --- lovely/backgrounds.toml | 7 +----- src/game_objects/backgrounds.lua | 25 +++++++++++++++++--- src/utils/backgrounds.lua | 39 ++++++++++++++++++++++++-------- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/lovely/backgrounds.toml b/lovely/backgrounds.toml index 923256e31..67225923f 100644 --- a/lovely/backgrounds.toml +++ b/lovely/backgrounds.toml @@ -98,11 +98,7 @@ target = 'game.lua' pattern = '''modulate_sound(dt)''' position = "after" payload = ''' -local cur_bg = SMODS.Background:get_current_background() -if SMODS.PRIMARY_BG_CANVAS and SMODS.PRIMARY_BG_CANVAS.prototype and SMODS.PRIMARY_BG_CANVAS.prototype.key ~= cur_bg.key then - SMODS.switch_background(cur_bg) -end - +SMODS.update_background() ''' match_indent = true @@ -135,4 +131,3 @@ payload = ''' SMODS.create_bg_canvasses() ''' match_indent = true - diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 46da2f73c..97777ae2f 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -113,15 +113,30 @@ function SMODS.BackgroundCanvas:update() end end -function SMODS.BackgroundCanvas:ease_alpha(target, delay) +function SMODS.BackgroundCanvas:ease_alpha(target, delay, ease_type) if target == self.alpha then return end target = math.min(1, math.max(target, 0)) + delay = delay or 2 + SMODS.is_bg_fading = true G.E_MANAGER:add_event(Event({ trigger = "ease", ref_table = self, ref_value = "alpha", ease_to = target, - delay = delay or 2, + delay = delay, + type = ease_type, + blocking = false, + blockable = false, + })) + G.E_MANAGER:add_event(Event({ + func = function() + SMODS.is_bg_fading = false + return true + end, + trigger = "after", + delay = delay, + blocking = false, + blockable = false, })) end @@ -136,16 +151,20 @@ SMODS.Background = SMODS.GameObject:extend { }, send_vars = nil, -- same as Shader.send_vars select_background = nil, -- should this bg be used, works like SMODS.Sounds:select_music_track - set_sprites = nil, -- sets sprites update = nil, -- runs on update + fade_time = nil, -- how much time it takes for this bg to fade in + fade_ease = nil, -- which easing curve this bg uses when fading in + inject = function(self) -- assert(self.shader or self.path, "Background " .. self.key .. " not given shader key or path") if self.path and (not self.shader) then SMODS.Shader.inject(self) self.shader = self.key end + + self.fade_time = self.fade_time or 2 end, get_current_background = function(self) local bg diff --git a/src/utils/backgrounds.lua b/src/utils/backgrounds.lua index 92ca63a6b..52c8f4765 100644 --- a/src/utils/backgrounds.lua +++ b/src/utils/backgrounds.lua @@ -1,6 +1,7 @@ function SMODS.create_bg_canvasses() if SMODS.BG_CANVAS_1 then SMODS.BG_CANVAS_1:remove(); SMODS.BG_CANVAS_1 = nil end if SMODS.BG_CANVAS_2 then SMODS.BG_CANVAS_2:remove(); SMODS.BG_CANVAS_2 = nil end + SMODS.background_queue = {} local w, h = G.CANVAS:getDimensions() SMODS.BG_CANVAS_1 = SMODS.BackgroundCanvas(-30, -13, w, h, SMODS.Background:get_current_background()) @@ -9,7 +10,33 @@ function SMODS.create_bg_canvasses() SMODS.PRIMARY_BG_CANVAS = SMODS.BG_CANVAS_1 end -SMODS.PRIMARY_BG_CANVAS = SMODS.BG_CANVAS_1 +function SMODS.draw_background() + local primary_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_1 or SMODS.BG_CANVAS_2 + local secondary_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_2 or SMODS.BG_CANVAS_1 + + primary_canvas:draw() + secondary_canvas:draw() +end + +SMODS.background_queue = {} +SMODS.is_bg_fading = false + +function SMODS.update_background() + -- queue bg fades + local cur_bg = SMODS.Background:get_current_background() + if + SMODS.PRIMARY_BG_CANVAS and SMODS.PRIMARY_BG_CANVAS.prototype and SMODS.PRIMARY_BG_CANVAS.prototype.key ~= cur_bg.key + and SMODS.background_queue[#SMODS.background_queue] ~= cur_bg.key + then + SMODS.background_queue[#SMODS.background_queue+1] = cur_bg.key + end + + -- handle fade queue + if not SMODS.is_bg_fading and #SMODS.background_queue > 0 then + local bg = SMODS.Backgrounds[table.remove(SMODS.background_queue, 1)] + SMODS.switch_background(bg) + end +end function SMODS.switch_background(bg) local w, h = G.CANVAS:getDimensions() @@ -24,14 +51,6 @@ function SMODS.switch_background(bg) new_canvas:set_active_bg(bg) -- fade out old canvas - old_canvas:ease_alpha(0, 2) + old_canvas:ease_alpha(0, bg.fade_time, bg.fade_ease) new_canvas.alpha = 1 end - -function SMODS.draw_background() - local primary_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_1 or SMODS.BG_CANVAS_2 - local secondary_canvas = SMODS.PRIMARY_BG_CANVAS == SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_2 or SMODS.BG_CANVAS_1 - - primary_canvas:draw() - secondary_canvas:draw() -end \ No newline at end of file From 0d6e4e9e4b5c14113e26f09cb535e77feb9700bb Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:44:11 -0400 Subject: [PATCH 10/14] completely disable drawing of G.SPLASH_BACK --- lovely/backgrounds.toml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lovely/backgrounds.toml b/lovely/backgrounds.toml index 67225923f..6a59cfc1c 100644 --- a/lovely/backgrounds.toml +++ b/lovely/backgrounds.toml @@ -60,7 +60,6 @@ SMODS.vort_offset = ((2*90.15315131*os.time())%100000) ''' match_indent = true - # Draw custom bgs # Game:draw [[patches]] @@ -78,8 +77,21 @@ if G.SPLASH_BACK then end end ''' -position = "after" +position = "at" payload = ''' +--[[ +if G.SPLASH_BACK then + if G.debug_background_toggle then + love.graphics.clear({0,1,0,1}) + else + love.graphics.push() + G.SPLASH_BACK:translate_container() + G.SPLASH_BACK:draw() + love.graphics.pop() + end +end +]] + if SMODS.PRIMARY_BG_CANVAS then if G.debug_background_toggle then else From d17aff3eef38f9ab0a79811992588dabd8919d5e Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:46:51 -0400 Subject: [PATCH 11/14] debug bg toggle --- lovely/backgrounds.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/lovely/backgrounds.toml b/lovely/backgrounds.toml index 6a59cfc1c..fabe8b854 100644 --- a/lovely/backgrounds.toml +++ b/lovely/backgrounds.toml @@ -94,6 +94,7 @@ end if SMODS.PRIMARY_BG_CANVAS then if G.debug_background_toggle then + love.graphics.clear({0,1,0,1}) else SMODS.draw_background() end From f91575d59ef4a43f9d0fe768512ea8cb28c69a9a Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:27:44 -0400 Subject: [PATCH 12/14] optional select_background, make get_current_background return key --- src/game_objects/backgrounds.lua | 13 ++++--------- src/utils/backgrounds.lua | 6 +++--- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 97777ae2f..06d872d85 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -147,7 +147,6 @@ SMODS.Background = SMODS.GameObject:extend { set = "Background", required_params = { 'key', - 'select_background' }, send_vars = nil, -- same as Shader.send_vars select_background = nil, -- should this bg be used, works like SMODS.Sounds:select_music_track @@ -171,7 +170,7 @@ SMODS.Background = SMODS.GameObject:extend { local maxp = -math.huge for _, v in ipairs(self.obj_buffer) do local s = self.obj_table[v] - if type(s.select_background) == 'function' then + if s.select_background and type(s.select_background) == 'function' then local res = s:select_background() if res then if type(res) ~= 'number' then res = 0 end @@ -179,7 +178,7 @@ SMODS.Background = SMODS.GameObject:extend { end end end - return SMODS.Backgrounds[bg or (G.STAGE == G.STAGES.RUN and "background" or "splash")] + return bg or (G.STAGE == G.STAGES.RUN and "background" or "splash") end } @@ -187,14 +186,10 @@ SMODS.splash_mid_flash = 0 SMODS.splash_vort_offset = 0 SMODS.Background { key = "splash", - shader = "splash", - select_background = function(self) - end + shader = "splash" } SMODS.Background { key = "background", - shader = "background", - select_background = function(self) - end + shader = "background" } \ No newline at end of file diff --git a/src/utils/backgrounds.lua b/src/utils/backgrounds.lua index 52c8f4765..184f5351f 100644 --- a/src/utils/backgrounds.lua +++ b/src/utils/backgrounds.lua @@ -25,10 +25,10 @@ function SMODS.update_background() -- queue bg fades local cur_bg = SMODS.Background:get_current_background() if - SMODS.PRIMARY_BG_CANVAS and SMODS.PRIMARY_BG_CANVAS.prototype and SMODS.PRIMARY_BG_CANVAS.prototype.key ~= cur_bg.key - and SMODS.background_queue[#SMODS.background_queue] ~= cur_bg.key + SMODS.PRIMARY_BG_CANVAS and SMODS.PRIMARY_BG_CANVAS.prototype and SMODS.PRIMARY_BG_CANVAS.prototype.key ~= cur_bg + and SMODS.background_queue[#SMODS.background_queue] ~= cur_bg then - SMODS.background_queue[#SMODS.background_queue+1] = cur_bg.key + SMODS.background_queue[#SMODS.background_queue+1] = cur_bg end -- handle fade queue From ca2cc029cee2bba6d916ad233020fddc3997a505 Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:28:01 -0400 Subject: [PATCH 13/14] add lsp def --- lsp_def/classes/background.lua | 37 ++++++++++++++++++++++++ lsp_def/classes/background_draw_step.lua | 26 +++++++++++++++++ lsp_def/utils.lua | 20 ++++++++++++- 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 lsp_def/classes/background.lua create mode 100644 lsp_def/classes/background_draw_step.lua diff --git a/lsp_def/classes/background.lua b/lsp_def/classes/background.lua new file mode 100644 index 000000000..0123798ea --- /dev/null +++ b/lsp_def/classes/background.lua @@ -0,0 +1,37 @@ +---@meta + +---@class SMODS.Background: SMODS.GameObject +---@field obj_table? table Table of objects registered to this class. +---@field super? SMODS.GameObject|table Parent class. +---@field key string Unique string to reference this object. +---@field shader? string Key of the shader to apply to the background, shader must already exist to use this. +---@field path? string Name of the shader file to use if `shader` is not provided. +---@field fade_time? number Time it takes for this background to fade in. +---@field fade_ease? string Easing curve used when this background fades in. Must be in SMODS.ease_types +---@field extend? fun(self: SMODS.Background|table, o: SMODS.Background|table): table Primary method of creating a class. +---@field check_duplicate_register? fun(self: SMODS.Background|table): boolean? Ensures objects already registered will not register. +---@field check_duplicate_key? fun(self: SMODS.Background|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. +---@field register? fun(self: SMODS.Background|table) Registers the object. +---@field check_dependencies? fun(self: SMODS.Background|table): boolean? Returns `true` if there's no failed dependencies. +---@field process_loc_text? fun(self: SMODS.Background|table) Called during `inject_class`. Handles injecting loc_text. +---@field send_to_subclasses? fun(self: SMODS.Background|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. +---@field pre_inject_class? fun(self: SMODS.Background|table) Called before `inject_class`. Injects and manages class information before object injection. +---@field post_inject_class? fun(self: SMODS.Background|table) Called after `inject_class`. Injects and manages class information after object injection. +---@field inject_class? fun(self: SMODS.Background|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. +---@field inject? fun(self: SMODS.Background|table, i?: number) Called during `inject_class`. Injects the object into the game. +---@field take_ownership? fun(self: SMODS.Background|table, key: string, obj: SMODS.Background|table, silent?: boolean): nil|table|SMODS.Background Takes control of vanilla objects. Child class must have get_obj for this to function +---@field get_obj? fun(self: SMODS.Background|table, key: string): SMODS.Background|table? Returns an object if one matches the `key`. +---@field select_background? fun(self: SMODS.Background|table): nil|number|boolean Called each frame. Determines what background to use. Background with the highest number is used. +---@field set_sprites? fun(self: SMODS.Background|table, bg: SMODS.BackgroundCanvas|table) Used for setting and manipulating sprites of the background when created or loaded. +---@field update? fun(self: SMODS.Center|table, bg: SMODS.BackgroundCanvas|table) Allows logic for this card to be run per-frame. +---@field send_vars? fun(self: SMODS.Background|table): table? Used to send extra args to the shader via `Shader:send(key, value)`. +---@field get_current_background? fun(self: SMODS.Background|table): nil|string Polls `SMODS.Background:select_background` and returns the key to the background to use. +---@overload fun(self: SMODS.Background): SMODS.Background +SMODS.Background = setmetatable({}, { + __call = function(self) + return self + end +}) + +---@type table +SMODS.Backgrounds = {} \ No newline at end of file diff --git a/lsp_def/classes/background_draw_step.lua b/lsp_def/classes/background_draw_step.lua new file mode 100644 index 000000000..1db45f000 --- /dev/null +++ b/lsp_def/classes/background_draw_step.lua @@ -0,0 +1,26 @@ +---@meta + +---@class SMODS.BackgroundDrawStep: SMODS.GameObject +---@field key string Unique string to reference this object. +---@field order? number Sets the order. `BackgroundDrawStep` objects are evaluated in order from lowest to highest. +---@field __call? fun(self: SMODS.BackgroundDrawStep|table, o: SMODS.BackgroundDrawStep|table): nil|table|SMODS.BackgroundDrawStep +---@field extend? fun(self: SMODS.BackgroundDrawStep|table, o: SMODS.BackgroundDrawStep|table): table Primary method of creating a class. +---@field check_duplicate_register? fun(self: SMODS.BackgroundDrawStep|table): boolean? Ensures objects already registered will not register. +---@field check_duplicate_key? fun(self: SMODS.BackgroundDrawStep|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. +---@field register? fun(self: SMODS.BackgroundDrawStep|table) Registers the object. +---@field check_dependencies? fun(self: SMODS.BackgroundDrawStep|table): boolean? Returns `true` if there's no failed dependencies. +---@field process_loc_text? fun(self: SMODS.BackgroundDrawStep|table) Called during `inject_class`. Handles injecting loc_text. +---@field send_to_subclasses? fun(self: SMODS.BackgroundDrawStep|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. +---@field pre_inject_class? fun(self: SMODS.BackgroundDrawStep|table) Called before `inject_class`. Injects and manages class information before object injection. +---@field post_inject_class? fun(self: SMODS.BackgroundDrawStep|table) Called after `inject_class`. Injects and manages class information after object injection. +---@field inject_class? fun(self: SMODS.BackgroundDrawStep|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. +---@field inject? fun(self: SMODS.BackgroundDrawStep|table, i?: number) Called during `inject_class`. Injects the object into the game. +---@field take_ownership? fun(self: SMODS.BackgroundDrawStep|table, key: string, obj: SMODS.BackgroundDrawStep|table, silent?: boolean): nil|table|SMODS.BackgroundDrawStep Takes control of vanilla objects. Child class must have get_obj for this to function +---@field get_obj? fun(self: SMODS.BackgroundDrawStep|table, key: string): SMODS.BackgroundDrawStep|table? Returns an object if one matches the `key`. +---@field func? fun(card: Card|table, layer?: string) Handles the drawing logic of the `DrawStep`. +---@overload fun(self: SMODS.BackgroundDrawStep): SMODS.BackgroundDrawStep +SMODS.BackgroundDrawStep = setmetatable({}, { + __call = function(self) + return self + end +}) \ No newline at end of file diff --git a/lsp_def/utils.lua b/lsp_def/utils.lua index a1f63a68e..c14f50a93 100644 --- a/lsp_def/utils.lua +++ b/lsp_def/utils.lua @@ -843,4 +843,22 @@ function SMODS.mod_blind_size(mod_blind_size) end ---@field mult? number Multiply blind size by this number ---@field card? Card Card responsible for blind size modification action, crucial for blind size display to work properly ---@field effect? table Table of effects that were calculated ----@field from_edition? boolean \ No newline at end of file +---@field from_edition? boolean + +---@class SMODS.BackgroundCanvas: Moveable +---@overload fun(...: any): SMODS.BackgroundCanvas|table +SMODS.BackgroundCanvas = {} +function SMODS.BackgroundCanvas:__call(...) return self end + +--- Creates SMODS.BG_CANVAS_1 and SMODS.BG_CANVAS_2, and removes previous instances of both. +function SMODS.create_bg_canvasses() end + +--- Draws the background. +function SMODS.draw_background() end + +--- Updates the current background, and handles the background fade queue. Gets run every frame. +function SMODS.update_background() end + +--- Begins fading the background to a new background. +--- @param bg string Key for an SMODS.Background object. +function SMODS.switch_background(bg) end \ No newline at end of file From 0efdf1135efbe6603eeafbd25f5bd0befcf99a20 Mon Sep 17 00:00:00 2001 From: InvalidOS <35383068+InvalidOS@users.noreply.github.com> Date: Sat, 18 Apr 2026 10:24:44 -0400 Subject: [PATCH 14/14] fix bg breaking + missing lsp docs --- lsp_def/classes/background.lua | 2 ++ src/game_objects/backgrounds.lua | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lsp_def/classes/background.lua b/lsp_def/classes/background.lua index 0123798ea..df6074f30 100644 --- a/lsp_def/classes/background.lua +++ b/lsp_def/classes/background.lua @@ -6,6 +6,8 @@ ---@field key string Unique string to reference this object. ---@field shader? string Key of the shader to apply to the background, shader must already exist to use this. ---@field path? string Name of the shader file to use if `shader` is not provided. +---@field atlas? string Key to the atlas used for the background sprite. +---@field pos? table|{x: integer, y: integer} Position of the background's sprite. ---@field fade_time? number Time it takes for this background to fade in. ---@field fade_ease? string Easing curve used when this background fades in. Must be in SMODS.ease_types ---@field extend? fun(self: SMODS.Background|table, o: SMODS.Background|table): table Primary method of creating a class. diff --git a/src/game_objects/backgrounds.lua b/src/game_objects/backgrounds.lua index 06d872d85..06f1599e7 100644 --- a/src/game_objects/backgrounds.lua +++ b/src/game_objects/backgrounds.lua @@ -38,7 +38,7 @@ SMODS.BackgroundCanvas = Moveable:extend() function SMODS.BackgroundCanvas:init(X, Y, W, H, prototype, alpha) Moveable.init(self, X, Y, W, H) - prototype = prototype or SMODS.Backgrounds.splash + prototype = (type(prototype) == "string" and SMODS.Backgrounds[prototype] or prototype) or SMODS.Backgrounds.splash self.states.collide.can = false self.states.hover.can = false