What are Extras?
Extras are external applications that add extra functionality to the PiXELS3D application. Extras communicate with the host application, in this case PiXELS3D, using the TCL scripting language. An extra can be created using FaceSpan, or even C/C++. This tutorial will concentrate on creating an extra in C/C++. This first tutorial in a series extras tutorials is aimed at users who are new to writing extras.


Introduction
Communicating with PiXELS3D is done using AppleEvents. If you were to write an AppleScript that sends the command:

sphere -name Sphere -radius 10.0000 -endSweep 360.0000 -uSteps 10 -vSteps 10

to PiXELS3D, the script would simply send an AppleEvent to PiXELS3D with the string “sphere -name Sphere -radius 10.0000 -endSweep 360.0000 -uSteps 10 -vSteps 10” attached to it. AppleScript is very easy to use. When using AppleScript you don’t have to worry about the technical aspects of AppleEvents; you simply type :

do script “sphere -name Sphere -radius 10.0000 -endSweep 360.0000 -uSteps 10 -vSteps 10”

PiXELS3D sends back a reply in the form of a string of characters. There are numerous advantages when writing extras in C/C++. One of the most notable advantages is the fact that math functions are usually quicker in a compiled language such as C/C++ as opposed to TCL.


Quick Introduction to AppleEvents
AppleEvents are sometimes referred to as “interapplication communication.” As stated earlier you can use AppleEvents to send PiXELS3D a command. When dealing with AppleEvents you have a target process which will receive the command. After the target has been identified you create the AppleEvent and attach parameters to it. In the case of PiXELS3D a C-style string is attached to the AppleEvent. The actual AppleEvent is sent to the target process using the AESend() function.

Sending AppleEvents to PiXELS3D
Now lets try sending an AppleEvent to PiXELS3D. We will create the target by specifying the application creator code. In the case of PiXELS3D the creator code is ‘Sync’. The following piece of code will create a AppleEvent descriptor that refers to the PiXELS3D application.

theErr = AECreateDesc(typeApplSignature, &applicationSignature, 4, &commandDesc);

The following piece of code creates the AppleEvent. Notice the ‘misc’ and ‘dosc’ values. These specify the type of AppleEvent. In the case of PiXELS3D we want the AppleEvent to be the “do script” command.

//Create the apple event
theErr = AECreateAppleEvent('misc', 'dosc', &commandDesc, kAutoGenerateReturnID, 1, &theEvent);

The next piece of code attaches a C-style string to the AppleEvent. Remember a C-style string is terminated with a null-byte. If you have to send pascal-style strings to PiXELS3D you can use the utility function p2cstr() to convert the pascal string to a C string.

//Attach the command to the AppleEvent
theErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, theCommand, strlen(theCommand));

Now comes the exciting part. We are ready to send the command. The parameters here may seem confusing. The kAEWaitReply value means that we want a reply from the target application. For example if we were to send the command “objectlist” to PiXELS3D we would get a reply that contains all the objects in the current scene. The kAENormalPriority means that this AppleEvent is of “normal priority.” The value parameter kNoTimeOut means that we will wait for as along as it takes to send/receive the AppleEvent; in other words there will be no timeout.

//Send the AppleEvent
theErr = AESend(&theEvent, &eventReply, kAEWaitReply, kAENormalPriority, kNoTimeOut, nil, nil);


Try it Out!
Now it is time to do something with all this information about AppleEvents and PiXELS3D. Below is a sample function that will change the bucket size given two integers. Try compiling the code and running it.



OSErr P3D_SetBucketSize (short x, short y)
{
char cmd[4096];
OSErr theErr;
AppleEvent theEvent;
//The AppleEvent being sent to P3D
AppleEvent eventReply;
AEDesc commandDesc;
//AEDesc for the PS command
OSType applicationSignature = 'SynC';

//Create the command string
sprintf(cmd, "array set bucketSize [list x %d y %d]\rsetbucketsize bucketSize", x, y);

//Create the descriptor
theErr = AECreateDesc(typeApplSignature, &applicationSignature, 4, &commandDesc);

if (theErr)
return theErr;

//Create the apple event
theErr = AECreateAppleEvent('misc', 'dosc', &commandDesc, kAutoGenerateReturnID, 1, &theEvent);

//Attach the command to the AppleEvent
theErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, cmd, strlen(cmd));

if (theErr)
return theErr;

//Send the AppleEvent
theErr = AESend(&theEvent, &eventReply, kAEWaitReply, kAENormalPriority, kNoTimeOut, nil, nil);

return (theErr);
}



Closing Notes
This tutorial is the first of a series of extras tutorials. Subsequent tutorials will dive into TCL scripting and graphics programming.