Understanding metatables

From GMod Wiki

Jump to: navigation, search
Lua: Understanding Metatables
Page white text.png Description:Explains Lua metatables
link=User:Anders Original Author:Anders
Calendar.png Created:1st December 2006
Stub.pngThis article is a stub.
You can help the GMod Wiki by expanding it.
This article is far from completed... if you can help out that would be great! The article might not be as clear as I wanted it to be, so if you have any suggestions please tell me on the article discussion page! --Anders 18:06, 1 December 2006 (GMT Standard Time)

Contents

What are Metatables?

Metatables let you change the behavior of the data types available in Lua. They are heavily used by GMod to implement custom data types, such as Vectors, Angles, Players and so on. Metatables are very useful for object oriented programming.

In this article I will implement a custom data type for defining colors.

Metamethods

The available metamethods are:

Color library

This is the color library that I've written.

 
-- This is supposed to be saved as lua/includes/modules/color.lua
module("color", package.seeall) -- Without package.seeall we would not be able to see any variables in the global scope (Msg etc)
 
local mt = {} -- The metatable
local methods = {} -- Methods for our color objects
mt.__index = methods -- Redirect all key "requests" to the methods table
 
-- Function for creating new color objects
--
-- Usage: col = color.new() or
--        col = color.new(red, green, blue, alpha)
function new (r, g, b, a)
  local obj = {} -- This is the color object
  obj.r = r or 0
  obj.g = g or 0
  obj.b = b or 0
  obj.a = a or 255
 
  setmetatable(obj, mt) -- This is the magic that makes everything work
  return obj
end
 
 
 
 
 
-- Override tostring() return value, without this, using tostring() on a color object would just return "table: 0xDEADBEEF"
function mt:__tostring ()
  -- You see how I use self below? This is because I used ":".
  -- It is syntactic sugar for adding the self argument. You could have written
  -- "function mt.__tostring (self)", it does the same... absolutely no difference.
 
  return "Color: "..self.r.." "..self.g.." "..self.b..." "..self.a
end
 
-- Define the multiplication operator
-- Example: col = col1 * col2
--          col = col * 2
function mt:__mul (m)
  local mr, mg, mb, ma
 
  if type(m) == "table" then
    -- Make sure it's a color object
    if getmetatable(m) == mt then
      -- Copy the colors from the other color
      mr = m:R()
      mg = m:G()
      mb = m:B()
      ma = m:A()
    else
      error("can only multiply colors with other colors or numbers")
    end
  else if type(m) == "number" then
    m = math.floor(m)
    mr = m
    mg = m
    mb = m
    ma = m
  else
    error("can only multiply colors with other colors or numbers")
  end
 
  self.r = math.Clamp(mr * self.r, 0, 255)
  self.g = math.Clamp(mg * self.g, 0, 255)
  self.b = math.Clamp(mb * self.b, 0, 255)
  self.a = math.Clamp(ma * self.a, 0, 255)
end
 
-- Define the division operator
-- Example: col = col / col2
--          col = col / 2
function mt:__div (d)
  local dr, dg, db, da
 
  if type(d) == "table" then
    -- Make sure it's a color object
    if getmetatable(d) == mt then
      -- Copy the colors from the other color
      dr = d:R()
      dg = d:G()
      db = d:B()
      da = d:A()
    else
      error("can only multiply colors with other colors or numbers")
    end
  else if type(d) == "number" then
    d = math.floor(d)
    dr = d
    dg = d
    db = d
    da = d
  else
    error("can only multiply colors with other colors or numbers")
  end
 
  self.r = math.Clamp(dr / self.r, 0, 255)
  self.g = math.Clamp(dg / self.g, 0, 255)
  self.b = math.Clamp(db / self.b, 0, 255)
  self.a = math.Clamp(da / self.a, 0, 255)
end
 
 
 
 

See Also

Personal tools
Namespaces
Variants
Actions
Navigation
Lua Scripting
Functions
Hooks
Toolbox