Consume, don't compete
One principle behind Field is that we like to consume other applications (by wrapping, linking and bridging) rather than compete with them (by re-implementing their features and interfaces). This is the principle that led to the ProcessingPlugin and it's part of the idea with our interest in including other languages into Field. Field is a cake-having-and-eating framework.
The page documents how Field can reach out to other applications.
Integration with Maya
One set of examples are from Autodesk: Maya and MotionBuilder now have Python integration. This can only be a good thing — 3d graphics programs have for a decade or more labored on with badly designed and badly implemented languages (there was a moment in time when MaxScript couldn't make up its mind if its arrays were 0- or 1- indexed).
Of course, in keeping with what, to our eye at least, is an incredibly flakey and ugly user interface, Maya's script editor leaves a lot to be desired. So there's been some interest in using Field — mainly in its capacity as a glorified text editor with a strong desktop metaphor — to execute commands in Maya. I'm very interested to see where this will be taken by people who are much more invested in Maya than we have.
Fortunately, "executing code somewhere else" is something that I've needed to do a lot in Field. And as of this writing there are three main ways for doing this in Field. The first is the remote plugin — which is useful for communicating between FIeld instances. But the other two work with Maya (and MotionBuilder) just fine.
Text transform area
Causing some part of the text editor to end up executing somewhere else in Field is easy — you can use a block transformation to achieve this result.
First, you insert into your text editor a "block transform begin" and a "block transform end" (right-click and select these from the popup menu). These are just embedded labels: give the begin the name 1. mel and the end the name \1. mel. Text transform begin's look for identically named 'ends' to pair up with to demarcate an area in the text editor. The mel refers to a function we're going to define that's going to be the text transform. The 1 tell's field that we're going to use command-1 as the keyboard shortcut for executing this text block.
Now we need our function mel that takes a string and causes it to be sent over a socket to Maya:
import telnetlib _self.host_ = _self.host_ or telnetLib.Telnet("localhost", 8999) def mel(scope, commands, global): _self.host_.write(commands)
So now we have something that looks like:
And in in Maya itself you run the command:
comandPort -name ":8999"
runs the telnet MEL-server. Adding -prefix "python" to that, gets you a (albeit single line) python-server.
In MotionBuilder, you are looking for this dialog:
which will start a telnet python server on port 4242.
Now we have an area in the Field text editor that, when it's executed, is actually executed in Maya or MotionBuilder? instead. The code looks like any other piece of code to the rest of Field: that is, it can be executed in timelines, it can hold embedded UI elements, it's version controlled &c. It just happens to execute remotely.
Sending things over to a telnet socket is so useful (above and beyond Maya integration), that it's included in Field's standard library — just use the text transform telnet(portnumber) — no further work necessary.
While we're here we can note two things about the block transform system. Firstly, by convention the string passed into the telnet(port[,host]) transform is automatically %'d with globals(), so we can include variables from the enclosing scope by saying %(myVariable)s. Secondly, it works just fine with Python's indentation. So we can also have the following, slightly odd looking mix of Python and MEL:
SimpleXMLRPCServer
Another, more conventionally-python way, is also perfectly possible inside Field: use Python's SimpleXMLRPCServer, which, as the name suggests makes an XML-RPC server. Because there's Python at either end of this communication, this is very easy:
In Field:
cmds = _self.cmds_ = _self.cmds_ or DictXMLServer("http://localhost:8999")
(In order to fully understand this idomatic use of the Field special variable _self you might want to look at ImportantPlugins and DelegationAndVisualElements).
In Maya, the slightly ungainly:
import thread from SimpleXMLRPCServer import SimpleXMLRPCServer from maya.utils import * class mainThreadHandler(SimpleXMLRPCRequestHandler): def _dispatch(self, method, params): x = getattr(cmds,method) kw = None p = [] for n in params: if (isinstance(n, type({}))): kw = n else: p.append(n) p = tuple(p) y = executeInMainThreadWithResult(x, *p, **kw) return y def log_message(self, format, *args): print format % args def dispatchForever(x): server = SimpleXMLRPCServer(("localhost", 8999), mainThreadHandler, allow_none=1) print "registering" for n in dir(cmds): xx= getattr(cmds, n) if (callable(xx)): server.register_function(getattr(cmds, n)) print "registering complete, serving" server.serve_forever() thread.start_new_thread(dispatchForever, (None,))
A more competent Maya person could perhaps assign this to a button, or make it run on startup. But most of this code (including the Field standard library class DictXMLServer) comes about because of SimpleXMLRPCServer's unwillingness to handle keyword arguments (and Maya's reliance on them). There's also some messing around with Maya's threading model.
In any case, now we can just write:
mySphere = cmds.sphere(radius=20)
in Field and it's magically executed in Maya. As is:
spheres = [] for n in range(0, 4): spheres.append(cmds.sphere(radius=20+n*10)) for s in spheres: cmds.move(10,20,30,s)
And so on — it's simply Python code. Return values are 'correct' (which would be more exciting if Maya made better use of them), auto-completion works &c. And again, the code looks like any other piece of code to Field.
AppleScript & everybody else
Apple makes some of this "forced entry" into proprietary applications quite easy with its AppleScript support.
Field includes the applescript text transform:
Executing this causes the Finder to show a file.
Based on this, we can begin to sneak our way into other applications. Recently, a frustrating journey into the depths of After Effects's JavaScript scripting got a shade less frustrating when we realized that we could supply JavaScript via AppleScript (!). The aftereffects text transform was born:
Yields
Presumably we could run a JavaScript XML-RPC client inside After Effects and do a similar trick as we did with Maya above...
So, Maya, MotionBuilder, After Effects, Photoshop (by extension) ...




