LScript v2.2 Release Notes

LScript v2.2 Release Notes



New Features


                                                                                                    
  All 20 LScript plug-ins have been integrated into a single disc file.  Further, LScript has
  been integrated into LCore, making it now an internal subsystem.



                                                                                                    
  A new Mesh Object Agent data member has been added, called "flags".  This data member is an
  array of five elements.  The first three duplicate the values found in the shadows[] data
  member.  The remaining two, flags[4] and flags[5], indicate the object's current
  "Unseen By Camera" and "Unseeen By Rays" settings.

  This new data member is intended to replace the existing shadows[] data member.  You should
  begin using this data member in future scripts as the shadows[] data memeber will eventually
  be removed from the Object Agent.



                                                                                                    
  A series of new identification methods have been added to the Object Agent class.
  These methods return a boolean true/false indicating the type of the object for
  which the Object Agent is a proxy.

        isMesh()
        isLight()
        isCamera()
        isBone()
        isScene()
        isImage()
        isChannel()
        isEnvelope()
        isVMap()
        isChannelGroup()



                                                                                                    
  The Image Object Agent now includes two new methods, alpha() and alphaSpot(), and a new data
  member called hasAlpha, for accessing Alpha-channel image data.

  The hasAlpha data member is a Boolean flag that indicates whether or not the image contains any
  Alpha image data.  If this flag is true, then the Alpha data can be accessed using the new methods.

  The new alpha() method functions just like the Image Object Agent rgb() method.  Given an (x,y)
  position within the image, the Alpha value for that pixel will be returned.  Alpha-channel data
  contains only one numeric value for each triplet RGB value.

  alphaSpot() functions just like rgbSpot(), with the exception that it only returns a single
  numeric value.


                                                                                                    
  The reqabort() function has been added to the Requester system.  This function is intended to be
  called from within a control or requester callback function, and will immediately terminate the
  posted requester.  No user intervention is required.

  When reqabort() is called without arguments, a "Cancel" result is returned to the reqpost() function.
  This simulates a user press of that button.  If a true value is provided to reqabort(), then an "Ok"
  result is passed to reqpost().

        generic
        {
            reqbegin("Reqabort() Test");

            reqsize(200,180);

            c1 = ctlstate("Goodbye",0,50,"goodbye");

            ctlposition(c1,35,10);

            if(reqpost())
                info("You pressed OK");
            else
                info("You pressed Cancel");

            reqend();
        }

        goodbye: val
        {
        //    reqabort();
            reqabort(true);
        }



                                                                                                    
  The ctlposition() function now accepts three additional, optional numeric arguments.  These
  new arguments provide access to sizeable requester controls in LScript.

  The third argument indicates the width (in pixels) of the control.  The fourth indicates the
  height (also in pixels) of the control.

  The fifth indicates the offset value for the control.  An offset value can be used to control
  the width of the label field for controls that have labels, or the distance a control is
  shifted to the right from its left-most position for those without labels.



                                                                                                    
  New selection types have been added to the Modeler selpolygon() function.  You can now select
  BONE, PATCH, and MBALL elements within the mesh.

  BONE is a synonym for Skelegon, and you can in fact also specify SKELEGON.

  MBALL stands for Metaball.

  These selection types are without argument, and will select all elements of that type within
  the current mesh.



                                                                                                    
  A new Light Object Agent data member has been added, called "flags".  This data member is an
  array of six elements, each corresponding to the flag values returned by the SDK function.  More
  specifically, each element provides the following information about the Light:

        flags[1]        true if Limited Range is enabled
        flags[2]        true if Affect Diffuse is enabled
        flags[3]        true if Affect Specular is enabled
        flags[4]        true if Affect Caustics is enabled
        flags[5]        true if Lens Flare is enabled
        flags[6]        true if Volumetric is enabled



                                                                                                    
  The Image Filter architecture supports 5 new buffer types:

    MOTIONX          2D vector-based motion blur buffer containing X distance values
    MOTIONY          2D vector-based motion blur buffer containing Y distance values
    REFLECTRED       Red levels of the contribution from mirror reflections
    REFLECTGREEN     Green levels of the contribution from mirror reflections
    REFLECTBLUE      Blue levels of the contribution from mirror reflections

  All new buffers are floating point, and must be accessed using the floatline()
  IF function.



                                                                                                    
  The Scene Object Agent has a new method called getSelect().  This method returns, as a list
  of Object Agents, all the items in a scene that are currently selected.  Called without arguments,
  all selected items--whether Mesh, Bone, Light, or Camera--will be returned.  A flag value can be
  specified to limit the view of selections to a particular genus.  Flags can be MESH, BONE, LIGHT,
  or CAMERA.

  This method is intended to simplfy the process of determining selected items, although the
  firstSelect() and nextSelect() methods are still available for special processing needs.



                                                                                                    
  The Scene Object Agent has a new data member called backdroptype.  This value holds the
  type of the current backdrop in the scene.  It can be either SOLID or GRADIENT.



                                                                                                    
  Several new backdrop-related methods have been added to the Scene Object Agent.

    backdropRay(time,ray)           This method returns the color value, as a vector, intersecting
                                    the given ray at the given time index.  The ray value must
                                    be normalized.
                                    
    backdropColor(time)             This method returns the color values for the zenith, sky, ground,
                                    and nadir, each as a vector, at the given time index.

    backdropSqueeze(time)           Returns the squeeze amount for the sky and ground, each as a
                                    floating point value, at the given time index.



                                                                                                    
  The Scene Object Agent has a new method called renderCamera().  Given a time index, this
  method will return the active camera in the scene at that time index as a Camera Object Agent.



                                                                                                    
  The Scene Object Agent has a new data member called fogtype.  This value holds the
  type of the fog active in the scene.  It can be one of NONE, LINEAR, NONLINEAR1,
  or NONLINEAR2.



                                                                                                    
  Many new fog-related methods have been added to the Scene Object Agent.

    fogMinDist(time)                This method returns the distance from the viewer (typically
                                    the camera) at which the fog effect is at a minimum. 
                                    
    fogMaxDist(time)                This method returns the distance at which the fog effect
                                    reaches its maximum

    fogMinAmount(time)              Returns the minimum amount of fog (the amount at the minimum
                                    distance). Fog amounts range from 0.0 to 1.0. 

    fogMaxAmount(time)              Returns the maximum amount of fog (the amount at the maximum
                                    distance).

    fogColor(time)                  This method returns, as a vector, the color of the fog at the
                                    given time index.



                                                                                                    
  The Scene Object Agent has three new data members that provide information about the scene's
  current compositing state.  compfg, compbg, and compfgalpha all contain either an Image Object
  Agent for the active compositing images (foreground, background, and foreground alpha,
  respectively), or they will contain 'nil' if no image is active for that position.



                                                                                                    
  A new Requester function has been added called requpdate().  This function can be used from
  within control callback functions to cause listboxes on the requester panel to refresh with
  new values.  It cannot be invoked from within a listbox count or value callback function,
  and will have no effect if it is.


            count;
            lb_items;

            generic
            {
                for(count = 1;count <= 5;count++)
                    lb_items += "Item_" + count;

                reqbegin("Testing requpdate()");

                c1 = ctllistbox("Items",300,300,"lb_count","lb_value");
                c2 = ctlbutton("Increment",200,"inc_button");

                reqpost();
            }

            lb_count
            {
                return(lb_items.count());
            }

            lb_value: index
            {
                return(lb_items[index]);
            }

            inc_button
            {
                x = count;
                y = 1;
                count += 5;

                while(x <= count)
                {
                    lb_items[y] = "Item_" + x;
                    ++x;
                    ++y;
                }

                requpdate();
            }



                                                                                                    
  Binary data can now be embedded directly within an LScript.  This data is handled by
  LScript as nothing more than a stream of unsigned bytes.  This allows any type of
  binary data to be embedded within the script and accessed at run-time.

  Binary data is delimited between a pair of preprocessor directives, "@data"
  and "@end".  Individual bytes are declared as integer values between 0 and 255.
  The data can be of any length on each line, but you should probably keep them
  under 80 columns for readibility and maximum editor compatibility.

  Each block of binary data must be named.  The name provided will become a global
  variable within the operating environment of the script when it begins to execute.

        @data bobdata
        070 079 082 077 000 000 039 064 076 087 079 050 084 065 071 083 000 000 000 010
        069 121 101 000 073 114 105 115 000 000 076 065 089 082 000 000 000 018 000 000
        ...
        @end

  The binary block identifiers exist at run-time just like any other global variable
  in your script.  They can be queried as Objects:

        info(bobdata.size());

  They can be used with the foreach() iterator:

        foreach(x,bobdata)
        {
            ...
        }

  They can be passed to functions:

        info(blocksize(bobdata));

        blocksize: data
        {
            return(data.size());
        }

  Their data can be accessed and modified as the script executes:

        x = bobdata[25];
        bobdata[25] = 0;

  As a side note, not only will your script sizes be considerably smaller, but parsing
  of the binary data will go slightly faster if values are included as a bare minimum.
  For instance, "0" will parse faster than "000", and consume two less bytes in the disc
  file.  The bytes in the examples above have been padded only for visual alignment, not
  out of any necessity.

  You can use this Generic script to generate syntactically correct LScript binary
  data from any disc file.  It will generate code to a new file, or you can specify
  an existing file (i.e., script) to which the generated code will be appended.



                                                                                                    
  A new File Object Agent method has been added specifically to handle block binary
  data.  Using writeData(), you can send the binary data in a block to a disc file.
  This can be used to re-create binary files from the embedded binary data within
  the script.  For instance, a LightWave object file can be embedded in a script
  and carried along with the script until needed:

        @version 2.2
        @warnings

        generic
        {
            output = File("ball.lwo","wb");
            output.writeData(ball);

            // important!  the file must be closed to flush any
            // remaining data to disc before the call to
            // LoadObject()

            output.close();

            LoadObject("ball.lwo");

            filedelete("ball.lwo");
        }

        @data ball
        070 079 082 077 000 000 039 064 076 087 079 050 084 065 071 083 000 000 000 010
        069 121 101 000 073 114 105 115 000 000 076 065 089 082 000 000 000 018 000 000
        000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 080 078 084 083
        ...
        @end



                                                                                                    
  A new global constant value called SCRIPTID exists in the LScript operating environment.
  This constant holds the full path and filename of the script currently being executed.



                                                                                                    
  The listbox control now has a fourth, optional callback function that allows you to specify
  which entries in the control can be selected by the user.  The select callback function
  should take an integer argument that represents the index of the element being selected,
  and should return a Boolean true/false value to indicate if the element can be selected.

        @version 2.2
        @warnings

        lb_items;

        generic
        {
            for(x = 1;x <= 5;x++)
                lb_items += "Item_" + x;

            reqbegin("Testing List Box");

            c1 = ctllistbox("Items",300,300,"lb_count","lb_name",,"lb_select");

            reqpost();
        }

        lb_count
        {
            return(lb_items.size());
        }

        lb_name: index
        {
            return(lb_items[index]);
        }

        lb_select: index
        {
            // only allow selection of the odd-numbered elements

            return(index & 1);
        }


Behavioral Changes


                                                                                                    
  Listbox controls in LScript are now always multiple-select.  In order to accomodate this,
  certain value changes have been made.

  The argument provided to the "event" function for listbox controls is now either an array
  of indices denoting the current selection(s) in the listbox, or 'nil' if no selections exist.

  The getvalue() return type for listbox controls has become multi-element, with each
  element denoting the index of the selected item.  If no items are selected in the listbox
  when getvalue() is called, then 'nil' is returned.

  The setvalue() function can now accept a number of different data types for setting the
  selection within a listbox.

  Here is a sample script to illustrates the new listbox interface mechanism:

    @version 2.2
    @warnings

    c1;
    lb_items;

    generic
    {
        for(x = 1;x <= 5;x++)
           lb_items += "Item_" + x;

        reqbegin("Testing List Box");

        c1 = ctllistbox("Items",300,300,"lb_count","lb_name","lb_event");
        c2 = ctlbutton("Select",50,"button_event");

        return if !reqpost();

        sel = getvalue(c1);

        reqend();

        if(sel == nil)
            info("No selections were made");
        else
            info("You have selected '",sel,"'!");
    }

    lb_count
    {
        return(lb_items.size());
    }

    lb_name: index
    {
        return(lb_items[index]);
    }

    lb_event: items
    {
        // 'items' is an array of integer index values,
        // or 'nil'

        if(items == nil)
            info("No items are selected");
        else
            info("You have selected '",items,"'!");
    }

    button_event
    {
    //    a = @"Item_2","Item_4"@;
        a = @1,3,5@;
    //    a = 4;
    //    a = "Item_5";

        setvalue(c1,a);
    }



                                                                                                    
  LScript is no longer using the Panels sub-system to generate requesters, but rather is
  now using the LightWave toolkit directly.  This has lead to a change in the
  interpretation of the listbox height value.

  The listbox control used to specify widths in pixels and heights in number of listbox
  entries that should be visible.  However, the height for a listbox now also specifies
  pixels.  Taking the example script provided in the v2.1 release notes, the following
  would produce a listbox that is 300-pixels wide and 10-pixels high in v2.2:
                                                                                                        
    c1 = ctllistbox("Items",300,10,"lb_count","lb_name","lb_event");

  This will need to be updated for use with v2.2:

    c1 = ctllistbox("Items",300,300,"lb_count","lb_name","lb_event");



                                                                                                    
  The compression algorithm used by the LScript run-time system did not function properly
  when compiled file sizes exeeded some threshold.  For this reason, it has been replaced
  with a newer binary-based compression algorithm that functions similarly, achieves
  equitable ratios, and does not appear to be effected by the size of the file.

  The original compression algorithm remains in LScript to support decompression of older
  compiled scripts.



                                                                                                    
  The LightColor() and AmbientColor() Command Sequence functions now expect their arguments
  to be in floating-point format, expressed as 0.0 to indicate 0 and 1.0 to indicated 255.
  You can continue to use integer values between 0 and 255 for individual color components,
  but they must be converted to their floating-point equivalents in the range of 0.0 to
  1.0--i.e., (150 / 255.0)


Bug Fixes


                                                                                                    
  Containers holding arrays were not being cleared completely when new values
  were assigned, leaving phantom pointers to the reclaimed arrays.


                                                                                                    
  Array duplication included an additional memory lock that prevented
  subsequent reclamation.  This caused memory consumption during a script's
  execution when arrays were frequently created and destroyed.


                                                                                                    
  Modeler's new() command dropped it's integer parameter with the release
  of LightWave [6].  LScript has been corrected to adhere to this.


                                                                                                    
  A problem with the logic flow in object processing caused certain data
  members (like 'totallayers') to be unrecognized.


                                                                                                    
  The Tab control created with ctltab() was not receiving the correct
  data type, causing a crash of the application when tabs are altered.


                                                                                                    
  The genus data member of the Object Agent passed to the Item Motion
  create() function always returned zero (0), regardless of the type of the
  object.



                                                                                                    
  The Image Object Agent methods rgbSpot(), lumaSpot() and needAA() were not
  accepting the correct number of arguments.


                                                                                                    
  The LightFalloffType() CS function was incorrectly accepting string arguments.
  It has been corrected to accept integer values between 1 and 4 (1==off).



                                                                                                    
  Point and Polygon data members introduced in v1.4 were lost during the object
  code reorganization that took place in v2.0.  These have been added back to
  LScript.



                                                                                                    
  Variables holding regular expressions (search, or search-and-replaced) could
  not correctly be tested for equality or inequality with other values.