LScript v2.3 Release Notes

LScript v2.3 Release Notes



New Features


                                                                                                    
  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).


Behavioral Changes


                                                                                                    
  Requester panels now adhere to the practice of mapping the Enter key to the 'Ok' button,
  and the Escape key to the 'Cancel' button (if it exists).


                                                                                                     
  The use of the LoadScene() and ClearScene() Layout CS commands are now disallowed in
  Master scripts that are functioning in SCENE mode.  Either of these commands can clear
  the script, potentially leaving LScript in an unstable state.


                                                                                                    
  The Channel Object Agent's setKeyTime() method has been removed from the object.  Key time
  indices are read-only, so this method has no purpose.


                                                                                                     
  The ctlfilename() function's default behavior is now to post a Save dialog when its selection
  button is pressed.  An optional Boolean true value as a fourth argument will alter this
  default behavior and post a Load dialog instead.  This change was made for the Mac where
  Save and Load dialogs have distinctly different functionality.


                                                                                                     
  The getfile() function now follows the same behavioral changes as ctlfilename().

Bug Fixes


                                                                                                    
  The AddEnvelope() and RemoveEnvelope() commands were internally wrapping the
  envelope name in quotation marks, which caused Layout some heartburn.


                                                                                                    
  The ctlposition() function was not accepting the correct number of arguments
  when used in Modeler scripts.


                                                                                                    
  The polygon() method and polygon data member of the Point integral data type were
  not implemented correctly, resulting in incorrect return values.


                                                                                                    
  The run-time system was not managing short numeric types when a need existed to
  swap bytes--such as when running an Intel-compiled script on the Macintosh.  This
  lead to some odd error messages and occasional crashes.


                                                                                                    
  The sort methods (sortA() and sortD()) were not properly handling strings.  A
  new sorting algorithm has been implemented to address this.


                                                                                                    
  The pre- and post-increment and pre- and post-decrement operators were not being provided
  the correct internal pointer types when applied to an object's data member.


                                                                                                    
  The VMap setValue() method was suffering from a lack of clarity in my understanding of the
  Vertex Map access functions (and a lack of consolidation of that particular API interface
  in the SDK).  This caused a crash on second and subsequent calls for the same VMap Object
  Agent.


                                                                                                    
  Associative assignments were not working correctly when the data being assigned was
  multiple-return Object Agents.


                                                                                                    
  The CLEAR action for selpoint() and selpolygon() would not clear specific points or
  polygons from the current selection when provided as arguments using the ID or NDX
  flags.


                                                                                                    
  The image offset values provided to ctlimage() were not being processed correctly.


                                                                                                    
  The vertical selection argument to the ctlchoice() function has been enabled.


                                                                                                    
  A re-entrancy problem existed when Generic scripts invoked Command Sequence functions that
  then invoked other Generic scripts as part of their processing.  This has been addressed.