Loading Local Images into the Slider
There are several different ways you can import images into a movie running in a Projector (or in Authoring). The first step for all the techniques is getting a list of files to import.
For example, if the images are in a folder called "Images" which is in the same folder as the movie, then a function like this will return a list of the JPGs in that folder:
on GetListOfImages (me, inDirectory)
-- returns a list of files (full path) in specified directory
fileList = [ ]
the itemDelimiter = "."
repeat with i = 1 to the maxInteger
n = getNthFileNameInFolder(inDirectory , i)
if n = EMPTY then exit repeat
if n.item[n.item.count] = "jpg" then
fileList.append(inDirectory & n)
end if
end repeat
return fileList
end
Once you have this list, you can loop through at 'import' the images. One technique for doing this is to set the fileName of a placeholder cast member. For example
member("PlaceHolder").filename = fileList[1]
Since our slider may use many images, and we only want to create a small thumbnail image for each, it is inefficient to load all the images into memory at once. For this reason, the following script will first load a 'place holder' graphic (which says "image loading") for each file into the slider. Then, one-by-one, it loads the real image into the slider (replacing the place holder as the real image is loaded).
Example source file available here
ImageLoader.local (Parent script)
-- loads images from a local directory (not for shockwave)
property myTempBitmap, mySlider, myIndx, myImagesToLoad
property myTarget
on new (me)
myTempBitmap = member("ImageLoader.local.bitmap")
if myTempBitmap.type <> #bitmap then
myTempBitmap = new(#bitmap)
myTempBitmap.name = "ImageLoader.local.bitmap"
end if
return me
end
on Destroy (me)
-- erase the bitmap
if myTempBitmap.ilk = #member then erase myTempBitmap
-- void our reference to the slider
myTarget = VOID
end
on stopMovie (me)
-- will get this message if the timeout is active
me.Destroy()
end
on loadImagesTo (me, theTargetObject, FolderOfImages)
-- get list of files to load
imageFiles = me._GetFileNames(FolderOfImages)
myTarget = theTargetObject
-- now load a temporary image into the slider for each real image
myImagesToLoad = [:]
repeat with aFilePath in imageFiles
myImagesToLoad.addProp(aFilePath, member("SliderLoadingImage").image)
end repeat
myTarget.LoadImages(myImagesToLoad)
-- now create a thread to actually load the real images
myIndx = 0
thread = timeout("ImageLoaderThread").new(100, #LoadNextImage, me)
end
on LoadNextImage (me, aTimeout)
-- called by the timeout
if myIndx < myImagesToLoad.count then
myIndx = myIndx + 1
whichFile = myImagesToLoad.getPropAt(myIndx)
myTempBitmap.filename = whichFile
-- replace the 'loading' image with the real one
myTarget.SetImageAt(myTempBitmap.image, whichFile, myIndx)
else
aTimeout.forget()
end if
end
on _GetFileNames (me, inDirectory)
-- returns a list of files (full path) in specified directory
fileList = [ ]
the itemDelimiter = "."
repeat with i = 1 to the maxInteger
n = getNthFileNameInFolder(inDirectory , i)
if n = EMPTY then exit repeat
if n.item[n.item.count] = "jpg" then
fileList.append(inDirectory & n)
end if
end repeat
return fileList
end
To demonstrate how this script works with the Slider, here is a behaviour that creates the slider and an instance of this Loader script:
property ancestor
property myMidH, myShift, myAlpha, myOffset
property myTrackingFlag, myStartH
property mySlideLeftRect, mySlideRightRect
on beginSprite me
thisSprite = sprite(me.spriteNum)
thisRect = thisSprite.rect
thisMember = thisSprite.member
thisCanvas = thisMember.image
thisCanvas.fill(thisCanvas.rect, rgb("#000000"))
--
myOffset = point(thisRect.left, thisRect.top)
myMidH = thisSprite.left + (thisSprite.width/2)
-- create the 'hot spots' for sliding
mySlideLeftRect = rect(thisSprite.left, thisSprite.top, thisSprite.left \
+ (thisSprite.width/3), thisSprite.bottom)
mySlideRightRect = rect(thisSprite.right-(thisSprite.width/3), \
thisSprite.top, thisSprite.right, thisSprite.bottom)
-- create the slider object
ancestor = script("HorizontalImageSlider.Class").new()
me.Initialise(thisCanvas, thisCanvas.rect)
-- set the path to the folder containing theimages
sep = the last char of the moviePath
folderContainingImages = the moviePath & "Images" & sep
-- create an Object to load up the images
imageLoaderDaemon = script("ImageLoader.local").new()
imageLoaderDaemon.loadImagesTo(me,folderContainingImages)
end
on endSprite (me)
-- clean up the canvas
thisSprite = sprite(me.spriteNum)
thisMember = thisSprite.member
thisCanvas = thisMember.image
thisCanvas.fill(thisCanvas.rect, rgb("#000000"))
end
on enterframe (me)
if myTrackingFlag then
-- the mouse was clicked on this sprite
if not (the mouseDown) then
-- stop tracking
myTrackingFlag = 0
else
-- 'drag' the slider to the current mouse location
mH = the mouseH
amt = myStartH - mH
myStartH = mH
me.Slide(amt)
end if
else
p = the mouseLoc
if inside(p, mySlideLeftRect) then
proposedAmt = myShift -1
myShift = Max(-10, proposedAmt)
else if inside(p, mySlideRightRect) then
proposedAmt = myShift + 1
myShift = Min(10, proposedAmt)
else
-- slow down to a stop
myShift = myShift * 0.75
if abs(myShift) < 2 then myShift = 0
end if
me.Slide(myShift)
end if
end
on mouseDown (me)
ClickedTile = me.GetTileIDAtPoint(the mouseLoc - myOffset)
if voidP(ClickedTile) then return 0
myTrackingFlag = 1
myShift= 0
myStartH = the mouseH
me.SelectTileByID(ClickedTile, (the shiftDown))
sendAllSprites(#ImageSelected, ClickedTile)
endMichael said
Yes I agree ... extremely smooth script. I would like to know how to modify to scroll vertically. The end result probably wouldn?t be that intuitive for the user but I would like to see it never the less. I have redesigned the slider sprite to run vertically however I have searched and searched and searched and I cannot work out where the script stipulates that the image must be placed left to right (I?m wanting to have them load underneath each other) nor where I can manipulate the script to have the slider scroll up and down.
Cheers, michael
Posted 1st August, 2006
Luke said
Hi,
Have a look in the "Slide" method, about two thirds of the way down, for these lines:
rectLeft = -myMapH
...
destRect = myMap[aTileIdx][#DRect].offset(rectLeft, 0)
This is stipulating that the 'destination rect' for each is to the left of the last rect. So you will want to change it to something like
rectBottom=-myMapV
...
destRect = myMap[aTileIdx][#DRect].offset(0, rectBottom)
to paint each tile below the one above. Changing the value of rectBottom will make the slider go up and down. (Note - the variable myMapV doesn't exist in the code. you will need to change myMapH to myMapV). If you are still stuck, let me know (I have a vertical version somewhere I can upload)
-- Luke
Posted 2nd August, 2006
Michael said
I'm with you now :) ... I got a little lost in the "...myMap[aTileIdx][#DRect]..." strings and it never really 'clicked' to research the offset function. I'm currently having a play around - ironed out most the bugs just one more tracking one to go. Thanks for your wisdom Luke.
- michael
Posted 2nd August, 2006
Gianluca said
Can you help me?
I run your source download file and all works fine (no code error),
but if i try to copy the castmembers and the sprite in another movie i recive this error:
script error:
Object expected.
Thread = timeout ("imageloader Thread").new(100, #loadnextimage, me)
i've assigned the HorizontalImageSlider.Behaviour to the bitmap sprite, i've to do something else?
Thanks for your help...
Posted 11th October, 2006
Luke said
Hi
That line uses the old syntax for creating timeout objects (it works fine when you open the flle with DMX2004 because director will run the movie in 'compatibility mode' and set the 'scriptExecutionStyle= 9'). When you paste the code into a new movie, the old syntax will error unless you explicitly set the scriptExecutionStyle. Better yet, change the code so it used the new DMX2004 syntax like this:
OLD SYNTAX:
Thread = timeout ("imageloader Thread").new(100, #loadnextimage, me)
NEW SYNTAX
Thread = timeout ().new("imageloader Thread", 100, #loadnextimage, me)
-- Luke
Posted 11th October, 2006
Dave said
Hi
Great script, ideal for presenting artwork or photos in director.
The horizontal scroll looks great but would it be possible to upload the vertical scroll version. You mentioned that you already have a vertical version .
I've made the changes Michael requested but it still isn't working properly.
Thanks
Dave
Posted 13th February, 2007
Alex Souza said
Great job! Quick question: is there a way to stop the slider when it finds the last image (currently there is a continuous loop)?my idea is to open with the first image allowing the user to move rigth to the last image (and vice-versa).
thanks a lot,
Alex
Posted 9th December, 2007
lucio said
Ã? una bellissima funzione e va bene nel proiector, ma non funziona se viene pubblicata in .dcr o in html
Messaggio di errore: Use of unsupported Lingo command
#getNthFileNameInFolder !!! Funziona solo nel Proiector?
Posted 12th July, 2009
joao said
Thanks for the script and the site. Keep up the good working.
Posted 4th March, 2006