Using FlashPaper in Macromedia Director
With the release of Macromedia Contribute 2.0, Macromedia added on a little component known as Macromedia FlashPaper. It didn’t get much fanfare and was simply a freebie for Contribute 2.0 PC users, but FlashPaper is not just for Contribute. It's built on the same Macromedia Flash technology used in browsers, and, of course, in Macromedia Director. My initial thought when I saw this was, "I can’t wait to get this in Director!"
This was a big deal to me at the time as I had spent a week debugging a very difficult PDF issue with a client's project. There are some great tools out there from companies like Integration New Media’s PDF Xtra that help you get Adobe Acrobat documents into Director. Many times the full power of PDF files is a lifesaver, but often I only have a simple document that needs to be read and printed. In these cases, the low overhead and not having to install any third party software on the user’s machine made FlashPaper an exciting new alternative. Top that off with the recent changes with new PDF engines, installation hassles on machines where users do not have administrative access to add programs, or new differences with OSX, and FlashPaper becomes far simpler for displaying basic read and print documents.
Requirements
To complete this tutorial you will need to install the following software and files:
Contribute which includes FlashPaper
Download the sample files:
- For FlashPaper 1 and 1.1:
flashpaper.zip (65 KB)
- For FlashPaper 2:
flashpaper2.zip (65 KB)
Well, I will freely admit my first attempt at integrating FlashPaper with Macromedia Director was not very successful. FlashPaper is a powerful Macromedia Flash application and is optimized for use in the browser; when Director tries to open and display FlashPaper, you quickly get a dose of "dueling apps" and the FlashPaper displays a bit strange, to say the least. With a little tinkering and some help from Steven Johnson at Macromedia, we we were able to produce a basic display of a FlashPaper document in Director by adjusting a few parameters. FlashPaper handles its own scaling, so we needed to disable any scaling by Director. Also, we needed to ensure the origin was perfectly centered. The following was the basic approach:
on beginSprite me
--use a point for center
sprite(spriteNum).originMode = #point
--set the origin
sprite(spriteNum).originH = sprite(spriteNum).width/2
sprite(spriteNum).originV = sprite(spriteNum).height/2
--set the scale mode to none (scales itself)
sprite(spriteNum).scaleMode = #noScale
end
And that, my friends, was all there was to it. FlashPaper displayed nicely in Director, and had its own included controls. After about five seconds of happily staring at my working project though, it occurred to me that I would love to do more with FlashPaper than just look at it. Where FlashPaper 1.0 was limited, FlashPaper 1.1 is much more versatile. It has an open API that allows developers to interact with the movie directly. You can modify anything from hiding part of the UI to swapping pages and printing. It's all written as standard Macromedia Flash calls making it fairly easy to use in Flash, HTML, and, of course, Director.
To properly use any Macromedia Flash component in Director,you must understand how Director interacts with Flash and understand the cross communication between the Flash object model and Director. If you have not read it already, I would recommend that you read Using Macromedia Flash in Director by Mark Jonkman in the Macromedia Director Developer Center. This will familiarize you with the basics of how the two can share data and what else is possible.
In creating controls that allow Director and FlashPaper to interact, I built my behavior in three stages.
- I created simple functions that mimicked the Macromedia Flash API. This gave me a Director-formatted set of functions that I could call to interact with FlashPaper and also created basic error checking that I could insert.
- I set up callbacks for events that FlashPaper monitored.
- I combined these base functions to create more advanced controls to use in Director.
Let’s start with the basics for tapping into the code functions FlashPaper allows you to use. Almost all the items you will use to interact with FlashPaper are Macromedia Flash functions. Since Director cannot simply call a function in Flash, as it needs an object to reference; you must to first get the root element of the Flash file. Store this in a property for the behavior as follows:
pRoot = sprite(spriteNum).getVariable("_root", 0)
The "0" is important as the last parameter. Setting this to false will return the actual Macromedia Flash object (which you need), instead of a text representation of the root object. One item of note about Flash in Director: I have found that many times it’s best to leave a frame for Flash to fully open and load before you start accessing objects and functions. For this reason, I always initialize any settings in the first exitFrame of the sprite. Combined with the sizing routine you get something like this:
on beginSprite me
pInitialize = 1
--use a point for center
sprite(spriteNum).originMode = #point
--set the origin
sprite(spriteNum).originH = sprite(spriteNum).width/2
sprite(spriteNum).originV = sprite(spriteNum).height/2
--set the scale mode to none (scales itself)
sprite(spriteNum).scaleMode = #noScale
end
on exitFrame me
if pInitialize then
--initialize after 1 frame for best playback
pRoot = sprite(spriteNum).getVariable("_root", 0)
pFlashPaper = pRoot.isFlashPaperDocument()
--validate flash paper
if pFlashPaper <> 1 then exit
pInitialize = 0
end if
end
Next, you need to ensure the behavior will be used only by FlashPaper
files. There are two points where you can check this. First, you will
use the isOkToAttach handler to ensure that no one tries
to place this on a bitmap image, text, and so forth:
on isOkToAttach me, vSpriteType, vSpriteNumber
--only use on a flash sprite
if sprite(vSpriteNumber).type <> #flash then
return false
else
return true
end if
end
Second, you must prevent any non-FlashPaper Macromedia Flash movies from using this as well. In the initialization routine, check FlashPaper using one of the built-in API calls:
pFlashPaper = pRoot.isFlashPaperDocument()
Now the fun can begin. Since you have a root object, you can start accessing functions.
pRoot.setCurrentPage(2)
This sets the currently viewed page to two. Next, wrap it in a Director function:
on setCurrentPage me, vPage
if not pFlashPaper then return 0
--sets the current page so that it is at least partially visible
vPage = integer(vPage)
if ilk(vPage) <> #integer then exit
if vPage > me.getLoadedPages() then
alert "Please wait for the document to finish loading."
exit
end if
pRoot.setCurrentPage(vPage)
return 1
end
I added a few checks to ensure I only try to load integers for page
numbers, and you will also see a reference to getLoadedPages()
that ensures that you don’t try to scroll to a page that has not yet
streamed in. Also note the check of the pFlashPaper property,
which prevents using the function on a non-FlashPaper sprite.
Repeat this process for each function in FlashPaper, creating Director counterparts with appropriate error checking. Now you have a basic clone of the FlashPaper functionality in Director. Next, you need to look at callbacks. FlashPaper has two basic callbacks at present. onPageChanged will fire whenever the page changes in the movie and onZoomChanged fires when the user zooms in and out. These are useful if you want to keep an external text field that displays the FlashPaper file's current percentage, page number, and so forth. As a first step, Director must intercept these events when they execute; you use the setCallback command to do this:
sprite(spriteNum).setCallback(pRoot, "onPageChanged", #pageChanged,
me)
This takes the current sprite (FlashPaper) and tells it that when the onPageChanged function executes in the root of the movie that it should redirect the feedback to the pageChanged handler in the current behavior. I have taken this a step further by setting the behavior to allow the user to declare a global handler that then is called with the results. The callback handler looks something like the following:
on pageChanged me, vPage
if not pFlashPaper then return 0
if pPageCallback = "" then
put me.getCurrentPage()
else
do pPageCallback && me.getCurrentPage()
end if
end
It’s that simple. The tricky part of interacting between Director and Macromedia Flash in general is the understanding of both applications and how the two interact. This is crucial to debugging as in many cases you are dealing with functions in both apps that can reside on varying levels, inside movie clips, and so forth. It is important to understand how to correctly find the objects you need to target and carefully make the calls at the right level.
Now that the basics are in, you can write a few of your own functions to make things more useful. You already have a handler to tell FlashPaper to open to a specific page, so you'll expand this a step further and create one that does a next and back page. By combining the getCurrentPage, getNumberOfPages, and setCurrentPage handlers, you can easily handle some basic navigation dynamically.
on goNextPage me
me.setCurrentPage(min(me.getNumberOfPages(), me.getCurrentPage() +
1))
end
on goPreviousPage me
me.setCurrentPage(max(1, me.getCurrentPage() - 1))
end
You can download the full source of the project to see the code in action, or you can check it out at Mediamacros.com. Note that there are additional functions in place for hiding UI elements (and thus using your own custom ones), printing, zooming, and so forth.
FlashPaper is an example of a powerful Macromedia Flash application that you can place in a Director environment to combine the power of both tools. This is also a great opportunity to learn and familiarize yourself with how Director and Flash can interact with one another quickly and easily.
About the author
Chuck Neal is CEO of MediaMacros, Inc, and owner and operator of www.mediamacros.com , a top resource for Macromedia Director users, featuring behaviors, open source games, Xtras database, and general info on using Director. Chuck has worked in multimedia and 3D for over eight years and for such diverse clients as Coca-Cola, Hasbro Toys, Sony, DreamWorks Records, the BBC, as well as a number of commercial game and software titles. He has had articles features in numerous online publications, spoken at the Macromedia Developer’s conference, and has been a regular presence over the years on the Macromedia forums.
Chuck currently accepts projects for CD, internet, games, kiosks, installations, as well as custom components, product support and cleanup and mastering services for other multimedia firms. He has served in support roles and advisory boards for companies such as Tabuleiro and Integration New Media.