At someone else's behest at work I spent a couple of days writing something called Pel::Mel. Basically it acted as a bridge between Perl and MEL, the Maya Embedded Language. The advantages of this are huge - you get support for namespaces and CPAN within MEL and we can do a much better job centrally installing and versioning extensions. The way it works is quite, well, evil.
Essentially it opens a port to Maya and speaks through that. Callbacks are done by recognising a callback being apssed in, stashing it somewhere and then installing a global callback in Maya space that actually writes to a FIFO which the Pel runloop then picks up and demarshalls back into arguments for the actual callback.
I know. I was vageuly surprised when it worked too.
What it does mean is that you can write stuff like ...
my $pel = Pel::Mel->new( port => $port );
my $win = $pel->window( -vis => 1, -title => 'myWin64' ); $pel->rowColumnLayout( -numberOfColumns => 4 );
for (1..64) { $pel->button(-label => $_, -command => [\&foo,$_,"second call back"] ); } $pel->button(-label => "quit", -command => [\&foo,"quit"] );
$pel->window(-edit, -width => 400, -height => 428, $win);
$pel->run;
sub foo { my $data = shift; my $next = shift; if ("quit" eq $data) { $pel->DESTROY; } else { print "callback from perl $data\n"; print "second argument to call back - '$next'\n" if defined $next; print "\n"; } }
and
my $url = "http://news.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml"; my $feed = get($url); my $rss = XML::RSS->new; $rss->parse($feed);
my $text = "";
foreach my $item (@{$rss->{"items"}}) { my $title = $item->{title}; $title =~ s/[^\w ]/ /g; $text .= $title . "; "; last if length($text) > 255; }
$text =~ s/; $//;
my $groupname = $pel->group(-n => "Text_foo0", -em); my $string = $pel->textCurves(-ch => 0, -f => "Courier", -t => quote_arg($text), -n => $groupname);
$pel->setAttr(${string}.".translateX => 0); $pel->setAttr(${string}.".translateY => 0); $pel->setAttr(${string}.".translateZ => 0);
$pel->setAttr(${string}.".rotateX" => 0); $pel->setAttr(${string}.".rotateY" => 0); $pel->setAttr(${string}.".rotateZ" => 0); my $off = 0; while (1) { $pel->setAttr(${string}.".translateX" => -$off); $off = (++$off%200); select(undef, undef, undef, 1/$FPS); }
The last one gets the BBC news headlines and scrolls them through a scene. It's funny loading it into existing scenes and seeing letters float behind characters' heads.