/src/aerys/minko/type/loader/SceneLoader.as
ActionScript | 208 lines | 165 code | 42 blank | 1 comment | 27 complexity | b1e436a2cacbb53a3e19cca68c94fdbf MD5 | raw file
1package aerys.minko.type.loader
2{
3 import aerys.minko.render.resource.texture.TextureResource;
4 import aerys.minko.scene.node.AbstractSceneNode;
5 import aerys.minko.scene.node.Group;
6 import aerys.minko.scene.node.ISceneNode;
7 import aerys.minko.type.Signal;
8 import aerys.minko.type.loader.parser.IParser;
9 import aerys.minko.type.loader.parser.ParserOptions;
10
11 import flash.events.Event;
12 import flash.events.ProgressEvent;
13 import flash.net.URLLoader;
14 import flash.net.URLLoaderDataFormat;
15 import flash.net.URLRequest;
16 import flash.utils.ByteArray;
17 import flash.utils.getQualifiedClassName;
18
19 public class SceneLoader implements ILoader
20 {
21 private static const REGISTERED_PARSERS : Vector.<Class> = new <Class>[];
22
23 private static const STATE_IDLE : uint = 0;
24 private static const STATE_LOADING : uint = 1;
25 private static const STATE_PARSING : uint = 2;
26 private static const STATE_COMPLETE : uint = 3;
27
28 private var _currentState : int;
29
30 private var _progress : Signal;
31 private var _complete : Signal;
32 private var _error : Signal;
33
34 private var _data : ISceneNode;
35 private var _parser : IParser;
36 private var _numDependencies : uint;
37 private var _dependencies : Vector.<ILoader>;
38 private var _parserOptions : ParserOptions;
39
40 private var _currentProgress : Number;
41 private var _currentProgressChanged : Boolean;
42 private var _isComplete : Boolean;
43
44 public function get error() : Signal
45 {
46 return _error;
47 }
48
49 public function get progress() : Signal
50 {
51 return _progress;
52 }
53
54 public function get complete() : Signal
55 {
56 return _complete;
57 }
58
59 public function get isComplete() : Boolean
60 {
61 return _isComplete;
62 }
63
64 public function get data() : ISceneNode
65 {
66 return _data;
67 }
68
69 public static function registerParser(parserClass : Class) : void
70 {
71 if (REGISTERED_PARSERS.indexOf(parserClass) != -1)
72 return;
73
74 if (!(new parserClass(new ParserOptions()) is IParser))
75 throw new Error('Parsers must implement the IParser interface.');
76
77 REGISTERED_PARSERS.push(parserClass);
78 }
79
80 public function SceneLoader(parserOptions : ParserOptions = null)
81 {
82 _currentState = STATE_IDLE;
83
84 _progress = new Signal('SceneLoader.progress');
85 _complete = new Signal('SceneLoader.complete');
86 _data = null;
87 _isComplete = false;
88
89 _parserOptions = parserOptions || new ParserOptions();
90 }
91
92 public function load(urlRequest : URLRequest) : void
93 {
94 if (_currentState != STATE_IDLE)
95 throw new Error('This controller is already loading an asset.');
96
97 _currentState = STATE_LOADING;
98
99 var urlLoader : URLLoader = new URLLoader();
100 urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
101 urlLoader.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
102 urlLoader.addEventListener(Event.COMPLETE, loadCompleteHandler);
103 urlLoader.load(urlRequest);
104 }
105
106 private function loadProgressHandler(e : ProgressEvent) : void
107 {
108 _progress.execute(this, 0.5 * e.bytesLoaded / e.bytesTotal);
109 }
110
111 private function loadCompleteHandler(e : Event) : void
112 {
113 _currentState = STATE_IDLE;
114
115 loadBytes(URLLoader(e.currentTarget).data);
116 }
117
118 public function loadClass(classObject : Class) : void
119 {
120 loadBytes(new classObject());
121 }
122
123 public function loadBytes(byteArray : ByteArray) : void
124 {
125 var startPosition : uint = byteArray.position;
126
127 if (_currentState != STATE_IDLE)
128 throw new Error('This loader is already loading an asset.');
129
130 _currentState = STATE_PARSING;
131 _progress.execute(this, 0.5);
132
133 if (_parserOptions != null && _parserOptions.parser != null)
134 {
135 _parser = new (_parserOptions.parser)(_parserOptions);
136
137 if (!_parser.isParsable(byteArray))
138 throw new Error('Invalid datatype for this parser.');
139 }
140 else
141 {
142 // search a parser by testing registered parsers.
143 var numRegisteredParser : uint = REGISTERED_PARSERS.length;
144 for (var parserId : uint = 0; parserId < numRegisteredParser; ++parserId)
145 {
146 _parser = new REGISTERED_PARSERS[parserId](_parserOptions);
147 byteArray.position = startPosition;
148 if (_parser.isParsable(byteArray))
149 break;
150 }
151
152 if (parserId == numRegisteredParser)
153 throw new Error('No parser could be found for this datatype.');
154 }
155
156 byteArray.position = startPosition;
157
158 _dependencies = _parser.getDependencies(byteArray);
159 _numDependencies = 0;
160
161 if (_dependencies != null)
162 for each (var dependency : ILoader in _dependencies)
163 if (!dependency.isComplete)
164 {
165 dependency.error.add(decrementDependencyCounter);
166 dependency.complete.add(decrementDependencyCounter);
167
168 _numDependencies++;
169 }
170
171 if (_numDependencies == 0)
172 parse();
173 }
174
175 private function decrementDependencyCounter(...args) : void
176 {
177 --_numDependencies;
178
179 if (_numDependencies == 0)
180 parse();
181 }
182
183 private function parse() : void
184 {
185 _parser.error.add(onParseError);
186 _parser.progress.add(onParseProgress);
187 _parser.complete.add(onParseComplete);
188 _parser.parse();
189 }
190
191 private function onParseError(parser : IParser) : void
192 {
193 _isComplete = true;
194 }
195
196 private function onParseProgress(parser : IParser, progress : Number) : void
197 {
198 _progress.execute(this, 0.5 * (1 + progress));
199 }
200
201 private function onParseComplete(parser : IParser, loadedData : ISceneNode) : void
202 {
203 _isComplete = true;
204 _data = loadedData;
205 _complete.execute(this, loadedData);
206 }
207 }
208}