bezier-string-art/utils.lua
2023-05-11 21:28:37 +03:00

225 lines
5.2 KiB
Lua

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