require "libs/TSerial" local targetFolder = "art" local reanalyzeCells = true -- Sprites loaded directly by dedicated entity classes or used as reference art -- (the palette swatch), not placeable RGB assets. Every other master PNG in a -- content folder is a colour asset. Keeping this list preserves the exact -- palette set from when assets were identified by their _r/_g/_b channel files. local NON_ASSET_SPRITES = { palette = true, color_changing_wall = true, door_locked_w = true, door_unlocked = true, player_sad = true, player_w = true, switch_pressed = true, } function getAllAssets() local objectnames = {} local topFolder = "art" local files = love.filesystem.getDirectoryItems(topFolder) for _, folder in pairs(files) do if string.sub(folder, 1, 1) ~= "_" then -- we ignore directories which are prepended w/ an underscore if not string.find(folder, "%.") then objectnames[folder] = {} -- this is a folder, probably local newFiles = love.filesystem.getDirectoryItems(topFolder .. "/" .. folder) for _, fileToAnalyze in pairs(newFiles) do -- One full-colour master PNG per asset. The draw path tints it -- per gun (see Entity:draw), so red/green/blue copies are just -- the same master drawn through gColor[channel]; the channels are -- split at load time, not stored as separate files. if fileToAnalyze:find("%.png$") then local name = fileToAnalyze:sub(1, fileToAnalyze:len() - 4) -- first folder to define a name wins; skip engine/reference art if not NON_ASSET_SPRITES[name] and not (globalAssetProperties[name] and globalAssetProperties[name].directory ~= folder) then local sprite = topFolder .. "/" .. folder .. "/" .. fileToAnalyze if not globalAssetProperties[name] then globalAssetProperties[name] = {} globalAssetProperties[name].preload = false end globalAssetProperties[name].directory = folder -- all three channels point at the same master image globalAssetProperties[name].sprites = { red = sprite, green = sprite, blue = sprite } -- class comes from a .meta sitting next to the art -- (authoritative); default to immoveable if none exists local metaPath = topFolder .. "/" .. folder .. "/" .. name .. ".meta" if love.filesystem.getInfo(metaPath, "file") then globalAssetProperties[name].class = TSerial.unpack(love.filesystem.read(metaPath)).class elseif not globalAssetProperties[name].class then globalAssetProperties[name].class = "immoveable" end -- Precompute per-channel occupied-cell shapes once and cache -- here; entities share this table by reference so collision -- never rescans pixels at runtime. Keyed per colour because -- each channel of the master leaves its own gaps. if reanalyzeCells or not globalAssetProperties[name].cells then globalAssetProperties[name].cells = getChannelCells(sprite) end end end end end end end -- Wired devices intentionally reuse the familiar switch/door artwork. Their -- white terminal marker is drawn by the entity class, while these synthetic -- asset records make them available to the ordinary palette and brush. local function synthetic(name, source, behavior) local original = globalAssetProperties[source] if not original then return end globalAssetProperties[name] = { directory = original.directory, sprites = original.sprites, cells = original.cells, class = behavior, preload = false, synthetic = true, } end synthetic("wired_switch", "switch", "wired_switch") synthetic("wired_door", "door", "wired_door") return globalAssetProperties end