Other languages — in Field

Field has always been an environment for piecing together large chunks of statically-typed, verbose, and soberly written Java with small amounts of nimble, experimental and heat-of-the-moment Python. Recently we've experimented with integrating alternative languages into Field — both languages that are actually 'hosted' in different applications (Python in Maya and MotionBuilder,AppleScript and JavaScript in Adobe products) and languages that are hosted directly inside Field (most notably Scala).

These experiments are ongoing, but more recently, with Field's move to the Java 6 JDK, we've been able to rapidly open up Field to alternative languages. Our current work in this domain is represented in the jsrscripting plugin. Right now we are playing with JRuby, Mirah, JavaScript, Scala, Clojure and, oddly enough, Java itself.

First (assuming that you've enabled jsrscripting in the plugin manager) note the new palette representing the "additional languages" that Field knows about:

While Field could, in theory, work with any language that has a JSR-223 standard interface for it, integrating the language runtime with Field takes a little work (not much, but a little). So we are going slowly right now as we experiment with these new languages. If you have a favorite let us know.

To actually 'activate' a language and its runtime click on it (and optionally click on the checkbox to get Field to do this automatically).

Each language installs a new Text Transform that pipes code to that language's interpreter (or compiler) and runtime environment — see MayaIntegration or EmbeddingGui for examples of Text transforms in the TextEditor — these appear in the right-click menu for transforms.

JavaC

So how are we doing? The first thing that's working is the idea itself — as you can see from JSRPlugin and it's sources (in 'extras' in the source-tree) there really isn't much to it at all. We're most pleased with the "Java" plugin:

This image shows most of what's working right now:

  • Bound.name(). For other variables there's the static namespace Bound. To offer variables up to this interface, use code like you see above: _self.java.someVariable = someValue. To access this from Java say Bound.someVariable() (note the (), this is a method call not a field). The contents of this transient class Bound is automatically made out of the contents of the magic variable _java just before you compile the code — the value of the variable is used to determine the class it presents to Java's type system. For other languages we have similar magic objects in the Python namespace (for example, _clojure).

  • Classes that are defined are propagated back out into the main Field environment — so you can instantiate and pass around the things that you define.

We can add one more useful text transform, something that does away with the class preamble. This is great if you are just wanting to define a method that does something and are happy with using Bound.something() to access things in the outer Field environment:

This Text transform defines a parameterless method (here 'randomize') that you can just call from Python like any other function. You'll also note that some of the embedded GUI elements work just fine (specifically the ones that don't use Python's magic to get their task done). If you really wanted to you could make a new Text Transform that turned around and called the JavaC transform that would do away with the outer class declaration — instantly you have something that resembles Processing. In fact, this is such a good idea that you'll find just this feature in Beta 10 and above (see ProcessingIntegrationFourWays).

Other languages: Clojure

We're also pretty excited about this:

That's Clojure (and Incanter) embedded directly into Field, with it's graphs being drawn as FLines

See IncanterInField, and ExperimentsInOvertone for more Clojure in Field action.

Other Languages: JRuby

Finally we're taking a close look at JRuby. And like the examples above, is probably best summarized as a screenshot:

In short:

  • _ruby.foo enables access to the variable $foo in JRuby (in much the same way as _clojure works in the Clojure integration and _java).
  • To export things from Python to JRuby you just set them in _ruby
  • Field's JRuby environment can see both Field's classes (and classes extended in the plugin manager) and JRuby's standard library.

_r in other languages

Other things from Field can be integrated into JRuby and Clojure. For example:

include Java
include_class Java::java.lang.Math
include_class Java::field.math.linalg.Vector3

$_r = proc {
    m = (0..100000).to_a
    x = 0
    v = Vector3.new 
    for q in m
        x += v.x
    end
}

This defines a _r method for "animating". Likewise Clojure (that uses Quil):

(use 'quil.core)
(use 'quil.dynamics)
(use 'quil.applet)

(.set applet-tl user/p)

(defn get-field-var [q]
    (.getVariable (field.core.execution.PythonInterface/getPythonInterface) q))


(defn _r []
    (stroke (random 255))
    (stroke-weight (random 10)) 
    (fill (random 255)) 


    (let [diam (random 100) 
        x   (random (* (get-field-var "_t") (width))) 
            y   (random (height))] 
    
        (ellipse x y diam diam))
)