Technical Information for xeoObject DevelopersSee also the xeoObject Language Reference
IntroductionxeoObjects are small external files that describe the functionality of a plug-in or process that cannot be defined within the core Auto-Illustrator program. For this reason, xeoObjects are used for plug-ins, and also elsewhere in the application. The document is written with the assumption that you are writing a plug-in for Auto-Illustrator in xeoObject format. The content here may not be suitable for other xeoObject applications, whether for Auto-Illustrator or not.
What is a xeoObject?A standard text file with a .xeo extention, written in a uniform language that is a perculiar hybrid of lingo and ASM, with C-style variable declarations. The language itself is very limited, with only a few operands, but this in conjunction with the flexible variable and handler style syntax, is enough to write reasonably complex plug-ins.A xeoObject also contains instructions that tell the xeoObject runtime environment how to layout a dialog box. You can make simple interactive plug-ins in the manner. The contents of a dialog box are also limited (for example, you can only have up to 16 buttons in your dialog), but should prove sufficient.
Language SyntaxHandlersYou divide your code blocks of instructions (known as a handler), and give each handler a name. Certain handlers are called by the xeoObject runtime environment, for example, when your plug-in needs to be executed, or when a user has interacted with a control on your dialog. Other handlers you can call yourself from your own code, meaning you can split the functionality of your plug-in up into easy to maintain chunks.The syntax to define a handler is the same as in Lingo or Applescript: on handlername code goes here endIf you want to call this handler from elsewhere in your xeoObject code, you can do so using the do keyword: do handlernameCertain handler names are fixed, and you should make sure you have defined handlers for these names:
on open on open senddata Auto-Illustrator::Plugin::Name Joe's First Plug-In endon launch Called when your plug-in is launched by a user. A user has selected your plug-in from the menu, so you should now start the main functionality of your plugin (ie, producing new shapes, setting up the dialog box if needed, etc).
VariablesVariables are a bit quirky in xeoObjects, but they are flexible. To start with, you use C-style variable definitions to define your variables as one of three different data types:int myIntegerVariable double myDoubleVariable string myStringVariableNote that you can put these definitions anywhere in your xeoObject file - there are no such things as local or global variables - everything has the same scope, so you need to bear that in mind when creating your various handlers. When you refer to your variables in your code, there are two ways of doing so. If you are referring to the variable, then you just provide it's name. You do this when you want to set variables, or do maths such as add and mul (multiply). For example: set myIntegerVariable 42 add myIntegerVariable 10 set myDoubleVariable 5.5 mul myDoubleVariable 2 set myStringVariable Mary Had a Little LambHowever, if in your code you wish to refer to the actual value of that variable, then you enclose the variable name in square braces: add myIntegerVariable [myDoubleVariable]This is a very important distinction. In the example above, the value of myDoubleVariable (which, I believe, we set to 5.5 then multiplied by 2, so is 11) is added to myIntegerVariable, which was 52. So myIntegerVariable is now 63. You dont need to typecast variables. If you try adding a number onto a string, the number variable is treated as a string. (Psst, you can add a string onto a number, so long as the string contains a number, but thats rarely necessary). add myStringVariable %20it cost%20 add myStringVariable [myIntegerVariable] add myStringVariable %20dollarsThe value of myStringVariable is now "Mary Had a Little Lamb it cost 63 dollars". Note that %20 was used to indicate a space. You need to do that sometimes because you dont use quotation marks with string constants (unlike other languages) and the xeoObject runtime environment removes surplus whitespace from your script before executing. Also, you cannot mix string constants with variable references, hence the need for three separate add statements in the above example.
Conditional statementsNaturally, there will be times when you only want to execute some code when some comparison of variables you are using matches your requirements. The if statement only executes the next line of code if the condition set out evaluates to true:if [myIntegerVariable] > 5 set myIntegerVariable 0Note, once again, the difference between the first and second reference to the variable called myIntegerVariable. The first is in square braces because we are comparing the value of that variable with the number 5. It would be very tempting to not include the square braces, but the xeoObject runtime environment wouldn't evaluate that if statement correctly because it wouldn't be comparing the value of the variable myIntegerVariable. The situation is comparable to that of using pointers in C or Pascal: you have to remember to dereference the variable if you actually want it's value. The difference here is that an un-dereferenced variable reference equals zero, not the actual pointer address as in other languages. But you really dont need to know that. There are five different comparison evaluations:
< for numeric less-than (ie, 5 < 6 is true) If you want to execute more than one line of code, you need to split that code into a separate handler and call it like so: on launch if [myIntegerVariable] == 42 do theMeaningOfLife end on theMeaningOfLife any amount of code goes here any amount of code goes here any amount of code goes here endAnother important thing to remember is that you can't nest if statements: on launch if [myIntegerVariable] == 42 if [myDoubleVariable] > 10 set myStringVariable Easy! endThis does not work! Why? Because if the first conditional comparison evaluates to false (ie, if myIntegerVariable does not equal 42) then the runtime environment skips the next line and stops at the set line, which is not actually what you intended! (indentation means nothing to the interpreter). Instead, you have to split nested if statements into separate handlers: on launch if [myIntegerVariable] == 4 do checkDoubleValue end on checkDoubleValue if [myDoubleVariable] > 10 set myStringVariable Easy! endIt's clumsy, but in this respect conditional statements in xeoObjects are more like ASM, because you have to think about the 'location' of the 'instruction pointer' (ie, the linenumber that is currently executing).
LoopsLuckily, loops in xeoObjects are much easier. They're just like BASIC FOR..NEXT loops, with a few minor changes to the syntax:for variableName firstValue lastValue stepIncrement whatever code goes here nextThis example counts from 1 to 10, adding that number to the end of a string, and each time divides another variable in half. for myIntegerVariable 1 10 1 add myStringVariable [myIntegerVariable] mul myDoubleVariable 0.5 nextPS. Don't put a conditional if statement right before a next statement. That's really bad. I'm sure you can figure out why. Also, watch out you dont get your lastValue or stepIncrement figures wrong - if you're counting from 1 to 10 but your stepIncrement is -1, you'll count 1, 0, -1, -2, -3 (etc) and you'll never ever reach 10! This will lock up your computer. Don't blame us.
|
|