Hot Spots


Checking Hot-Spots

Date:    Wed, 16 Nov 1994 23:43:05 -0600
From:    Matthew Caldwell <sexkittn@BURN.DEMON.CO.UK>

-- create a property list of hotspot rects:
 
  global gHotSpotList
  set gHotSpotList = [ #quitBtn   : [20, 20, 100, 40],  <contd>
                       #cancelBtn : [20, 50, 100, 70] ... ]
 
-- and check the mouse location against it
 
  on checkHotSpots
    put point( the mouseH, the mouseV ) into mouseLoc
    repeat with i = 1 to count( gHotSpotList )
      if inside( mouseLoc, getAt( gHotSpotList, i ) ) then
        return getPropAt( gHotSpotList, i )
      end if
    end repeat
    return #noHotSpot
  end checkHotSpots
An alternative is to divide your whole stage area into equal parts (say 20 x 20 pixels) and apportion hotspots only in integral chunks. Convert the mouse Loc into an index to these chunks, and look it up in a list.
 
  -- before we start we have to work out the size of the stage array
  -- (skip this if you already know it)
 
  global gBlocksAcross, gBlockWidth, gBlockHeight, gBlockList
 
  on startMovie
    set gBlockWidth = 20
    set gBlockHeight = 20
    set pixAcross = the stageRight - the stageLeft
    set gBlocksAcross = pixAcross/gBlockWidth
    -- we don't need to care about how many blocks down there are
    set gBlockList = [ #quitBtn:42, #quitBtn:43, #quitBtn:44 <etc> ]
  end startMovie
 
  -- convert the mouseLoc to a block number, and get the associated label
 
  on getBlockLabel
    put the mouseH into H
    put the mouseV into V
    set blockNum = (V/gBlockHeight) * gBlocksAcross + (H/gBlockWidth)
    return getOne(gBlockList, blockNum)
  end calculateBlockNumber
 
[caveat emptor: these scripts are untried and untested]

Checking HotSpots with Lists

--**************************************************************
--*                                                            *
--*         CHECKING HOT-SPOTS USING LISTS Script              *
--*      by Miles Lightwood (from work by Matthew Caldwell)     *
--*                                                            *
--**************************************************************
 
-- startMovie
-- Make sure you declare your list a global. I put all my global
-- declarations in a startMovie hand.
on startMovie
  global lsHotSpot
  listInit
end
 
-- listInit
-- This initializes as globals the lists used in this movie.
-- This is the first step to using lists.
-- Follow the below to create a property list of hotspot rects:
-- Format: #quitBtn :   rect    (20,     20,     100,     40)
-- Syntax: prop^    : value^  UL x^   UL y^    LR x^   LR y^
on listInit
  global lsHotSpot
 
  set lsHotSpot =3D [ #helpBtn   : rect(  0, 445, 135, 462),
                    #ovrvwBtn  : rect(135, 445, 269, 462),
                    #nextBtn   : rect(  0, 463, 135, 479),
                    #prevBtn   : rect(135, 463, 269, 479),
                    #quitBtn   : rect(578, 424, 615, 461) ]
--                  ... add as many button/rects as you like
--                  to this list; just make sure you follow
--                  the above format and syntax.
end
 
-- checkHotSpot 
-- Place this hand in a movie script; call it from anywhere else.
-- This hand determines the dimensions and coordinates of the "rect"
-- that a mouseUp/or Down occurs in. This rect is a value in a property
-- list. Once the mouseUp/or Down point has been determined, it is
-- compared to all the rects in the list "lsHotSpot". If it lies
-- within one of the rects in the list then the associated property
-- is returned to the next hand. If not, "#noHotSpot" is returned.
on checkHotSpot
  global lsHotSpot
 
  put point( the mouseH, the mouseV ) into mouseLoc
  repeat with i =3D 1 to count( lsHotSpot )
    if inside( mouseLoc, getAt( lsHotSpot, i)) = TRUE then
      return (getpropAt( lsHotSpot, i ))
    end if
  end repeat
  return #noHotSpot -- <-- this is optional
end
 
--whichHotSpot
-- Place this hand in a movie script; call it from anywhere else.
-- This hand evaluates the property(a symbol) returned by the
-- "checkHotSpot" hand, and then executes the associated command.
-- The commands in the following are just alert dialogs which are
-- useful for debugging purposes; they could be other hand calls,
-- statements, etc.
on whichHotSpot
  global lsHotSpot
 
  if checkHotSpots() = #helpBtn then
    alert "Help Button"
  else  if checkHotSpots() = #nextBtn then
      alert "Next Button"
  else  if checkHotSpots() = #ovrvwBtn then
      alert "Overview Button"
  else  if checkHotSpots() = #prevBtn then
      alert "Previous Button"
  else if checkHotSpots() = #quitBtn then
      alert "Quit Button"
  else if checkHotSpots() = #noHotSpot then
       put checkHotSpots()
  end if
end
 
--doHotSpots
-- To make the above hands work, attach this to a sprite, and
-- call it from a sprite script in a mouseDown handler.
on doHotSpots
 checkHotSpot
 whichHotSpot
end

Invisible Hot Spots

What is the easiest way to define invisible hot spots using Director ???
Scott Brisko <sbrisko@netcom.com> replied

The best way to do what you are doing is to make quickdraw boxes (use the tool pallete) with no fill or line, thus invsible. You can either assign them a cast script or a sprite script to branch them off to the direction you want.


Paul Farry <p.farry@ucq.edu.au> replied

Put rectangles on the screen CMD 7 pallette. and the dotted lines. with score code on them.


J.-Robert Thibault <JRobert.Thibault%FORESTERIE%ULAVAL@REDIRECTEUR.ULAVAL.CA> replied

Any object can have a script embedded. You can do exactly as in HC.

An object can a rectangle with no visible boundary. In it, you script something like go theframe+1 and you will get the effect similar to go next card.

By this technique, you can have a cliquable state of Texas, and so on...


Charles B. Abrams <ABRAMS@OMC.LAN.MCGILL.CA> replied

You can have an unlimited number of hot spots by creating one large invisible object over the screen, and a script that traps the mouse location when clicked. You then use Lingo to check the position of the mouse, and act accordingly.


alan levine <levine@maricopa.bitnet> replied

If your hotspots are fairly regular in shape (i.e. rectangles or circles) use the quickdraw shapes from the tools palette to create an unfilled shape. Click once on the shape and use the line styles on the tools menu to make the boder invisible (the dotted ones at the top of the available lines). You can then put scripts either in the cast member of the shape; however I would create just a few and put various scripts/handlers in the score. In this way, the same cast can generate many different scriptable actions.


Anna Gupta replied

What has worked for us many times is: Create the shape of the sprite you are trying to click on in any paint program like photoshop or illustrator. Import it into director and then make that shape completely black. When you put it over the area you wish to click on the stage, use the ink effects and choose lightest. This will make an invisible "hot spot". This way you can attach a script to allow branching.


Irregular Hot Spots

Is there anyway to make cast with shapes
to make click on them , but not just squares like in Dir. 3.1.1 ? Like
circles or the shape of the cast ?.
Make sure that the background of the cast is white, then set the ink of the hot-spot, or the cast itself to *Matte*.

This will make a click-on respond only when on the cast itself, not its bounding rectangle.

+-------------------------------------------------------------------------+
                               -----------------------------------
 Miles Lightwood             /         ####   #####   ####         \
                           /          #   ##    #    #    #          \
 miles@rhythm.com        /             ####     #     ####             \
                            \       6  .  5    L  I  T  R  E        /
 Rhythm & Hues, Inc.            \=  =  =  =  =  =  =  =  =  =  = /
                                    \ =  =  =  =  =  =  =  = /
 vox: 213.851.6500                      \ =  =  =  =  =  /
                                            \  =  =  /
 fax: 213.851.5505                              \/
                          "G R R R...T  H  E    G  R  E  A  T    O  N  E"
+-------------------------------------------------------------------------+

Moving Hot Spots

Date:    Thu, 23 Mar 1995 14:52:37 +1030
From:    Matt Craig 
Subject: Re: How to make multiple "hot spots" on a moving bitmap?
Here is my question: I have a bitmap castmember that appears on many different screens and functions in the capacity of a navigation tool. I would like to make different regions of this bitmapped castmember "hot." That is, I should, for example, like a mouseup event that occurs on the left of the sprite to trigger one handler, and a mouseup on the right triggers another, the center another, etc.

I would imagine that your graphic makes it obvious which points to click on (eg some sort of composite buttons graphic/sprite)

What you need to do is define those regions 'mathematically' - ie find out what the rects are that define each of those regions in your graphic. You will also need to reference the mouseClick as a pt which is LOCAL to that sprite, rather than as a stage coordinates (as your registration point MAY be moving around, it is probable best to reference the mouse position with the top/left of the sprite)

on mouseDown
  doClick(whichArea())  -- need to include the () after whichArea as it is
end                     -- a function call, not a variable
 
on doClick area         -- example of what to do with the result
  if area <> "" then
    if area = #topLeft then
      put "topLeft"
    else if area = #topRight then
      put "topRight"
    else if area = #botLeft then
      put "botLeft"
    else if area = #botRight then
      put "botRight"
    end if
  end if
end
 
on whichArea
  -- you need to define x, as that is the sprite number of your graphic
  set localPt to the clickLoc - point(the left of sprite x,the top of sprite x)
 
  -- then say you had four rects in your sprite,
  -- with local sprite coordinates of...
  -- rect(left,top,right,bottom)
  set tlRect to rect(0,0,50,50)
  set blRect to rect(0,51,50,100)
  set trRect to rect(51,0,100,50)
  set brRect to rect(51,51,100,100)
  set rectList to
[topLeft:tlRect,topRight:trRect,botLeft:blRect,botRight:brRect]
  -- you would probably do the above using properties in a child/parent handler,
  -- rather than every time you clicked to mouse down as in this handler
 
  -- this is where we find out if the mouse was clicked within any of the rects
  repeat with i = 1 to count(rectList)
    set myProp to getPropAt(rectList,i)
    set myRect to getAt(rectList,i)
    if inside(localPt,myRect) then
      return myProp
    end if
  end repeat
  return ""
end