box-of-eases/src/dropdown.lua

384 lines
13 KiB
Lua
Raw Normal View History

2021-09-17 22:25:14 +00:00
local self = {}
2021-09-18 10:02:25 +00:00
local icon = {
2021-09-19 12:16:40 +00:00
inease = love.graphics.newImage('assets/textures/inease-icon.png'),
outease = love.graphics.newImage('assets/textures/outease-icon.png'),
inoutease = love.graphics.newImage('assets/textures/inoutease-icon.png'),
transientease = love.graphics.newImage('assets/textures/transientease-icon.png'),
unknownease = love.graphics.newImage('assets/textures/unknownease-icon.png'),
linearease = love.graphics.newImage('assets/textures/linearease-icon.png'),
instantease = love.graphics.newImage('assets/textures/instantease-icon.png'),
pulseease = love.graphics.newImage('assets/textures/pulseease-icon.png'),
2021-09-18 10:02:25 +00:00
}
2021-09-17 22:25:14 +00:00
local dropdowns = {}
local dropdownValueCache = {}
2021-09-18 09:16:20 +00:00
local dropdownScrollCache = {}
2021-09-17 22:25:14 +00:00
local maxDropdown = 16
self.openDropdown = 0
local dropdownScroll = 0
local dropdownScrollE = 0
2021-09-19 20:13:08 +00:00
local scrollbarSize = 6
2021-09-19 20:04:39 +00:00
2021-09-17 22:25:14 +00:00
local function skeys(t)
local k = {}
for n,v in pairs(t) do table.insert(k, {n, v}) end
table.sort(k, function(a, b) return a[2].i < b[2].i end)
local k2 = {}
for _,v in ipairs(k) do table.insert(k2, v[1]) end
return k2
end
2021-09-18 10:02:25 +00:00
local function icons(keys)
local e = {}
for i,v in ipairs(keys) do
table.insert(e, (ease.eases[v].type or 'unknown') .. 'ease')
end
return e
end
2021-09-18 10:39:28 +00:00
local function params(keys)
local e = {}
for i,v in ipairs(keys) do
table.insert(e, ease.eases[v].params)
end
return e
end
2021-09-17 22:25:14 +00:00
function self.get(index)
return dropdowns[index]
end
function self.selected(index)
return dropdowns[index].options[dropdowns[index].selected]
end
function self.kget(key)
for _, v in ipairs(dropdowns) do
if v.name == key then
return v
end
end
end
function self.kselected(key)
for _, v in ipairs(dropdowns) do
if v.name == key then
return v.options[v.selected]
end
end
end
2021-09-19 19:11:33 +00:00
function self.swap(key, key2)
local a, b = self.kget(key), self.kget(key2)
local s = a.selected
a.selected = b.selected
b.selected = s
end
2021-09-17 22:25:14 +00:00
local dropdownId
local function insertDropdown(tab, f)
dropdownId = dropdownId + 1
f.selected = (self.kget(f.name) or dropdownValueCache[f.name] or {selected = 1}).selected
f.selected = (f.selected - 1) % #f.options + 1
2021-09-17 23:26:40 +00:00
f.open = (self.kget(f.name) or {open = 0}).open
2021-09-17 22:25:14 +00:00
return table.insert(tab, f)
end
function self.createDropdowns()
local d = {}
dropdownId = 0
insertDropdown(d, {
2021-09-17 22:51:42 +00:00
x = outerpadding,
y = outerpadding,
width = dropdownWidth,
2021-09-17 22:25:14 +00:00
options = {
'Preview Ease',
'Mix Eases',
2021-09-19 10:16:27 +00:00
'Multiply Eases',
2021-09-17 22:25:14 +00:00
'Create Ease'
},
name = 'mode'
})
2021-09-18 00:48:03 +00:00
local param1 = {}
local param2 = {}
2021-09-18 10:02:25 +00:00
local eases = skeys(ease.eases)
2021-09-19 10:16:27 +00:00
if d[dropdownId].selected == modes.preview then -- preview ease
2021-09-17 22:25:14 +00:00
insertDropdown(d, {
2021-09-17 22:51:42 +00:00
x = outerpadding + dropdownWidth + padding,
y = outerpadding,
width = dropdownWidth,
2021-09-18 10:02:25 +00:00
options = eases,
name = 'ease1',
2021-09-18 10:39:28 +00:00
icons = icons(eases),
params = params(eases)
2021-09-17 22:25:14 +00:00
})
2021-09-18 01:20:46 +00:00
local _e = ease.eases[d[dropdownId].options[d[dropdownId].selected]]
param1[1] = slider.kvalue(_e.name .. 'param11') or (_e.params[1] and _e.params[1].default) or 1
param1[2] = slider.kvalue(_e.name .. 'param12') or (_e.params[2] and _e.params[2].default) or 1
2021-09-18 00:48:03 +00:00
ease.ease = function(x)
2021-09-18 01:20:46 +00:00
return _e.f(x, param1[1], param1[2])
2021-09-18 00:48:03 +00:00
end
2021-09-19 10:16:27 +00:00
elseif d[dropdownId].selected == modes.mix then -- mix eases
2021-09-17 22:25:14 +00:00
insertDropdown(d, {
2021-09-17 22:51:42 +00:00
x = outerpadding + dropdownWidth + padding,
y = outerpadding,
width = dropdownWidth,
2021-09-18 10:02:25 +00:00
options = eases,
name = 'ease1',
2021-09-18 10:39:28 +00:00
icons = icons(eases),
params = params(eases)
2021-09-17 22:25:14 +00:00
})
insertDropdown(d, {
2021-09-17 22:51:42 +00:00
x = outerpadding + dropdownWidth + padding + dropdownWidth + padding,
y = outerpadding,
width = dropdownWidth,
2021-09-18 10:02:25 +00:00
options = eases,
name = 'ease2',
2021-09-18 10:39:28 +00:00
icons = icons(eases),
params = params(eases)
2021-09-17 22:25:14 +00:00
})
2021-09-18 01:20:46 +00:00
local _e1 = ease.eases[d[dropdownId - 1].options[d[dropdownId - 1].selected]]
local _e2 = ease.eases[d[dropdownId].options[d[dropdownId].selected]]
param1[1] = slider.kvalue(_e1.name .. 'param11') or (_e1.params[1] and _e1.params[1].default) or 1
param1[2] = slider.kvalue(_e1.name .. 'param12') or (_e1.params[2] and _e1.params[2].default) or 1
param2[1] = slider.kvalue(_e2.name .. 'param21') or (_e2.params[1] and _e2.params[1].default) or 1
param2[2] = slider.kvalue(_e2.name .. 'param22') or (_e2.params[2] and _e2.params[2].default) or 1
2021-09-18 01:20:46 +00:00
ease.ease = ease.mixEase(_e1.f, _e2.f, slider.kvalue('mix'), param1, param2)
2021-09-19 10:16:27 +00:00
elseif d[dropdownId].selected == modes.multiply then -- mult eases
insertDropdown(d, {
x = outerpadding + dropdownWidth + padding,
y = outerpadding,
width = dropdownWidth,
options = eases,
name = 'ease1',
icons = icons(eases),
2021-09-19 11:22:47 +00:00
params = params(eases),
tooltip = 'The a in b(a(x))'
2021-09-19 10:16:27 +00:00
})
insertDropdown(d, {
x = outerpadding + dropdownWidth + padding + dropdownWidth + padding,
y = outerpadding,
width = dropdownWidth,
options = eases,
name = 'ease2',
icons = icons(eases),
2021-09-19 11:22:47 +00:00
params = params(eases),
tooltip = 'The b in b(a(x))'
2021-09-19 10:16:27 +00:00
})
local _e1 = ease.eases[d[dropdownId - 1].options[d[dropdownId - 1].selected]]
local _e2 = ease.eases[d[dropdownId].options[d[dropdownId].selected]]
param1[1] = slider.kvalue(_e1.name .. 'param11') or (_e1.params[1] and _e1.params[1].default) or 1
param1[2] = slider.kvalue(_e1.name .. 'param12') or (_e1.params[2] and _e1.params[2].default) or 1
param2[1] = slider.kvalue(_e2.name .. 'param21') or (_e2.params[1] and _e2.params[1].default) or 1
param2[2] = slider.kvalue(_e2.name .. 'param22') or (_e2.params[2] and _e2.params[2].default) or 1
ease.ease = function(x)
return _e2.f(_e1.f(x, param1[1], param1[2]), param2[1], param2[2])
end
elseif d[dropdownId].selected == modes.create then -- create eases
2021-09-17 22:25:14 +00:00
insertDropdown(d, {
2021-09-17 22:51:42 +00:00
x = outerpadding + dropdownWidth + padding,
y = outerpadding,
width = dropdownWidth,
2021-09-18 10:02:25 +00:00
options = eases,
name = 'ease1',
icons = icons(eases)
2021-09-17 22:25:14 +00:00
})
end
dropdowns = d
2021-09-17 22:44:26 +00:00
minEase = (self.kselected('ease1') and ease.eases[self.kselected('ease1')].min == -1) or (self.kselected('ease2') and ease.eases[self.kselected('ease2')].min == -1)
2021-09-18 00:05:13 +00:00
mode = dropdown.kget('mode').selected
2021-09-17 22:25:14 +00:00
end
function self.update(dt)
maxDropdown = math.floor(math.min(16 * (margin + fontHeight), love.graphics.getHeight() * 0.75) / (margin + fontHeight))
2021-09-17 22:25:14 +00:00
if self.openDropdown ~= 0 then
dropdownScroll = math.max(dropdownScroll, -(#self.get(self.openDropdown).options - maxDropdown + 1))
2021-09-17 22:25:14 +00:00
dropdownScroll = math.min(dropdownScroll, 0)
dropdownScrollE = mix(dropdownScrollE, dropdownScroll, dt * 10)
end
2021-09-17 23:26:40 +00:00
for i, v in ipairs(dropdowns) do
if i == self.openDropdown then
v.open = mix(v.open, 1, dt * 14)
else
v.open = mix(v.open, 0, dt * 20)
end
end
2021-09-19 20:04:39 +00:00
if love.mouse.isDown(1) then
local x, y = getMousePosition()
2021-09-19 20:04:39 +00:00
for i,v in ipairs(dropdowns) do
local h = fontHeight + margin
if self.openDropdown == i then
if x > v.x and x > v.x + v.width - scrollbarSize and y > v.y + h and y < v.y + h * (math.min(#v.options, maxDropdown) + 1) and not (#v.options < maxDropdown) then
dropdownScroll = ((y - (v.y + h)) / (h * (math.min(#v.options, maxDropdown)))) * -(#v.options - maxDropdown + 1)
end
end
end
end
2021-09-17 22:25:14 +00:00
end
function self.render()
local mx, my = getMousePosition()
2021-09-17 22:25:14 +00:00
for i,v in ipairs(dropdowns) do
2021-09-18 00:05:13 +00:00
local x, y, w, h = v.x, v.y, v.width, fontHeight + margin
2021-09-17 22:38:04 +00:00
2021-09-18 10:14:32 +00:00
love.graphics.setColor(0.06, 0.06, 0.12, 0.6)
if mx > x and mx < x + w and my > y and my < y + h then
2021-09-17 22:25:14 +00:00
love.graphics.setColor(0.8, 0.8, 1, love.mouse.isDown(1) and 0.4 or 0.3)
2021-09-19 11:22:47 +00:00
if v.tooltip then tooltips.show(v.tooltip) end
2021-09-17 22:25:14 +00:00
end
love.graphics.rectangle('fill', x, y, w, h)
2021-09-17 22:38:04 +00:00
2021-09-17 22:25:14 +00:00
love.graphics.setColor(1, 1, 1, 1)
2021-09-17 22:38:04 +00:00
2021-09-17 22:25:14 +00:00
love.graphics.rectangle('line', x, y, w, h)
2021-09-18 10:23:20 +00:00
if v.icons and v.icons[v.selected] then
local sprite = icon[v.icons[v.selected]]
love.graphics.draw(sprite, x + 2, y + 2, 0, fontHeight / sprite:getWidth(), fontHeight / sprite:getHeight())
love.graphics.print(self.selected(i), x + margin/2 + fontHeight, y + margin/2)
else
love.graphics.print(self.selected(i), x + margin/2, y + margin/2)
end
2021-09-17 23:06:31 +00:00
-- love.graphics.rectangle('line', x + w - h, y, h, h)
2021-09-18 10:21:53 +00:00
love.graphics.setLineWidth(1)
2021-09-17 22:25:14 +00:00
love.graphics.polygon('line', x + w - h/2 + 0.3 * h, y + h/2 - 0.3 * h, x + w - h/2 - 0.3 * h, y + h/2 - 0.3 * h, x + w - h/2, y + h/2 + 0.3 * h)
2021-09-17 22:38:04 +00:00
2021-09-17 23:26:40 +00:00
if self.openDropdown == i or v.open > 0.01 then
2021-09-17 22:25:14 +00:00
for i,o in ipairs(v.options) do
2021-09-17 23:26:40 +00:00
local x, y, w, h = x, y + ((i - 1) * v.open + 1) * h, w, h * v.open
2021-09-17 22:38:04 +00:00
2021-09-17 23:26:40 +00:00
y = y + dropdownScrollE * h * v.open
2021-09-17 22:25:14 +00:00
local gi = y / h
if gi > (maxDropdown + 1) or gi < 1 then
2021-09-17 22:25:14 +00:00
goto continue
end
2021-09-17 22:38:04 +00:00
-- help
2021-09-17 23:26:40 +00:00
local a = (1 - math.min(math.max((1 - (maxDropdown - gi)) * (1 - (math.abs(dropdownScrollE) / (#v.options - maxDropdown + 1))), 0), 1)) * math.max(math.min(gi - 1, 1), 0) * v.open
2021-09-17 22:38:04 +00:00
2021-09-18 10:14:32 +00:00
love.graphics.setColor(0.06, 0.06, 0.12, 0.6 * a)
2021-09-17 22:25:14 +00:00
if mx > x and mx < x + w and my > y and my < y + h then
2021-09-18 10:14:32 +00:00
love.graphics.setColor(0.4, 0.4, 1, (love.mouse.isDown(1) and 0.8 or 0.7) * a)
2021-09-17 22:25:14 +00:00
end
love.graphics.rectangle('fill', x, y, w, h)
2021-09-17 22:38:04 +00:00
2021-09-17 22:25:14 +00:00
love.graphics.setColor(1, 1, 1, 0.75 * a)
love.graphics.rectangle('line', x, y, w, h)
2021-09-17 22:38:04 +00:00
2021-09-17 22:25:14 +00:00
love.graphics.setColor(1, 1, 1, 1 * a)
2021-09-18 09:16:20 +00:00
if i == v.selected then
2021-09-18 10:14:32 +00:00
love.graphics.setColor(0.5, 0.5, 1, 1 * a)
2021-09-18 09:16:20 +00:00
end
2021-09-18 10:02:25 +00:00
if v.icons and v.icons[i] then
local sprite = icon[v.icons[i]]
love.graphics.draw(sprite, x + 2, y + 2, 0, fontHeight / sprite:getWidth(), fontHeight / sprite:getHeight())
love.graphics.print(v.options[i], x + 2 + fontHeight, y + 2)
else
love.graphics.print(v.options[i], x + 2, y + 2)
end
2021-09-17 22:38:04 +00:00
2021-09-18 10:39:28 +00:00
if v.params and v.params[i] then
local str = ''
for _,p in ipairs(v.params[i]) do
str = str .. ' ' .. string.sub(p.name, 1, 1)
end
2021-09-19 19:36:33 +00:00
love.graphics.setFont(getFont(0.8, true))
2021-09-18 10:39:28 +00:00
love.graphics.setColor(0.8, 0.8, 1, 0.8 * a)
2021-09-19 19:36:33 +00:00
love.graphics.printf(str, x, y, w - 2, 'right')
love.graphics.setFont(interfaceFont)
2021-09-18 10:39:28 +00:00
end
2021-09-17 22:25:14 +00:00
::continue::
end
2021-09-17 22:38:04 +00:00
2021-09-17 22:25:14 +00:00
-- scrollwheel
2021-09-17 22:38:04 +00:00
2021-09-17 22:25:14 +00:00
if #v.options > maxDropdown then
local displayed = maxDropdown / (#v.options)
local scroll = math.abs(dropdownScrollE) / (#v.options - maxDropdown + 1)
2021-09-19 20:04:39 +00:00
local size = scrollbarSize
2021-09-17 22:38:04 +00:00
2021-09-19 20:13:08 +00:00
love.graphics.setColor(1, 1, 1, 0.8 * v.open)
2021-09-17 23:26:40 +00:00
love.graphics.rectangle('fill', x + w - size, y + h + scroll * (1 - displayed) * (maxDropdown - 1) * h * v.open, size, displayed * (maxDropdown - 1) * h * v.open)
2021-09-17 22:25:14 +00:00
end
end
2021-09-18 10:21:53 +00:00
love.graphics.setLineWidth(lineWidth)
2021-09-17 22:25:14 +00:00
end
end
function self.mousepressed(x, y, m)
local clickedDropdown = false
for i,v in ipairs(dropdowns) do
2021-09-18 00:05:13 +00:00
local h = fontHeight + margin
2021-09-17 22:25:14 +00:00
if self.openDropdown == 0 then
if x > v.x and x < v.x + v.width and y > v.y and y < v.y + h + margin then
if m == 1 then
self.openDropdown = i
clickedDropdown = true
2021-09-18 09:16:20 +00:00
dropdownScroll = dropdownScrollCache[i] or 0
dropdownScrollE = dropdownScrollCache[i] or 0
2021-09-17 22:25:14 +00:00
elseif m == 3 then
dropdowns[i].selected = math.random(1, #dropdowns[i].options)
2021-09-18 00:05:13 +00:00
createUI()
2021-09-17 22:25:14 +00:00
end
end
elseif self.openDropdown == i then
if x > v.x and x < v.x + v.width and y > v.y + h and y < v.y + h * (math.min(#v.options, maxDropdown) + 1) and m == 1 then
clickedDropdown = true
end
end
end
2021-09-17 22:38:04 +00:00
2021-09-17 22:25:14 +00:00
if not clickedDropdown and m == 1 then
2021-09-18 09:16:20 +00:00
dropdownScrollCache[self.openDropdown] = dropdownScroll
2021-09-17 22:25:14 +00:00
self.openDropdown = 0
end
end
function self.mousereleased(x, y, m)
for i,v in ipairs(dropdowns) do
2021-09-18 00:05:13 +00:00
local h = fontHeight + margin
2021-09-17 22:25:14 +00:00
if self.openDropdown == i then
2021-09-19 20:04:39 +00:00
if x > v.x and x < v.x + v.width and y > v.y + h and y < v.y + h * (math.min(#v.options, maxDropdown) + 1) and m == 1 and (x < v.x + v.width - scrollbarSize or #v.options < maxDropdown) then
2021-09-17 22:25:14 +00:00
v.selected = math.floor((y - v.y) / h - dropdownScrollE)
self.openDropdown = 0
dropdownValueCache[v.name] = {selected = v.selected}
2021-09-18 09:16:20 +00:00
dropdownScrollCache[i] = dropdownScroll
2021-09-18 00:05:13 +00:00
createUI()
2021-09-17 22:25:14 +00:00
end
end
end
end
function self.wheelmoved(x, y)
if self.openDropdown ~= 0 then
dropdownScroll = dropdownScroll + y
else
local mx, my = getMousePosition()
2021-09-17 22:25:14 +00:00
for i,v in ipairs(dropdowns) do
2021-09-18 00:05:13 +00:00
local h = fontHeight + margin
2021-09-17 22:25:14 +00:00
if mx > v.x and mx < v.x + v.width and my > v.y and my < v.y + h + margin then
dropdowns[i].selected = dropdowns[i].selected - math.floor(y)
dropdowns[i].selected = (dropdowns[i].selected - 1) % #dropdowns[i].options + 1
2021-09-18 00:05:13 +00:00
createUI()
2021-09-17 22:25:14 +00:00
end
end
end
end
return self