- Reestructuració completa
This commit is contained in:
15
data/utils/app.lua
Normal file
15
data/utils/app.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
app = {
|
||||
update = nil,
|
||||
stack = {},
|
||||
}
|
||||
|
||||
function app.push(func)
|
||||
table.insert(app.stack, app.update)
|
||||
app.update = func
|
||||
end
|
||||
|
||||
function app.pop()
|
||||
if #app.stack > 0 then
|
||||
app.update = table.remove(app.stack)
|
||||
end
|
||||
end
|
||||
362
data/utils/console.lua
Normal file
362
data/utils/console.lua
Normal file
@@ -0,0 +1,362 @@
|
||||
local separators = " ()[],-+*/=<>"
|
||||
|
||||
local function split_by_last_separator(s)
|
||||
for i = #s, 1, -1 do
|
||||
local c = s:sub(i, i)
|
||||
if separators:find(c, 1, true) then
|
||||
if i == #s then
|
||||
-- Separador al final
|
||||
return s, ""
|
||||
end
|
||||
-- Separador en medio
|
||||
return s:sub(1, i), s:sub(i + 1)
|
||||
end
|
||||
end
|
||||
-- Sin separadores
|
||||
return "", s
|
||||
end
|
||||
|
||||
local function split_by_last_dot(s)
|
||||
local last = s:match(".*()%.") -- devuelve la posición DESPUÉS del último punto
|
||||
|
||||
if not last then
|
||||
-- No hay puntos: primera parte = cadena completa, segunda = ""
|
||||
return "", s
|
||||
end
|
||||
|
||||
-- Si el punto está al final, la segunda parte es ""
|
||||
if last > #s then
|
||||
return s, ""
|
||||
end
|
||||
|
||||
-- Primera parte incluye el punto
|
||||
local first = s:sub(1, last - 1)
|
||||
local second = s:sub(last+1)
|
||||
|
||||
return first, second
|
||||
end
|
||||
|
||||
function get_by_path(path)
|
||||
local current = _G
|
||||
|
||||
for segment in path:gmatch("[^%.]+") do
|
||||
if type(current) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
current = current[segment]
|
||||
if current == nil then
|
||||
--print("get_by_path: " ..segment.." es nil")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--print("get_by_path: ok")
|
||||
return current
|
||||
end
|
||||
|
||||
function entries_starting_with(s, t)
|
||||
if not t then return nil end
|
||||
local result = {}
|
||||
for k, v in pairs(t) do
|
||||
if type(k) == "string" and k:sub(1, #s) == s then
|
||||
result[#result+1] = k
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
console = {
|
||||
command = "",
|
||||
history = {},
|
||||
history_pos = 0,
|
||||
cursor = 50,
|
||||
autocomplete_list = {},
|
||||
autocomplete_prefix = "",
|
||||
autocomplete_index = 1,
|
||||
} local me = console
|
||||
|
||||
function me.enable()
|
||||
app.push(me.update)
|
||||
me.command = ""
|
||||
end
|
||||
|
||||
function me.update()
|
||||
surf.target(0)
|
||||
draw.rrectf(0, 92, 160, 108, 4, 1)
|
||||
draw.rrect(0, 92, 160, 108, 4, 13)
|
||||
draw.text(">", 2, 96, 13)
|
||||
draw.text(me.command, 6, 96, 13)
|
||||
|
||||
if me.autocomplete_list and #me.autocomplete_list>0 then
|
||||
--local num = math.min(5, #me.autocomplete_list)
|
||||
--local base_y = 92-num*7
|
||||
--draw.rectf(3+#me.command*4, base_y, 80, num*7, 1)
|
||||
--draw.rect(3+#me.command*4, base_y, 80, num*7, 13)
|
||||
--for i=1,num do
|
||||
-- draw.text(me.autocomplete_list[i], 6+#me.command*4, base_y+i*7, 13)
|
||||
--end
|
||||
|
||||
local sufix = me.autocomplete_list[me.autocomplete_index]:sub(#me.autocomplete_prefix+1)
|
||||
draw.text(sufix, 6+#me.command*4, 96, 6)
|
||||
end
|
||||
|
||||
if me.cursor > 24 then
|
||||
draw.text("_", 6+#me.command*4, 96, 13)
|
||||
end
|
||||
me.cursor = me.cursor - 1
|
||||
if me.cursor == 0 then me.cursor = 50 end
|
||||
|
||||
if key.press(key.ESCAPE) then
|
||||
app.pop()
|
||||
return
|
||||
end
|
||||
|
||||
local should_update = false
|
||||
|
||||
if #me.history>0 then
|
||||
if key.press(key.UP) and me.history_pos > 1 then
|
||||
me.history_pos = me.history_pos - 1
|
||||
me.command = me.history[me.history_pos]
|
||||
should_update = true
|
||||
elseif key.press(key.DOWN) and me.history_pos < #me.history then
|
||||
me.history_pos = me.history_pos + 1
|
||||
me.command = me.history[me.history_pos]
|
||||
should_update = true
|
||||
end
|
||||
end
|
||||
|
||||
local k = key.press()
|
||||
if k ~= key.UNKNOWN then
|
||||
should_update = true
|
||||
if k >= key.A and k <= key.Z then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. string.char(k+61)
|
||||
else
|
||||
me.command = me.command .. string.char(k+93)
|
||||
end
|
||||
elseif k == key.N0 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '='
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '}'
|
||||
else
|
||||
me.command = me.command .. '0'
|
||||
end
|
||||
elseif k == key.N1 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '!'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '|'
|
||||
else
|
||||
me.command = me.command .. '1'
|
||||
end
|
||||
elseif k == key.N2 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '"'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '@'
|
||||
else
|
||||
me.command = me.command .. '2'
|
||||
end
|
||||
elseif k == key.N3 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '·'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '#'
|
||||
else
|
||||
me.command = me.command .. '3'
|
||||
end
|
||||
elseif k == key.N4 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '$'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '~'
|
||||
else
|
||||
me.command = me.command .. '4'
|
||||
end
|
||||
elseif k == key.N5 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '%'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. '5'
|
||||
end
|
||||
elseif k == key.N6 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '&'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. '6'
|
||||
end
|
||||
elseif k == key.N7 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '/'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. '7'
|
||||
end
|
||||
elseif k == key.N8 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '('
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. '8'
|
||||
end
|
||||
elseif k == key.N9 then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. ')'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. '9'
|
||||
end
|
||||
|
||||
elseif k == key.PERIOD then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. ':'
|
||||
else
|
||||
me.command = me.command .. '.'
|
||||
end
|
||||
|
||||
elseif k == key.COMMA then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. ';'
|
||||
else
|
||||
me.command = me.command .. ','
|
||||
end
|
||||
|
||||
elseif k == key.GRAVE then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. ' '
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '\\'
|
||||
else
|
||||
me.command = me.command .. ' '
|
||||
end
|
||||
|
||||
elseif k == key.EQUALS then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '¿'
|
||||
else
|
||||
me.command = me.command .. '¡'
|
||||
end
|
||||
|
||||
elseif k == key.SLASH then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '_'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. '-'
|
||||
end
|
||||
|
||||
elseif k == key.APOSTROPHE then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '"'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '{'
|
||||
else
|
||||
me.command = me.command .. '\''
|
||||
end
|
||||
|
||||
elseif k == key.SEMICOLON then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. 'Ñ'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. 'ñ'
|
||||
end
|
||||
|
||||
elseif k == key.BACKSLASH then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. 'Ç'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '}'
|
||||
else
|
||||
me.command = me.command .. 'ç'
|
||||
end
|
||||
|
||||
elseif k == key.RIGHTBRACKET then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '*'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ']'
|
||||
else
|
||||
me.command = me.command .. '+'
|
||||
end
|
||||
|
||||
elseif k == key.LEFTBRACKET then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '^'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. '['
|
||||
else
|
||||
me.command = me.command .. '`'
|
||||
end
|
||||
|
||||
elseif k == key.NONUSBACKSLASH then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '>'
|
||||
elseif key.down(key.RALT) then
|
||||
me.command = me.command .. ' '
|
||||
else
|
||||
me.command = me.command .. '<'
|
||||
end
|
||||
|
||||
elseif k == key.MINUS then
|
||||
if key.down(key.LSHIFT) or key.down(key.RSHIFT) then
|
||||
me.command = me.command .. '?'
|
||||
else
|
||||
me.command = me.command .. '\''
|
||||
end
|
||||
|
||||
elseif k == key.SPACE then
|
||||
me.command = me.command .. ' '
|
||||
elseif k == key.BACKSPACE then
|
||||
me.command = me.command:sub(1, #me.command - 1)
|
||||
|
||||
elseif k == key.TAB then
|
||||
local sufix = me.autocomplete_list[me.autocomplete_index]:sub(#me.autocomplete_prefix+1)
|
||||
me.command = me.command .. sufix
|
||||
|
||||
elseif k == key.RETURN then
|
||||
table.insert(me.history, me.command)
|
||||
me.history_pos = #me.history+1
|
||||
local f,err = load(me.command)
|
||||
if not f then
|
||||
print("Error al compilar:", err)
|
||||
else
|
||||
print(f())
|
||||
app.pop()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if should_update then
|
||||
local a, b = split_by_last_separator(me.command)
|
||||
if b ~= "" then
|
||||
local ba, bb = split_by_last_dot(b)
|
||||
me.autocomplete_prefix = bb
|
||||
if ba ~= "" then
|
||||
me.autocomplete_list = entries_starting_with(bb, get_by_path(ba))
|
||||
--print(bb..":"..ba)
|
||||
--print(#me.autocomplete_list)
|
||||
else
|
||||
me.autocomplete_list = entries_starting_with(bb, _G)
|
||||
--print(bb..":".."golbal")
|
||||
--print(#me.autocomplete_list)
|
||||
end
|
||||
else
|
||||
me.autocomplete_prefix = ""
|
||||
me.autocomplete_list = entries_starting_with("", _G)
|
||||
--print("<buit>"..":".."golbal")
|
||||
--print(#me.autocomplete_list)
|
||||
end
|
||||
end
|
||||
end
|
||||
66
data/utils/msgbox.lua
Normal file
66
data/utils/msgbox.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
require "ui"
|
||||
require "util"
|
||||
|
||||
msgbox = {
|
||||
title = "TITOL",
|
||||
text = { "Este es el missatge.", "Pot estar en varies linies" },
|
||||
buttons = { {"YES", sys.quit}, {"NO", app.pop} },
|
||||
selected = 0,
|
||||
w = 100,
|
||||
h = 50,
|
||||
} local me = msgbox
|
||||
|
||||
function me.show(title, text, buttons, default)
|
||||
me.selected = default or 1
|
||||
me.title = title
|
||||
me.text = text
|
||||
me.buttons = buttons
|
||||
|
||||
me.w = 0
|
||||
for i,v in ipairs(me.text) do
|
||||
local width = #v*4+8
|
||||
if width > me.w then me.w = width end
|
||||
end
|
||||
|
||||
me.h = #me.text*6+35
|
||||
|
||||
app.push(me.update)
|
||||
end
|
||||
|
||||
function me.update()
|
||||
local top = (160-me.w)//2
|
||||
local left = (104-me.h)//2
|
||||
view.clip(top, left, me.w, me.h)
|
||||
view.origin(top, left)
|
||||
draw.rrectf(0,0,me.w, me.h,4,27)
|
||||
|
||||
--draw.rectf(1,1,me.w-2, 7, 21)
|
||||
draw.text(me.title, 5, 4, 4)
|
||||
|
||||
local y = 14
|
||||
for i,v in ipairs(me.text) do
|
||||
draw.text(v, 5, y, 21)
|
||||
y = y + 6
|
||||
end
|
||||
|
||||
local mx, my = mouse.pos()
|
||||
|
||||
local x = me.w - 35
|
||||
y = me.h - 12
|
||||
for i,v in ipairs(me.buttons) do
|
||||
ui.pushbutton(v[1],x,y,7,22,21,v[2],me.selected==i)
|
||||
x = x - 34
|
||||
end
|
||||
|
||||
if key.press(key.ESCAPE) then
|
||||
app.pop()
|
||||
elseif key.press(key.RIGHT) then
|
||||
me.selected=me.selected-1
|
||||
if me.selected==0 then me.selected = #me.buttons end
|
||||
elseif key.press(key.LEFT) then
|
||||
me.selected=me.selected+1
|
||||
if me.selected>#me.buttons then me.selected = 1 end
|
||||
elseif key.press(key.RETURN) then
|
||||
me.buttons[me.selected][2]()
|
||||
end
|
||||
end
|
||||
61
data/utils/palfade.lua
Normal file
61
data/utils/palfade.lua
Normal file
@@ -0,0 +1,61 @@
|
||||
require "util"
|
||||
|
||||
palfade = {
|
||||
original = {},
|
||||
reddish = {},
|
||||
} local me = palfade
|
||||
|
||||
function me.init()
|
||||
for i=1,32 do
|
||||
me.reddish[i] = {r=me.original[i].r, g=me.original[i].g, b=me.original[i].b}
|
||||
end
|
||||
end
|
||||
|
||||
function me.reddish_limit(r, g, b)
|
||||
local t = util.luminance(r, g, b) / 255
|
||||
|
||||
local R = 255 * t
|
||||
local G = g * (1 - t)
|
||||
local B = b * (1 - t)
|
||||
|
||||
return R, G, B
|
||||
end
|
||||
|
||||
function me.fade_reddish_color(r, g, b, f)
|
||||
local ff = math.min(1, f+util.luminance(r,g,b))
|
||||
local R = math.floor(r*ff)
|
||||
local G = math.floor(g*f)
|
||||
local B = math.floor(b*f)
|
||||
|
||||
return R, G, B
|
||||
end
|
||||
|
||||
function me.fade_reddish(f)
|
||||
for i=1,32 do
|
||||
local r, g, b = me.fade_reddish_color(me.original[i].r, me.original[i].g, me.original[i].b, f)
|
||||
me.reddish[i].r, me.reddish[i].g, me.reddish[i].b = r, g, b
|
||||
pal.color(i-1,r,g,b)
|
||||
end
|
||||
end
|
||||
|
||||
function me.fade_red(f)
|
||||
for i=1,32 do
|
||||
local r = math.floor(me.reddish[i].r + (255-me.reddish[i].r)*f)
|
||||
local g = math.floor(me.reddish[i].g - (me.reddish[i].g)*f)
|
||||
local b = math.floor(me.reddish[i].b - (me.reddish[i].b)*f)
|
||||
pal.color(i-1,r,g,b)
|
||||
end
|
||||
end
|
||||
|
||||
function me.fade_white(f)
|
||||
for i=1,32 do
|
||||
local r = math.floor(me.reddish[i].r + (255-me.reddish[i].r)*f)
|
||||
local g = math.floor(me.reddish[i].g + (255-me.reddish[i].g)*f)
|
||||
local b = math.floor(me.reddish[i].b + (255-me.reddish[i].b)*f)
|
||||
pal.color(i-1,r,g,b)
|
||||
end
|
||||
end
|
||||
|
||||
function me.restore()
|
||||
pal.set(me.original)
|
||||
end
|
||||
164
data/utils/tweening.lua
Normal file
164
data/utils/tweening.lua
Normal file
@@ -0,0 +1,164 @@
|
||||
local pi = math.pi
|
||||
local sin = math.sin
|
||||
local cos = math.cos
|
||||
local abs = math.abs
|
||||
|
||||
local function backIn(t, s) s = s or 1.70158; return t * t * ((s + 1) * t - s) end
|
||||
local function backOut(t, s) s = s or 1.70158; t = t - 1; return 1 + t * t * ((s + 1) * t + s) end
|
||||
local function backInOut(t, s)
|
||||
s = s or 1.70158
|
||||
if t < 0.5 then
|
||||
local tt = 2 * t
|
||||
return (tt * tt * ((s * 1.525 + 1) * tt - s * 1.525)) / 2
|
||||
else
|
||||
local tt = 2 * t - 2
|
||||
return (2 + tt * tt * ((s * 1.525 + 1) * tt + s * 1.525)) / 2
|
||||
end
|
||||
end
|
||||
|
||||
-- Bounce (helper)
|
||||
local function bounceOut(t)
|
||||
local n1 = 7.5625
|
||||
local d1 = 2.75
|
||||
if t < 1 / d1 then
|
||||
return n1 * t * t
|
||||
elseif t < 2 / d1 then
|
||||
t = t - 1.5 / d1
|
||||
return n1 * t * t + 0.75
|
||||
elseif t < 2.5 / d1 then
|
||||
t = t - 2.25 / d1
|
||||
return n1 * t * t + 0.9375
|
||||
else
|
||||
t = t - 2.625 / d1
|
||||
return n1 * t * t + 0.984375
|
||||
end
|
||||
end
|
||||
|
||||
easing = {} local me = easing
|
||||
|
||||
function me.linear(t) return t end
|
||||
|
||||
-- Sine
|
||||
function me.easeInSine(t) return 1 - cos((t * pi) / 2) end
|
||||
function me.easeOutSine(t) return sin((t * pi) / 2) end
|
||||
function me.easeInOutSine(t) return -(cos(pi * t) - 1) / 2 end
|
||||
|
||||
-- Quad
|
||||
function me.easeInQuad(t) return t * t end
|
||||
function me.easeOutQuad(t) return 1 - (1 - t) * (1 - t) end
|
||||
function me.easeInOutQuad(t)
|
||||
if t < 0.5 then return 2 * t * t end
|
||||
return 1 - ((-2 * t + 2)^2) / 2
|
||||
end
|
||||
|
||||
-- Cubic
|
||||
function me.easeInCubic(t) return t * t * t end
|
||||
function me.easeOutCubic(t) return 1 - ((1 - t)^3) end
|
||||
function me.easeInOutCubic(t)
|
||||
if t < 0.5 then return 4 * t * t * t end
|
||||
return 1 - ((-2 * t + 2)^3) / 2
|
||||
end
|
||||
|
||||
-- Expo
|
||||
function me.easeInExpo(t) return (t == 0) and 0 or (2^(10 * t - 10)) end
|
||||
function me.easeOutExpo(t) return (t == 1) and 1 or 1 - (2^(-10 * t)) end
|
||||
function me.easeInOutExpo(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
if t < 0.5 then return (2^(20 * t - 10)) / 2 end
|
||||
return (2 - (2^(-20 * t + 10))) / 2
|
||||
end
|
||||
|
||||
-- Back (overshoot)
|
||||
function me.easeInBack(t) return backIn(t) end
|
||||
function me.easeOutBack(t) return backOut(t) end
|
||||
function me.easeInOutBack(t) return backInOut(t) end
|
||||
|
||||
-- Elastic
|
||||
function me.easeInElastic(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
local c4 = (2 * pi) / 3
|
||||
return -(2^(10 * t - 10)) * sin((t * 10 - 10.75) * c4)
|
||||
end
|
||||
function me.easeOutElastic(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
local c4 = (2 * pi) / 3
|
||||
return (2^(-10 * t)) * sin((t * 10 - 0.75) * c4) + 1
|
||||
end
|
||||
function me.easeInOutElastic(t)
|
||||
if t == 0 then return 0 end
|
||||
if t == 1 then return 1 end
|
||||
local c5 = (2 * pi) / 4.5
|
||||
if t < 0.5 then
|
||||
return -((2^(20 * t - 10)) * sin((20 * t - 11.125) * c5)) / 2
|
||||
end
|
||||
return ((2^(-20 * t + 10)) * sin((20 * t - 11.125) * c5)) / 2 + 1
|
||||
end
|
||||
|
||||
-- Bounce
|
||||
function me.easeInBounce(t) return 1 - bounceOut(1 - t) end
|
||||
function me.easeOutBounce(t) return bounceOut(t) end
|
||||
function me.easeInOutBounce(t)
|
||||
if t < 0.5 then return (1 - bounceOut(1 - 2 * t)) / 2 end
|
||||
return (1 + bounceOut(2 * t - 1)) / 2
|
||||
end
|
||||
|
||||
|
||||
tweening = {
|
||||
list = {},
|
||||
} me = tweening
|
||||
|
||||
function me.add(from, to, duration, easingFun, callback)
|
||||
local tween = {
|
||||
from = from,
|
||||
to = to,
|
||||
duration = math.max(0.000001, duration or 0.001),
|
||||
easing = easingFun,
|
||||
callback = callback,
|
||||
t = 0,
|
||||
}
|
||||
me.list[#me.list + 1] = tween
|
||||
return tween
|
||||
end
|
||||
|
||||
function me.update(dt)
|
||||
if #me.list==0 then return end
|
||||
|
||||
-- iterate backwards so we can remove finished tweens safely
|
||||
for i = #me.list, 1, -1 do
|
||||
local tw = me.list[i]
|
||||
tw.t = tw.t + (dt or 0)
|
||||
local progress = tw.t / tw.duration
|
||||
if progress >= 1 then
|
||||
-- finished: ensure final value, call callback with finished=true, remove
|
||||
local value = tw.to
|
||||
if tw.callback then
|
||||
-- callback(value, normalizedProgress, finished)
|
||||
tw.callback(value, 1, true)
|
||||
end
|
||||
table.remove(me.list, i)
|
||||
else
|
||||
-- in progress
|
||||
local alpha = tw.easing(progress)
|
||||
local value = tw.from + (tw.to - tw.from) * alpha
|
||||
if tw.callback then tw.callback(value, progress, false) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function me.clear()
|
||||
for i = #me.list, 1, -1 do table.remove(me.list, i) end
|
||||
end
|
||||
|
||||
-- Optional helper: cancel a specific tween (pass the tween returned by add)
|
||||
function me.cancel(tween)
|
||||
for i = #me.list, 1, -1 do
|
||||
if me.list[i] == tween then
|
||||
table.remove(me.list, i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
40
data/utils/ui.lua
Normal file
40
data/utils/ui.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
ui = {}
|
||||
|
||||
function ui.pushbutton(label,x,y,h,col1,col2,callback,selected)
|
||||
local size = (#label*4)-1+4
|
||||
local text_y = (h-5)//2
|
||||
local button_h=0
|
||||
local mx, my = mouse.pos()
|
||||
if mx>=x and mx<x+size and my>=y and my<y+h then
|
||||
button_h = mouse.down(mouse.LEFT) and -1 or 1
|
||||
if mouse.press(mouse.LEFT) then callback() end
|
||||
end
|
||||
draw.rrectf(x,y+1,size,h,1,col2)
|
||||
draw.rrectf(x,y-button_h,size,h,1,col1)
|
||||
draw.text(label,x+2,y+text_y-button_h,col2)
|
||||
if selected then
|
||||
draw.rrect(x-1,y-button_h-1,size+2,h+3+button_h,3,1)
|
||||
end
|
||||
end
|
||||
|
||||
function ui.togglebutton(label,x,y,h,col1,col2,dis1,dis2,state,callback,selected)
|
||||
local size = (#label*4)-1+4
|
||||
local text_y = (h-5)//2
|
||||
local bh=0
|
||||
local mx, my = mouse.pos()
|
||||
if mx>=x and mx<x+size and my>=y and my<y+h then
|
||||
bh = mouse.down(mouse.LEFT) and -1 or 1
|
||||
if mouse.press(mouse.LEFT) then callback() end
|
||||
end
|
||||
if not state then
|
||||
col1,col2 = dis1,dis2
|
||||
else
|
||||
if bh>-1 then bh=bh-1 end
|
||||
end
|
||||
draw.rrectf(x,y+1,size,h,1,col2)
|
||||
draw.rrectf(x,y-bh,size,h,1,col1)
|
||||
draw.text(label,x+2,y+text_y-bh,col2)
|
||||
if selected then
|
||||
draw.rrect(x-1,y-bh-1,size+2,h+3+bh,3,1)
|
||||
end
|
||||
end
|
||||
29
data/utils/util.lua
Normal file
29
data/utils/util.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
util={}
|
||||
|
||||
function util.inside(x, y, rectangle)
|
||||
if x >= rectangle[1] and
|
||||
y >= rectangle[2] and
|
||||
x < rectangle[3]+rectangle[1] and
|
||||
y < rectangle[4]+rectangle[2] then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function util.aabb(sprite)
|
||||
local x = sprite.pos.x + sprite.bbo.left
|
||||
local y = sprite.pos.y + sprite.bbo.top
|
||||
local w = sprite.size.w - sprite.bbo.right - sprite.bbo.left
|
||||
local h = sprite.size.h - sprite.bbo.bottom - sprite.bbo.top
|
||||
return x, y, w, h
|
||||
end
|
||||
|
||||
function util.check_aabb_collision(x1,y1,w1,h1, x2,y2,w2,h2)
|
||||
return ( x1 < x2 + w2 and x1 + w1 > x2 and y1 < y2 + h2 and y1 + h1 > y2 )
|
||||
end
|
||||
|
||||
function util.luminance(r, g, b)
|
||||
return (0.2126*r + 0.7152*g + 0.0722*b)/255
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user