Date: Wed, 12 Jul 1995 17:14:07 +0000 From: Daetwyler Christof <daetwyler@AUM.UNIBE.CH> Subject: Irregular clickable "sprites"A few days ago, I posted, that you can now ftp a little program, that demonstrates our technique, how multiple irregular-shaped hot-spots can be easily done. The program is called EYE, it allows the interactive examination of a fundus altered by diabetic disease. The program is in english and in german.
I forgot to mention the sites, where you can get the Windows-Version and where you find the story, how this technique has been evoluted with the help of the listserver DIRECT-L in the Internet.
If you take our Web-Site into your Bookmarks, you won't have to copy the links. The URL where our Projects are described is:
http://www.iawf.unibe.ch/aum/Portrait/prod/cbt.htm
Here's again the story of making as many irregular-shaped-hotzones as you want:
I'm working on an interactive education programm in neurology for medical students. One big problem is, how interactivity can be made. My idea is, that lots of problems can be easy solved... ...IF I COULD DETECT THE COLOR OF THE BITMAP-PIXEL UNDER MY CURSOR!Imagine: A very complicated anatomy-Pictuere with dozends of nerves, every of them in an slightly different color - and my program could detect over which nerve the cursor rolls by detecting the color. No need to make complicated-formed sprites and detect the rollovers!
If anybody know, how this could be done, please let me know. Many thanks in advance.
Second I get your XCmd
Third I wanted a similar XCmd for the Window-side
Fourth I got the following solution:
Here's the best solution I could come up with for finding the pixel color under the cursor (short of writing an XObject.) In the process of coming up with this solution I discovered how to make unlimited irregular shaped hotspots without using a single channel! Yipee! :)STEP 1: Pull your 640x480 backdrop up in Photoshop and convert it to 8 bit (your choice of palette.)
STEP 2: Save a copy out in RAW format and choose TEXT (upper case) for the file type. The data fork should be exactly 307200 bytes for a 640x480. If it's 921600 then you saved it as RGB which will mess up the scheme. The resource fork is unimportant. Let's save it with the name 'MyRawPictFile'
STEP 3: Now in your Director movie, load the raw pict file data into a string using fileIO. (PC users beware of 64K fileIO limit, you'll have to chop it up into 64K chunks) Something like this will do:
on LoadRawPictIntoString global gPictInAString if objectP(myObj) then myObj(mDispose) set whichFIle = the pathName & "MyRawPictFile" put FileIO(mNew,"read",whichFIle) into myObj put myObj(mReadFile) into gPictInAString endSTEP 4: Put the following subroutine in a movie script.
on FindColorOfPixelUnderCursor global gPictInAString set x = the mouseH set y = the mouseV set locOfPixelInString = (y*640) + x + 1 return charToNum(char locOfPixelInString of gPictInAString) endSTEP 5: To check what color is under your cursor call the FindColorOfPixelUnderCursor routine. Pop these two event handlers into the same score script and open your message window to try it out. You should get index numbers from 0 to 255 which correspond to the colors in the current palette:
on mouseDown put FindColorOfPixelUnderCursor() end on exitFrame go to the frame endNOTE: In case it's not obvious, I'm not really checking the color of the pixel under the cursor. I'm just associating the coordinates of the mouseclick with a location in a string. The string represents a particular picture which may or may not be on the stage. It will return the indexes to the pict file represented by the string regardless of what's on stage.
But wait there's more! Consider the following derivative of this solution.
WE CAN HAVE 256+ IRREGULAR SHAPED CLICK ZONES!!!
By using this same process you can have 256 irregularly formed, disconnected click zones. Just pull your 640x480 pict file up in Photoshop 3.0. Create a new layer and go around painting over each click zone in its own unique color. After you've painted each of your click zones in a different color, copy this *matte* layer to a new document, change the new document to indexed color, and proceed as above.
Notice that this is not really a matte. It doesn't hide under your backdrop or take up a channel. It's sort of a virtual matte if you will. :) It just sits out in its string which you reference easily as in FindColorOfPixelUnderCursor. For this purpose its not the color that's important but rather the *index*. The color is just providing an easy way to assign a unique identifier to each and every pixel location on the stage.
Once you have your indexes you can just set up a property list to connect the index numbers of your click zones with their respective handlers. Like...
on mouseDown set clickList = [0:"handler1",1:"handler2"] do getaProp(clickList,FindColorOfPixelUnderCursor()) endou can even make the cursor change over the click zones by FindingColorOfPixelUnderCursor and hooking up the index with a property list of cursors! Like so:
Init a list of cusors ...
on InitCursorLIst -- Index 0 = arrow -- Index 1 = crosshair -- Index 2 = custom 1bit cusor in cast 7 with mask in cast 8 set gCursorList = [0:-1,1:2,2:[7,8]] endThen set the cursor according to the pixel under the cursor:on exitFrame global gCursorList cursor (getaProp(gCursorList,FindColorOfPixelUnderCursor())) go to the frame endPitfalls to watch for:Is this not Inspirational!!! :) Maybe Director is not so bad after all! ;)
- Make sure you are painting with the pencil not the brush in Photoshop. The pencil will provide clean edges. The antialiasing of the paint brush would cause problems when you convert to indexed color.
- Make sure your using colors which will map to different indexes. The easiest way to do this is to load a System Palette into the swatches. Then dab into the swatches with the color picker to choose your colors for the pencil. Then convert to system pal when your done and the RGB colors will index exactly.
- Furthermore if you need even more than 256 click zones, just do the same sort of thing in RGB. The RAW format will give three bytes per pixel instead of one so the math will be a little different but all in all it should work out pretty much the same. You will then be able to have 16.7 million click zones!!! Guess this is kind of overkill since a 640x480 has only 307200 pixels. ;)
P.S. I have actually tried this out and it works. :) I'm posting this to DIRECT-L too.
+-----------------------------------+ | Steve Gerber | | sgerber2@aol.com | +-----------------------------------+ | Freelance Macromedia Director(tm) | | Lingo Programmer | +-----------------------------------+
Fifth I made out of it one RAW per Sprite:
Now I got the solution, how every Sprite can have as many RAW-files (ego Layers with Information), as I like. The script is following: You need 2 frames, in the first frame you set the globals, in the second frame you detect the 'colours'
on exitFrame RawFilesImport put " " into field "message" end on RawFilesImport global gRawPeri, gRawSegm, gRawRefl, gRawSpez, gSpriteV, gSpriteH, gSpriteWidthThis handler loads data of rawFiles into global variables and puts the location of sprite 1 into global variables
put the top of Sprite 1 into gSpriteV put the left of Sprite 1 into gSpriteH put the width of Sprite 1 into gSpriteWidth - load RawFile with data about peripheral nerves into global gRawPeri set whichFile = the pathName & "rPeri_1.txt" put FileIO(mNew, "read", whichFile) into myObj put myObj(mReadFile) into gRawPeri - load RawFile with data about segmental nerves into global gRawSegm if objectP(myObj) then myObj(mDispose) set whichFile = the pathName & "rSegm_1.txt" put FileIO(mNew, "read", whichFile) into myObj put myObj(mReadFile) into gRawSegm - load RawFile with data about reflex-zones into global gRawRefl if objectP(myObj) then myObj(mDispose) set whichFile = the pathName & "rRefl_1.txt" put FileIO(mNew, "read", whichFile) into myObj put myObj(mReadFile) into gRawRefl - load RawFile with data about special messages (blow-up's, change of shown picts etc) if objectP(myObj) then myObj(mDispose) set whichFile = the pathName & "rSpez_1.txt" put FileIO(mNew, "read", whichFile) into myObj put myObj(mReadFile) into gRawSpez if objectP(myObj) then myObj(mDispose) put "" into myObj end
on exitFrame
if rollover(1) then
PixelToQualities
else
put empty into field "message"
end if
go to the frame
end
on PixelToQualities
global gRawPeri, gRawSegm, gRawRefl, gRawSpez, gSpriteV, gSpriteH,
gSpriteWidth
- This handler gets the position of the cursor relative to Sprite 1
- then it gets the corresponding character in different RAW-Files
- and Get the information about the qualities to show out of a item List
set x = the mouseH - gSpriteH
set y = the mouseV - gSpriteV
set z = 180
set RawChar = ((y) * z) + x + 1
set raw_1 to charToNum(char RawChar of gRawPeri)
set raw_2 to charToNum(char RawChar of gRawSegm)
set raw_3 to charToNum(char RawChar of gRawRefl)
set raw_4 to charToNum(char RawChar of gRawSpez)
if raw_1 > 0 then put item raw_1 of field "PeripherieText" into raw_1TEXT
if raw_2 > 0 then put item raw_2 of field "SegmentText" into raw_2TEXT
if raw_3 > 0 then put item raw_3 of field "ReflexText" into raw_3TEXT
if raw_4 > 0 then put item raw_4 of field "SpezialText" into raw_4TEXT
put raw_2TEXT & return & raw_1TEXT & return & raw_3TEXT & return & raw_4TEXT into field "Message"
updateStage
end
on mouseUp
- functionates, if the numToChar of the hotRegion is shown in line 1 of field "Message":
if (value(line 1 of field "Message")) > 0 then
put line 1 of field "input" into item (value(line 1 of field "Input")) of field "Itemlist_n"
end if
end
Q: Are RAW-Files for Windows different from RAW-Files for Mac?
Q: How can I break RAW-Files into smaller chunks?
A: The easiest way is to change the resolution from 72dpi to 36dpi in
PhotoShop before you make the RAW-Files. This makes the RAW-Files 4 times
smaller!(or 16 times when you would use 18dpi and so on). But then you have
to change the script to find the right 'color'-value in that way, that you
divide the x-wide and the y-height by either 2 (in case of 36dpi as
documented in the script below), or 4 (would be the case by 18dpi) and so
on:
-- The sprite with the RAW-File correlated is sprite 1
-- The RAW-File is exactly 109 pixels wide (was 218 pixels in 72dpi)
-- the global variable gRawChar1 gets the position of the ASCII-Value in the RAW-File
-- according to the position of the cursor over sprite 1
-- The variable RAW-File contains a RAW-File read in by fileIO
set x = (the mouseH - (the left of sprite 1)) / 2
set y =(the mouseV - (the top of sprite 1)) / 2
set z = 109
set gRawChar = ((y) * z) + x + 1
set RawInput to charToNum(char gRawChar of RAWfile)
-- **2** the following fixes a bug in DfW v4.04
if RawInput > 255 then set RawInput to value(RawInput - 65280)
-- end of bug-fix
-------------------------------------------------
_?_ Christof Daetwyler MD
/_ _\ Dept. for Education Media AUM
[\O-O/] AUM - IAWF, University of Berne
\_-_/ Inselspital 38
_| |_ CH - 3010 Bern
/ \_/ \ Tel: +41 31 632 25 12
__oOOO___OOOo__ Fax: +41 31 381 93 22
-------------------------------------------------