| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- local g = love.graphics
- require 'lib/component'
- Dropdown = extend(Component)
- function Dropdown:activate()
- self.value = nil
- self.choices = self.choices or {}
- self.factor = 0
- self.prevFactor = self.factor
- self.hoverFactor = 0
- self.prevHoverFactor = self.hoverFactor
- self.choiceHoverFactors = {}
- self.prevChoiceHoverFactors = {}
- self.hoverDirty = false
- end
- function Dropdown:update()
- local mx, my = love.mouse.getPosition()
- local ox, oy = self:getOffset()
- mx, my = mx + ox, my + oy
- local hover = self:contains(mx, my)
- self.prevFactor = self.factor
- self.prevHoverFactor = self.hoverFactor
- self.factor = math.lerp(self.factor, self:focused() and 1 or 0, math.min(16 * ls.tickrate, 1))
- self.hoverFactor = math.lerp(self.hoverFactor, (self:focused() or hover) and 1 or 0, math.min(16 * ls.tickrate, 1))
- if self:focused() then
- local hoverIndex = self:contains(mx, my)
- local hoverAmount = 1 + (love.mouse.isDown('l') and .5 or 0)
- for i = 1, #self.choices do
- self.prevChoiceHoverFactors[i] = self.choiceHoverFactors[i] or 0
- self.choiceHoverFactors[i] = math.lerp(self.prevChoiceHoverFactors[i], i == hoverIndex and hoverAmount or 0, math.min(16 * ls.tickrate, 1))
- end
- if hover then
- if self.hoverDirty ~= hoverIndex and hoverIndex ~= 0 and (not self.gooey.focused or self.gooey.focused == self) then
- ctx.sound:play('juju1', function(sound) sound:setPitch(.75) end)
- self.hoverDirty = hoverIndex
- end
- else
- self.hoverDirty = false
- end
- end
- if hover then
- if not self.hoverDirty and (not self.gooey.focused or self.gooey.focused == self) then
- ctx.sound:play('juju1', function(sound) sound:setPitch(.75) end)
- self.hoverDirty = true
- end
- else
- self.hoverDirty = false
- end
- end
- function Dropdown:render()
- local u, v = ctx.u, ctx.v
- local x, y, w, h = unpack(self.geometry())
- local mx, my = love.mouse.getPosition()
- local ox, oy = self:getOffset()
- mx, my = mx + ox, my + oy
- local hoverIndex = self:contains(mx, my)
- local choiceHoverFactors = table.interpolate(self.prevChoiceHoverFactors, self.choiceHoverFactors, ls.accum / ls.tickrate)
- local hoverFactor = math.lerp(self.prevHoverFactor, self.hoverFactor, ls.accum / ls.tickrate)
- local factor = math.lerp(self.prevFactor, self.factor, ls.accum / ls.tickrate)
- local dropdownHeight = self:getDropdownHeight() * factor
- local font = g.setFont('mesmerize', h - .02 * v)
- g.setColor(255, 255, 255, 40 + (20 * hoverFactor))
- g.rectangle('fill', x, y, w, h)
- g.setColor(0, 0, 0, 255 * factor)
- g.rectangle('fill', x, y + h, w, dropdownHeight)
- if hoverIndex and hoverIndex > 0 then
- g.setColor(255, 255, 255, 30 * choiceHoverFactors[hoverIndex])
- g.rectangle('fill', x, y + h * hoverIndex, w, h)
- end
- --[[g.setColor(255, 255, 255, 255)
- g.rectangle('line', math.round(x) + .5, math.round(y) + .5, w, h)]]
- for i = 1, #self.choices do
- local factor = factor
- local hoverFactor = 0
- if self:focused() then
- local prev = self:getDropdownHeight() * (i - 1) / #self.choices
- factor = math.clamp((dropdownHeight - prev) / h, 0, 1) ^ 4
- hoverFactor = choiceHoverFactors[i]
- end
- local alpha = math.min(180 * factor + (75 * hoverFactor), 255)
- if self.choices[i] == self.value then g.setColor(100, 200, 50, 255 * factor)
- else g.setColor(220, 220, 220, alpha) end
- g.print(self.choices[i], x + .01 * v, y + h * i + .01 * v)
- end
- g.setColor(255, 255, 255)
- g.print(self.label, x + .01 * v, y + .01 * v)
- g.setColor(100, 200, 50, 255)
- g.print(self.value, x + w - .01 * v - font:getWidth(self.value), y + .01 * v)
- end
- function Dropdown:mousepressed(mx, my, b)
- local ox, oy = self:getOffset()
- mx, my = mx + ox, my + oy
- if b == 'l' and self:contains(mx, my) then
- self.gooey.hot = self
- if self:focused() then return true end
- end
- end
- function Dropdown:mousereleased(mx, my, b)
- local ox, oy = self:getOffset()
- mx, my = mx + ox, my + oy
- if b == 'l' then
- if not self:focused() then
- if self.gooey.hot == self and self:contains(mx, my) then
- self.gooey:focus(self)
- ctx.sound:play('juju1', function(sound) sound:setPitch(1) end)
- end
- else
- local hit = self.gooey.hot == self and self:contains(mx, my)
- self.gooey:unfocus()
- if hit then
- self.value = self.choices[hit] or self.value
- self:emit('change', {component = self})
- ctx.sound:play('juju1', function(sound) sound:setPitch(1) end)
- return true
- end
- end
- end
- end
- function Dropdown:contains(mx, my)
- local x, y, w, h = unpack(self.geometry())
- if math.inside(mx, my, x, y, w, h) then return 0 end
- if self:focused() then
- for i = 1, #self.choices do
- if math.inside(mx, my, x, y + h * i, w, h) then
- return i
- end
- end
- end
- return false
- end
- function Dropdown:getDropdownHeight()
- local h = self.geometry()[4]
- return h * (#self.choices)
- end
|