Page 1 of 2
Color Constant Trick
Posted: Wed Jun 20, 2012 11:11 pm
by ejmr
I recently posted a thread asking for some help, and got some great responses. So I wanted to give back by sharing a trick I learned while working on my current game project which others may find useful.
I found myself reading writing lots of calls like
Code: Select all
love.graphics.setColor(96, 85, 64)
Unless you are really familiar with your RGB values---and I am not---you may not know that creates a dark orange color. I wanted to create named color constants. So at first I created a table like so:
Code: Select all
Colors = {}
Colors.darkOrange = { 96, 85, 64 }
Colors.yellow = { 196, 196, 0 }
-- And so on.
The Lua function unpack() lets you take an array/table and expand its values as the parameters to a function call. So this let me go back and start writing
Code: Select all
love.graphics.setColor(unpack(Colors.yellow))
Except I felt calling unpack() every time was tedious on its own. Enter the usefulness of metatable functions. You can change the __index() function for a table to automatically unpack values. So I returned to my table of colors and added this:
Code: Select all
Colors.__index =
function (table, key)
local value = rawget(table, key)
if value ~= nil then
return unpack(value)
else
return nil
end
end
Now writing Colors.yellow is the same as unpack(Colors.yellow). This let me return to my original code and replace it with the more readable (in my opinion)
Code: Select all
love.graphics.setColor(Colors.darkOrange)
.
Just a simple trick I wanted to share that maybe some of you will find useful.
Re: Color Constant Trick
Posted: Wed Jun 20, 2012 11:23 pm
by Xgoff
i'd be surprised if that would work because iirc __index always truncates to 1 return value
also, setColor can take a table directly so you don't need to unpack anyway
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 1:05 am
by ejmr
Xgoff wrote:i'd be surprised if that would work because iirc __index always truncates to 1 return value
It works without any errors or problems.
also, setColor can take a table directly so you don't need to unpack anyway
Looks like a change added in version 7.0.0. Thanks for pointing this out.
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 3:01 am
by Xgoff
ejmr wrote:Xgoff wrote:i'd be surprised if that would work because iirc __index always truncates to 1 return value
It works without any errors or problems.
actually, it works because of setColor's table support; __index doesn't even get called since the fields already exist in the Colors table
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 5:41 am
by OmarShehata
Neat trick though! Thanks for posting.
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 5:45 am
by ejmr
Thanks! Xgoff is correct, however, in that __index() is not even called in my specific example. But the trick could be useful in other situations where you want to unpack() something automatically or modify the behavior of normal table access.
Ah, I do love the power of metatables in Lua
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 8:04 am
by coffee
ejmr wrote:Just a simple trick I wanted to share that maybe some of you will find useful.
Thanks. As alternative method you wouldn't need to metatable or unpack nothing if you use a shortcut function to the long love.graphics.setColor. I did it here
viewtopic.php?f=4&t=4854#p41738 for a shorter custom setColor(). As you see do basically the same constant color trick and as extra also use alpha naming/gradations. But your unpack method in vanilla command is also neat.
Miko did something close to yours here
viewtopic.php?f=4&t=4854#p41760
BTW scirath's color management
viewtopic.php?f=5&t=7378 is a very good advanced application of your naming concept.
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 8:50 am
by kikito
ejmr wrote:It works without any errors or problems.
I have not tried it, but I'm very sure trying to combine the Colors lib with an alpha value would fail:
Code: Select all
love.graphics.setColor(Colors.darkOrange, 128) -- I want to apply the color, and some alpha, too
To be fair, an explicit unpack would also fail.
Code: Select all
love.graphics.setColor(unpack(Colors.darkOrange), 128) -- same kind of fail
The only way I think this would work would be making darkOrange a function (or probably a callable table), so it can accept-and-pass an alpha value. In other words, to be used like this:
Code: Select all
love.graphics.setColor(Colors.darkOrange(128)) -- this could work, but requires more plumbing into the colors
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 9:24 am
by coffee
kikito wrote:ejmr wrote:It works without any errors or problems.
I have not tried it, but I'm very sure trying to combine the Colors lib with an alpha value would fail:
Code: Select all
love.graphics.setColor(Colors.darkOrange, 128) -- I want to apply the color, and some alpha, too
To be fair, an explicit unpack would also fail.
Code: Select all
love.graphics.setColor(unpack(Colors.darkOrange), 128) -- same kind of fail
The only way I think this would work would be making darkOrange a function (or probably a callable table), so it can accept-and-pass an alpha value. In other words, to be used like this:
Code: Select all
love.graphics.setColor(Colors.darkOrange(128)) -- this could work, but requires more plumbing into the colors
I pointed before miko method. Don't his way solve that problem?
viewtopic.php?f=4&t=4854#p41760
Code: Select all
ALPHAS={['half']=128, ['total']=0, ['opaque']=255}
COLORS={['black']={0,0,0}, ['white']={255,255,255}}
MT_Color={
alpha=function(self, a)
if not a then return end
self[4]=ALPHAS[a] or tonumber(a)
end,
RGB=function(self, r, g, b)
if not r then return end
if type(r)=='string' then
local c=COLORS[r]
if c then
for i=1,3 do
self[i]=c[i]
end
else
error('Unknown color: '..r)
end
else
self[1], self[2], self[3]=r, g, b
end
end
}
MT_Color.__index=MT_Color
function newColor(r, g, b, a)
local o=setmetatable({0,0,0,0}, MT_Color)
o:RGB(r, g, b)
o:alpha(a or 255)
return o
end
green=newColor(0,255,0)
print('green 1', unpack(green))
green:alpha('half')
print('green 2', unpack(green))
green:RGB('white')
print('green 3', unpack(green))
love.graphics.setColor(green)
Re: Color Constant Trick
Posted: Thu Jun 21, 2012 11:15 am
by ejmr
kikito wrote:ejmr wrote:It works without any errors or problems.
I have not tried it, but I'm very sure trying to combine the Colors lib with an alpha value would fail:
Code: Select all
love.graphics.setColor(Colors.darkOrange, 128) -- I want to apply the color, and some alpha, too
This is true; it does fail in this circumstance. Thank you for pointing out this short-coming so I can rectify it in my own project.