0 Content

1 Introduction
2 Examples
2.1 Basic examples, single file
2.2 Basic examples, multiple files
2.3 Displaying the loading progress
2.4 Using targetspecific listeners
2.5 Errorhandling
2.6 Queuemanagement
2.7 Miscellanous
3 API
3.1 Constructor
3.2 Static constants
3.3 Loading and observing targets
3.4 Managing the queue
3.5 Managing listeners
3.6 Events
3.7 Configuration
3.8 Getters, getting information about the loading process
4 FAQ
5 Donations
6 Bugs
7 Support
8 History
9 Status and copyright
10 License For Use

1 Introduction

As Colin Moock, the author of Actionscript - The Definitive Guide stated lately: Preloading still is a major problem for a lot of flashers. The different interfaces to the different filetypes (SWF, XML, Text, Sound), the asynchronous behaviour of the loading process and the uncomplete errorhandling alltogether make preloading really hard to handle. This is why Colin started a petition and proposed a new interface for preloading.
The LoaderClass is based on Colin's interface proposal. Some changes and additions had to be made, because of practical implications.

If you find the class useful and want to support further development, don't forget to donate.

2 Examples

2.1 Basic examples, single file

back

2.1.1 Loading a swf into a MovieClip given by its targetpath

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();
myLoader.load("target_mc", "myMovie.swf");

back

2.1.2 Loading a swf into a MovieClip given by reference

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();
myLoader.load( _root.mc.holder, "myMovie.swf");

back

2.1.3 Loading a swf into a level

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();
myLoader.load( 3, "myMovie.swf");

back

2.1.4 Loading a swf into a created MovieClip

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();
var mc = createEmptyMovieClip("myClip_mc", 1);
myLoader.load( mc, "myMovie.swf");

back

2.1.5 Loading a xml file

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();

x = new XML();
myLoader.load( x, "myXML.xml");

back

2.1.6 Loading a textfile

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();

lv = new LoadVars();
myLoader.load( lv, "myText.txt");

back

2.1.7 Loading a sound

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();

snd = new Sound();
myLoader.load( snd, "mySound.mp3");

back

2.1.8 Loading a streaming sound

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();

snd = new Sound();
// the additional parameter (1)
// is passed to Sound.load 
myLoader.load( snd, "mySound.mp3", null, 1);

back

2.2 Basic examples, multiple files

When loading multiple files, the LoaderClass puts all of the requests into an internal queue and executes one by one.

back

2.2.1 Loading multiple swfs into created MovieClips

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();
for( var i=0; i<10; i++){
                     var mc = createEmptyMovieClip("mc" + i, i);
                     var url = "movie" + i + ".swf";
	myLoader.load( mc, url);	
}

back

2.2.2 Loading multiple files of mixed type

#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();
myLoader.load("target_mc", "myMovie.swf");
myLoader.load( _root.mc.holder, "myMovie.swf");
myLoader.load( 3, "myMovie.swf");
x = new XML();
myLoader.load( x, "myXML.xml");
lv = new LoadVars();
myLoader.load( lv, "myText.txt");
snd = new Sound();
myLoader.load( snd, "mySound.mp3");

back

2.3 Displaying the loading progress

To display the progress you can add a listener object to the loader. The listener object provides methods to handle the events raised by the loader.

back

2.3.1 Using a simple bar

We use a simple bar, which is scaled horizontally, to show the loading progress. Since the scale of a MovieClip is a percentage value, we can directly assign the percentage of the loaded bytes.
Create a bar, place it on stage, name it bar_mc and set it to _xscale = 100.

#include "com.qlod.LoaderClass.as"

bar_mc.onLoadProgress = function( loaderObj){
	this._xscale = loaderObj.getPercent();
}

myLoader = new com.qlod.LoaderClass();
myLoader.addListener( bar_mc);
myLoader.load("target_mc", "myMovie.swf");

back

2.3.2 Using a dynamic TextField

We use a dynamic TextField to display the percentage, the bytesLoaded and the total number of bytes.
Create a dynamic TextField and set its instancename to progress_txt.

#include "com.qlod.LoaderClass.as"

progress_txt.onLoadProgress = function( loaderObj){
	this.text = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}

myLoader = new com.qlod.LoaderClass();
myLoader.addListener( progress_txt);
myLoader.load("target_mc", "myMovie.swf");

back

2.3.3 Using multiple listeners, eg. a bar and a dynamic TextField

We can use as much listener objects as we like. The following example sports both of the above listeners at once.
#include "com.qlod.LoaderClass.as"

progress_txt.onLoadProgress = function( loaderObj){
	this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}

bar_mc.onLoadProgress = function( loaderObj){
	this._xscale = loaderObj.getPercent();
}

myLoader = new com.qlod.LoaderClass();
myLoader.addListener( bar_mc);
myLoader.addListener( progress_txt);
myLoader.load("target_mc", "myMovie.swf");

back

2.4 Using targetspecific listeners

Sometimes you need a listener which listens to one specific loading process and not to all of them. This can be achieved by using the listener object as an additional parameter to load. The listener is automatically added when loading of the target starts and removed, after loading of the target is completed. The following example uses a plain object to handle the events.

back

2.4.1 Simple targetspecific listeners

#include "com.qlod.LoaderClass.as"

myListener_obj = new Object();

myListener_obj.onLoadStart = function( loaderObj){
	trace("Loading of " + loaderObj.getTarget() + " has started");
}

myListener_obj.onLoadProgress = function( loaderObj){
	trace("Percentage: " + loaderObj.getPercent());
}

myListener_obj.onLoadComplete = function( success, loaderObj){
	trace("Loading of " + loaderObj.getTarget() + " is completed");
	_root.gotoAndPlay("introduction");
}

myLoader = new com.qlod.LoaderClass();
myLoader.load("target_mc", "myMovie.swf", myListener_obj);

back

2.4.2 Advanced targetspecific listeners

The following example creates a page of thumbnails where every thumbnail shows its own loading bar.
#include "com.qlod.LoaderClass.as"

myLoader = new com.qlod.LoaderClass();

var depth = 0;
var rows = 4;
var cols = 5;
for( var i=0; i<rows; i++){
	for( var j=0; j<cols; j++){
		++depth;
		//
		var thumbnail_mc = createEmptyMovieClip("thumbnail_mc" + depth, depth);
		//
		var bar_mc = thumbnail_mc.createEmptyMovieClip("bar_mc", 0);
		bar_mc.onLoadProgress = function( loaderObj){
			this.clear();
			this.lineStyle(0, 0xff0000);
			this.lineTo( loaderObj.getPercent(), 0);	
		}
		bar_mc.onLoadComplete = function( success, loaderObj){
			this.removeMovieClip();
		}
		//
		var img_mc = thumbnail_mc.createEmptyMovieClip("img_mc", 1);
		//
		myLoader.load( img_mc, "img" + depth + ".jpg", bar_mc);			
	}
}

back

2.5 Errorhandling

Some times a file cannot be loaded because the server is down, the url is incorrect or the file simply doesn't exist. The LoaderClass raises a onTimeout-event if this happens. Handling of this event works the same way as handling the other events. Here is a simple example:
#include "com.qlod.LoaderClass.as"

myErrorHandler_obj = new Object();

myErrorHandler_obj.onTimeout = function( loaderObj){
	trace("Timeout-Error: The file " + loaderObj.getUrl() + " could not be loaded.");
}

myLoader = new com.qlod.LoaderClass();
myLoader.addListener( myErrorHandler_obj);
myLoader.load("target_mc", "notExistent.swf");

back

The default timeout interval is 10 (ten) seconds. You can change it through a call to myLoader.setTimeoutMs( newLengthMs).

2.6 Queuemanagement

Think about a system consisting of a menue, which loads different swfs into a content area. If the user chooses an entry, the menue sends a request to our loader and the loader loads the swf into the content MovieClip. If the swfs are big enough, there is a chance, that the user suddenly wants to visit another area than the currently loading one. To handle this, we need a notion of "breaking" the current loading process. The LoaderClass provides three methods for this:

Create a mc named content_mc and two other mcs, named button1_mc and button2_mc.

#include "com.qlod.LoaderClass.as"

myLoader = new LoaderClass();

function loadContent( url){
	myLoader.clear();
	myLoader.load( content_mc, url);
}

button1_mc.onRelease = function(){
	loadContent("movie1.swf");
}

button2_mc.onRelease = function(){
	loadContent("movie2.swf");
}

back

2.7 Miscellanous

back

2.7.1 Delaying the progress events

Sometimes loading happens so fast, that you can't see and control your loading animation. The following example shows you how to set the minimum number of steps your preloader shows. Create a dynamic TextField and set its instancename to progress_txt.
#include "com.qlod.LoaderClass.as"

progress_txt.onLoadProgress = function( loaderObj){
	this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}

myLoader = new com.qlod.LoaderClass();

// show 5 steps at least
myLoader.setMinSteps( 5);
myLoader.addListener( progress_txt);
myLoader.load("target_mc", "myMovie.swf");
If you delay the progress events, special care is needed, because your loaded movie starts playing automatically. A common approach is to add an empty frame to the loaded movie with just a stop action in it. Then you are able / have to start the movie explicitely in your onLoadComplete-handler (or later). If you don't want to change the movie, you can also set its alpha to zero onLoadStart and to 100 onLoadComplete. If your movie has more than one frame, you also have to take care of the correct frame.

back

2.7.2 Observing the main timeline

If you wish to watch the main timeline loading, you can use observe instead of load. Create a dynamic TextField and set its instancename to progress_txt.
#include "com.qlod.LoaderClass.as"

progress_txt.onLoadProgress = function( loaderObj){
	this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}

myLoader = new com.qlod.LoaderClass();

// show 5 steps at least
myLoader.setMinSteps( 5);
myLoader.addListener( progress_txt);
myLoader.observe(this);

back

3 API

3.1 Constructor

Creates an instance of the loader class.
MyLoader = new com.qlod.LoaderClass( [piTimeOutMs [, piIntervalMs [, piMinSteps]]]);
param piTimeoutMs
integer, optional, specifies the milliseconds until a timeoutError is raised, default 10000

param piIntervalMs
integer, optional, specifies the length of the interval which checks the loadingprogress, default 100

param piMinSteps
integer, optional, specifies the number of minimum steps, the loadingprocess is divided into, default 1


back

3.2 Static constants

com.qlod.LoaderClass .DEFAULT_TIMEOUT_MS
If setTimeoutMs() is called without a valid parameter, this value is taken instead

com.qlod.LoaderClass .DEFAULT_INTERVAL_MS
If setIntervalMs() is called without a valid parameter, this value is taken instead

com.qlod.LoaderClass .DEFAULT_MIN_STEPS
If setMinSteps() is called without a valid parameter, this value is taken instead

back

3.3 Loading and observing targets

3.3.1 Loading

id = myLoader.load( pLoc, psUrl [, poListener [, pAdditionalParameter ]]])
Start loading the swf at url into the given location loc.

param pLoc
integer || string || object, specifies the level, path or object to load into

param psUrl
string, specifies the url to load from

param poListener
object, specifies a listener solely for this item. This listener is added automatically if the loading of the item starts and removed automatically, if the loading is completed.

param pAdditionalParameter
this and any more parameters are transparently passed to the load method of the item, e.g. you can use it to pass a stream parameter to a call of sound.load

return integer
returns an unique id


back

3.3.2 Observing

Id = myLoader.observe( pLoc [, psUrl [, poListener]] )
Start observing the given location loc. This works the same as load, but the thing to observe is already loading. You can use it to preload the main timeline for example.

param pLoc
integer || string || object, specifies the level, path or object to load into

param psUrl
string, optional, specifies the url which is loaded from. If the url is not a string, the property pLoc._url is taken instead.

param poListener
object, specifies a listener solely for this item. This listener is added automatically if the loading of the item starts and removed automatically, if the loading is completed.

return integer
returns an unique id


back

3.4 Managing the queue

3.4.1 Clearing the queue completely

myLoader.clear()
Clear the queue and stop the current loading process

back

3.4.2 Remove a specific item

myLoader.remove( pId)
Remove the item with the given id ( which was previously returned by load or observe)

param pId
integer, specifies the item to remove from the loading queue

back

3.4.3 Remove the current item

myLoader.removeCurrent()
Stop the currently loading item and head on to the next in the queue (if any)

back

3.5 Managing listeners

3.5.1 Adding listeners

myLoader.addListener( pObj)
Add a listener object to our listeners list.

param pObj
object, the listener object handles the events raised by the loader

back

3.5.2 Removing listeners

myLoader.removeListener( pObj)
Remove a listener object from our listeners list.

param pObj
object, the listener object to remove

back

3.6 Events

The following events are raised by the LoaderClass.

3.6.1 onQueueStart

yourListener.onQueueStart( pLoaderObj)
This event is fired when loading of the items in the queue starts.

param pLoaderObj
LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.

back

3.6.2 onQueueStop

yourListener.onQueueStop( pLoaderObj)
This event is fired when the queue exhausts.

param pLoaderObj
LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.

back

3.6.3 onLoadStart

yourListener.onLoadStart( pLoaderObj)
This event is fired when loading starts.

param pLoaderObj
LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.

back

3.6.4 onLoadComplete

yourListener.onLoadComplete( pSuccess, pLoaderObj)
This event is fired when loading is completed.

param pSuccess
Boolean, true if loading succeded, false otherwise
param pLoaderObj
LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.

back

3.6.5 onLoadProgress

yourListener.onLoadProgress( pLoaderObj)
This event is fired on every interval while the item is loading

param pLoaderObj
LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.

back

3.6.6 onLoadTimeout

yourListener.onLoadTimeout( pLoaderObj)
This event is fired, when the webserver doesn't start sending within the timeout interval.

param pLoaderObj
LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.

3.7 Configuration

3.7.1 setTimeoutMs

myLoader.setTimeoutMs( [piMilliseconds])
Sets the actual length of the timeout. If the timeoutMs is not a number, the defaultvalue is set.

param piMilliseconds
integer, optional, specifies the new length of the timeout in milliseconds
return integer
returns the current value

back

3.7.2 getTimeoutMs

myLoader.getTimeoutMs()
Returns the actual length of the timeout interval

return integer
returns the current value in milliseconds

back

3.7.3 disableTimeout

myLoader.disableTimeout()
Completely disable timeout handling

back

3.7.4 enableTimeout

myLoader.enableTimeout()
Enable timeouthandling. Timeouthandling is enabled by default.

back

3.7.5 setIntervalMs

myLoader.setIntervalMs( [piMilliseconds])
Sets the actual length of the checkinterval. If the intervalMs is not a number, the default value is set

param piMilliseconds
integer, optional, specifies the new length of the interval in milliseconds
return integer
returns the current value

back

3.7.6 getIntervalMs

myLoader.getIntervalMs()
Returns the actual length of the checkinterval.

return integer

back

3.7.7 setMinSteps

myLoader.setMinSteps( [piMinSteps])
Sets the minimum number of steps. Every preloading process takes at least this much steps. If the piMinSteps is not a number, the default value is set.

param piMinSteps
integer, optional, specifies the new iMinSteps
return integer
returns the current value

back

3.7.8 getMinSteps

myLoader.getMinSteps()
Returns the actual value of minSteps

return integer

3.8 Getters, getting information about the loading process

Inside your eventhandlers you can use the following methods to retrieve the information you need. Here is a small example which uses getPercent, getBytesLoaded and getBytesTotal to display some information in a dynamix TextField.
#include "com.qlod.LoaderClass.as"

progress_txt.onLoadProgress = function( loaderObj){
	this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}

myLoader = new com.qlod.LoaderClass();

myLoader.addListener( progress_txt);
myLoader.observe(this);

back

3.8.1 isLoading

loaderObj.isLoading()
returns true if the loader is loading

return boolean

back

3.8.2 getBytesLoaded

loaderObj.getBytesLoaded()
returns the current bytes loaded or 0

return integer >= 0

back

3.8.3 getBytesTotal

loaderObj.getBytesTotal()
returns the current bytes total or 1

return integer >= 1

back

3.8.4 getKBLoaded

loaderObj.getKBLoaded()
returns the current bytes loaded or 0 in KB

return integer >= 0

back

3.8.5 getKBTotal

loaderObj.getKBTotal()
returns the current bytes total or 1 in KB

return integer >= 1

back

3.8.6 getPercent

loaderObj.getPercent()
returns the relation of loaded and total bytes in percent

return integer >= 0

back

3.8.7 getDuration

loaderObj.getDuration()
returns the current duration of the loading process in milliseconds

return integer >= 0

back

3.8.8 getSpeed

loaderObj.getSpeed()
returns the current downloadrate in bytes/second

return integer >= 0

back

3.8.9 getEstimatedTotalTime

loaderObj.getEstimatedTotalTime()
returns the estimated total download time for the current item in seconds

return integer >= 0

back

3.8.10 getTarget

loaderObj.getTarget()
returns the current target. If the target is a MovieClip, the targetpath is returned, otherwise the object is returned

return string | object

back

3.8.11 getTargetObj

loaderObj.getTargetObj()
returns the current target as object

return object

back

3.8.12 getUrl

loaderObj.getUrl()
returns the url of the current loading process

return string

back

4 FAQ

What are the frequently asked questions ?

back

5 Donations

There have been 23 donations between 5 and 15 $ yet. Are you no. 24 ? Donate to paypal@helpqlodhelp.com. You can also use the direct link to paypal

back

6 Bugs

Please send bugs / possible improvements with detailed descriptions to components@helpqlodhelp.com

back

7 Support

We provide professional scripting support and freelancing programming services at reasonable rates. Contact us for the details at components@helpqlodhelp.com

back

8 History

04/24/2003 v0.1
published
04/24/2003 v0.2
Ms-bug removed
did some refactoring into smaller functions
added getPercentLoaded and getBytesPerSecond
04/24/2003 v0.3
added parameters to constructor
added NO_INIT ( inheritance guard) to constructor
added getters/setters for timeOutMs
added getters/setters for intervalMs
moved default-settings into the setters
04/24/2003 v0.4
added defaultProperties to the prototype
04/25/2003 v0.5
added some documentation in javadoc style
04/26/2003 v0.6
refactored locToTarget into smaller functions
added errorhandling for invalid location parameter
added watch to allow for watching already loading timelines
added example for using watch
04/26/2003 v0.7
removed bug with sequential loading
added support for waitUntil-function
04/26/2003 v0.8
added onLoadTimeout event and example code
removed kb and bps parameters from onLoadProgress,
added milliseconds parameter to onLoadProgress
04/29/2003 v0.9
changed some things to make the class more universal
now movieclips, xml, loadvars and sound can be loaded with the same interface
changed classname MovieClipLoader to Loader
changed methodname loadClip to load
changed methodname watchClip to watch
added locIsLoadable-method
changed locToTarget to allow for target objects
05/01/2003 v0.9a
added transparent queueing
added events onQueueStart
added events onQueueStop
added method isLoading
05/04/2003 v0.9b
changed default value for bytesTotal to 1, to make calculating percentage easier
05/04/2003 v0.9c
moved the waitUntil-function into the class and removed it from the interface
05/05/2003 v0.9d
renamed internal method checkProgress to sendProgress
added call to broadcastProgress at the beginning of the loading process ( to reset displays)
added property minSteps, with default, getters and setters
removed getPercentLoaded and getBytesPerSecond
changed defaultIntervalMs to 100 to make animations smoother
changed defaultTimeoutMs to 10000, to make errorhandling faster
renamed watch to observe
05/05/2003 v0.9e
added praefixes to variables
renamed Loader to LoaderClass
renamed sendProgress to broadcastProgress
added checkIntGreaterZero
05/07/2003 v0.9f
corrected minStep-bug
05/07/2003 v0.9g
corrected currentStep-bug
05/09/2003 v0.9h
corrected initialisation of funcWaitUntil
changed timeout to work with an interval, which is probably less time consuming
observe now retrieves the url from the object, if no url is given
05/09/2003 v0.9i
corrected some minor FlashDoc inconsistencies
05/16/2003 v0.9jbeta
added switch and constants to allow for changing the parameterstyle of the callbacks
added getters for bytesLoaded, bytesTotal, kbLoaded, kbTotal, percent
added getters for time, speed, estimatedTotalTime, target, url, targetObj
added switch to enable/disable Timeout
05/17/2003 v0.9jbeta1
changed default properties to static constants
added check for object to observe
moved the api to the beginning of the file
05/18/2003 v0.9jbeta2
delete o
removed bug in locIsPath, now movieClips are rejected
added locIsMovieClip, now movieClips are recognized
05/18/2003 v0.9k
moved beta to alpha because of latest corrections
05/18/2003 v0.9l
bug in getStepPercent removed
05/30/2003 v0.9mb
added support for additional parameters to load
05/31/2003 v0.9mb1
added getStepKBLoaded
06/01/2003 v0.9mb2
added clear, remove, removeCurrent
06/01/2003 v0.9mb3
added namespace
moved class to com.qlod Domain
removed the ..Step.. methods
removed the paramStyle switch
corrected the docs of onLoadComplete
corrected the example code
06/03/2003 v0.9mb4
changed getTime to getDuration
06/05/2003 v0.9mb5
added support for specific listeners
06/13/2003 v1.0
Added this documentation
removed api and history from as-file
06/16/2003 v1.01
removed additional parameter bug
removed namespace bug
added doc for additional parameters (see load)
08/07/2003 v1.02
removed a bug with targetspecific listeners
added LoaderItemClass
added support for "late" targets, allow to use a string point to a target, which doesn't exist yet

8 Status

Written and copyright held by Ralf Bokelberg and Colin Moock.
Last change: June, Friday 13th, 2003

9 License For Use

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

back