[fixed] feature request: flux tweeing lib table support.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
gcmartijn
Party member
Posts: 134
Joined: Sat Dec 28, 2019 6:35 pm

[fixed] feature request: flux tweeing lib table support.

Post by gcmartijn »

Hello,

I'm use this lib https://github.com/rxi/flux inside my game already.
But now I need a feature that I can't implement at the moment.

The thing is that it is not working with nested tables, like color.

Code: Select all

    local tweenFadeOut = {x = 0, color = {0, 0, 0, 0}}
    Tween.to(textObj, 3, tweenFadeOut)
EDIT

I made a solution but I'm not happy with te result yet.
The alpha fading is to fast (but i'm using in the example 3 seconds...) but it does something.

original code: https://github.com/rxi/flux/blob/master/flux.lua
modified below

Code: Select all

--
-- flux
--
-- Copyright (c) 2016 rxi
--
-- This library is free software; you can redistribute it and/or modify it
-- under the terms of the MIT license. See LICENSE for details.
--

local flux = {_version = "0.1.5"}
flux.__index = flux

flux.tweens = {}
flux.easing = {
  linear = function(p)
    return p
  end
}

local easing = {
  quad = "p * p",
  cubic = "p * p * p",
  quart = "p * p * p * p",
  quint = "p * p * p * p * p",
  expo = "2 ^ (10 * (p - 1))",
  sine = "-math.cos(p * (math.pi * .5)) + 1",
  circ = "-(math.sqrt(1 - (p * p)) - 1)",
  back = "p * p * (2.7 * p - 1.7)",
  elastic = "-(2^(10 * (p - 1)) * math.sin((p - 1.075) * (math.pi * 2) / .3))"
}

local makefunc = function(str, expr)
  local load = loadstring or load
  return load("return function(p) " .. str:gsub("%$e", expr) .. " end")()
end

for k, v in pairs(easing) do
  flux.easing[k .. "in"] = makefunc("return $e", v)
  flux.easing[k .. "out"] = makefunc([[
    p = 1 - p
    return 1 - ($e)
  ]], v)
  flux.easing[k .. "inout"] =
    makefunc(
    [[
    p = p * 2
    if p < 1 then
      return .5 * ($e)
    else
      p = 2 - p
      return .5 * (1 - ($e)) + .5
    end
  ]],
    v
  )
end

local tween = {}
tween.__index = tween

local function makefsetter(field)
  return function(self, x)
    local mt = getmetatable(x)
    if type(x) ~= "function" and not (mt and mt.__call) then
      error("expected function or callable", 2)
    end
    local old = self[field]
    self[field] = old and function()
        old()
        x()
      end or x
    return self
  end
end

local function makesetter(field, checkfn, errmsg)
  return function(self, x)
    if checkfn and not checkfn(x) then
      error(errmsg:gsub("%$x", tostring(x)), 2)
    end
    self[field] = x
    return self
  end
end

tween.ease =
  makesetter(
  "_ease",
  function(x)
    return flux.easing[x]
  end,
  "bad easing type '$x'"
)
tween.delay =
  makesetter(
  "_delay",
  function(x)
    return type(x) == "number"
  end,
  "bad delay time; expected number"
)
tween.onstart = makefsetter("_onstart")
tween.onupdate = makefsetter("_onupdate")
tween.oncomplete = makefsetter("_oncomplete")

function tween.new(obj, time, vars)
  local self = setmetatable({}, tween)
  self.obj = obj
  self.rate = time > 0 and 1 / time or 0
  self.progress = time > 0 and 0 or 1
  self._delay = 0
  self._ease = "quadout"
  self.vars = {}
  for k, v in pairs(vars) do
    self.vars[k] = v
  end

  return self
end

function tween:initVars(vars, k2, v)
  if k2 then
    for k, v2 in pairs(v) do
      self.vars[k2][k] = {start = self.obj[k2][k], diff = v2 - self.obj[k2][k]}
    end
  else
    for k, v in pairs(vars) do
      local x = self.obj[k]
      if type(x) == "table" then
        self:initVars(x, k, v)
      else
        self.vars[k] = {start = x, diff = v - x}
      end
    end
  end
end

function flux:updateVars(vars, x, t, k2)
  if k2 then
    for k, v2 in pairs(vars) do
      t.obj[k2][k] = v2.start + x * v2.diff
    end
  else
    for k, v in pairs(vars) do
      if v.start and v.diff then
        t.obj[k] = v.start + x * v.diff
      else
        self:updateVars(v, x, t, k)
      end
    end
  end
end

function tween:init()
  self:initVars(self.vars)
  self.inited = true
end

function tween:after(...)
  local t
  if select("#", ...) == 2 then
    t = tween.new(self.obj, ...)
  else
    t = tween.new(...)
  end
  t.parent = self.parent
  self:oncomplete(
    function()
      flux.add(self.parent, t)
    end
  )
  return t
end

function tween:stop()
  flux.remove(self.parent, self)
end

function flux.group()
  return setmetatable({}, flux)
end

function flux:to(obj, time, vars)
  return flux.add(self, tween.new(obj, time, vars))
end

function flux:update(deltatime)
  for i = #self, 1, -1 do
    local t = self[i]
    if t._delay > 0 then
      t._delay = t._delay - deltatime
    else
      if not t.inited then
        flux.clear(self, t.obj, t.vars)
        t:init()
      end
      if t._onstart then
        t._onstart()
        t._onstart = nil
      end
      t.progress = t.progress + t.rate * deltatime
      local p = t.progress
      local x = p >= 1 and 1 or flux.easing[t._ease](p)

      flux:updateVars(t.vars, x, t)

      -- for k, v in pairs(t.vars) do
      --   t.obj[k] = v.start + x * v.diff
      -- end
      if t._onupdate then
        t._onupdate()
      end
      if p >= 1 then
        flux.remove(self, i)
        if t._oncomplete then
          t._oncomplete()
        end
      end
    end
  end
end

function flux:clear(obj, vars)
  for t in pairs(self[obj]) do
    if t.inited then
      for k in pairs(vars) do
        t.vars[k] = nil
      end
    end
  end
end

function flux:add(tween)
  -- Add to object table, create table if it does not exist
  local obj = tween.obj
  self[obj] = self[obj] or {}
  self[obj][tween] = true
  -- Add to array
  table.insert(self, tween)
  tween.parent = self
  return tween
end

function flux:remove(x)
  if type(x) == "number" then
    -- Remove from object table, destroy table if it is empty
    local obj = self[x].obj
    self[obj][self[x]] = nil
    if not next(self[obj]) then
      self[obj] = nil
    end
    -- Remove from array
    self[x] = self[#self]
    return table.remove(self)
  end
  for i, v in ipairs(self) do
    if v == x then
      return flux.remove(self, i)
    end
  end
end

local bound = {
  to = function(...)
    return flux.to(flux.tweens, ...)
  end,
  update = function(...)
    return flux.update(flux.tweens, ...)
  end,
  remove = function(...)
    return flux.remove(flux.tweens, ...)
  end
}
setmetatable(bound, flux)

return bound
Ross
Citizen
Posts: 97
Joined: Tue Mar 13, 2018 12:12 pm
Contact:

Re: [fixed] feature request: flux tweeing lib table support.

Post by Ross »

You should just do two separate tweens. One for 'textObj' and one for 'textObj.color'.
gcmartijn
Party member
Posts: 134
Joined: Sat Dec 28, 2019 6:35 pm

Re: [fixed] feature request: flux tweeing lib table support.

Post by gcmartijn »

Not needed with the new code.

This is working perfect now

Code: Select all

  -- Fade the text in (2 seconds) and out (1 second) and move the text 10 pixels to the left, but first wait 3 seconds
    Tween.to(textObj, 2, {color = {255, 255, 255, 1.0}}):after(1, {x = textObj.x - 10, color = {255, 255, 255, 0.0}}):delay(
        3
    )
Post Reply

Who is online

Users browsing this forum: No registered users and 59 guests