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 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
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.
Put rectangles on the screen CMD 7 pallette. and the dotted lines. with score code on them.
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...
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.
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.
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.
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"
+-------------------------------------------------------------------------+
Date: Thu, 23 Mar 1995 14:52:37 +1030 From: Matt CraigHere 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.Subject: Re: How to make multiple "hot spots" on a moving bitmap?
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