/* * PROJECT: FLARManager * http://transmote.com/flar * Copyright 2009, Eric Socolofsky * -------------------------------------------------------------------------------- * This work complements FLARToolkit, developed by Saqoosha as part of the Libspark project. * http://www.libspark.org/wiki/saqoosha/FLARToolKit * FLARToolkit is Copyright (C)2008 Saqoosha, * and is ported from NYARToolkit, which is ported from ARToolkit. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this framework; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For further information please contact: * * http://transmote.com/flar * */ package com.transmote.flar.pattern { import flash.display.Loader; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IOErrorEvent; import flash.events.SecurityErrorEvent; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; import flash.utils.Dictionary; import org.libspark.flartoolkit.FLARException; import org.libspark.flartoolkit.core.FLARCode; /** * Manages loading FLARPatterns and instantiating corresponding FLARCodes. * * @author Eric Socolofsky * @url http://transmote.com/flar */ public class FLARPatternLoader extends EventDispatcher { private var loadingPatterns:Vector.; private var _loadedPatterns:Vector.; private var _unscaledMarkerWidths:Vector.; private var patternsByLoader:Dictionary; private var flarPatternsByFlarCodes:Dictionary; private var numPatternsLoaded:uint = 0; private var bLoading:Boolean; /** * Constructor. */ public function FLARPatternLoader () {} /** * Get loaded patterns, as FLARCode instances. * @throws Error if still loading. */ public function get loadedPatterns () :Vector. { if (this.bLoading) { throw new Error("currently loading patterns. listen for Event.INIT to signal load completion."); } return this._loadedPatterns; } /** * Frees up the pattern loader for garbage collection. */ public function dispose () :void { if (this.bLoading) { this.loadingPatterns = null; var loader:Loader; for (var loaderKey:* in this.patternsByLoader) { loader = loaderKey as Loader; if (!loader) { continue; } delete this.patternsByLoader[loader]; loader.removeEventListener(IOErrorEvent.IO_ERROR, this.onPatternLoadError); loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onPatternLoadError); loader.removeEventListener(Event.COMPLETE, this.onPatternLoaded); loader.close(); } this.patternsByLoader = null; } else { var flarCode:FLARCode; for each (flarCode in this.loadedPatterns) { // NOTE: FLARToolkit classes do not implement any disposal functionality, // and will likely not be removed from memory on FLARManager disposal. //flarCode.dispose(); flarCode = null; } for (var flarCodeKey:* in this.flarPatternsByFlarCodes) { flarCode = flarCodeKey as FLARCode; if (!flarCode) { continue; } delete this.flarPatternsByFlarCodes[flarCode]; } this.flarPatternsByFlarCodes = null; this._unscaledMarkerWidths = null; } } /** * Return unscaled marker widths, for use by FLARMultiMarkerDetector. * This array is synchronized with this.loadedPatterns -- * the unscaledMarkerWidth at each index corresponds to the loaded pattern at each index. */ public function get unscaledMarkerWidths () :Vector. { return this._unscaledMarkerWidths; } /** * Load a list of FLARPatterns, and store as FLARCodes accessible as loadedPatterns. * * @param patterns Vector of FLARPatterns to load. * @throws Error If pattern load is currently in progress. */ public function loadTrackerConfig (patterns:Vector.) :void { if (this.bLoading) { throw new Error("currently loading patterns."); } this.bLoading = true; this.loadingPatterns = patterns; this.patternsByLoader = new Dictionary(true); this.flarPatternsByFlarCodes = new Dictionary(true); this._loadedPatterns = new Vector.(this.loadingPatterns.length); var i:uint = this.loadingPatterns.length; while (i--) { this.loadPattern(this.loadingPatterns[i]); } } private function loadPattern (pattern:FLARPattern) :void { var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.TEXT; loader.addEventListener(IOErrorEvent.IO_ERROR, this.onPatternLoadError); loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onPatternLoadError); loader.addEventListener(Event.COMPLETE, this.onPatternLoaded); this.patternsByLoader[loader] = pattern; loader.load(new URLRequest(pattern.filename)); } private function onPatternLoadError (evt:Event) :void { var errorText:String = "Pattern load error."; if (evt is IOErrorEvent) { errorText += ("\n"+ IOErrorEvent(evt).text); } else if (evt is SecurityErrorEvent) { errorText += ("\n"+ SecurityErrorEvent(evt).text); } this.onPatternLoaded(evt, new Error(errorText)); } private function onPatternLoaded (evt:Event, error:Error=null) :void { var loader:URLLoader = evt.target as URLLoader; loader.removeEventListener(IOErrorEvent.IO_ERROR, this.onPatternLoadError); loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onPatternLoadError); loader.removeEventListener(Event.COMPLETE, this.onPatternLoaded); var loadedPattern:FLARPattern = FLARPattern(this.patternsByLoader[loader]); delete this.patternsByLoader[loader]; var loadedPatternIndex:int = this.loadingPatterns.indexOf(loadedPattern); if (error) { this.checkForLoadCompletion(); // TODO: probably want to change this to trace(), not throw. trace(error); } else { // create the FLARCode from the loaded pattern data var flarCode:FLARCode = new FLARCode(loadedPattern._resolution, loadedPattern._resolution, loadedPattern._patternToBorderRatioX, loadedPattern._patternToBorderRatioY); try { flarCode.loadARPatt(String(loader.data)); } catch (e:FLARException) { throw e; } // store the FLARCode in this.loadedPatterns this.flarPatternsByFlarCodes[flarCode] = loadedPattern; this._loadedPatterns[loadedPatternIndex] = flarCode; } this.numPatternsLoaded++; this.checkForLoadCompletion(); } private function checkForLoadCompletion () :void { if (this.numPatternsLoaded == this.loadingPatterns.length) { this.sortPatternsAndUnscaledMarkerWidths(); this.loadingPatterns = null; // release reference to FLARPatterns Vector this.bLoading = false; this.dispatchEvent(new Event(Event.INIT)); } } private function sortPatternsAndUnscaledMarkerWidths () :void { var i:int = this.loadingPatterns.length; this._unscaledMarkerWidths = new Vector.(i); while (i--) { if (this._loadedPatterns[i]) { this._unscaledMarkerWidths[i] = this.loadingPatterns[i].unscaledMarkerWidth; } else { // cull patterns that did not load successfully this._loadedPatterns.splice(i, 1); this._unscaledMarkerWidths.splice(i, 1); } } } } }