1 /*
  2 SpiderGL Computer Graphics Library
  3 Copyright (c) 2010, Marco Di Benedetto - Visual Computing Lab, ISTI - CNR
  4 All rights reserved.
  5 
  6 Redistribution and use in source and binary forms, with or without
  7 modification, are permitted provided that the following conditions are met:
  8     * Redistributions of source code must retain the above copyright
  9       notice, this list of conditions and the following disclaimer.
 10     * Redistributions in binary form must reproduce the above copyright
 11       notice, this list of conditions and the following disclaimer in the
 12       documentation and/or other materials provided with the distribution.
 13     * Neither the name of SpiderGL nor the
 14       names of its contributors may be used to endorse or promote products
 15       derived from this software without specific prior written permission.
 16 
 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20 DISCLAIMED. IN NO EVENT SHALL PAUL BRUNT BE LIABLE FOR ANY
 21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27 */
 28 
 29 /**
 30  * @fileOverview Utility
 31  */
 32 
 33 /**
 34  * The SpiderGL.Utility namespace.
 35  *
 36  * @namespace The SpiderGL.Utility namespace.
 37  */
 38 SpiderGL.Utility = { };
 39 
 40 /**
 41  * Gets default value for varibles.
 42  *
 43  * This function is used to get default values for optional variables.
 44  * If arg is undefined or is {@link SpiderGL.Core.DEFAULT}, then defaultValue will be returned. Otherwise, arg will be returned.
 45  *
 46  * @returns {any} Returns arg if arg is not undefined and is not {@link SpiderGL.Core.DEFAULT}, otherwise returns defaultValue.
 47  *
 48  * @example
 49  * var DEFAULT_V = 1;
 50  *
 51  * var v = null;
 52  * v = SpiderGL.Utility.getDefaultValue(someVar, DEFAULT_V); // someVar is undefined, so v = DEFAULT_V
 53  *
 54  * var someVar = 2;
 55  * v = SpiderGL.Utility.getDefaultValue(someVar, DEFAULT_V); // someVar is defined, so v = someVar
 56  *
 57  * var someVar = SpiderGL.Core.DEFAULT;
 58  * v = SpiderGL.Utility.getDefaultValue(someVar, DEFAULT_V); // someVar is SpiderGL.Core.DEFAULT, so v = DEFAULT_V
 59  *
 60  * @example
 61  * var DEFAULT_Y = 1;
 62  * var DEFAULT_Z = 2;
 63  *
 64  * function setObject(obj, x, options) {
 65  *   options = options || { }; // create an empty object to avoid testing for null
 66  *   obj.x = x;
 67  *   obj.y = SpiderGL.Utility.getDefaultValue(options.y, DEFAULT_Y);
 68  *   obj.z = SpiderGL.Utility.getDefaultValue(options.z, DEFAULT_Z);
 69  * }
 70  *
 71  * var obj = {
 72  *   x : 0,
 73  *   y : 1,
 74  *   z : 2
 75  * };
 76  *
 77  * setObject(obj, 3);        // obj = { x:3, y:DEFAULT_Y, z:DEFAULT_Z }
 78  * setObject(obj, 4, {z:5}); // obj = { x:4, y:DEFAULT_Y, z:5         }
 79  */
 80 SpiderGL.Utility.getDefaultValue = function (arg, defaultValue) {
 81 	if ((arg === undefined) || (arg === SpiderGL.Core.DEFAULT)) { return defaultValue; }
 82 	return arg;
 83 }
 84 
 85 /**
 86  * Gets default values for objects.
 87  *
 88  * @param {object} defaultObj The object containing the default values.
 89  * @param {object} obj The object from which values are extracted.
 90  *
 91  * @returns {object} The modified defaultObj.
 92  */
 93 SpiderGL.Utility.getDefaultObject = function (defaultObj, obj) {
 94 	if (obj) {
 95 		var sDefault = SpiderGL.Core.DEFAULT;
 96 		//var getter = null;
 97 		for (var p in obj) {
 98 			/* getter = obj.__lookupGetter__(p);
 99 			if (getter) {
100 				defaultObj.__defineGetter__(p, getter);
101 			}
102 			else */ if (obj[p] != sDefault) {
103 				defaultObj[p] = obj[p];
104 			}
105 		}
106 	}
107 	return defaultObj;
108 };
109 
110 /**
111  * Sets default values for the passed object.
112  *
113  * @param {object} defaultObj The object containing the default values.
114  * @param {object} obj The object from which values are extracted.
115  *
116  * @returns {object} The modified obj. If obj is null, defaultObj will be returned.
117  */
118 SpiderGL.Utility.setDefaultValues = function (defaultObj, obj) {
119 	if (!obj) return defaultObj;
120 
121 	var sDefault = SpiderGL.Core.DEFAULT;
122 	for (var p in obj) {
123 		if (obj[p] == sDefault) {
124 			if (typeof defaultObj[p] != "undefined") {
125 				obj[p] = defaultObj[p];
126 			}
127 		}
128 	}
129 	for (var p in defaultObj) {
130 		if (typeof obj[p] == "undefined") {
131 			obj[p] = defaultObj[p];
132 		}
133 	}
134 	return obj;
135 };
136 
137 /**
138  * Converts the input arguments to a 4-component Float32Array.
139  * The input value is handled like WebGL handles constant vertex attributes,
140  * that is, if the input parameter is null, a number, or an array with less than four components,
141  * missing values are taken from the array [0, 0, 0, 1] at the respective position. 
142  *
143  * @param {null|undefined|number|array|Float32Array} x The input value.
144  *
145  * @returns {array} a 4-component array.
146  *
147  * @example
148  * x = SpiderGL.Utility.getAttrib4fv();                        // x = [0, 0, 0, 1]
149  * x = SpiderGL.Utility.getAttrib4fv(null);                    // x = [0, 0, 0, 1]
150  * x = SpiderGL.Utility.getAttrib4fv(undefined);               // x = [0, 0, 0, 1]
151  * x = SpiderGL.Utility.getAttrib4fv(0);                       // x = [0, 0, 0, 1]
152  * x = SpiderGL.Utility.getAttrib4fv(7);                       // x = [7, 0, 0, 1]
153  * x = SpiderGL.Utility.getAttrib4fv([]);                      // x = [0, 0, 0, 1]
154  * x = SpiderGL.Utility.getAttrib4fv([1]);                     // x = [1, 0, 0, 1]
155  * x = SpiderGL.Utility.getAttrib4fv([1, 2]);                  // x = [1, 2, 0, 1]
156  * x = SpiderGL.Utility.getAttrib4fv([1, 2, 3]);               // x = [1, 2, 3, 1]
157  * x = SpiderGL.Utility.getAttrib4fv([1, 2, 3, 4, 5, 6]);      // x = [1, 2, 3, 4]
158  * x = SpiderGL.Utility.getAttrib4fv(new Float32Array([0,9]);  // x = [0, 9, 0, 1]
159  */
160 SpiderGL.Utility.getAttrib4fv = function (x) {
161 	if (SpiderGL.Type.isNumber(x)) return [x, 0, 0, 1];
162 	if (!x) return [0, 0, 0, 1];
163 	return [
164 		(x[0] != undefined) ? x[0] : 0,
165 		(x[1] != undefined) ? x[1] : 0,
166 		(x[2] != undefined) ? x[2] : 0,
167 		(x[3] != undefined) ? x[3] : 1
168 	];
169 }
170 
171 /**
172  * Gets the number of milliseconds elapsed since January 1, 1970 at 00:00.
173  * It is a utility function for (new Date()).getTime().
174  *
175  * @returns {number} The number of milliseconds elapsed since January 1, 1970 at 00:00.
176  */
177 SpiderGL.Utility.getTime = function () {
178 	return (new Date()).getTime();
179 };
180 
181 SpiderGL.Utility.Timer = function () {
182 	this._tStart   = -1;
183 	this._tElapsed = 0;
184 }
185 
186 SpiderGL.Utility.Timer.prototype = {
187 	_accumElapsed : function () {
188 		this._tElapsed += this.now - this._tStart;
189 	},
190 
191 	get now() {
192 		return Date.now();
193 	},
194 
195 	start : function () {
196 		if (this.isStarted) return;
197 		if (this.isPaused)  return;
198 		this._tStart   = this.now;
199 		this._tElapsed = 0;
200 	},
201 
202 	restart : function () {
203 		var r = this.elapsed;
204 		this._tStart   = this.now;
205 		this._tElapsed = 0;
206 		return r;
207 	},
208 
209 	stop : function () {
210 		if (!this.isStarted) return;
211 		if (this.isPaused)   return;
212 		this._accumElapsed();
213 		this._tStart = -1;
214 	},
215 
216 	get isStarted() {
217 		return (this._tStart >= 0);
218 	},
219 
220 	pause : function () {
221 		if (!this.isStarted) return;
222 		if (this.isPaused)   return;
223 		this._accumElapsed();
224 		this._tStart = -2;
225 	},
226 
227 	resume : function () {
228 		if (!this.isStarted) return;
229 		if (!this.isPaused)  return;
230 		this._tStart = this.now;
231 	},
232 
233 	get isPaused() {
234 		return (this._tStart == -2);
235 	},
236 
237 	get elapsed() {
238 		return ((this.isStarted) ? (this._tElapsed + (this.now - this._tStart)) : (this._tElapsed))
239 	}
240 };
241