Contents | < Browse | Browse >

/// Bountiful Bevelled Buttons
    By Andrew Porter

 | ountiful                      __________________________
 |O/  _                       An |_________________________/|
 |  | evelled        Automated ||                         ||
 |O ||O/  _               Button ||           By            ||
 |_/ |  | uttons       Library ||      Andrew Porter      ||
     |O ||O/             for the ||||
     |_/ |             Director ||_________________________||
         |O |          Version 2 |/_________________________|

*** The Tool & Goal ***

     The Director Version 2 is a powerful text based authoring
system for creating interactive multimedia presentations, slide
shows and animations. Yet, the strength of the program is also
its weakness. Although the process is easy, it needs some
programming skills and careful attention to details. One area
that could be streamlined is button creation for interactive

     Professional looking multimedia presentations usually have
3D bevelled buttons that are not hard to create but can be time
consuming create. The Director has a "Button Utility" to use with
pre-drawn graphics but no built-in button creation features...
yet, it does have a full list of graphic capabilities. The
following is an explanation of how to develop a button "library"
that will allow you to create a 3 dimensional looking bevelled
button within your Director script. The command will position,
size and colour a bevelled button and centre a text label on it.
You can even have an optional "button hole."

     For those who don't use the Director as their authoring
system the BASIC language source could be easily translated to
the language of your choice. It could even be adapted for use
with ARexx capable paint & draw programs.

     As you know, on-screen buttons are the main way to
navigate through an interactive presentation. Normally, with the
Director, an author would use a paint program to draw buttons,
save the image(s), and then load it into the Button Utility to
mark out the hotspot locations. This is an easy, largely
automated process.

     Yet, there are a few potential problems with this method. If
you have many different screens of buttons, each one takes up
valuable disk space and waiting for it to load can slow down the
presentation. Also, using a paint program to draw buttons can be
time consuming and tedious, especially if you want to make many
revisions. The solution?  Use the graphic capabilities of the
Director to render the buttons for you.

     To render buttons on screen you could simply make a
rectangle and stick some text on it, though it wouldn't look very
elegant or professional. A powerful feature of the Director is
the external library. A library is frequently used pieces of
code that can be called up in any script with just a few
commands. The MakeButton command described here will render
buttons of any size at any location on any screen format. The
size of the bevel, the location of the text, the colours and
almost any feature can be modified with a few quick numbers.

*** The Essence of Buttonness ***

     To get the impression of 3 dimensions, a button can have
light and dark areas around it that provide the illusion that it
is raised out from the screen. The bevelled look requires some
work because there are five facets (or sides) that include the
button top area, (the part that would be pressed) and four
trapezoid "sides" (two parallel lines joined by angled lines)
that appear to slope up from the screen surface to the edges of
the button top. Shading of the sides, or bevels, is done
according to an imaginary high, leftside light source. The bevels
on the top and left are brighter than the right and bottom
bevels. The use of colour and shades is what gives a button its

     Generally, the thicker the bevels the "higher" the button
appears (but, if the bevels get too large they loose the
illusion.)  Also, bevels usually appear equal on all sides, as if
the button was looked at straight-on. One way to enhance the
look of a button is to place it in a "buttonhole," such as a
bevelled frame around the button with a slight gap between. This
gives the impression that the button is mounted on the screen and
inlaid into it. Usually the buttonhole bevels have the opposite
colour scheme to make it appear to be further away instead of
nearer. An author must have control over the thickness and
colour of button and hole bevels and the size and colour of the

     Buttons without a label or picture would be quite useless.
Therefore, to note their function, buttons must have text or
pictures on them. For aesthetic reasons this information
probably should be centred or positioned in some way and should
appear to be apart of the button, ie. text should be constrained
to the button and wrap around inside it if needed. The author
also should be able to control the font, colour, indentation of
margins and other attributes of the text.

*** A Button Library ***

     In general, an multimedia author needs to be concerned about
the three basic categories of location, size and colour.
Location includes the location of the button and the location of
the text within the button. Size is the size of the button, its
bevels, font size, and, if there is a buttonhole, the size of the
buttonhole gap and bevels. Colour includes the colour of button
elements and arrangement and text style and colour.

     When developing a presentation an author will often have
one consistent style for the whole work and will only need to be
concerned with the button size, location, and label. Everything
else could be set once by default or a configuration setup.

     Presented here, the Button Library has four main user
commands:  "MakeButton" takes care of positioning, sizing and
labelling; "ButtonConfig" sets up bevel sizes and the existence
of a ButtonHole; "ButtonColour" sets the colours for all the
various parts; and "ButtonText" sets the font type and some text
attributes. There is also a command called "ButtonReset" to
restore the default values. Only MakeButton actually does
anything, the others simply assign variables. There are also
several other procedures in the library that are not directly

*** The MakeButton Command ***

     There are several ways to render bevels. One way is to
create the outline for each facet by drawing a line from one
point to another, resulting in a closed graphic, and fill it in
with the appropriate colour. This is similar to how it would be
done in a paint program. The Director has a built-in feature
that can do this more efficiently. Using the POLYGON command all
you have to do is feed the coordinates for each facet and the
program will render it. After doing this five times you have a
bevelled button.

     Of course, you can't input any coordinates that you want,
you have to be systematic. A bevelled button is composed of two
rectangles, one inside the other for a total of eight corners or
points. The bevel ends are formed by drawing a line from one
inside point of the large rectangle to an opposing outside point
of the smaller graphic. All the points have a relationship to
each other by being equal, less or greater in value than the
others, depending on the location.

     The MakeButton command uses the left/top corner coordinates
and the width and height of the button. A button that originates
at location 10,10; is 50 pixels wide and 25 pixels high and says
"Press Me" would use the command: DO MakeButton, 10, 10, 50, 25,
"Press Me". MakeButton uses the PARAMETER command to grab the
coordinates. It knows that the first two numbers represent the
location of the top corner (10,10) and the second two are width
and height (50,25). These values represent the outside edges of
the larger rectangle. The default thickness for bevels is 5
pixels, so the small inner rectangle can be calculated because it
is 5 pixels smaller on all sides.

     I mentioned that there are a total of eight points to be
calculated. I have numbered these points P1 to P8 going
clockwise around and in from the left/top corner. The math is
very easy but a diagram explains it better than I can:

  x = the starting x coordinate (left)
  y = the starting y coordinate (top)
 p# = the two x & y coordinates
p#x = the x coordinate of the p# point
p#y = the y coordinate of the p# point
 bx = the bevel width
 by = the bevel height

  p1 _________________ p2   Outer Rectangle
    |_______________/|     p1 = x & y
    ||p5           p6||     p2 = (x + width) & y
    ||               ||     p3 = (x + width) & (y + height)
    ||               ||     p4 = x & (y + height)
    ||               ||
    ||               ||     Inner Rectangle
    ||p8___________p7||     p5 = (p1x + bx) & (p1y + by)
    |/_______________|     p6 = (p2x - bx) & (p2y + by)
  p4                   p3   p7 = (p3x - bx) & (p3y - by)
                            p8 = (p4x + bx) & (p4y - by)

               The inner rectangle is calculated by using
               the values in p1,p2,p3 & p4 and adding or
               subtracting the bevel width or height, as required.

     When calculating the coordinates, all values are in relation
to the origin that is considered temporarily to be 0,0 or the top
corner of the screen. This way the image could easily be moved
to any location on the screen. After completing the calculations
for the eight points the values are recorded in a 2 dimensional,
8 element array called "PointList". An array is a group of variables
accessed by a number instead of a name. When finished, we have the
relative location for all the points.

     The next step is to draw the polygons. As I mentioned, an
array stores the eight points for the button numbered 1 to 8. To
draw each facet all that needs to be done is pass the point
number and colour to the POLYGON command for rendering. We are
not passing the actual coordinates, only its location in the
PointList array. We do this five times: the button top and four

     If a ButtonHole is to be drawn then it is be done first,
before drawing the button, using the same method as above. The
only difference is that the size has to be calculated to be
larger than the button, it also has inverted colours.

     I should note that there is an internal procedure charged
with the dual purpose of setting bevel and gap variables and
adjusting for the screen format. Amiga screen formats have
different pixel aspects (the ratio of width to height) and can
distort images if not dealt with. Hires and Lores screen pixels
are almost square but Medres (640x200) and Interlace (320x400)
are double-high and double-wide, respectively. The Button library
will adjust for this distortion for the bevels so they will
appear to be the same thickness on all sides, regardless of
screen display format.

    The last deed to be done is button labelling. All that is
required here is to calculate the margins of the button and use
an FTEXT command to write the label. The PointList array,
mentioned earlier, provides the margins that are then adjusted
for screen location and indentation. The result is that the text
will always wrap, left to right, in the button area. The
formating codes are inserted into the text string for use with
FTEXT. FTEXT outputs formatted text that can include colour,
font, style and justification changes. Therefore, the author can
use special codes to highlite the text.

    The centre of the from top to bottom is calculated and is
then adjusted for the font height. If the author wants to have it
higher or lower then she or he can modify the FontHeight
parameter accordingly. With this feature the button library is
not limited to buttons, it also could be used to display text.

    The source for this library may look long but if you use
buttons frequently you probably will find that the effort to
type it out is worth the convenience it provides. One word of
warning:  unlike ARexx, the Director is CASE sensitive for
variable and procedure labels. When you type it out be VERY
careful to follow any mIXeD CAsE names. You also will note that
many variables have a "b" at the beginning. This is to protect
against name duplication within your script which could have
unexpected results. When you are finished save it as

*** Button Things Up! ***

    How to do you use this library?  There are a couple steps
but it isn't too difficult. The first thing is to put INCLUDE
Director:library/Button.dlib" in your script, usually at the
top. To get a default button type:

    DO MakeButton,<Xpos>,<Ypos>,<Width>,<Height>,<"Comment">
Then you have to set up the hotspot by adding the same
position/size parameters to your buttonlist array (see Director
manual, P11-3).

    To change bevel thickness or the existence of a buttonhole
type:   DO ButtonConfig,<BevSize>,<HoleBev>,<GapSize>,<Adjust>

BevSize is the bevel thickness, HoleBev is the buttonhole bevel
thickness & GapSize is the size of the gap. If HoleBev and
GapSize are both 0 no ButtonHole is drawn. Adjust turns screen
format adjustment OFF (0) or ON (1).

    To change the colour you enter:
    DO ButtonColours, <Top>,<Hilite>,<Shade1>,<Shade2>,<Shade3>,

Each parameter is a colour palette number. Top is the button
colour, Hilite is the top bevel, Shade1 to Shade3 are
respectively the right-side, bottom and left-side bevels, Dark is
the gap colour, Text is the text colour and TextBG is for the
text shadow.

    To modify the text configuration use the command:
    DO ButtonText, <FontNum>, <FontHeight>, <ShadowX>,
       <ShadowY>, <LMargin>, <RMargin>, <Justify>, <Centre>

FontNum is a loaded font from 1-9, 0 makes no changes and 10
resets to default system font. FontHeight is the height in pixels
for the font, or the number of pixels text is to be offset from
the centre (divided by 2.)  ShadowX & ShadowY are the text
background offset in pixels (NONE if 0). LMargin & RMargin are
the margins within the button. Ypos is the number of pixels down
from the top edge (will approximate the centre if 0), Justify and
Centre will each turn justification or centring ON (1) or OFF (0).

    The script called ShowButtons shows how to use the button
library. Like most things, the best way to learn is to play
around. Enhancements of this library could include changable
text, rounded edges, automatic brush placement, display effects,
animation, etc. You could create a utility to save IFF pictures
to modify renderings in paint programs. Also, modification of the
Button Utility, that is included with the Director, could allow
you to interactively draw buttons, similar to a draw program. The
possiblities are almost endless if you want bountiful bevelled

Copywrite 1993 Andrew Porter
ImagEYE Creations

;*** NOTE *** *** NOTE *** *** NOTE *** *** NOTE *** *** NOTE ***
;SAVE the following as "Director:Library/Button.dlib"
;Upto the next NOTE
;*** NOTE *** *** NOTE *** *** NOTE *** *** NOTE *** *** NOTE ***

;* Button Library    *
;* 1993 Andrew Porter, ImagEYE Creations *

  GOTO SkipButton  : REM Skip library

  REM Make Bevel Buttons
  IF bSetup <> 1
    DIM bButtonText[180]  : REM Records button label
    DIM bPointList[8,2],2 : REM Records button coordinates
    DIM bPolyAry[9,2],2   : REM Records polygon coordinates
    bSetup = 1  : REM Mark that arrays are setup
  REM Get button location, size and text
  PARAMETER bButLeft,bButTop,bButWidth,bButHeight,bButtonText$
  REM Setup default colours, configuration and text format
    IF bSetConfig<>1 THEN DO ButtonConfig,5,3,2,1
    IF bSetColours<>1 THEN DO ButtonColours,14,1,2,3,4,0,1,0
    IF bSetText<>1 THEN DO ButtonText,0,9,0,0,5,5,0,1
  DO bScreenAdjust        : REM Adjust for pixel aspect
  REM Draw a button hole when bevel OR gap is given
    IF (bHoleBevelX>0)|(bGapX>0) THEN DO bButtonHole
  REM Calculate the bevel coordinates
    DO bCalcBevel,bButLeft,bButTop,bButWidth,bButHeight,bButBevX,bButBevY
  REM Draw bevelled button
    DO bMakeBevel,bHiLite,bShadow2,bShadow3,bShadow1,bButtonClr
  REM Put a label on button
    DO bButtonLabel

  REM Resets button defaults
    DO ButtonConfig,5,3,2,1
    DO ButtonColours,14,1,2,3,4,0,1,0
    DO ButtonText,0,9,0,0,5,5,0,1

  REM Assign button defaults
    PARAMETER bButBev,bHoleBev,bGap,bAdjust
    bSetConfig = 1        : REM Button defaults set

  REM Assign button colours
    PARAMETER bButtonClr,bHiLite,bShadow1,bShadow2
    PARAMETER bShadow3,bDark,bTextClr,bDropColour
    bSetColours = 1       : REM Colour defaults set

  REM Assign text configuration
    PARAMETER bFontNum,bFontHeight,bShadowX,bShadowY
    PARAMETER bLMargin,bRMargin,bJust,bCentre
    bSetText = 1 : REM Text defaults set

  REM Adjust for current screen pixel aspect
  REM so bevels will appear equal on all sides
  RESOLUTION outbuffer,bXres,bYres,bDepth
  REM All sides are equal
    bButBevX = bButBev       :   bButBevY = bButBev
    bGapX = bGap   :   bGapY = bGap
    bHoleBevX = bHoleBev     :   bHoleBevY = bHoleBev
  IF bAdjust <> 1 THEN RETURN
  IF (bXres >= 640) & (bYres < 400)
    REM Buffer is likely MedRes, make pixels double wide
    bButBevX = bButBev * 2
    bGapX = bGap * 2
    bHoleBevX = bHoleBev * 2
  IF (bXres < 640) & (bYres >= 400)
    REM Buffer is likely LoRes Interlace, make double high
    bButBevY = bButBev * 2
    bGapY = bGap * 2
    bHoleBevY = bHoleBev * 2

  REM Draw button hole for buttons which has inverted colour
  REM Use outside edge of button to determine size
    bHoleLeft = bButLeft - bGapX - bHoleBevX
    bHoleTop =  bButTop - bGapY - bHoleBevY
    bHoleWidth =  bButWidth+(bGapX * 2)+(bHoleBevX * 2)
    bHoleHeight =  bButHeight+(bGapY * 2)+(bHoleBevY * 2)
  REM Calculate bevel for button hole
    DO bCalcBevel,bHoleLeft,bHoleTop,bHoleWidth,bHoleHeight,bHoleBevX,bHoleBevY

  REM Pass inverted colour scheme to button hole
    DO bMakeBevel,bShadow3,bShadow1,bHiLite,bShadow2,bDark

  REM Calculate inside bevel co-ordinates
  PARAMETER bLeft,bTop,bWidth,bHeight,bBevelX,bBevelY
  REM Set origin at Left, Top corner of button
  bPolyAry[1,1] = bLeft,bTop
  REM Build point list starting top/left, clockwise & in.
  bPointList[1,1] = 0,0
  bPointList[2,1] = bWidth,0
  bPointList[3,1] = bWidth,bHeight
  bPointList[4,1] = 0,bHeight
  bPointList[5,1] = bBevelX,bBevelY
  bPointList[6,1] = (bWidth-bBevelX),bBevelY
  bPointList[7,1] = (bWidth-bBevelX),(bHeight-bBevelY)
  bPointList[8,1] = bBevelX,(bHeight-bBevelY)

  PARAMETER bTopClr,bRightClr,bBottomClr,bLeftClr,bDisplayClr
  REM Draw each facet by passing point number & cols
  DO bDrawBevels,bTopClr,1,2,6,5     : REM Top bevel
  DO bDrawBevels,bRightClr,6,2,3,7   : REM Right bevel
  DO bDrawBevels,bBottomClr,8,7,3,4  : REM Bottom bevel
  DO bDrawBevels,bLeftClr,1,5,8,4    : REM Left bevel
  DO bDrawBevels,bDisplayClr,5,6,7,8 : REM Button area

  REM Draw the bevelled button
  bPolyAry[2,1] = 100,100
  bPolyAry[4,1] = 4
  PARAMETER bColour,bP1,bP2,bP3,bP4
  bPolyAry[4,2] = bColour
  REM Get point values from point numbers
  bPolyAry[6,1] = bPointList[bP1,1],bPointList[bP1,2]
  bPolyAry[7,1] = bPointList[bP2,1],bPointList[bP2,2]
  bPolyAry[8,1] = bPointList[bP3,1],bPointList[bP3,2]
  bPolyAry[9,1] = bPointList[bP4,1],bPointList[bP4,2]
      POLYGON bPolyAry

  REM Convert numbers to characters & retain all digits
  PARAMETER tNumber,tPlaces
  DIM convnum[13]
  DIM tChar[2]
  tDecimal = 1
  FOR tCount = 1 TO (tPlaces-1)
    tDecimal = tDecimal * 10
  FOR tCount = 1 TO tPlaces
    tTempVal = tNumber/tDecimal
    tDigit = tTempVal
    tDigit = tDigit - ((tTempVal/10)*10)
    convnum$[tCount] = tDigit
    tDecimal = tDecimal/10
    tOld = tDigit

  DIM bBText[200]      : REM Set up transfer string array
  REM Convert colour num to 2 characters, returns convnum$
  DO bConvNumber,bTextClr,2
  STRING "|c";convnum$,bBText$,4  :REM Insert colour code
  REM Get left margin for button
  bStartX = bButLeft + bPointList[5,1] + bLMargin
  DO bConvNumber,bStartX,3  :REM Convert to 3 characters
  REM Insert left margin command
  STRING "|ml";convnum$,bBText$[5],6
  REM Get right margin, convert to characters and insert
  bEndX = (bButLeft + bPointList[6,1])-bRMargin
  DO bConvNumber,bEndX,3
  STRING "|mr";convnum$;"|r1",bBText$[11],9
  REM Has a font been loaded? Must be #1-9, 10
  IF (bFontNum > 0) & (bFontNum <= 10)
  REM Font 10 resets font to default
  IF bFontNum = 10 THEN bFontNum = 0
  STRING "|f";bFontNum;bButtonText$;"|t";bCentre;"|r1",bBText$[20],179
    STRING bButtonText$;"|t1|r1|t0",bBText$[20],179
  REM Calculate label position
  bStartY=bStartY-(bFontHeight/2) :REM Adjust for LF
  IF (bShadowX <> 0)|(bShadowY <> 0)
    MOVE bStartX,(bStartY+bShadowY)
    FTEXT bJust,bBText$,bDropColour,bShadowX
  MOVE bStartX,bStartY
  FTEXT bJust,bBText$


;CopyWrite 1993 Andrew Porter
;May be copied for NON-COMMERCIAL uses
;All Right Reserved
;ImagEYE Creations

;*** NOTE *** *** NOTE *** *** NOTE *** *** NOTE *** *** NOTE ***
;SAVE the preceding as "Director:Library/Button.dlib"
;SAVE the following in a separate file and run using the director
;*** NOTE *** *** NOTE *** *** NOTE *** *** NOTE *** *** NOTE ***

;*         ShowButton   1993 Andrew Porter                 *
;*    A demonstration of the Bevelled Button Library       *

  REM Load library
  INCLUDE "Director:Library/Button.dlib"

  REM Load a special font

  NEW 640,200,4 :REM Open 16 colour hires screen

  REM Set colours 0-4 as shades of grey
  color 0,0,0,0
  color 1,14,14,14
  color 2,12,12,12
  color 3,9,9,9
  color 4,6,6,6

  REM Display title
  CENTER ON : SETFONT 1 : MOVE 0,20 : PEN 15
  TEXT "A demonstration of the Bevelled Button Library"

  REM First a default
  DO MakeButton,25,40,150,50,"Default BUTTON"

  REM Now Change the bevel size
  DO ButtonConfig,2,5,5,1
  DO MakeButton,230,45,150,30,"New Bevel Sizes"

  REM Now get rid of the button hole and screen adjustment
  REM Notice how side bevels are not as thick
  DO ButtonConfig,5,0,0,0
  DO MakeButton,410,35,225,50,"No hole, No adjust"

  REM Now reset to defaults and change colours
  DO ResetButton
  DO ButtonColours,3,2,2,4,4,0,6,0
  DO MakeButton,25,110,150,50,"New Colours"

  REM Now change the Font attributes
  DO ButtonText,1,20,2,1,2,2,0,1
  DO MakeButton,200,110,240,75,"New Font & Backgound"

  REM Now change the Font attributes
  DIM ReadText[200]
  ReadText$ = "This is an example of wrapped
  text in a button.  This could be used to
  give instructions however it is limited
  to 170 characters."

  REM Reset font, move to top, and turn centring off
  DO ResetButton
  DO ButtonText,10,75,0,0,2,2,0,0
  DO MakeButton,470,100,160,90,ReadText$

  REM Show Exit
  DO ResetButton
  DO MakeButton,25,175,150,20,"LMB to Exit"

  goto EndlessPause