Hi,
here's a great breakdown of the boxcontrollermulti script from Lyle that can help you getting started :)
====================================================================================================
BOXCONTROLLERMULTI SCRIPT BREAKDOWN - by Lyle Milton
The HandleSelect function determines which handle action will be updating the handle, and the HandleUpdate function updates the handle.
In regards to the boxcontrollermulti.msa script, those functions are critical. However, they are not required. Only create those functions if you need to. Just so you have a clear understanding, I'll break down those functions step-by-step. But please keep in mind that this is all specific to the boxcontrollermulti.msa script. Your functions can be completely different. The only requirements are:
your action script *must* have a HandleAction function and have the SCRIPT_ACTION_DRAG or _CLICK defined. Otherwise, it will be recognized as an action script.
if you need to perform some operation when the frame is updated, you must create a HandleUpdate function
if you need to perform some operation when the handle is selected in the world view, you must create a HandleSelect function.
while your functions can have any number of params (you're not limited to the ones shown here), all of your Handle* funcs MUST HAVE THE SAME PARAMETERS. For example, all Handle* functions in that boxcontrollermulti.msa script have the params : object obj1, int chan1, object obj2, int chan2, int update. Your HandleAction function will be used as a "template", i.e. if your HandleSelect function doesn't have the same format as your HandleAction function, your HandleSelect function will never be called. Likewise for HandleUpdate.
Onward...
The HandleSelect function simply sets the "update" parameter. Here's the breakdown:
//The select handle function===============================================
int HandleSelect(object obj1, int chan1, object obj2, int chan2, int update)
{
int action, sib;
string class_name;
1. Get the current handle action (the script) & name of that action (the script's name)
action = ActionActive();
class_name = ActionClass(action);
2. Set this action's update parameter to 1 (on). This means that the objects/channels used by this action (obj1, chan1, obj2, chan2) will be used to update the handle's position. Note that "update" corresponds to the "int update" parameter of the HandleAction, HandleUpdate, & HandleSelect. I could have just as easily set the obj1, chan1, etc. params if needed.
ActionParamSet(action, "update", 1);
3. Set the previous & next actions' update parameter to 0 (off). This means that those actions will not attempt to update the handle. Note that we're only concerned with other instances of this script (denoted by class_name). Use the ActionIsClass function to ensure we're only modifying actions of this same class.
sib = action;
while(sib=ActionPrev(sib))
{
if (ActionIsClass(sib, class_name))
ActionParamSet(sib, "update", 0);
}
sib = action;
while(sib=ActionNext(sib))
{
if (ActionIsClass(sib, class_name))
ActionParamSet(sib, "update", 0);
}
4. Force the handle to update by calling our own HandleUpdate function. This is necessary because frame update messages are never sent when a handle is selected. Frame updating can be a costly operation, so handle updaing will need to be done explicitly.
HandleUpdate(obj1, chan1, obj2, chan2, 1);
return (1);
}
When the frame is updated, the HandleUpdate function is called. In this case, it repositions all the handles that make up the boxcontroller:
//The update handle function===============================================
int HandleUpdate(object obj1, int chan1, object obj2, int chan2, int update)
{
int handle;
int child, prev;
double x, y, posx, posy;
float r, g, b;
int stipple;
1. If this action isn't currently in charge of updating the handle, just exit the function. This value corresponds to that which was set in HandleSelect.
if (!update) return (1);
2. Get the currently processing handle. This is the handle to which this action is attached. In this case, it's the Marker handle for the boxcontroller.
handle = HandleActive();
3. Set the Marker handle's position based on the values from chan1 & chan2.
//update marker,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
posx = motchan(obj1, chan1, NOW);
posy = motchan(obj2, chan2, NOW);
x = (posx * BOX_SIZE) - BOX_HALF;
y = (posy * BOX_SIZE) - BOX_HALF;
x = Clamp(x, -BOX_HALF, BOX_HALF);
y = Clamp(y, -BOX_HALF, BOX_HALF);
HandleOffsetVecSet(handle, x, y, 0);
4. Determine the horizontal crosshair handle's attributes. In this case, it's setting an error color for the handles if the channel values go outside the boundaries of the box. And, just like on the EditSphere, it draws the lines in a stipple pattern if the corresponding channel has no key at this particular frame. The stipple number corresponds to the location in the Handle line style pattern tray (it's the 1st or 11th item in that tray).
//update crosshair,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
if ((posy<0)||(posy>1))
{
r = 1;
g = 0;
b = 0;
}
else
{
r = 0.94;
g = 0.60;
b = 0.5;
}
if (KeyChannelExists(obj2, NOW, chan2))
stipple = 0;
else
stipple = 10;
5. Set the horizontal crosshair handles's positions and attributes. The handled are repositioned so that they stay within the boxcontroller's boundaries.
child = HandleChild(handle);
HandleOffsetVecSet(child, -BOX_HALF-x, 0, 0); //horizontal line -
HandleColorVecSet(child, r, g, b);
HandleLineStippleSet(child, stipple);
child = HandleNext(child);
HandleOffsetVecSet(child, BOX_HALF-x, 0, 0); //horizontal line +
HandleColorVecSet(child, r, g, b);
HandleLineStippleSet(child, stipple);
HandleTextSet(child, str(posy));
6. Repeat steps 4 & 5, but for the vertical crosshair handles.
if ((posx<0)||(posx>1))
{
r = 1;
g = 0;
b = 0;
}
else
{
r = 0.94;
g = 0.60;
b = 0.5;
}
if (KeyChannelExists(obj1, NOW, chan1))
stipple = 0;
else
stipple = 10;
child = HandleNext(child);
HandleOffsetVecSet(child, 0, -BOX_HALF-y, 0); //vertical line -
HandleColorVecSet(child, r, g, b);
HandleLineStippleSet(child, stipple);
child = HandleNext(child);
HandleOffsetVecSet(child, 0, BOX_HALF-y, 0); //vertical line +
HandleColorVecSet(child, r, g, b);
HandleLineStippleSet(child, stipple);
HandleTextSet(child, str(posx));
7. Set the position of the box handles. This wouldn't really be necessary if the handles were originally positioned via the interface, however this method is more direct and it corrects any modifications that were made via the interface.
//update box edges,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
prev = HandlePrev(handle);
HandleOffsetVecSet(prev, BOX_HALF, BOX_HALF, 0); //start (tr)
child = HandleChild(prev);
HandleOffsetVecSet(child, 0, -BOX_SIZE, 0); //right edge (br)
child = HandleChild(child);
HandleOffsetVecSet(child, -BOX_SIZE, 0, 0); //bottom edge (bl)
child = HandleChild(child);
HandleOffsetVecSet(child, 0, BOX_SIZE, 0); //left edge (tl)
child = HandleChild(child);
HandleOffsetVecSet(child, BOX_SIZE, 0, 0); //top edge (tr)
return (1);
}
====================================================================================================
vBulletin v3.0.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.