--------------------------------------------------- -- Effect class for the awesome window manager -- A port of mootools Fx Library --------------------------------------------------- -- Licensed under MIT License -- * (c) 2010, Georg Nagel --------------------------------------------------- Effect = {} Effect.__index = Effect function Effect.create(obj, options) local fx = { options = { fps = 40, duration = 0.5 } } setmetatable(fx,Effect) fx._obj = obj if type(options) == 'table' then fx:setOptions(options) end fx._timer = timer({ timeout = 1/fx.options.fps }) fx._timer:add_signal("timeout", function () fx:step() end) fx._is_func = (type(fx._obj) == 'function') fx._props = {} return fx end function Effect:setOptions (options) tmp = self.options for k,v in pairs(options) do self.options[k] = v end end function Effect:start (properties) self._time = 0 o = self._obj if self._is_func then o = self._obj() end if (self._timer.started) then self._timer:stop() end for k,v in pairs(self._props) do if not properties[k] and properties[k] ~= 0 then properties[k] = v.to end end for k,v in pairs(properties) do if o[k] then self._props[k] = { from = o[k], to = v } end end self:validateTransition() self._timer:start() end function Effect:stop() self._timer:stop() end function Effect:step () self._time = self._time + self._timer.timeout local newProps = {} if (self._time < self.options.duration) then for k,v in pairs(self._props) do local delta = self.transition(self._time / self.options.duration) newProps[k] = self:compute(v.from, v.to, delta) end else for k,v in pairs(self._props) do newProps[k] = v.to self._timer:stop() end end self:set(newProps) end function Effect:set (props) if self._is_func then self._obj(props); else for k,v in pairs(self._props) do self._obj[prop] = value end end end function Effect:compute (from, to, delta) return (to - from) * delta + from end function Effect:validateTransition () local trans = self.options.transition; if type(trans) ~= 'function' then trans = Effect.Transitions.linear end self.transition = trans; end Effect.Transitions = {} function Effect.Transitions.linear (zero) return zero end local transitions = {} function transitions.Pow (p, x) if type(x) == 'table' and x[0] then x = x[0] else x = 6 end return math.pow(p, x); end function transitions.Expo (p) return math.pow(2, 8 * (p - 1)); end function transitions.Circ (p) return 1 - math.sin(math.acos(p)); end function Effect.Transitions.Sine (p) return 1 - math.sin((1 - p) * math.pi / 2); end function transitions.Back (p, x) if type(x) == 'table' and x[0] then x = x[0] else x = 1.618 end return math.pow(p, 2) * ((x + 1) * p - x); end function transitions.Bounce (p) if p < 1/2.75 then return 7.5625*p*p end if p < 2/2.75 then p = p - (1.5/2.75) return 7.5625*p*p + 0.75 end if p < 2.5/2.75 then p = p - (2.25/2.75) return 7.5625*p*p + 0.9375 end p = p - (2.625/2.75) return 7.5625*p*p + 0.984375 end function transitions.Elastic (p, x) p = p - 1 if type(x) == 'table' and x[0] then x = x[0] else x = 3 end return match.pow(2, 10 * p) * math.cos(20 * p * math.pi * x / 3); end for i, name in pairs({'Quad', 'Cubic', 'Quart', 'Quint'}) do transitions[name] = function (p) return math.pow(p, i + 2) end end Effect.Transitions.easeIn = {} Effect.Transitions.easeOut = {} Effect.Transitions.easeInOut = {} for name,transition in pairs(transitions) do Effect.Transitions.easeIn[name] = transition Effect.Transitions.easeOut[name] = function (p) return 1 - transitions[name](1 - p); end Effect.Transitions.easeInOut[name] = function (p) local x = p <= 0.5 and transitions[name](2 * p, params) / 2 or (2 - transitions[name](2 * (1 - p))) / 2 return x end end