Strata Live 3D CX / Meson User Manual

Overview

"Meson" is the name of a suite of connected technologies which allow interactive applications with both 2D and 3D elements to be developed quickly, and with a very small execution footprint. Like "Java" the name denotes a language, an object model of predefined classes, and a runtime execution environment.

The ordinary deployment method of a Meson application is in an applet on a web page. The following example shows a typical use case:

<html><body>
<applet code='com.kaon.meson.MesonApplet' archive='mesonApplet.jar,rasterGluon.jar,sceneGluon.jar' width=400 height=300>
<param name='meson' value='
Applet.Primary.fill="336699";
Applet.Primary.image="/images/productDemo/splash.jpg";
Meson.gluon("com.kaon.meson.raster.RasterGluon");
Data.Primary.url="/apps/productDemo/program.jar";
'>
</applet>
</body></html>

In this example, a short program is given right in the HTML file, using the meson applet parameter. This program uses the trick of giving an attribute value over multiple lines, in order to improve readability. Note, however, that the HTML processor strips out the line feeds before passing the parameter to the applet, so the applet receives this program as one very long line. Therefore, each line ends with a ; to break the statements up for the parser. This program sets the background color of the applet (used until an image appears), then sets the initial image in the applet using a URL relative to this page. Next it loads the Java code used for 2D (raster) operations, and then creates a data source to fetch the application program. This program would display its own progress meter, and load other Java code to extend the functionality into the 3D space.

Note that there is no way to express the ' (apostrophe) character in a HTML parameter value. Therefore, this character is not required in the Meson language. If you need to include ' in a program on a web page, the unicode version \u0027 can be used.

Developing a Meson program using only a browser to debug can be difficult. For this reason, Meson includes a console application called "blackboard" which executes program files, and has a command-line interface into which expressions can be typed. In this way, it is similar to a LISP development environment, where debugging and programming are performed with the same tool. In the context of the blackboard application, the above program would be this:

/* Create the Primary applet window 400x300 */
Meson.newApplet(["Primary",400,300])
/* The rest is the same, except there is no need for trailing ; on each line */
Applet.Primary.fill="336699"
Applet.Primary.image="/images/productDemo/splash.jpg"
Meson.gluon("com.kaon.meson.raster.RasterGluon")
Data.Primary.url="/apps/productDemo/program.jar"

To run the blackboard application with a command line interface, open a command window, and cd to the folder where Live 3D is installed. Then type the following: jre/bin/java -mx96M -jar blackboard.jar optionally followed by the names of text files containing Meson program statements. To run the blackboard program non-interactively, just drag a program text file onto the Blackboard.exe launcher icon.

The blackboard application adds a few items to the Meson environment:

  • Meson.newApplet takes an array with up to 5 elements as its argument. First is the name of the applet, which can be prepended with a * to request an applet window with no title bar or close button. Then width and height, followed optionally by left and top screen coordinates.
  • Meson.exit takes a single number argument, causing the blackboard application to terminate with that exit code.
  • The attribute javaWindow is added to the Applet object, which can then be manipulated using Java reflection.
  • The attribute windowClosed is added to the Applet object, with the default value {Meson.exit(0)}. This can be changed by the application, as needed.

Conceptual Framework

The heart of a Meson environment is the blackboard. This is a common place where all data is stored. Each piece of data on the blackboard (each "attribute") has a name and a value. For example, Meson.clock ::= 5.3 is a way of expressing that the datum called "Meson.clock" has the value "5.3". The power in the Meson language comes from the ability to put expressions into the blackboard, which get their values by performing operations on other attributes in the blackboard. For example, Image.Blue.x ::= Image.Yellow.mouseX+50 says that the value of the attribute Image.Blue.x should always be 50 larger than the current value of the attribute Image.Yellow.mouseX. These two examples are expressed in the Meson language as follows:

Meson.clock=5.3
Image.Blue.x={Image.Yellow.mouseX+50}

The Meson.clock example is called an immediate expression, whereas the Image.Blue.x example is a deferred expression. When an expression references an attribute on the blackboard which is defined by a deferred expression, that expression is evaluated. In the semantics of Java, a deferred expression is like a method, whereas an immediate expression is like an instance variable. For almost all cases, deferred expression can fully describe the dynamic state of the sytem. However, for the few cases where this is not true, the Meson runtime provides the concept of a Trigger. A trigger combines some sort of test, with an expression to evaluate under conditions described by the test. There are several variations of Trigger, to detect "transition to true" conditions, "value changed" conditions, and "value might have changed" conditions. Triggers are only evaluated when the attributes in their test are assigned new values. In the case of deferred expression, the Trigger wll be tested when any attribute used in that expression is assigned a new value. In general, there are two ways to express most relationships between attributes:

Procedural
/* Re-center the toolbar when the display width changes using a Trigger */
ChangeTrigger.ToolCenter.test={Display.Primary.width}
ChangeTrigger.ToolCenter.exec={Image.Toolbar.x=Display.Primary/2}
Declarative
/* Define the toolbar to always be centered */
Image.Toolbar.x={Display.Primary.width/2}

When a choice like this exists, do not use the Trigger. The latter expression is more concise, easier to debug, and more efficient than the former expression. The temptation will probably be to use the former method, because that is how it would be done in a procedural language like Java or Basic. But Meson is a declarative language, not a procedural one. A Trigger should be used only when there is no way to express the relationship in a declarative manner, as shown in the following example:

/* Show the pressed state when the mouse is pressed (Declarative) */
Area.Button1.state={Area.Button1.press?"press":"off"}
/* Increment a counter on each press (Procedural) */
Trigger.Button1.test={Area.Button1.press}
Trigger.Button1.exec={counter=counter+1}

The blackboard uses a smart cache to minimize the runtime cost of using deferred expressions. For example, if Image.Toolbar.x is defined as follows:

Image.Toolbar.x={Display.Primary.width/2}

the first time anything reads Image.Toolbar.x from the blackboard, the calculation will be performed. This value is cached, and every other blackboard value which contributed to its calculation (just Display.Primary.width in this case), is tagged with the cache dependency. If Display.Primary.width changes, then the cached value of Image.Toolbar.x will be dropped. But until then, subsequent reads of this attribute will be essentially free. In a typical Meson application, about 90% of attribute fetches from the blackboard hit the cache.

The presence of the cache is generally transparent to the Meson programmer. However, there is one case which requires special care: programming by side effect. When an attribute on the blackboard is really being used as a procedure, callers must use care to reference it using procedure call semantics. For example:

/* Define a procedure to increment the counter */
increment={counter=counter+1}
/* Increment a counter on each press */
Trigger.Button1.test={Area.Button1.press}
Trigger.Button1.exec={increment()}

Note the use of parenthesis in the read of increment. This tells the cache system to evaluate the expression, regardless of whether a value might be cached.

The blackboard is augmented with a scratch data storage area, called the notebook. The notebook has pages, which can store attributes, much like the blackboard. The idea of the notebook is that it is a semi-private area where an expression can take notes without polluting the blackboard. For example:

distSquared={#dx=Applet.Primary.mouseX-cx;#dy=Applet.Primary.mouseY-cy;
                     #dx*#dx+#dy*#dy}

In this example, two notebook attributes (#dx and #dy) are used to store temporary values. Reading and writing attributes in the notebook is more efficient than working on attributes on the blackboard, because notebook attributes have two restrictions: notebook attributes cannot be tested in a Trigger, and notebook attributes cannot be objects (for example, #Image.Foo.x does not create an object of class Image, whereas Image.Foo.x would implicitly create such an object). Also, notebook attributes are not cached.

An application uses attributes on the current page of the notebook with the # operator. It is also possible to use attributes on the next page of the notebook, using the ^ operator. This facility is provided as an argument passing mechanism -- when an attribute is referenced using function notation (for example, Meson.sin(3.14)), the notebook page is advanced. This way each function can safely write any attribute without concern for trashing someone else's notes.

squareSum={#dx*#dx + #dy*#dy}
distSquared={squareSum(^dx=Applet.Primary.mouseX-cx;
                     ^dy=Applet.Primary.mouseY-cy)}

The remainder of this document fully describes the Meson language and object model.


Syntax

Meson programs are written in a line-oriented declarative language. A typical line of a Meson program looks like this:

attribute=value

Attributes can be simple names, or they can be fully qualified object members. For example:

/* Assign 5 to x */
x=5
/* Assign 5 to the x attribute in object Toolbar, of class Image */
Image.Toolbar.x=5

Each delcaration occurs on a single logical line. If the text is long, lines can be split by ending them with \ (similar to some BASIC interpreters). Unbalanced curly braces implicitly cause line continuation:

Image.Label.text="This is a very long string "+ \
                     "which has been split across lines."
Scene.3d.width={Display.Primary.Width-
                     Image.RightToolbar.Width}

Literal symbols include quoted strings (as with Javascript, the forms "string" and 'string' are both allowed, to ease embedding quote and apostrophe characters within strings), the special strings true and false, and any string of non-operator characters starting with any of the following: ._-0123456789 (period, underscore, minus sign, and digits). In essence, the quotes are optional when symbols start with these characters. Whether a symbol denotes a number depends on how it is used, not on what its starting character is. The symbols true and false are recognized by the parser and need not be quoted. Using quotes around a string allows the use of any special character, and also enables the use of escaping (\n for newline, \t for tab, \" for a quote, \' for an apostrophe, and \uXXXX for a unicode character). Note that the parser reads the text as UTF-8 encoded unicode, so using unicode escapes is only necessary if the text is being edited with a ASCII editor, like Notepad.

/* Examples of literal strings */
Style.Default.color=336699
Style.Default.color="336699"
Style.Default.color="FFFFFF"
black="ff000000"
text='He said, "Hello".'
text="It's my party..."
/* Example of attribute reference */
Style.Default.color=black
/* Example of attribute reference thru a literal string (functionally identical to previous line) */
Style.Default.color=@("black")
/* String using escaping character (newline) */
Image.Logo.text="Powered By\nwww.strata.com"
/* String using unicode escape for ° symbol */
Image.Temp.text={"Current Temp: " ~ temp ~ "\u00B0 C"}

There are two kinds of expressions which can be used on the right side of an assignment: immediate and deferred. An immediate expression is evaluated right away, whereas a deferred expression is like a little program which will run on demand:

Examples of immediate expressions.

/* Set the width of the main 3D window */
Scene.3d.width=300
/* Center the toolbar */
Image.Toolbar.anchor=_C
Image.Toolbar.x=Scene.3d.width/2

Examples of deferred expressions.

/* Set the width of the main 3D window to always match the primary display */
Scene.3d.width={Display.Primary.width}
/* Set the position of the toolbar to always be centered */
Image.Toolbar.x={Display.Primary.width/2}

Expressions can combine terms using a variety of operators:

  • * / %  Multiply, Divide, Remainder
  •  + -   Add, Subtract
  • ! & |  Not, And, Or (boolean operators)
  •  ∪ \   Union, Set Minus (array operators; ++ -- also accepted)
  •   ~    Concatenate (string operator)
  • ≈ < >  Equal to, Less Than, Greater Than (== is accepted in place of )
  • ≠ ≤ ≥  Not Equal to, Less or Equal, Greater or Equal (!= <= >= also accepted)
  •  ? :   Test (a?b:c means if (a==true) then b else c), the : clause is optional
  • @ # ^  Attribute Reference, Local Reference, Parameter Reference
  •   ¬    Dereference (-> also accepted)
  •   =    Assignment
  •  ; ,   Statement Separators
  •  { }   Deferred Expression
  •  ( )   Grouping/Function Operator
  •  [ ]   Array Operator
  •  « »   Prefix Section (<< and >> also accepted)

The following examples demonstrate some syntactic paradigms:

/* Set the state of an area, based on the current 3D mode */
Area.Measure.state={Scene.3d.mode=="rotate"?"on":"off"}
/* Use a local attribute for efficiency */
/* Notice that when multiple expressions appear in a row, the last is the value of the expression as a whole */
attr={#dx=(Image.Pop.x-Image.base.x); #dx * #dx}
/* Use a deferred expression as a function, passing argument thru a global */
/* Use the function in an immediate assignment to attr */
square={square.arg * square.arg}
attr=(square.arg=(Image.Pop.x-Image.base.x); square())
/* Use a deferred expression as a function, using the implicit argument #arg */
square={#arg * #arg}
attr=square(Image.Pop.x-Image.base.x)
/* Use a deferred expression as a function, using explicit arguments */
squareSum={#x*#x + #y*#y}
attr=squareSum(^x=Image.Pop.x-Image.base.x;^y=Image.Pop.y-Image.base.y)
/* Compute a value using recursion */
power={#exp==1?#base:(#base*power(^base=#base;^exp=#exp-1))}
Image.Expr.text="5^6=" ~ power(^base=5;^exp=6)
/* Same thing, but using tail recursion instead of a function call */
power={#exp==1?#base:(#exp=#exp-1;#base*power)}
/* Store the name of an object in a string, then get an attribute of that object */
theImage="Image.Main"
theX={@(theImage~.x)}
/* Same thing, but using dereference syntax */
theY={theImage->y}
/* Example of using + to join deferred expressions */
/* This is equivalent to (Meson.log("Hello");Meson.log("World")) */
hello={Meson.log("Hello")}
helloWorld=hello+{Meson.log("World")}
/* Example of using prefix sections */
Foo.Class<<
.bar=1 /* equivalent to Foo.Class.bar=1 */
.baz=2 /* equivalent to Foo.Class.baz=2 */
>>

Built-in Functions

The Meson interpreter defines a handful of built-in functions:

foreach(string elem, array in, deferred do) iterates over the elements in an array:

numbers=[one,two,three]
count={^c=0;foreach(^elem="i";^in=numbers;^do={#c=#c+1;@Meson.log(#c~" = "~#i)})}
/* Results:
meson> count
1.0 = one
2.0 = two
3.0 = three
 */

try(deferred exec, deferred catch) returns the value of the exec clause unless an exception is thrown, in which case the value of the catch clause is returned. When the catch clause is evaluated three additional local attributes are placed in the notebook: exception fully qualified Java class of the exception; message message member of the Java exception; javaException actual Java Exception object.

width="90%"
widthNum={try(^exec={width+0};^catch={
Meson.log("E: {"~#exception~"}");
Meson.log("M: {"~#message~"}");
Meson.log("J: {"~#javaException~"}");
-1})}
/* Results:
meson> widthNum
E: {com.kaon.meson.MesonException}
M: {Error converting "90%" to Number
90%
width
width+0}
J: {com.kaon.meson.MesonException: Error converting "90%" to Number
90%
width
width+0}
-1
 */

Meson.length(array arg) returns the number of elements in the array.

Meson.assert(boolean arg) throws an exception if the passed arg is not equal to "true":

a=5
b={Meson.assert(a==5); a}
c={b*b}
d={a=3}
e=d+c
/* Results: When the last line is exectued:
meson> e=d+c
input:5: e=d+c
Assertion Failed
ÄMeson.assert
_Meson.assert_
call _Meson.assert_ with ((a≈5))
(call _Meson.assert_ with ((a≈5)));@a
_b_
_b_*_b_
_c_
_d_+_c_
e=_d_+_c_
 */

Meson.throw(string arg) throws an exception

Meson.log(string arg) prints a string to the console

Meson.dump(string arg) dumps the blackboard contents to the console. Only blackboard items starting with the passed argument are dumped. Use Meson.dump("") for a full dump.

Meson.getMethod(string class, string method, array args) and Meson.callMethod(java.lang.reflect.Method method, array args) are used together to access Java methods:

/* Access the Java random number generator */
randMethod=Meson.getMethod(^class="java.lang.Math";^method="random";^args=[])
rand={Meson.callMethod(^method=randMethod;^args=[])}
Image.Foo.x={rand * Display.Primary.width}
/* Access the Java atan2 method (this is actually included in the Raster gluon) */
Meson.atan2Method=Meson.getMethod(^class="java.lang.Math"; \
                     ^method="atan2";^args=["double","double"])
Meson.atan2={Meson.callMethod(^method=Meson.atan2Method;^args=#arg)}
someAttr=Meson.atan2([1, 0.5])

Note that for non-static methods, the Java object to operate on should be passed as the first array element to Meson.callMethod but should not be declared in the array passed to Meson.getMethod. Use the built-in attribute null to pass a null pointer as an argument.

Meson.newInstance(string className) creates an instance of a Java class using the no-arguments constructor.

Meson.gluon(string arg) loads a Gluon to add more built-in functions:

/* Put splash.jpg into the applet, then load the Raster functions and show splash2.jpg */
Applet.Primary.image="splash.jpg"
Meson.gluon("com.kaon.meson.raster.RasterGluon")
Display.Primary.file="splash2.jpg"

Each bit of functionality in the Meson system is provided by a Gluon. A Gluon is a set of Java classes which extend the native capabilities of the Meson language. This document describes functions provided by the Raster and Scene Gluons.

Meson.showDocument(string applet, string url, string target) is used to request than an applet show an HTML page (url parameter) in a frame or window (target parameter).

Meson.showStatus(string applet, string status) is used to request than an applet show a message in the the status bar of the browser window.

Meson.jsEval(string javascript) is used to invoke an arbitrary javascript expression in the context of the web page that includes the applet. Note that the MAYSCRIPT attribute must be added to the applet tag on the HTML page if this method is used.

Meson.addContextMenu(string applet, string label) adds a label to the applet context menu. Calling this with the ^label="-" inserts a separator. When the user accesses an item on the context menu, this label value is placed in the applet's menuItem attribute.

/* Add a context menu item to open a web page */
Meson.addContextMenu(^applet="Applet.Primary", ^label="CNN")
Trigger.CNN.test={Applet.Primary.menuItem=="CNN"}
Trigger.CNN.exec={Meson.showDocument(^applet="Applet.Primary", ^url="http://cnn.com", target="_blank")}

Meson.unique generates a unique identifier, useful for creating helper objects.

/* This is a utility function to create a repeating timer */
/* for example, setInterval(^delay=1, ^exec={Meson.log(Meson.clock)}) */
/* It uses Meson.unique to generate a unique name for the timer */
setInterval={#t="Timer."~Meson.unique();#t->delay=#delay;#t->repeat=true;#t->exec=#exec;
                     @(#t->start);#t}

Meson.checkpoint captures the entire state of the blackboard into an attribute

Meson.restore(arg) restores the state of the blackboard to the passed checkpoint

/* Put checkpoint/restore on the context menu */
Meson.addContextMenu(^applet="Applet.Primary", ^label="Checkpoint")
Meson.addContextMenu(^applet="Applet.Primary", ^label="Restore")
ckpt=Meson.checkpoint()
Trigger.Checkpoint.test={Applet.Primary.menuItem=="Checkpoint"}
Trigger.Checkpoint.exec={ckpt=Meson.checkpoint()}
Trigger.Restore.test={Applet.Primary.menuItem=="Restore"}
Trigger.Restore.exec={ckpt=Meson.restore()}

Note that the checkpoint itself is not in the checkpointed blackboard, so restore returns the checkpoint, so that it can be stored into the restored blackboard. If the Restore trigger simply said Trigger.Restore.exec={Meson.restore()} then the attribute ckpt would disappear after restore, since it is restoring a blackboard which had no ckpt attribute on it.

Meson.setInterval(number delay, deferred exec) creates a repeating timer, similar to the JavaScript setInterval function

Meson.setCurrentDataSource(string arg) sets the default data source for images created between now and the next time this is called. This is used by the Data class of the Raster gluon to control defaulting when reading a meson program, and the data used by that program, from the same file. The argument should either be the name of a Data object (Meson.setCurrentDataSource(Data.myProg)) or a URL relative to the current document base (Meson.setCurrentDataSource("http:/data/")). Since this is set automatically by the Data object, it is unlikely an application will ever need to call this function.

Meson.clock holds the time since Meson initialization, in seconds.

Meson.frameStep holds the amount of time since the last tick, in seconds.

Meson.documentBase holds the URL of the applets using this blackboard.

Meson.displayDepth holds the bit depth (16 or 32) of the display on which the applet appears.

Meson.notebookPages holds the number of pages in the notebook (32, by default). An application can increase this limit if it needs to use recursive evaluations which are very deep.

clear black green silver lime gray olive white yellow maroon navy red blue purple teal fuchsia aqua are all predefined with their CSS-equivalent color values (clear has alpha channel of 0x00, all other have alpha of 0xff)

Meson.isMac is true on Mac OS (9 or X) platforms

Meson.language holds the two-letter code of the default user language as reported by the O/S (en, es, zh, etc...)


Object Models

Several classes are included in the the baseline Meson system: Trigger, ChangeTrigger, HairTrigger, Timer, Ticker, Applet, and GenericPeer. Applications create instances of these classes with the notation Class Name.Instance Name.attributes...=value. In other words, an instance of a class is created when one of the attributes of that instance is referenced.

Each class defines a set of attributes which have special meaning in instances of that class. The application may use custom attributes within the scope of an instance as well. The predefined attributes have types which the system expects to find when it parses them. These are:

  • string a string of unicode characters
  • integer a positive, negative, or 0 whole number
  • number an integer or floating point number (when this represents an integral values, such as pixels, floating point values will be rounded to the nearest integer)
  • color an ARGB color value specified as 4 or 8 hex digits, or an RGB color value specified as 3 or 6 hex digits (note that the character # used in HTML colors must be omitted, because # has special meaning)
  • enum a value from the specified list of choices
  • boolean true or false
  • array a set of values (generally, if a value of a different type is used where an array is expected, a one-element array will be created automatically)
  • attribute the name of an attribute or class instance
  • native a native Java object
  • deferred a deferred expression

Assignments which do not start with a class name create attributes in a global variable space. Assignments which start with a # create attributes on the current notebook page. Assignments which start with a ^ create attributes on the next notebook page, which will be the current notebook page of the next function invoked.

The defaults for a class can be overridden using the special object Class which acts as a template during instantiation. For example, to change the default for Images to use 16-bit color depth instead of 32-bit color depth, use Image.Class.depth=16. Note that this will not retroactively change existing instances. To implement retroactive changes to defaults, use deferred assignments: defaultImageDepth=32 and Image.Class.depth={defaultImageDepth}. In this example, images get {defaultImageDepth} as their depth attribute, so that a subsequent assignment defaultImageDepth=16 would flow through to the images.

Applications can create custom classes using the special member extends. For example, HotImage.extends="Image" creates a new class HotImage which extends Image. The application can then assign attributes to HotImage.Class which will become the defaults for HotImage objects. Note that if an attribute matches the name of an attribute in the superclass, then the subclass initializer sets the superclass attribute instead. For example, if HotImage.Class.layer=5, then when the object HotImage.Foo is created, the assignment Image.Foo.layer=5 will occur. In this example, HotImage.Foo.layer becomes a proxy to the underying attribute Image.Foo.layer, so reads and writes of either attribute actually change the one in the base class.

A class can extend multiple base classes. For example, Display.extends=["Applet","Image"]. The order in which base classes are listed is used to resolve conflicts. For example, both Applet and Image define the width attribute. Since Display extends Applet first, the default value of width comes from Applet, and the Display and Image versions of the object both proxy width from Applet:

A.extends=""
A.Class.a=1
A.Class.x=2
B.extends=""
B.Class.b=3
B.Class.x=4
C.extends=["A","B"]
C.Class.c=5
C.Class.a=6
/* Create a C called foo, and make sure it's b is 3 */
Meson.assert(C.foo.b==3)
/* First base class wins */
Meson.assert(C.foo.x==2)
/* Super class wins */
Meson.assert(C.foo.a==6)
Meson.assert(C.foo.x=9;(A.foo.x==9 & B.foo.x==9 & C.foo.x==9))

The $ character is substituted dynamically in class initialization with the name of the object being created. For example, HotImage.Class.x={HotSpot.$.x} implies that the object HotImage.Reset automatically get the attribute assignment HotImage.Reset.x={HotSpot.Reset.x}, allowing automatic linking between objects in the user-defined class HotImage and similarly named hotspots. Similarly, $$ substitutes the fully qualified name including the class and instance parts.

/* Load a localization table */
i18n.OK="Way!"
i18n.Cancel="No Way!"
/* Set up a class to conveniently set up text areas using translations */
I18NImage.extends="Image"
I18NImage.Class.text={i18n.$}
/* Create some images using translation. Note that the .text member is set automatically */
buttonPadding=5
I18NImage.OK.anchor=SE
I18NImage.OK.x={Image.Dialog.width/2 - buttonPadding}
I18NImage.OK.y={Image.Dialog.height - buttonPadding}
I18NImage.Cancel.anchor=SW
I18NImage.Cancel.x={Image.Dialog.width/2 + buttonPadding}
I18NImage.Cancel.y={Image.Dialog.height - buttonPadding}

A class can be given a special member new which is an expression evaluated when an instance is created, just after all the predefined Class attributes are set. This facility can be used to automatically create partner attributes or objects which go along with instances of a class.

/* Define a TipImage to be an image which auto-hides after 2 seconds */
TipImage.extends="I18NImage"
TipImage.Class.time=2
TipImage.new={ Timer.Hide$.delay=$$.time;
                     Timer.Hide$.exec={$$.layer=-1};
                     Trigger.Hide$.test={$$.layer>-1};
                     Trigger.Hide$.exec={Timer.Hide$.start()} }
TipImage.Class.anchor=_S
/* Create a tip image to go with an area called Reset */
TipImage.Reset.x=Area.Reset.x+Area.Reset.width/2
TipImage.Reset.y=Area.Reset.y
/* Define a SlowTipImage to be a TipImage with a longer delay */
SlowTipImage.extends="TipImage"
SlowTipImage.Class.time=5
/* The following line creates a SlowTipImage, but the time setting does not have the desired effect (see the explanation, below). */
SlowTipImage.Foo.time=1

The prior example demonstrates the order in which initialization of objects takes place when subclassing is being used:

  • superclass (recursively) members
  • subclass members
  • superclass (recursively) new
  • subclass new
  • instance members

In the example, the final assignment results in the following assignments (in this order) at run time:

/* I18NImage initializers */
Image.Foo.text={i18n.Foo}
/* TipImage initializers */
TipImage.Foo.time=2
Image.Foo.anchor=_S
/* SlowTipImage initializers */
TipImage.Foo.time=5
/* TipImage new */
Timer.HideFoo.delay=TipImage.Foo.time
/*  (evaluates to Timer.HideFoo.delay=5) */
Timer.HideFoo.tick={Image.Foo.layer=-1}
Trigger.HideFoo.test={Image.Foo.layer>-1}
Trigger.HideFoo.exec={Timer.HideFoo.start()}
/* Assignment statement */
TipImage.Foo.time=1

The final assignment has no effect, because the assignment to Timer.Hide$.delay was an immediate expression. In order for this example to have the intended results, a deferred expression should have been used:

TipImage.new={ Timer.Hide$.delay={TipImage.$.time};
Then the initialization would have been:
Timer.HideFoo.delay={TipImage.Foo.time}

which would respond to subsequent changes to the time member of TipImage objects.

The .new attribute is unique, in that each one in a class hierarchy has an opportunity to run during initialization. Contrast this with other attributes, in which the proxy substitution rules described above cause subclass members to merely replace superclass members at instantiation. Sometime it is desirable for the subclass to override an attribute (particularly one which holds a deferred expression), but keep access to the superclass definition as well. This can be accomplished by accessing the special Class instance member, and using the + operator to join deferred expressions together:

Foo.extends=""
Foo.Class.someMethod={Meson.log("$$ " ~ #arg)}
Bar.extends="Foo"
Bar.Class.access=0
Bar.Class.someMethod=Foo.Class.someMethod+{$$.access=$$.access+1}

Another case where + is used to join expressions is adding functionality to an already-defind method:

Foo.Class.new=Foo.Class.new+{Meson.log("Detected creation of object: $$")}

By convention, class and object names start with capital letters, while attributes start with lowercase letters. This language is case sensitive.


Basic Object Model

Class: Trigger

A trigger runs a deferred expression when the value of a test expression changes to true.

This example sets an attribute in response to a mouse press on the Area called Button

Trigger.Show.test={Area.Button.press}
Trigger.Show.exec={Image.PressedImage.layer=9}

This example sets an attribute in response to a mouse release on the Area called Button

Trigger.Hide.test={!Area.Button.press}
Trigger.Hide.exec={Image.PressedImage.layer=-1}
 test
An expression which should evaluate to true or false
Typedeferred
 exec
This expression is evaluated when the test transitions from false to true
Typedeferred

Class: ChangeTrigger    (Extends Trigger)

A change trigger runs a deferred expression when the value of a test expression changes.

This example increments a counter whenever an area changes state in any way

ChangeTrigger.StateCount.test={Area.Button.state}
ChangeTrigger.StateCount.exec={Area.Button.stateCounter=Area.Button.stateCounter+1}
 test
An expression which is evaluated
Typedeferred
 exec
This expression is evaluated when the test value changes
Typedeferred

Class: HairTrigger    (Extends Trigger)

A hair trigger runs a deferred expression when anything referenced in the test might have changed, regardless of whether the value of the test expression actually changed. Note that writing a value to the blackboard which is identical to the value already there will not fire a HairTrigger.

This example prints a message whenever the layer or alpha is modified

HairTrigger.DebugVis.test={Image.Foo.layer;Image.Foo.state}
HairTrigger.DebugVis.exec={Meson.dump(Image.Foo)}
 test
An expression
Typedeferred
 exec
This expression is evaluated whenever anything in the test might have changed
Typedeferred

Class: Timer

Timers are used to perform actions after a delay, or periodically.

This example displays a popup image for a hotspot when the mouse enters, and uses a timer to hide the hotspot 2.5 seconds after the mouse exits.

Timer.HidePort.exec={Image.portPopup.layer=-1}
Timer.HidePort.delay=2.5
/* Use a trigger to show the popup */
Trigger.SP1.test={HotSpot.Port.hover}
Trigger.SP1.exec={Image.portPopup.layer=9}
/* Use a trigger start the hide timer */
Trigger.SP2.test={!HotSpot.Port.hover}
Trigger.SP2.exec={Timer.hidePort.start()}
 delay
The delay between events generated by this timer (seconds).
Typenumber
Default0
 repeat
Controls whether the timer fires once, or periodically.
Typeboolean
Defaultfalse
 exec
This expression is evaluated when when the timer ticks.
Typedeferred
 start
Reading this attribute starts the timer.
RestrictionsUse function() semantics
 stop
Reading this attribute stops the timer without firing it.
RestrictionsUse function() semantics

Class: Ticker

Tickers are used to evaluate an expression every frame. An order member is present which can be used to control the order of execution of Tickers in the system.

 order
Tickers execute in increasing order, starting at 0. The order of execution for Tickers with the same order attribute is the order in which they were created. Setting the order to a value less than 0, such as -1, will prevent the ticker from ticking.
Typenumber
Default0
 exec
This expression is evaluated when when the Ticker ticks.
Typedeferred

Class: Applet

Applet objects represent applets on web pages. Applet is the only graphical class included in the base object model, in order to keep the initial footprint of Meson very small. Applications will typically use the Applet class only to display a splash logo. After loading the Raster gluon, the application will then use the Display class which extends the Applet class with image manipulation capabilities.

The name of an applet comes from it's mesonName property on the HTML page. If no name is given, the default Applet name is Primary. If the application uses multiple applets on the same Blackboard, names must be assigned explicitly.

 javaApplet
This holds the java.applet.Applet object for the applet.
Typenative
Default""
RestrictionsRead Only
 javaImage
This holds the java.awt.Image object used as the background of the applet. Initially, this is based on the image attribute, but when the Raster gluon is loaded, the Display class replaces it with a new image to reflect the dynamic state of the executing program.
Typenative
Default""
RestrictionsRead Only
 fill
The fill is used at Applet startup to control the background color.
Typecolor
Defaultfff
 image
The image attribute is a URL (relative to the document on which the applet is placed) of an image to show in the Applet while the remainder of the program is loading. Progressive JPG or Interlaced GIF images can be used to get immediate content onto the screen.
Typestring
Default""
 pleaseRepaint
When set to true, the applet will ask Java to initiate a repaint.
Typeboolean
Defaultfalse
 width
Width of the applet. This may change if the applet is in a resizable window, and uses percentage for its width attribute.
Typeinteger
Default0
RestrictionsRead Only
 height
Height of the applet. This may change if the applet is in a resizable window, and uses percentage for its height attribute.
Typeinteger
Default0
RestrictionsRead Only

Keyboard and mouse input is delivered into Applet attributes. In order to ensure Trigger objects fire correctly, the events are queued as they happen, so that if multiple events happen during a frame, the next frame will get all those events in order. For example, if the left mouse button is clicked, the press element will be set to true (causing Triggers watching for press to execute), and then to false (causing release Triggers to execute).

 mouseX
The X position of the mouse, measured from the left side of the applet. Note that browsers typically only deliver mouse coordinates when the applet has focus.
Typeinteger
Default-1
RestrictionsRead Only
 mouseY
The Y position of the mouse, measured from the top of the applet. Note that browsers typically only deliver mouse coordinates when the applet has focus.
Typeinteger
Default-1
RestrictionsRead Only
 press
True when the left mouse button is being pressed in the applet.
Typeboolean
Defaultfalse
RestrictionsRead Only
 shift
True when the Shift key is pressed and the applet has focus.
Typeboolean
Defaultfalse
RestrictionsRead Only
 ctrl
True when the Control key is pressed and the applet has focus.
Typeboolean
Defaultfalse
RestrictionsRead Only
 key
Holds the most recently typed key. Triggers which respond to keystrokes can set this back to "" after firing, to respond to mulitple presses in a row. For special keys, this holds the key name (Enter, Left, Right, Up, Down, Tab, Delete, Back). For all other keys, it holds the unicode letter.
Typestring
Default""

Class: GenericPeer

Generic Peer is extended by other objects which bear a very close relationship to objects implemented by Gluons in Java code. Their primary purpose is to provide a simple, consistent way for Meson programs to invoke methods on these native objects. Their use is entirely optional, as they merely wrap calls to built-in functions like Meson.getMethod and Meson.callMethod.

 javaClass
Specifies the fully-qualified Java class name of the native peer class.
Typestring
 javaObject
Holds the native object which is created in reponse to this object being referenced in the Meson program. Note that a no-arguments constructor is used by default, so a native class using this facility should use separate initializers (similar to the design pattern used in Applets and Servlets).
Typenative
 callMethod
Invokes a method on the native object. Arguments are as follows:
  • method: native method name as a string
  • types: array of argument types. For primitive types, use strings like float or long. For object types use the fully-qualified class name, such as java.lang.String. For array types, use the Java method signature conventions (for example, "[[F" for a two-dimensional array of float, or "[Ljava.lang.String;" for a one-dimensional array of strings.
  • args: array of arguments, which must correspond to the values passed in the types parameter. As explained above, use null for null parameters.
Typedeferred
 getMethod
Looks up a method of the native object. When a method is going to be called very frequently, it is a good idea to look it up once in advance and cache it, rather than looking it up over and over with callMethod. Arguments are as follows:
  • method: native method name as a string
  • types: array of argument types. For primitive types, use strings like float or long. For object types use the fully-qualified class name, such as java.lang.String. For array types, use the Java method signature conventions (for example, "[[F" for a two-dimensional array of float, or "[Ljava.lang.String;" for a one-dimensional array of strings.
Typedeferred

Raster Gluon

The Raster gluon adds several classes to Meson: Anim, Data, Image, Display, Area, and Style. It also adds several built-in functions.

Raster Built-in Functions

Meson.sin(number arg), Meson.cos(number arg), Meson.tan(number arg), Meson.atan(number arg), Meson.atan2(array arg), Meson.round(number arg), Meson.ceil(number arg), Meson.floor(number arg), Meson.ln(number arg) (natural log), Meson.exp(number arg) (natural exponent) provide access to the equivalent methods in java.lang.Math. For convenience, the attributes Meson.degToRad and Meson.radToDeg are also defined.

/* Create a ticker which updates the angle at frame rate */
Ticker.Dot.exec={currentAngle=currentAngle+Meson.frameStep*rateDegPerSec}
rateDegPerSec=360/60
/* Set the x,y location of an image to move around a circle */
Image.Dot.x={dotRadius * Meson.cos(currentAngle*Meson.degToRad)}
Image.Dot.y={dotRadius * Meson.sin(currentAngle*Meson.degToRad)}
/* Derive radius value from image parent width */
dotRadius={(Image.Dot.parent~.width)/2-Image.Dot.width}

Meson.formatFloat(number value, string format) returns the number formatted according to the user's regional numeric formatting conventions, as specified by the OS. The format specifier is of the form integerDigits[.decimalDigits]. That is, the if no decimal part is given, the value will be shown as an integer.

Raster Object Model

Class: Anim

Animation objects are used to set attributes to values over time. The animation uses a combination of linear interpolation and exponential smoothing, to allow values to change in a variety of ways.

This example shows how to use an Anim object to make a toolbar slide in when the mouse enters the area (like a desktop taskbar with auto-hide).

/* Define a rectangle on the toolbar to detect mouse hover. */
/* Default dimensions of the area match the Image size. */
Area.ShowToolbar.image="Image.Toolbar"
/* Create an animation to control the y coordinate of the image toolbar, */
/* changing it at a maximum rate of 10 pixels per second. */
Anim.ToolY.attr=["Image.Toolbar.y"]
Anim.ToolY.rate=10
Anim.ToolY.highPriority=true
/* Have the goal be 5 pixels, or toolbar height pixels, above the display bottom. */
Anim.ToolY.goal=[{Display.Primary.height-(Area.ShowToolbar.hover?Image.Toolbar.height:5)}]
 attr
The attributes which are controlled by this animation.
Typearray of attribute
 goal
The value to be assigned to each attr over time.
Typearray of number
 rate
The maximum rate (per second) at which to change the value. If this value is <0, the rate is not limited.
Typenumber
Default-1
 smooth
The exponential smoothing constant to apply when changing the value. A value of 0 changes instantly, whereas a value of 1 will never change. This parameter controls the amount of goal value to blend with the current value each time step, based on the equation weight=smoothtimeStepSeconds. Typical values are around 0.05.
Typenumber
Default0
 threshold
When an attribute value is this close to the goal (|goal-attribute|≤threshold) the attribute will be set to exactly the goal.
Typenumber
Default0.001
 enabled
The animation only operates when this attribute is true.
Typeboolean
Defaulttrue
 autoDisable
If this is set to true, the animation will set its own enabled attribute to false when the attribute value reaches the goal. This is used for "one shot" animations.
Typeboolean
Defaultfalse
 modulus
If modulus is non-zero, then the attribute will skip up or down an appropriate amount to never be more than half the modulus away from the goal. For example, when the attribute is an angular measure, a modulus of 360 will lead to the attribute following the shortest path around the circle to the goal.
Typenumber
Default0
 highPriority
A high-priority animation sets an internal flag in the applet context when it is running (i.e., when the attribute value is not the goal, and the animation is enabled). This flag is consulted by various low-priority tasks, such as 3D Scene anti-aliasing, to control sharing of CPU cycles. In a nutshell, a high-priority animation will be visually smoother than a normal priority one on a heavily loaded system. For animations with moving rasters, such as the toolbar animation in the above example, this will give a better appearance. For animations of alpha parameters, it is generally not necessary, as the user cannot see the subtle frame rate differences involved.
Typeboolean
Defaultfalse

Class: Data

Data objects represent a bundle of resources used by a Meson application. The data file referenced by this object is in the ZIP (JAR) format, and may contain an arbitrary mix of .txt files containing Meson programs, .jpg and .gif files used by those programs, 3D scene data including wavelet .kwl files and compressed binary data, and other ZIPs or JARs. The best compression is achieved by building a compressed JAR containing a single uncompressed JAR with the files. The resulting compression is much better than a simple compressed JAR.

 url
URL (relative to the page the applet is on) of the JAR file containing the data
Typestring
 state
State of the data file. Data starts in the _NEW state, immediate transitions to the _OPEN state where data is read, and transitions to the _CLOSED state when reading is complete. It may transition to the _FAILED state if any error occurs.
Typeenum 
_NEW, _OPEN, _CLOSED, _FAILED
RestrictionsRead Only
 errorMessage
When the state is _FAILED, this holds the error message
Typestring
RestrictionsRead Only
 contentLength
Contains the content length, as reported by the server. Note that this may be -1 if the server does not know the content length.
Typenumber
RestrictionsRead Only
 bytesRead
Contains a count of bytes read so far.
Typenumber
RestrictionsRead Only
 stall
Set this to true to temporarily stall reading the data.
Typeboolean
Defaultfalse
 fileList
Contains the list of files read from this data source so far.
Typearray
 imagePercentLoaded
If the data source contains wavelet-encoded images, this holds the percentage of image data which has been decoded so far.
Typenumber
Default100
 reset
When set to true, the file read will stop, and the state will transition back to _NEW. This will cause the file to immediately start loading again, unless you first set the url attribute to "".
Typeboolean
 parse
Indicates that the URL points to Meson code or a ZIP/JAR archive which should be parsed.
Typeboolean
Defaulttrue
 unparsed
When the parse attribute is false, the data pointed at by the URL will be read into a string and placed into this attribute.
Typestring

Class: Image

An image is a rectangular raster of pixels. There are three ways to create an image: from a file, by rendering text, or simply allocating a blank area.

 file
Create the image from the specified file. The file may be a GIF or JPG format image (PNG format is not supported in all browser environments, so it should be avoided). GIF files may use animation, although this should be avoided where possible for performance reasons (using a multi-state image and flipping thru the states will yield faster update rates). In cases where a continuous alpha channel is required (in contrast to the On/Off alpha of GIF transparency), two images may be given, separated by an @ symbol. The first file gives the color information, and the second gives alpha information. For example: Image.Toolbar.file="toolbar.jpg@toolbarMask.gif". The blue channel of the pixels in the GIF images are used as the alpha channel (in practice, a gray-scale GIF can be used, since the red and green channels are ignored). The color pixels may come from either a JPG or GIF format file, however, if GIF is used, it must not include transparency (specify transparency in the alpha channel file instead). Animation is not permitted in an alpha channel GIF.
Typestring
Example"top.jpg"
 text
Create the image by rendering the specified text. The background of the text comes from the buffer attribute. If no buffer color is given, the text will be on a transparent background.
Typestring
Example"Open Lid"
 tabDefault
Specifies the default spacing, in pixels, for tab stops (used when rendering text containing the \t character).
Typenumber
Default50
 tabStops
Specifies explicit tab stop locations, in pixels. Note that, as with word processing programs, the default tab spacing is used to the right of the last explicit tab stop.
Typearray
Default[]
 wrapWidth
Text can be auto-wrapped while being rendered, to ensure the resulting image does not exceed a certain width. This attribute controls that process. Note that spaces, tabs, language-specific rules (such as Japanese, where breaks between glyphs are allowed except in a few cases), and style-changes can result in breaks (the non-breaking-space unicode character \u00A0 can be used to insert a non-breaking space between words). If a single piece of unbreakable text is longer than will fit in the wrapWidth, then text wrapping will not be performed on that text. In this case, the width member could end up larger than wrapWidth, if set implicitly. If you assign a particular value to width then text which extends beyond this will be clipped.
Typenumber
Default0
 language
When using the wrapWidth attribute, this selects the language rules to use when determining how to break long lines at word boundaries.
Typestring
Default{Meson.language}
 country
When using the wrapWidth attribute, this selects the country-specific language rules to use when determining how to break long lines at word boundaries.
Typestring
Default""
 buffer
Create a buffer with the specified fill color
Typecolor
Example"FF336699"
 softEdge
Used together with a buffer, this softens the alpha channel all the way around the rectangular image by the specified number of pixels on each side.
Typenumber
Default0

Images can represented internally using 32-bit ARGB, or 16-bit YCrCb representation. In the 32-bit setting, alpha and the 3 color channels are represented by 8 bits each. In the 16-bit setting, each adjacent pair of pixels share a chominance value, and each has its own luminance. Both modes support a full 256 gray levels, but only the 32 bit mode supports alpha channels and the complete range of colors. For textures compressed with JPEG compression, there is nothing to be gained using 32-bit representation, because JPEG forces each pair of adjacent pixels to have the same chrominance.

 depth
Set the color depth to be used to represent this image
Typeenum 16, 32
Default32

Text images will always use font smoothing when the underlying Java implementation supports it. When it does not, font smoothing can be emulated to varying degrees of precision. The higher the degree, the longer it takes to render the text initially. Once the text is set, however, the speed of rendering is not impacted by smoothing.

 fontSmooth
Font anti-aliasing control. A value of 0 does no anti-aliasing, 1 does a little anti-aliasing, while value of 2 does maximum anti-aliasing. Note that text which changes frequently, such as the measuring distance, should use a value of 0 for best performance. This only controls the default anti-aliasing for an image. Individual text Styles can specify a different level of text anti-aliasing, which will take precedence over this setting.
Typeenum 0, 1, 2
Default2

An image can have multiple states, which are stacked vertically, with the first state on top, the next one below it, and so on. The version of an image which appears on the screen is the first state overlaid with other states as specified by Area objects within the image.

 states
Names the states represented within the image.
Typearray
Default["default"]

The image is placed at an X,Y coordinate relative to its parent image (such as the display). The coordinates specify the location that the anchor pixel should be located on that image. The 0,0 point on the parent is the northwest corner of the parent.

 parent
The image on which this image is rendered.
Typeattribute
Default"Display.Primary"
 x
The X position of the image anchor, relative to its parent.
Typenumber
Default0
 y
The Y position of the image anchor, relative to its parent.
Typenumber
Default0
 layer
The stacking order value of this image. 0 is on the bottom. Images with a layer value < 0 are not displayed.
Typeinteger
Default0
 alpha
The alpha blending value of this image. 0.0 is transparent; 1.0 is opaque.
Typenumber
Default1.0
 anchor
The position of the anchor expressed as a compass direction, or _C for center. For example, if the image is 150x24, anchor=_S would place the anchor at 75,24.
Typeenum 
_N, _NW, _W, _SW, _S, _SE, _E, _NE, _C
Default_NW
 width
The width of the image.
Typenumber
 height
The displayed height of the image. Note that if the number of states is greater than 0, then the height reported in this attribute will be a fraction of the actual overall height of the image.
Typenumber
 tile
For Images which use file attribute, and also specify an explicit width and/or height, the file contents will be placed int the upper left corner by default. If the tile is set to true, however, the file will instead be tiled across the image area (like the background image of an HTML page).
Typeboolean
Defaultfalse
 draw
Provides a hook to a method that will draw the contents of the image whenever it is required. This will be invoked immediately after the data buffer is cleared. A pointer to the underlying Java MesonRaster class object is passed as the argument.
Typedeferred

Images can be scaled independently in X and Y, and rotated through an arbitrary angle. All transforms apply about the anchor of the image. Note that this transform is done at rendering-time, and is currently not cached in any way, so it is best not to use large scaled or rotated images over 3D windows or other screen areas that refresh quite frequently. Children of the image inherit scale and rotation, and are given locations relative to the un-transformed parent.

 scaleX
Width scaling factor. Use a number less than 1 to shrink the image, or a number larger than 1 to stretch it.
Typenumber
Default1
 scaleY
Height scaling factor. Use a number less than 1 to shrink the image, or a number larger than 1 to stretch it.
Typenumber
Default1
 angle
Rotation angle, in degrees. Note that since Y increases as you move down the screen, this rotates the opposite direction from the geometry you learned in high school: angle=90 means turn the image 1/4 turn clockwise, for example.
Typenumber
Default0
 oversample
When rendering with scaleX ≠ 1, scaleY ≠ 1, or angle ≠ 0, this controls oversampling. Oversampling is an anti-aliasing technique in which an area of the original image is averaged together to determine what color to render in each pixel of the destination image. As a general rule, oversampling will improve the apperance of images that are scaled down by a factor of 2 or more in either dimension. For large images, where render time is dominated by the time it takes to read data from memory, oversampling will slow rendering of images by a factor of about 3.
Typeboolean
Defaultfalse
 bilinear
When rendering with scaleX ≠ 1, scaleY ≠ 1, or angle ≠ 0, this controls bi-linear filtering. Bi-linear filtering is an anti-aliasing technique in which colors in the original image are interpolated to determine what color to render in each pixel of the destination image. As a general rule, bi-linear filtering will improve the apperance of images that are scaled by a factor larger than 0.5 in either dimension (that is, scaled down by a factor less than 2, or scaled up by any factor), or when the image is rotated. For large images, where render time is dominated by the time it takes to read data from memory, bi-linear filtering will slow rendering of images by a factor of about 4.
Typeboolean
Defaultfalse

Note that oversample and bilinear can be used together, for example, if the image is both scaled down and rotated, but the delays compound, so using both together may be up to 12 times slower than rendering with neither filter enabled. On the other hand, if the image is scale down considerably, it will not take that long to render anyway, so the extra processing may not be noticeable.

By default, images monitor mouse motion over their surface, and respond to these actions. This can be switched on and off at the image level, or for individual areas within the image. Disabling mouse input for an image implicitly disables it for all children images as well, however, it does not change the enabled attribute of those images.

 enabled
Controls whether the image responds to mouse actions such as motion and clicking.
Typeboolean
Defaulttrue
 cursor
Cursor to display when the mouse is over this image (when this image is enabled). If "" is specified, the parent determines the cursor. This setting may be overridden by individual areas on the image. If a digit or letter is given, that is used to access any built-in cursor provided by the Java environment.
Typeenum 
"", _ARROW, _HAND, _CROSSHAIR, _MOVE, 0,1,2,...9,A,B,...
Default

Each image automatically creates a Trigger object to repaint when one of several attributes changes. In rare circumstances, an application may need to request a repaint of this to reflect a change in an attribute other than the default ones.

 repaint
Read this attribute to trigger a repaint of the applet
Typedeferred
RestrictionsUse function() semantics

Most attributes of the image are monitored to determine when the image needs to be rebuilt (text re-rendered, or image file re-decoded). However, there are some cases where the application will need to tell the image that regeneration is needed: making changes to text Style objects used by text rendered into the image is the most common case. The rebuild flag can be used in these cases.

 rebuild
Set this to true to force a re-build of the image.
Typeboolean
Defaultfalse

Each image has several additional attributes which derive their values from other attributes. If scale or rotation transforms are being used, these transforms are inverted in the calculation of these derived attributes. For example, mouseX is the location of the mouse X coordinate on the original image, not the location of the mouse on the scaled or rotated image.

 absX
The X location of the northwest corner of the image relative to the topmost parent's northwest corner.
Typenumber
RestrictionsRead Only
 absY
The Y location of the northwest corner of the image relative to the topmost parent's northwest corner.
Typenumber
RestrictionsRead Only
 absAlpha
The net alpha value of this image, taking into account the alpha values of all its ancestors.
Typenumber
RestrictionsRead Only
 absEnabled
The net enabled state of this image, taking into account the enabled state of all its ancestors.
Typeboolean
RestrictionsRead Only
 absVisible
The net visibility state of this image, taking into account the layer and alpha values of all its ancestors.
Typeboolean
RestrictionsRead Only
 mouseX
The X location of the mouse, relative to the northwest corner of this image
Typenumber
RestrictionsRead Only
 mouseY
The Y location of the mouse, relative to the northwest corner of this image
Typenumber
RestrictionsRead Only
 display
The display on which this image ultimately appears
Typeattribute
RestrictionsRead Only
 anchorX
The X location of the image anchor, relative to the northwest corner of this image (this is derived from anchor by default, but can be set to an explicit value, if needed).
Typenumber
 anchorY
The Y location of the image anchor, relative to the northwest corner of this image (this is derived from anchor by default, but can be set to an explicit value, if needed).
Typenumber
 children
List of all Images with this image as their parent
Typearray
RestrictionsRead Only
 areas
List of all Areas with this image as their image
Typearray
RestrictionsRead Only
 javaRaster
The native representation of this raster inside the Raster gluon Java code
Typenative
RestrictionsRead Only
 displayBasis
This member is true when the image has the same coordinate basis as the display. That is, it is true when scaleX==1, scaleY==1, and angle==0. This is used to shortcut the math used in mouse coordinate calculation, and to determine which algorithm to use to transfer pixels from the image to the display.
Typeboolean

The transform members scaleX, scaleY, and angle are used to compute transformation matrices for the image. These matrices are stored in image attributes via complex expressions which can be overridden to achieve 2D transform effects such as shearing. Each 3x2 affine transform matrix is stored in 6 members:

| m00 m01 m02 |    | w00 w01 w02 |    | i00 i01 i02 |
| m10 m11 m12 |    | w10 w11 w12 |    | i10 i11 i12 |

The m??, w??, and i?? attributes store the local-to-parent transform, local-to-world transform, and world-to-local transform of this image, respectively. The m members are derived from scaleX, scaleY, angle, x, y, anchorX, and anchorY members. The w members are derived from the m members of this image, and the w members of this image's parent image. The i members are derived exclusively from the w members. So, for example, if you install a shear matrix into the m members, the w and i members will automatically reflect this change. However, be careful that whatever matrix you install in m is invertable (that is, it has a non-zero determinant) since failure to do so will lead to extremely strange results. One last caution: even if you set the m matrix explicitly, you should still set the scaleX and scaleY members, as they are used in the computation of the barycentric mapping functions of source-to-destination pixels in the case of oversampling and bilinear filtering. (If that last sentence was meaningless to you, you probably should not be changing the matrix members directly!)

Class: Display    (Extends ["Applet", "Image"])

Display combines the base class Applet with the raster class Image. When the Raster gluon initializes it promotes all Applet objects into Display objects.

 buffer
Controls the background color of the display. Note that alpha values other than FF are not permitted, due to browser limitations.
Typecolor
Default{Applet.$.fill}
 file
Controls the background beneath all other images. Note that using a transparent GIF or an alpha channel image will yield inconsistent and unpredictable results.
Typestring
Default{Applet.$.image}
 dither
When the operating system reports that the user is operating in "high-color" (16 bit color) mode (Meson.displayDepth=="16"), the true color image is dithered by Meson, using an error diffusion algorithm. This removes color bands, resulting in a much better looking image.
Typeboolean
Defaulttrue
 invokeNextPaint
Enqueue an expression to be evaluated just before the next paint pass. This can be used to guarantee execution of a native built-in method in the AWT event thread.
Typedeferred

Class: Area

An image can have a variety of area objects within it, which define rectangular regions which can respond to mouse actions and show multiple states.

Area.RotateMode.image="Image.Toolbar"
Area.RotateMode.x=12
Area.RotateMode.y=34
Area.RotateMode.width=5
Area.RotateMode.height=6
Image.RotateTip.layer={Area.RotateMode.hover==true?9:-1}
Area.RotateMode.state={Scene.3d.mode=="rotate"?
                     "on":(Area.RotateMode.hover==true?"hover":"off")}
Trigger.RotateMode.test={Area.RotateMode.press}
Trigger.RotateMode.exec={Scene.3d.mode="rotate"}

This example creates an area on the Image Toolbar called RotateMode covering the specified rectangular area. It then sets up rules to show a tool tip and light up the "hover" state of the image in this area when the mouse hovers over the area, and hide the tool tip and revert the state when the mouse leaves the area. It shows the "on" state when the scene is in Rotate mode, regardless of the hover. The last assignments create a Trigger which sets the attribute mode in the primary 3D scene, to set the desired major mode of the interface to rotate when the area is pressed with the mouse.

 image
The image on which this area resides.
Typeattribute
DefaultDisplay.Primary
 x
The pixel location of the left side of the area.
Typenumber
Default0
 y
The pixel location of the top side of the area.
Typenumber
Default0
 width
The width of the area, in pixels.
Typenumber
Defaultimage->width
 height
The height of the area, in pixels.
Typenumber
Defaultimage->height
 enabled
Controls whether the area responds to mouse actions such as motion and clicking.
Typeboolean
Defaulttrue
 state
In a multi-state image, this controls which state is displayed in this area.
Typestring
Default"default"
 cursor
Cursor to display when the mouse is hovering over this area
Typeenum 
_ARROW, _HAND, _CROSSHAIR, _MOVE, 0,1,...9,A,B,...
 mouseHover
Indicates that the mouse is hovering over the area. In general, applications should not reference this attribute, but should use hover instead.
Typeboolean
RestrictionsRead Only
 hover
Indicates that the mouse is hovering over the area. Note that this is actually an expression, which, by default, exactly matches the value of mouseHover. However, this expression can be overridden, for example to cause two areas to work as one (this is done automatically, for example, when rendering text with embedded areas that wrap across lines). Note that the pixel under the mouse must be drawn by this area's image in order to transition to hover=true (see boxPick below). If the mouse button is pressed on the area, no other area will be considered to have hover until the mouse is released. That is, "grab" is implicit.
Typeboolean
 press
Indicates that the left mouse button is pressed in the area.
Typeboolean
RestrictionsRead Only
 boxPick
Ordinarily, an area will only be considered for mouse hover if it's image drew the pixel under the mouse cursor. To have the area be considered regardless of whether the individual pixel was drawn, set boxPick to true. Note that the image itself still must be drawn, so this is only relevant with images that have an alpha channel (such as text).
Typeboolean
Defaultfalse
 defaultPick
Default pick behavior is similar to boxPick, except that the pick will happen if either the pick was on a pixel drawn by the image, or if it was on the display behind the image inside the area boundary. That is, other images can block reception of the hover.
Typeboolean
Defaultfalse

When areas are generated automatically during text rendering, the following attributes will also be set:

 content
The un-styled text content which was rendered into this area. Note that if multiple area sections have the same ID, this is the concatenation of all those bits of content.
Typestring
 init
This attribute is read, using function semantics, when the text in this area is first rendered into the image, in cases where the id is followed by (). See the hypertext example in the section on the area attribute of the Style class.
Typedeferred

Class: Style

Styles are used to control the appearance of images created from text. Where possible, attribute names mirror those used in CSS. There is a predefined style called Default which is used in the absence of style controls in the text. When rendering text, styles are called out by %style{text to style}. A span of text can be identified by adding :id after the style name, and when the style defines an area, initialization arguments can follow the id, as follows: %style:id(args){text to style} Styles can be nested, where the inner style overrides one or more parameters of the outer style. ID's are concatenated in this case. When placed on an image with multiple states, the character # can be used to indicate which state is being rendered. For example, if an image has states ["plain","hover"] then the text "%Hot_#{Click Here}" would be rendered with style Hot_plain in the plain version of the image, and style Hot_hover in the hover version. The # character can also be used in the ID - the same substitution rule applies.

This example shows how the default style can be set, along with one custom style.

Style.Default.fontFamily=["Arial", "Helvetica", "SansSerif"]
Style.Default.fontSize=12
Style.Default.textAlign=_CENTER
Style.Bold.fontWeight=_BOLD
Image.message.text="Powered By\n%Bold{www.strata.com}"
 fontFamily
The font family to use for text. As with CSS, a list of fallback fonts can be specified. The last fallback should be one of SansSerif, Serif, or Monospaced. (Note that on some operating systems, case matters.) The special value [] means this attribute is not set.
Typearray
Default[]
 fontSize
The font size, in points. (Unlike CSS, font sizes cannot be specified in other units, such as em or px). The value -1 means this attribute is not set.
Typenumber
Default-1
 fontWeight
The font weight. The value . means this attribute is not set.
Typeenum 
_PLAIN, _BOLD, .
Default.
 fontStyle
The font style. The value . means this attribute is not set.
Typeenum 
_PLAIN, _ITALIC, .
Default.
 fontSmooth
Font smoothing. The value -1 means this attribute is not set. Typically, font smoothing is specified by the Image into which the text is rendered. However, this attribute allows overriding of the font smoothing for a given style. For example, when rendering a large amount of text, Image.MyText.fontSmooth=0 might be used to speed up rendering, but Style.Bold.fontSmooth=2 could be used to enable font smoothing for bold spans.
Typeenum 
-1, 0, 1, 2
Default-1
 textDecoration
The text decoration. The value . means this attribute is not set.
Typeenum 
_NONE, _UNDERLINE, .
Default.
 color
The text color. The value "" means this attribute is not set.
Typecolor
Default""
 dropShadow
The color of the text drop shadow. Use a color with 0 alpha (such as 0000) to skip drawing the drop shadow. The value "" means this attribute is not set.
Typecolor
Default""
 shadowOffset
The distance to the drop shadow, if any. The value -1 means this attribute is not set.
Typenumber
Default-1
 offsetX
The sub-pixel X offset used to render the text. Use this together with the fontSmooth attribute of the image to achieve subtle text effects. The value -1 means this attribute is not set.
Typenumber
Default-1
Example-0.5
 offsetY
The sub-pixel Y offset used to render the text. Use this together with the fontSmooth attribute of the image to achieve subtle text effects. The value -1 means this attribute is not set.
Typenumber
Default-1
Example0.5

The following attributes may impact more than just the text area being rendered. For example, a style midway through a line with a larger lineSpacing will increase the spacing for the entire line. When the styles used in a text image differ in global settings, such as margin, the value used will be derived from a certain character in the text, which is indicated below.

 textAlign
The text alignment for multi-line text, and for text created with explicit image width or wrapWidth. The value . means this attribute is not set. The alignment of all text on a line should be consistent, to avoid strange text-overlap effects.
Typeenum 
_LEFT, _CENTER, _RIGHT, .
Default.
 lineSpacing
Extra spacing (in pixels) to use between lines of text. Use positive numbers to increase space between lines, or negative numbers to bring lines closer together. The value -999 means this attribute is not set. The line spacing for any given line is the maximum of all styles used on that line.
Typenumber
Default.
 margin
The number of pixels of space with which to inset the text inside the image. The value -1 means this attribute is not set.
Typenumber
Default-1
 marginLeft
The number of pixels of space with which to inset the text inside the image on the left side. This takes precedence over the margin attribute. The value -1 means this attribute is not set. The style of the first character on a line controls the left margin for that line.
Typenumber
Default-1
 marginRight
The number of pixels of space with which to inset the text inside the image on the right side. This takes precedence over the margin attribute. The value -1 means this attribute is not set. The style of the last character on a line controls the right margin for that line.
Typenumber
Default-1
 marginBottom
The number of pixels of space with which to inset the text inside the image on the bottom side. This takes precedence over the margin attribute. The value -1 means this attribute is not set. The style of the last character on all lines controls the bottom margin for the image (the largest bottom-margin on those characters wins).
Typenumber
Default-1
 marginTop
The number of pixels of space with which to inset the text inside the image on the top side. This takes precedence over the margin attribute. The value -1 means this attribute is not set. The style of the last character of the first line controls the top margin.
Typenumber
Default-1
 borderThickness
The thickness of the border, in pixels. The value -1 means this attribute is not set. The border properties (thickness, colors) of the first character rendered control the border.
Typenumber
Default-1
 borderColor
The border color. The value "" means this attribute is not set.
Typecolor
Default""
 borderColorLeft
The border color on the left side. This takes precedence over the borderColor attribute. The value "" means this attribute is not set.
Typecolor
Default""
 borderColorRight
The border color on the right side. This takes precedence over the borderColor attribute. The value "" means this attribute is not set.
Typecolor
Default""
 borderColorBottom
The border color on the bottom side. This takes precedence over the borderColor attribute. The value "" means this attribute is not set.
Typecolor
Default""
 borderColorTop
The border color on the top side. This takes precedence over the borderColor attribute. The value "" means this attribute is not set.
Typecolor
Default""

The following style attributes allow styles to generate more sophisticated text-processing results, such as inserting bullets for a list, or making hot links in the midst of the text. Examples are included to more clearly demonstrate how these features are intended to be used.

 contentPre
Additional content which should be prepended when a span starts using this style. Note that this may itself contain style directives.
Typestring
Default""
 contentPost
Additional content which should be appended when a span stops using this style. Note that this may itself contain style directives.
Typestring
Default""

This example shows how to use contentPre, contentPost, margins and tabs, to produce bullet points with a hanging indent.

Style.BulletMark<<
.marginLeft=0
.color=red
.lineSpacing=10
>>
Style.Bullet<<
.marginLeft=15
.color=blue
.contentPre="%BulletMark{\u2022}\t"
.contentPost="\n"
>>
Image.BulletList<<
.tabStops=[15]
.wrapWidth=100
.text="%Bullet{The first bullet point is the most important}\
%Bullet{The second bullet point is also fairly important}\
%Bullet{The third bullet point is not at all important}"
>>
 area
When a style includes the area attribute, an instance of the indicated class (which should be Area or a class derived from Area) will be created for any identified span which appears within that style. A span is identified only if it, or an encapsulating span, uses the :id syntax when the style is specified. If the span includes arguments, in the form (args) then those will be passed to the area init method. If multiple spans occur within the style (as could happen if the style used other style within it, or if word wrapping is enabled), then Area class objects are created for all the subsequent spans, and the members of these area are rigged to work together with the main area class object.
Typestring
Default""

This example shows how to use styles to create hyperlinks within a text area.

Link.extends="Area"
Link.Class<<
.url=""
.target="_blank"
.init={$$.url=#arg}
.state={$$.hover?"h":"p"}
.boxPick=true
.new={
Trigger.$_h.test={$$.hover};
Trigger.$_h.exec={Meson.showStatus(^applet="Applet.Primary",^status=$$.url)};
Trigger.$_p.test={$$.press};
Trigger.$_p.exec={Meson.showDocument(^applet="Applet.Primary"
                     ^url=$$.url,^target=$$.target)};
}
>>
Style.Link<<
_p.area="Link"
_p.textDecoration=_UNDERLINE
_p.color=blue
_h.textDecoration=_UNDERLINE
_h.color=red
>>
Image.Text<<
.states=["p","h"]
.wrapWidth=100
.text="This is some text containing \
%Link_#:Google(http://www.google.com'){a link that will wrap} \
to a site called %Link_#:Google{google} that you can use \
to search. Another %Link_#:Yahoo('http://www.yahoo.com'){site \
%Bold{that you}} can use is %Link_#:Yahoo{Yahoo}."
>>

The Link class extends area, and includes an init method, which receives the argument. When a Link is created, it creates two triggers: one to show the URL on the status line when the mouse hovers, and the other to open the link when the mouse clicks. Next, two styles are created: Link_p for plain links, and Link_h for hovering links. Only the first has an area associated with it, using the Link class which was just defined. When the Link_p style is used, a corresponding Link object will be created. Finally, an image is created which uses these styles. Note that only the first link encountered with a given ID needs to include initializer arguments. Subsequent spans with the same ID (either implicitly created because of word wrap, or explicitly created as in this example) have simple Area objects created which are rigged to mirror/control the Link object.

The following table shows the default style values.

Style.Default.fontFamily=[SansSerif]
Style.Default.fontSize=12
Style.Default.fontWeight=_PLAIN
Style.Default.fontStyle=_PLAIN
Style.Default.fontSmooth=-1
Style.Default.textAlign=_LEFT
Style.Default.textDecoration=_NONE
Style.Default.lineSpacing=0
Style.Default.margin=2
Style.Default.color=black
Style.Default.dropShadow=""
Style.Default.shadowOffset=1
Style.Default.borderThickness=0
Style.Default.borderColor=black
Style.Default.offsetX=0
Style.Default.offsetY=0
Style.Default.contentPre=""
Style.Default.contentPost=""
Style.Default.area=""

Scene Gluon

Scene Built-in Functions

Scene.setObjectWriteZAlpha(string scene, string object, boolean write) controls whether the indicated object writes into the Z-buffer when drawing with alpha. Ordinarily, this is true, but it might not be desired, for example, to allow picking through semi-transparent windows.

Scene.measure(string scene, number x0, number y0, number x1, number y1) returns the distance in native units between the two pixel locations.

Scene.pick(string scene, number x, number y) performs a pick operation under the indicated pixel location. If no pixel was drawn at that location, the return value is false. If a pixel was drawn, multiple return values can be fetched from the notebook: ^object object ID, ^material material ID, ^x ^y ^z world coordinates location, ^lx ^ly ^lz local coordinates location.

Trigger.Pick.test={Area.3d.press}
Trigger.Pick.exec={Scene.pick(^scene="Scene.3d",^x=Scene.3d.mouseX,^y=Scene.3d.mouseY)?Meson.log("Picked obj:"~^object~" mat:"~^material);}

Scene Object Model

Class: Scene    (Extends Image)

A Scene is a rendered 3D environment. By default, the view of a scene can be manipulated using certain mouse gestures. However, the manner by which mouse gestures translate into view changes is entirely programmed in the Meson language, and can therefore be overriden to use other interface approaches. The most direct way to override the default behavior is to set the mode attribute of the scene to "" which will disable the Anim object which updates the view. Then add new controller objects to manipulate the Scene's view as needed.

Scene adds the following attributes to the base Image class:

 runtime
Indicates the internal runtime representation of a 3D world which is rendered in this scene. The runtime is created using a set of classes documented at the end of this section, and is typically generated automatically by software.
Typenative
 loaded
Indicates whether all the images used by textures have been loaded sufficiently to be displayed. For streaming textures, more resolution will continue to load as data is received.
Typeboolean
 unloadRuntimes
Indicates that if the runtime associated with the scene is changed, the textures used by the previous runtime should be cleared from memory. Restoring the previous runtime will therefore require re-decoding of all texture information, so this mode sacrifices performance for memory conservation. Disabling unloadRuntimes should only be done after a careful examination of memory requirements of the application.
Typeboolean
Defaulttrue
 mode
The current major mode of the user interface (the thing that happens when the mouse is dragged on the 3D area).
Typeenum 
rotate, move, measure
Defaultrotate
 inch
The scale to multiply native 3D distance values by in order to get Inches.
Typenumber
RestrictionsRead Only
 cm
The scale to multiply native 3D distance values by in order to get centimeters.
Typenumber
RestrictionsRead Only
 distance
The most recent measured distance.
Typenumber
RestrictionsRead Only
 view
The view definition to use when projecting 3D data into the image.
Typestring
DefaultView.(scene name)
 minFPS
The minimum desirable frame rate. When the actual frame rate drops below this value, various visual-quality-degrading optimizations are employed to improve the frame rate (not doing linear filtering, mipmapping, etc.).
Typenumber
Default10
 antialias
Whether to perform incremental anti-aliasing passes when the scene is not changing.
Typeboolean
Defaulttrue
 pauseAntialias
Whether to temporarily pause computation of antialias image to improve responsiveness.
Typeboolean
Default(true when mouse is pressed)
 mipmap
Whether to compute reduced-resolution versions of all file-derived textures in the scene, in order to avoid aliasing artifacts when anti-aliasing is not being performed (such as when the object is moving). This increases memory consumption by about 33%, so it should be turned off when exceptionally large scenes are being used. Since most Java VMs will not allow applets to use more than 64MB, the memory limit for texture (assuming 16-bit depth) is less than 32 Mega-pixels without mipmapping, and less than 24 Mega-pixels with mipmapping. Exactly how much less than these number will be available depends on the 2D environment in which the 3D scene is placed (screen size, anti-aliasing used, other 2D images in the scene, etc.).
Typeboolean
Defaulttrue
 thetaStep
The amount by which to change theta as the mouse moves during interactive rotation.
Typenumber
Default360 / scene width
 phiStep
The amount by which to change phi as the mouse moves during interactive rotation.
Typenumber
Default180 / scene height
 illustrationMode
Turns on illustration rendering mode.
Typeboolean
Defaulttrue
 illustrationThickness
In illustration mode, controls the line thickness.
Typenumber
Default1
 illustrationThreshold
In illustration mode, controls the crease angle threshold used to detect where to draw lines. In degrees, in the range 0 to 90.
Typenumber
Default15
 illustrationLineColor
In illustration mode, controls the color of drawn lines. This may include an alpha component.
Typecolor
Defaultblack
 illustrationFillColor
In illustration mode, controls the color of area fills. This may not include an alpha component. Set this to "" or clear to indicate that areas should be rendered in ordinary photorealistic style.
Typecolor
Defaultwhite

Scene overrides these attributes:

 buffer
3D Scenes are always rendered using alpha channels. Change the background behind the scene by changing the parent image, or sibling images with lower layer values.
Typecolor
Default0000
RestrictionsRead Only
 cursor
By default, the cursor used by a scene is dynamically set based on the value of the mode attribute of the scene.
Typestring
Defaultdepends on mode

Class: HotSpot

A HotSpot is a 3D sphere in the scene which is projected into screen space each frame to allow connections between the 2D interface elements (such as popup graphics) and points in 3D space. HotSpot objects are not created directly by Meson programs. Instead, the program includes a HotSpotRT object which is associated with a 3D scene runtime. The Scene then creates a peer HotSpot object for each HotSpotRT it finds, and fills it with projected information. This peer is named HotSpot.(scene name)_(HotSpot RT name). For example, if a scene named Scene.3d finds a HotSpot named HotSpotRT.hs1, it will create the object HotSpot.3d_hs1.

 x
The projected X image coordinate of the current location of the hotspot.
Typenumber
RestrictionsRead Only
 y
The projected Y image coordinate of the current location of the hotspot.
Typenumber
RestrictionsRead Only
 z
The distance between the viewer and the current location of the hotspot.
Typenumber
RestrictionsRead Only
 radius
The projected radius of the hotspot, in pixels.
Typenumber
RestrictionsRead Only
 visible
Set to true if the closest part of the hotspot sphere is in front of the 3D objects in the scene.
Typeboolean
RestrictionsRead Only
 mouseHover
Indicates that the mouse is hovering over the hotspot. Note that applications generally should not use this attribute directly, but rather should use the hover attribute.
Typeboolean
 hover
Indicates that the mouse is hovering over the hotspot. Note that the pixel under the mouse must be drawn by this hotspot's Scene image in order to transition to hover=true. This defaults to an expression which simply mirrors the mouseHover attribute, but can be modified to achieve more complex behaviors.
Typeboolean
 press
Indicates that the left mouse button is pressed on the HotSpot.
Typeboolean
RestrictionsRead Only