NOTE November 1, 2003:

You will most likely find this project:
http://www.shovemedia.com/chooser/index.php?xml_file=timeline_v2_beta.xml
a great deal more useful.

The ActionScript Timeline accomplishes similar tasks, only much better.

ioLib pages are kept mostly for posterity, and because occasionally (miraculously?) people still find it useful.
But personally, I use the ActionScript Timeline...

// -----------------------------------------


ioLib 2.0

copyleft 2001 - - Jon Williams - - ioResearch - - for a list of contributors call _root.ioAuthors()
this module is covered by the GNU LIMITED GENERAL PUBLIC LICENSE - - NO WARRANTY
see LGPL.txt for details - - Do not remove this notice

// -----------------------------------------

Examples

Download

// -----------------------------------------


// NEW!

* Object.io namespace to hold library functions without dirtying _root
* io.implements helps you achieve the ultimate separation of code and graphics
* io.MovieClip extension prototype
* io.Mask masking framework
* ioDebug upgrade
* io.Callback
* improved io.loadMovie
* io.isNested

// Known Issues

* objAttraction and other movements based upon the position of another object
do not yet have the option of converting coordinates to global values

send comments, suggestions, & additions to jon@ioResearch.com

// Contents

Installation Instructions

ioDebug

Object.io.frameLoop
Object.io.callback
Object.io.clutch
Object.io.bufferedClutch
Object.io.xmlToObj
Object.io.objToXml
Object.io.loadMovie
Object.io.setVars
Object.io.isNested

Object.io.implements

Object.io.MovieClip.ioRemoveFrameLoops
Object.io.MovieClip.ioRemoveFrameLoopsRecursive
Object.io.MovieClip.ioRemoveMovieClip
Object.io.MovieClip.ioUnloadMovie
Object.io.MovieClip.ioSetRGB
Object.io.MovieClip.ioSetHex
Object.io.MovieClip.addForce
Object.io.MovieClip.killForce
Object.io.MovieClip.getForceIds
Object.io.MovieClip.pauseForce
Object.io.MovieClip.unpauseForce
Object.io.MovieClip.getForceState

Object.io.forces.pointAttraction
Object.io.forces.objAttraction
Object.io.forces.totalDeltaAttraction
Object.io.forces.angleAttraction
Object.io.forces.accelBy
Object.io.forces.accelAt
Object.io.forces.moveTo
Object.io.forces.moveBy
Object.io.forces.moveAt
Creating Custom Forces

Object.io.Mask

Extending the Force Concept

// -----------------------------------------

// Installation:

add the file ioLib.fla to /Macromedia/Flash5/Libraries
add the file ioLib.txt to the directory containing your project

open Flash 5

select "Window" menu >> "Common Libraries" >> "ioLib"
the ioLib.fla will open as a Library

drag an instance of "ac, ioStepLoops" into your movie.

add

#include "ioLib.as"

as code on the first frame of your movie.
(the ioLib.as file must be saved in the same directory as your FLA file)

WARNING:

One (and only one) copy of the ioStepLoops clip must remain on the stage throughout your project.
Be careful that loaded movies do NOT contain a copy of ioLib. Loaded movies should be
able to take advantage of ioLib as long as the container movie has ioLib installed.

If your project contains modules which rely on ioLib, and you need to add ioLib during testing,
temporarily add the ioStepLoops clip on its own layer. Add the #include "ioLib.as" line.
When testing inside the container movie, comment out the include, and turn the ioStepLoops layer into a guide.
Re-export the module swf, and then load it into your container project.

TROUBLESHOOTING:

1) If the library is successfully installed, it will write "ioLib installed" into the Output window when you test your movie in the flash authoring environment.
2) Make sure you included the ioStepLoops actionclip.
3) Read this document.
4) Take a look at template.fla This is a good starting point for creating your own projects with ioLib

ioDebug

If you've ever attempted to use the debugger included with Flash 5, the existence of this object will require no explanation.
ioDebug is a drag-and-drop replacement which will dynamically show the contents of its parent.

// Installation

Drag an instance of the "ioDebugLoader" clip from the ioLib Library into your movie. If you haven't already, follow the instructions for installing ioLib. (If ioLib is not installed, the debugger will load an alternate version which pre-includes ioLib)

The replacement debugger uses a pixel font from the Hooge family. In order to prevent problems on machines which do not have this font installed, the ioDebugLoader clip loads a swf which has the font already embedded. Be careful not to re-export swf files from ioDebugTemplate.fla if you do not have this font installed.

// Usage

Test your movie. Once the instance containing ioLib is on stage, you should see the ioDebug clip. It should list one item--the movieClip which contains it. If you added it to the main timeline, it should refer to its parent level.

Click the item in ioDebug. It should expand to show all the objects/variables it contains. Repeat this process for any movieClip or object contained inside of any other. The heirarchy is analagous to your computer's file system.

Each ioDebug entry has a red button to its left. Pressing this button causes the ioLib system to watch that object/variable for changes. Values are updated once per frame for each selected item. The button will turn green to indicate that ioDebug is watching that item. Click the button again to turn off the watch. Due to processor limitations, a watch only processes its direct children. For example, if you place a watch on the main timeline (_level0), ioDebug will indicate when movieClips appear or disappear from that timeline. However, it will not indicate changes *inside* those movieClips. Place a watch directly on the movieClip to keep its listing updated, and so on.

For best performance, only place watches on those items which need constant updates. Watching a variable requires much less processing than watching an entire object. Therefore, if you only need to watch a specific property of an object, it is better to place a watch on the specific property rather than the object itself.

References to movieClips appear with the pathname in parenthesis. This is to help distinguish between a movieClip's direct child movieClips and variable references to movieClips that are nested elsewhere.

Button instances will appear in ioDebug as "instanceXXX" movieClips with a value of "button"

ioDebug is a draggable clip. Click and drag the blue titlebar to position within your movie.

Due to popular demand, ioDebug ver 2.0 includes a scrollBar

NOTE: For usability reasons, functions that are members of Object.io.MovieClip (see below) are not shown in ioDebug

NOTE: Extended prototype chains may cause ioDebug to detect multiple function properties of the same name. This is due to funky behaviour of Flash's "for...in" loop. The first member will have a normal title (e.g. "push"), additional members will appear with an id number (e.g. "push (id:7)" ). You may notice this when debugging bufferedClutch objects.

NOTE: If you would like a taller (or shorter) ioDebug panel, you'll need to edit the height of the mask in ioDebug???Template.fla Make sure you have the Hooge pixel font family installed! ioDebug will take care of positioning the other elements.

NOTE: ioDebug uses the ioHashTable object internally. ioHashTable is not documented here because it is not yet deemed ready for public use. See ioLib.as for source and credits.

Object.io.frameLoop

the frameLoop is the heart of many of ioLib's functions. It's complex, but very powerful.

Occasionally, it's preferable to create frameloops programmatically rather than creating
movieClip objects for this purpose and then having to deal with attaching/duplicating/removing them.
Creating frameloops via code can make your projects much more maintainable.

// Constructor

Object.io.frameLoop ()
returns an empty frameLoop object

if a frameLoop object is left running, it will continue to take up system resources, and may potentially cause frameLoops created
at a later time to function incorrectly. ioLib contains a series of functions designed to make clean-up an easy process.

See:
Object.io.frameLoop.end()
Object.io.cleanLoops()
Object.io.MovieClip.ioRemoveFrameLoops()
Object.io.MovieClip.ioRemoveFrameLoopsRecursive()
Object.io.MovieClip.ioRemoveMovie()
Object.io.MovieClip.ioUnloadMovie()

// Methods

Object.io.frameLoop.addFrame ( object, method, argumentObject, argumentProperty)
  object: the object which contains the method
  method: the name of the method to run (passed as a string)
  argumentObject: the object which contains the property to be passed as an argument at runtime
    NOTE: argumentObject may be ommited and no argument will be passed to the method
  argumentProperty: the property of the argument object which will be passed to the method as an argument (passed as a string)
    NOTE: argumentProperty may be ommited, and the entire argumentObject will be passed to the method

addFrame() adds a "frame" to the frameLoop object. If you wish one action to happen repeatedly (on every frame until
the frameLoop ends) add only one "frame". If you wish two actions to happen repeatedly (each taking turns, one every
frame until the frameLoop ends) add two "frames"...etc.

  // Examples
  
// create a frameLoop for:  _root.fadeUp(10)

  myFrameLoop = new Object.io.frameLoop()

  myFrameLoop.addFrame ( _root, "fadeUp", 10)
  If the argument won't be the same each time, split it into an argumentObject and argumentProperty like this:   
// create a frameLoop for:  _root.fadeUp(_root.currentPick)

  myFrameLoop = new Object.io.frameLoop()

  myFrameLoop.addFrame ( _root, "fadeUp", _root, "currentPick")
  the frameLoop object also supports running a function to retrieve the argument for your frameloop definition:   
// create a frameLoop for:  _root.fadeUp(_root.getPick (12) )

  myFrameLoop = new Object.io.frameLoop()

  myFrameLoop.addFrame ( _root, "fadeUp", _root.getPick, 12)
  
// create a frameLoop for:  _root.fadeUp(_root.getPick () )

  myFrameLoop = new Object.io.frameLoop()

  myFrameLoop.addFrame ( _root, "fadeUp", _root.getPick)
Object.io.frameLoop.loop ()
this method is called automatically by the ioLib system. You should never need to call this method directly. It causes
the frameLoop to process one "frame". The loop() method is called on all active frameLoops, once per frame.

Object.io.frameLoop.setDone ( object, method, argumentObject, argumentProperty)

  object: the object which contains the method
  method: the name of the method to run (passed as a string)
  argumentObject: the object which contains the property to be passed as an argument at runtime
    NOTE: argumentObject may be ommited and no argument will be passed to the method
  argumentProperty: the property of the argument object which will be passed to the method as an argument (passed as a string)
    NOTE: argumentProperty may be ommited, and the entire argumentObject will be passed to the method

setDone() facilitates an action running automatically when the frameLoop is destroyed. If setDone() has been called,
the function will run automatically when end() is called. See Object.io.frameLoop.end()

Object.io.frameLoop.setLifeTime (loops)
  loops: the number of times to process the frameLoop

after running setLifeTime, end() will be called automatically after the configured number of iterations have completed.

Object.io.frameLoop.reset ()

occasionally a variable which was used for one frameLoop will be reused for a new frameLoop. It is best to call
reset() prior to calling the constructor function again. This will automatically call end() on the old instance of
frameLoop object should that be necessary.

Object.io.frameLoop.end ()

this method is used to destroy an frameLoop that is no longer needed. This MUST be done in order to free system
resources. If setDone() was called on this frameLoop, the method will be called by end().

// Properties

Object.io.frameLoop.running

true/false -- this property can be used to determine if an frameLoop is currently running.

// Related Object.io Methods

Object.io.stepLoops()

Object.io.stepLoops() is called once per frame and is responsible for calling loop() on all currently active frameLoops.
This is ordinarily handled by a clipEvent(enterframe) installed by ioLib (Remember that clip you dragged on the stage?)

Object.io.cleanLoops()

Object.io.cleanLoops() must be called periodically by any flash system which utilizes ioLib. cleanLoops is responsible
for de-registering old frameLoops. There is a slight performance hit based on the total number of frameLoops.
Although it is possible for ioLib to perform this cleanup automatically, it has no way of knowing when is a
"bad" time v/s a "good" time. Therefore, its implementation is left up to the individual project.

Object.io.Callback

This object is new to ioLib version 2.0 The callback object simplifies passing a function pointer to a number of ioLib components. Each callback uses 3 to 4 parameters. This is potentially confusing when a constructor takes more than one callback (such as the new io.loadMovie method) By using a seperate object to describe callbacks, functions that require callbacks as parameters aren't nearly so messy.

//Constructor

Object.io.callback (object, method, argumentObject, argumentProperty)
  object: the object which contains the method
  method: the name of the method to run (passed as a string)
  argumentObject: the object which contains the property to be passed as an argument at runtime
    NOTE: argumentObject may be ommited and no argument will be passed to the method
  argumentProperty: the property of the argument object which will be passed to the method as an argument (passed as a string)
    NOTE: argumentProperty may be ommited, and the entire argumentObject will be passed to the method

returns a callback object populated with the specified method definition.

Object.io.clutch

One of the more common tasks in flash development is finding a way to link the properties of two objects.
Flash has a built-in function -- startDrag() -- for linking the x/y properties of a movieClip to the mouse x/y,
but what to do if you'd like to create your own links?

if an clutch object is left running (engaged), it will continue to take up system resources, and may potentially cause frameLoops
created at a later time to function incorrectly (if its container movie is destroyed, for instance). ioLib contains a series of functions
designed to make clean-up an easy process.

See:
Object.io.clutch.disengage()
Object.io.MovieClip.ioRemoveFrameLoopsRecursive()
Object.io.MovieClip.ioRemoveMovie()
Object.io.MovieClip.ioUnloadMovie()

// Constructor

Object.io.clutch ( inObject, inProperty, outObject, outProperty )
  inObject: the object containing the source data
  inProperty: the property of inObject containing the source data (passed as a string)
  outObject: the object to which data will be passed
  outProperty: the property of outObject which will be set by ioClutch. (passed as a string)

the constructor returns a clutch object with the specified linkage, but does not begin processing.

// Methods

Object.io.clutch.engage()

calling engage() causes the linkage to take effect.

Object.io.clutch.disengage()

calling disengage() causes the linkage to be temporarally paused (thus not taking processor time),
yet without destroying the clutch object.

Object.io.clutch.setTransform (function)
  function: the function which will be used to convert from inObject "coordinates" to outObject "coordinates"

often, the relationship between the linked objects is not 1:1 ioLib allows the programmer to create transform
functions which will be automatically called by a running clutch. Transform functions will recieve the following parameters:

  inObject: the inObject with which the clutch was created.
  outObject: the outObject with which the clutch was created.
  inValue: the current value of inObject[inProperty]

Transform functions are expected to then return the correct value for outObject[outProperty]

In most cases, the relationship is a linear one. Here's a template transform function for use as an example.

//LINEAR EXAMPLE
xform1 = function (inObj, outObj, inValue) {

var inLow = 10
var inHi = 25
var outLow = 100
var outHi = 200

var outValue = (((inValue-inLow)/(inHi - inLow)) * (outHi - outLow)) + outLow

return outValue
}

to use this function as your clutch transform:

myClutch.setTransform (xform1)

Object.io.clutch.setLinger (frames)
  frames: number of frames to continue processing after disengage()

In systems which utilize multiple clutch objects, it may become necessary for processing to continue for a few
frames past the disengage() call in order for data to be successfully recognized and migrated. This is especially
true if the inObject of one clutch is the outObject of another clutch.

// Properties

Object.io.clutch.ratio

In those cases in which you do not wish to use a transform function, but there is a constant relationship
between inProperty and outProperty, set the ratio property of the clutch (default is 1)

//RATIO EXAMPLE

myClutch.ratio = 2 //to multiply the inProperty by 2 before setting outProperty
myClutch.ratio = (1/3) //to divide the inProperty by 3 before setting outProperty


Object.io.clutch.buffer

The buffer property contains the last known value of inObject[inProperty]

// Performance

Projects which rely heavily on the clutch object (more than 20 in movies which are already performance-challenged) may
experience a performance hit. The dynamic nature of the object contains some inherent inefficiencies. Developers are generally
advised to continue using the clutch object until the project is complete. During the optimization process, clutch objects
can be systematically converted to clipEvents with very little effort. The structure imposed by the clutch object lends itself
towards an overall reduced development time and easy conversion to more efficient routines. In addition, the ability to dynamically
start and stop the clutch object can oftentimes make it *more* efficient than the same system built utilizing clipEvents.

Object.io.bufferedClutch

See Object.io.clutch for full description. bufferedClutch extends the clutch object by offering a setBufferLength method.
There are times in which values of inObject[inProperty] should be recorded for later use and/or the
outObject should be updated out-of-step from the inObject.

// Constructor

Object.io.bufferedClutch ( inObject, inProperty, outObject, outProperty )
  inObject: the object containing the source data
  inProperty: the property of inObject containing the source data (passed as a string)
  outObject: the object to which data will be passed
  outProperty: the property of outObject which will be set by ioClutch. (passed as a string)

the constructor returns an bufferedClutch object with the specified linkage.

Object.io.bufferedClutch.setBufferLength ( bufferLength )
  bufferLength: number of slots in the buffer

the buffer's length is set to bufferLength and all slots in the buffer are populated with
the current value of inObject[inProperty]

Object.io.bufferedClutch.setNoDelay()


it may be desirable to retain a history in the clutch while keeping outObject synchronized with
the most current value as opposed to the oldest value. Call setNoDelay() to accomplish this.

Object.io.bufferedClutch.setDelay ( delay )
  delay: the delay (in frames) between a value being read from inObject[inProperty] and being sent to
    outObject[outProperty]

it may be desirable to retain a history in the clutch that is longer than the delay between property
updates. Calling setDelay() allows finer control than simply using setNoDelay().

// Properties

Object.io.bufferedClutch.buffer

The buffer property of a bufferedClutch is an Array.

The most recent values of inObject[inProperty] are located at the end of the Array:

newest = myBufClutch.buffer[myBufClutch.buffer.length-1]


The oldest values of inObject[inProperty] are located at the beginning of the Array:

oldest = myBufClutch.buffer[0]

Object.io.cmlToObj

xmlToObj is a utility function used to create an Object using the attribute/value pairs passed in an xmlNode.

// Usage

myObject = Object.io.xmlToObj (xmlObject)

the attribute/value pairs found in xmlObject are used to populate myObject

// Example

myXML = new XML ("<exampleData name='bill' ss='241-95-0000' x='17' y='20' />")
myObject = Object.io.xmlToObj (myXML.childNodes[0]) // send the first (and only) childNode, not the whole document

//myObject.name = "bill"
//myObject.ss = "241-95-0000"
//myObject.x = "17"
//myObject.y = "20"


NOTE: to convert string values to numeric values for use in computation:
myObject.x = Number (myObject.x)

Object.io.objToXml

Object.io.objToXML is a utility function used to create an XML Object using the data stored in a movieClip or Object.

// Usage

myXML = Object.io.objToXML ("nodeName", myObject)

the attribute/value pairs found in myObject are used to populate myXML. Passing a movieClip reference will create
an XML object containing data for _x, _y, _alpha, _xscale, _yscale, _target, etc

// Example

myObject = new Object ()
myObject.x = 27
myObject.y = 100
myObject.name = "bill"
myObject.color = "FFCC00"

myXML = Object.io.objToXML ("myObjectData", myObject)

trace (myXML)

//Should return:
// <myObjectData x="27" y="100" name="bill" color="FFCC00" />



Object.io.loadMovie

the ability to load external swf files as movieClips is very powerful and often used when the developer would like to use a template.
This proves difficult in practice as it becomes neccessary to create and keep track of preloaders and to wait until the movieClip
is completely loaded to populate it with data. The more movies you're attempting to load at once, the more difficult the proceedure
becomes.

// Usage

Object.io.loadMovie (myMovieClip, path, varsObject, completeCallback, percentageCallback)
  myMovieClip: the containerClip the swf will be loaded into
  path: path to the swf file that should be loaded
  vars: an object containing the data which should be sent to this movieClip once it is fully loaded
  completeCallback: a callback object which describes the method that should be run once the movieClip is fully loaded
  percentageCallback: a callback object which describes the method that should be notified with loading progress.

Object.io.loadMovie will automatically discard the contents of myMovieClip. If the movieClip contains ioFrameLoop objects, they will
be removed via the end() method. See Object.io.MovieClip.ioUnloadMovie().

Often, you'll need to use movieClip.attachMovie() to create a movieClip instance to run Object.io.loadMovie() upon.
The ioLib library contains a linked movieClip object called "empty" which can be used for this purpose.

If the percentageCallback attribute has been set, its function definition will be called every frame while the movie is loading. This allows the developer to easily implement a status bar or progress animation. If the argumentObject/argumentProperty of the percentageCallback object was set, the callback will be in the form of:
obj.method(arg, percentLoaded)
if not, the callback will be in the form of:
obj.method(percentLoaded)
This feature allows the developer to take advantage of the full callback object since the percentage argument (passed automatically by ioLoadMovie) doesn't displace any user-defined argument.

NOTE: movies loaded with Object.io.loadMovie are loaded with visibility set to false. This allows the developer complete control over
when/where/how the loaded movie appears.

To automatically show the movie once it is loaded, add a _visible attribute to the varsObject:

myVarsObject = new Object()
myVarsObject._visible = true

Object.io.loadMovie (myMovie, "myExternal.swf", myVarsObject)
//the movie's visibility will automatically be set to true, after the movie is completely loaded.

// Example

myVarsObject = new Object()
myVarsObject._visible = true
myVarsObject._x = 200
myVarsObject._y = 50
myVarsObject.name = "bob"

myCompleteCallback = new _root.ioCallback ( _root, "notifyMe", myMovie, name)
myPercentageCallback = new _root.ioCallback ( _root, "updateStatus", name)

Object.io.loadMovie (myMovie,"myExternal.swf", myVarsObject, myCompleteCallback, myPercentageCallback)
//once the movie is loaded, it will be moved to _x = 200, _y = 200
//its visibility will be set to true
//a variable called "name" will be set to "bob" on the movieClip's timeline
//the ioLib system will automatically call: _root.notifyMe(myMovie.name)
//which in this case will be equivalent to: _root.notifyMe("bob")

// Properties

myMovie.ioLoadedPercent

the amount of a movie being loaded via ioLoadMovie that has loaded (0 - 100)

myMovie.ioLoaded

true if the movie is completely loaded, false or null otherwise


Object.io.setVars

sets the variables in a movieClip equal to the variables in another movieClip or Object

// Usage

Object.io.setVars (myMovieClip, varsObject)
  myMovieClip: the movieClip which will have variables set   varsObject: an object containing the data to populate myMovieClip

// Example

myVars = new Object
myVars._x = 100
myVars._y = 50
myVars._alpha = 70
myVars._rotation = 90
myVars.name = "sharron"
myVars.id = 123456

Object.io.setVars (myMovieClip, myVars)

//or

Object.io.setVars (myMovieClip, anotherMovieClip)
//sets all the values of myMovieClip equal to the values of anotherMovieClip



Object.io.implements

adds a custom object to the specified object's prototype chain. This is extremely useful for separating code and graphics. You should note that you'll need to use ioLib's implements function if you wish to access any of the Object.io.MovieClip extensions. It's easy:

// Usage

Object.io.implements (object, prototypeObject)
  object: (usually a movieClip) which should inherit the functionality of prototypeObject
  prototypeObject: an object which contains functions as properties

// Example

Object.io.implements (myMovieClip, Object.io.MovieClip)
//gives myMovieClip access to all the functions found in Object.io.MovieClip
//it is now safe to call:
myMovieClip.ioSetHex ("FFCC00")


Object.io.isNested

returns true if the specified movieClip is nested under this movieClip, otherwise false

// Usage

testVar = Object.io.isNested (myMovieClip, testMc)

Object.io.MovieClip.ioRemoveFrameLoops

calls end() on any running frameLoops in the movieClip

// Usage

myMovieClip.ioRemoveFrameLoops()
Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.ioRemoveFrameLoopsRecursive

calls end() on any running ioFrameLoops in the movieClip, including those running in any internal movieClips or ioClutches.

// Usage

myMovieClip.ioRemoveFrameLoopsRecursive()
Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.ioRemoveMovieClip

removes the movieClip (including the instance name) after calling ioRemoveFrameLoopsRecursive()

// Usage

myMovieClip.ioRemoveMovieClip()
Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.ioUnloadMovie

unloads movie (leaving the instance name) after calling ioRemoveFrameLoopsRecursive()

// Usage

myMovieClip.ioUnloadMovie()

Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first

NOTE: the output window within the Flash authoring environment may display an error which looks something like:
Error opening URL "file:///D|/projects/flash/"

This is because of a peculiarity of using movieClip.unloadMovie(). ioUnloadMovie uses movieClip.unloadMovie() internally.
This warning should not affect the performance of your projects.


Object.io.MovieClip.ioSetRGB

sets the color of a movieClip object to an RGB value

// Usage

myMovieClip.ioSetRGB (r,g,b)
  r: red component (0 - 255)
  g: green component (0 - 255)
  b: blue component (0 - 255)

// Example

myMovieClip.ioSetRGB (255,255,255)
//turns myMovieClip white

Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.ioSetHex

sets the color of a movieClip object to a hexidecimal value

// Usage

myMovieClip.ioSetHex ( hex )
  hex: hexidecimal value used to set color (passed as a string)

// Example

myMovieClip.ioSetHex ("FFFF00")
//turns myMovieClip yellow

Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.addForce

adds a movement behavior to a movieClip object and returns a unique force id. See Object.io.MovieClip.killForce()

// Usage

myMovieClip.addForce ( forceFn, arg1, arg2, arg3...)
  forceFn: force function to use on this movieClip. Must be a member of Object.io.forces (passed as a string)
  argN: arguments to be passed to the force function -- force specific

// Example

myForceId = myMovieClip.addForce ("objAttraction", mc12, .2, .8)
//myMovieClip will now be attracted to mc12

Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.killForce

removes a movement behavior from a movieClip object

// Usage

myMovieClip.killForce ( forceId )
  forceId: the force id of the force to remove. See Object.io.MovieClip.addForce()

// Example

myMovieClip.killForce (myForceId)
Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.getForceIds

returns an array containing the ids of all forces currently acting upon this movieClip, including any that may be paused.

// Usage

myForceList = myMovieClip.getForceIds ()

// Example

myForceList = myMovieClip.getForceIds ()

var myFlag = true
for (var i in myForceList) {
  if (myMovieClip.getForceState[myForceList[i]]) {
    myFlag = false
  }
}
if (myFlag) {
  //only perform the actions here if there are no forces acting on myMovieClip
}


Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.pauseForce

temporarily stops a movement behavior without killing the force

// Usage

myMovieClip.pauseForce ( forceId )
  forceId: the force id of the force to pause. See Object.io.MovieClip.addForce()

// Example

myMovieClip.pauseForce (myForceId)
Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.unPauseForce

resumes a movement behavior that was previously paused

// Usage

myMovieClip.unPauseForce ( forceId )
  forceId: the force id of the force to resume. See Object.io.MovieClip.addForce()

// Example

myMovieClip.unPauseForce (myForceId)
Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first


Object.io.MovieClip.getForceState

returns true if the force is running, false if the force is paused or no longer active

// Usage

myBoolean = myMovieClip.getForceState ( myForceId )
  forceId: the force id of the force to test

// Example

myBoolean = myMovieClip.getForceState ( myForceId )
if (myBoolean) {
  trace ("force " + myForceId + " is active.")
}
else {
  trace ("force " + myForceId + " is inactive.")
}



Note: Object.io.implements must be used to add the Object.io.MovieClip extensions to myMovieClip first

Object.io.forces.pointAttraction

attracts or repells to/from an x,y coordinate

// Usage

myMovieClip.addForce ("pointAttraction", x, y, accel, accelUnits, frictionPercent, range, killFlag)
  x: x coordinate to attract/repell to/from
  y: y coordinate to attract/repell to/from
  accel: acceleration constant: positive values attract, negative values repell
  accelUnits: acceleration units:
    "pc" -- percent, each itteration, the movement force will be a percentage of the distance
    "px" -- pixels, each itteration, the movement force will be a number of pixels
  frictionPercent: (0 - 1) percentage of momentum that is maintained from the last iteration.
    values close to 0 retain little momentum, values close to 1 retain most of their momentum.
  range: range is the distance, in pixels from the x/y coordinate, at which this force will begin decay.
    A null range sets an infinite range.
  killFlag: (true/false) should this force be automatically removed once the specified range has been
    reached? Default is true. This attribute is most often used with repulsion (negative acceleration).

NOTE: killFlag may initially appear to be a redundant feature in light of the "range" attribute.
Keep in mind that multiple forces may act on the same object resulting in the movieClip being
brought *back* into range. killFlag allows the developer to control behavior under these
circumstances.

// Examples

//move to (150, 200) accelerating 10% per frame with low enough friction (.9) to give some "springyness"
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("pointAttraction", 150, 200, .1, "pc", .9)

//move to (150, 200) accelerating 4 pixels per frame until 6 pixels away
//with low enough friction (.9) to give some "springyness"
//NOTE: ommiting range with with acceleration measured in pixels may not produce the intended effect
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("pointAttraction", 150, 200, 4, "px", .9, 6)

//move away from (150, 200) accelerating 10% per frame until at least 200 pixels away
//with low enough friction (.9) to give a smooth stop
//kill the force once this range has been reached
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("pointAttraction", 150, 200, -.1, "pc", .9, 200, true)

//move away from (150, 200) accelerating 4 pixels per frame until at least 200 pixels away
//with low enough friction (.9) to give a smooth stop
//keep this force active. If myMovieClip gets close enough to (150,200), this force will take effect again.
//NOTE: using repulsion (negative acceleration) with acceleration measured in pixels may not produce the intended effect
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("pointAttraction", 150, 200, -4, "px", .9, 200, false)



Object.io.forces.objAttraction

attracts or repells to/from a movieClip object's coordinates

// Usage

myMovieClip.addForce ("objAttraction", mc, accel, accelUnits, frictionPercent, range, killFlag)
  mc: movieClip whose x/y coordinate to attract/repell to/from
  accel: acceleration constant: positive values attract, negative values repell
  accelUnits: acceleration units:
    "pc" -- percent, each itteration, the movement force will be a percentage of the distance
    "px" -- pixels, each itteration, the movement force will be a number of pixels
  frictionPercent: (0 - 1) percentage of momentum that is maintained from the last iteration.
    values close to 0 retain little momentum, values close to 1 retain most of their momentum.
  range: range is the distance, in pixels from the x/y coordinate, at which this force will begin decay.
    A null range sets an infinite range.
  killFlag: (true/false) should this force be automatically removed once the specified range has been
    reached? Default is true. This attribute is most often used with repulsion (negative acceleration).

NOTE: killFlag may initially appear to be a redundant feature in light of the "range" attribute.
Keep in mind that multiple forces may act on the same object resulting in the movieClip being
brought *back* into range. killFlag allows the developer to control behavior under these
circumstances.

// Examples

//move towards mc2 accelerating 10% per frame with low enough friction (.9) to give some "springyness"
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("objAttraction", mc2, .1, "pc", .9)

//move towards mc2 accelerating 4 pixels per frame until 6 pixels away
//with low enough friction (.9) to give some "springyness"
//NOTE: ommiting range with with acceleration measured in pixels may not produce the intended effect
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("objAttraction", mc2, 4, "px", .9, 6)

//move away from mc2 accelerating 10% per frame until at least 200 pixels away
//with low enough friction (.9) to give a smooth stop
//kill the force once this range has been reached
myMovieClip.ioAddForce ("ioObjAttraction", mc2, -.1, "pc", .9, 200, true)

//move away from mc2 accelerating 4 pixels per frame until at least 200 pixels away
//with low enough friction (.9) to give a smooth stop
//keep this force active. If mc2 gets close enough, this force will take effect again.
//NOTE: using repulsion (negative acceleration) with acceleration measured in pixels may not produce the intended effect
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("objAttraction", mc2, -4, "px", .9, 200, false)



Object.io.forces.totalDeltaAttraction

attracts or repells to/from a total x/y change

// Usage

myMovieClip.addForce ("totalDeltaAttraction", dx, dy, accel, accelUnits, frictionPercent, range)
  dx: distance on the x-axis from this movieClip to attract/repell to/from
  dy: distance on the y-axis from this movieClip to attract/repell to/from
  accel: acceleration constant: positive values attract, negative values repell
  accelUnits: acceleration units:
    "pc" -- percent, each itteration, the movement force will be a percentage of the distance
    "px" -- pixels, each itteration, the movement force will be a number of pixels
  frictionPercent: (0 - 1) percentage of momentum that is maintained from the last iteration.
    values close to 0 retain little momentum, values close to 1 retain most of their momentum.
  range: range is the distance, in pixels from the x/y coordinate, at which this force will begin decay.
    ommiting the range attribute sets an infinite range.

// Example

//move 50 pixels to the right, 80 pixels up, accelerating 10% per frame with low enough friction (.9) to give some "springyness"
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("totalDeltaAttraction", 50, -80, .1, "pc", .9)



Object.io.forces.angleAttraction

attracts or repells to/from a total x/y change

// Usage

myMovieClip.addForce ("angleAttraction", theta, totalDistance, accel, accelUnits, frictionPercent, range)
  theta: angle (in degrees) to attract/repell to/from
  totalDistance: total distance from this movieClip to attract/repell to/from
  accel: acceleration constant: positive values attract, negative values repell
  accelUnits: acceleration units:
    "pc" -- percent, each itteration, the movement force will be a percentage of the distance
    "px" -- pixels, each itteration, the movement force will be a number of pixels
  frictionPercent: (0 - 1) percentage of momentum that is maintained from the last iteration.
    values close to 0 retain little momentum, values close to 1 retain most of their momentum.
  range: range is the distance, in pixels from the x/y coordinate, at which this force will begin decay.
    ommiting the range attribute sets an infinite range.

// Example

//move towards 1 o'clock (35 degrees) by 80 pixels, accelerating 10% per frame with low enough friction (.9) to give some "springyness"
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("angleAttraction", 35, 80, 0, .1, "pc", .9)



Object.io.forces.accelBy

accelerates the movieClip at the specified rate for the specified number of frames, then slows to a stop.

// Usage

myMovieClip.addForce ("accelBy", accelRateX, accelRateY, frictionPercent, lifeTime)
  accelRateX: rate of acceleration along x-axis (positive values move right, negative values move left)
  accelRateY: rate of acceleration along y-axis (positive values move down, negative values move up)
  frictionPercent: (0 - 1) percentage of momentum that is maintained from the last iteration.
  lifeTime: lifeTime of this force in frames. After this number of iterations, the movieClip will cease to accelerate
    and will begin to slow to a stop (via frictionPercent)

// Example

// accelerate down and to the right for 5 frames
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("accelBy", 5, 10, .9, 5)



Object.io.forces.accelAt

accelerates the movieClip at the specified angle and rate for the specified number of frames, then slows to a stop.

// Usage

myMovieClip.addForce ("accelAt", theta, accelRate, frictionPercent, lifeTime)
  theta: angle (in degrees) at which to accelerate
  accelRate: rate of acceleration (in pixels)
  frictionPercent: (0 - 1) percentage of momentum that is maintained from the last iteration.
  lifeTime: lifeTime of this force in frames. After this number of iterations, the movieClip will cease to accelerate
    and will begin to slow to a stop (via frictionPercent)

// Example

// accelerate towards 1 o'clock (35 degrees) by 10 pixels per frame for 5 frames
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("accelAt", 35, 10, .9, 5)



Object.io.forces.moveTo

moves the movieClip to the x/y coordinate in steps of delta

// Usage

myMovieClip.addForce ("moveTo", x, y, delta)
  x: the x coordinate to move to
  y: the y coordinate to move to
  delta: the number of pixels to move per frame

// Example

//move to 20, 50 in 2 pixel increments
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("moveTo", 20, 50, 2)



Object.io.forces.moveBy

moves the movieClip by the specified amounts in steps of delta

// Usage

myMovieClip.addForce ("moveBy", dx, dy, delta)
  dx: the distance to move along the x-axis
  dy: the distance to move along the y-axis
  delta: the number of pixels to move per frame

// Example

//move to 20 pixels right, 50 pixels down, in 2 pixel increments
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("moveBy", 20, 50, 2)



Object.io.forces.moveAt

moves the movieClip at the specified angle for the specified distance in steps of delta

// Usage

myMovieClip.addForce ("moveAt", theta, totalDist, delta)
  theta: the angle (in degrees) at which to move
  totalDist: the total distance to move
  delta: the number of pixels to move per frame

// Example

//move towards 1 o'clock (35 degrees), 50 pixels in 2 pixel increments
Object.io.implements (myMovieClip, Object.io.MovieClip)
myMovieClip.addForce ("moveAt", 35, 50, 2)



//Properties

movieClip.ioDx

The amount the movieClip will move along the x-axis during this frame. ioDx is reset to zero by ioLib
each frame. Custom force functions should add to ioDx. Otherwise, this property should only be modified via addForce.
In addition, calculations based on the current value will behave erratically.

movieClip.ioDy

The amount the movieClip will move along the y-axis during this frame. ioDy is reset to zero by ioLib each
frame. Custom force functions should add to ioDy. Otherwise, this property should only be modified via addForce.
In addition, calculations based on the current value will behave erratically.

movieClip.ioVx

The current speed of the movieClip along the x-axis. This value is calculated based on movement completed
during the last frame update. This property is read-only.

movieClip.ioVy

The current speed of the movieClip along the y-axis. This value is calculated based on movement completed
during the last frame update. This property is read-only.

// Creating Custom Forces

The forces included with ioLib are a good starting point for creating your own custom force functions.
All force functions are expected to follow the following syntax:

forceFn (mc, args, data, ioForceId)
  mc: the movieClip object to act upon
  args: an array containing the arguments which configure this specific force
    (e.g. coordinates to seek, an acceleration rate, friction constant, etc)
  data: an object containing data specific to this instance of the force which will be reused from frame to frame
    (e.g. acceleration, a force "lifetime" counter, etc)
  ioForceId: the id of the current force.

First, your force function must be accessible to any movieClip which will attempt to utilize it.
The io.force system ensures this by forcing you to attach your force functions to the Object.io.forces object.
This will provide access to the force function from any movieClip in your project.

// Example

Object.io.forces.newForce = function (mc, args, data, ioForceId) {
  //force code here
}


Next, if your force needs to utilize iteration data over time, try to avoid storing this information directly in
the movieClip. Instead, use the data argument. Although slightly more complicated, this allows one movieClip to
utilize more than one of the same kind of force.

To use the data argument, simply return an object containing your data at the end of your force function. It will
be passed back to the function (also as an object) during the next iteration.

// Example

Object.io.forces.newForce = function (mc, args, data, ioForceId) {
  
  //how much influence did this force have last time?
  var dx = data.dx
  var dy = data.dy

  //...edited for clarity...
  
  //save this iteration's change data for next time.
  var dataObj = new Object()
  dataObj.dx = dx
  dataObj.dy = dy

  return dataObj
}


Your force influences a movieClip by manipulating its ioDx and ioDy properties instead of changing the _x and _y
properties directly. Again, this adds complexity, but allows you to have lots of forces influencing a single movieClip.

// Example

Object.io.forces.newForce = function (mc, args, data, ioForceId) {
  this.ioDx += 10
  //this force will create an influence to move an object to the right
  //10 pixels per frame until it is destroyed.
}



// Extending the Force Concept

Experiment with the arguments of the included force functions and feel free to use their code as the starting point
for your own forces. They already provide a wide range of behaviors; perhaps the movement you need can be achieved
by changing the sign of an argument (for instance).

It is actually quite possible to affect properties of your movieClips other than _x and _y using the provided force system.
You may also wish to experiment with scale, alpha, rotation, etc.

In addition, forces may be the ideal solution to movement problems which do not immediately appear to be relevant.
Collision detection, bounce physics, etc are possibilities.

Object.io.Mask

Flash's masking does not currently allow the range of possibilities that are sometimes desired. Funky nestings are required to achieve the combination of effects we find ourselves desiring. Object.io.Mask offers a framework designed to allow greater control over your mask effects. Best of all, masks and the objects they mask are elligible for use with the ioLib force behavior set. This combination allows for a stunning array of possibilities.

// Usage

Any project using Object.io.Mask must import the library textfile. If you use it often, feel free to add the contents to ioLib.as

#import "ioMask.as"

To add an ioMask object to your project, first attach an ioMask template from the library. Use the example template in the ioLib.fla library as a starting point.

this.attachMovie("io.mask.star", "mask1", 1)

The actions layer of the template includes the following line of code which causes the movieClip to take on ioMask properties.

Object.io.implements(this, Object.io.mask)

Object.io.mask.setMasked

Sets the underlying masked movieClip which will be viewed through the mask. This should be an exported library clip.

// Usage

Object.io.mask.setMasked ( exportedId )

// Example

myMask.setMasked("pic1")

Object.io.mask.getMask

Returns the mask movieClip which can be used with Object.io.forces. Usage with other functions may yield undesirable results. To move, scale, or rotate the mask, use the provided utility functions.

// Usage

Object.io.mask.getMask ()

// Example

myMc = myMask.getMask()
myMc.addForce("totalDeltaAttraction",x,y,15,"px",.8,10)

Object.io.mask.getMasked

Returns the masked movieClip which can be used with Object.io.forces. Usage with other functions may yield undesirable results. To move, scale, or rotate the masked texture, use the provided utility functions.

// Usage

Object.io.mask.getMasked ()

// Example

myMc = myMask.getMasked()
myMc.addForce("totalDeltaAttraction",x,y,15,"px",.8,10)

Object.io.mask.setMaskRotation

Rotates the mask portion of an io.Mask object

// Usage

Object.io.mask.setMaskRotation (deg)
  deg: degrees to rotate

// Example

myMask.setMaskRotation(90)

Object.io.mask.setMaskX

Sets the mask x coordinate on an io.Mask object

// Usage

Object.io.mask.setMaskX (coord)
  coord: x-coordinate to move to

// Example

myMask.setMaskX(200)

Object.io.mask.setMaskY

Sets the mask y coordinate on an io.Mask object

// Usage

Object.io.mask.setMaskY (coord)
  coord: y-coordinate to move to

// Example

myMask.setMaskY(200)

Object.io.mask.setMaskXDelta

Moves the mask x coordinate of an io.Mask object by the given amount

// Usage

Object.io.mask.setMaskX (delta)
  delta: amount of change

// Example

myMask.setMaskXDelta(20)

Object.io.mask.setMaskYDelta

Moves the mask y coordinate of an io.Mask object by the given amount

// Usage

Object.io.mask.setMaskYDelta (delta)
  delta: amount of change

// Example

myMask.setMaskYDelta(-20)

Object.io.mask.setMaskXScale

Sets the mask x-scale of an io.Mask object

// Usage

Object.io.mask.setMaskXScale (scale)
  scale: percentage scale (100 = 100%)

// Example

myMask.setMaskXScale(200)

Object.io.mask.setMaskYScale

Sets the mask y-scale of an io.Mask object

// Usage

Object.io.mask.setMaskYScale (coord)
  scale: percentage scale (100 = 100%)

// Example

myMask.setMaskYScale(200)

Object.io.mask.setMaskedRotation

Rotates the masked portion of an io.Mask object

// Usage

Object.io.mask.setMaskedRotation (deg)
  deg: degrees to rotate

// Example

myMask.setMaskedRotation(90)

Object.io.mask.setMaskedX

Sets the masked x coordinate on an io.Mask object

// Usage

Object.io.mask.setMaskedX (coord)
  coord: x-coordinate to move to

// Example

myMask.setMaskedX(200)

Object.io.mask.setMaskedY

Sets the masked y coordinate on an io.Mask object

// Usage

Object.io.mask.setMaskedY (coord)
  coord: y-coordinate to move to

// Example

myMask.setMaskedY(200)

Object.io.mask.setMaskedXDelta

Moves the masked x coordinate of an io.Mask object by the given amount

// Usage

Object.io.mask.setMaskedX (delta)
  delta: amount of change

// Example

myMask.setMaskedXDelta(20)

Object.io.mask.setMaskedYDelta

Moves the masked y coordinate of an io.Mask object by the given amount

// Usage

Object.io.mask.setMaskedYDelta (delta)
  delta: amount of change

// Example

myMask.setMaskedYDelta(-20)

Object.io.mask.setMaskedXScale

Sets the masked x-scale of an io.Mask object

// Usage

Object.io.mask.setMaskedXScale (scale)
  scale: percentage scale (100 = 100%)

// Example

myMask.setMaskedXScale(200)

Object.io.mask.setMaskedYScale

Sets the masked y-scale of an io.Mask object

// Usage

Object.io.mask.setMaskedYScale (coord)
  scale: percentage scale (100 = 100%)

// Example

myMask.setMaskedYScale(200)