[N-World Contents] [Book Contents] [Prev] [Next] [Index]

N·World is completely extensible. This means that you can define operations for inclusion in the N·World interface which behave in exactly the same fashion as those features which are built in. For example, you can add Geometry Editor Menu items to the N-Geometry interface. You can also define Dynamics Operations, which are executed on a frame-by-frame basis by N-Dynamics.


Extending Dynamics

The Dynamics Philosophy

Dynamics operates on a relatively simple philosophy. Users define actions, which are then executed sequentially over time. When you define your own dynamics operation, you create code which is also executed on a frame by frame basis. You'll also need to integrate your new operation with the Dynamics menu, and provide ways for users to manipulate the parameters which control your new operation.

Inheritance, Dynamic, and Static Values

One of the most useful attributes of Dynamics is the ability to program action along curves. A curve essentially provides a way of changing a parameter over time. Parameters whose values change over time are dynamic. Conversely, parameters whose values do not change are static. Within dynamics, the value of a given parameter might be determined explicitly for that parameter, in which case the value is said to be local. However, values can also be inherited from higher-level channels.


Dynamics Operations

In the following discussion, we'll be making use of a dynamic operation we defined called Random Transform. The listing for this operation appears below. and can also be found in /usr/local/ngc/demo/src/random-mvmt.lisp.

Preparing To Define Dynamics Operations

The basic steps in creating a dynamics operation are:

1. Define your Dynamics Operation function.

Dynamics Operations parameters serve as local variables within the function that defines the operation. Therefore, defining and debugging the operative code of your new operation is necessary before you can know which parameters you'll need to get from the user.

In our example, the operative code consists of three functions:

2. Define the parameters you'll need for your new function

Users will interact with the Dynamics menus to specify values for these parameters. Parameter fields are built on classes, which can be predefined (built-in to Dynamics), or defined by you. These classes control the types of values the fields can accommodate, and also control the behavior of the fields. for example, some types are designed to return N-Geometry objects, others Ftriplets, strings, numbers, color objects, etc.

Our example has five parameters:

3. Define the Dynamics Operation

The definition defines several overall parameters of the operation itself, including its class, its name as it will appear on the Dynamics menus, and which applications it is associated with (its universe). The parameters section defines the fields

Here's the listing for Random Transform. It causes the selected object to move randomly within limits defined by its parameters:

;;; -*- Mode: Common-Lisp; Package: DYNAMICS; -*-

(in-package :geometry)

:======================================================================

;     Functions used in the Dynamic Operation

;======================================================================

;;;random-neg returns either 1 or -1, randomly

(defun random-neg ()

  (if (eq 1 (random 2))

               -1

               1))

(defun clean-range (range)

  (cond ((or (eq range nil)

             (eq range 0))

         1)

        (t range)

        )) 

    

; Random transform generates a temporary transformation matrix (temp-matrix)

; then alters that matrix.  The :move argument to alter-3d-matrix requires 3 args

; which are displacements along each axis. The displacements themselves are calculated 
; with respect to the value specified for range in the Dynamics parameters menu.

; If home is "YES", then the object is returned to its home position before the altered
; matrix is applied to the object, resulting in the object "hovering" around it's home
; position. Otherwise, there are no constraints other than RANGE on the possible position
; of the object.

(defun random-transform (object home x-range y-range z-range)

  (3d::using-transform-matrix ((temp-matrix))

    (let (

;;; These forms set the value of each range to:

;;; 1 if it is 0 originally

;;; the original value multiplied by 1 or -1 returned by (random-neg)

          

          (x (* (random-neg) (clean-range x-range)))

          (y (* (random-neg) (clean-range y-range)))

          (z (* (random-neg) (clean-range z-range)))

          )

;;; alter the temporary matrix by moving it along each axis by the values we just 
;;; generated

      

      (3d::alter-3d-matrix temp-matrix

                           :move (3d::make-ftriplet! x y z))

;;; If home is YES, then move the object back to its home position      

	(if (string-equal home "YES")

          (3d::initialize-transformation object))

      

;;; Then, apply the modified transformation matrix to the object      

	(3d::transform object temp-matrix))))

  

(in-package :dynamics)

;======================================================================

;      Creating the Dynamics class

;          This function creates a class listing in the Dynamics Operation menu.

;======================================================================

(def-dynamic-operation-class 3d::random

    "randomness"

    "Operations to introduce a little chaos into your scripts"

    :geometry

    :dynageometry)

;;======================================================================

;;;		The dynamic operation itself.

;;======================================================================

(dyna::define-dynamic-operation (random-transform

				 :class 3d::random

				 :universe :dynageometry

				 :pretty-name-string "Random Movement"

				 :documentation

				 "Record animation data for export")

    

    ((object              `dyna::object

                            :prompt "Object"

                            :documentation "Select object for randomization")

     (which-axes           `dyna::symbol

                           :prompt "Axes?"

                           :default :all

                           :field-type `ui::multiple-choice-field

                           :field-args

                           `(:subfield-info `((:label "All" :on-value :all)

                                              (:label "Choose" :on-value :choose))

                             :reformat-on-select t)

                           :documentation "Select axes for movement"

                           )

     (axes                `dyna::symbol

                          :prompt "Choose Axes"

                          :default :x

                          :field-type `ui::multiple-choice-field

                          :field-args

                          `(:subfield-info `((:label "X" :on-value :x)

                                             (:label "Y" :on-value :y)

                                             (:label "Z" :on-value :z))

                            :reformat-on-select t)

                          :expose-test (dyna::action-test :which-axes `(:choose))

                          )

     

                           

     (range                `3d::factor

                           :dynamic-p t

                           :prompt "Range"

                           :documentation "Enter range for position to vary by")

     (home                 `dyna::yes-or-no

                           :prompt "Home?"

                           :default :no

                           :documentation "Reinitialize transform for each frame?")

     )

  (format t "axes: ~a which axes: ~a~% " axes which-axes)

 

  (cond (			(string-equal which-axes "ALL") 

			(3d::random-transform object home range range range)) 

        ((string-equal axes "x") (3d::random-transform object home range nil nil))

        ((string-equal axes "y") (3d::random-transform object home nil range nil))

        (t (3d::random-transform object home nil nil range)))

  

  (if (and *last-frame-p*

           (string-equal home "YES"))

      (3d::initialize-transformation object)))

Anatomy of a Dynamics Operation

When users specify operations for dynamics channels, the first thing which appears is the operations class menu. Selecting an operation class results in a menu of operations, as shown in Figure 10.1.

Figure 10.1 Dynamics Select Operation Class & Select Operation Menu

These are not classes in the normal CLOS sense, instead, they serve an organizational function within the Dynamics menus. You can add your operations to existing classes, or add your own.

Choosing an operation adds a channel with that operation to the current script.

Defining Dynamics Operations Classes

You can define a new class of Dynamics Operation with DYNA:DEF-DYNAMIC-OPERATION-CLASS macro, which has the following general form:

	(dyna:def-dynamic-operation-class symbol-for-class pretty name documentation category
universe)

In our example, a class called randomness is defined:

(def-dynamic-operation-class 3d::random

    "randomness"

    "Operations to introduce a little chaos into your
scripts"

    :geometry

    :dynageometry)

Because Lisp is a dynamic environment, your new class will be available in the Dynamics menus as soon as you compile your code.

Dynamics Classes Utilities

The global variable dyna::*known-operation-classes* is a list of all currently defined Dynamics Operations classes. Describing a class yields all the information you're likely to need to add an operation to that class. For example,

(describe (first dyna::*known-operation-class*))

returns

#<DYNAMIC-OPERATION-CLASS @ #x126b7fe2> is a structure of type DYNAMIC-OPERATION CLASS. 
It has these slots:

				 NAME-SYMBOL        :BASIC-FUNCTIONS

				 PRETTY-NAME-STRING  "Basic Functions"

				 MOUSE-DOC-LINE     "Menu of basic programming operations."

				 CATEGORY           :DYNAMICS

				 UNIVERSES          :DYNALISP

You can find a specific class using DYNA::FIND-DYNAMIC-OPERATION-CLASS. So, to find the random class we defined in our example:

(dyna::find-dynamic-operation-class `random)

which returns:

#S(DYNAMIC-OPERATION-CLASS							:NAME-SYMBOL RANDOM :PRETTY-NAME-STRING "randomness"

							:MOUSE-DOC-LINE "Operations to introduce a little chaos into
your scripts"
:CATEGORY :GEOMETRY

							:UNIVERSES :DYNAGEOMETRY)

(assuming, of course, that you've compiled that operation). Of course, you can use dyna::*known-operation-classes* to find the name symbol for any defined class.

Controlling Input with Parameters

You'll use parameter fields to provide a way for users to interact with your dynamic operations. Each field type is designed to bind a variable to an object of a specific type. Field-types map to Dynamics parameter classes (this time we mean classes in the CLOS sense). There are many built in parameter classes, and you can also define your own.

To define a parameter field type, you need to define a class and a field-type for the parameter type. N-Dynamics parameter types map directly to UI field types, and accept many of the same parameters as UI field types. In this example, we'll define a new class which allows users to select more than one object:

(defclass 3D-OBJECTS-FIELD (ui::object-field)

    ()

	 ( 	:default-initargs 

		:documentation (ui::make-three-part-who-line "L: Choose 3D objects.")))

;; 

(defmethod UI::SELECT-METHOD((self 3D-OBJECTS-FIELD) mx my buttons)

  (declare (ignore mx my buttons))

  (let ((val (rest (3d::choose-objects t))))

    (when val 

      (setf (ui::field-value self) val)

      (dolist (obj val)

        (dyna::register-3d-object obj))  ; defined below until 3d obs are ext obs

      (ui::draw-field self)

      (ui::make-visible self)

      )

  ))

Once your parameter classes are defined, you can map field-types to your classes with DYNA:DEFINE-FIELD-TYPE:

(DYNA:DEFINE-FIELD-TYPE (field-type class-type &OPTIONAL
field-init-args)

So for our choose-objects class:

(define-field-type `3d-objects-field `3d-objects)

To use the new type in a Dynamic Operation definition, refer to it by it's short name, `3d::objects. For example:

(objects					`3d-objects

					:prompt "Object"

					:documentation "Select an Objects"

Built-in Dynamics Parameter Field Types

N-Dynamics includes many predefined field types, summarized in Table 10.1. Figure 10.2 and Figure 10.3 show how each field looks.

Table 10.1 Dynamics field types
Dynamics Field Type Comments Returns
`symbol

Returns a symbol or a string

A string

`yes-or-no

Creates two buttons, labelled "Yes" and "No".

A string, either "YES" or "NO"

`object

Holds Geometry objects

An object

`attribute-set

Produces a pop-up listing of all currently defined materials.

A material.

`light-object

Produces a pop-up listing of all lights currently loaded into Geometry

A light object

`trajectory-object

Produces a pop-up list of all trajectory objects loaded into geometry

A trajectory object

`3d::angle

Accommodates an angle

A single float

`3d::factor

Accommodates a factor

A single float

`3d::displacement

Accommodates a defined displacement

An object of type locus-state

`spot-light-object

Produces a pop-up list of spot-lights loaded into geometry

A spot-light object.

`3d::skeleton

Produces a pop-up list of skeleton objects loaded into Geometry

A skeleton object

transformation

Accommodates a transformation value.

Returns a transformation value.

`color

Produces a color-editor pop-up menu

An object of type RGB-COLOR

`numeric-inheritable-property

Accommodates a number

A number

`3d::ftriplet

Accepts (requires) three numbers

An ftriplet

`3d::fquad

Accepts (requires) four numbers

An fjord

`3d::quaternion

Accepts (requires) four numbers

A quaternion

`3d::axis-for-object

Accepts (requires) three numbers

A list of the three numbers (c.f. ftriplet)

`3d::xyz-triplet

Accepts (requires) three numbers

A list of three numbers

`doublet

Accepts two numbers. If only one is entered, the second value defaults to the first.

A list of two numbers.

`attribute-domain

Produces a pop-up list of attribute domains

An attribute domain.

`string

Accepts a string

A string (simple-array character).

Figure 10.2 N-Dynamics Field types

Figure 10.3 More N-Dynamics field types

Setting Parameter Type Defaults

You can define global defaults for all parameters of a given type with DYNA:DEFINE-GLOBAL-DEFAULT-FOR-TYPE. For example, the following form sets up a default of 0.0 for all instances of parameter type numeric-inheritable-property.

				(define-global-default-for-type numeric-inheritable-property 0.0)

Parameter Type Slider Defaults

Many parameters can be modified using a special dialog, the Dynamics Slider (Figure 10.4).

Figure 10.4 The Dynamics slider

You can define default parameters for slider dialogs used to edit parameters for your operations. These parameters are defined as keyword arguments to DYNA:DEFINE-SLIDER-PARAMETERS-FOR-TYPE, which has the following general form:

(DYNA:DEFINE-SLIDER-PARAMETERS-FOR-TYPE type &REST plist)

Dynamics sliders have six default parameters, summarized in Table 10.2

Table 10.2 Dynamics slider parameters
Parameter Description
:min-value

The absolute minimum value possible for the slider.

:max-value

The absolute maximum value possible for the slider

:low-offset

The minimum value to be displayed by the slider by default

:high-offset

The maximum value to be displayed by the slider by default

:digits

The precision of the value contained by the slider

The slider can express an absolute range of values limited by :min-value and :max-value. When it first appears, the slider may be configured to show only a subset of this absolute range, as specified by :low-offset and :high-offset.

Defining Parameters

Once you've defined types, fields, and slider defaults for your parameters, you need to define parameter properties (parameter parameters, if you will). These are defined within the dyna:define-dynamic-operation form with the parameters themselves. Parameter properties are summarized in Table 10.3.

Table 10.3 Parameter properties
Property Options Description
:make-visible

t or NIL

If t, ensures that an object is visible before executing operation

:initialize-transformation

t or NIL

If t, initializes object transformation matrix before executing operation

:dynamic-p

t nil

If specified, the parameter can be dynamic, or change over time. Otherwise, value remains constant over the length of a script. Values of dynamic properties can be set with curves.

:dynamic-default

:static

If specified, the value can be dynamic, but is constant by default.

:documentation

<string>

A string explaining the parameter which appears on the mouse doc line

:default

<value>

A default value for the parameter

:nil-ok-p

t

If t, then the parameter can be undefined (nil).

:field-type

<field-type>

The UI field type, if not specified with dyna:define-field-type.

:expose-test

function or lambda list

The expose test determines whether a field will be made visible in the menu or not, based on the return value of the function or lambda list.

:field-args

<args>

Arguments appropriate to :field-type, if specified.

:prompt

<string>

A label for the parameter in the Edit Action Properties menu. If not specified, the parameter name will appear as the label

For example, a typical parameter definition might look something like this:

(number 	'numeric-inheritable-property

		     :prompt    "Number"

		     :nil-ok-p  t

		     :dynamic-p t)

This parameter definition results in a field in the Edit Action Properties menu like the one in Figure 10.5.

Figure 10.5 Example parameter field

There is no value field in this example, because the parameter is defined as dynamic. However, a (click-r) on the source field brings up a pop-up menu which will allow the user to change to source of this parameter. Obviously, if :dynamic-p t is not specified, then the parameter cannot be dynamic under any circumstances.

Earlier we defined a global default for numeric-inheritable-property, 0.0. You can override this default for a specific parameter with the :default keyword argument, e.g.

(number 'numeric-inheritable-property

	     :prompt    "Number"

	     :nil-ok-p  t

		:default 1.0

		:dynamic-p t)

In much the same way, specifying :dynamic-default :static means that the parameter can be dynamic, but is static by default. For example,

(number 'numeric-inheritable-property

		:prompt    "Number"

		:nil-ok-p  t

		:default 1.0

		:dynamic-p t

		:dynamic-default :static)

Controlling Program Flow

There are several utilities you can use to manage the behavior of your Dynamics operations. For example, in Random Transform we used the *last-frame-p* predicate, which returns t when an animation reaches the last frame. Other predicates are listed in Table 10.4.

Table 10.4 Dynamics Predicates and Variables
Symbol Function
*first-frame-p*

Returns t when first frame is the current frame.

*last-frame-p*

Returns t when the last frame is the current frame.

*animating-p*

t when an animation is underway.

*initial-frame*

The initial frame of a script

*selected-time*

The position in time of the recording cursor on the timeline

*default-frame-rate*

The default frame rate

*current-time*

The current time in a script

*current-frame-number*

The current frame number

*last-animated-frame*

The preceding frame animated.


Extending Geometry

The N-Geometry window is basically a 3D object editor. When you (SHIFT-L) on on element in the N-Geometry editor, the menus which appear are specialized for the selected element. For example, transformation options never appear when you've selected a segment, and cut is an inappropriate choice for an object. These specialized menus and their behavior are defined with edmethods.


Understanding Editor Methods

The N-Geometry 3D object editor is completely extensible. You extend the editor by defining new methods called edmethods, and adding them to the Geometry editor menus. Because edmethods are specialized on Geoclasses, they automatically appear in the editor menus when the user has selected an object or element of an object relevant to the method.

The basic steps in defining a new edmethod are:

GeoClasses

Every Geometry element class, polyhedra, segments, vertices, etc., has GEOCLASS as its metaclass. Slots in the GEOCLASS determine (among other things) whether a given class can be edited in the Geometry window. Classes having geoclass as their metaclass are defined using (defgeoclass).

(defgeoclass (name superclasses slots &rest options))

With the exception of the options, all the arguments to defgeoclass are the same as for defclass. Some of the more important options are:

For example, we can create a subclass of vertex called my-vertex, which is not editable:

(defgeoclass MY-VERTEX (vertex)

  ()

  (:editable-p nil)

)

However, because my-vertex is a subclass of vertex, I can make all of the editing operations available for vertex available to my-vertex by setting editable-p to t.

If a geoclass itself contains elements which are themselves editable, these can be specified as a list with the :editable-elements option. For example, polyhedron is defined with (:editable elements vertex edge face).

Geoclass Utilities

(FIND-GEOCLASS (SYMBOL &OPTIONAL (ERRORP T))

This function has the same functionality as (find-class) but is restricted to geoclasses. For example, to find the geoclass skeleton:

(find-geoclass `skeleton)

which returns

#<GEOCLASS SKELETON>

(BODIABLE-GEOCLASSES())

This function returns a list of all geoclasses for which :bodiable-p is t.

(EDITABLE-GEOCLASSES ())

This function returns a list of all editable geoclasses (those for which :editable-p is t).

The Editor Menu Interface

Operations in the Geometry editor menus are divided into logical groups called edcategories. Operations themselves are represented by ed-menu-items.

Figure 10.6 Geometry Editor menus

Ed-categories are constructed with DEF-EDCATEGORY:

(DEF-EDCATEGORY (NAME &OPTIONAL PRETTY-NAME DOCUMENTATION))

Available ed-categories are:

:TRANSFORM 

:DISPLACEMENT 

:GEOMETRIC 

:EXTRUSION 

:SUBDIVISION 

:TOPOLOGIC 

:GENERATOR 

:SELECTOR 

:FIXUP 

:MISCELLANEOUS 

Editor Menu Items (edmenu-items)

The operations themselves are represented by edmenu-items. An edmenu-item corresponds to one item in the Editor menus. In other words, the various CUT operations (for wires, faces, segments, etc.) are all represented by a single edmenu-item.

Use DEF-EDMENU-ITEM to define a new edmenu-item:

(def-edmenu-item (name category menu-item-name 
&optional insert-point)

Edmenu-item Utilities

(FIND-EDMENU-ITEM (SYMBOL &OPTIONAL (ERRORP T)))

Returns an edmenu-item, given a symbol which evaluates to an edmenu item. For example,

3D(22): (find-edmenu-item `cut)

#<EDMENU-ITEM CUT>

(FIND-EDMENU-ITEM-BY-MENU-ITEM-NAME (NAME)

Returns an edmenu-item, given the name-string of the item. For example, to find the edmenu-item for Axis Move:

3D(23):(find-edmenu-item-by-menu-item-name "Axis Move")

#<EDMENU-ITEM AXIS-MOVE>


Defining Editor Methods (edmethods)

Now that we know how to integrate our new methods with the Geometry Editor interface, we're ready to actually create a usable edmethod. Of course, we use DEFEDMETHOD to do so:

(defedmethod name arglist ((edmenu-item handler &optional 
mouse-button include-classes exclude-classes) &rest
options) &body body)

So, for example, to define a new editor method called MY-CUT:

(defedmethod MY-CUT (bdis&elements)

		((my-cut my-cut L))

		"An example defmethod"

The string at the end of the form is a documentation string, and will appear on the mouse doc line when the cursor is over the edmenu-item linked to this method.

Understanding bdis&elements

Nearly all editor methods accept a list of bdis and elements associated with the currently selected elements. Parsing this list allows for a method to determine which objects and bodies to operate on, and helps you to detect situations (such as elements selected from two different bodies) where your method may not be appropriate.

The (get-selected-el-alist *camera*) function returns the bdis&elements list for selected elements. The list is sorted in bdi order. For example, if I select two faces from two objects in the geometry window:

Figure 10.7 Two faces selected from two objects

then evaluate (get-selected-el-alist *camera*):

3D(23): (get-selected-el-alist *camera*)

((#<BDI (Octahedron) @ #x196ccf0a> #<FACE 1> #<FACE 5>)

(#<BDI (Cube) @ #x196c5832> #<FACE 3> #<FACE 1>))

Using the bdis&elements List

The following code demonstrates how to use the bdis&elements list to check the element list passed to your method. In this case, the loop-applying-operation form looks through the list to determine whether or not multiple faces have been selected:

(when (loop-applying-operation (bdis&elements `cut-face bdi) (op el elist)

			(:prefer-compound-op t

				:extra-args    ((cdr (assoc bdi seglist)))

				:return-vals   (newf newe)

				:post-op-forms (setq 						*modified-faces* (append elist newf)

										*modified-edges* (append (collect-my-segments elist)

                                                                 newe))))

            (unlock-elements self nil)

            `cut-face)

A Sample Edmethod

The following is a complete example edmethod, specialized for a face. The method accepts a numeric argument, then divides the selected face into the specified number of faces.

(DEF-EDMENU-ITEM MULTI-CUT-FACE

    (:subdivision :main) "Multi-Cut")

    

    

(defedmethod ED-MULTI-CUT-FACE (bdis&elements)

  ((multi-cut-face multi-cut-face L ))

  "Make multiple division of face between edges"

  

  (with-slots (cached-elements) self

			(let* (		(el      cached-elements)

					(seglist 			(sel-elements

								(select-n-elements self 2 `edge el nil "to cut between.")))

					(pt1     (first seglist))

					(pt2     (second seglist))

					(n       4)

					)

          (declare (special n))

          (unless (or (< (length seglist) 2) (eq pt1 pt2))

            (3d-cvv-choose "Number of faces" `((n "# of Faces?" :integer)))

            (funcall-with-history #'multi-cut-face el seglist n) t)))

  )

(defmethod MULTI-CUT-FACE ((self face) segments n)

(

		.......Your implementation here.....

)


Geometry User Interface Utilities

N-Geometry has a specialized suite of user-interface tools. Known as cvv forms, these tools provide powerful and flexible tools for you to use when interacting with the user via your edmethods. In the above example, we used (3d-cvv-choose), which produces a dialog box like this:

Figure 10.8 3d-cvv-choose dialog box

CVV UI tools are built on the basic UI toolkit, but offer an enhanced level of encapsulation. For example, in this example, the :integer keyword defines the type of the field. No need to create a number field within a root window. Though by no means exhaustive, the following list shows some of the more useful types returnable with 3d-cvv-choose. Remember that the value returned by the interface element of a 3d-cvv-choose dialog is bound to a variable, not returned by the function. The CVV function itself returns several values, the first of which is either :exit (when the user clicks on Do It), or :abort (when the user clicks on Abort).

Table 10.5 3D-CVV-CHOOSE types
Argument Comments
BOUNDS-SOURCE-FOR-MAPPERS

Creates choose-object dialog, labelled appropriately

WIRE-OBJ

Creates choose-object dialog.

GEO-OBJECTS

Creates choose-objects dialog

TERMINAL-OBJECT

Creates choose-objects dialog, limits display to terminal objects

GEO-OBJECT

Creates choose-object dialog, any geo-object legal

LIGHT-OBJECT

Creates pop-up list of light-objects

LIGHT-GROUP

Creates a pop-up list of light-groups

AXIS

Creates a choose-axis pop-up menu

IMAGE-TYPE

Requires specialization, e.g. :image-type :rgb

LIGHT-GROUP-PATHNAME

Creates a choose-light-group pop-up, returns pathname to selected group.

PALETTE-COLOR

Creates a color-palette, returns the selected color.

FILE-NAME

Creates a text-field.

PROJECT

Creates an N·World choose project or directory pop-up.

FLOATING-TRIPLET

Accepts and returns an ftriplet

FLOATING-DOUBLET

Accepts an fdoublet

SLIDER

Creates a slider.

KEYPAD-NUMBER

Creates a numeric keypad.

INVERTED-CHECK-MARK

Creates checkmark field, sets variable to NIL when checked, T when not checked (hence "inverted")

CHECK-MARK

Creates checkmark-field, sets variable to T when checked.

REVERSE-SWITCH

Creates an on-off toggle field, with ON first. Returns T when ON selected.

SWITCH

Creates an on-off toggle field, with OFF first. Returns T when OFF is selected.

BOOLEAN

Creates yes-no toggle field. Returns T when yes selected.

STRING

Accepts a string.

NO-SELECT

No selection. Use for alerts, confirms, etc. Does not bind variable, but returns T when Do-It selected, nil



[N-World Contents] [Book Contents] [Prev] [Next] [Index]

Another fine product from Nichimen documentation!

Copyright © 1996, Nichimen Graphics Corporation. All rights reserved.