|
The Scene Object Agent now provides information pertaining to the state of the Layout's
dynamic update setting. This information is available in the dynamicupdate data member,
and will be one of the following:
DYNUP_OFF
DYNUP_DELAYED
DYNUP_INTERACTIVE
|
|
A new method is available in the Scene Object Agent to determine the display state of
an object in the scene. Given either the name of an existing object, or that object's
proxy, the visibility() method will return one of the following indicators:
VIS_VISIBLE
VIS_HIDDEN
VIS_BOUNDINGBOX
VIS_VERTICES
VIS_WIREFRAME
VIS_FFWIREFRAME
VIS_SHADED
VIS_TEXTURED
|
|
A new method exists in the Scene Object Agent to retrieve the X and Y position of an
object's entry in Layout's schematic view. Provided a name or proxy, the schemaPosition()
method will return two floating-point values representing this position.
Coupled with the SchematicPosition() Command Sequence function, a script can manage
the complete arrangement of Layout's schematic viewport.
|
|
The displayopts[] data member, belonging to the Scene Object Agent, provides information
regarding display-related settings in Layout. The following are the specific elements
in the array:
displayopts[1] Boolean 'true' if Motion Paths are displayed
displayopts[2] Boolean 'true' if Handles are displayed
displayopts[3] Boolean 'true' if IK Chains are displayed
displayopts[4] Boolean 'true' if Cages are displayed
displayopts[5] Boolean 'true' if Safe Areas are displayed
displayopts[6] Boolean 'true' if Field Charts are displayed
|
|
The new generalopts[] Scene Object Agent data member provides information regarding
general settings in Layout. The following are the specific elements in the array:
generalopts[1] Boolean 'true' if Hide Tool Bar is enabled
generalopts[2] Boolean 'true' if Right Tool Bar is enabled
generalopts[3] Boolean 'true' if Parent In Place is enabled
generalopts[4] Boolean 'true' if Fractional Frame is enabled
generalopts[5] Boolean 'true' if Keys In Slider is enabled
generalopts[6] Boolean 'true' if Play Exact Rate is enabled
|
|
Layout Object Agents export a new data member, visibility, that contains one of the
values returned by the Scene Object Agent's visibility() method.
|
|
A new schemaPosition() method has been added to Layout Object Agents that will return
two floating-point values that represent the object's position in Layout's schematic
viewport.
|
|
Both the Scene and Layout Object Agents export a new method called server(). This method
will return the name of an active plug-in applied to the object. The first argument is
the plug-in class to be queried. The second is an optional index value for selecting
a specific plug-in.
The plug-in class can be a literal string (like "ItemMotionHandler"), or you can use
one of the following pre-defined constants:
SERVER_ANIMLOADER_H SERVER_ANIMLOADER_I
SERVER_ANIMSAVER_H SERVER_ANIMSAVER_I
SERVER_CHANNEL_H SERVER_CHANNEL_I
SERVER_CUSTOMOBJ_H SERVER_CUSTOMOBJ_I
SERVER_DISPLACEMENT_H SERVER_DISPLACEMENT_I
SERVER_ENVIRONMENT_H SERVER_ENVIRONMENT_I
SERVER_IMAGEFILTER_H SERVER_IMAGEFILTER_I
SERVER_PIXELFILTER_H SERVER_PIXELFILTER_I
SERVER_FRAMEBUFFER_H SERVER_FRAMEBUFFER_I
SERVER_MASTER_H SERVER_MASTER_I
SERVER_ITEMMOTION_H SERVER_ITEMMOTION_I
SERVER_OBJREPLACEMENT_H SERVER_OBJREPLACEMENT_I
SERVER_SHADER_H SERVER_SHADER_I
SERVER_TEXTURE_H SERVER_TEXTURE_I
SERVER_VOLUMETRIC_H SERVER_VOLUMETRIC_I
Where _H indicates a Handler-type server (i.e., "ItemMotionHandler") and _I indicates
an Interface-type server (i.e., "ItemMotionInterface").
Certain classes of plug-in are itemless, such as Image Filter and Master. While you can
provide these class types to a Layout Object, you will only get a valid return value if
you use these with the Scene Object Agent (and, of course, plug-ins of that type are
active). Likewise for classes that are associated with objects; they will not
return valid values with the Scene Object Agent.
|
|
The sort methods (sortA() and sortD()) now support Point and Polygon identifiers when
encountered in arrays.
|
|
A new integral data type method called reduce() has been added. This method will remove
duplicate values from the data type (useful mostly for strings and arrays). Duplicate values
are expected to be in linear order--i.e., adjacent to one another. You should probably
employ one of the sort methods before invoking reduce().
The following is an example of using the reduce() method. A linear series of Polygon
identifiers are gathered into an array in a situation where there is a high probablity of
duplication. Subsequent calls to sortA() and reduce() remove any duplicate entries from
the resulting array:
...
for(x = 1;x <= pointCnt;x++)
{
rawPolys = points[x].polygon();
polyCnt = rawPolys.count();
for(y = 1;y <= polyCnt;y++)
polySelect += rawPolys[y];
}
polySelect.sortA();
polySelect.reduce();
...
|
|
The Requester mechanism supports an optional idle-time callback. The reqpost()/reqopen()
functions will now accept up to two new arguments to enable idle-time processing. The first
argument is the name of the UDF to be invoked. The UDF takes no arguments, and is enabled to
allow for drawing on the Requester panel. The second optional argument is the timeout interval
(in milliseconds) to be used between calls to the idle-time UDF. If ommitted, the default
timeout value is 500 milliseconds (one-half of a second).
generic
{
reqbegin("Testing Idle");
c1 = ctlnumber("Number",1.0);
reqpost("idleTest"); // called at 500-millisecond intervals
reqend();
}
color = <0,255 * .5,255 * .75>;
idleTest
{
drawline(color,0,2,100,2);
color.x += 5;
color.y += 5;
color.z += 5;
if(color.x > 255) color.x = 0;
if(color.y > 255) color.y = 0;
if(color.z > 255) color.z = 0;
}
Certain conditions may prevent the system from invoking the UDF at exact interval times.
Thus, the timeout value specified should be considered only an approximation--in other words,
you should not make the assumption that only that amount of time has elapsed when your
idle-time UDF is invoked.
|
|
The Requester control identifier value, returned by functions like ctlstring() and
ctlnumber(), has been promoted to valid LScript data type status. This ascension has
enabled the new Control data type to sport its own set of object attributes. Below
are the initial set of methods and data members. The attribute set may be expanded
in future releases of LScript.
The new methods exported by the new Control data type:
active([<Boolean>])
This method sets the immediate active state of the
control. An optional Boolean value indicates whether
or not the control should be active. If ommitted,
an implicit 'true' value is assumed.
visible([<Boolean>])
This method sets the immediate visible state of the
control. An optional Boolean value indicates whether
or not the control should be visible. If ommitted,
an implicit 'true' value is assumed.
position(<column>,<row>)
Sets the location of the control on the open Requester
panel to the specified column/row. The re-positioning
action is immediate. You should use the visible() method
before and after this call to ensure a clean move of
the control.
Data members exported by the Control data type:
value
This data member holds the context value display
by the control. Reading from and writing to this
value is equivalent to using the setvalue() and
getvalue() functions, respectively, on the control
identifier.
active (read-only)
Returns a Boolean value indicating the current
active state of the control, where a 'true' value
indicates that the control is currently active and
can interact with the user.
visible (read-only)
Returns a Boolean value indicating the current
visible state of the control, where a 'true' value
indicates that the control is currently visible
on the Requester panel.
x (read-only)
Contains the control's current X position on the
Requester panel.
y (read-only)
Contains the control's current Y position on the
Requester panel.
w (read-only)
Contains the control's width
h (read-only)
Contains the control's height
|
|
A new function has been added to the Requester drawing toolbox. The drawerase() function
takes the the X and Y position, along with the width and height, of the area to be erased
on the Requester panel.
...
drawerase(10,10,50,25);
...
|
|
Requester panels can now be interactively resized by the user if an internal resize callback
is defined within the script using the new reqresize() function. This function takes up to
five arguments, the first, a required string value, should identify a UDF within the script.
This UDF should accept two integer arguments, indicating the new width and height of the
Requester panel, and should return nothing.
Two optional pairs of numbers can also be provided to indicate the the minimum width and
height, and maximum width and height, for the panel. If ommitted, the minimum width and
height becomes that of the initial window, and the maximum width and height is limited only
by the screen resolution.
The following Generic script illustrates the use of the new resize mechanism by locking a
control to a specific location on the panel, regardless of its size:
c1;
generic
{
reqbegin("Resize Me!");
c1 = ctlnumber("Number",1.0);
reqresize("resize",,,640,480); // maximum becomes 640x480
reqpost();
reqend();
}
resize: w,h
{
c1.position(w - c1.w - 5,h - c1.h - 35);
}
Resizing of Requester panels is only enabled when the reqresize() function successfully
identifies a callback UDF. If reqresize() is not used, then the panel is locked to its
initial size.
|
|
LScript sports a new plug-in class, Custom (Object). Like Item Animation, Custom Object
can take an optional argument to its create() UDF that is an Object Agent for the object
to which this script is assigned. Custom Object also supports the init(), newtime() and
cleanup() UDFs.
The Custom Object process() UDF takes a single argument which is a Custom Object Agent
that provides an interface to the underlying Custom Object functionality. It exports
the following data and methods:
view
a read-only data member that indicates which
view drawing will effect. It will contain one
of the following:
VIEW_ZY
VIEW_XZ
VIEW_XY
VIEW_PERSP
VIEW_LIGHT
VIEW_CAMERA
VIEW_SCHEMA
flags[]
read-only array of settings for the current Custom
instance. it only has a single element right
now (flags[1]) which will be 'true' if the Custom
object should be drawn in a selected state, or
'false' otherwise.
setColor(<r,g,b>|r,g,b[,a])
sets the color for subsequent drawing actions.
setPattern(pat)
sets the drawing pattern. solid by default, or
can be one of the following:
PATTERN_SOLID (or "SOLID")
PATTERN_DOT (or "DOT")
PATTERN_DASH (or "DASH")
PATTERN_LONGDOT (or "LONGDOT")
drawPoint(<pos>[,coord])
draw a point into the current view at the vector
location <pos> using the previously set color and
line pattern. The coord parameter is optional
(SYS_OBJECT is the default), and can be one of
the following:
SYS_WORLD (or "WORLD" or "GLOBAL")
SYS_OBJECT (or "OBJECT" or "LOCAL")
SYS_ICON (or "ICON")
drawLine(<pos1>,<pos2>[,coord])
draws a line segment from vector <pos1> to
vector <pos2>.
drawTriangle(<pos1>,<pos2>,<pos3>[,coord])
draws a triangle whose end points are vector <pos1>,
vector <pos2>, and vector <pos3>.
drawCircle(<pos>,rad[,coord])
draws a circle whose center point is vector <pos>,
with a radius of rad.
drawText(<pos>,text[,coord,[align]])
draws the provided text string at the vector
location <pos>. the align argument can be one
of the following:
LEFT (or "LEFT")
CENTER (or "CENTER")
RIGHT (or "RIGHT")
The plug-in API does not maintain state information between evaluations, and neither does
LScript. This means that every time the process() UDF is called, the color is set back
to that established for the object in the Layout interface, and the drawing pattern is
always PATTERN_SOLID.
Here is a short Custom Object LScript that duplicates the "barn" sample provided by
Ernie in the LightWave SDK:
@warnings
@script custom
vert = @ <0.0, 0.0, 0.0>, <1.0, 0.0, 0.0>, <1.0, 1.0, 0.0>,
<0.5, 1.5, 0.0>, <0.0, 1.0, 0.0>, <0.0, 0.0, -1.0>,
<1.0, 0.0, -1.0>, <1.0, 1.0, -1.0>, <0.5, 1.5, -1.0>,
<0.0, 1.0, -1.0> @;
edge = @ 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 6, 7,
7, 8, 8, 9, 9, 10, 10, 6, 1, 6, 2, 7,
3, 8, 4, 9, 5, 10, 2, 5, 1, 3 @;
process: ca
{
for(x = 1;x < 31;x += 2)
ca.drawLine(vert[edge[x]],vert[edge[x+1]]);
ca.setPattern("dot");
for(x = 31; x < 35;x += 2)
ca.drawLine(vert[edge[x]],vert[edge[x+1]]);
}
|
|
LScript now offers a new Object Agent for Layout scripts: Particle.
This Object Agent provides an interface to the underlying plug-in API Particle System
services. Specific documentation for that global service can be found in the LightWave
SDK docs.
A Particle Object Agent instance is created using the constructor Particle(). This
constructor can be used to create a new instance of a Particle database, or it can be
used to acquire an existing Particle System, depending upon the arguments provided.
If a valid Layout Object Agent is provided to the constructor, then a list of the
Particle systems active on that object are returned. If no Particle systems are
enabled for that object, then 'nil' is returned.
...
obj = Mesh("Cow");
part = Particle(obj) || error("No particle systems active!");
...
When creating a new Particle system, you must specify the type of the particles and
provide a list of the buffers that are to be created and maintained for each particle.
Particle types can be one of PART_PARTICLE (single particle) or PART_TRAIL (particle with
tail). As with most constants in LScript, these can also be specified using the string
equivalents "particle" and "trail".
The buffers that can be allocated for each particle are as follows:
PART_POSITION (or "position")
PART_SIZE (or "size")
PART_SCALE (or "scale")
PART_ROTATION (or "rotation")
PART_VELOCITY (or "velocity")
PART_AGE (or "age")
PART_FORCE (or "force")
PART_PRESSURE (or "pressure")
PART_TEMPERATURE (or "temperature")
PART_MASS (or "mass")
PART_LINK (or "link")
PART_ID (or "id")
PART_ENABLE (or "enable")
PART_RGBA (or "rgba")
PART_COLLISION (or "collision")
Particles can exist in one of three states: PART_ALIVE, PART_DEAD, or PART_LIMBO. These
values are used when reading/writing the PART_ENABLE buffer.
The following methods and data members are exported by the Particle Object Agent:
count
returns the current number of particles (integer) defined
in the instance.
save()
writes particle-specific data during the save state
load()
loads particle data during the load state
attach(Object Agent)
attaches the particle instance to a Layout Object Agent
so systems like HyperVoxels can access the particle data
detach(Object Agent)
disassociates the particle instance from its object
reset()
clears all particles from the instance
addParticle()
generates a new particle in the instance. the index
value of the new particle is returned.
remParticle(index)
removes the indicated particle index from the instance
setParticle(index,bufid,value)
sets the data for the specified particle buffer for the
indicated particle index.
getParticle(index,bufid)
retrieves the value in the specified particle buffer for
the indicated particle index.
Here is the LScript equivalent of the particle SDK example. You can test it by applying
it to an object, and then enabling that object in HyperVoxels:
@warnings
@version 2.3
@script displace
part;
create: id
{
part = Particle("particle",@"position","size","enable","rgba"@);
part.attach(id);
}
newtime: id, frame, time
{
part.reset();
}
flags { return(WORLD); }
process: da
{
i = part.addParticle();
part.setParticle(i,"position",<da.oPos[1],da.oPos[2],da.oPos[3]>);
part.setParticle(i,"rgba",100,150,200,255);
part.setParticle(i,"enable",PART_ALIVE);
}
|
|
The following Command Sequence functions have been added to the Layout LScript
programming environment, sychronizing the system to LightWave Layout 525:
DynamicUpdate(1-3)
BoundingBoxThreshold(threshold)
AddPosition(<x,y,z>|x,y,z)
AddRotation(<h,p,b>|h,p,b)
AddScale(<x,y,z>|x,y,z)
RadiosityIntensity(0.0-1.0)
CausticIntensity(0.0-1.0)
ZenithColor(<r,g,b>|r,g,b)
SkyColor(<r,g,b>|r,g,b)
GroundColor(<r,g,b>|r,g,b)
NadirColor(<r,g,b>|r,g,b)
EditServer(class,index)
BoneFalloffType(1-7)
ShadowMapSize(16-32000)
ShowTargetLines()
MasterPlugins()
Generics()
ClearAudio()
LoadAudio()
PlayAudio()
ReplaceObjectLayer(layer,filename)
HStiffness(stiffness)
PStiffness(stiffness)
BStiffness(stiffness)
ItemActive(Boolean)
ItemLock(Boolean)
RadiosityType(1-3)
AddButton(command,group)
LoadObjectLayer(layer,filename)
LightQuality(1-5)
|
|
A new pragma called @name has been added to the pre-processor. The value of this
pragma is a display name for the script. This value will be used by the LightWave
LCore subsystem to provide a menu display name for the script when it is installed
as a plug-in. In addition, it will be used as a backup value for those scripts
who have the capability to call the identification function setdesc(), but do not.
@warnings
@script generic
@name Bone Cloner
...
If specified, script names are also now embedded into compiled LScripts, providing
them with the same naming capabilities when installed.
|
|
The VMap Object Agent now supports creation of user-defined vertex maps in Modeler.
The method used is nearly identical to that of creating a new vertex map from a
pre-defined type. In order to generate a custom vertex map, instead of using one
of the pre-defined type identifiers, you must provide a custom map type. Custom
map types are a unique four-character sequence, housed in an initialization block.
For example, to generate a vertex map of type NMBK, named my_normals, with
two data elements per point:
...
@define VMAP_NMBK @'N','M','B','K'@
...
normMap = VMap(VMAP_NMBK,"my_normals",2);
Be aware that custom vertex maps will not appear anywhere in the application's
interface. They are of types not known to the application, so no allocation is
made for them. They will, however, be stored into the object file when it
is saved, and will continue to be transported within the object file.
The VMap() constructor will return 'nil' if it fails to generate the new vertex
map, regardless of its mode (custom or pre-defined).
|