Libraries and meta classes

From Filter Forge Wiki

Revision as of 11:17, 24 November 2011; view current revision
←Older revision | Newer revision→
Jump to: navigation, search

W.I.P.

Neither the forum or the filter library is suitable for publishing general Lua code like functions, meta classes and libraries. Use this wiki section to post the code you want to share. The Common Operations section in the Scripting Tips and Tricks article contains some examples, but these are really just to give a few basic scripting examples; This page is not limited to simple examples.

-- Sphinx.

Contents

About this page

Using code

...

Adding code

...

Modifying code

...

Useful functions

...

Meta Classes

...

Point Class

Documentation

Code

local point = {}
local point_mt = {}

function point.new(x,y)
   return setmetatable({x, y}, point_mt)
end

-- Metatable setup, default operator handling

point_mt.__add = function(a,b)
  -- a+b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		-- both ops are tables, assume xy points, e.g. p1 + p2
		return setmetatable({a[1] + b[1], a[2] + b[2]}, point_mt)
	 else
		-- op 'b' is a single value, eg: p1 + 3
		return setmetatable({a[1] + b, a[2] + b}, point_mt)
	 end
	 elseif (tb == "table") then
	 -- op 'a' is a single value, case: 3 + p1
	 return setmetatable({a + b[1], a + b[2]}, point_mt)
  end
  -- no support for other types, let lua take care of errors
end

point_mt.__sub = function(a,b)
  -- a-b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] - b[1], a[2] - b[2]}, point_mt)
	 else
		return setmetatable({a[1] - b, a[2] - b}, point_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a - b[1], a - b[2]}, point_mt)
  end
end

point_mt.__mul = function(a,b)
  -- a*b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] * b[1], a[2] * b[2]}, point_mt)
	 else
		return setmetatable({a[1] * b, a[2] * b}, point_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a * b[1], a * b[2]}, point_mt)
  end
end

point_mt.__div = function(a,b)
  -- a/b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] / b[1], a[2] / b[2]}, point_mt)
	 else
		-- minor optimization
		local r = 1 / b
		return setmetatable({a[1] * r, a[2] * r}, point_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a / b[1], a / b[2]}, point_mt)
  end
end

point_mt.__mod = function(a,b)
  -- a % b == a - math.floor(a/b)*b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] % b[1], a[2] % b[2]}, point_mt)
	 else
		-- minor optimization
		local r = 1 / b
		return setmetatable({a[1] - math.floor(a[1] * r) * b, a[2] - math.floor(a[2] * r) * b}, point_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a % b[1], a % b[2]}, point_mt)
  end
end

point_mt.__unm = function(a)
  -- -a
  return setmetatable({-a[1], -a[2]}, point_mt)
end

point_mt.__len = function(a)
  return 2
end

point_mt.__pow = function(a,b)
  -- a^b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] ^ b[1], a[2] ^ b[2]}, point_mt)
	 else
		return setmetatable({a[1] ^ b, a[2] ^ b}, point_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a ^ b[1], a ^ b[2]}, point_mt)
  end
end

point_mt.__eq = function (a,b)
  -- a = b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return (a[1] == b[1]) and (a[2] == b[2])
	 else
		return (a[1] == b) and (a[2] == b)
	 end
	 elseif (tb == "table") then
	 return (a == b[1]) and (a == b[2])
  end
  return false
end

point_mt.__le = function (a,b)
  -- a <= b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return (a[1] <= b[1]) and (a[2] <= b[2])
	 else
		return (a[1] <= b) and (a[2] <= b)
	 end
	 elseif (tb == "table") then
	 return (a <= b[1]) and (a <= b[2])
  end
  return false
end

point_mt.__lt = function (a,b)
  -- a < b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return (a[1] < b[1]) and (a[2] < b[2])
	 else
		return (a[1] < b) and (a[2] < b)
	 end
	 elseif (tb == "table") then
	 return (a < b[1]) and (a < b[2])
  end
  return false
end

point_mt.__tostring = function (t)
  return "x,y: ".. t[1]..", ".. t[2]
end

-- aux. meta methods -----------

point_mt.methods = {

  x = function(t) return t[1] end,
  y = function(t) return t[2] end,
  
  length = function(t)
	 local x,y = t[1], t[2]
	 return math.sqrt(x*x + y*y)
  end,
  
  inverse_length = function(t)
	 -- 1 / length
	 local x,y = t[1], t[2]
	 return (x*x + y*y) ^ -0.5
  end,

  sum = function(t)
	 return t[1] + t[2]
  end,
  
  average = function(t)
	 return (t[1] + t[2]) * 0.5
  end,
   
  max = function(t)
	 return math.max(t[1], t[2])
  end,
  
  min = function(t)
	 return math.min(t[1], t[2])
  end,
  
  median = function(t)
	 return (t.min + t.max) * 0.5
  end,
  
  normalized = function(t)
	 -- minor optimization: 1 / sqrt(x) = x^-0.5
	 local x,y = t[1], t[2]
	 local l = (x*x + y*y) ^ -0.5
	 return setmetatable({x * l, y * l}, point_mt)
  end,

  inverse = function(t)
	 return setmetatable({1/t[1], 1/t[2]}, point_mt)
  end,
  
  swap_xy = function(t)
	 return setmetatable({t[2], t[1]}, point_mt)
  end,

  abs = function(t)
	 return setmetatable({math.abs(t[1]), math.abs(t[2])}, point_mt)
  end,

  copy = function(t)
	 return setmetatable({t[1], t[2]}, point_mt)
  end
}
   
point_mt.__index = function (t, k)
  return point_mt.methods[k](t)
end

Vector Class

Documentation

...

Code

-- SPHINX - VECTOR CLASS ----------------------------------------------------------
local vector = {}
local vector_mt = {}

function vector.new(x,y,z)
	return setmetatable({x,y,z}, vector_mt)
end

function vector.cross_product(v1, v2)
    return setmetatable(
     {vec1[2] * vec2[3] - vec1[3] * vec2[2];
      vec1[3] * vec2[1] - vec1[1] * vec2[3];
      vec1[1] * vec2[2] - vec1[2] * vec2[1]}, vector_mt)
end;

function vector.dot_product(v1, v2)
    return (v1 * v2).sum
end;
   
-- Metatable setup, default operator handling

vector_mt.__add = function(a,b)
  -- a+b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		-- both ops are tables, assume xyz vectors, e.g. vec1 + vec2
		return setmetatable({a[1] + b[1], a[2] + b[2], a[3] + b[3]}, vector_mt)
	 else
		-- op 'b' is a single value, eg: vec1 + 3
		return setmetatable({a[1] + b, a[2] + b, a[3] + b}, vector_mt)
	 end
	 elseif (tb == "table") then
	 -- op 'a' is a single value, case: 3 + vec1
	 return setmetatable({a + b[1], a + b[2], a + b[3]}, vector_mt)
  end
  -- no support for other types, let lua take care of errors
end

vector_mt.__sub = function(a,b)
  -- a-b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] - b[1], a[2] - b[2], a[3] - b[3]}, vector_mt)
	 else
		return setmetatable({a[1] - b, a[2] - b, a[3] - b}, vector_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a - b[1], a - b[2], a - b[3]}, vector_mt)
  end
end

vector_mt.__mul = function(a,b)
  -- a*b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] * b[1], a[2] * b[2], a[3] * b[3]}, vector_mt)
	 else
		return setmetatable({a[1] * b, a[2] * b, a[3] * b}, vector_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a * b[1], a * b[2], a * b[3]}, vector_mt)
  end
end

vector_mt.__div = function(a,b)
  -- a/b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] / b[1], a[2] / b[2], a[3] / b[3]}, vector_mt)
	 else
		-- minor optimization
		local r = 1 / b
		return setmetatable({a[1] * r, a[2] * r, a[3] * r}, vector_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a / b[1], a / b[2], a / b[3]}, vector_mt)
  end
end

vector_mt.__mod = function(a,b)
  -- a % b == a - math.floor(a/b)*b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] % b[1], a[2] % b[2], a[3] % b[3]}, vector_mt)
	 else
		-- minor optimization
		local r = 1 / b
		return setmetatable({a[1] - math.floor(a[1] * r) * b,
		   a[2] - math.floor(a[2] * r) * b,
		a[3] - math.floor(a[3] * r) * b}, vector_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a % b[1], a % b[2], a % b[3]}, vector_mt)
  end
end

vector_mt.__unm = function(a)
  -- -a
  return setmetatable({-a[1], -a[2], -a[3]}, vector_mt)
end

vector_mt.__len = function(a)
  -- #a
  -- we could return length of vector, but # operator is often used in loops, so...
  return 3 -- or #a, but length 3 is assumed
end

vector_mt.__pow = function(a,b)
  -- a^b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return setmetatable({a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]}, vector_mt)
	 else
		return setmetatable({a[1] ^ b, a[2] ^ b, a[3] ^ b}, vector_mt)
	 end
	 elseif (tb == "table") then
	 return setmetatable({a ^ b[1], a ^ b[2], a ^ b[3]}, vector_mt)
  end
end

vector_mt.__eq = function (a,b)
  -- a = b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return (a[1] == b[1]) and (a[2] == b[2]) and (a[3] == b[3])
	 else
		return (a[1] == b) and (a[2] == b) and (a[3] == b)
	 end
	 elseif (tb == "table") then
	 return (a == b[1]) and (a == b[2]) and (a == b[3])
  end
  return false
end

vector_mt.__le = function (a,b)
  -- a <= b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return (a[1] <= b[1]) and (a[2] <= b[2]) and (a[3] <= b[3])
	 else
		return (a[1] <= b) and (a[2] <= b) and (a[3] <= b)
	 end
	 elseif (tb == "table") then
	 return (a <= b[1]) and (a <= b[2]) and (a <= b[3])
  end
  return false
end

vector_mt.__lt = function (a,b)
  -- a < b
  local ta,tb = type(a), type(b)
  if (ta == "table") then
	 if (tb == "table") then
		return (a[1] < b[1]) and (a[2] < b[2]) and (a[3] < b[3])
	 else
		return (a[1] < b) and (a[2] < b) and (a[3] < b)
	 end
	 elseif (tb == "table") then
	 return (a < b[1]) and (a < b[2]) and (a < b[3])
  end
  return false
end
  
vector_mt.__tostring = function (t)
  return "x,y,z: ".. t[1]..", ".. t[2]..", ".. t[3]
end

-- aux. meta methods -----------

vector_mt.methods = {
  x = function(t) return t[1] end,
  y = function(t) return t[2] end,
  z = function(t) return t[3] end,
  
  r = function(t) return t[1] end,
  g = function(t) return t[2] end,
  b = function(t) return t[3] end,

  length = function(t)
	 local x,y,z = t[1], t[2], t[3]
	 return math.sqrt(x*x + y*y + z*z)
  end,
  
  inverse_length = function(t)
	 -- 1 / length
	 local x,y,z = t[1], t[2], t[3]
	 return (x*x + y*y + z*z) ^ -0.5
  end,
  
  sum = function(t)
	 return t[1] + t[2] + t[3]
  end,
  
  average = function(t)
	 return (t[1] + t[2] + t[3]) * (1/3)
  end,
  
  max = function(t)
	 return math.max(t[1], t[2], t[3])
  end,
  
  min = function(t)
	 return math.min(t[1], t[2], t[3])
  end,
  
  median = function(t)
	 return (t.min + t.max) * 0.5
  end,
  
  normalized = function(t)
	 -- minor optimization: 1 / sqrt(x) = x^-0.5
	 local x,y,z = t[1], t[2], t[3]
	 local l = (x*x + y*y + z*z) ^ -0.5
	 return setmetatable({x * l, y * l, z * l}, vector_mt)
  end,
  
  inverse = function(t)
	 return setmetatable({1/t[1], 1/t[2], 1/t[3]}, vector_mt)
  end,
  
  abs = function(t)
	 return setmetatable({math.abs(t[1]), math.abs(t[2]), math.abs(t[3])}, vector_mt)
  end,
  
  copy = function(t)
	 return setmetatable({t[1], t[2], t[3]}, vector_mt)
  end
}
 
vector_mt.__index = function (t, k)
  return vector_mt.methods[k](t)
end

Color Class

Documentation

Code

...

Further reading

External Lua scripting resources

Filter Forge Help

General Lua Links

Personal tools