local utils = {} local alignment = { ["top"] = 0, ["left"] = 0, ["middle"] = -0.5, ["center"] = -0.5, ["bottom"] = -1, ["right"] = -1 } local Vector2 = require("Vector2") local _tx, _ty = 0, 0 local _stack = { sx = {}, sy = {}, sw = {}, sh = {}, tx = {}, ty = {} } --[[ function atan2 (y, x) return (x > 0 ) and math.atan(y/x) or (x < 0 and y >= 0) and math.atan(y/x) + math.pi or (x < 0 and y < 0) and math.atan(y/x) - math.pi or (x == 0 and y > 0) and math.pi/2 or (x == 0 and y < 0) and -math.pi/2 or 0 -- this situration is technically undefined end ]] function utils.lastIndex(t) local res = -math.huge for k in pairs(t) do if k > res then res = k end end return res end function utils.translate(dx, dy) love.graphics.translate(dx, dy) _tx, _ty = _tx + dx, _ty + dy end function utils.pushRegion(x, y, w, h) local sx, sy, sw, sh = love.graphics.getScissor() table.insert(_stack.sx, sx) table.insert(_stack.sy, sy) table.insert(_stack.sw, sw) table.insert(_stack.sh, sh) table.insert(_stack.tx, _ty) table.insert(_stack.ty, _tx) love.graphics.push() if x and y then if w and h then love.graphics.intersectScissor(_tx + x, _ty + y, math.max(0, w), math.max(0, h)) end utils.translate(x, y) end end function utils.popRegion() local sx = table.remove(_stack.sx) local sy = table.remove(_stack.sy) local sw = table.remove(_stack.sw) local sh = table.remove(_stack.sh) _tx = table.remove(_stack.tx) or 0 _ty = table.remove(_stack.ty) or 0 love.graphics.pop() if sx and sy and sw and sh then love.graphics.setScissor(sx, sy, sw, sh) else love.graphics.setScissor() end end function utils.smoothLine (x1, y1, x2, y2, width, color) love.graphics.setLineStyle("smooth") love.graphics.setLineWidth(width) if color then love.graphics.setColor(color) end love.graphics.line(x1, y1, x2, y2) end function utils.clamp(x, A, B) if x < A then return A elseif x > B then return B else return x end end local function previous(t, i) i = i - 1 if i > 0 then return i, t[i] end end function utils.revipairs(t) return previous, t, #t+1 end function utils.smoothRectangle(x, y, w, h, r, color) love.graphics.setLineStyle("smooth") love.graphics.setLineWidth(1) if color then love.graphics.setColor(color) end love.graphics.rectangle("fill", x, y, w, h, r) love.graphics.rectangle("line", x, y, w, h, r) end function utils.borderRectangle(x,y,w,h,r,lineWidth,color) love.graphics.setLineStyle("smooth") love.graphics.setLineWidth(lineWidth) if color then love.graphics.setColor(color) end love.graphics.rectangle("line", x, y, w, h, r) end function utils.alignedPrint(font, text, x, y, alignX, alignY) local line_count = (select(2, text:gsub('\n', '\n')) or 0) + 1 local width = font:getWidth(text) local height = font:getHeight()*line_count love.graphics.setFont(font) love.graphics.print(text, utils.round(x + (alignment[alignX] or -0.5) * width), utils.round(y + (alignment[alignY] or -0.5) * height)) end function utils.rgb(r, g, b) return {r/255, g/255, b/255, 1} end function utils.rgba(r, g, b, a) return {r/255, g/255, b/255, a} end function utils.round(num, numDecimalPlaces) local mult = 10^(numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end function utils.map(x, A, B, C, D) return (x - A) / (B - A) * (D - C) + C end function utils.sign(x) if x > 0 then return 1 elseif x < 0 then return -1 else return 0 end end function utils.clone(data) if type(data) ~= "table" then return data else local new = {} for k, v in pairs(data) do new[k] = utils.clone(v) end return setmetatable(new, getmetatable(data)) end end function utils.serialize(data) if type(data) == "string" then return "\""..data.."\"" elseif type(data) == "table" then local t = {} for key,value in pairs(data) do table.insert(t,"["..utils.serialize(key).."]="..utils.serialize(value)) end return "{"..table.concat(t,",").."}" else return tostring(data) end end function utils.unserialize(data) return load("return "..data, nil, "t", {Vector2 = Vector2})() end function utils.printTable(t,depth) depth = depth or 0 for k,v in pairs(t) do if type(v) == "table" then print(string.rep(" ", depth)..k, "table:") utils.printTable(v,depth+1) else print(string.rep(" ", depth)..k, v) end end end function utils.loadFile(fileName) if not love.filesystem.getInfo(fileName) then return nil end local file = love.filesystem.read(fileName) local data = love.data.decompress("string","zlib", file) return utils.unserialize(data) end function utils.saveFile(data, fileName) local rawstring = utils.serialize(data) local file = io.open(fileName, "wb") file:write(love.data.compress("string","zlib",rawstring)) end function utils.pairsByKeys(t) local tableKeys = {} for key in pairs(t) do table.insert(tableKeys, key) end table.sort(tableKeys) local i = 0 local n = table.getn(tableKeys) return function () i = i + 1 if i <= n then return tableKeys[i], t[tableKeys[i]] end end end return utils