However, it isn't quite like real world, as if you start dyeing the water multiple times, say, "red" and then "green" it doesn't behave in real life. It just says the water is "greenish red". What I needed was a way to model additive and subtractive colour mixing which results in human-readable colours... enter Acme::Colour!
The module takes in colour names, mixes in other colours (either as light or as paint) and returns a colour name. So black with red and green makes yellow if dealing with light, or white plus cyan and magenta makes green if dealing with paint.
The actual colour mixing wasn't the hard part (I got colour values from Graphics::ColorNames). The hard part was returning a colour name. I didn't want to know the red, green and blue values of the resulting colour but rather that it was "dark red". So I get the RGB values and go through every named colour that I know and find the closest match in 3D RGB space. Hey presto: named colours to named colours.
Taken straight from the tests:
$c = Acme::Colour->new("orange");
ok($c, "should get colour");
is("$c", "orange", "should get orange");
is("$c", "dark red", "orange and brown is dark red");
Now all I need to do is make a better pipeline example...