Skip to content

Instantly share code, notes, and snippets.

@trusktr
Created December 13, 2017 23:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trusktr/e37dbc24c51b9d3e2f9e508e75cf8f99 to your computer and use it in GitHub Desktop.
Save trusktr/e37dbc24c51b9d3e2f9e508e75cf8f99 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
var infamous = (function (exports) {
'use strict';
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function unwrapExports (x) {
return x && x.__esModule ? x['default'] : x;
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
// 7.2.1 RequireObjectCoercible(argument)
var _defined = function (it) {
if (it == undefined) { throw TypeError("Can't call method on " + it); }
return it;
};
// 7.1.13 ToObject(argument)
var _toObject = function (it) {
return Object(_defined(it));
};
var hasOwnProperty = {}.hasOwnProperty;
var _has = function (it, key) {
return hasOwnProperty.call(it, key);
};
var _global = createCommonjsModule(function (module) {
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global = module.exports = typeof window != 'undefined' && window.Math == Math
? window : typeof self != 'undefined' && self.Math == Math ? self
// eslint-disable-next-line no-new-func
: Function('return this')();
if (typeof __g == 'number') { __g = global; } // eslint-disable-line no-undef
});
var SHARED = '__core-js_shared__';
var store = _global[SHARED] || (_global[SHARED] = {});
var _shared = function (key) {
return store[key] || (store[key] = {});
};
var id = 0;
var px = Math.random();
var _uid = function (key) {
return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
};
var shared = _shared('keys');
var _sharedKey = function (key) {
return shared[key] || (shared[key] = _uid(key));
};
// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)
var IE_PROTO = _sharedKey('IE_PROTO');
var ObjectProto = Object.prototype;
var _objectGpo = Object.getPrototypeOf || function (O) {
O = _toObject(O);
if (_has(O, IE_PROTO)) { return O[IE_PROTO]; }
if (typeof O.constructor == 'function' && O instanceof O.constructor) {
return O.constructor.prototype;
} return O instanceof Object ? ObjectProto : null;
};
var _core = createCommonjsModule(function (module) {
var core = module.exports = { version: '2.5.0' };
if (typeof __e == 'number') { __e = core; } // eslint-disable-line no-undef
});
var _aFunction = function (it) {
if (typeof it != 'function') { throw TypeError(it + ' is not a function!'); }
return it;
};
// optional / simple context binding
var _ctx = function (fn, that, length) {
_aFunction(fn);
if (that === undefined) { return fn; }
switch (length) {
case 1: return function (a) {
return fn.call(that, a);
};
case 2: return function (a, b) {
return fn.call(that, a, b);
};
case 3: return function (a, b, c) {
return fn.call(that, a, b, c);
};
}
return function (/* ...args */) {
return fn.apply(that, arguments);
};
};
var _isObject = function (it) {
return typeof it === 'object' ? it !== null : typeof it === 'function';
};
var _anObject = function (it) {
if (!_isObject(it)) { throw TypeError(it + ' is not an object!'); }
return it;
};
var _fails = function (exec) {
try {
return !!exec();
} catch (e) {
return true;
}
};
// Thank's IE8 for his funny defineProperty
var _descriptors = !_fails(function () {
return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;
});
var document$1 = _global.document;
// typeof document.createElement is 'object' in old IE
var is = _isObject(document$1) && _isObject(document$1.createElement);
var _domCreate = function (it) {
return is ? document$1.createElement(it) : {};
};
var _ie8DomDefine = !_descriptors && !_fails(function () {
return Object.defineProperty(_domCreate('div'), 'a', { get: function () { return 7; } }).a != 7;
});
// 7.1.1 ToPrimitive(input [, PreferredType])
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
// and the second argument - flag - preferred type is a string
var _toPrimitive = function (it, S) {
if (!_isObject(it)) { return it; }
var fn, val;
if (S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) { return val; }
if (typeof (fn = it.valueOf) == 'function' && !_isObject(val = fn.call(it))) { return val; }
if (!S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) { return val; }
throw TypeError("Can't convert object to primitive value");
};
var dP = Object.defineProperty;
var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) {
_anObject(O);
P = _toPrimitive(P, true);
_anObject(Attributes);
if (_ie8DomDefine) { try {
return dP(O, P, Attributes);
} catch (e) { /* empty */ } }
if ('get' in Attributes || 'set' in Attributes) { throw TypeError('Accessors not supported!'); }
if ('value' in Attributes) { O[P] = Attributes.value; }
return O;
};
var _objectDp = {
f: f
};
var _propertyDesc = function (bitmap, value) {
return {
enumerable: !(bitmap & 1),
configurable: !(bitmap & 2),
writable: !(bitmap & 4),
value: value
};
};
var _hide = _descriptors ? function (object, key, value) {
return _objectDp.f(object, key, _propertyDesc(1, value));
} : function (object, key, value) {
object[key] = value;
return object;
};
var PROTOTYPE = 'prototype';
var $export = function (type, name, source) {
var IS_FORCED = type & $export.F;
var IS_GLOBAL = type & $export.G;
var IS_STATIC = type & $export.S;
var IS_PROTO = type & $export.P;
var IS_BIND = type & $export.B;
var IS_WRAP = type & $export.W;
var exports = IS_GLOBAL ? _core : _core[name] || (_core[name] = {});
var expProto = exports[PROTOTYPE];
var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] : (_global[name] || {})[PROTOTYPE];
var key, own, out;
if (IS_GLOBAL) { source = name; }
for (key in source) {
// contains in native
own = !IS_FORCED && target && target[key] !== undefined;
if (own && key in exports) { continue; }
// export native or passed
out = own ? target[key] : source[key];
// prevent global pollution for namespaces
exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key]
// bind timers to global for call from export context
: IS_BIND && own ? _ctx(out, _global)
// wrap global constructors for prevent change them in library
: IS_WRAP && target[key] == out ? (function (C) {
var F = function (a, b, c) {
if (this instanceof C) {
switch (arguments.length) {
case 0: return new C();
case 1: return new C(a);
case 2: return new C(a, b);
} return new C(a, b, c);
} return C.apply(this, arguments);
};
F[PROTOTYPE] = C[PROTOTYPE];
return F;
// make static versions for prototype methods
})(out) : IS_PROTO && typeof out == 'function' ? _ctx(Function.call, out) : out;
// export proto methods to core.%CONSTRUCTOR%.methods.%NAME%
if (IS_PROTO) {
(exports.virtual || (exports.virtual = {}))[key] = out;
// export proto methods to core.%CONSTRUCTOR%.prototype.%NAME%
if (type & $export.R && expProto && !expProto[key]) { _hide(expProto, key, out); }
}
}
};
// type bitmap
$export.F = 1; // forced
$export.G = 2; // global
$export.S = 4; // static
$export.P = 8; // proto
$export.B = 16; // bind
$export.W = 32; // wrap
$export.U = 64; // safe
$export.R = 128; // real proto method for `library`
var _export = $export;
// most Object methods by ES6 should accept primitives
var _objectSap = function (KEY, exec) {
var fn = (_core.Object || {})[KEY] || Object[KEY];
var exp = {};
exp[KEY] = exec(fn);
_export(_export.S + _export.F * _fails(function () { fn(1); }), 'Object', exp);
};
// 19.1.2.9 Object.getPrototypeOf(O)
_objectSap('getPrototypeOf', function () {
return function getPrototypeOf(it) {
return _objectGpo(_toObject(it));
};
});
var getPrototypeOf$1 = _core.Object.getPrototypeOf;
var getPrototypeOf = createCommonjsModule(function (module) {
module.exports = { "default": getPrototypeOf$1, __esModule: true };
});
var _Object$getPrototypeOf = unwrapExports(getPrototypeOf);
var classCallCheck = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
exports.default = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
});
var _classCallCheck = unwrapExports(classCallCheck);
// 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes)
_export(_export.S + _export.F * !_descriptors, 'Object', { defineProperty: _objectDp.f });
var $Object = _core.Object;
var defineProperty$1 = function defineProperty(it, key, desc) {
return $Object.defineProperty(it, key, desc);
};
var defineProperty = createCommonjsModule(function (module) {
module.exports = { "default": defineProperty$1, __esModule: true };
});
var _Object$defineProperty = unwrapExports(defineProperty);
var createClass = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _defineProperty2 = _interopRequireDefault(defineProperty);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) { descriptor.writable = true; }
(0, _defineProperty2.default)(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) { defineProperties(Constructor.prototype, protoProps); }
if (staticProps) { defineProperties(Constructor, staticProps); }
return Constructor;
};
}();
});
var _createClass = unwrapExports(createClass);
// 7.1.4 ToInteger
var ceil = Math.ceil;
var floor = Math.floor;
var _toInteger = function (it) {
return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
};
// true -> String#at
// false -> String#codePointAt
var _stringAt = function (TO_STRING) {
return function (that, pos) {
var s = String(_defined(that));
var i = _toInteger(pos);
var l = s.length;
var a, b;
if (i < 0 || i >= l) { return TO_STRING ? '' : undefined; }
a = s.charCodeAt(i);
return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff
? TO_STRING ? s.charAt(i) : a
: TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
};
};
var _library = true;
var _redefine = _hide;
var _iterators = {};
var toString = {}.toString;
var _cof = function (it) {
return toString.call(it).slice(8, -1);
};
// fallback for non-array-like ES3 and non-enumerable old V8 strings
// eslint-disable-next-line no-prototype-builtins
var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
return _cof(it) == 'String' ? it.split('') : Object(it);
};
// to indexed object, toObject with fallback for non-array-like ES3 strings
var _toIobject = function (it) {
return _iobject(_defined(it));
};
// 7.1.15 ToLength
var min = Math.min;
var _toLength = function (it) {
return it > 0 ? min(_toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
};
var max = Math.max;
var min$1 = Math.min;
var _toAbsoluteIndex = function (index, length) {
index = _toInteger(index);
return index < 0 ? max(index + length, 0) : min$1(index, length);
};
// false -> Array#indexOf
// true -> Array#includes
var _arrayIncludes = function (IS_INCLUDES) {
return function ($this, el, fromIndex) {
var O = _toIobject($this);
var length = _toLength(O.length);
var index = _toAbsoluteIndex(fromIndex, length);
var value;
// Array#includes uses SameValueZero equality algorithm
// eslint-disable-next-line no-self-compare
if (IS_INCLUDES && el != el) { while (length > index) {
value = O[index++];
// eslint-disable-next-line no-self-compare
if (value != value) { return true; }
// Array#indexOf ignores holes, Array#includes - not
} } else { for (;length > index; index++) { if (IS_INCLUDES || index in O) {
if (O[index] === el) { return IS_INCLUDES || index || 0; }
} } } return !IS_INCLUDES && -1;
};
};
var arrayIndexOf = _arrayIncludes(false);
var IE_PROTO$2 = _sharedKey('IE_PROTO');
var _objectKeysInternal = function (object, names) {
var O = _toIobject(object);
var i = 0;
var result = [];
var key;
for (key in O) { if (key != IE_PROTO$2) { _has(O, key) && result.push(key); } }
// Don't enum bug & hidden keys
while (names.length > i) { if (_has(O, key = names[i++])) {
~arrayIndexOf(result, key) || result.push(key);
} }
return result;
};
// IE 8- don't enum bug keys
var _enumBugKeys = (
'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'
).split(',');
// 19.1.2.14 / 15.2.3.14 Object.keys(O)
var _objectKeys = Object.keys || function keys(O) {
return _objectKeysInternal(O, _enumBugKeys);
};
var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
_anObject(O);
var keys = _objectKeys(Properties);
var length = keys.length;
var i = 0;
var P;
while (length > i) { _objectDp.f(O, P = keys[i++], Properties[P]); }
return O;
};
var document$2 = _global.document;
var _html = document$2 && document$2.documentElement;
// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
var IE_PROTO$1 = _sharedKey('IE_PROTO');
var Empty = function () { /* empty */ };
var PROTOTYPE$1 = 'prototype';
// Create object with fake `null` prototype: use iframe Object with cleared prototype
var createDict = function () {
// Thrash, waste and sodomy: IE GC bug
var iframe = _domCreate('iframe');
var i = _enumBugKeys.length;
var lt = '<';
var gt = '>';
var iframeDocument;
iframe.style.display = 'none';
_html.appendChild(iframe);
iframe.src = 'javascript:'; // eslint-disable-line no-script-url
// createDict = iframe.contentWindow.Object;
// html.removeChild(iframe);
iframeDocument = iframe.contentWindow.document;
iframeDocument.open();
iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
iframeDocument.close();
createDict = iframeDocument.F;
while (i--) { delete createDict[PROTOTYPE$1][_enumBugKeys[i]]; }
return createDict();
};
var _objectCreate = Object.create || function create(O, Properties) {
var result;
if (O !== null) {
Empty[PROTOTYPE$1] = _anObject(O);
result = new Empty();
Empty[PROTOTYPE$1] = null;
// add "__proto__" for Object.getPrototypeOf polyfill
result[IE_PROTO$1] = O;
} else { result = createDict(); }
return Properties === undefined ? result : _objectDps(result, Properties);
};
var _wks = createCommonjsModule(function (module) {
var store = _shared('wks');
var Symbol = _global.Symbol;
var USE_SYMBOL = typeof Symbol == 'function';
var $exports = module.exports = function (name) {
return store[name] || (store[name] =
USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : _uid)('Symbol.' + name));
};
$exports.store = store;
});
var def = _objectDp.f;
var TAG = _wks('toStringTag');
var _setToStringTag = function (it, tag, stat) {
if (it && !_has(it = stat ? it : it.prototype, TAG)) { def(it, TAG, { configurable: true, value: tag }); }
};
'use strict';
var IteratorPrototype = {};
// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
_hide(IteratorPrototype, _wks('iterator'), function () { return this; });
var _iterCreate = function (Constructor, NAME, next) {
Constructor.prototype = _objectCreate(IteratorPrototype, { next: _propertyDesc(1, next) });
_setToStringTag(Constructor, NAME + ' Iterator');
};
'use strict';
var ITERATOR = _wks('iterator');
var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`
var FF_ITERATOR = '@@iterator';
var KEYS = 'keys';
var VALUES = 'values';
var returnThis = function () { return this; };
var _iterDefine = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
_iterCreate(Constructor, NAME, next);
var getMethod = function (kind) {
if (!BUGGY && kind in proto) { return proto[kind]; }
switch (kind) {
case KEYS: return function keys() { return new Constructor(this, kind); };
case VALUES: return function values() { return new Constructor(this, kind); };
} return function entries() { return new Constructor(this, kind); };
};
var TAG = NAME + ' Iterator';
var DEF_VALUES = DEFAULT == VALUES;
var VALUES_BUG = false;
var proto = Base.prototype;
var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
var $default = $native || getMethod(DEFAULT);
var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
var methods, key, IteratorPrototype;
// Fix native
if ($anyNative) {
IteratorPrototype = _objectGpo($anyNative.call(new Base()));
if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
// Set @@toStringTag to native iterators
_setToStringTag(IteratorPrototype, TAG, true);
// fix for some old engines
if (!_library && !_has(IteratorPrototype, ITERATOR)) { _hide(IteratorPrototype, ITERATOR, returnThis); }
}
}
// fix Array#{values, @@iterator}.name in V8 / FF
if (DEF_VALUES && $native && $native.name !== VALUES) {
VALUES_BUG = true;
$default = function values() { return $native.call(this); };
}
// Define iterator
if ((!_library || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
_hide(proto, ITERATOR, $default);
}
// Plug for library
_iterators[NAME] = $default;
_iterators[TAG] = returnThis;
if (DEFAULT) {
methods = {
values: DEF_VALUES ? $default : getMethod(VALUES),
keys: IS_SET ? $default : getMethod(KEYS),
entries: $entries
};
if (FORCED) { for (key in methods) {
if (!(key in proto)) { _redefine(proto, key, methods[key]); }
} } else { _export(_export.P + _export.F * (BUGGY || VALUES_BUG), NAME, methods); }
}
return methods;
};
'use strict';
var $at = _stringAt(true);
// 21.1.3.27 String.prototype[@@iterator]()
_iterDefine(String, 'String', function (iterated) {
this._t = String(iterated); // target
this._i = 0; // next index
// 21.1.5.2.1 %StringIteratorPrototype%.next()
}, function () {
var O = this._t;
var index = this._i;
var point;
if (index >= O.length) { return { value: undefined, done: true }; }
point = $at(O, index);
this._i += point.length;
return { value: point, done: false };
});
var _iterStep = function (done, value) {
return { value: value, done: !!done };
};
'use strict';
// 22.1.3.4 Array.prototype.entries()
// 22.1.3.13 Array.prototype.keys()
// 22.1.3.29 Array.prototype.values()
// 22.1.3.30 Array.prototype[@@iterator]()
var es6_array_iterator = _iterDefine(Array, 'Array', function (iterated, kind) {
this._t = _toIobject(iterated); // target
this._i = 0; // next index
this._k = kind; // kind
// 22.1.5.2.1 %ArrayIteratorPrototype%.next()
}, function () {
var O = this._t;
var kind = this._k;
var index = this._i++;
if (!O || index >= O.length) {
this._t = undefined;
return _iterStep(1);
}
if (kind == 'keys') { return _iterStep(0, index); }
if (kind == 'values') { return _iterStep(0, O[index]); }
return _iterStep(0, [index, O[index]]);
}, 'values');
// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
_iterators.Arguments = _iterators.Array;
var TO_STRING_TAG = _wks('toStringTag');
var DOMIterables = ('CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,' +
'DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,' +
'MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,' +
'SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,' +
'TextTrackList,TouchList').split(',');
for (var i = 0; i < DOMIterables.length; i++) {
var NAME = DOMIterables[i];
var Collection = _global[NAME];
var proto = Collection && Collection.prototype;
if (proto && !proto[TO_STRING_TAG]) { _hide(proto, TO_STRING_TAG, NAME); }
_iterators[NAME] = _iterators.Array;
}
var f$1 = _wks;
var _wksExt = {
f: f$1
};
var iterator$2 = _wksExt.f('iterator');
var iterator = createCommonjsModule(function (module) {
module.exports = { "default": iterator$2, __esModule: true };
});
unwrapExports(iterator);
var _meta = createCommonjsModule(function (module) {
var META = _uid('meta');
var setDesc = _objectDp.f;
var id = 0;
var isExtensible = Object.isExtensible || function () {
return true;
};
var FREEZE = !_fails(function () {
return isExtensible(Object.preventExtensions({}));
});
var setMeta = function (it) {
setDesc(it, META, { value: {
i: 'O' + ++id, // object ID
w: {} // weak collections IDs
} });
};
var fastKey = function (it, create) {
// return primitive with prefix
if (!_isObject(it)) { return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; }
if (!_has(it, META)) {
// can't set metadata to uncaught frozen object
if (!isExtensible(it)) { return 'F'; }
// not necessary to add metadata
if (!create) { return 'E'; }
// add missing metadata
setMeta(it);
// return object ID
} return it[META].i;
};
var getWeak = function (it, create) {
if (!_has(it, META)) {
// can't set metadata to uncaught frozen object
if (!isExtensible(it)) { return true; }
// not necessary to add metadata
if (!create) { return false; }
// add missing metadata
setMeta(it);
// return hash weak collections IDs
} return it[META].w;
};
// add metadata on freeze-family methods calling
var onFreeze = function (it) {
if (FREEZE && meta.NEED && isExtensible(it) && !_has(it, META)) { setMeta(it); }
return it;
};
var meta = module.exports = {
KEY: META,
NEED: false,
fastKey: fastKey,
getWeak: getWeak,
onFreeze: onFreeze
};
});
var defineProperty$3 = _objectDp.f;
var _wksDefine = function (name) {
var $Symbol = _core.Symbol || (_core.Symbol = _library ? {} : _global.Symbol || {});
if (name.charAt(0) != '_' && !(name in $Symbol)) { defineProperty$3($Symbol, name, { value: _wksExt.f(name) }); }
};
var _keyof = function (object, el) {
var O = _toIobject(object);
var keys = _objectKeys(O);
var length = keys.length;
var index = 0;
var key;
while (length > index) { if (O[key = keys[index++]] === el) { return key; } }
};
var f$2 = Object.getOwnPropertySymbols;
var _objectGops = {
f: f$2
};
var f$3 = {}.propertyIsEnumerable;
var _objectPie = {
f: f$3
};
// all enumerable object keys, includes symbols
var _enumKeys = function (it) {
var result = _objectKeys(it);
var getSymbols = _objectGops.f;
if (getSymbols) {
var symbols = getSymbols(it);
var isEnum = _objectPie.f;
var i = 0;
var key;
while (symbols.length > i) { if (isEnum.call(it, key = symbols[i++])) { result.push(key); } }
} return result;
};
// 7.2.2 IsArray(argument)
var _isArray = Array.isArray || function isArray(arg) {
return _cof(arg) == 'Array';
};
// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)
var hiddenKeys = _enumBugKeys.concat('length', 'prototype');
var f$5 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
return _objectKeysInternal(O, hiddenKeys);
};
var _objectGopn = {
f: f$5
};
// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
var gOPN$1 = _objectGopn.f;
var toString$1 = {}.toString;
var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
? Object.getOwnPropertyNames(window) : [];
var getWindowNames = function (it) {
try {
return gOPN$1(it);
} catch (e) {
return windowNames.slice();
}
};
var f$4 = function getOwnPropertyNames(it) {
return windowNames && toString$1.call(it) == '[object Window]' ? getWindowNames(it) : gOPN$1(_toIobject(it));
};
var _objectGopnExt = {
f: f$4
};
var gOPD$1 = Object.getOwnPropertyDescriptor;
var f$6 = _descriptors ? gOPD$1 : function getOwnPropertyDescriptor(O, P) {
O = _toIobject(O);
P = _toPrimitive(P, true);
if (_ie8DomDefine) { try {
return gOPD$1(O, P);
} catch (e) { /* empty */ } }
if (_has(O, P)) { return _propertyDesc(!_objectPie.f.call(O, P), O[P]); }
};
var _objectGopd = {
f: f$6
};
'use strict';
// ECMAScript 6 symbols shim
var META = _meta.KEY;
var gOPD = _objectGopd.f;
var dP$1 = _objectDp.f;
var gOPN = _objectGopnExt.f;
var $Symbol = _global.Symbol;
var $JSON = _global.JSON;
var _stringify = $JSON && $JSON.stringify;
var PROTOTYPE$2 = 'prototype';
var HIDDEN = _wks('_hidden');
var TO_PRIMITIVE = _wks('toPrimitive');
var isEnum = {}.propertyIsEnumerable;
var SymbolRegistry = _shared('symbol-registry');
var AllSymbols = _shared('symbols');
var OPSymbols = _shared('op-symbols');
var ObjectProto$1 = Object[PROTOTYPE$2];
var USE_NATIVE = typeof $Symbol == 'function';
var QObject = _global.QObject;
// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
var setter = !QObject || !QObject[PROTOTYPE$2] || !QObject[PROTOTYPE$2].findChild;
// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
var setSymbolDesc = _descriptors && _fails(function () {
return _objectCreate(dP$1({}, 'a', {
get: function () { return dP$1(this, 'a', { value: 7 }).a; }
})).a != 7;
}) ? function (it, key, D) {
var protoDesc = gOPD(ObjectProto$1, key);
if (protoDesc) { delete ObjectProto$1[key]; }
dP$1(it, key, D);
if (protoDesc && it !== ObjectProto$1) { dP$1(ObjectProto$1, key, protoDesc); }
} : dP$1;
var wrap = function (tag) {
var sym = AllSymbols[tag] = _objectCreate($Symbol[PROTOTYPE$2]);
sym._k = tag;
return sym;
};
var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function (it) {
return typeof it == 'symbol';
} : function (it) {
return it instanceof $Symbol;
};
var $defineProperty$1 = function defineProperty(it, key, D) {
if (it === ObjectProto$1) { $defineProperty$1(OPSymbols, key, D); }
_anObject(it);
key = _toPrimitive(key, true);
_anObject(D);
if (_has(AllSymbols, key)) {
if (!D.enumerable) {
if (!_has(it, HIDDEN)) { dP$1(it, HIDDEN, _propertyDesc(1, {})); }
it[HIDDEN][key] = true;
} else {
if (_has(it, HIDDEN) && it[HIDDEN][key]) { it[HIDDEN][key] = false; }
D = _objectCreate(D, { enumerable: _propertyDesc(0, false) });
} return setSymbolDesc(it, key, D);
} return dP$1(it, key, D);
};
var $defineProperties = function defineProperties(it, P) {
_anObject(it);
var keys = _enumKeys(P = _toIobject(P));
var i = 0;
var l = keys.length;
var key;
while (l > i) { $defineProperty$1(it, key = keys[i++], P[key]); }
return it;
};
var $create = function create(it, P) {
return P === undefined ? _objectCreate(it) : $defineProperties(_objectCreate(it), P);
};
var $propertyIsEnumerable = function propertyIsEnumerable(key) {
var E = isEnum.call(this, key = _toPrimitive(key, true));
if (this === ObjectProto$1 && _has(AllSymbols, key) && !_has(OPSymbols, key)) { return false; }
return E || !_has(this, key) || !_has(AllSymbols, key) || _has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
};
var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {
it = _toIobject(it);
key = _toPrimitive(key, true);
if (it === ObjectProto$1 && _has(AllSymbols, key) && !_has(OPSymbols, key)) { return; }
var D = gOPD(it, key);
if (D && _has(AllSymbols, key) && !(_has(it, HIDDEN) && it[HIDDEN][key])) { D.enumerable = true; }
return D;
};
var $getOwnPropertyNames = function getOwnPropertyNames(it) {
var names = gOPN(_toIobject(it));
var result = [];
var i = 0;
var key;
while (names.length > i) {
if (!_has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) { result.push(key); }
} return result;
};
var $getOwnPropertySymbols = function getOwnPropertySymbols(it) {
var IS_OP = it === ObjectProto$1;
var names = gOPN(IS_OP ? OPSymbols : _toIobject(it));
var result = [];
var i = 0;
var key;
while (names.length > i) {
if (_has(AllSymbols, key = names[i++]) && (IS_OP ? _has(ObjectProto$1, key) : true)) { result.push(AllSymbols[key]); }
} return result;
};
// 19.4.1.1 Symbol([description])
if (!USE_NATIVE) {
$Symbol = function Symbol() {
if (this instanceof $Symbol) { throw TypeError('Symbol is not a constructor!'); }
var tag = _uid(arguments.length > 0 ? arguments[0] : undefined);
var $set = function (value) {
if (this === ObjectProto$1) { $set.call(OPSymbols, value); }
if (_has(this, HIDDEN) && _has(this[HIDDEN], tag)) { this[HIDDEN][tag] = false; }
setSymbolDesc(this, tag, _propertyDesc(1, value));
};
if (_descriptors && setter) { setSymbolDesc(ObjectProto$1, tag, { configurable: true, set: $set }); }
return wrap(tag);
};
_redefine($Symbol[PROTOTYPE$2], 'toString', function toString() {
return this._k;
});
_objectGopd.f = $getOwnPropertyDescriptor;
_objectDp.f = $defineProperty$1;
_objectGopn.f = _objectGopnExt.f = $getOwnPropertyNames;
_objectPie.f = $propertyIsEnumerable;
_objectGops.f = $getOwnPropertySymbols;
if (_descriptors && !_library) {
_redefine(ObjectProto$1, 'propertyIsEnumerable', $propertyIsEnumerable, true);
}
_wksExt.f = function (name) {
return wrap(_wks(name));
};
}
_export(_export.G + _export.W + _export.F * !USE_NATIVE, { Symbol: $Symbol });
for (var es6Symbols = (
// 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14
'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'
).split(','), j = 0; es6Symbols.length > j;){ _wks(es6Symbols[j++]); }
for (var wellKnownSymbols = _objectKeys(_wks.store), k = 0; wellKnownSymbols.length > k;) { _wksDefine(wellKnownSymbols[k++]); }
_export(_export.S + _export.F * !USE_NATIVE, 'Symbol', {
// 19.4.2.1 Symbol.for(key)
'for': function (key) {
return _has(SymbolRegistry, key += '')
? SymbolRegistry[key]
: SymbolRegistry[key] = $Symbol(key);
},
// 19.4.2.5 Symbol.keyFor(sym)
keyFor: function keyFor(key) {
if (isSymbol(key)) { return _keyof(SymbolRegistry, key); }
throw TypeError(key + ' is not a symbol!');
},
useSetter: function () { setter = true; },
useSimple: function () { setter = false; }
});
_export(_export.S + _export.F * !USE_NATIVE, 'Object', {
// 19.1.2.2 Object.create(O [, Properties])
create: $create,
// 19.1.2.4 Object.defineProperty(O, P, Attributes)
defineProperty: $defineProperty$1,
// 19.1.2.3 Object.defineProperties(O, Properties)
defineProperties: $defineProperties,
// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
// 19.1.2.7 Object.getOwnPropertyNames(O)
getOwnPropertyNames: $getOwnPropertyNames,
// 19.1.2.8 Object.getOwnPropertySymbols(O)
getOwnPropertySymbols: $getOwnPropertySymbols
});
// 24.3.2 JSON.stringify(value [, replacer [, space]])
$JSON && _export(_export.S + _export.F * (!USE_NATIVE || _fails(function () {
var S = $Symbol();
// MS Edge converts symbol values to JSON as {}
// WebKit converts symbol values to JSON as null
// V8 throws on boxed symbols
return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}';
})), 'JSON', {
stringify: function stringify(it) {
var arguments$1 = arguments;
if (it === undefined || isSymbol(it)) { return; } // IE8 returns string on undefined
var args = [it];
var i = 1;
var replacer, $replacer;
while (arguments.length > i) { args.push(arguments$1[i++]); }
replacer = args[1];
if (typeof replacer == 'function') { $replacer = replacer; }
if ($replacer || !_isArray(replacer)) { replacer = function (key, value) {
if ($replacer) { value = $replacer.call(this, key, value); }
if (!isSymbol(value)) { return value; }
}; }
args[1] = replacer;
return _stringify.apply($JSON, args);
}
});
// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint)
$Symbol[PROTOTYPE$2][TO_PRIMITIVE] || _hide($Symbol[PROTOTYPE$2], TO_PRIMITIVE, $Symbol[PROTOTYPE$2].valueOf);
// 19.4.3.5 Symbol.prototype[@@toStringTag]
_setToStringTag($Symbol, 'Symbol');
// 20.2.1.9 Math[@@toStringTag]
_setToStringTag(Math, 'Math', true);
// 24.3.3 JSON[@@toStringTag]
_setToStringTag(_global.JSON, 'JSON', true);
_wksDefine('asyncIterator');
_wksDefine('observable');
var symbol$1 = _core.Symbol;
var symbol = createCommonjsModule(function (module) {
module.exports = { "default": symbol$1, __esModule: true };
});
var _Symbol = unwrapExports(symbol);
var _typeof_1 = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _iterator2 = _interopRequireDefault(iterator);
var _symbol2 = _interopRequireDefault(symbol);
var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj; };
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) {
return typeof obj === "undefined" ? "undefined" : _typeof(obj);
} : function (obj) {
return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj);
};
});
unwrapExports(_typeof_1);
var possibleConstructorReturn = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _typeof3 = _interopRequireDefault(_typeof_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && ((typeof call === "undefined" ? "undefined" : (0, _typeof3.default)(call)) === "object" || typeof call === "function") ? call : self;
};
});
var _possibleConstructorReturn = unwrapExports(possibleConstructorReturn);
// Works with __proto__ only. Old v8 can't work with null proto objects.
/* eslint-disable no-proto */
var check = function (O, proto) {
_anObject(O);
if (!_isObject(proto) && proto !== null) { throw TypeError(proto + ": can't set as prototype!"); }
};
var _setProto = {
set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line
function (test, buggy, set) {
try {
set = _ctx(Function.call, _objectGopd.f(Object.prototype, '__proto__').set, 2);
set(test, []);
buggy = !(test instanceof Array);
} catch (e) { buggy = true; }
return function setPrototypeOf(O, proto) {
check(O, proto);
if (buggy) { O.__proto__ = proto; }
else { set(O, proto); }
return O;
};
}({}, false) : undefined),
check: check
};
// 19.1.3.19 Object.setPrototypeOf(O, proto)
_export(_export.S, 'Object', { setPrototypeOf: _setProto.set });
var setPrototypeOf$2 = _core.Object.setPrototypeOf;
var setPrototypeOf = createCommonjsModule(function (module) {
module.exports = { "default": setPrototypeOf$2, __esModule: true };
});
unwrapExports(setPrototypeOf);
// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
_export(_export.S, 'Object', { create: _objectCreate });
var $Object$1 = _core.Object;
var create$3 = function create(P, D) {
return $Object$1.create(P, D);
};
var create$1 = createCommonjsModule(function (module) {
module.exports = { "default": create$3, __esModule: true };
});
unwrapExports(create$1);
var inherits = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _setPrototypeOf2 = _interopRequireDefault(setPrototypeOf);
var _create2 = _interopRequireDefault(create$1);
var _typeof3 = _interopRequireDefault(_typeof_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : (0, _typeof3.default)(superClass)));
}
subClass.prototype = (0, _create2.default)(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) { _setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass; }
};
});
var _inherits = unwrapExports(inherits);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* A high-performance static matrix math library used to calculate
* affine transforms on surfaces and other renderables.
* Famo.us uses 4x4 matrices corresponding directly to
* WebKit matrices (column-major order).
*
* The internal "type" of a Matrix is a 16-long float array in
* row-major order, with:
* elements [0],[1],[2],[4],[5],[6],[8],[9],[10] forming the 3x3
* transformation matrix;
* elements [12], [13], [14] corresponding to the t_x, t_y, t_z
* translation;
* elements [3], [7], [11] set to 0;
* element [15] set to 1.
* All methods are static.
*
* @static
*
* @class Transform
*/
var Transform = {};
// WARNING: these matrices correspond to WebKit matrices, which are
// transposed from their math counterparts
Transform.precision = 1e-6;
Transform.identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
/**
* Multiply two or more Transform matrix types to return a Transform matrix.
*
* @method multiply4x4
* @static
* @param {Transform} a left Transform
* @param {Transform} b right Transform
* @return {Transform}
*/
Transform.multiply4x4 = function multiply4x4(a, b) {
return [
a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3],
a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3],
a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3],
a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3],
a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7],
a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7],
a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7],
a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7],
a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11],
a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11],
a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11],
a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11],
a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15],
a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15],
a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15],
a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15]
];
};
/**
* Fast-multiply two Transform matrix types to return a
* Matrix, assuming bottom row on each is [0 0 0 1].
*
* @method multiply
* @static
* @param {Transform} a left Transform
* @param {Transform} b right Transform
* @return {Transform}
*/
Transform.multiply = function multiply(a, b) {
return [
a[0] * b[0] + a[4] * b[1] + a[8] * b[2],
a[1] * b[0] + a[5] * b[1] + a[9] * b[2],
a[2] * b[0] + a[6] * b[1] + a[10] * b[2],
0,
a[0] * b[4] + a[4] * b[5] + a[8] * b[6],
a[1] * b[4] + a[5] * b[5] + a[9] * b[6],
a[2] * b[4] + a[6] * b[5] + a[10] * b[6],
0,
a[0] * b[8] + a[4] * b[9] + a[8] * b[10],
a[1] * b[8] + a[5] * b[9] + a[9] * b[10],
a[2] * b[8] + a[6] * b[9] + a[10] * b[10],
0,
a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12],
a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13],
a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14],
1
];
};
/**
* Return a Transform translated by additional amounts in each
* dimension. This is equivalent to the result of
*
* Transform.multiply(Matrix.translate(t[0], t[1], t[2]), m).
*
* @method thenMove
* @static
* @param {Transform} m a Transform
* @param {Array.Number} t floats delta vector of length 2 or 3
* @return {Transform}
*/
Transform.thenMove = function thenMove(m, t) {
if (!t[2]) { t[2] = 0; }
return [m[0], m[1], m[2], 0, m[4], m[5], m[6], 0, m[8], m[9], m[10], 0, m[12] + t[0], m[13] + t[1], m[14] + t[2], 1];
};
/**
* Return a Transform matrix which represents the result of a transform matrix
* applied after a move. This is faster than the equivalent multiply.
* This is equivalent to the result of:
*
* Transform.multiply(m, Transform.translate(t[0], t[1], t[2])).
*
* @method moveThen
* @static
* @param {Array.Number} v vector representing initial movement
* @param {Transform} m matrix to apply afterwards
* @return {Transform} the resulting matrix
*/
Transform.moveThen = function moveThen(v, m) {
if (!v[2]) { v[2] = 0; }
var t0 = v[0] * m[0] + v[1] * m[4] + v[2] * m[8];
var t1 = v[0] * m[1] + v[1] * m[5] + v[2] * m[9];
var t2 = v[0] * m[2] + v[1] * m[6] + v[2] * m[10];
return Transform.thenMove(m, [t0, t1, t2]);
};
/**
* Return a Transform which represents a translation by specified
* amounts in each dimension.
*
* @method translate
* @static
* @param {Number} x x translation
* @param {Number} y y translation
* @param {Number} z z translation
* @return {Transform}
*/
Transform.translate = function translate(x, y, z) {
if (z === undefined) { z = 0; }
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
};
/**
* Return a Transform scaled by a vector in each
* dimension. This is a more performant equivalent to the result of
*
* Transform.multiply(Transform.scale(s[0], s[1], s[2]), m).
*
* @method thenScale
* @static
* @param {Transform} m a matrix
* @param {Array.Number} s delta vector (array of floats &&
* array.length == 3)
* @return {Transform}
*/
Transform.thenScale = function thenScale(m, s) {
return [
s[0] * m[0], s[1] * m[1], s[2] * m[2], 0,
s[0] * m[4], s[1] * m[5], s[2] * m[6], 0,
s[0] * m[8], s[1] * m[9], s[2] * m[10], 0,
s[0] * m[12], s[1] * m[13], s[2] * m[14], 1
];
};
/**
* Return a Transform which represents a scale by specified amounts
* in each dimension.
*
* @method scale
* @static
* @param {Number} x x scale factor
* @param {Number} y y scale factor
* @param {Number} z z scale factor
* @return {Transform}
*/
Transform.scale = function scale(x, y, z) {
if (z === undefined) { z = 1; }
if (y === undefined) { y = x; }
return [x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1];
};
/**
* Return a Transform which represents a clockwise
* rotation around the x axis.
*
* @method rotateX
* @static
* @param {Number} theta radians
* @return {Transform}
*/
Transform.rotateX = function rotateX(theta) {
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
return [1, 0, 0, 0, 0, cosTheta, sinTheta, 0, 0, -sinTheta, cosTheta, 0, 0, 0, 0, 1];
};
/**
* Return a Transform which represents a clockwise
* rotation around the y axis.
*
* @method rotateY
* @static
* @param {Number} theta radians
* @return {Transform}
*/
Transform.rotateY = function rotateY(theta) {
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
return [cosTheta, 0, -sinTheta, 0, 0, 1, 0, 0, sinTheta, 0, cosTheta, 0, 0, 0, 0, 1];
};
/**
* Return a Transform which represents a clockwise
* rotation around the z axis.
*
* @method rotateZ
* @static
* @param {Number} theta radians
* @return {Transform}
*/
Transform.rotateZ = function rotateZ(theta) {
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
return [cosTheta, sinTheta, 0, 0, -sinTheta, cosTheta, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
};
/**
* Return a Transform which represents composed clockwise
* rotations along each of the axes. Equivalent to the result of
* Matrix.multiply(rotateX(phi), rotateY(theta), rotateZ(psi)).
*
* @method rotate
* @static
* @param {Number} phi radians to rotate about the positive x axis
* @param {Number} theta radians to rotate about the positive y axis
* @param {Number} psi radians to rotate about the positive z axis
* @return {Transform}
*/
Transform.rotate = function rotate(phi, theta, psi) {
var cosPhi = Math.cos(phi);
var sinPhi = Math.sin(phi);
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
var cosPsi = Math.cos(psi);
var sinPsi = Math.sin(psi);
var result = [
cosTheta * cosPsi,
cosPhi * sinPsi + sinPhi * sinTheta * cosPsi,
sinPhi * sinPsi - cosPhi * sinTheta * cosPsi,
0,
-cosTheta * sinPsi,
cosPhi * cosPsi - sinPhi * sinTheta * sinPsi,
sinPhi * cosPsi + cosPhi * sinTheta * sinPsi,
0,
sinTheta,
-sinPhi * cosTheta,
cosPhi * cosTheta,
0,
0, 0, 0, 1
];
return result;
};
/**
* Return a Transform which represents an axis-angle rotation
*
* @method rotateAxis
* @static
* @param {Array.Number} v unit vector representing the axis to rotate about
* @param {Number} theta radians to rotate clockwise about the axis
* @return {Transform}
*/
Transform.rotateAxis = function rotateAxis(v, theta) {
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
var verTheta = 1 - cosTheta; // versine of theta
var xxV = v[0] * v[0] * verTheta;
var xyV = v[0] * v[1] * verTheta;
var xzV = v[0] * v[2] * verTheta;
var yyV = v[1] * v[1] * verTheta;
var yzV = v[1] * v[2] * verTheta;
var zzV = v[2] * v[2] * verTheta;
var xs = v[0] * sinTheta;
var ys = v[1] * sinTheta;
var zs = v[2] * sinTheta;
var result = [
xxV + cosTheta, xyV + zs, xzV - ys, 0,
xyV - zs, yyV + cosTheta, yzV + xs, 0,
xzV + ys, yzV - xs, zzV + cosTheta, 0,
0, 0, 0, 1
];
return result;
};
/**
* Return a Transform which represents a transform matrix applied about
* a separate origin point.
*
* @method aboutOrigin
* @static
* @param {Array.Number} v origin point to apply matrix
* @param {Transform} m matrix to apply
* @return {Transform}
*/
Transform.aboutOrigin = function aboutOrigin(v, m) {
var t0 = v[0] - (v[0] * m[0] + v[1] * m[4] + v[2] * m[8]);
var t1 = v[1] - (v[0] * m[1] + v[1] * m[5] + v[2] * m[9]);
var t2 = v[2] - (v[0] * m[2] + v[1] * m[6] + v[2] * m[10]);
return Transform.thenMove(m, [t0, t1, t2]);
};
/**
* Return a Transform representation of a skew transformation
*
* @method skew
* @static
* @param {Number} phi scale factor skew in the x axis
* @param {Number} theta scale factor skew in the y axis
* @param {Number} psi scale factor skew in the z axis
* @return {Transform}
*/
Transform.skew = function skew(phi, theta, psi) {
return [1, Math.tan(theta), 0, 0, Math.tan(psi), 1, 0, 0, 0, Math.tan(phi), 1, 0, 0, 0, 0, 1];
};
/**
* Return a Transform representation of a skew in the x-direction
*
* @method skewX
* @static
* @param {Number} angle the angle between the top and left sides
* @return {Transform}
*/
Transform.skewX = function skewX(angle) {
return [1, 0, 0, 0, Math.tan(angle), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
};
/**
* Return a Transform representation of a skew in the y-direction
*
* @method skewY
* @static
* @param {Number} angle the angle between the top and right sides
* @return {Transform}
*/
Transform.skewY = function skewY(angle) {
return [1, Math.tan(angle), 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
};
/**
* Returns a perspective Transform matrix
*
* @method perspective
* @static
* @param {Number} focusZ z position of focal point
* @return {Transform}
*/
Transform.perspective = function perspective(focusZ) {
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -1 / focusZ, 0, 0, 0, 1];
};
/**
* Return translation vector component of given Transform
*
* @method getTranslate
* @static
* @param {Transform} m Transform
* @return {Array.Number} the translation vector [t_x, t_y, t_z]
*/
Transform.getTranslate = function getTranslate(m) {
return [m[12], m[13], m[14]];
};
/**
* Return inverse affine transform for given Transform.
* Note: This assumes m[3] = m[7] = m[11] = 0, and m[15] = 1.
* Will provide incorrect results if not invertible or preconditions not met.
*
* @method inverse
* @static
* @param {Transform} m Transform
* @return {Transform}
*/
Transform.inverse = function inverse(m) {
// only need to consider 3x3 section for affine
var c0 = m[5] * m[10] - m[6] * m[9];
var c1 = m[4] * m[10] - m[6] * m[8];
var c2 = m[4] * m[9] - m[5] * m[8];
var c4 = m[1] * m[10] - m[2] * m[9];
var c5 = m[0] * m[10] - m[2] * m[8];
var c6 = m[0] * m[9] - m[1] * m[8];
var c8 = m[1] * m[6] - m[2] * m[5];
var c9 = m[0] * m[6] - m[2] * m[4];
var c10 = m[0] * m[5] - m[1] * m[4];
var detM = m[0] * c0 - m[1] * c1 + m[2] * c2;
var invD = 1 / detM;
var result = [
invD * c0, -invD * c4, invD * c8, 0,
-invD * c1, invD * c5, -invD * c9, 0,
invD * c2, -invD * c6, invD * c10, 0,
0, 0, 0, 1
];
result[12] = -m[12] * result[0] - m[13] * result[4] - m[14] * result[8];
result[13] = -m[12] * result[1] - m[13] * result[5] - m[14] * result[9];
result[14] = -m[12] * result[2] - m[13] * result[6] - m[14] * result[10];
return result;
};
/**
* Returns the transpose of a 4x4 matrix
*
* @method transpose
* @static
* @param {Transform} m matrix
* @return {Transform} the resulting transposed matrix
*/
Transform.transpose = function transpose(m) {
return [m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]];
};
function _normSquared(v) {
return (v.length === 2) ? v[0] * v[0] + v[1] * v[1] : v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
}
function _norm(v) {
return Math.sqrt(_normSquared(v));
}
function _sign(n) {
return (n < 0) ? -1 : 1;
}
/**
* Decompose Transform into separate .translate, .rotate, .scale,
* and .skew components.
*
* @method interpret
* @static
* @param {Transform} M transform matrix
* @return {Object} matrix spec object with component matrices .translate,
* .rotate, .scale, .skew
*/
Transform.interpret = function interpret(M) {
// QR decomposition via Householder reflections
//FIRST ITERATION
//default Q1 to the identity matrix;
var x = [M[0], M[1], M[2]]; // first column vector
var sgn = _sign(x[0]); // sign of first component of x (for stability)
var xNorm = _norm(x); // norm of first column vector
var v = [x[0] + sgn * xNorm, x[1], x[2]]; // v = x + sign(x[0])|x|e1
var mult = 2 / _normSquared(v); // mult = 2/v'v
//bail out if our Matrix is singular
if (mult >= Infinity) {
return {translate: Transform.getTranslate(M), rotate: [0, 0, 0], scale: [0, 0, 0], skew: [0, 0, 0]};
}
//evaluate Q1 = I - 2vv'/v'v
var Q1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
//diagonals
Q1[0] = 1 - mult * v[0] * v[0]; // 0,0 entry
Q1[5] = 1 - mult * v[1] * v[1]; // 1,1 entry
Q1[10] = 1 - mult * v[2] * v[2]; // 2,2 entry
//upper diagonal
Q1[1] = -mult * v[0] * v[1]; // 0,1 entry
Q1[2] = -mult * v[0] * v[2]; // 0,2 entry
Q1[6] = -mult * v[1] * v[2]; // 1,2 entry
//lower diagonal
Q1[4] = Q1[1]; // 1,0 entry
Q1[8] = Q1[2]; // 2,0 entry
Q1[9] = Q1[6]; // 2,1 entry
//reduce first column of M
var MQ1 = Transform.multiply(Q1, M);
//SECOND ITERATION on (1,1) minor
var x2 = [MQ1[5], MQ1[6]];
var sgn2 = _sign(x2[0]); // sign of first component of x (for stability)
var x2Norm = _norm(x2); // norm of first column vector
var v2 = [x2[0] + sgn2 * x2Norm, x2[1]]; // v = x + sign(x[0])|x|e1
var mult2 = 2 / _normSquared(v2); // mult = 2/v'v
//evaluate Q2 = I - 2vv'/v'v
var Q2 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
//diagonal
Q2[5] = 1 - mult2 * v2[0] * v2[0]; // 1,1 entry
Q2[10] = 1 - mult2 * v2[1] * v2[1]; // 2,2 entry
//off diagonals
Q2[6] = -mult2 * v2[0] * v2[1]; // 2,1 entry
Q2[9] = Q2[6]; // 1,2 entry
//calc QR decomposition. Q = Q1*Q2, R = Q'*M
var Q = Transform.multiply(Q2, Q1); //note: really Q transpose
var R = Transform.multiply(Q, M);
//remove negative scaling
var remover = Transform.scale(R[0] < 0 ? -1 : 1, R[5] < 0 ? -1 : 1, R[10] < 0 ? -1 : 1);
R = Transform.multiply(R, remover);
Q = Transform.multiply(remover, Q);
//decompose into rotate/scale/skew matrices
var result = {};
result.translate = Transform.getTranslate(M);
result.rotate = [Math.atan2(-Q[6], Q[10]), Math.asin(Q[2]), Math.atan2(-Q[1], Q[0])];
if (!result.rotate[0]) {
result.rotate[0] = 0;
result.rotate[2] = Math.atan2(Q[4], Q[5]);
}
result.scale = [R[0], R[5], R[10]];
result.skew = [Math.atan2(R[9], result.scale[2]), Math.atan2(R[8], result.scale[2]), Math.atan2(R[4], result.scale[0])];
//double rotation workaround
if (Math.abs(result.rotate[0]) + Math.abs(result.rotate[2]) > 1.5 * Math.PI) {
result.rotate[1] = Math.PI - result.rotate[1];
if (result.rotate[1] > Math.PI) { result.rotate[1] -= 2 * Math.PI; }
if (result.rotate[1] < -Math.PI) { result.rotate[1] += 2 * Math.PI; }
if (result.rotate[0] < 0) { result.rotate[0] += Math.PI; }
else { result.rotate[0] -= Math.PI; }
if (result.rotate[2] < 0) { result.rotate[2] += Math.PI; }
else { result.rotate[2] -= Math.PI; }
}
return result;
};
/**
* Weighted average between two matrices by averaging their
* translation, rotation, scale, skew components.
* f(M1,M2,t) = (1 - t) * M1 + t * M2
*
* @method average
* @static
* @param {Transform} M1 f(M1,M2,0) = M1
* @param {Transform} M2 f(M1,M2,1) = M2
* @param {Number} t
* @return {Transform}
*/
Transform.average = function average(M1, M2, t) {
t = (t === undefined) ? 0.5 : t;
var specM1 = Transform.interpret(M1);
var specM2 = Transform.interpret(M2);
var specAvg = {
translate: [0, 0, 0],
rotate: [0, 0, 0],
scale: [0, 0, 0],
skew: [0, 0, 0]
};
for (var i = 0; i < 3; i++) {
specAvg.translate[i] = (1 - t) * specM1.translate[i] + t * specM2.translate[i];
specAvg.rotate[i] = (1 - t) * specM1.rotate[i] + t * specM2.rotate[i];
specAvg.scale[i] = (1 - t) * specM1.scale[i] + t * specM2.scale[i];
specAvg.skew[i] = (1 - t) * specM1.skew[i] + t * specM2.skew[i];
}
return Transform.build(specAvg);
};
/**
* Compose .translate, .rotate, .scale, .skew components into
* Transform matrix
*
* @method build
* @static
* @param {matrixSpec} spec object with component matrices .translate,
* .rotate, .scale, .skew
* @return {Transform} composed transform
*/
Transform.build = function build(spec) {
var scaleMatrix = Transform.scale(spec.scale[0], spec.scale[1], spec.scale[2]);
var skewMatrix = Transform.skew(spec.skew[0], spec.skew[1], spec.skew[2]);
var rotateMatrix = Transform.rotate(spec.rotate[0], spec.rotate[1], spec.rotate[2]);
return Transform.thenMove(Transform.multiply(Transform.multiply(rotateMatrix, skewMatrix), scaleMatrix), spec.translate);
};
/**
* Determine if two Transforms are component-wise equal
* Warning: breaks on perspective Transforms
*
* @method equals
* @static
* @param {Transform} a matrix
* @param {Transform} b matrix
* @return {boolean}
*/
Transform.equals = function equals(a, b) {
return !Transform.notEquals(a, b);
};
/**
* Determine if two Transforms are component-wise unequal
* Warning: breaks on perspective Transforms
*
* @method notEquals
* @static
* @param {Transform} a matrix
* @param {Transform} b matrix
* @return {boolean}
*/
Transform.notEquals = function notEquals(a, b) {
if (a === b) { return false; }
// shortci
return !(a && b) ||
a[12] !== b[12] || a[13] !== b[13] || a[14] !== b[14] ||
a[0] !== b[0] || a[1] !== b[1] || a[2] !== b[2] ||
a[4] !== b[4] || a[5] !== b[5] || a[6] !== b[6] ||
a[8] !== b[8] || a[9] !== b[9] || a[10] !== b[10];
};
/**
* Constrain angle-trio components to range of [-pi, pi).
*
* @method normalizeRotation
* @static
* @param {Array.Number} rotation phi, theta, psi (array of floats
* && array.length == 3)
* @return {Array.Number} new phi, theta, psi triplet
* (array of floats && array.length == 3)
*/
Transform.normalizeRotation = function normalizeRotation(rotation) {
var result = rotation.slice(0);
if (result[0] === Math.PI * 0.5 || result[0] === -Math.PI * 0.5) {
result[0] = -result[0];
result[1] = Math.PI - result[1];
result[2] -= Math.PI;
}
if (result[0] > Math.PI * 0.5) {
result[0] = result[0] - Math.PI;
result[1] = Math.PI - result[1];
result[2] -= Math.PI;
}
if (result[0] < -Math.PI * 0.5) {
result[0] = result[0] + Math.PI;
result[1] = -Math.PI - result[1];
result[2] -= Math.PI;
}
while (result[1] < -Math.PI) { result[1] += 2 * Math.PI; }
while (result[1] >= Math.PI) { result[1] -= 2 * Math.PI; }
while (result[2] < -Math.PI) { result[2] += 2 * Math.PI; }
while (result[2] >= Math.PI) { result[2] -= 2 * Math.PI; }
return result;
};
/**
* (Property) Array defining a translation forward in z by 1
*
* @property {array} inFront
* @static
* @final
*/
Transform.inFront = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1e-3, 1];
/**
* (Property) Array defining a translation backwards in z by 1
*
* @property {array} behind
* @static
* @final
*/
Transform.behind = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1e-3, 1];
var Transform_1 = Transform;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* This namespace holds standalone functionality.
* Currently includes name mapping for transition curves,
* name mapping for origin pairs, and the after() function.
*
* @class Utility
* @static
*/
var Utility = {};
/**
* Table of direction array positions
*
* @property {object} Direction
* @final
*/
Utility.Direction = {
X: 0,
Y: 1,
Z: 2
};
/**
* Return wrapper around callback function. Once the wrapper is called N
* times, invoke the callback function. Arguments and scope preserved.
*
* @method after
*
* @param {number} count number of calls before callback function invoked
* @param {Function} callback wrapped callback function
*
* @return {function} wrapped callback with coundown feature
*/
Utility.after = function after(count, callback) {
var counter = count;
return function() {
counter--;
if (counter === 0) { callback.apply(this, arguments); }
};
};
/**
* Load a URL and return its contents in a callback
*
* @method loadURL
*
* @param {string} url URL of object
* @param {function} callback callback to dispatch with content
*/
Utility.loadURL = function loadURL(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function onreadystatechange() {
if (this.readyState === 4) {
if (callback) { callback(this.responseText); }
}
};
xhr.open('GET', url);
xhr.send();
};
/**
* Create a document fragment from a string of HTML
*
* @method createDocumentFragmentFromHTML
*
* @param {string} html HTML to convert to DocumentFragment
*
* @return {DocumentFragment} DocumentFragment representing input HTML
*/
Utility.createDocumentFragmentFromHTML = function createDocumentFragmentFromHTML(html) {
var element = document.createElement('div');
element.innerHTML = html;
var result = document.createDocumentFragment();
while (element.hasChildNodes()) { result.appendChild(element.firstChild); }
return result;
};
/*
* Deep clone an object.
* @param b {Object} Object to clone
* @return a {Object} Cloned object.
*/
Utility.clone = function clone(b) {
var a;
if (typeof b === 'object') {
a = (b instanceof Array) ? [] : {};
for (var key in b) {
if (typeof b[key] === 'object' && b[key] !== null) {
if (b[key] instanceof Array) {
a[key] = new Array(b[key].length);
for (var i = 0; i < b[key].length; i++) {
a[key][i] = Utility.clone(b[key][i]);
}
}
else {
a[key] = Utility.clone(b[key]);
}
}
else {
a[key] = b[key];
}
}
}
else {
a = b;
}
return a;
};
var Utility_1 = Utility;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: david@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/*eslint-disable new-cap */
/**
* Transition meta-method to support transitioning multiple
* values with scalar-only methods.
*
*
* @class MultipleTransition
* @constructor
*
* @param {Object} method Transionable class to multiplex
*/
function MultipleTransition(method) {
this.method = method;
this._instances = [];
this.state = [];
}
MultipleTransition.SUPPORTS_MULTIPLE = true;
/**
* Get the state of each transition.
*
* @method get
*
* @return state {Number|Array} state array
*/
MultipleTransition.prototype.get = function get() {
var this$1 = this;
for (var i = 0; i < this._instances.length; i++) {
this$1.state[i] = this$1._instances[i].get();
}
return this.state;
};
/**
* Set the end states with a shared transition, with optional callback.
*
* @method set
*
* @param {Number|Array} endState Final State. Use a multi-element argument for multiple transitions.
* @param {Object} transition Transition definition, shared among all instances
* @param {Function} callback called when all endStates have been reached.
*/
MultipleTransition.prototype.set = function set(endState, transition, callback) {
var this$1 = this;
var _allCallback = Utility_1.after(endState.length, callback);
for (var i = 0; i < endState.length; i++) {
if (!this$1._instances[i]) { this$1._instances[i] = new (this$1.method)(); }
this$1._instances[i].set(endState[i], transition, _allCallback);
}
};
/**
* Reset all transitions to start state.
*
* @method reset
*
* @param {Number|Array} startState Start state
*/
MultipleTransition.prototype.reset = function reset(startState) {
var this$1 = this;
for (var i = 0; i < startState.length; i++) {
if (!this$1._instances[i]) { this$1._instances[i] = new (this$1.method)(); }
this$1._instances[i].reset(startState[i]);
}
};
var MultipleTransition_1 = MultipleTransition;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: david@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
*
* A state maintainer for a smooth transition between
* numerically-specified states. Example numeric states include floats or
* Transfornm objects.
*
* An initial state is set with the constructor or set(startValue). A
* corresponding end state and transition are set with set(endValue,
* transition). Subsequent calls to set(endValue, transition) begin at
* the last state. Calls to get(timestamp) provide the _interpolated state
* along the way.
*
* Note that there is no event loop here - calls to get() are the only way
* to find out state projected to the current (or provided) time and are
* the only way to trigger callbacks. Usually this kind of object would
* be part of the render() path of a visible component.
*
* @class TweenTransition
* @constructor
*
* @param {Object} options TODO
* beginning state
*/
function TweenTransition(options) {
this.options = Object.create(TweenTransition.DEFAULT_OPTIONS);
if (options) { this.setOptions(options); }
this._startTime = 0;
this._startValue = 0;
this._updateTime = 0;
this._endValue = 0;
this._curve = undefined;
this._duration = 0;
this._active = false;
this._callback = undefined;
this.state = 0;
this.velocity = undefined;
}
/**
* Transition curves mapping independent variable t from domain [0,1] to a
* range within [0,1]. Includes functions 'linear', 'easeIn', 'easeOut',
* 'easeInOut', 'easeOutBounce', 'spring'.
*
* @property {object} Curve
* @final
*/
TweenTransition.Curves = {
linear: function(t) {
return t;
},
easeIn: function(t) {
return t*t;
},
easeOut: function(t) {
return t*(2-t);
},
easeInOut: function(t) {
if (t <= 0.5) { return 2*t*t; }
else { return -2*t*t + 4*t - 1; }
},
easeOutBounce: function(t) {
return t*(3 - 2*t);
},
spring: function(t) {
return (1 - t) * Math.sin(6 * Math.PI * t) + t;
}
};
TweenTransition.SUPPORTS_MULTIPLE = true;
TweenTransition.DEFAULT_OPTIONS = {
curve: TweenTransition.Curves.linear,
duration: 500,
speed: 0 /* considered only if positive */
};
var registeredCurves = {};
/**
* Add "unit" curve to internal dictionary of registered curves.
*
* @method registerCurve
*
* @static
*
* @param {string} curveName dictionary key
* @param {unitCurve} curve function of one numeric variable mapping [0,1]
* to range inside [0,1]
* @return {boolean} false if key is taken, else true
*/
TweenTransition.registerCurve = function registerCurve(curveName, curve) {
if (!registeredCurves[curveName]) {
registeredCurves[curveName] = curve;
return true;
}
else {
return false;
}
};
/**
* Remove object with key "curveName" from internal dictionary of registered
* curves.
*
* @method unregisterCurve
*
* @static
*
* @param {string} curveName dictionary key
* @return {boolean} false if key has no dictionary value
*/
TweenTransition.unregisterCurve = function unregisterCurve(curveName) {
if (registeredCurves[curveName]) {
delete registeredCurves[curveName];
return true;
}
else {
return false;
}
};
/**
* Retrieve function with key "curveName" from internal dictionary of
* registered curves. Default curves are defined in the
* TweenTransition.Curves array, where the values represent
* unitCurve functions.
*
* @method getCurve
*
* @static
*
* @param {string} curveName dictionary key
* @return {unitCurve} curve function of one numeric variable mapping [0,1]
* to range inside [0,1]
*/
TweenTransition.getCurve = function getCurve(curveName) {
var curve = registeredCurves[curveName];
if (curve !== undefined) { return curve; }
else { throw new Error('curve not registered'); }
};
/**
* Retrieve all available curves.
*
* @method getCurves
*
* @static
*
* @return {object} curve functions of one numeric variable mapping [0,1]
* to range inside [0,1]
*/
TweenTransition.getCurves = function getCurves() {
return registeredCurves;
};
// Interpolate: If a linear function f(0) = a, f(1) = b, then return f(t)
function _interpolate(a, b, t) {
return ((1 - t) * a) + (t * b);
}
function _clone(obj) {
if (obj instanceof Object) {
if (obj instanceof Array) { return obj.slice(0); }
else { return Object.create(obj); }
}
else { return obj; }
}
// Fill in missing properties in "transition" with those in defaultTransition, and
// convert internal named curve to function object, returning as new
// object.
function _normalize(transition, defaultTransition) {
var result = {curve: defaultTransition.curve};
if (defaultTransition.duration) { result.duration = defaultTransition.duration; }
if (defaultTransition.speed) { result.speed = defaultTransition.speed; }
if (transition instanceof Object) {
if (transition.duration !== undefined) { result.duration = transition.duration; }
if (transition.curve) { result.curve = transition.curve; }
if (transition.speed) { result.speed = transition.speed; }
}
if (typeof result.curve === 'string') { result.curve = TweenTransition.getCurve(result.curve); }
return result;
}
/**
* Set internal options, overriding any default options.
*
* @method setOptions
*
*
* @param {Object} options options object
* @param {Object} [options.curve] function mapping [0,1] to [0,1] or identifier
* @param {Number} [options.duration] duration in ms
* @param {Number} [options.speed] speed in pixels per ms
*/
TweenTransition.prototype.setOptions = function setOptions(options) {
if (options.curve !== undefined) { this.options.curve = options.curve; }
if (options.duration !== undefined) { this.options.duration = options.duration; }
if (options.speed !== undefined) { this.options.speed = options.speed; }
};
/**
* Add transition to end state to the queue of pending transitions. Special
* Use: calling without a transition resets the object to that state with
* no pending actions
*
* @method set
*
*
* @param {number|FamousMatrix|Array.Number|Object.<number, number>} endValue
* end state to which we _interpolate
* @param {transition=} transition object of type {duration: number, curve:
* f[0,1] -> [0,1] or name}. If transition is omitted, change will be
* instantaneous.
* @param {function()=} callback Zero-argument function to call on observed
* completion (t=1)
*/
TweenTransition.prototype.set = function set(endValue, transition, callback) {
if (!transition) {
this.reset(endValue);
if (callback) { callback(); }
return;
}
this._startValue = _clone(this.get());
transition = _normalize(transition, this.options);
if (transition.speed) {
var startValue = this._startValue;
if (startValue instanceof Object) {
var variance = 0;
for (var i in startValue) { variance += (endValue[i] - startValue[i]) * (endValue[i] - startValue[i]); }
transition.duration = Math.sqrt(variance) / transition.speed;
}
else {
transition.duration = Math.abs(endValue - startValue) / transition.speed;
}
}
this._startTime = Date.now();
this._endValue = _clone(endValue);
this._startVelocity = _clone(transition.velocity);
this._duration = transition.duration;
this._curve = transition.curve;
this._active = true;
this._callback = callback;
};
/**
* Cancel all transitions and reset to a stable state
*
* @method reset
*
* @param {number|Array.Number|Object.<number, number>} startValue
* starting state
* @param {number} startVelocity
* starting velocity
*/
TweenTransition.prototype.reset = function reset(startValue, startVelocity) {
if (this._callback) {
var callback = this._callback;
this._callback = undefined;
callback();
}
this.state = _clone(startValue);
this.velocity = _clone(startVelocity);
this._startTime = 0;
this._duration = 0;
this._updateTime = 0;
this._startValue = this.state;
this._startVelocity = this.velocity;
this._endValue = this.state;
this._active = false;
};
/**
* Get current velocity
*
* @method getVelocity
*
* @returns {Number} velocity
*/
TweenTransition.prototype.getVelocity = function getVelocity() {
return this.velocity;
};
/**
* Get interpolated state of current action at provided time. If the last
* action has completed, invoke its callback.
*
* @method get
*
*
* @param {number=} timestamp Evaluate the curve at a normalized version of this
* time. If omitted, use current time. (Unix epoch time)
* @return {number|Object.<number|string, number>} beginning state
* _interpolated to this point in time.
*/
TweenTransition.prototype.get = function get(timestamp) {
this.update(timestamp);
return this.state;
};
function _calculateVelocity(current, start, curve, duration, t) {
var velocity;
var eps = 1e-7;
var speed = (curve(t) - curve(t - eps)) / eps;
if (current instanceof Array) {
velocity = [];
for (var i = 0; i < current.length; i++){
if (typeof current[i] === 'number')
{ velocity[i] = speed * (current[i] - start[i]) / duration; }
else
{ velocity[i] = 0; }
}
}
else { velocity = speed * (current - start) / duration; }
return velocity;
}
function _calculateState(start, end, t) {
var state;
if (start instanceof Array) {
state = [];
for (var i = 0; i < start.length; i++) {
if (typeof start[i] === 'number')
{ state[i] = _interpolate(start[i], end[i], t); }
else
{ state[i] = start[i]; }
}
}
else { state = _interpolate(start, end, t); }
return state;
}
/**
* Update internal state to the provided timestamp. This may invoke the last
* callback and begin a new action.
*
* @method update
*
*
* @param {number=} timestamp Evaluate the curve at a normalized version of this
* time. If omitted, use current time. (Unix epoch time)
*/
TweenTransition.prototype.update = function update(timestamp) {
if (!this._active) {
if (this._callback) {
var callback = this._callback;
this._callback = undefined;
callback();
}
return;
}
if (!timestamp) { timestamp = Date.now(); }
if (this._updateTime >= timestamp) { return; }
this._updateTime = timestamp;
var timeSinceStart = timestamp - this._startTime;
if (timeSinceStart >= this._duration) {
this.state = this._endValue;
this.velocity = _calculateVelocity(this.state, this._startValue, this._curve, this._duration, 1);
this._active = false;
}
else if (timeSinceStart < 0) {
this.state = this._startValue;
this.velocity = this._startVelocity;
}
else {
var t = timeSinceStart / this._duration;
this.state = _calculateState(this._startValue, this._endValue, this._curve(t));
this.velocity = _calculateVelocity(this.state, this._startValue, this._curve, this._duration, t);
}
};
/**
* Is there at least one action pending completion?
*
* @method isActive
*
*
* @return {boolean}
*/
TweenTransition.prototype.isActive = function isActive() {
return this._active;
};
/**
* Halt transition at current state and erase all pending actions.
*
* @method halt
*
*/
TweenTransition.prototype.halt = function halt() {
this.reset(this.get());
};
// Register all the default curves
TweenTransition.registerCurve('linear', TweenTransition.Curves.linear);
TweenTransition.registerCurve('easeIn', TweenTransition.Curves.easeIn);
TweenTransition.registerCurve('easeOut', TweenTransition.Curves.easeOut);
TweenTransition.registerCurve('easeInOut', TweenTransition.Curves.easeInOut);
TweenTransition.registerCurve('easeOutBounce', TweenTransition.Curves.easeOutBounce);
TweenTransition.registerCurve('spring', TweenTransition.Curves.spring);
TweenTransition.customCurve = function customCurve(v1, v2) {
v1 = v1 || 0; v2 = v2 || 0;
return function(t) {
return v1*t + (-2*v1 - v2 + 3)*t*t + (v1 + v2 - 2)*t*t*t;
};
};
var TweenTransition_1 = TweenTransition;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: david@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/*eslint-disable new-cap */
/**
* A state maintainer for a smooth transition between
* numerically-specified states. Example numeric states include floats or
* Transform objects.
*
* An initial state is set with the constructor or set(startState). A
* corresponding end state and transition are set with set(endState,
* transition). Subsequent calls to set(endState, transition) begin at
* the last state. Calls to get(timestamp) provide the interpolated state
* along the way.
*
* Note that there is no event loop here - calls to get() are the only way
* to find state projected to the current (or provided) time and are
* the only way to trigger callbacks. Usually this kind of object would
* be part of the render() path of a visible component.
*
* @class Transitionable
* @constructor
* @param {number|Array.Number|Object.<number|string, number>} start
* beginning state
*/
function Transitionable(start) {
this.currentAction = null;
this.actionQueue = [];
this.callbackQueue = [];
this.state = 0;
this.velocity = undefined;
this._callback = undefined;
this._engineInstance = null;
this._currentMethod = null;
this.set(start);
}
var transitionMethods = {};
Transitionable.register = function register(methods) {
var success = true;
for (var method in methods) {
if (!Transitionable.registerMethod(method, methods[method]))
{ success = false; }
}
return success;
};
Transitionable.registerMethod = function registerMethod(name, engineClass) {
if (!(name in transitionMethods)) {
transitionMethods[name] = engineClass;
return true;
}
else { return false; }
};
Transitionable.unregisterMethod = function unregisterMethod(name) {
if (name in transitionMethods) {
delete transitionMethods[name];
return true;
}
else { return false; }
};
function _loadNext() {
if (this._callback) {
var callback = this._callback;
this._callback = undefined;
callback();
}
if (this.actionQueue.length <= 0) {
this.set(this.get()); // no update required
return;
}
this.currentAction = this.actionQueue.shift();
this._callback = this.callbackQueue.shift();
var method = null;
var endValue = this.currentAction[0];
var transition = this.currentAction[1];
if (transition instanceof Object && transition.method) {
method = transition.method;
if (typeof method === 'string') { method = transitionMethods[method]; }
}
else {
method = TweenTransition_1;
}
if (this._currentMethod !== method) {
if (!(endValue instanceof Object) || method.SUPPORTS_MULTIPLE === true || endValue.length <= method.SUPPORTS_MULTIPLE) {
this._engineInstance = new method();
}
else {
this._engineInstance = new MultipleTransition_1(method);
}
this._currentMethod = method;
}
this._engineInstance.reset(this.state, this.velocity);
if (this.velocity !== undefined) { transition.velocity = this.velocity; }
this._engineInstance.set(endValue, transition, _loadNext.bind(this));
}
/**
* Add transition to end state to the queue of pending transitions. Special
* Use: calling without a transition resets the object to that state with
* no pending actions
*
* @method set
*
* @param {number|FamousMatrix|Array.Number|Object.<number, number>} endState
* end state to which we interpolate
* @param {transition=} transition object of type {duration: number, curve:
* f[0,1] -> [0,1] or name}. If transition is omitted, change will be
* instantaneous.
* @param {function()=} callback Zero-argument function to call on observed
* completion (t=1)
*/
Transitionable.prototype.set = function set(endState, transition, callback) {
if (!transition) {
this.reset(endState);
if (callback) { callback(); }
return this;
}
var action = [endState, transition];
this.actionQueue.push(action);
this.callbackQueue.push(callback);
if (!this.currentAction) { _loadNext.call(this); }
return this;
};
/**
* Cancel all transitions and reset to a stable state
*
* @method reset
*
* @param {number|Array.Number|Object.<number, number>} startState
* stable state to set to
*/
Transitionable.prototype.reset = function reset(startState, startVelocity) {
this._currentMethod = null;
this._engineInstance = null;
this._callback = undefined;
this.state = startState;
this.velocity = startVelocity;
this.currentAction = null;
this.actionQueue = [];
this.callbackQueue = [];
};
/**
* Add delay action to the pending action queue queue.
*
* @method delay
*
* @param {number} duration delay time (ms)
* @param {function} callback Zero-argument function to call on observed
* completion (t=1)
*/
Transitionable.prototype.delay = function delay(duration, callback) {
var endValue;
if (this.actionQueue.length) { endValue = this.actionQueue[this.actionQueue.length - 1][0]; }
else if (this.currentAction) { endValue = this.currentAction[0]; }
else { endValue = this.get(); }
return this.set(endValue, { duration: duration,
curve: function() {
return 0;
}},
callback
);
};
/**
* Get interpolated state of current action at provided time. If the last
* action has completed, invoke its callback.
*
* @method get
*
* @param {number=} timestamp Evaluate the curve at a normalized version of this
* time. If omitted, use current time. (Unix epoch time)
* @return {number|Object.<number|string, number>} beginning state
* interpolated to this point in time.
*/
Transitionable.prototype.get = function get(timestamp) {
if (this._engineInstance) {
if (this._engineInstance.getVelocity)
{ this.velocity = this._engineInstance.getVelocity(); }
this.state = this._engineInstance.get(timestamp);
}
return this.state;
};
/**
* Is there at least one action pending completion?
*
* @method isActive
*
* @return {boolean}
*/
Transitionable.prototype.isActive = function isActive() {
return !!this.currentAction;
};
/**
* Halt transition at current state and erase all pending actions.
*
* @method halt
*/
Transitionable.prototype.halt = function halt() {
return this.set(this.get());
};
var Transitionable_1 = Transitionable;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: david@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* A library of curves which map an animation explicitly as a function of time.
*
* @class Easing
*/
var Easing = {
/**
* @property inQuad
* @static
*/
inQuad: function(t) {
return t*t;
},
/**
* @property outQuad
* @static
*/
outQuad: function(t) {
return -(t-=1)*t+1;
},
/**
* @property inOutQuad
* @static
*/
inOutQuad: function(t) {
if ((t/=.5) < 1) { return .5*t*t; }
return -.5*((--t)*(t-2) - 1);
},
/**
* @property inCubic
* @static
*/
inCubic: function(t) {
return t*t*t;
},
/**
* @property outCubic
* @static
*/
outCubic: function(t) {
return ((--t)*t*t + 1);
},
/**
* @property inOutCubic
* @static
*/
inOutCubic: function(t) {
if ((t/=.5) < 1) { return .5*t*t*t; }
return .5*((t-=2)*t*t + 2);
},
/**
* @property inQuart
* @static
*/
inQuart: function(t) {
return t*t*t*t;
},
/**
* @property outQuart
* @static
*/
outQuart: function(t) {
return -((--t)*t*t*t - 1);
},
/**
* @property inOutQuart
* @static
*/
inOutQuart: function(t) {
if ((t/=.5) < 1) { return .5*t*t*t*t; }
return -.5 * ((t-=2)*t*t*t - 2);
},
/**
* @property inQuint
* @static
*/
inQuint: function(t) {
return t*t*t*t*t;
},
/**
* @property outQuint
* @static
*/
outQuint: function(t) {
return ((--t)*t*t*t*t + 1);
},
/**
* @property inOutQuint
* @static
*/
inOutQuint: function(t) {
if ((t/=.5) < 1) { return .5*t*t*t*t*t; }
return .5*((t-=2)*t*t*t*t + 2);
},
/**
* @property inSine
* @static
*/
inSine: function(t) {
return -1.0*Math.cos(t * (Math.PI/2)) + 1.0;
},
/**
* @property outSine
* @static
*/
outSine: function(t) {
return Math.sin(t * (Math.PI/2));
},
/**
* @property inOutSine
* @static
*/
inOutSine: function(t) {
return -.5*(Math.cos(Math.PI*t) - 1);
},
/**
* @property inExpo
* @static
*/
inExpo: function(t) {
return (t===0) ? 0.0 : Math.pow(2, 10 * (t - 1));
},
/**
* @property outExpo
* @static
*/
outExpo: function(t) {
return (t===1.0) ? 1.0 : (-Math.pow(2, -10 * t) + 1);
},
/**
* @property inOutExpo
* @static
*/
inOutExpo: function(t) {
if (t===0) { return 0.0; }
if (t===1.0) { return 1.0; }
if ((t/=.5) < 1) { return .5 * Math.pow(2, 10 * (t - 1)); }
return .5 * (-Math.pow(2, -10 * --t) + 2);
},
/**
* @property inCirc
* @static
*/
inCirc: function(t) {
return -(Math.sqrt(1 - t*t) - 1);
},
/**
* @property outCirc
* @static
*/
outCirc: function(t) {
return Math.sqrt(1 - (--t)*t);
},
/**
* @property inOutCirc
* @static
*/
inOutCirc: function(t) {
if ((t/=.5) < 1) { return -.5 * (Math.sqrt(1 - t*t) - 1); }
return .5 * (Math.sqrt(1 - (t-=2)*t) + 1);
},
/**
* @property inElastic
* @static
*/
inElastic: function(t) {
var s=1.70158;var p=0;var a=1.0;
if (t===0) { return 0.0; } if (t===1) { return 1.0; } if (!p) { p=.3; }
s = p/(2*Math.PI) * Math.asin(1.0/a);
return -(a*Math.pow(2,10*(t-=1)) * Math.sin((t-s)*(2*Math.PI)/ p));
},
/**
* @property outElastic
* @static
*/
outElastic: function(t) {
var s=1.70158;var p=0;var a=1.0;
if (t===0) { return 0.0; } if (t===1) { return 1.0; } if (!p) { p=.3; }
s = p/(2*Math.PI) * Math.asin(1.0/a);
return a*Math.pow(2,-10*t) * Math.sin((t-s)*(2*Math.PI)/p) + 1.0;
},
/**
* @property inOutElastic
* @static
*/
inOutElastic: function(t) {
var s=1.70158;var p=0;var a=1.0;
if (t===0) { return 0.0; } if ((t/=.5)===2) { return 1.0; } if (!p) { p=(.3*1.5); }
s = p/(2*Math.PI) * Math.asin(1.0/a);
if (t < 1) { return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin((t-s)*(2*Math.PI)/p)); }
return a*Math.pow(2,-10*(t-=1)) * Math.sin((t-s)*(2*Math.PI)/p)*.5 + 1.0;
},
/**
* @property inBack
* @static
*/
inBack: function(t, s) {
if (s === undefined) { s = 1.70158; }
return t*t*((s+1)*t - s);
},
/**
* @property outBack
* @static
*/
outBack: function(t, s) {
if (s === undefined) { s = 1.70158; }
return ((--t)*t*((s+1)*t + s) + 1);
},
/**
* @property inOutBack
* @static
*/
inOutBack: function(t, s) {
if (s === undefined) { s = 1.70158; }
if ((t/=.5) < 1) { return .5*(t*t*(((s*=(1.525))+1)*t - s)); }
return .5*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2);
},
/**
* @property inBounce
* @static
*/
inBounce: function(t) {
return 1.0 - Easing.outBounce(1.0-t);
},
/**
* @property outBounce
* @static
*/
outBounce: function(t) {
if (t < (1/2.75)) {
return (7.5625*t*t);
} else if (t < (2/2.75)) {
return (7.5625*(t-=(1.5/2.75))*t + .75);
} else if (t < (2.5/2.75)) {
return (7.5625*(t-=(2.25/2.75))*t + .9375);
} else {
return (7.5625*(t-=(2.625/2.75))*t + .984375);
}
},
/**
* @property inOutBounce
* @static
*/
inOutBounce: function(t) {
if (t < .5) { return Easing.inBounce(t*2) * .5; }
return Easing.outBounce(t*2-1.0) * .5 + .5;
}
};
var Easing_1 = Easing;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: david@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* A class for transitioning the state of a Transform by transitioning the
* X, Y, and Z axes of it's translate, scale, skew and rotate components
* independently.
*
* @class TransitionableTransform
* @constructor
*
* @param [transform=Transform.identity] {Transform} The initial transform state
*/
function TransitionableTransform(transform) {
var this$1 = this;
this._final = Transform_1.identity.slice();
this._finalTranslate = [0, 0, 0];
this._finalRotate = [0, 0, 0];
this._finalSkew = [0, 0, 0];
this._finalScale = [1, 1, 1];
this.translate = [];
this.rotate = [];
this.skew = [];
this.scale = [];
for (var i=0; i<3; i+=1) {
this$1.translate[i] = new Transitionable_1(this$1._finalTranslate[i]);
this$1.rotate[i] = new Transitionable_1(this$1._finalRotate[i]);
this$1.skew[i] = new Transitionable_1(this$1._finalSkew[i]);
this$1.scale[i] = new Transitionable_1(this$1._finalScale[i]);
}
if (transform) { this.set(transform); }
}
function _build() {
return Transform_1.build({
translate: [this.translate[0].get(), this.translate[1].get(), this.translate[2].get()],
rotate: [this.rotate[0].get(), this.rotate[1].get(), this.rotate[2].get()],
skew: [this.skew[0].get(), this.skew[1].get(), this.skew[2].get()],
scale: [this.scale[0].get(), this.scale[1].get(), this.scale[2].get()]
});
}
function _buildFinal() {
return Transform_1.build({
translate: this._finalTranslate,
rotate: this._finalRotate,
skew: this._finalSkew,
scale: this._finalScale
});
}
function _countOfType(array, type) {
var count = 0;
for (var i=0; i<array.length; i+=1) {
if (typeof array[i] === type+'') {
count+=1;
}
}
return count;
}
/**
* An optimized way of setting only the translation component of a Transform. Axes who's values are null will not be affected.
*
* @method setTranslate
* @chainable
*
* @param translate {Array} New translation state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setTranslate = function setTranslate(translate, transition, callback) {
var this$1 = this;
var numberOfAxes = _countOfType(translate, 'number');
var _callback = callback ? Utility_1.after(numberOfAxes, callback) : null;
for (var i=0; i<translate.length; i+=1) {
if (typeof translate[i] === 'number') {
this$1.translate[i].set(translate[i], transition, _callback);
this$1._finalTranslate[i] = translate[i];
}
}
this._final = _buildFinal.call(this);
return this;
};
/**
* Translate only along the X axis of the translation component of a Transform.
*
* @method setTranslateX
* @chainable
*
* @param translate {Number} New translation state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setTranslateX = function setTranslateX(translate, transition, callback) {
this.translate[0].set(translate, transition, callback);
this._finalTranslate[0] = translate;
this._final = _buildFinal.call(this);
return this;
};
/**
* Translate only along the Y axis of the translation component of a Transform.
*
* @method setTranslateY
* @chainable
*
* @param translate {Number} New translation state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setTranslateY = function setTranslateY(translate, transition, callback) {
this.translate[1].set(translate, transition, callback);
this._finalTranslate[1] = translate;
this._final = _buildFinal.call(this);
return this;
};
/**
* Translate only along the Z axis of the translation component of a Transform.
*
* @method setTranslateZ
* @chainable
*
* @param translate {Number} New translation state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setTranslateZ = function setTranslateZ(translate, transition, callback) {
this.translate[2].set(translate, transition, callback);
this._finalTranslate[2] = translate;
this._final = _buildFinal.call(this);
return this;
};
/**
* An optimized way of setting only the scale component of a Transform. Axes who's values are null will not be affected.
*
* @method setScale
* @chainable
*
* @param scale {Array} New scale state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setScale = function setScale(scale, transition, callback) {
var this$1 = this;
var numberOfAxes = _countOfType(scale, 'number');
var _callback = callback ? Utility_1.after(numberOfAxes, callback) : null;
for (var i=0; i<scale.length; i+=1) {
if (typeof scale[i] === 'number') {
this$1.scale[i].set(scale[i], transition, _callback);
this$1._finalScale[i] = scale[i];
}
}
this._final = _buildFinal.call(this);
return this;
};
/**
* Scale only along the X axis of the scale component of a Transform.
*
* @method setScaleX
* @chainable
*
* @param scale {Number} New scale state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setScaleX = function setScaleX(scale, transition, callback) {
this.scale[0].set(scale, transition, callback);
this._finalScale[0] = scale;
this._final = _buildFinal.call(this);
return this;
};
/**
* Scale only along the Y axis of the scale component of a Transform.
*
* @method setScaleY
* @chainable
*
* @param scale {Number} New scale state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setScaleY = function setScaleY(scale, transition, callback) {
this.scale[1].set(scale, transition, callback);
this._finalScale[1] = scale;
this._final = _buildFinal.call(this);
return this;
};
/**
* Scale only along the Z axis of the scale component of a Transform.
*
* @method setScaleZ
* @chainable
*
* @param scale {Number} New scale state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setScaleZ = function setScaleZ(scale, transition, callback) {
this.scale[2].set(scale, transition, callback);
this._finalScale[2] = scale;
this._final = _buildFinal.call(this);
return this;
};
/**
* An optimized way of setting only the rotational component of a Transform. Axes who's values are null will not be affected.
*
* @method setRotate
* @chainable
*
* @param eulerAngles {Array} Euler angles for new rotation state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setRotate = function setRotate(eulerAngles, transition, callback) {
var this$1 = this;
var numberOfAxes = _countOfType(eulerAngles, 'number');
var _callback = callback ? Utility_1.after(numberOfAxes, callback) : null;
for (var i=0; i<eulerAngles.length; i+=1) {
if (typeof eulerAngles[i] === 'number') {
this$1.rotate[i].set(eulerAngles[i], transition, _callback);
this$1._finalRotate[i] = eulerAngles[i];
}
}
this._final = _buildFinal.call(this);
return this;
};
/**
* Rotate only about the X axis of the rotational component of a Transform.
*
* @method setScaleX
* @chainable
*
* @param eulerAngle {Number} New rotational state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setRotateX = function setRotateX(eulerAngle, transition, callback) {
this.rotate[0].set(eulerAngle, transition, callback);
this._finalRotate[0] = eulerAngle;
this._final = _buildFinal.call(this);
return this;
};
/**
* Rotate only about the Y axis of the rotational component of a Transform.
*
* @method setScaleY
* @chainable
*
* @param eulerAngle {Number} New rotational state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setRotateY = function setRotateY(eulerAngle, transition, callback) {
this.rotate[1].set(eulerAngle, transition, callback);
this._finalRotate[1] = eulerAngle;
this._final = _buildFinal.call(this);
return this;
};
/**
* Rotate only about the Z axis of the rotational component of a Transform.
*
* @method setScaleZ
* @chainable
*
* @param eulerAngle {Number} New rotational state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setRotateZ = function setRotateZ(eulerAngle, transition, callback) {
this.rotate[2].set(eulerAngle, transition, callback);
this._finalRotate[2] = eulerAngle;
this._final = _buildFinal.call(this);
return this;
};
/**
* An optimized way of setting only the skew component of a Transform. Axes who's values are null will not be affected.
*
* @method setSkew
* @chainable
*
* @param skewAngles {Array} New skew state. Axes who's values are null will not be affected.
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setSkew = function setSkew(skewAngles, transition, callback) {
var this$1 = this;
var numberOfAxes = _countOfType(skewAngles, 'number');
var _callback = callback ? Utility_1.after(numberOfAxes, callback) : null;
for (var i=0; i<skewAngles.length; i+=1) {
if (typeof skewAngles[i] === 'number') {
this$1.skew[i].set(skewAngles[i], transition, _callback);
this$1._finalSkew[i] = skewAngles[i];
}
}
this._final = _buildFinal.call(this);
return this;
};
/**
* Skew only about the X axis of the skew component of a Transform.
*
* @method setSkewX
* @chainable
*
* @param skewAngle {Number} New skew state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setSkewX = function setSkewX(skewAngle, transition, callback) {
this.skew[0].set(skewAngle, transition, callback);
this._finalSkew[0] = skewAngle;
this._final = _buildFinal.call(this);
return this;
};
/**
* Skew only about the Y axis of the skew component of a Transform.
*
* @method setSkewY
* @chainable
*
* @param skewAngle {Number} New skew state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setSkewY = function setSkewY(skewAngle, transition, callback) {
this.skew[1].set(skewAngle, transition, callback);
this._finalSkew[1] = skewAngle;
this._final = _buildFinal.call(this);
return this;
};
/**
* Skew only about the Z axis of the skew component of a Transform.
*
* @method setSkewZ
* @chainable
*
* @param skewAngle {Number} New skew state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.setSkewZ = function setSkewZ(skewAngle, transition, callback) {
this.skew[2].set(skewAngle, transition, callback);
this._finalSkew[2] = skewAngle;
this._final = _buildFinal.call(this);
return this;
};
/**
* Setter for a TransitionableTransform with optional parameters to transition
* between Transforms. Animates all axes of all components.
*
* @method set
* @chainable
*
* @param transform {Array} New transform state
* @param [transition] {Object} Transition definition
* @param [callback] {Function} Callback
* @return {TransitionableTransform}
*/
TransitionableTransform.prototype.set = function set(transform, transition, callback) {
var this$1 = this;
var components = Transform_1.interpret(transform);
this._finalTranslate = components.translate;
this._finalRotate = components.rotate;
this._finalSkew = components.skew;
this._finalScale = components.scale;
this._final = transform;
var _callback = callback ? Utility_1.after(12, callback) : null;
for (var i=0; i<3; i+=1) {
this$1.translate[i].set(components.translate[i], transition, _callback);
this$1.rotate[i].set(components.rotate[i], transition, _callback);
this$1.skew[i].set(components.skew[i], transition, _callback);
this$1.scale[i].set(components.scale[i], transition, _callback);
}
return this;
};
/**
* Sets the default transition to use for transitioning betwen Transform states
*
* @method setDefaultTransition
*
* @param transition {Object} Transition definition
*/
TransitionableTransform.prototype.setDefaultTransition = function setDefaultTransition(transition) {
var this$1 = this;
for (var i=0; i<3; i+=1) {
this$1.translate[i].setDefault(transition);
this$1.rotate[i].setDefault(transition);
this$1.skew[i].setDefault(transition);
this$1.scale[i].setDefault(transition);
}
};
/**
* Getter. Returns the current state of the Transform
*
* @method get
*
* @return {Transform}
*/
TransitionableTransform.prototype.get = function get() {
if (this.isActive()) {
return _build.call(this);
}
else { return this._final; }
};
/**
* Get the destination state of the Transform
*
* @method getFinal
*
* @return Transform {Transform}
*/
TransitionableTransform.prototype.getFinal = function getFinal() {
return this._final;
};
/**
* Determine if the TransitionableTransform is currently transitioning
*
* @method isActive
*
* @return {Boolean}
*/
TransitionableTransform.prototype.isActive = function isActive() {
var this$1 = this;
var isActive = false;
for (var i=0; i<3; i+=1) {
if (
this$1.translate[i].isActive()
|| this$1.rotate[i].isActive()
|| this$1.skew[i].isActive()
|| this$1.scale[i].isActive()
) {
isActive = true; break;
}
}
return isActive;
};
/**
* Halts the transition
*
* @method halt
*/
TransitionableTransform.prototype.halt = function halt() {
var this$1 = this;
for (var i=0; i<3; i+=1) {
this$1.translate[i].halt();
this$1.rotate[i].halt();
this$1.skew[i].halt();
this$1.scale[i].halt();
this$1._finalTranslate[i] = this$1.translate[i].get();
this$1._finalRotate[i] = this$1.rotate[i].get();
this$1._finalSkew[i] = this$1.skew[i].get();
this$1._finalScale[i] = this$1.scale[i].get();
}
this._final = this.get();
return this;
};
var TransitionableTransform_1 = TransitionableTransform;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/* TODO: remove these dependencies when deprecation complete */
/**
*
* A collection of visual changes to be
* applied to another renderable component. This collection includes a
* transform matrix, an opacity constant, a size, an origin specifier.
* Modifier objects can be added to any RenderNode or object
* capable of displaying renderables. The Modifier's children and descendants
* are transformed by the amounts specified in the Modifier's properties.
*
* @class Modifier
* @constructor
* @param {Object} [options] overrides of default options
* @param {Transform} [options.transform] affine transformation matrix
* @param {Number} [options.opacity]
* @param {Array.Number} [options.origin] origin adjustment
* @param {Array.Number} [options.size] size to apply to descendants
*/
function Modifier(options) {
this._transformGetter = null;
this._opacityGetter = null;
this._originGetter = null;
this._alignGetter = null;
this._sizeGetter = null;
this._proportionGetter = null;
/* TODO: remove this when deprecation complete */
this._legacyStates = {};
this._output = {
transform: Transform_1.identity,
opacity: 1,
origin: null,
align: null,
size: null,
proportions: null,
target: null
};
if (options) {
if (options.transform) { this.transformFrom(options.transform); }
if (options.opacity !== undefined) { this.opacityFrom(options.opacity); }
if (options.origin) { this.originFrom(options.origin); }
if (options.align) { this.alignFrom(options.align); }
if (options.size) { this.sizeFrom(options.size); }
if (options.proportions) { this.proportionsFrom(options.proportions); }
}
}
/**
* Function, object, or static transform matrix which provides the transform.
* This is evaluated on every tick of the engine.
*
* @method transformFrom
*
* @param {Object} transform transform provider object
* @return {Modifier} this
*/
Modifier.prototype.transformFrom = function transformFrom(transform) {
if (transform instanceof Function) { this._transformGetter = transform; }
else if (transform instanceof Object && transform.get) { this._transformGetter = transform.get.bind(transform); }
else {
this._transformGetter = null;
this._output.transform = transform;
}
return this;
};
/**
* Set function, object, or number to provide opacity, in range [0,1].
*
* @method opacityFrom
*
* @param {Object} opacity provider object
* @return {Modifier} this
*/
Modifier.prototype.opacityFrom = function opacityFrom(opacity) {
if (opacity instanceof Function) { this._opacityGetter = opacity; }
else if (opacity instanceof Object && opacity.get) { this._opacityGetter = opacity.get.bind(opacity); }
else {
this._opacityGetter = null;
this._output.opacity = opacity;
}
return this;
};
/**
* Set function, object, or numerical array to provide origin, as [x,y],
* where x and y are in the range [0,1].
*
* @method originFrom
*
* @param {Object} origin provider object
* @return {Modifier} this
*/
Modifier.prototype.originFrom = function originFrom(origin) {
if (origin instanceof Function) { this._originGetter = origin; }
else if (origin instanceof Object && origin.get) { this._originGetter = origin.get.bind(origin); }
else {
this._originGetter = null;
this._output.origin = origin;
}
return this;
};
/**
* Set function, object, or numerical array to provide align, as [x,y],
* where x and y are in the range [0,1].
*
* @method alignFrom
*
* @param {Object} align provider object
* @return {Modifier} this
*/
Modifier.prototype.alignFrom = function alignFrom(align) {
if (align instanceof Function) { this._alignGetter = align; }
else if (align instanceof Object && align.get) { this._alignGetter = align.get.bind(align); }
else {
this._alignGetter = null;
this._output.align = align;
}
return this;
};
/**
* Set function, object, or numerical array to provide size, as [width, height].
*
* @method sizeFrom
*
* @param {Object} size provider object
* @return {Modifier} this
*/
Modifier.prototype.sizeFrom = function sizeFrom(size) {
if (size instanceof Function) { this._sizeGetter = size; }
else if (size instanceof Object && size.get) { this._sizeGetter = size.get.bind(size); }
else {
this._sizeGetter = null;
this._output.size = size;
}
return this;
};
/**
* Set function, object, or numerical array to provide proportions, as [percent of width, percent of height].
*
* @method proportionsFrom
*
* @param {Object} proportions provider object
* @return {Modifier} this
*/
Modifier.prototype.proportionsFrom = function proportionsFrom(proportions) {
if (proportions instanceof Function) { this._proportionGetter = proportions; }
else if (proportions instanceof Object && proportions.get) { this._proportionGetter = proportions.get.bind(proportions); }
else {
this._proportionGetter = null;
this._output.proportions = proportions;
}
return this;
};
/**
* Deprecated: Prefer transformFrom with static Transform, or use a TransitionableTransform.
* @deprecated
* @method setTransform
*
* @param {Transform} transform Transform to transition to
* @param {Transitionable} transition Valid transitionable object
* @param {Function} callback callback to call after transition completes
* @return {Modifier} this
*/
Modifier.prototype.setTransform = function setTransform(transform, transition, callback) {
if (transition || this._legacyStates.transform) {
if (!this._legacyStates.transform) {
this._legacyStates.transform = new TransitionableTransform_1(this._output.transform);
}
if (!this._transformGetter) { this.transformFrom(this._legacyStates.transform); }
this._legacyStates.transform.set(transform, transition, callback);
return this;
}
else { return this.transformFrom(transform); }
};
/**
* Deprecated: Prefer opacityFrom with static opacity array, or use a Transitionable with that opacity.
* @deprecated
* @method setOpacity
*
* @param {Number} opacity Opacity value to transition to.
* @param {Transitionable} transition Valid transitionable object
* @param {Function} callback callback to call after transition completes
* @return {Modifier} this
*/
Modifier.prototype.setOpacity = function setOpacity(opacity, transition, callback) {
if (transition || this._legacyStates.opacity) {
if (!this._legacyStates.opacity) {
this._legacyStates.opacity = new Transitionable_1(this._output.opacity);
}
if (!this._opacityGetter) { this.opacityFrom(this._legacyStates.opacity); }
return this._legacyStates.opacity.set(opacity, transition, callback);
}
else { return this.opacityFrom(opacity); }
};
/**
* Deprecated: Prefer originFrom with static origin array, or use a Transitionable with that origin.
* @deprecated
* @method setOrigin
*
* @param {Array.Number} origin two element array with values between 0 and 1.
* @param {Transitionable} transition Valid transitionable object
* @param {Function} callback callback to call after transition completes
* @return {Modifier} this
*/
Modifier.prototype.setOrigin = function setOrigin(origin, transition, callback) {
/* TODO: remove this if statement when deprecation complete */
if (transition || this._legacyStates.origin) {
if (!this._legacyStates.origin) {
this._legacyStates.origin = new Transitionable_1(this._output.origin || [0, 0]);
}
if (!this._originGetter) { this.originFrom(this._legacyStates.origin); }
this._legacyStates.origin.set(origin, transition, callback);
return this;
}
else { return this.originFrom(origin); }
};
/**
* Deprecated: Prefer alignFrom with static align array, or use a Transitionable with that align.
* @deprecated
* @method setAlign
*
* @param {Array.Number} align two element array with values between 0 and 1.
* @param {Transitionable} transition Valid transitionable object
* @param {Function} callback callback to call after transition completes
* @return {Modifier} this
*/
Modifier.prototype.setAlign = function setAlign(align, transition, callback) {
/* TODO: remove this if statement when deprecation complete */
if (transition || this._legacyStates.align) {
if (!this._legacyStates.align) {
this._legacyStates.align = new Transitionable_1(this._output.align || [0, 0]);
}
if (!this._alignGetter) { this.alignFrom(this._legacyStates.align); }
this._legacyStates.align.set(align, transition, callback);
return this;
}
else { return this.alignFrom(align); }
};
/**
* Deprecated: Prefer sizeFrom with static origin array, or use a Transitionable with that size.
* @deprecated
* @method setSize
* @param {Array.Number} size two element array of [width, height]
* @param {Transitionable} transition Valid transitionable object
* @param {Function} callback callback to call after transition completes
* @return {Modifier} this
*/
Modifier.prototype.setSize = function setSize(size, transition, callback) {
if (size && (transition || this._legacyStates.size)) {
if (!this._legacyStates.size) {
this._legacyStates.size = new Transitionable_1(this._output.size || [0, 0]);
}
if (!this._sizeGetter) { this.sizeFrom(this._legacyStates.size); }
this._legacyStates.size.set(size, transition, callback);
return this;
}
else { return this.sizeFrom(size); }
};
/**
* Deprecated: Prefer proportionsFrom with static origin array, or use a Transitionable with those proportions.
* @deprecated
* @method setProportions
* @param {Array.Number} proportions two element array of [percent of width, percent of height]
* @param {Transitionable} transition Valid transitionable object
* @param {Function} callback callback to call after transition completes
* @return {Modifier} this
*/
Modifier.prototype.setProportions = function setProportions(proportions, transition, callback) {
if (proportions && (transition || this._legacyStates.proportions)) {
if (!this._legacyStates.proportions) {
this._legacyStates.proportions = new Transitionable_1(this._output.proportions || [0, 0]);
}
if (!this._proportionGetter) { this.proportionsFrom(this._legacyStates.proportions); }
this._legacyStates.proportions.set(proportions, transition, callback);
return this;
}
else { return this.proportionsFrom(proportions); }
};
/**
* Deprecated: Prefer to stop transform in your provider object.
* @deprecated
* @method halt
*/
Modifier.prototype.halt = function halt() {
if (this._legacyStates.transform) { this._legacyStates.transform.halt(); }
if (this._legacyStates.opacity) { this._legacyStates.opacity.halt(); }
if (this._legacyStates.origin) { this._legacyStates.origin.halt(); }
if (this._legacyStates.align) { this._legacyStates.align.halt(); }
if (this._legacyStates.size) { this._legacyStates.size.halt(); }
if (this._legacyStates.proportions) { this._legacyStates.proportions.halt(); }
this._transformGetter = null;
this._opacityGetter = null;
this._originGetter = null;
this._alignGetter = null;
this._sizeGetter = null;
this._proportionGetter = null;
};
/**
* Deprecated: Prefer to use your provided transform or output of your transform provider.
* @deprecated
* @method getTransform
* @return {Object} transform provider object
*/
Modifier.prototype.getTransform = function getTransform() {
return this._transformGetter();
};
/**
* Deprecated: Prefer to determine the end state of your transform from your transform provider
* @deprecated
* @method getFinalTransform
* @return {Transform} transform matrix
*/
Modifier.prototype.getFinalTransform = function getFinalTransform() {
return this._legacyStates.transform ? this._legacyStates.transform.getFinal() : this._output.transform;
};
/**
* Deprecated: Prefer to use your provided opacity or output of your opacity provider.
* @deprecated
* @method getOpacity
* @return {Object} opacity provider object
*/
Modifier.prototype.getOpacity = function getOpacity() {
return this._opacityGetter();
};
/**
* Deprecated: Prefer to use your provided origin or output of your origin provider.
* @deprecated
* @method getOrigin
* @return {Object} origin provider object
*/
Modifier.prototype.getOrigin = function getOrigin() {
return this._originGetter();
};
/**
* Deprecated: Prefer to use your provided align or output of your align provider.
* @deprecated
* @method getAlign
* @return {Object} align provider object
*/
Modifier.prototype.getAlign = function getAlign() {
return this._alignGetter();
};
/**
* Deprecated: Prefer to use your provided size or output of your size provider.
* @deprecated
* @method getSize
* @return {Object} size provider object
*/
Modifier.prototype.getSize = function getSize() {
return this._sizeGetter ? this._sizeGetter() : this._output.size;
};
/**
* Deprecated: Prefer to use your provided proportions or output of your proportions provider.
* @deprecated
* @method getProportions
* @return {Object} proportions provider object
*/
Modifier.prototype.getProportions = function getProportions() {
return this._proportionGetter ? this._proportionGetter() : this._output.proportions;
};
// call providers on tick to receive render spec elements to apply
function _update() {
if (this._transformGetter) { this._output.transform = this._transformGetter(); }
if (this._opacityGetter) { this._output.opacity = this._opacityGetter(); }
if (this._originGetter) { this._output.origin = this._originGetter(); }
if (this._alignGetter) { this._output.align = this._alignGetter(); }
if (this._sizeGetter) { this._output.size = this._sizeGetter(); }
if (this._proportionGetter) { this._output.proportions = this._proportionGetter(); }
}
/**
* Return render spec for this Modifier, applying to the provided
* target component. This is similar to render() for Surfaces.
*
* @private
* @method modify
*
* @param {Object} target (already rendered) render spec to
* which to apply the transform.
* @return {Object} render spec for this Modifier, including the
* provided target
*/
Modifier.prototype.modify = function modify(target) {
_update.call(this);
this._output.target = target;
return this._output;
};
var Modifier_1 = Modifier;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* A singleton that maintains a global registry of Surfaces.
* Private.
*
* @private
* @static
* @class Entity
*/
var entities = [];
/**
* Get entity from global index.
*
* @private
* @method get
* @param {Number} id entity registration id
* @return {Surface} entity in the global index
*/
function get(id) {
return entities[id];
}
/**
* Overwrite entity in the global index
*
* @private
* @method set
* @param {Number} id entity registration id
* @param {Surface} entity to add to the global index
*/
function set(id, entity) {
entities[id] = entity;
}
/**
* Add entity to global index
*
* @private
* @method register
* @param {Surface} entity to add to global index
* @return {Number} new id
*/
function register(entity) {
var id = entities.length;
set(id, entity);
return id;
}
/**
* Remove entity from global index
*
* @private
* @method unregister
* @param {Number} id entity registration id
*/
function unregister(id) {
set(id, null);
}
var Entity = {
register: register,
unregister: unregister,
get: get,
set: set
};
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
*
* This object translates the rendering instructions ("render specs")
* that renderable components generate into document update
* instructions ("update specs"). Private.
*
* @private
* @class SpecParser
* @constructor
*/
function SpecParser() {
this.result = {};
}
SpecParser._instance = new SpecParser();
/**
* Convert a render spec coming from the context's render chain to an
* update spec for the update chain. This is the only major entry point
* for a consumer of this class.
*
* @method parse
* @static
* @private
*
* @param {renderSpec} spec input render spec
* @param {Object} context context to do the parse in
* @return {Object} the resulting update spec (if no callback
* specified, else none)
*/
SpecParser.parse = function parse(spec, context) {
return SpecParser._instance.parse(spec, context);
};
/**
* Convert a renderSpec coming from the context's render chain to an update
* spec for the update chain. This is the only major entrypoint for a
* consumer of this class.
*
* @method parse
*
* @private
* @param {renderSpec} spec input render spec
* @param {Context} context
* @return {updateSpec} the resulting update spec
*/
SpecParser.prototype.parse = function parse(spec, context) {
this.reset();
this._parseSpec(spec, context, Transform_1.identity);
return this.result;
};
/**
* Prepare SpecParser for re-use (or first use) by setting internal state
* to blank.
*
* @private
* @method reset
*/
SpecParser.prototype.reset = function reset() {
this.result = {};
};
// Multiply matrix M by vector v
function _vecInContext(v, m) {
return [
v[0] * m[0] + v[1] * m[4] + v[2] * m[8],
v[0] * m[1] + v[1] * m[5] + v[2] * m[9],
v[0] * m[2] + v[1] * m[6] + v[2] * m[10]
];
}
var _zeroZero = [0, 0];
// From the provided renderSpec tree, recursively compose opacities,
// origins, transforms, and sizes corresponding to each surface id from
// the provided renderSpec tree structure. On completion, those
// properties of 'this' object should be ready to use to build an
// updateSpec.
SpecParser.prototype._parseSpec = function _parseSpec(spec, parentContext, sizeContext) {
var this$1 = this;
var id;
var target;
var transform;
var opacity;
var origin;
var align;
var size;
if (typeof spec === 'number') {
id = spec;
transform = parentContext.transform;
align = parentContext.align || _zeroZero;
if (parentContext.size && align && (align[0] || align[1])) {
var alignAdjust = [align[0] * parentContext.size[0], align[1] * parentContext.size[1], 0];
transform = Transform_1.thenMove(transform, _vecInContext(alignAdjust, sizeContext));
}
this.result[id] = {
transform: transform,
opacity: parentContext.opacity,
origin: parentContext.origin || _zeroZero,
align: parentContext.align || _zeroZero,
size: parentContext.size
};
}
else if (!spec) { // placed here so 0 will be cached earlier
return;
}
else if (spec instanceof Array) {
for (var i = 0; i < spec.length; i++) {
this$1._parseSpec(spec[i], parentContext, sizeContext);
}
}
else {
target = spec.target;
transform = parentContext.transform;
opacity = parentContext.opacity;
origin = parentContext.origin;
align = parentContext.align;
size = parentContext.size;
var nextSizeContext = sizeContext;
if (spec.opacity !== undefined) { opacity = parentContext.opacity * spec.opacity; }
if (spec.transform) { transform = Transform_1.multiply(parentContext.transform, spec.transform); }
if (spec.origin) {
origin = spec.origin;
nextSizeContext = parentContext.transform;
}
if (spec.align) { align = spec.align; }
if (spec.size || spec.proportions) {
var parentSize = size;
size = [size[0], size[1]];
if (spec.size) {
if (spec.size[0] !== undefined) { size[0] = spec.size[0]; }
if (spec.size[1] !== undefined) { size[1] = spec.size[1]; }
}
if (spec.proportions) {
if (spec.proportions[0] !== undefined) { size[0] = size[0] * spec.proportions[0]; }
if (spec.proportions[1] !== undefined) { size[1] = size[1] * spec.proportions[1]; }
}
if (parentSize) {
if (align && (align[0] || align[1])) { transform = Transform_1.thenMove(transform, _vecInContext([align[0] * parentSize[0], align[1] * parentSize[1], 0], sizeContext)); }
if (origin && (origin[0] || origin[1])) { transform = Transform_1.moveThen([-origin[0] * size[0], -origin[1] * size[1], 0], transform); }
}
nextSizeContext = parentContext.transform;
origin = null;
align = null;
}
this._parseSpec(target, {
transform: transform,
opacity: opacity,
origin: origin,
align: align,
size: size
}, nextSizeContext);
}
};
var SpecParser_1 = SpecParser;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* A wrapper for inserting a renderable component (like a Modifer or
* Surface) into the render tree.
*
* @class RenderNode
* @constructor
*
* @param {Object} object Target renderable component
*/
function RenderNode(object) {
this._object = null;
this._child = null;
this._hasMultipleChildren = false;
this._isRenderable = false;
this._isModifier = false;
this._resultCache = {};
this._prevResults = {};
this._childResult = null;
if (object) { this.set(object); }
}
/**
* Append a renderable to the list of this node's children.
* This produces a new RenderNode in the tree.
* Note: Does not double-wrap if child is a RenderNode already.
*
* @method add
* @param {Object} child renderable object
* @return {RenderNode} new render node wrapping child
*/
RenderNode.prototype.add = function add(child) {
var childNode = (child instanceof RenderNode) ? child : new RenderNode(child);
if (this._child instanceof Array) { this._child.push(childNode); }
else if (this._child) {
this._child = [this._child, childNode];
this._hasMultipleChildren = true;
this._childResult = []; // to be used later
}
else { this._child = childNode; }
return childNode;
};
/**
* Return the single wrapped object. Returns null if this node has multiple child nodes.
*
* @method get
*
* @return {Ojbect} contained renderable object
*/
RenderNode.prototype.get = function get() {
return this._object || (this._hasMultipleChildren ? null : (this._child ? this._child.get() : null));
};
/**
* Overwrite the list of children to contain the single provided object
*
* @method set
* @param {Object} child renderable object
* @return {RenderNode} this render node, or child if it is a RenderNode
*/
RenderNode.prototype.set = function set(child) {
this._childResult = null;
this._hasMultipleChildren = false;
this._isRenderable = child.render ? true : false;
this._isModifier = child.modify ? true : false;
this._object = child;
this._child = null;
if (child instanceof RenderNode) { return child; }
else { return this; }
};
/**
* Get render size of contained object.
*
* @method getSize
* @return {Array.Number} size of this or size of single child.
*/
RenderNode.prototype.getSize = function getSize() {
var result = null;
var target = this.get();
if (target && target.getSize) { result = target.getSize(); }
if (!result && this._child && this._child.getSize) { result = this._child.getSize(); }
return result;
};
// apply results of rendering this subtree to the document
function _applyCommit(spec, context, cacheStorage) {
var result = SpecParser_1.parse(spec, context);
var keys = Object.keys(result);
for (var i = 0; i < keys.length; i++) {
var id = keys[i];
var childNode = Entity.get(id);
var commitParams = result[id];
commitParams.allocator = context.allocator;
var commitResult = childNode.commit(commitParams);
if (commitResult) { _applyCommit(commitResult, context, cacheStorage); }
else { cacheStorage[id] = commitParams; }
}
}
/**
* Commit the content change from this node to the document.
*
* @private
* @method commit
* @param {Context} context render context
*/
RenderNode.prototype.commit = function commit(context) {
var this$1 = this;
// free up some divs from the last loop
var prevKeys = Object.keys(this._prevResults);
for (var i = 0; i < prevKeys.length; i++) {
var id = prevKeys[i];
if (this$1._resultCache[id] === undefined) {
var object = Entity.get(id);
if (object.cleanup) { object.cleanup(context.allocator); }
}
}
this._prevResults = this._resultCache;
this._resultCache = {};
_applyCommit(this.render(), context, this._resultCache);
};
/**
* Generate a render spec from the contents of the wrapped component.
*
* @private
* @method render
*
* @return {Object} render specification for the component subtree
* only under this node.
*/
RenderNode.prototype.render = function render() {
if (this._isRenderable) { return this._object.render(); }
var result = null;
if (this._hasMultipleChildren) {
result = this._childResult;
var children = this._child;
for (var i = 0; i < children.length; i++) {
result[i] = children[i].render();
}
}
else if (this._child) { result = this._child.render(); }
return this._isModifier ? this._object.modify(result) : result;
};
var RenderNode_1 = RenderNode;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* EventEmitter represents a channel for events.
*
* @class EventEmitter
* @constructor
*/
function EventEmitter() {
this.listeners = {};
this._owner = this;
}
/**
* Trigger an event, sending to all downstream handlers
* listening for provided 'type' key.
*
* @method emit
*
* @param {string} type event type key (for example, 'click')
* @param {Object} event event data
* @return {EventHandler} this
*/
EventEmitter.prototype.emit = function emit(type, event) {
var this$1 = this;
var handlers = this.listeners[type];
if (handlers) {
for (var i = 0; i < handlers.length; i++) {
handlers[i].call(this$1._owner, event);
}
}
return this;
};
/**
* Bind a callback function to an event type handled by this object.
*
* @method "on"
*
* @param {string} type event type key (for example, 'click')
* @param {function(string, Object)} handler callback
* @return {EventHandler} this
*/
EventEmitter.prototype.on = function on(type, handler) {
if (!(type in this.listeners)) { this.listeners[type] = []; }
var index = this.listeners[type].indexOf(handler);
if (index < 0) { this.listeners[type].push(handler); }
return this;
};
/**
* Alias for "on".
* @method addListener
*/
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
/**
* Unbind an event by type and handler.
* This undoes the work of "on".
*
* @method removeListener
*
* @param {string} type event type key (for example, 'click')
* @param {function} handler function object to remove
* @return {EventEmitter} this
*/
EventEmitter.prototype.removeListener = function removeListener(type, handler) {
var listener = this.listeners[type];
if (listener !== undefined) {
var index = listener.indexOf(handler);
if (index >= 0) { listener.splice(index, 1); }
}
return this;
};
/**
* Call event handlers with this set to owner.
*
* @method bindThis
*
* @param {Object} owner object this EventEmitter belongs to
*/
EventEmitter.prototype.bindThis = function bindThis(owner) {
this._owner = owner;
};
var EventEmitter_1 = EventEmitter;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* EventHandler forwards received events to a set of provided callback functions.
* It allows events to be captured, processed, and optionally piped through to other event handlers.
*
* @class EventHandler
* @extends EventEmitter
* @constructor
*/
function EventHandler() {
EventEmitter_1.apply(this, arguments);
this.downstream = []; // downstream event handlers
this.downstreamFn = []; // downstream functions
this.upstream = []; // upstream event handlers
this.upstreamListeners = {}; // upstream listeners
}
EventHandler.prototype = Object.create(EventEmitter_1.prototype);
EventHandler.prototype.constructor = EventHandler;
/**
* Assign an event handler to receive an object's input events.
*
* @method setInputHandler
* @static
*
* @param {Object} object object to mix trigger, subscribe, and unsubscribe functions into
* @param {EventHandler} handler assigned event handler
*/
EventHandler.setInputHandler = function setInputHandler(object, handler) {
object.trigger = handler.trigger.bind(handler);
if (handler.subscribe && handler.unsubscribe) {
object.subscribe = handler.subscribe.bind(handler);
object.unsubscribe = handler.unsubscribe.bind(handler);
}
};
/**
* Assign an event handler to receive an object's output events.
*
* @method setOutputHandler
* @static
*
* @param {Object} object object to mix pipe, unpipe, on, addListener, and removeListener functions into
* @param {EventHandler} handler assigned event handler
*/
EventHandler.setOutputHandler = function setOutputHandler(object, handler) {
if (handler instanceof EventHandler) { handler.bindThis(object); }
object.pipe = handler.pipe.bind(handler);
object.unpipe = handler.unpipe.bind(handler);
object.on = handler.on.bind(handler);
object.addListener = object.on;
object.removeListener = handler.removeListener.bind(handler);
};
/**
* Trigger an event, sending to all downstream handlers
* listening for provided 'type' key.
*
* @method emit
*
* @param {string} type event type key (for example, 'click')
* @param {Object} event event data
* @return {EventHandler} this
*/
EventHandler.prototype.emit = function emit(type, event) {
var this$1 = this;
EventEmitter_1.prototype.emit.apply(this, arguments);
var i = 0;
for (i = 0; i < this.downstream.length; i++) {
if (this$1.downstream[i].trigger) { this$1.downstream[i].trigger(type, event); }
}
for (i = 0; i < this.downstreamFn.length; i++) {
this$1.downstreamFn[i](type, event);
}
return this;
};
/**
* Alias for emit
* @method addListener
*/
EventHandler.prototype.trigger = EventHandler.prototype.emit;
/**
* Add event handler object to set of downstream handlers.
*
* @method pipe
*
* @param {EventHandler} target event handler target object
* @return {EventHandler} passed event handler
*/
EventHandler.prototype.pipe = function pipe(target) {
if (target.subscribe instanceof Function) { return target.subscribe(this); }
var downstreamCtx = (target instanceof Function) ? this.downstreamFn : this.downstream;
var index = downstreamCtx.indexOf(target);
if (index < 0) { downstreamCtx.push(target); }
if (target instanceof Function) { target('pipe', null); }
else if (target.trigger) { target.trigger('pipe', null); }
return target;
};
/**
* Remove handler object from set of downstream handlers.
* Undoes work of "pipe".
*
* @method unpipe
*
* @param {EventHandler} target target handler object
* @return {EventHandler} provided target
*/
EventHandler.prototype.unpipe = function unpipe(target) {
if (target.unsubscribe instanceof Function) { return target.unsubscribe(this); }
var downstreamCtx = (target instanceof Function) ? this.downstreamFn : this.downstream;
var index = downstreamCtx.indexOf(target);
if (index >= 0) {
downstreamCtx.splice(index, 1);
if (target instanceof Function) { target('unpipe', null); }
else if (target.trigger) { target.trigger('unpipe', null); }
return target;
}
else { return false; }
};
/**
* Bind a callback function to an event type handled by this object.
*
* @method "on"
*
* @param {string} type event type key (for example, 'click')
* @param {function(string, Object)} handler callback
* @return {EventHandler} this
*/
EventHandler.prototype.on = function on(type, handler) {
var this$1 = this;
EventEmitter_1.prototype.on.apply(this, arguments);
if (!(type in this.upstreamListeners)) {
var upstreamListener = this.trigger.bind(this, type);
this.upstreamListeners[type] = upstreamListener;
for (var i = 0; i < this.upstream.length; i++) {
this$1.upstream[i].on(type, upstreamListener);
}
}
return this;
};
/**
* Alias for "on"
* @method addListener
*/
EventHandler.prototype.addListener = EventHandler.prototype.on;
/**
* Listen for events from an upstream event handler.
*
* @method subscribe
*
* @param {EventEmitter} source source emitter object
* @return {EventHandler} this
*/
EventHandler.prototype.subscribe = function subscribe(source) {
var this$1 = this;
var index = this.upstream.indexOf(source);
if (index < 0) {
this.upstream.push(source);
for (var type in this$1.upstreamListeners) {
source.on(type, this$1.upstreamListeners[type]);
}
}
return this;
};
/**
* Stop listening to events from an upstream event handler.
*
* @method unsubscribe
*
* @param {EventEmitter} source source emitter object
* @return {EventHandler} this
*/
EventHandler.prototype.unsubscribe = function unsubscribe(source) {
var this$1 = this;
var index = this.upstream.indexOf(source);
if (index >= 0) {
this.upstream.splice(index, 1);
for (var type in this$1.upstreamListeners) {
source.removeListener(type, this$1.upstreamListeners[type]);
}
}
return this;
};
var EventHandler_1 = EventHandler;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* Internal helper object to Context that handles the process of
* creating and allocating DOM elements within a managed div.
* Private.
*
* @class ElementAllocator
* @constructor
* @private
* @param {Node} container document element in which Famo.us content will be inserted
*/
function ElementAllocator(container) {
if (!container) { container = document.createDocumentFragment(); }
this.container = container;
this.detachedNodes = {};
this.nodeCount = 0;
}
/**
* Move the document elements from their original container to a new one.
*
* @private
* @method migrate
*
* @param {Node} container document element to which Famo.us content will be migrated
*/
ElementAllocator.prototype.migrate = function migrate(container) {
var oldContainer = this.container;
if (container === oldContainer) { return; }
if (oldContainer instanceof DocumentFragment) {
container.appendChild(oldContainer);
}
else {
while (oldContainer.hasChildNodes()) {
container.appendChild(oldContainer.firstChild);
}
}
this.container = container;
};
/**
* Allocate an element of specified type from the pool.
*
* @private
* @method allocate
*
* @param {string} type type of element, e.g. 'div'
* @return {Node} allocated document element
*/
ElementAllocator.prototype.allocate = function allocate(type) {
type = type.toLowerCase();
if (!(type in this.detachedNodes)) { this.detachedNodes[type] = []; }
var nodeStore = this.detachedNodes[type];
var result;
if (nodeStore.length > 0) {
result = nodeStore.pop();
}
else {
result = document.createElement(type);
this.container.appendChild(result);
}
this.nodeCount++;
return result;
};
/**
* De-allocate an element of specified type to the pool.
*
* @private
* @method deallocate
*
* @param {Node} element document element to deallocate
*/
ElementAllocator.prototype.deallocate = function deallocate(element) {
var nodeType = element.nodeName.toLowerCase();
var nodeStore = this.detachedNodes[nodeType];
nodeStore.push(element);
this.nodeCount--;
};
/**
* Get count of total allocated nodes in the document.
*
* @private
* @method getNodeCount
*
* @return {Number} total node count
*/
ElementAllocator.prototype.getNodeCount = function getNodeCount() {
return this.nodeCount;
};
var ElementAllocator_1 = ElementAllocator;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var _zeroZero$1 = [0, 0];
var usePrefix = !('perspective' in document.documentElement.style);
function _getElementSize() {
var element = this.container;
return [element.clientWidth, element.clientHeight];
}
var _setPerspective = usePrefix ? function(element, perspective) {
element.style.webkitPerspective = perspective ? perspective.toFixed() + 'px' : '';
} : function(element, perspective) {
element.style.perspective = perspective ? perspective.toFixed() + 'px' : '';
};
/**
* The top-level container for a Famous-renderable piece of the document.
* It is directly updated by the process-wide Engine object, and manages one
* render tree root, which can contain other renderables.
*
* @class Context
* @constructor
* @private
* @param {Node} container Element in which content will be inserted
*/
function Context(container) {
this.container = container;
this._allocator = new ElementAllocator_1(container);
this._node = new RenderNode_1();
this._eventOutput = new EventHandler_1();
this._size = _getElementSize.call(this);
this._perspectiveState = new Transitionable_1(0);
this._perspective = undefined;
this._nodeContext = {
allocator: this._allocator,
transform: Transform_1.identity,
opacity: 1,
origin: _zeroZero$1,
align: _zeroZero$1,
size: this._size
};
this._eventOutput.on('resize', function() {
this.setSize(_getElementSize.call(this));
}.bind(this));
}
// Note: Unused
Context.prototype.getAllocator = function getAllocator() {
return this._allocator;
};
/**
* Add renderables to this Context's render tree.
*
* @method add
*
* @param {Object} obj renderable object
* @return {RenderNode} RenderNode wrapping this object, if not already a RenderNode
*/
Context.prototype.add = function add(obj) {
return this._node.add(obj);
};
/**
* Move this Context to another containing document element.
*
* @method migrate
*
* @param {Node} container Element to which content will be migrated
*/
Context.prototype.migrate = function migrate(container) {
if (container === this.container) { return; }
this.container = container;
this._allocator.migrate(container);
};
/**
* Gets viewport size for Context.
*
* @method getSize
*
* @return {Array.Number} viewport size as [width, height]
*/
Context.prototype.getSize = function getSize() {
return this._size;
};
/**
* Sets viewport size for Context.
*
* @method setSize
*
* @param {Array.Number} size [width, height]. If unspecified, use size of root document element.
*/
Context.prototype.setSize = function setSize(size) {
if (!size) { size = _getElementSize.call(this); }
this._size[0] = size[0];
this._size[1] = size[1];
};
/**
* Commit this Context's content changes to the document.
*
* @private
* @method update
* @param {Object} contextParameters engine commit specification
*/
Context.prototype.update = function update(contextParameters) {
if (contextParameters) {
if (contextParameters.transform) { this._nodeContext.transform = contextParameters.transform; }
if (contextParameters.opacity) { this._nodeContext.opacity = contextParameters.opacity; }
if (contextParameters.origin) { this._nodeContext.origin = contextParameters.origin; }
if (contextParameters.align) { this._nodeContext.align = contextParameters.align; }
if (contextParameters.size) { this._nodeContext.size = contextParameters.size; }
}
var perspective = this._perspectiveState.get();
if (perspective !== this._perspective) {
_setPerspective(this.container, perspective);
this._perspective = perspective;
}
this._node.commit(this._nodeContext);
};
/**
* Get current perspective of this context in pixels.
*
* @method getPerspective
* @return {Number} depth perspective in pixels
*/
Context.prototype.getPerspective = function getPerspective() {
return this._perspectiveState.get();
};
/**
* Set current perspective of this context in pixels.
*
* @method setPerspective
* @param {Number} perspective in pixels
* @param {Object} [transition] Transitionable object for applying the change
* @param {function(Object)} callback function called on completion of transition
*/
Context.prototype.setPerspective = function setPerspective(perspective, transition, callback) {
return this._perspectiveState.set(perspective, transition, callback);
};
/**
* Trigger an event, sending to all downstream handlers
* listening for provided 'type' key.
*
* @method emit
*
* @param {string} type event type key (for example, 'click')
* @param {Object} event event data
* @return {EventHandler} this
*/
Context.prototype.emit = function emit(type, event) {
return this._eventOutput.emit(type, event);
};
/**
* Bind a callback function to an event type handled by this object.
*
* @method "on"
*
* @param {string} type event type key (for example, 'click')
* @param {function(string, Object)} handler callback
* @return {EventHandler} this
*/
Context.prototype.on = function on(type, handler) {
return this._eventOutput.on(type, handler);
};
/**
* Unbind an event by type and handler.
* This undoes the work of "on".
*
* @method removeListener
*
* @param {string} type event type key (for example, 'click')
* @param {function} handler function object to remove
* @return {EventHandler} internal event handler object (for chaining)
*/
Context.prototype.removeListener = function removeListener(type, handler) {
return this._eventOutput.removeListener(type, handler);
};
/**
* Add event handler object to set of downstream handlers.
*
* @method pipe
*
* @param {EventHandler} target event handler target object
* @return {EventHandler} passed event handler
*/
Context.prototype.pipe = function pipe(target) {
return this._eventOutput.pipe(target);
};
/**
* Remove handler object from set of downstream handlers.
* Undoes work of "pipe".
*
* @method unpipe
*
* @param {EventHandler} target target handler object
* @return {EventHandler} provided target
*/
Context.prototype.unpipe = function unpipe(target) {
return this._eventOutput.unpipe(target);
};
var Context_1 = Context;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* A collection of methods for setting options which can be extended
* onto other classes.
*
*
* **** WARNING ****
* You can only pass through objects that will compile into valid JSON.
*
* Valid options:
* Strings,
* Arrays,
* Objects,
* Numbers,
* Nested Objects,
* Nested Arrays.
*
* This excludes:
* Document Fragments,
* Functions
* @class OptionsManager
* @constructor
* @param {Object} value options dictionary
*/
function OptionsManager(value) {
this._value = value;
this.eventOutput = null;
}
/**
* Create options manager from source dictionary with arguments overriden by patch dictionary.
*
* @static
* @method OptionsManager.patch
*
* @param {Object} source source arguments
* @param {...Object} data argument additions and overwrites
* @return {Object} source object
*/
OptionsManager.patch = function patchObject(source, data) {
var arguments$1 = arguments;
var manager = new OptionsManager(source);
for (var i = 1; i < arguments.length; i++) { manager.patch(arguments$1[i]); }
return source;
};
function _createEventOutput() {
this.eventOutput = new EventHandler_1();
this.eventOutput.bindThis(this);
EventHandler_1.setOutputHandler(this, this.eventOutput);
}
/**
* Create OptionsManager from source with arguments overriden by patches.
* Triggers 'change' event on this object's event handler if the state of
* the OptionsManager changes as a result.
*
* @method patch
*
* @param {...Object} arguments list of patch objects
* @return {OptionsManager} this
*/
OptionsManager.prototype.patch = function patch() {
var arguments$1 = arguments;
var this$1 = this;
var myState = this._value;
for (var i = 0; i < arguments.length; i++) {
var data = arguments$1[i];
for (var k in data) {
if ((k in myState) && (data[k] && data[k].constructor === Object) && (myState[k] && myState[k].constructor === Object)) {
if (!myState.hasOwnProperty(k)) { myState[k] = Object.create(myState[k]); }
this$1.key(k).patch(data[k]);
if (this$1.eventOutput) { this$1.eventOutput.emit('change', {id: k, value: this$1.key(k).value()}); }
}
else { this$1.set(k, data[k]); }
}
}
return this;
};
/**
* Alias for patch
*
* @method setOptions
*
*/
OptionsManager.prototype.setOptions = OptionsManager.prototype.patch;
/**
* Return OptionsManager based on sub-object retrieved by key
*
* @method key
*
* @param {string} identifier key
* @return {OptionsManager} new options manager with the value
*/
OptionsManager.prototype.key = function key(identifier) {
var result = new OptionsManager(this._value[identifier]);
if (!(result._value instanceof Object) || result._value instanceof Array) { result._value = {}; }
return result;
};
/**
* Look up value by key or get the full options hash
* @method get
*
* @param {string} key key
* @return {Object} associated object or full options hash
*/
OptionsManager.prototype.get = function get(key) {
return key ? this._value[key] : this._value;
};
/**
* Alias for get
* @method getOptions
*/
OptionsManager.prototype.getOptions = OptionsManager.prototype.get;
/**
* Set key to value. Outputs 'change' event if a value is overwritten.
*
* @method set
*
* @param {string} key key string
* @param {Object} value value object
* @return {OptionsManager} new options manager based on the value object
*/
OptionsManager.prototype.set = function set(key, value) {
var originalValue = this.get(key);
this._value[key] = value;
if (this.eventOutput && value !== originalValue) { this.eventOutput.emit('change', {id: key, value: value}); }
return this;
};
/**
* Bind a callback function to an event type handled by this object.
*
* @method "on"
*
* @param {string} type event type key (for example, 'change')
* @param {function(string, Object)} handler callback
* @return {EventHandler} this
*/
OptionsManager.prototype.on = function on() {
_createEventOutput.call(this);
return this.on.apply(this, arguments);
};
/**
* Unbind an event by type and handler.
* This undoes the work of "on".
*
* @method removeListener
*
* @param {string} type event type key (for example, 'change')
* @param {function} handler function object to remove
* @return {EventHandler} internal event handler object (for chaining)
*/
OptionsManager.prototype.removeListener = function removeListener() {
_createEventOutput.call(this);
return this.removeListener.apply(this, arguments);
};
/**
* Add event handler object to set of downstream handlers.
*
* @method pipe
*
* @param {EventHandler} target event handler target object
* @return {EventHandler} passed event handler
*/
OptionsManager.prototype.pipe = function pipe() {
_createEventOutput.call(this);
return this.pipe.apply(this, arguments);
};
/**
* Remove handler object from set of downstream handlers.
* Undoes work of "pipe"
*
* @method unpipe
*
* @param {EventHandler} target target handler object
* @return {EventHandler} provided target
*/
OptionsManager.prototype.unpipe = function unpipe() {
_createEventOutput.call(this);
return this.unpipe.apply(this, arguments);
};
var OptionsManager_1 = OptionsManager;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* The singleton object initiated upon process
* startup which manages all active Context instances, runs
* the render dispatch loop, and acts as a listener and dispatcher
* for events. All methods are therefore static.
*
* On static initialization, window.requestAnimationFrame is called with
* the event loop function.
*
* Note: Any window in which Engine runs will prevent default
* scrolling behavior on the 'touchmove' event.
*
* @static
* @class Engine
*/
var Engine = {};
var contexts = [];
var nextTickQueue = [];
var currentFrame = 0;
var deferQueue = [];
var lastTime = Date.now();
var frameTime;
var frameTimeLimit;
var loopEnabled = true;
var eventForwarders = {};
var eventHandler = new EventHandler_1();
var options = {
containerType: 'div',
containerClass: 'famous-container',
fpsCap: undefined,
runLoop: true,
appMode: true
};
var optionsManager = new OptionsManager_1(options);
/** @const */
var MAX_DEFER_FRAME_TIME = 10;
/**
* Inside requestAnimationFrame loop, step() is called, which:
* calculates current FPS (throttling loop if it is over limit set in setFPSCap),
* emits dataless 'prerender' event on start of loop,
* calls in order any one-shot functions registered by nextTick on last loop,
* calls Context.update on all Context objects registered,
* and emits dataless 'postrender' event on end of loop.
*
* @static
* @private
* @method step
*/
Engine.step = function step() {
var this$1 = this;
currentFrame++;
var currentTime = Date.now();
// skip frame if we're over our framerate cap
if (frameTimeLimit && currentTime - lastTime < frameTimeLimit) { return; }
var i = 0;
frameTime = currentTime - lastTime;
lastTime = currentTime;
eventHandler.emit('prerender');
// empty the queue
var numFunctions = nextTickQueue.length;
while (numFunctions--) { (nextTickQueue.shift())(currentFrame); }
// limit total execution time for deferrable functions
while (deferQueue.length && (Date.now() - currentTime) < MAX_DEFER_FRAME_TIME) {
deferQueue.shift().call(this$1);
}
for (i = 0; i < contexts.length; i++) { contexts[i].update(); }
eventHandler.emit('postrender');
};
// engage requestAnimationFrame
function loop() {
if (options.runLoop) {
Engine.step();
window.requestAnimationFrame(loop);
}
else { loopEnabled = false; }
}
window.requestAnimationFrame(loop);
//
// Upon main document window resize (unless on an "input" HTML element):
// scroll to the top left corner of the window,
// and for each managed Context: emit the 'resize' event and update its size.
// @param {Object=} event document event
//
function handleResize(event) {
for (var i = 0; i < contexts.length; i++) {
contexts[i].emit('resize');
}
eventHandler.emit('resize');
}
window.addEventListener('resize', handleResize, false);
handleResize();
/**
* Initialize famous for app mode
*
* @static
* @private
* @method initialize
*/
function initialize() {
// prevent scrolling via browser
window.addEventListener('touchmove', function(event) {
event.preventDefault();
}, true);
addRootClasses();
}
var initialized = false;
function addRootClasses() {
if (!document.body) {
Engine.nextTick(addRootClasses);
return;
}
document.body.classList.add('famous-root');
document.documentElement.classList.add('famous-root');
}
/**
* Add event handler object to set of downstream handlers.
*
* @method pipe
*
* @param {EventHandler} target event handler target object
* @return {EventHandler} passed event handler
*/
Engine.pipe = function pipe(target) {
if (target.subscribe instanceof Function) { return target.subscribe(Engine); }
else { return eventHandler.pipe(target); }
};
/**
* Remove handler object from set of downstream handlers.
* Undoes work of "pipe".
*
* @method unpipe
*
* @param {EventHandler} target target handler object
* @return {EventHandler} provided target
*/
Engine.unpipe = function unpipe(target) {
if (target.unsubscribe instanceof Function) { return target.unsubscribe(Engine); }
else { return eventHandler.unpipe(target); }
};
/**
* Bind a callback function to an event type handled by this object.
*
* @static
* @method "on"
*
* @param {string} type event type key (for example, 'click')
* @param {function(string, Object)} handler callback
* @return {EventHandler} this
*/
Engine.on = function on(type, handler) {
if (!(type in eventForwarders)) {
eventForwarders[type] = eventHandler.emit.bind(eventHandler, type);
addEngineListener(type, eventForwarders[type]);
}
return eventHandler.on(type, handler);
};
function addEngineListener(type, forwarder) {
if (!document.body) {
Engine.nextTick(addEventListener.bind(this, type, forwarder));
return;
}
document.body.addEventListener(type, forwarder);
}
/**
* Trigger an event, sending to all downstream handlers
* listening for provided 'type' key.
*
* @method emit
*
* @param {string} type event type key (for example, 'click')
* @param {Object} event event data
* @return {EventHandler} this
*/
Engine.emit = function emit(type, event) {
return eventHandler.emit(type, event);
};
/**
* Unbind an event by type and handler.
* This undoes the work of "on".
*
* @static
* @method removeListener
*
* @param {string} type event type key (for example, 'click')
* @param {function} handler function object to remove
* @return {EventHandler} internal event handler object (for chaining)
*/
Engine.removeListener = function removeListener(type, handler) {
return eventHandler.removeListener(type, handler);
};
/**
* Return the current calculated frames per second of the Engine.
*
* @static
* @method getFPS
*
* @return {Number} calculated fps
*/
Engine.getFPS = function getFPS() {
return 1000 / frameTime;
};
/**
* Set the maximum fps at which the system should run. If internal render
* loop is called at a greater frequency than this FPSCap, Engine will
* throttle render and update until this rate is achieved.
*
* @static
* @method setFPSCap
*
* @param {Number} fps maximum frames per second
*/
Engine.setFPSCap = function setFPSCap(fps) {
frameTimeLimit = Math.floor(1000 / fps);
};
/**
* Return engine options.
*
* @static
* @method getOptions
* @param {string} key
* @return {Object} engine options
*/
Engine.getOptions = function getOptions(key) {
return optionsManager.getOptions(key);
};
/**
* Set engine options
*
* @static
* @method setOptions
*
* @param {Object} [options] overrides of default options
* @param {Number} [options.fpsCap] maximum fps at which the system should run
* @param {boolean} [options.runLoop=true] whether the run loop should continue
* @param {string} [options.containerType="div"] type of container element. Defaults to 'div'.
* @param {string} [options.containerClass="famous-container"] type of container element. Defaults to 'famous-container'.
*/
Engine.setOptions = function setOptions(options) {
return optionsManager.setOptions.apply(optionsManager, arguments);
};
/**
* Creates a new Context for rendering and event handling with
* provided document element as top of each tree. This will be tracked by the
* process-wide Engine.
*
* @static
* @method createContext
*
* @param {Node} el will be top of Famo.us document element tree
* @return {Context} new Context within el
*/
Engine.createContext = function createContext(el) {
if (!initialized && options.appMode) { Engine.nextTick(initialize); }
var needMountContainer = false;
if (!el) {
el = document.createElement(options.containerType);
el.classList.add(options.containerClass);
needMountContainer = true;
}
var context = new Context_1(el);
Engine.registerContext(context);
if (needMountContainer) { mount(context, el); }
return context;
};
function mount(context, el) {
if (!document.body) {
Engine.nextTick(mount.bind(this, context, el));
return;
}
document.body.appendChild(el);
context.emit('resize');
}
/**
* Registers an existing context to be updated within the run loop.
*
* @static
* @method registerContext
*
* @param {Context} context Context to register
* @return {FamousContext} provided context
*/
Engine.registerContext = function registerContext(context) {
contexts.push(context);
return context;
};
/**
* Returns a list of all contexts.
*
* @static
* @method getContexts
* @return {Array} contexts that are updated on each tick
*/
Engine.getContexts = function getContexts() {
return contexts;
};
/**
* Removes a context from the run loop. Note: this does not do any
* cleanup.
*
* @static
* @method deregisterContext
*
* @param {Context} context Context to deregister
*/
Engine.deregisterContext = function deregisterContext(context) {
var i = contexts.indexOf(context);
if (i >= 0) { contexts.splice(i, 1); }
};
/**
* Queue a function to be executed on the next tick of the
* Engine.
*
* @static
* @method nextTick
*
* @param {function(Object)} fn function accepting window object
*/
Engine.nextTick = function nextTick(fn) {
nextTickQueue.push(fn);
};
/**
* Queue a function to be executed sometime soon, at a time that is
* unlikely to affect frame rate.
*
* @static
* @method defer
*
* @param {Function} fn
*/
Engine.defer = function defer(fn) {
deferQueue.push(fn);
};
optionsManager.on('change', function(data) {
if (data.id === 'fpsCap') { Engine.setFPSCap(data.value); }
else if (data.id === 'runLoop') {
// kick off the loop only if it was stopped
if (!loopEnabled && data.value) {
loopEnabled = true;
window.requestAnimationFrame(loop);
}
}
});
var Engine_1 = Engine;
/*
* @overview Utility functions used by infamous.
*
* LICENSE
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/**
* Creates a [famous/src/core/Context](#famous/src/core/Context) having the specified 3D perspective.
*
* @param {Number} perspective The integer amount of perspective to apply to the `Context`.
* @returns {module: famous/src/core/Context} The `Context` with the applied perspective.
*/
function contextWithPerspective(perspective) {
var context = Engine_1.createContext();
context.setPerspective(perspective);
return context;
}
function simpleExtend(object) {
var others = [], len = arguments.length - 1;
while ( len-- > 0 ) others[ len ] = arguments[ len + 1 ];
others.forEach(function (other) {
for (var prop in other) {
object[prop] = other[prop];
}
});
}
var utils = Object.freeze({
contextWithPerspective: contextWithPerspective,
simpleExtend: simpleExtend
});
"use strict";
// Polyfill for Function.name on browsers that do not support it (IE):
// See: http://stackoverflow.com/questions/6903762/function-name-not-supported-in-ie
if (!(function f() {}).name) {
Object.defineProperty(Function.prototype, "name", {
get: function () {
var name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1];
// For better performance only parse once, and then cache the
// result through a new accessor for repeated access.
Object.defineProperty(this, "name", { value: name });
return name;
}
});
}
/*
* LICENSE
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/**
* Molecules are the basic building blocks of all UI components. Molecules
* extend [famous/src/core/RenderNode](#famous/src/core/RenderNode), so they can be
* added to any `RenderNode` of a famo.us render tree, and by default they will
* also accept anything that a normal Famo.us `RenderNode` can accept via the
* `add` method. Classes that extend from `Molecule` might override
* `RenderNode.add` in order to accept things like arrays of renderables in
* stead of a single renderable.
*
* Molecules encapsulate the basic things you need for a component -- a
* [famous/src/transitions/TransitionableTransform](#famous/src/transitions/TransitionableTransform)
* for positioning things in space, and a [famous/src/core/EventHandler](#famous/src/core/EventHandler)
* for capturing user interaction -- exposing a unified API for working with these
* things. For now, [famous/src/core/Modifier](#famous/src/core/Modifier) is used as the interface
* for applying transforms and sizing, but this will change in Mixed Mode
* Famo.us.
*
* All components extend Molecule, but at the same time they can also use any
* number of Molecules internally to do nice things like create layouts and
* position multiple things in space.
*
* @class Molecule
* @extends {module: famous/src/core/RenderNode}
*/
var Molecule = function (_RenderNode) {
_inherits(Molecule, _RenderNode);
/**
* Creates a new `Molecule` and applies `initialOptions` to it's internal
* `famous/src/core/Modifier`. See [famous/src/core/Modifier](#famous/src/core/Modifier)
* for details on what options you can pass.
*
* Note: Mixed Mode Famo.us does away with Modifiers, so this API will
* change slightly, but the change will be in such a way that APIs of
* higher level classes won't change because of this. One of the biggest
* changes in Mixed Mode will be that `size` will be set only on a
* per-Surface basis as far as a render tree is concerned. So if you
* normally put multiple `Surface` instances into a `Modifier` that has a
* size, then instead you'll have to explicitly assign a `size` to each
* `Surface`. This is a good thing, and makes for a cleaner and easier to
* use render tree with a separation of concerns from classes that can
* handle boundaries and group sizing. `Molecule` might then be an example
* of such a class with it's own size API.
*
* @constructor
* @param {Object} initialOptions The options to initialize this Molecule's `Modifier` with.
*/
function Molecule(initialOptions) {
_classCallCheck(this, Molecule);
// "private" stuff. Not really, but regard it like so. For example, if
// you see something like obj._.someVariable then you're accessing
// internal stuff that wasn't designed to be accessed directly, and any
// problem you enounter with that is your own problem. :)
//
// TODO: Use a WeakMap to store these at some point.
var _this = _possibleConstructorReturn(this, (Molecule.__proto__ || _Object$getPrototypeOf(Molecule)).call(this));
_this._ = {
options: {}, // set and get with this.options
defaultOptions: {}
// Add default values for this Molecule
// TODO: Make default options static for the class.
};simpleExtend(_this._.defaultOptions, {
align: [0.5, 0.5],
origin: [0.5, 0.5],
transform: new TransitionableTransform_1(),
handler: new EventHandler_1()
});
// set the user's initial options. This automatically creates
// this.modifier, and adds it to this (don't forget, *this* is a
// RenderNode, so a Molecule can add things to itself).
//
// NOTE: this.options is a setter property. This statement applies all
// relevant properties to this.modifier.
_this.options = initialOptions;
return _this;
}
/**
* @property {Object} options The Molecule's options, which get applied to
* `this.modifier`. This may change with Mixed Mode. Setting this property
* overrides existing options. To extend existing options with new options,
* use `setOptions` instead. Unspecified options will be set to their default
* values.
*
* Note: Anytime `this.options` is assigned a new value, `this.modifier` is set
* to a new [famous/src/core/Modifier](#famous/src/core/Modifier).
*/
_createClass(Molecule, [{
key: 'setOptions',
/**
* Compounds `newOptions` into the existing options, similar to extending an
* object and overriding only the desired properties. To override all
* options with a set of new options, set `this.options` directly.
*
* An example of setting just a single option without erasing other options:
*
* ```js
* const myMolecule = new Molecule()
* myMolecule.setOptions({
* align: [0.2, 0.8]
* })
* ```
*
* @param {Object} newOptions An object containing the new options to apply to this `Molecule`.
*/
value: function setOptions(newOptions) {
var this$1 = this;
if (typeof newOptions == 'undefined' || newOptions.constructor.name != "Object") { newOptions = {}; }
for (var prop in newOptions) {
// Subject to change when Famo.us API changes.
if (Modifier_1.prototype['' + prop + 'From']) {
this$1.modifier['' + prop + 'From'](newOptions[prop]);
}
this$1._.options[prop] = newOptions[prop];
}
}
/**
* Sets all options back to their defaults.
*
* Note: Anytime this is called, `this.modifier` is set to a new
* [famous/src/core/Modifier](#famous/src/core/Modifier) having the default
* options.
*/
}, {
key: 'resetOptions',
value: function resetOptions() {
this.modifier = new Modifier_1();
this.set(this.modifier);
this.setOptions(this._.defaultOptions);
}
/**
* Forwards events from this Molecule's [famous/src/core/EventHandler](#famous/src/core/EventHandler) to the given
* target, which can be another `EventHandler` or `Molecule`.
*
* This method is equivalent to [famous/src/core/EventHandler.pipe](#famous/src/core/EventHandler.pipe),
* acting upon `this.handler`.
*
* TODO v0.1.0: Let this method accept a `Molecule`, then stop doing `pipe(this._.handler)` in other places
*/
}, {
key: 'pipe',
value: function pipe() {
var args = Array.prototype.splice.call(arguments, 0);
return this.options.handler.pipe.apply(this.options.handler, args);
}
/**
* Stops events from this Molecule's [famous/src/core/EventHandler](#famous/src/core/EventHandler)
* from being sent to the given target.
*
* This method is equivalent to [famous/src/core/EventHandler.unpipe](#famous/src/core/EventHandler.unpipe),
* acting upon `this.handler`.
*
* TODO v0.1.0: Let this method accept a `Molecule`, then stop doing `pipe(this.options.handler)` in other places
*/
}, {
key: 'unpipe',
value: function unpipe() {
var args = Array.prototype.splice.call(arguments, 0);
return this.options.handler.unpipe.apply(this.options.handler, args);
}
/**
* Register an event handler for the specified event.
* See [famous/src/core/EventHandler.on](#famous/src/core/EventHandler.on).
*/
}, {
key: 'on',
value: function on() {
var args = Array.prototype.splice.call(arguments, 0);
return this.options.handler.on.apply(this.options.handler, args);
}
/**
* Unregister an event handler for the specified event.
* See [famous/src/core/EventHandler.off](#famous/src/core/EventHandler.off).
*/
}, {
key: 'off',
value: function off() {
var args = Array.prototype.splice.call(arguments, 0);
return this.options.handler.on.apply(this.options.handler, args);
}
}, {
key: 'options',
set: function (newOptions) {
this.resetOptions();
this.setOptions(newOptions);
},
get: function () {
return this._.options;
}
/**
* @property {module: famous/src/transitions/TransitionableTransform} transform
* The transform of this `Molecule`. The default is a
* [famous/src/transitions/TransitionableTransform](#famous/src/transitions/TransitionableTransform).
* Setting this property automatically puts the new transform into effect.
* See [famous/src/core/Modifier.transformFrom](#famous/src/core/Modifier.transformFrom).
*/
}, {
key: 'transform',
set: function (newTransform) {
this.setOptions({ transform: newTransform });
},
get: function () {
return this.options.transform;
}
}]);
return Molecule;
}(RenderNode_1);
var forLength_1 = createCommonjsModule(function (module, exports) {
"use strict";
// loop for a given length, performing action each loop iteration. action receives the index of the loop.
exports.forLength = forLength;
function forLength(length, action) {
for (var i = 0; i < length; i += 1) {
action(i);
}
}
exports["default"] = forLength;
exports.__esModule = true;
});
var forLength = unwrapExports(forLength_1);
/*
* LICENSE
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/**
* A scenegraph tree with a variable number of leaf node Modifiers (the grid
* cells) that are arranged in a grid. Add any [famous/src/core/RenderNode](#famous/src/core/RenderNode)-compatible
* item to each leafnode of the grid.
*
* TODO: Use Molecule instead of Modifier for the grid cells.
* TODO: Add an options parameter, that the Molecule constructor will handle.
*
* @class Grid
* @extends Molecule
*/
var Grid = function (_Molecule) {
_inherits(Grid, _Molecule);
/**
* Creates a new Grid having the specified number of columns, number of rows,
* and famo.us-style size.
*
* @constructor
* @param {Number} columns The integer number of columns.
* @param {Number} rows The integer number of rows.
* @param {Array} size A famo.us-style width/height size array.
*/
function Grid(columns, rows, size) {
_classCallCheck(this, Grid);
var _this = _possibleConstructorReturn(this, (Grid.__proto__ || _Object$getPrototypeOf(Grid)).call(this, { size: size }));
_this.columns = columns;
_this.rows = rows;
_this.cellNodes = [];
if (typeof _this.options.size === 'undefined') {
_this.setOptions({ size: [undefined, undefined] });
}
forLength(_this.columns * _this.rows, _this._createGridCell.bind(_this));
return _this;
}
/**
* Creates a grid cell at the given index.
*
* @private
* @param {Number} index The integer index of the grid cell.
*/
_createClass(Grid, [{
key: '_createGridCell',
value: function _createGridCell(index) {
var column = index % this.columns;
var row = Math.floor(index / this.columns);
var cellSize = null;
if (typeof this.options.size[0] != 'undefined' && typeof this.options.size[1] != 'undefined') {
cellSize = [];
cellSize[0] = this.options.size[0] / this.columns;
cellSize[1] = this.options.size[1] / this.rows;
}
var mod = new Modifier_1({
align: [0, 0],
origin: [0, 0],
size: cellSize ? [cellSize[0], cellSize[1]] : [undefined, undefined],
transform: Transform_1.translate(column * cellSize[0], row * cellSize[1], 0)
});
var mod2 = new Modifier_1({
//transform: Transform.rotateY(Math.PI/10),
align: [0.5, 0.5],
origin: [0.5, 0.5]
});
// FIXME: ^^^ Why do I need an extra Modifier to align stuff in the middle of the grid cells?????
this.cellNodes.push(this.add(mod).add(mod2));
}
/**
* Sets the items to be layed out in the grid.
*
* @param {Array} children An array of [famous/src/core/RenderNode](#famous/src/core/RenderNode)-compatible items.
*/
}, {
key: 'setChildren',
value: function setChildren(children) {
forLength(this.columns * this.rows, function (index) {
//this.cellNodes[index].set(null); // TODO: how do we erase previous children?
this.cellNodes[index].add(children[index]);
}.bind(this));
return this;
}
}]);
return Grid;
}(Molecule);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var usePrefix$1 = !('transform' in document.documentElement.style);
var devicePixelRatio = window.devicePixelRatio || 1;
/**
* A base class for viewable content and event
* targets inside a Famo.us application, containing a renderable document
* fragment. Like an HTML div, it can accept internal markup,
* properties, classes, and handle events.
*
* @class ElementOutput
* @constructor
*
* @param {Node} element document parent of this container
*/
function ElementOutput(element) {
this._matrix = null;
this._opacity = 1;
this._origin = null;
this._size = null;
this._eventOutput = new EventHandler_1();
this._eventOutput.bindThis(this);
/** @ignore */
this.eventForwarder = function eventForwarder(event) {
this._eventOutput.emit(event.type, event);
}.bind(this);
this.id = Entity.register(this);
this._element = null;
this._sizeDirty = false;
this._originDirty = false;
this._transformDirty = false;
this._invisible = false;
if (element) { this.attach(element); }
}
/**
* Bind a callback function to an event type handled by this object.
*
* @method "on"
*
* @param {string} type event type key (for example, 'click')
* @param {function(string, Object)} fn handler callback
* @return {EventHandler} this
*/
ElementOutput.prototype.on = function on(type, fn) {
if (this._element) { this._element.addEventListener(type, this.eventForwarder); }
this._eventOutput.on(type, fn);
};
/**
* Unbind an event by type and handler.
* This undoes the work of "on"
*
* @method removeListener
* @param {string} type event type key (for example, 'click')
* @param {function(string, Object)} fn handler
*/
ElementOutput.prototype.removeListener = function removeListener(type, fn) {
this._eventOutput.removeListener(type, fn);
};
/**
* Trigger an event, sending to all downstream handlers
* listening for provided 'type' key.
*
* @method emit
*
* @param {string} type event type key (for example, 'click')
* @param {Object} [event] event data
* @return {EventHandler} this
*/
ElementOutput.prototype.emit = function emit(type, event) {
if (event && !event.origin) { event.origin = this; }
var handled = this._eventOutput.emit(type, event);
if (handled && event && event.stopPropagation) { event.stopPropagation(); }
return handled;
};
/**
* Add event handler object to set of downstream handlers.
*
* @method pipe
*
* @param {EventHandler} target event handler target object
* @return {EventHandler} passed event handler
*/
ElementOutput.prototype.pipe = function pipe(target) {
return this._eventOutput.pipe(target);
};
/**
* Remove handler object from set of downstream handlers.
* Undoes work of "pipe"
*
* @method unpipe
*
* @param {EventHandler} target target handler object
* @return {EventHandler} provided target
*/
ElementOutput.prototype.unpipe = function unpipe(target) {
return this._eventOutput.unpipe(target);
};
/**
* Return spec for this surface. Note that for a base surface, this is
* simply an id.
*
* @method render
* @private
* @return {Object} render spec for this surface (spec id)
*/
ElementOutput.prototype.render = function render() {
return this.id;
};
// Attach Famous event handling to document events emanating from target
// document element. This occurs just after attachment to the document.
// Calling this enables methods like #on and #pipe.
function _addEventListeners(target) {
var this$1 = this;
for (var i in this$1._eventOutput.listeners) {
target.addEventListener(i, this$1.eventForwarder);
}
}
// Detach Famous event handling from document events emanating from target
// document element. This occurs just before detach from the document.
function _removeEventListeners(target) {
var this$1 = this;
for (var i in this$1._eventOutput.listeners) {
target.removeEventListener(i, this$1.eventForwarder);
}
}
/**
* Return a Matrix's webkit css representation to be used with the
* CSS3 -webkit-transform style.
* Example: -webkit-transform: matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,716,243,0,1)
*
* @method _formatCSSTransform
* @private
* @param {FamousMatrix} m matrix
* @return {string} matrix3d CSS style representation of the transform
*/
function _formatCSSTransform(m) {
m[12] = Math.round(m[12] * devicePixelRatio) / devicePixelRatio;
m[13] = Math.round(m[13] * devicePixelRatio) / devicePixelRatio;
var result = 'matrix3d(';
for (var i = 0; i < 15; i++) {
result += (m[i] < 0.000001 && m[i] > -0.000001) ? '0,' : m[i] + ',';
}
result += m[15] + ')';
return result;
}
/**
* Directly apply given FamousMatrix to the document element as the
* appropriate webkit CSS style.
*
* @method setMatrix
*
* @static
* @private
* @param {Element} element document element
* @param {FamousMatrix} matrix
*/
var _setMatrix;
if (usePrefix$1) {
_setMatrix = function(element, matrix) {
element.style.webkitTransform = _formatCSSTransform(matrix);
};
}
else {
_setMatrix = function(element, matrix) {
element.style.transform = _formatCSSTransform(matrix);
};
}
// format origin as CSS percentage string
function _formatCSSOrigin(origin) {
return (100 * origin[0]) + '% ' + (100 * origin[1]) + '%';
}
// Directly apply given origin coordinates to the document element as the
// appropriate webkit CSS style.
var _setOrigin = usePrefix$1 ? function(element, origin) {
element.style.webkitTransformOrigin = _formatCSSOrigin(origin);
} : function(element, origin) {
element.style.transformOrigin = _formatCSSOrigin(origin);
};
// Shrink given document element until it is effectively invisible.
var _setInvisible = usePrefix$1 ? function(element) {
element.style.webkitTransform = 'scale3d(0.0001,0.0001,0.0001)';
element.style.opacity = 0;
} : function(element) {
element.style.transform = 'scale3d(0.0001,0.0001,0.0001)';
element.style.opacity = 0;
};
function _xyNotEquals$1(a, b) {
return (a && b) ? (a[0] !== b[0] || a[1] !== b[1]) : a !== b;
}
/**
* Apply changes from this component to the corresponding document element.
* This includes changes to classes, styles, size, content, opacity, origin,
* and matrix transforms.
*
* @private
* @method commit
* @param {Context} context commit context
*/
ElementOutput.prototype.commit = function commit(context) {
var target = this._element;
if (!target) { return; }
var matrix = context.transform;
var opacity = context.opacity;
var origin = context.origin;
if (!matrix && this._matrix) {
this._matrix = null;
this._opacity = 0;
_setInvisible(target);
return;
}
if (_xyNotEquals$1(this._origin, origin)) { this._originDirty = true; }
if (Transform_1.notEquals(this._matrix, matrix)) { this._transformDirty = true; }
if (this._invisible) {
this._invisible = false;
this._element.style.display = '';
}
if (this._opacity !== opacity) {
this._opacity = opacity;
target.style.opacity = (opacity >= 1) ? '0.999999' : opacity;
}
if (this._transformDirty || this._originDirty || this._sizeDirty) {
if (this._sizeDirty) { this._sizeDirty = false; }
if (this._originDirty) {
if (origin) {
if (!this._origin) { this._origin = [0, 0]; }
this._origin[0] = origin[0];
this._origin[1] = origin[1];
}
else { this._origin = null; }
_setOrigin(target, this._origin);
this._originDirty = false;
}
if (!matrix) { matrix = Transform_1.identity; }
this._matrix = matrix;
var aaMatrix = this._size ? Transform_1.thenMove(matrix, [-this._size[0]*origin[0], -this._size[1]*origin[1], 0]) : matrix;
_setMatrix(target, aaMatrix);
this._transformDirty = false;
}
};
ElementOutput.prototype.cleanup = function cleanup() {
if (this._element) {
this._invisible = true;
this._element.style.display = 'none';
}
};
/**
* Place the document element that this component manages into the document.
*
* @private
* @method attach
* @param {Node} target document parent of this container
*/
ElementOutput.prototype.attach = function attach(target) {
this._element = target;
_addEventListeners.call(this, target);
};
/**
* Remove any contained document content associated with this surface
* from the actual document.
*
* @private
* @method detach
*/
ElementOutput.prototype.detach = function detach() {
var target = this._element;
if (target) {
_removeEventListeners.call(this, target);
if (this._invisible) {
this._invisible = false;
this._element.style.display = '';
}
}
this._element = null;
return target;
};
var ElementOutput_1 = ElementOutput;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* A base class for viewable content and event
* targets inside a Famo.us application, containing a renderable document
* fragment. Like an HTML div, it can accept internal markup,
* properties, classes, and handle events.
*
* @class Surface
* @constructor
*
* @param {Object} [options] default option overrides
* @param {Array.Number} [options.size] [width, height] in pixels
* @param {Array.string} [options.classes] CSS classes to set on target div
* @param {Array} [options.properties] string dictionary of CSS properties to set on target div
* @param {Array} [options.attributes] string dictionary of HTML attributes to set on target div
* @param {string} [options.content] inner (HTML) content of surface
*/
function Surface(options) {
ElementOutput_1.call(this);
this.options = {};
this.properties = {};
this.attributes = {};
this.content = '';
this.classList = [];
this.size = null;
this._classesDirty = true;
this._stylesDirty = true;
this._attributesDirty = true;
this._sizeDirty = true;
this._contentDirty = true;
this._trueSizeCheck = true;
this._dirtyClasses = [];
if (options) { this.setOptions(options); }
this._currentTarget = null;
}
Surface.prototype = Object.create(ElementOutput_1.prototype);
Surface.prototype.constructor = Surface;
Surface.prototype.elementType = 'div';
Surface.prototype.elementClass = 'famous-surface';
/**
* Set HTML attributes on this Surface. Note that this will cause
* dirtying and thus re-rendering, even if values do not change.
*
* @method setAttributes
* @param {Object} attributes property dictionary of "key" => "value"
*/
Surface.prototype.setAttributes = function setAttributes(attributes) {
var this$1 = this;
for (var n in attributes) {
if (n === 'style') { throw new Error('Cannot set styles via "setAttributes" as it will break Famo.us. Use "setProperties" instead.'); }
this$1.attributes[n] = attributes[n];
}
this._attributesDirty = true;
};
/**
* Get HTML attributes on this Surface.
*
* @method getAttributes
*
* @return {Object} Dictionary of this Surface's attributes.
*/
Surface.prototype.getAttributes = function getAttributes() {
return this.attributes;
};
/**
* Set CSS-style properties on this Surface. Note that this will cause
* dirtying and thus re-rendering, even if values do not change.
*
* @method setProperties
* @chainable
* @param {Object} properties property dictionary of "key" => "value"
*/
Surface.prototype.setProperties = function setProperties(properties) {
var this$1 = this;
for (var n in properties) {
this$1.properties[n] = properties[n];
}
this._stylesDirty = true;
return this;
};
/**
* Get CSS-style properties on this Surface.
*
* @method getProperties
*
* @return {Object} Dictionary of this Surface's properties.
*/
Surface.prototype.getProperties = function getProperties() {
return this.properties;
};
/**
* Add CSS-style class to the list of classes on this Surface. Note
* this will map directly to the HTML property of the actual
* corresponding rendered <div>.
*
* @method addClass
* @chainable
* @param {string} className name of class to add
*/
Surface.prototype.addClass = function addClass(className) {
if (this.classList.indexOf(className) < 0) {
this.classList.push(className);
this._classesDirty = true;
}
return this;
};
/**
* Remove CSS-style class from the list of classes on this Surface.
* Note this will map directly to the HTML property of the actual
* corresponding rendered <div>.
*
* @method removeClass
* @chainable
* @param {string} className name of class to remove
*/
Surface.prototype.removeClass = function removeClass(className) {
var i = this.classList.indexOf(className);
if (i >= 0) {
this._dirtyClasses.push(this.classList.splice(i, 1)[0]);
this._classesDirty = true;
}
return this;
};
/**
* Toggle CSS-style class from the list of classes on this Surface.
* Note this will map directly to the HTML property of the actual
* corresponding rendered <div>.
*
* @method toggleClass
* @param {string} className name of class to toggle
*/
Surface.prototype.toggleClass = function toggleClass(className) {
var i = this.classList.indexOf(className);
if (i >= 0) {
this.removeClass(className);
} else {
this.addClass(className);
}
return this;
};
/**
* Reset class list to provided dictionary.
* @method setClasses
* @chainable
* @param {Array.string} classList
*/
Surface.prototype.setClasses = function setClasses(classList) {
var this$1 = this;
var i = 0;
var removal = [];
for (i = 0; i < this.classList.length; i++) {
if (classList.indexOf(this$1.classList[i]) < 0) { removal.push(this$1.classList[i]); }
}
for (i = 0; i < removal.length; i++) { this$1.removeClass(removal[i]); }
// duplicates are already checked by addClass()
for (i = 0; i < classList.length; i++) { this$1.addClass(classList[i]); }
return this;
};
/**
* Get array of CSS-style classes attached to this div.
*
* @method getClasslist
* @return {Array.string} array of class names
*/
Surface.prototype.getClassList = function getClassList() {
return this.classList;
};
/**
* Set or overwrite inner (HTML) content of this surface. Note that this
* causes a re-rendering if the content has changed.
*
* @method setContent
* @chainable
* @param {string|Document Fragment} content HTML content
*/
Surface.prototype.setContent = function setContent(content) {
if (this.content !== content) {
this.content = content;
this._contentDirty = true;
}
return this;
};
/**
* Return inner (HTML) content of this surface.
*
* @method getContent
*
* @return {string} inner (HTML) content
*/
Surface.prototype.getContent = function getContent() {
return this.content;
};
/**
* Set options for this surface
*
* @method setOptions
* @chainable
* @param {Object} [options] overrides for default options. See constructor.
*/
Surface.prototype.setOptions = function setOptions(options) {
if (options.size) { this.setSize(options.size); }
if (options.classes) { this.setClasses(options.classes); }
if (options.properties) { this.setProperties(options.properties); }
if (options.attributes) { this.setAttributes(options.attributes); }
if (options.content) { this.setContent(options.content); }
return this;
};
// Apply to document all changes from removeClass() since last setup().
function _cleanupClasses(target) {
var this$1 = this;
for (var i = 0; i < this._dirtyClasses.length; i++) { target.classList.remove(this$1._dirtyClasses[i]); }
this._dirtyClasses = [];
}
// Apply values of all Famous-managed styles to the document element.
// These will be deployed to the document on call to #setup().
function _applyStyles(target) {
var this$1 = this;
for (var n in this$1.properties) {
target.style[n] = this$1.properties[n];
}
}
// Clear all Famous-managed styles from the document element.
// These will be deployed to the document on call to #setup().
function _cleanupStyles(target) {
var this$1 = this;
for (var n in this$1.properties) {
target.style[n] = '';
}
}
// Apply values of all Famous-managed attributes to the document element.
// These will be deployed to the document on call to #setup().
function _applyAttributes(target) {
var this$1 = this;
for (var n in this$1.attributes) {
target.setAttribute(n, this$1.attributes[n]);
}
}
// Clear all Famous-managed attributes from the document element.
// These will be deployed to the document on call to #setup().
function _cleanupAttributes(target) {
var this$1 = this;
for (var n in this$1.attributes) {
target.removeAttribute(n);
}
}
function _xyNotEquals(a, b) {
return (a && b) ? (a[0] !== b[0] || a[1] !== b[1]) : a !== b;
}
/**
* One-time setup for an element to be ready for commits to document.
*
* @private
* @method setup
*
* @param {ElementAllocator} allocator document element pool for this context
*/
Surface.prototype.setup = function setup(allocator) {
var this$1 = this;
var target = allocator.allocate(this.elementType);
if (this.elementClass) {
if (this.elementClass instanceof Array) {
for (var i = 0; i < this.elementClass.length; i++) {
target.classList.add(this$1.elementClass[i]);
}
}
else {
target.classList.add(this.elementClass);
}
}
target.style.display = '';
this.attach(target);
this._opacity = null;
this._currentTarget = target;
this._stylesDirty = true;
this._classesDirty = true;
this._attributesDirty = true;
this._sizeDirty = true;
this._contentDirty = true;
this._originDirty = true;
this._transformDirty = true;
};
/**
* Apply changes from this component to the corresponding document element.
* This includes changes to classes, styles, size, content, opacity, origin,
* and matrix transforms.
*
* @private
* @method commit
* @param {Context} context commit context
*/
Surface.prototype.commit = function commit(context) {
if (!this._currentTarget) { this.setup(context.allocator); }
var target = this._currentTarget;
var size = context.size;
if (this._classesDirty) {
_cleanupClasses.call(this, target);
var classList = this.getClassList();
for (var i = 0; i < classList.length; i++) { target.classList.add(classList[i]); }
this._classesDirty = false;
this._trueSizeCheck = true;
}
if (this._stylesDirty) {
_applyStyles.call(this, target);
this._stylesDirty = false;
this._trueSizeCheck = true;
}
if (this._attributesDirty) {
_applyAttributes.call(this, target);
this._attributesDirty = false;
this._trueSizeCheck = true;
}
if (this.size) {
var origSize = context.size;
size = [this.size[0], this.size[1]];
if (size[0] === undefined) { size[0] = origSize[0]; }
if (size[1] === undefined) { size[1] = origSize[1]; }
if (size[0] === true || size[1] === true) {
if (size[0] === true){
if (this._trueSizeCheck || (this._size[0] === 0)) {
var width = target.offsetWidth;
if (this._size && this._size[0] !== width) {
this._size[0] = width;
this._sizeDirty = true;
}
size[0] = width;
} else {
if (this._size) { size[0] = this._size[0]; }
}
}
if (size[1] === true){
if (this._trueSizeCheck || (this._size[1] === 0)) {
var height = target.offsetHeight;
if (this._size && this._size[1] !== height) {
this._size[1] = height;
this._sizeDirty = true;
}
size[1] = height;
} else {
if (this._size) { size[1] = this._size[1]; }
}
}
this._trueSizeCheck = false;
}
}
if (_xyNotEquals(this._size, size)) {
if (!this._size) { this._size = [0, 0]; }
this._size[0] = size[0];
this._size[1] = size[1];
this._sizeDirty = true;
}
if (this._sizeDirty) {
if (this._size) {
target.style.width = (this.size && this.size[0] === true) ? '' : this._size[0] + 'px';
target.style.height = (this.size && this.size[1] === true) ? '' : this._size[1] + 'px';
}
this._eventOutput.emit('resize');
}
if (this._contentDirty) {
this.deploy(target);
this._eventOutput.emit('deploy');
this._contentDirty = false;
this._trueSizeCheck = true;
}
ElementOutput_1.prototype.commit.call(this, context);
};
/**
* Remove all Famous-relevant attributes from a document element.
* This is called by SurfaceManager's detach().
* This is in some sense the reverse of .deploy().
*
* @private
* @method cleanup
* @param {ElementAllocator} allocator
*/
Surface.prototype.cleanup = function cleanup(allocator) {
var this$1 = this;
var i = 0;
var target = this._currentTarget;
this._eventOutput.emit('recall');
this.recall(target);
target.style.display = 'none';
target.style.opacity = '';
target.style.width = '';
target.style.height = '';
_cleanupStyles.call(this, target);
_cleanupAttributes.call(this, target);
var classList = this.getClassList();
_cleanupClasses.call(this, target);
for (i = 0; i < classList.length; i++) { target.classList.remove(classList[i]); }
if (this.elementClass) {
if (this.elementClass instanceof Array) {
for (i = 0; i < this.elementClass.length; i++) {
target.classList.remove(this$1.elementClass[i]);
}
}
else {
target.classList.remove(this.elementClass);
}
}
this.detach(target);
this._currentTarget = null;
allocator.deallocate(target);
};
/**
* Place the document element that this component manages into the document.
*
* @private
* @method deploy
* @param {Node} target document parent of this container
*/
Surface.prototype.deploy = function deploy(target) {
var content = this.getContent();
if (content instanceof Node) {
while (target.hasChildNodes()) { target.removeChild(target.firstChild); }
target.appendChild(content);
}
else { target.innerHTML = content; }
};
/**
* Remove any contained document content associated with this surface
* from the actual document.
*
* @private
* @method recall
*/
Surface.prototype.recall = function recall(target) {
var df = document.createDocumentFragment();
while (target.hasChildNodes()) { df.appendChild(target.firstChild); }
this.setContent(df);
};
/**
* Get the x and y dimensions of the surface.
*
* @method getSize
* @return {Array.Number} [x,y] size of surface
*/
Surface.prototype.getSize = function getSize() {
return this._size ? this._size : this.size;
};
/**
* Set x and y dimensions of the surface.
*
* @method setSize
* @chainable
* @param {Array.Number} size as [width, height]
*/
Surface.prototype.setSize = function setSize(size) {
this.size = size ? [size[0], size[1]] : null;
this._sizeDirty = true;
return this;
};
var Surface_1 = Surface;
/*
* LICENSE
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/**
* Planes have the properties of [Molecules](#Molecule), plus they contain a
* [famous/src/core/Surface](#famous/src/core/Surface) so that they ultimately render
* onto the screen. A Surface's events are automatically piped to it's
* [famous/src/core/EventHandler](#famous/src/core/EventHandler), inherited from
* `Molecule`.
*
* @class Plane
* @extends Molecule
*/
var Plane = function (_Molecule) {
_inherits(Plane, _Molecule);
/**
* Creates a new `Plane`. Properties from the `initialOptions` parameter
* are applied to this Plane's [famous/src/core/Surface](#famous/src/core/Surface) as well as to
* to this Plane's [famous/src/core/Modifier](#famous/src/core/Modifier), hence the API of a Plane
* is currently the combination of the Famo.us `Modifier` and `Surface` APIs.
*
* @constructor
* @param {Object} initialOptions Options for the new Plane.
*/
function Plane(initialOptions) {
_classCallCheck(this, Plane);
var _this = _possibleConstructorReturn(this, (Plane.__proto__ || _Object$getPrototypeOf(Plane)).call(this, initialOptions));
_this.surface = new Surface_1(_this.options);
_this.add(_this.surface);
_this.surface.pipe(_this.options.handler);
return _this;
}
/**
* Get the content of this Plane's [famous/src/core/Surface](#famous/src/core/Surface).
* See [famous/src/core/Surface.getContent](#famous/src/core/Surface.getContent).
*/
_createClass(Plane, [{
key: 'getContent',
value: function getContent() {
var args = Array.prototype.splice.call(arguments, 0);
return this.surface.getContent.apply(this.surface, args);
}
/**
* Set the content of this Plane's [famous/src/core/Surface](#famous/src/core/Surface).
* See [famous/src/core/Surface.setContent](#famous/src/core/Surface.setContent).
*/
}, {
key: 'setContent',
value: function setContent() {
var args = Array.prototype.splice.call(arguments, 0);
return this.surface.setContent.apply(this.surface, args);
}
}]);
return Plane;
}(Molecule);
/*
* LICENSE
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/**
* A scenegraph tree who's two leaf nodes are [Plane](#Plane) instances facing
* opposite directions. For the purposes of these docs, in a brand new app with
* only a single `DoubleSidedPlane` added to the context, and having no
* rotation, "plane1" faces you and "plane2" faces away.
*
* @class DoubleSidedPlane
* @extends Molecule
*/
var DoubleSidedPlane = function (_Molecule) {
_inherits(DoubleSidedPlane, _Molecule);
/**
* Creates a new `DoubleSidedPlane` who's `initialOptions` get passed to
* both [Plane](#Plane) instances, as well as this DoubleSidedPlane's parent
* [Molecule](#Molecule) constructor.
*
* @constructor
* @param {Object} initialOptions The options to initiate the `DoubleSidedPlane` with.
*/
function DoubleSidedPlane(initialOptions) {
_classCallCheck(this, DoubleSidedPlane);
var _this = _possibleConstructorReturn(this, (DoubleSidedPlane.__proto__ || _Object$getPrototypeOf(DoubleSidedPlane)).call(this, initialOptions));
_this.children = [];
_this.plane1 = new Plane(_this.options);
_this.plane1.transform.set(Transform_1.rotate(0, 0, 0));
_this.setOptions({ properties: { background: 'orange' } });
_this.plane2 = new Plane(_this.options);
_this.plane2.transform.set(Transform_1.rotate(0, Math.PI, 0));
_this.children.push(_this.plane1);
_this.children.push(_this.plane2);
_this.add(_this.plane2);
_this.add(_this.plane1);
_this.plane1.pipe(_this.options.handler);
_this.plane2.pipe(_this.options.handler);
return _this;
}
/**
* Get the content of the [famous/src/core/Surface](#famous/src/core/Surface) of each [Plane](#Plane).
*
* @returns {Array} An array containing two items, the content of each
* `Plane`. The first item is from "plane1".
*/
_createClass(DoubleSidedPlane, [{
key: 'getContent',
value: function getContent() {
return [this.plane1.getContent(), this.plane2.getContent()];
}
/**
* Set the content of both [Plane](#Plane) instances.
*
* @param {Array} content An array of content, one item per `Plane`. The
* first item is for "plane1".
*/
}, {
key: 'setContent',
value: function setContent(content) {
this.plane1.setContent(content[0]);
this.plane2.setContent(content[1]);
}
}]);
return DoubleSidedPlane;
}(Molecule);
/*
* LICENSE
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/**
* A calendar widget for selecting a date (WIP).
*
* @class Calendar
* @extends Molecule
*/
var Calendar = function (_Molecule) {
_inherits(Calendar, _Molecule);
/**
* Create a new `Calendar` with the given Famo.us-style size array and
* transition. The transition is the type of animation used when switching
* between months.
*
* @constructor
* @param {Array} calendarSize A Famo.us-style width/height size array.
* @param {String} transition The name of the animation transition to use when switching months.
*/
function Calendar(calendarSize, transition) {
_classCallCheck(this, Calendar);
var _this = _possibleConstructorReturn(this, (Calendar.__proto__ || _Object$getPrototypeOf(Calendar)).call(this, { size: calendarSize }));
_this.transition = transition;
_this.flipSide = 0; // 0 means the initial front faces are showing, 1 means the initial back faces are showing.
_this.columnsRows = [7, 6];
_this.planes = [];
_this._initializeTransitions();
_this._createGrid();
setTimeout(function () {
this.transitions[this.transition]();
setInterval(this.transitions[this.transition], 2000);
}.bind(_this), 800);
return _this;
}
/**
* Creates the grid used for the layout of the day cells.
*
* @private
*/
_createClass(Calendar, [{
key: '_createGrid',
value: function _createGrid() {
var grid = new Grid(this.columnsRows[0], this.columnsRows[1], this.options.size);
forLength(this.columnsRows[0] * this.columnsRows[1], function (i) {
var plane = new DoubleSidedPlane({
properties: {
background: 'teal'
}
});
this.planes.push(plane);
}.bind(this));
grid.setChildren(this.planes);
this.add(grid);
}
/**
* Set up `this.transitions`, containing the available month-to-month
* transitions.
*
* @private
*/
}, {
key: '_initializeTransitions',
value: function _initializeTransitions() {
this.transitions = {
flipDiagonal: function () {
this.flipSide = +!this.flipSide;
// determine which dimension of the grid is shorter and which is longer.
var shortest = 0;
var longest;
this.columnsRows.forEach(function (item, index) {
if (item < this.columnsRows[shortest]) { shortest = index; }
}.bind(this));
longest = +!shortest;
// for each diagonal of the grid, flip those cells.
forLength(this.columnsRows[0] + this.columnsRows[1] - 1, function (column) {
forLength(this.columnsRows[shortest], function (row) {
if (column - row >= 0 && column - row < this.columnsRows[longest]) {
var plane = this.planes[column - row + this.columnsRows[longest] * row];
flipOne(plane, column);
}
}.bind(this));
}.bind(this));
function flipOne(item, column) {
if (typeof item.__targetRotation == 'undefined') {
item.__targetRotation = new Transitionable_1(0);
}
var rotation = new Transitionable_1(item.__targetRotation.get());
item.__targetRotation.set(item.__targetRotation.get() + Math.PI);
//item.get().transformFrom(function() {
//return Transform.rotateY(rotation.get());
//});
item.children[0].get().transformFrom(function () {
return Transform_1.rotateY(rotation.get());
});
item.children[1].get().transformFrom(function () {
return Transform_1.rotateY(rotation.get() + Math.PI);
});
setTimeout(function () {
rotation.set(item.__targetRotation.get(), { duration: 2000, curve: Easing_1.outExpo });
}, 0 + 50 * column);
}
}.bind(this)
};
}
}]);
return Calendar;
}(Molecule);
// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
var $getOwnPropertyDescriptor$1 = _objectGopd.f;
_objectSap('getOwnPropertyDescriptor', function () {
return function getOwnPropertyDescriptor(it, key) {
return $getOwnPropertyDescriptor$1(_toIobject(it), key);
};
});
var $Object$2 = _core.Object;
var getOwnPropertyDescriptor$1 = function getOwnPropertyDescriptor(it, key) {
return $Object$2.getOwnPropertyDescriptor(it, key);
};
var getOwnPropertyDescriptor = createCommonjsModule(function (module) {
module.exports = { "default": getOwnPropertyDescriptor$1, __esModule: true };
});
var _Object$getOwnPropertyDescriptor = unwrapExports(getOwnPropertyDescriptor);
var get$1 = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _getPrototypeOf2 = _interopRequireDefault(getPrototypeOf);
var _getOwnPropertyDescriptor2 = _interopRequireDefault(getOwnPropertyDescriptor);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function get(object, property, receiver) {
if (object === null) { object = Function.prototype; }
var desc = (0, _getOwnPropertyDescriptor2.default)(object, property);
if (desc === undefined) {
var parent = (0, _getPrototypeOf2.default)(object);
if (parent === null) {
return undefined;
} else {
return get(parent, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === undefined) {
return undefined;
}
return getter.call(receiver);
}
};
});
var _get = unwrapExports(get$1);
var utils$1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.clone = clone;
exports.isEmptyObject = isEmptyObject;
exports.toCSS = toCSS;
var stringify = JSON.stringify;
var parse = JSON.parse;
/**
* Deeply clone object using serialization.
* Expects object to be plain and without cyclic dependencies.
*
* http://jsperf.com/lodash-deepclone-vs-jquery-extend-deep/6
*
* @type {Object} obj
* @return {Object}
*/
function clone(obj) {
return parse(stringify(obj));
}
/**
* Determine whether an object is empty or not.
* More performant than a `Object.keys(obj).length > 0`
*
* @type {Object} obj
* @return {Boolean}
*/
function isEmptyObject(obj) {
for (var key in obj) {
return false;
} // eslint-disable-line no-unused-vars
return true;
}
/**
* Simple very fast UID generation based on a global counter.
*/
var uid = exports.uid = function () {
var globalReference = typeof window == 'undefined' ? commonjsGlobal : window;
var namespace = '__JSS_VERSION_COUNTER__';
if (globalReference[namespace] == null) { globalReference[namespace] = 0; }
// In case we have more than one jss version.
var versionCounter = globalReference[namespace]++;
var ruleCounter = 0;
/**
* Returns a uid.
* Ensures uniqueness if more than 1 jss version is used.
*
* @api public
* @return {String}
*/
function get() {
return 'jss-' + versionCounter + '-' + ruleCounter++;
}
/**
* Resets the counter.
*
* @api public
*/
function reset() {
ruleCounter = 0;
}
return { get: get, reset: reset };
}();
/**
* Indent a string.
*
* http://jsperf.com/array-join-vs-for
*
* @param {Number} level
* @param {String} str
* @return {String}
*/
function indent(level, str) {
var indentStr = '';
for (var index = 0; index < level; index++) {
indentStr += ' ';
}return indentStr + str;
}
/**
* Converts a Rule to CSS string.
*
* Options:
* - `selector` use `false` to get a rule without selector
* - `indentationLevel` level of indentation
*
* @param {String} selector
* @param {Object} style
* @param {Object} options
* @return {String}
*/
function toCSS(selector, style) {
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var indentationLevel = options.indentationLevel || 0;
var str = '';
if (options.selector !== false) {
str += indent(indentationLevel, selector + ' {');
indentationLevel++;
}
for (var prop in style) {
var value = style[prop];
// We want to generate multiple style with identical property names.
if (Array.isArray(value)) {
for (var index = 0; index < value.length; index++) {
str += '\n' + indent(indentationLevel, prop + ': ' + value[index] + ';');
}
} else { str += '\n' + indent(indentationLevel, prop + ': ' + value + ';'); }
}
if (options.selector !== false) { str += '\n' + indent(--indentationLevel, '}'); }
return str;
}
/**
* Get class names from a selector.
*
* @param {String} selector
* @return {String}
*/
var findClassNames = exports.findClassNames = function () {
var dotsRegExp = /[.]/g;
var classesRegExp = /[.][^ ,]+/g;
return function (selector) {
var classes = selector.match(classesRegExp);
if (!classes) { return ''; }
return classes.join(' ').replace(dotsRegExp, '');
};
}();
});
unwrapExports(utils$1);
var Rule_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Regular rules.
*
* @api public
*/
var Rule = function () {
function Rule(selector, style, options) {
_classCallCheck(this, Rule);
this.id = utils$1.uid.get();
this.type = 'regular';
this.options = options;
this.selectorText = selector || '';
this.className = options.className || '';
this.originalStyle = style;
// We expect style to be plain object.
this.style = (0, utils$1.clone)(style);
if (options.named) {
this.name = selector;
if (!this.className) {
this.className = this.name ? this.name + '--' + this.id : this.id;
}
this.selectorText = '.' + this.className;
}
}
/**
* Set selector string.
* Attenition: use this with caution. Most browser didn't implement selector
* text setter, so this will result in rerendering of entire style sheet.
*
* @param {String} selector
* @api public
*/
_createClass(Rule, [{
key: 'prop',
/**
* Get or set a style property.
*
* @param {String} name
* @param {String|Number} [value]
* @return {Rule|String|Number}
* @api public
*/
value: function prop(name, value) {
var style = this.options.Renderer.style;
// Its a setter.
if (value != null) {
this.style[name] = value;
// Only defined if option linked is true.
if (this.renderable) { style(this.renderable, name, value); }
return this;
}
// Its a getter, read the value from the DOM if its not cached.
if (this.renderable && this.style[name] == null) {
// Cache the value after we have got it from the DOM once.
this.style[name] = style(this.renderable, name);
}
return this.style[name];
}
/**
* Apply rule to an element inline.
*
* @param {Element} renderable
* @return {Rule}
* @api public
*/
}, {
key: 'applyTo',
value: function applyTo(renderable) {
var this$1 = this;
for (var prop in this$1.style) {
var value = this$1.style[prop];
var style = this$1.options.Renderer.style;
if (Array.isArray(value)) {
for (var index = 0; index < value.length; index++) {
style(renderable, prop, value[index]);
}
} else { style(renderable, prop, value); }
}
return this;
}
/**
* Returns JSON representation of the rule.
* Array of values is not supported.
*
* @return {Object}
* @api public
*/
}, {
key: 'toJSON',
value: function toJSON() {
var this$1 = this;
var style = Object.create(null);
for (var prop in this$1.style) {
if (_typeof(this$1.style[prop]) != 'object') {
style[prop] = this$1.style[prop];
}
}
return style;
}
/**
* Generates a CSS string.
*
* @see toCSS
* @api public
*/
}, {
key: 'toString',
value: function toString(options) {
return (0, utils$1.toCSS)(this.selector, this.style, options);
}
}, {
key: 'selector',
set: function set() {
var selector = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0];
var _options = this.options;
var Renderer = _options.Renderer;
var sheet = _options.sheet;
// After we modify selector, ref by old selector needs to be removed.
if (sheet) { sheet.unregisterRule(this); }
this.selectorText = selector;
this.className = (0, utils$1.findClassNames)(selector);
if (!this.renderable) {
// Register the rule with new selector.
if (sheet) { sheet.registerRule(this); }
return;
}
var changed = Renderer.setSelector(this.renderable, selector);
if (changed) {
sheet.registerRule(this);
return;
}
// If selector setter is not implemented, rerender the sheet.
// We need to delete renderable from the rule, because when sheet.deploy()
// calls rule.toString, it will get the old selector.
delete this.renderable;
sheet.registerRule(this).deploy().link();
}
/**
* Get selector string.
*
* @return {String}
* @api public
*/
,
get: function get() {
if (this.renderable) {
return this.options.Renderer.getSelector(this.renderable);
}
return this.selectorText;
}
}]);
return Rule;
}();
exports.default = Rule;
});
unwrapExports(Rule_1);
var SimpleRule_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Rule like @charset, @import, @namespace.
*
* @api public
*/
var SimpleRule = function () {
function SimpleRule(name, value, options) {
_classCallCheck(this, SimpleRule);
this.id = utils$1.uid.get();
this.type = 'simple';
this.name = name;
this.value = value;
this.options = options;
}
/**
* Generates a CSS string.
*
* @return {String}
* @api public
*/
_createClass(SimpleRule, [{
key: 'toString',
value: function toString() {
var this$1 = this;
if (Array.isArray(this.value)) {
var str = '';
for (var index = 0; index < this.value.length; index++) {
str += this$1.name + ' ' + this$1.value[index] + ';';
if (this$1.value[index + 1]) { str += '\n'; }
}
return str;
}
return this.name + ' ' + this.value + ';';
}
}]);
return SimpleRule;
}();
exports.default = SimpleRule;
});
unwrapExports(SimpleRule_1);
var KeyframeRule_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) {
var arguments$1 = arguments;
for (var i = 1; i < arguments.length; i++) { var source = arguments$1[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Keyframe rule.
*
* @api private
*/
var KeyframeRule = function () {
function KeyframeRule(selector, frames, options) {
_classCallCheck(this, KeyframeRule);
this.id = utils$1.uid.get();
this.type = 'keyframe';
this.selector = selector;
this.options = options;
this.frames = this.formatFrames(frames);
}
/**
* Creates formatted frames where every frame value is a rule instance.
*
* @api private
*/
_createClass(KeyframeRule, [{
key: 'formatFrames',
value: function formatFrames(frames) {
var this$1 = this;
var newFrames = Object.create(null);
for (var name in frames) {
var options = _extends({}, this$1.options, { named: false, parent: this$1 });
newFrames[name] = this$1.options.jss.createRule(name, frames[name], options);
}
return newFrames;
}
/**
* Generates a CSS string.
*
* @return {String}
* @api private
*/
}, {
key: 'toString',
value: function toString() {
var this$1 = this;
var str = this.selector + ' {\n';
var options = { indentationLevel: 1 };
for (var name in this$1.frames) {
str += this$1.frames[name].toString(options) + '\n';
}
str += '}';
return str;
}
}]);
return KeyframeRule;
}();
exports.default = KeyframeRule;
});
unwrapExports(KeyframeRule_1);
var ConditionalRule_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) {
var arguments$1 = arguments;
for (var i = 1; i < arguments.length; i++) { var source = arguments$1[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Conditional rule for @media, @supports
*
* @api public
*/
var ConditionalRule = function () {
function ConditionalRule(selector, styles, options) {
var this$1 = this;
_classCallCheck(this, ConditionalRule);
this.id = utils$1.uid.get();
this.type = 'conditional';
this.selector = selector;
this.options = options;
this.rules = Object.create(null);
for (var name in styles) {
this$1.createRule(name, styles[name]);
}
}
/**
* A conditional rule always contains child rules.
*
* @param {Object} styles
* @return {Array} rules
* @api public
*/
_createClass(ConditionalRule, [{
key: 'createRule',
value: function createRule(name, style, options) {
var newOptions = _extends({}, this.options, { parent: this });
var _newOptions = newOptions;
var sheet = _newOptions.sheet;
var jss = _newOptions.jss;
// We have already a rule in the current style sheet with this name,
// This new rule is supposed to overwrite the first one, for this we need
// to ensure it will have the same className/selector.
var existingRule = sheet && sheet.getRule(name);
var className = existingRule ? existingRule.className : null;
if (className || options) {
newOptions = _extends({}, newOptions, { className: className }, options);
}
var rule = (sheet || jss).createRule(name, style, newOptions);
this.rules[name] = rule;
return rule;
}
/**
* Generates a CSS string.
*
* @return {String}
* @api public
*/
}, {
key: 'toString',
value: function toString() {
var this$1 = this;
var str = this.selector + ' {\n';
for (var name in this$1.rules) {
var rule = this$1.rules[name];
if (rule.style && (0, utils$1.isEmptyObject)(rule.style)) {
continue;
}
var ruleStr = rule.toString({ indentationLevel: 1 });
str += ruleStr + '\n';
}
str += '}';
return str;
}
}]);
return ConditionalRule;
}();
exports.default = ConditionalRule;
});
unwrapExports(ConditionalRule_1);
var FontFaceRule = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Font-face rules.
*
* @api public
*/
var Rule = function () {
function Rule(selector, style, options) {
_classCallCheck(this, Rule);
this.id = utils$1.uid.get();
this.type = 'font-face';
this.options = options;
this.selector = selector;
this.style = style;
}
/**
* Generates a CSS string.
*
* @see toCSS
* @api public
*/
_createClass(Rule, [{
key: 'toString',
value: function toString(options) {
var this$1 = this;
if (Array.isArray(this.style)) {
var str = '';
for (var index = 0; index < this.style.length; index++) {
str += (0, utils$1.toCSS)(this$1.selector, this$1.style[index], options);
if (this$1.style[index + 1]) { str += '\n'; }
}
return str;
}
return (0, utils$1.toCSS)(this.selector, this.style, options);
}
}]);
return Rule;
}();
exports.default = Rule;
});
unwrapExports(FontFaceRule);
var createRule_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createRule;
var _Rule2 = _interopRequireDefault(Rule_1);
var _SimpleRule2 = _interopRequireDefault(SimpleRule_1);
var _KeyframeRule2 = _interopRequireDefault(KeyframeRule_1);
var _ConditionalRule2 = _interopRequireDefault(ConditionalRule_1);
var _FontFaceRule2 = _interopRequireDefault(FontFaceRule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Map of at rules to corresponding implementation class.
*
* @type {Object}
*/
var atRuleClassMap = {
'@charset': _SimpleRule2.default,
'@import': _SimpleRule2.default,
'@namespace': _SimpleRule2.default,
'@keyframes': _KeyframeRule2.default,
'@media': _ConditionalRule2.default,
'@supports': _ConditionalRule2.default,
'@font-face': _FontFaceRule2.default
};
var atRuleNameRegExp = /^@[^ ]+/;
/**
* Create rule factory.
*
* @param {Object} [selector] if you don't pass selector - it will be generated
* @param {Object} [style] declarations block
* @param {Object} [options] rule options
* @return {Object} rule
* @api private
*/
function createRule(selector) {
var style = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
// Is an at-rule.
if (selector && selector[0] === '@') {
var name = atRuleNameRegExp.exec(selector)[0];
var AtRule = atRuleClassMap[name];
return new AtRule(selector, style, options);
}
if (options.named == null) { options.named = true; }
return new _Rule2.default(selector, style, options);
}
});
unwrapExports(createRule_1);
var DomRenderer_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* DOM rendering backend for StyleSheet.
*
* @api private
*/
var DomRenderer = function () {
_createClass(DomRenderer, null, [{
key: 'style',
value: function style(element, name, value) {
try {
if (value == null) { return element.style[name]; }
element.style[name] = value;
} catch (err) {
// IE8 may throw if property is unknown.
return false;
}
return true;
}
}, {
key: 'setSelector',
value: function setSelector(cssRule, selector) {
cssRule.selectorText = selector;
// Return false if setter was not successful.
// Currently works in chrome only.
return cssRule.selectorText === selector;
}
}, {
key: 'getSelector',
value: function getSelector(cssRule) {
return cssRule.selectorText;
}
}]);
function DomRenderer(options) {
_classCallCheck(this, DomRenderer);
this.head = document.head || document.getElementsByTagName('head')[0];
this.element = options.element || document.createElement('style');
// IE8 will not have `styleSheet` prop without `type and `styleSheet.cssText`
// is the only way to render on IE8.
this.element.type = 'text/css';
if (options.media) { this.element.setAttribute('media', options.media); }
if (options.meta) { this.element.setAttribute('data-meta', options.meta); }
}
/**
* Insert style element into render tree.
*
* @api private
*/
_createClass(DomRenderer, [{
key: 'attach',
value: function attach() {
if (this.element.parendNode) { return; }
this.head.appendChild(this.element);
}
/**
* Remove style element from render tree.
*
* @api private
*/
}, {
key: 'detach',
value: function detach() {
this.element.parentNode.removeChild(this.element);
}
/**
* Inject CSS string into element.
*
* @param {String} cssStr
* @api private
*/
}, {
key: 'deploy',
value: function deploy(sheet) {
var css = '\n' + sheet.toString() + '\n';
if ('sheet' in this.element) { this.element.innerHTML = css; }
// On IE8 the only way to render is `styleSheet.cssText`.
else if ('styleSheet' in this.element) { this.element.styleSheet.cssText = css; }
}
/**
* Insert a rule into element.
*
* @param {Rule} rule
* @return {CSSStyleRule}
* @api private
*/
}, {
key: 'insertRule',
value: function insertRule(rule) {
// IE8 has only `styleSheet` and `styleSheet.rules`
var sheet = this.element.sheet || this.element.styleSheet;
var cssRules = sheet.cssRules || sheet.rules;
var nextIndex = cssRules.length;
if (sheet.insertRule) { sheet.insertRule(rule.toString(), nextIndex); }else { sheet.addRule(rule.selector, rule.toString({ selector: false }), nextIndex); }
return cssRules[nextIndex];
}
/**
* Get all rules elements.
*
* @return {Object} rules map, where key is selector, CSSStyleRule is value.
* @api private
*/
}, {
key: 'getRules',
value: function getRules() {
// IE8 has only `styleSheet` and `styleSheet.rules`
var sheet = this.element.sheet || this.element.styleSheet;
var cssRules = sheet.rules || sheet.cssRules;
var rules = Object.create(null);
for (var index = 0; index < cssRules.length; index++) {
var cssRule = cssRules[index];
rules[cssRule.selectorText] = cssRule;
}
return rules;
}
}]);
return DomRenderer;
}();
exports.default = DomRenderer;
});
unwrapExports(DomRenderer_1);
var VirtualRenderer_1 = createCommonjsModule(function (module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Rendering backend to do nothing in nodejs.
*/
var VirtualRenderer = function () {
function VirtualRenderer() {
_classCallCheck(this, VirtualRenderer);
}
_createClass(VirtualRenderer, [{
key: "attach",
value: function attach() {}
}, {
key: "detach",
value: function detach() {}
}, {
key: "deploy",
value: function deploy() {}
}, {
key: "insertRule",
value: function insertRule() {}
}, {
key: "getRules",
value: function getRules() {
return {};
}
}], [{
key: "style",
value: function style() {}
}, {
key: "setSelector",
value: function setSelector() {}
}, {
key: "getSelector",
value: function getSelector() {}
}]);
return VirtualRenderer;
}();
exports.default = VirtualRenderer;
});
unwrapExports(VirtualRenderer_1);
var findRenderer_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = findRenderer;
var _DomRenderer2 = _interopRequireDefault(DomRenderer_1);
var _VirtualRenderer2 = _interopRequireDefault(VirtualRenderer_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Find proper renderer.
* Option `virtual` is used to force use of VirtualRenderer even if DOM is
* detected, used for testing only.
*
* @param {Object} options
* @return {Renderer}
* @api private
*/
function findRenderer() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
if (options.Renderer) { return options.Renderer; }
return options.virtual || typeof document == 'undefined' ? _VirtualRenderer2.default : _DomRenderer2.default;
}
});
unwrapExports(findRenderer_1);
var StyleSheet_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) {
var arguments$1 = arguments;
for (var i = 1; i < arguments.length; i++) { var source = arguments$1[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
var _createRule3 = _interopRequireDefault(createRule_1);
var _findRenderer2 = _interopRequireDefault(findRenderer_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* StyleSheet model.
*
* Options:
*
* - `media` media query - attribute of style element.
* - `meta` meta information about this style - attribute of style element, for e.g. you could pass
* component name for easier debugging.
* - `named` true by default - keys are names, selectors will be generated, if false - keys are
* global selectors.
* - `link` link jss `Rule` instances with DOM `CSSRule` instances so that styles, can be modified
* dynamically, false by default because it has some performance cost.
* - `element` style element, will create one by default
*
* @param {Object} [rules] object with selectors and declarations
* @param {Object} [options]
* @api public
*/
var StyleSheet = function () {
function StyleSheet(rules, options) {
var this$1 = this;
_classCallCheck(this, StyleSheet);
this.options = _extends({}, options);
if (this.options.named == null) { this.options.named = true; }
this.rules = Object.create(null);
this.classes = Object.create(null);
this.attached = false;
this.deployed = false;
this.linked = false;
var Renderer = (0, _findRenderer2.default)(this.options);
this.options.Renderer = Renderer;
this.renderer = new Renderer(this.options);
for (var name in rules) {
this$1.createRule(name, rules[name]);
}
}
/**
* Attach renderable to the render tree.
*
* @api public
* @return {StyleSheet}
*/
_createClass(StyleSheet, [{
key: 'attach',
value: function attach() {
if (this.attached) { return this; }
if (!this.deployed) { this.deploy(); }
this.renderer.attach();
if (!this.linked && this.options.link) { this.link(); }
this.attached = true;
return this;
}
/**
* Remove renderable from render tree.
*
* @return {StyleSheet}
* @api public
*/
}, {
key: 'detach',
value: function detach() {
if (!this.attached) { return this; }
this.renderer.detach();
this.attached = false;
return this;
}
/**
* Add a rule to the current stylesheet. Will insert a rule also after the stylesheet
* has been rendered first time.
*
* @param {Object} [name] can be selector or name if ´options.named is true
* @param {Object} style property/value hash
* @return {Rule}
* @api public
*/
}, {
key: 'addRule',
value: function addRule(name, style) {
var rule = this.createRule(name, style);
// Don't insert rule directly if there is no stringified version yet.
// It will be inserted all together when .attach is called.
if (this.deployed) {
var renderable = this.renderer.insertRule(rule);
if (this.options.link) { rule.renderable = renderable; }
}
return rule;
}
/**
* Create rules, will render also after stylesheet was rendered the first time.
*
* @param {Object} rules name:style hash.
* @return {Array} array of added rules
* @api public
*/
}, {
key: 'addRules',
value: function addRules(rules) {
var this$1 = this;
var added = [];
for (var name in rules) {
added.push(this$1.addRule(name, rules[name]));
}
return added;
}
/**
* Get a rule.
*
* @param {String} name can be selector or name if `named` option is true.
* @return {Rule}
* @api public
*/
}, {
key: 'getRule',
value: function getRule(name) {
return this.rules[name];
}
/**
* Convert rules to a CSS string.
*
* @param {Object} options
* @return {String}
* @api public
*/
}, {
key: 'toString',
value: function toString(options) {
var rules = this.rules;
var stringified = Object.create(null);
var str = '';
for (var name in rules) {
var rule = rules[name];
// We have the same rule referenced twice if using named rules.
// By name and by selector.
if (stringified[rule.id]) {
continue;
}
if (rule.style && (0, utils$1.isEmptyObject)(rule.style)) {
continue;
}
if (rule.rules && (0, utils$1.isEmptyObject)(rule.rules)) {
continue;
}
if (str) { str += '\n'; }
str += rule.toString(options);
stringified[rule.id] = true;
}
return str;
}
/**
* Create a rule, will not render after stylesheet was rendered the first time.
* Will link the rule in `this.rules`.
*
* @see createRule
* @api private
*/
}, {
key: 'createRule',
value: function createRule(name, style, options) {
options = _extends({}, options, {
sheet: this,
jss: this.options.jss,
Renderer: this.options.Renderer
});
// Scope options overwrite instance options.
if (options.named == null) { options.named = this.options.named; }
var rule = (0, _createRule3.default)(name, style, options);
this.registerRule(rule);
options.jss.plugins.run(rule);
return rule;
}
/**
* Register a rule in `sheet.rules` and `sheet.classes` maps.
*
* @param {Rule} rule
* @api public
*/
}, {
key: 'registerRule',
value: function registerRule(rule) {
// Children of container rules should not be registered.
if (rule.options.parent) {
// We need to register child rules of conditionals in classes, otherwise
// user can't access generated class name if it doesn't overrides
// a regular rule.
if (rule.name && rule.className) {
this.classes[rule.name] = rule.className;
}
return this;
}
if (rule.name) {
this.rules[rule.name] = rule;
if (rule.className) { this.classes[rule.name] = rule.className; }
}
if (rule.selector) {
this.rules[rule.selector] = rule;
}
return this;
}
/**
* Unregister a rule.
*
* @param {Rule} rule
* @api public
*/
}, {
key: 'unregisterRule',
value: function unregisterRule(rule) {
// Children of a conditional rule are not registered.
if (!rule.options.parent) {
delete this.rules[rule.name];
delete this.rules[rule.selector];
}
delete this.classes[rule.name];
return this;
}
/**
* Deploy pure CSS string to a renderable.
*
* @return {StyleSheet}
* @api private
*/
}, {
key: 'deploy',
value: function deploy() {
this.renderer.deploy(this);
this.deployed = true;
return this;
}
/**
* Link renderable CSS rules with their corresponding models.
*
* @return {StyleSheet}
* @api private
*/
}, {
key: 'link',
value: function link() {
var this$1 = this;
var renderables = this.renderer.getRules();
for (var selector in renderables) {
var rule = this$1.rules[selector];
if (rule) { rule.renderable = renderables[selector]; }
}
this.linked = true;
return this;
}
}]);
return StyleSheet;
}();
exports.default = StyleSheet;
});
unwrapExports(StyleSheet_1);
var PluginsRegistry_1 = createCommonjsModule(function (module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Register a plugin, run a plugin.
*
* @api public
*/
var PluginsRegistry = function () {
function PluginsRegistry() {
_classCallCheck(this, PluginsRegistry);
this.registry = [];
}
/**
* Register plugin. Passed function will be invoked with a rule instance.
*
* @param {Function} fn
* @api public
*/
_createClass(PluginsRegistry, [{
key: "use",
value: function use(fn) {
this.registry.push(fn);
}
/**
* Execute all registered plugins.
*
* @param {Rule} rule
* @api private
*/
}, {
key: "run",
value: function run(rule) {
var this$1 = this;
for (var index = 0; index < this.registry.length; index++) {
this$1.registry[index](rule);
}
}
}]);
return PluginsRegistry;
}();
exports.default = PluginsRegistry;
});
unwrapExports(PluginsRegistry_1);
var SheetsRegistry_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Sheets registry to access them all at one place.
*
* @api public
*/
var SheetsRegistry = function () {
function SheetsRegistry() {
_classCallCheck(this, SheetsRegistry);
this.registry = [];
}
/**
* Register a style sheet.
*
* @param {StyleSheet} sheet
* @api public
*/
_createClass(SheetsRegistry, [{
key: 'add',
value: function add(sheet) {
this.registry.push(sheet);
}
/**
* Returns CSS string with all Style Sheets.
*
* @param {StyleSheet} sheet
* @api public
*/
}, {
key: 'toString',
value: function toString(options) {
return this.registry.map(function (sheet) {
return sheet.toString(options);
}).join('\n');
}
}]);
return SheetsRegistry;
}();
exports.default = SheetsRegistry;
});
unwrapExports(SheetsRegistry_1);
var Jss_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _extends = Object.assign || function (target) {
var arguments$1 = arguments;
for (var i = 1; i < arguments.length; i++) { var source = arguments$1[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
var _StyleSheet2 = _interopRequireDefault(StyleSheet_1);
var _PluginsRegistry2 = _interopRequireDefault(PluginsRegistry_1);
var _SheetsRegistry2 = _interopRequireDefault(SheetsRegistry_1);
var _createRule3 = _interopRequireDefault(createRule_1);
var _findRenderer2 = _interopRequireDefault(findRenderer_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Main Jss class.
*
* @api public
*/
var Jss = function () {
function Jss() {
_classCallCheck(this, Jss);
this.sheets = new _SheetsRegistry2.default();
this.plugins = new _PluginsRegistry2.default();
this.uid = utils$1.uid;
this.version = '3.11.1';
}
/**
* Creates a new instance of Jss.
*
* @see Jss
* @api public
*/
_createClass(Jss, [{
key: 'create',
value: function create() {
return new Jss();
}
/**
* Create a stylesheet.
*
* @see StyleSheet
* @api public
*/
}, {
key: 'createStyleSheet',
value: function createStyleSheet(rules, options) {
var sheet = new _StyleSheet2.default(rules, _extends({}, options, { jss: this }));
this.sheets.add(sheet);
return sheet;
}
/**
* Create a rule.
*
* @see createRule
* @api public
*/
}, {
key: 'createRule',
value: function createRule(selector, style, options) {
// Enable rule without selector.
if ((typeof selector === 'undefined' ? 'undefined' : _typeof(selector)) == 'object') {
options = style;
style = selector;
selector = null;
}
var rule = (0, _createRule3.default)(selector, style, _extends({}, options, {
jss: this,
Renderer: (0, _findRenderer2.default)(options)
}));
this.plugins.run(rule);
return rule;
}
/**
* Register plugin. Passed function will be invoked with a rule instance.
*
* @param {Function} plugins
* @api public
*/
}, {
key: 'use',
value: function use() {
var arguments$1 = arguments;
var _this = this;
for (var _len = arguments.length, plugins = Array(_len), _key = 0; _key < _len; _key++) {
plugins[_key] = arguments$1[_key];
}
plugins.forEach(function (plugin) {
return _this.plugins.use(plugin);
});
return this;
}
}]);
return Jss;
}();
exports.default = Jss;
});
unwrapExports(Jss_1);
var lib = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Rule = exports.StyleSheet = exports.Jss = undefined;
var _Jss2 = _interopRequireDefault(Jss_1);
var _StyleSheet2 = _interopRequireDefault(StyleSheet_1);
var _Rule2 = _interopRequireDefault(Rule_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var jss = new _Jss2.default();
// Hotfix for babel 5 migration, will be removed in version 4.0.0
/**
* StyleSheets written in javascript.
*
* @copyright Oleg Slobodskoi 2014-2016
* @website https://github.com/jsstyles/jss
* @license MIT
*/
module.exports = exports = jss;
// For testing only.
exports.Jss = _Jss2.default;
exports.StyleSheet = _StyleSheet2.default;
exports.Rule = _Rule2.default;
exports.default = jss;
});
var Jss = unwrapExports(lib);
var lib$1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) {
var arguments$1 = arguments;
for (var i = 1; i < arguments.length; i++) { var source = arguments$1[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports.default = jssNested;
var regExp = /&/g;
/**
* Convert nested rules to separate, remove them from original styles.
*
* @param {Rule} rule
* @api public
*/
function jssNested() {
return function (rule) {
if (rule.type !== 'regular') { return; }
var _rule$options = rule.options;
var sheet = _rule$options.sheet;
var jss = _rule$options.jss;
var parent = _rule$options.parent;
var container = sheet || jss;
var options = void 0;
if (parent && parent.type === 'conditional') {
container = parent;
}
for (var prop in rule.style) {
if (prop[0] === '&') {
if (!options) { options = _extends({}, rule.options, { named: false }); }
var name = prop.replace(regExp, rule.selector);
container.createRule(name, rule.style[prop], options);
delete rule.style[prop];
}
}
};
}
});
var jssNested = unwrapExports(lib$1);
var lib$2 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = jssExtend;
/**
* Handle `extend` property.
*
* @param {Rule} rule
* @api public
*/
function jssExtend() {
function extend(rule, newStyle, style) {
if (typeof style.extend == 'string') {
if (rule.options && rule.options.sheet) {
var refRule = rule.options.sheet.getRule(style.extend);
if (refRule) { extend(rule, newStyle, refRule.originalStyle); }
}
} else if (Array.isArray(style.extend)) {
for (var index = 0; index < style.extend.length; index++) {
extend(rule, newStyle, style.extend[index]);
}
} else {
for (var prop in style.extend) {
if (prop === 'extend') { extend(rule, newStyle, style.extend.extend); }else { newStyle[prop] = style.extend[prop]; }
}
}
// Copy base style.
for (var _prop in style) {
if (_prop !== 'extend') { newStyle[_prop] = style[_prop]; }
}
return newStyle;
}
return function (rule) {
if (!rule.style || !rule.style.extend) { return; }
rule.style = extend(rule, {}, rule.style);
};
}
});
var jssExtend = unwrapExports(lib$2);
var lib$3 = createCommonjsModule(function (module, exports) {
// Don't automatically add 'px' to these possibly-unitless properties.
// Borrowed from jquery.
'use strict';
exports.__esModule = true;
exports['default'] = jssPx;
var cssNumber = {
'animation-iteration-count': true,
'box-ordinal-group': true,
'column-count': true,
'fill-opacity': true,
'flex': true,
'flex-grow': true,
'flex-order': true,
'flex-shrink': true,
'font-weight': true,
'line-height': true,
'opacity': true,
'order': true,
'orphans': true,
'stop-opacity': true,
'tab-size': 1,
'widows': true,
'z-index': true,
'zoom': true
};
/**
* Add px to numeric values.
*
* @param {Rule} rule
* @api public
*/
function jssPx() {
return function (rule) {
var style = rule.style;
if (!style) { return; }
for (var prop in style) {
if (!cssNumber[prop] && typeof style[prop] == 'number') {
style[prop] += 'px';
}
}
};
}
module.exports = exports['default'];
});
var jssPx = unwrapExports(lib$3);
var _typeof$1 = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var isBrowser = (typeof window === "undefined" ? "undefined" : _typeof$1(window)) === "object" && (typeof document === "undefined" ? "undefined" : _typeof$1(document)) === 'object' && document.nodeType === 9;
var module$1 = Object.freeze({
isBrowser: isBrowser,
default: isBrowser
});
var _isInBrowser = ( module$1 && isBrowser ) || module$1;
var prefix = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _isInBrowser2 = _interopRequireDefault(_isInBrowser);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var js = ''; /**
* Export javascript style and css style vendor prefixes.
* Based on "transform" support test.
*/
var css = '';
// We should not do anything if required serverside.
if (_isInBrowser2['default']) {
// Order matters. We need to check Webkit the last one because
// other vendors use to add Webkit prefixes to some properties
var jsCssMap = {
Moz: '-moz-',
// IE did it wrong again ...
ms: '-ms-',
O: '-o-',
Webkit: '-webkit-'
};
var style = document.createElement('p').style;
var testProp = 'Transform';
for (var key in jsCssMap) {
if (key + testProp in style) {
js = key;
css = jsCssMap[key];
break;
}
}
}
/**
* Vendor prefix string for the current browser.
*
* @type {{js: String, css: String}}
* @api public
*/
exports['default'] = { js: js, css: css };
});
unwrapExports(prefix);
var camelize_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = camelize;
var regExp = /[-\s]+(.)?/g;
/**
* Convert dash separated strings to camel cased.
*
* @param {String} str
* @return {String}
*/
function camelize(str) {
return str.replace(regExp, toUpper);
}
function toUpper(match, c) {
return c ? c.toUpperCase() : '';
}
});
unwrapExports(camelize_1);
var supportedProperty_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = supportedProperty;
var _isInBrowser2 = _interopRequireDefault(_isInBrowser);
var _prefix2 = _interopRequireDefault(prefix);
var _camelize2 = _interopRequireDefault(camelize_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var el = void 0;
var cache = {};
if (_isInBrowser2['default']) {
el = document.createElement('p');
/**
* We test every property on vendor prefix requirement.
* Once tested, result is cached. It gives us up to 70% perf boost.
* http://jsperf.com/element-style-object-access-vs-plain-object
*
* Prefill cache with known css properties to reduce amount of
* properties we need to feature test at runtime.
* http://davidwalsh.name/vendor-prefix
*/
var computed = window.getComputedStyle(document.documentElement, '');
for (var key in computed) {
if (!isNaN(key)) { cache[computed[key]] = computed[key]; }
}
}
/**
* Test if a property is supported, returns supported property with vendor
* prefix if required. Returns `false` if not supported.
*
* @param {String} prop dash separated
* @return {String|Boolean}
* @api public
*/
function supportedProperty(prop) {
// For server-side rendering.
if (!el) { return prop; }
// We have not tested this prop yet, lets do the test.
if (cache[prop] != null) { return cache[prop]; }
// Camelization is required because we can't test using
// css syntax for e.g. in FF.
// Test if property is supported as it is.
if ((0, _camelize2['default'])(prop) in el.style) {
cache[prop] = prop;
}
// Test if property is supported with vendor prefix.
else if (_prefix2['default'].js + (0, _camelize2['default'])('-' + prop) in el.style) {
cache[prop] = _prefix2['default'].css + prop;
} else {
cache[prop] = false;
}
return cache[prop];
}
});
unwrapExports(supportedProperty_1);
var supportedValue_1 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports['default'] = supportedValue;
var _isInBrowser2 = _interopRequireDefault(_isInBrowser);
var _prefix2 = _interopRequireDefault(prefix);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var cache = {};
var el = void 0;
if (_isInBrowser2['default']) { el = document.createElement('p'); }
/**
* Returns prefixed value if needed. Returns `false` if value is not supported.
*
* @param {String} property
* @param {String} value
* @return {String|Boolean}
* @api public
*/
function supportedValue(property, value) {
// For server-side rendering.
if (!el) { return value; }
// It is a string or a number as a string like '1'.
// We want only prefixable values here.
if (typeof value !== 'string' || !isNaN(parseInt(value, 10))) { return value; }
var cacheKey = property + value;
if (cache[cacheKey] != null) { return cache[cacheKey]; }
// IE can even throw an error in some cases, for e.g. style.content = 'bar'
try {
// Test value as it is.
el.style[property] = value;
} catch (err) {
cache[cacheKey] = false;
return false;
}
// Value is supported as it is.
if (el.style[property] !== '') {
cache[cacheKey] = value;
} else {
// Test value with vendor prefix.
value = _prefix2['default'].css + value;
// Hardcode test to convert "flex" to "-ms-flexbox" for IE10.
if (value === '-ms-flex') { value = '-ms-flexbox'; }
el.style[property] = value;
// Value is supported with vendor prefix.
if (el.style[property] !== '') { cache[cacheKey] = value; }
}
if (!cache[cacheKey]) { cache[cacheKey] = false; }
// Reset style value.
el.style[property] = '';
return cache[cacheKey];
}
});
unwrapExports(supportedValue_1);
var lib$5 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.supportedValue = exports.supportedProperty = exports.prefix = undefined;
var _prefix2 = _interopRequireDefault(prefix);
var _supportedProperty2 = _interopRequireDefault(supportedProperty_1);
var _supportedValue2 = _interopRequireDefault(supportedValue_1);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
exports['default'] = {
prefix: _prefix2['default'],
supportedProperty: _supportedProperty2['default'],
supportedValue: _supportedValue2['default']
}; /**
* CSS Vendor prefix detection and property feature testing.
*
* @copyright Oleg Slobodskoi 2015
* @website https://github.com/jsstyles/css-vendor
* @license MIT
*/
exports.prefix = _prefix2['default'];
exports.supportedProperty = _supportedProperty2['default'];
exports.supportedValue = _supportedValue2['default'];
});
unwrapExports(lib$5);
var lib$4 = createCommonjsModule(function (module, exports) {
'use strict';
exports.__esModule = true;
exports['default'] = jssVendorPrefixer;
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj['default'] = obj; return newObj; } }
var vendor = _interopRequireWildcard(lib$5);
/**
* Add vendor prefix to a property name when needed.
*
* @param {Rule} rule
* @api public
*/
function jssVendorPrefixer() {
return function (rule) {
if (rule.type === 'keyframe') {
rule.selector = '@' + vendor.prefix.css + 'keyframes' + rule.selector.substr(10);
return;
}
if (rule.type !== 'regular') { return; }
for (var prop in rule.style) {
var value = rule.style[prop];
var changeProp = false;
var supportedProp = vendor.supportedProperty(prop);
if (supportedProp && supportedProp !== prop) { changeProp = true; }
var changeValue = false;
var supportedValue = vendor.supportedValue(supportedProp, value);
if (supportedValue && supportedValue !== value) { changeValue = true; }
if (changeProp || changeValue) {
if (changeProp) { delete rule.style[prop]; }
rule.style[supportedProp || prop] = supportedValue || value;
}
}
};
}
module.exports = exports['default'];
});
var jssVendorPrefixer = unwrapExports(lib$4);
var lib$6 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var regExp = /([A-Z])/g;
/**
* Replace a string passed from String#replace.
* @param {String} str
* @return {String}
*/
function replace(str) {
return '-' + str.toLowerCase();
}
/**
* Convert camel cased properties of a single style to dasherized.
*
* @param {Object} style
* @return {Object} convertedStyle
*/
function convertCase(style) {
var convertedStyle = {};
for (var prop in style) {
var value = style[prop];
prop = prop.replace(regExp, replace);
convertedStyle[prop] = value;
}
return convertedStyle;
}
/**
* Allow camel cased property names by converting them back to dasherized.
*
* @param {Rule} rule
*/
exports.default = function () {
return function jssCamelCase(rule) {
var style = rule.style;
if (!style) { return; }
if (Array.isArray(style)) {
// Handle rules like @font-face, which can have multiple styles in an array
for (var index = 0; index < style.length; index++) {
style[index] = convertCase(style[index]);
}
} else {
rule.style = convertCase(style);
}
};
};
});
var jssCamelCase = unwrapExports(lib$6);
var lib$7 = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = jssPropsSort;
/**
* Sort props by length.
*
* @param {Rule} rule
* @api public
*/
function jssPropsSort() {
function sort(prop0, prop1) {
return prop0.length > prop1.length;
}
return function (rule) {
var style = rule.style;
var type = rule.type;
if (!style || type !== 'regular') { return; }
var newStyle = {};
var props = Object.keys(style).sort(sort);
for (var prop in props) {
newStyle[props[prop]] = style[props[prop]];
}
rule.style = newStyle;
};
}
});
var jssPropsSort = unwrapExports(lib$7);
var jss = Jss.create();
jss.use(jssNested());
jss.use(jssExtend());
jss.use(jssPx());
jss.use(jssVendorPrefixer());
jss.use(jssCamelCase());
jss.use(jssPropsSort());
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
var _now = Date.now;
function _timestampTouch(touch, event, history) {
return {
x: touch.clientX,
y: touch.clientY,
identifier : touch.identifier,
origin: event.origin,
timestamp: _now(),
count: event.touches.length,
history: history
};
}
function _handleStart$1(event) {
var this$1 = this;
if (event.touches.length > this.touchLimit) { return; }
this.isTouched = true;
for (var i = 0; i < event.changedTouches.length; i++) {
var touch = event.changedTouches[i];
var data = _timestampTouch(touch, event, null);
this$1.eventOutput.emit('trackstart', data);
if (!this$1.selective && !this$1.touchHistory[touch.identifier]) { this$1.track(data); }
}
}
function _handleMove$1(event) {
var this$1 = this;
if (event.touches.length > this.touchLimit) { return; }
for (var i = 0; i < event.changedTouches.length; i++) {
var touch = event.changedTouches[i];
var history = this$1.touchHistory[touch.identifier];
if (history) {
var data = _timestampTouch(touch, event, history);
this$1.touchHistory[touch.identifier].push(data);
this$1.eventOutput.emit('trackmove', data);
}
}
}
function _handleEnd$1(event) {
var this$1 = this;
if (!this.isTouched) { return; }
for (var i = 0; i < event.changedTouches.length; i++) {
var touch = event.changedTouches[i];
var history = this$1.touchHistory[touch.identifier];
if (history) {
var data = _timestampTouch(touch, event, history);
this$1.eventOutput.emit('trackend', data);
delete this$1.touchHistory[touch.identifier];
}
}
this.isTouched = false;
}
function _handleUnpipe() {
var this$1 = this;
for (var i in this$1.touchHistory) {
var history = this$1.touchHistory[i];
this$1.eventOutput.emit('trackend', {
touch: history[history.length - 1].touch,
timestamp: Date.now(),
count: 0,
history: history
});
delete this$1.touchHistory[i];
}
}
/**
* Helper to TouchSync – tracks piped in touch events, organizes touch
* events by ID, and emits track events back to TouchSync.
* Emits 'trackstart', 'trackmove', and 'trackend' events upstream.
*
* @class TouchTracker
* @constructor
* @param {Object} options default options overrides
* @param [options.selective] {Boolean} selective if false, saves state for each touch
* @param [options.touchLimit] {Number} touchLimit upper bound for emitting events based on number of touches
*/
function TouchTracker(options) {
this.selective = options.selective;
this.touchLimit = options.touchLimit || 1;
this.touchHistory = {};
this.eventInput = new EventHandler_1();
this.eventOutput = new EventHandler_1();
EventHandler_1.setInputHandler(this, this.eventInput);
EventHandler_1.setOutputHandler(this, this.eventOutput);
this.eventInput.on('touchstart', _handleStart$1.bind(this));
this.eventInput.on('touchmove', _handleMove$1.bind(this));
this.eventInput.on('touchend', _handleEnd$1.bind(this));
this.eventInput.on('touchcancel', _handleEnd$1.bind(this));
this.eventInput.on('unpipe', _handleUnpipe.bind(this));
this.isTouched = false;
}
/**
* Record touch data, if selective is false.
* @private
* @method track
* @param {Object} data touch data
*/
TouchTracker.prototype.track = function track(data) {
this.touchHistory[data.identifier] = [data];
};
var TouchTracker_1 = TouchTracker;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* Handles piped in touch events. Emits 'start', 'update', and 'events'
* events with delta, position, velocity, acceleration, clientX, clientY, count, and touch id.
* Useful for dealing with inputs on touch devices. Designed to be used either as standalone, or
* included in a GenericSync.
*
* @class TouchSync
* @constructor
*
* @example
* var Surface = require('../core/Surface');
* var TouchSync = require('../inputs/TouchSync');
*
* var surface = new Surface({ size: [100, 100] });
* var touchSync = new TouchSync();
* surface.pipe(touchSync);
*
* touchSync.on('start', function (e) { // react to start });
* touchSync.on('update', function (e) { // react to update });
* touchSync.on('end', function (e) { // react to end });*
*
* @param [options] {Object} default options overrides
* @param [options.direction] {Number} read from a particular axis
* @param [options.rails] {Boolean} read from axis with greatest differential
* @param [options.velocitySampleLength] {Number} Number of previous frames to check velocity against.
* @param [options.scale] {Number} constant factor to scale velocity output
* @param [options.touchLimit] {Number} touchLimit upper bound for emitting events based on number of touches
*/
function TouchSync(options) {
this.options = Object.create(TouchSync.DEFAULT_OPTIONS);
this._optionsManager = new OptionsManager_1(this.options);
if (options) { this.setOptions(options); }
this._eventOutput = new EventHandler_1();
this._touchTracker = new TouchTracker_1({
touchLimit: this.options.touchLimit
});
EventHandler_1.setOutputHandler(this, this._eventOutput);
EventHandler_1.setInputHandler(this, this._touchTracker);
this._touchTracker.on('trackstart', _handleStart.bind(this));
this._touchTracker.on('trackmove', _handleMove.bind(this));
this._touchTracker.on('trackend', _handleEnd.bind(this));
this._payload = {
delta : null,
position : null,
velocity : null,
clientX : undefined,
clientY : undefined,
count : 0,
touch : undefined
};
this._position = null; // to be deprecated
}
TouchSync.DEFAULT_OPTIONS = {
direction: undefined,
rails: false,
touchLimit: 1,
velocitySampleLength: 10,
scale: 1
};
TouchSync.DIRECTION_X = 0;
TouchSync.DIRECTION_Y = 1;
var MINIMUM_TICK_TIME = 8;
/**
* Triggered by trackstart.
* @method _handleStart
* @private
*/
function _handleStart(data) {
var velocity;
var delta;
if (this.options.direction !== undefined){
this._position = 0;
velocity = 0;
delta = 0;
}
else {
this._position = [0, 0];
velocity = [0, 0];
delta = [0, 0];
}
var payload = this._payload;
payload.delta = delta;
payload.position = this._position;
payload.velocity = velocity;
payload.clientX = data.x;
payload.clientY = data.y;
payload.count = data.count;
payload.touch = data.identifier;
this._eventOutput.emit('start', payload);
}
/**
* Triggered by trackmove.
* @method _handleMove
* @private
*/
function _handleMove(data) {
var history = data.history;
var currHistory = history[history.length - 1];
var prevHistory = history[history.length - 2];
var distantHistory = history[history.length - this.options.velocitySampleLength] ?
history[history.length - this.options.velocitySampleLength] :
history[history.length - 2];
var distantTime = distantHistory.timestamp;
var currTime = currHistory.timestamp;
var diffX = currHistory.x - prevHistory.x;
var diffY = currHistory.y - prevHistory.y;
var velDiffX = currHistory.x - distantHistory.x;
var velDiffY = currHistory.y - distantHistory.y;
if (this.options.rails) {
if (Math.abs(diffX) > Math.abs(diffY)) { diffY = 0; }
else { diffX = 0; }
if (Math.abs(velDiffX) > Math.abs(velDiffY)) { velDiffY = 0; }
else { velDiffX = 0; }
}
var diffTime = Math.max(currTime - distantTime, MINIMUM_TICK_TIME);
var velX = velDiffX / diffTime;
var velY = velDiffY / diffTime;
var scale = this.options.scale;
var nextVel;
var nextDelta;
if (this.options.direction === TouchSync.DIRECTION_X) {
nextDelta = scale * diffX;
nextVel = scale * velX;
this._position += nextDelta;
}
else if (this.options.direction === TouchSync.DIRECTION_Y) {
nextDelta = scale * diffY;
nextVel = scale * velY;
this._position += nextDelta;
}
else {
nextDelta = [scale * diffX, scale * diffY];
nextVel = [scale * velX, scale * velY];
this._position[0] += nextDelta[0];
this._position[1] += nextDelta[1];
}
var payload = this._payload;
payload.delta = nextDelta;
payload.velocity = nextVel;
payload.position = this._position;
payload.clientX = data.x;
payload.clientY = data.y;
payload.count = data.count;
payload.touch = data.identifier;
this._eventOutput.emit('update', payload);
}
/**
* Triggered by trackend.
* @method _handleEnd
* @private
*/
function _handleEnd(data) {
this._payload.count = data.count;
this._eventOutput.emit('end', this._payload);
}
/**
* Set internal options, overriding any default options
*
* @method setOptions
*
* @param [options] {Object} default options overrides
* @param [options.direction] {Number} read from a particular axis
* @param [options.rails] {Boolean} read from axis with greatest differential
* @param [options.scale] {Number} constant factor to scale velocity output
*/
TouchSync.prototype.setOptions = function setOptions(options) {
return this._optionsManager.setOptions(options);
};
/**
* Return entire options dictionary, including defaults.
*
* @method getOptions
* @return {Object} configuration options
*/
TouchSync.prototype.getOptions = function getOptions() {
return this.options;
};
var TouchSync_1 = TouchSync;
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Owner: mark@famo.us
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2015
*/
/**
* Combines multiple types of sync classes (e.g. mouse, touch,
* scrolling) into one standardized interface for inclusion in widgets.
*
* Sync classes are first registered with a key, and then can be accessed
* globally by key.
*
* Emits 'start', 'update' and 'end' events as a union of the sync class
* providers.
*
* @class GenericSync
* @constructor
* @param syncs {Object|Array} object with fields {sync key : sync options}
* or an array of registered sync keys
* @param [options] {Object|Array} options object to set on all syncs
*/
function GenericSync(syncs, options) {
this._eventInput = new EventHandler_1();
this._eventOutput = new EventHandler_1();
EventHandler_1.setInputHandler(this, this._eventInput);
EventHandler_1.setOutputHandler(this, this._eventOutput);
this._syncs = {};
if (syncs) { this.addSync(syncs); }
if (options) { this.setOptions(options); }
}
GenericSync.DIRECTION_X = 0;
GenericSync.DIRECTION_Y = 1;
GenericSync.DIRECTION_Z = 2;
// Global registry of sync classes. Append only.
var registry = {};
/**
* Register a global sync class with an identifying key
*
* @static
* @method register
*
* @param syncObject {Object} an object of {sync key : sync options} fields
*/
GenericSync.register = function register(syncObject) {
for (var key in syncObject){
if (registry[key]){ // skip redundant registration
if (registry[key] !== syncObject[key]) // only if same registered class
{ throw new Error('Conflicting sync classes for key: ' + key); }
}
else { registry[key] = syncObject[key]; }
}
};
/**
* Helper to set options on all sync instances
*
* @method setOptions
* @param options {Object} options object
*/
GenericSync.prototype.setOptions = function(options) {
var this$1 = this;
for (var key in this$1._syncs){
this$1._syncs[key].setOptions(options);
}
};
/**
* Pipe events to a sync class
*
* @method pipeSync
* @param key {String} identifier for sync class
*/
GenericSync.prototype.pipeSync = function pipeToSync(key) {
var sync = this._syncs[key];
this._eventInput.pipe(sync);
sync.pipe(this._eventOutput);
};
/**
* Unpipe events from a sync class
*
* @method unpipeSync
* @param key {String} identifier for sync class
*/
GenericSync.prototype.unpipeSync = function unpipeFromSync(key) {
var sync = this._syncs[key];
this._eventInput.unpipe(sync);
sync.unpipe(this._eventOutput);
};
function _addSingleSync(key, options) {
if (!registry[key]) { return; }
this._syncs[key] = new (registry[key])(options);
this.pipeSync(key);
}
/**
* Add a sync class to from the registered classes
*
* @method addSync
* @param syncs {Object|Array.String} an array of registered sync keys
* or an object with fields {sync key : sync options}
*/
GenericSync.prototype.addSync = function addSync(syncs) {
var this$1 = this;
if (syncs instanceof Array)
{ for (var i = 0; i < syncs.length; i++)
{ _addSingleSync.call(this$1, syncs[i]); } }
else if (syncs instanceof Object)
{ for (var key in syncs)
{ _addSingleSync.call(this$1, key, syncs[key]); } }
};
var GenericSync_1 = GenericSync;
var callAfter_1 = createCommonjsModule(function (module, exports) {
"use strict";
exports.callAfter = callAfter;
function callAfter(times, callback) {
var count = 0;
return function () {
if (++count == times) {
if (typeof callback == "function") {
callback.apply(this, arguments);
}
}
};
}
exports["default"] = callAfter;
exports.__esModule = true;
});
var callAfter = unwrapExports(callAfter_1);
/*
* LICENSE
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/**
* A scenegraph with two Molecule leafnodes: the menu area and the content
* area. The menu area is hidden beyond the edge of the screen while the
* content area is visible. Swiping in from the edge of the screen reveals the
* menu, putting the content area out of focus. A mouse can also be used, and
* hovering near the edge of the screen also reveals the menu.
*
* Note: This layout is mostly useful if it exists at the root of a context so
* that the menu is clipped when it is closed (off to the side), otherwise the
* menu will be visible beyond the boundary of the container that contains the
* PushMenuLayout.
*
* Note: If you've called `openMenu` or `closeMenu` with a callback, the callback
* will be canceled if a drag or hover on the menu happens before the animation
* has completed. Please open an issue on GitHub if you have any opinion
* against this. :) Maybe we can add a boolean option for this behavior.
*
* TODO: Embed working example here.
*
* @class PushMenuLayout
* @extends Molecule
*/
var PushMenuLayout = function (_Molecule) {
_inherits(PushMenuLayout, _Molecule);
/**
* Creates a new PushMenuLayout.
*
* @constructor
* @param {Object} options The options to instantiate a `PushMenuLayout` with.
*
* TODO v0.1.0: Handle `PushMenuLayout`-specific user options. Currently they
* just get passed into super() for the Molecule constructor to handle.
*/
function PushMenuLayout(initialOptions) {
_classCallCheck(this, PushMenuLayout);
// Add default values for this PushMenuLayout
// TODO: Make default options static for the class.
var _this = _possibleConstructorReturn(this, (PushMenuLayout.__proto__ || _Object$getPrototypeOf(PushMenuLayout)).call(this, initialOptions));
simpleExtend(_this._.defaultOptions, {
menuSide: 'left', // left or right
menuWidth: 200,
menuHintSize: 10, // the amount of the menu that is visible before opening the menu.
pushAreaWidth: 40, // the area on the screen edge that the user can touch and drag to push out the menu.
animationDuration: 1000,
animationType: 'foldDown', // options: foldDown moveBack
// TODO: Background color for the whole layout should be the color that the fade fades to.
// TODO: Replace fade star/end colors with a fog color value and intensity.
fade: true, // when content recedes, it fades into the fog.
fadeStartColor: 'rgba(255,255,255,0)',
fadeEndColor: 'rgba(255,255,255,1)',
blur: false, // XXX: WIP, so false by default.
blurRadius: 5
});
// TODO: performance hit, this setter is invoked in the Molecule constructor, then here again.
_this.options = initialOptions;
// TODO v0.1.0: Mark these as private.
// TODO v0.1.0: this.contentWidth should be the width of whatever is containing
// the layout, but we're just using it as a whole-page app for now. Get
// size from a commit? UPDATE: See the new famous/src/views/SizeAwareView
_this.contentWidth = document.body.clientWidth - _this.options.menuHintSize;
// Changing these values outside of an instance of PushMenuLayout might
// cause the layout to break. They are designed to be modified
// internally only.
_this.isOpen = false;
_this.isOpening = false;
_this.isClosing = false;
_this.isAnimating = false; // keep track of whether the menu is opening or closing.
_this.isBeingDragged = false; // whether the user is dragging/pushing the menu or not.
_this.transitionCallback = undefined; // holds the callback to the current open or close menu animation.
// Set the touch sync for pulling/pushing the menu open/closed.
GenericSync_1.register({
touch: TouchSync_1
});
_this._createComponents();
_this._initializeEvents();
return _this;
}
/**
* See Molecule.setOptions
*
* @override
*/
_createClass(PushMenuLayout, [{
key: 'setOptions',
value: function setOptions(newOptions) {
_get(PushMenuLayout.prototype.__proto__ || _Object$getPrototypeOf(PushMenuLayout.prototype), 'setOptions', this).call(this, newOptions);
}
/**
* See Molecule.resetOptions
*
* @override
*/
}, {
key: 'resetOptions',
value: function resetOptions() {
_get(PushMenuLayout.prototype.__proto__ || _Object$getPrototypeOf(PushMenuLayout.prototype), 'resetOptions', this).call(this);
}
/**
* Creates the menu area, content area, `Plane` for the fade effect, etc.
*
* @private
*/
}, {
key: '_createComponents',
value: function _createComponents() {
var layout = this;
this.touchSync = new GenericSync_1(['touch']);
this.alignment = this.options.menuSide == "left" ? 0 : 1;
this.animationTransition = new Transitionable_1(0);
this.mainMol = new Molecule();
this.menuMol = new Molecule({
size: [this.options.menuWidth, undefined]
});
this.menuMol.oldTransform = this.menuMol.transform;
this.menuMol.transform = function () {
// override
var currentPosition = layout.animationTransition.get();
switch (layout.options.animationType) {
case "foldDown":
// XXX: this is depending on my modifications for TransitionableTransform.
this.oldTransform.setTranslateX(layout.options.menuSide == 'left' ? currentPosition * (layout.options.menuWidth - layout.options.menuHintSize) /*range*/ - (layout.options.menuWidth - layout.options.menuHintSize) /*offset*/ : currentPosition * -(layout.options.menuWidth - layout.options.menuHintSize) /*range*/ + (layout.options.menuWidth - layout.options.menuHintSize) /*offset*/
);
break;
case "moveBack":
// XXX: this is depending on my modifications for TransitionableTransform.
this.oldTransform.setTranslateX(layout.options.menuSide == 'left' ? currentPosition * (layout.options.menuWidth - layout.options.menuHintSize) /*range*/ - (layout.options.menuWidth - layout.options.menuHintSize) /*offset*/ : currentPosition * -(layout.options.menuWidth - layout.options.menuHintSize) /*range*/ + (layout.options.menuWidth - layout.options.menuHintSize) /*offset*/
);
break;
}
return this.oldTransform.get();
}.bind(this.menuMol);
// contains the user's menu content.
this.menuContentMol = new Molecule();
this.contentMol = new Molecule({
size: [this.contentWidth, undefined]
});
this.contentMol.oldTransform = this.contentMol.transform;
this.contentMol.transform = function () {
// override
var currentPosition = layout.animationTransition.get();
switch (layout.options.animationType) {
case "foldDown":
// XXX: this is depending on my modifications for TransitionableTransform.
this.oldTransform.setTranslateX(layout.options.menuSide == 'left' ? currentPosition * (layout.options.menuWidth - layout.options.menuHintSize) /*range*/ + layout.options.menuHintSize /*offset*/ : currentPosition * -(layout.options.menuWidth - layout.options.menuHintSize) /*range*/ - layout.options.menuHintSize /*offset*/
);
// XXX: this is depending on my modifications for TransitionableTransform.
this.oldTransform.setRotateY(layout.options.menuSide == 'left' ? currentPosition * Math.PI / 8 : currentPosition * -Math.PI / 8);
break;
case "moveBack":
var depth = 100;
// XXX: this is depending on my modifications for TransitionableTransform.
this.oldTransform.setTranslateX(layout.options.menuSide == 'left' ? layout.options.menuHintSize : -layout.options.menuHintSize);
this.oldTransform.setTranslateZ(currentPosition * -depth);
break;
}
return this.oldTransform.get();
}.bind(this.contentMol);
this.menuTouchPlane = new Plane({
size: [this.options.menuWidth + this.options.pushAreaWidth - this.options.menuHintSize, undefined],
properties: {
zIndex: '-1000' // below everything
}
});
this.mainMol.setOptions({
origin: [this.alignment, 0.5],
align: [this.alignment, 0.5]
});
this.menuMol.setOptions({
origin: [this.alignment, 0.5],
align: [this.alignment, 0.5]
});
this.contentMol.setOptions({
origin: [this.alignment, 0.5],
align: [this.alignment, 0.5]
});
// FIXME: WHY THE EFF must I also set align and origin on menuTouchPlane
// when I've already set it on it's parent (this.menuMol)?????
this.menuTouchPlane.setOptions({
origin: [this.alignment, 0.5],
align: [this.alignment, 0.5]
});
// Bring the menu content molecule and touch plane forward just
// slightly so they're just above the content and content's fade plane,
// so touch and mouse interaction works. HTML, the bad parts. ;)
this.menuContentMol.transform.setTranslateZ(2);
this.menuTouchPlane.transform.setTranslateZ(2);
/*
* Styles for the fadePlane
*/
// TODO: move this somewhere else . it's specific for each animation
this.updateStyles = function () {
var startColor;
var endColor;
switch (this.options.animationType) {
case "foldDown":
startColor = this.options.fadeStartColor;
endColor = this.options.fadeEndColor;
break;
case "moveBack":
startColor = endColor = this.options.fadeEndColor;
break;
}
var styles = {
'.infamous-fadeLeft': {
background: [endColor, '-moz-linear-gradient(left, ' + endColor + ' 0%, ' + startColor + ' 100%)', '-webkit-gradient(left top, right top, color-stop(0%, ' + endColor + '), color-stop(100%, ' + startColor + '))', '-webkit-linear-gradient(left, ' + endColor + ' 0%, ' + startColor + ' 100%)', '-o-linear-gradient(left, ' + endColor + ' 0%, ' + startColor + ' 100%)', '-ms-linear-gradient(left, ' + endColor + ' 0%, ' + startColor + ' 100%)', 'linear-gradient(to right, ' + endColor + ' 0%, ' + startColor + ' 100%)'],
filter: 'progid:DXImageTransform.Microsoft.gradient( startColorstr=\'#cc000000\', endColorstr=\'#4d000000\', GradientType=1 )'
},
'.infamous-fadeRight': {
background: [startColor, '-moz-linear-gradient(left, ' + startColor + ' 0%, ' + endColor + ' 100%)', '-webkit-gradient(left top, right top, color-stop(0%, ' + startColor + '), color-stop(100%, ' + endColor + '))', '-webkit-linear-gradient(left, ' + startColor + ' 0%, ' + endColor + ' 100%)', '-o-linear-gradient(left, ' + startColor + ' 0%, ' + endColor + ' 100%)', '-ms-linear-gradient(left, ' + startColor + ' 0%, ' + endColor + ' 100%)', 'linear-gradient(to right, ' + startColor + ' 0%, ' + endColor + ' 100%)'],
filter: 'progid:DXImageTransform.Microsoft.gradient( startColorstr=\'#4d000000\', endColorstr=\'#cc000000\', GradientType=1 )'
}
};
if (this.fadeStylesheet) {
this.fadeStylesheet.detach();
}
this.fadeStylesheet = jss.createStyleSheet(styles);
this.fadeStylesheet.attach();
};
if (this.options.fade) {
this.updateStyles();
this.fadePlane = new Plane({
size: [undefined, undefined],
classes: [
// TODO: switch to jss namespace.
this.options.menuSide == 'left' ? 'infamous-fadeRight' : 'infamous-fadeLeft'],
properties: {
zIndex: '1000',
pointerEvents: 'none'
}
});
// FIXME: Why the EFF must I also set align and origin on fadePlane when
// I've already set it on it's parent (this.contentMol)?????
this.fadePlane.setOptions({
origin: [this.alignment, 0.5],
align: [this.alignment, 0.5]
});
// move the fadePlane forward by 1px so it doesn't glitch out.
// Chrome will make the fadePlane and the surface in the content
// area (if any) blink randomly when the two surfaces are in the
// same exact position together.
this.fadePlane.transform.setTranslateZ(1);
this.fadePlane.setOptions({
opacity: this.animationTransition
});
// TODO: Make fadePlane a sibling to menuMol and contentMol so that
// contentMol contains only the user;s content. This will affect
// the code in this.render().
this.contentMol.add(this.fadePlane);
}
this.add(this.mainMol);
this.mainMol.add(this.contentMol);
this.menuMol.add(this.menuTouchPlane);
this.menuMol.add(this.menuContentMol);
this.mainMol.add(this.menuMol);
// TODO: Also create and add a background plane for the menu area so it will catch events that might fall through the menu content.
}
/**
* Sets up the events for the touch and mouse interaction that opens and
* closes the menu.
*
* @private
*/
}, {
key: '_initializeEvents',
value: function _initializeEvents() {
// move the menu, following the user's drag. Don't let the user drag the menu past the menu width.
this.options.handler.on('update', function (event) {
// update == drag
this.isBeingDragged = true;
// stop the current transitions if any, along with the current callback if any.
this._haltAnimation(true);
var currentPosition = this.animationTransition.get();
// TODO: handle the right-side menu.
switch (this.options.animationType) {
case "foldDown":
this.animationTransition.set(currentPosition + event.delta[0] / (this.options.menuWidth - this.options.menuHintSize));
break;
case "moveBack":
this.animationTransition.set(currentPosition + event.delta[0] / (this.options.menuWidth - this.options.menuHintSize));
break;
}
currentPosition = this.animationTransition.get();
if (currentPosition > 1) {
this.animationTransition.set(1);
} else if (currentPosition < 0) {
this.animationTransition.set(0);
}
}.bind(this));
this.options.handler.on('end', function (event) {
this.isBeingDragged = false;
var currentPosition = this.animationTransition.get();
if (currentPosition < 0.5) {
this.closeMenu();
} else {
this.openMenu();
}
}.bind(this));
// TODO v0.1.0: Use a SizeAwareView instead of relying on the body, since we
// might not be directly in the body.
window.addEventListener('resize', function (event) {
this.contentWidth = document.body.clientWidth - this.options.menuHintSize;
this.contentMol.setOptions({ size: [this.contentWidth, undefined] });
}.bind(this));
/*
* Wire up events
* TODO: consolidate dup code here and in setMenu
*/
this.menuTouchPlane.pipe(this.touchSync);
this.menuTouchPlane.on('mouseenter', function () {
if (!this.isOpening) {
this.openMenu();
}
}.bind(this));
this.menuTouchPlane.on('mouseleave', function () {
if (!this.isClosing) {
this.closeMenu();
}
}.bind(this));
this.touchSync.pipe(this.options.handler);
}
/**
* Add a scenegraph to the content area of the PushMenuLayout. You can put
* anything you want into the content area (magical 3D things for example),
* just be careful not to let them cover the menu or you'll block the user
* from interacting with the menu.
*
* @param {module: famous/src/core/RenderNode} node A scenegraph, i.e. a
* RenderNode with stuff in it.
*
* TODO: Accept plain renderables, f.e. Surfaces, etc. This change requires
* also modifying the code in this.render() to account for renderables.
*
* TODO: Make a sibling method to reset the content area.
*/
}, {
key: 'setContent',
value: function setContent(node) {
this.contentMol.add(node);
}
/**
* Add a scenegraph to the menu area of the PushMenuLayout. If the object
* that you pass into setMenu is an infamous component, or a famo.us
* Surface, then it's events will be piped to this PushMenuLayout's input
* sync so that the user can open and close the menu with touch or mouse.
* General advice here would be to keep whatever you put into the menu
* contained within the boundaries of the menu or you might have touch and
* mouse interaction outside of the menu.
*
* @param {module: famous/src/core/RenderNode} node A scenegraph, i.e. a
* RenderNode with stuff in it.
*
* TODO: Accept plain renderables, f.e. Surfaces, etc.
*
* TODO: Remove old content before adding new content.
*/
}, {
key: 'setMenu',
value: function setMenu(node) {
this.menuContentMol.add(node);
if (node instanceof Molecule) {
node.pipe(this.touchSync);
node.on('mouseenter', function () {
if (!this.isOpening) {
this.openMenu();
}
}.bind(this));
node.on('mouseleave', function () {
if (!this.isClosing) {
this.closeMenu();
}
}.bind(this));
}
}
// TODO: replace menu easing with physics so the user can throw the menu,
// using initial velocity and drag to slow it down, and stop immediately
// when it hits the fully-open or fully-closed positions.
/**
* Opens the menu.
*
* @param {Function} callback The function to be called when the animation finishes.
* @param {boolean} [cancelPreviousCallback=false] This is optional. If
* true, then the callback of a previous open or close animation will be
* canceled if that animation was still inprogress when this method is
* called, otherwise the callback of the previous open or close animation
* will be fired immediately before the animation for this animation begins.
*/
}, {
key: 'openMenu',
value: function openMenu(callback, cancelPreviousCallback) {
this._haltAnimation(cancelPreviousCallback);
this.isClosing = false;
this.isOpening = true;
this._animate('open', callback);
}
/**
* Closes the menu.
*
* @param {Function} callback The function to be called when the animation finishes.
* @param {boolean} [cancelPreviousCallback=false] This is optional. If
* true, then the callback of a previous open or close animation will be
* canceled if that animation was still inprogress when this method is
* called, otherwise the callback of the previous open or close animation
* will be fired immediately before the animation for this animation begins.
*/
}, {
key: 'closeMenu',
value: function closeMenu(callback, cancelPreviousCallback) {
this._haltAnimation(cancelPreviousCallback);
this.isClosing = true;
this.isOpening = false;
this._animate('close', callback);
}
/**
* Toggles the menu open or closed. If the menu is open or is opening, then it will now start
* closing, and vice versa.
*
* @param {Function} callback The function to be called when the animation finishes.
* @param {boolean} [cancelPreviousCallback=false] This is optional. If
* true, then the callback of a previous open or close animation will be
* canceled if that animation was still inprogress when this method is
* called, otherwise the callback of the previous open or close animation
* will be fired immediately before the animation for this animation begins.
*/
}, {
key: 'toggleMenu',
value: function toggleMenu(callback, cancelPreviousCallback) {
if (this.isOpen || this.isOpening) {
this.closeMenu(callback, cancelPreviousCallback);
} else if (!this.isOpen || this.isClosing) {
this.openMenu(callback, cancelPreviousCallback);
}
}
/**
* Animates the menu to it's target state.
*
* @private
* @param {String} targetState The name of the state to animate to.
* @param {Function} callback The function to call after the animation completes.
*/
}, {
key: '_animate',
value: function _animate(targetState, callback) {
this.isAnimating = true;
this.transitionCallback = callback;
var _callback;
var self = this;
function setupCallback(numberOfTransitions) {
// Fire callback after numberOfTransitions calls, when the 4 transitions are complete.
_callback = callAfter(numberOfTransitions, function () {
self.isAnimating = self.isOpening = self.isClosing = false;
self.isOpen = targetState == 'open' ? true : false;
if (typeof self.transitionCallback == 'function') {
self.transitionCallback();
}
self.transitionCallback = undefined;
}.bind(self));
}
setupCallback(1);
if (targetState == 'open') {
this.animationTransition.set(1, { duration: this.options.animationDuration, curve: Easing_1.outExpo }, _callback);
} else if (targetState == 'close') {
this.animationTransition.set(0, { duration: this.options.animationDuration, curve: Easing_1.outExpo }, _callback);
}
}
/**
* Halts the current animation, if any.
*
* @private
* @param {boolean} [cancelCallback=false] Defaults to false. If true, the
* halted animation's callback won't fire, otherwise it will be fired.
*/
}, {
key: '_haltAnimation',
value: function _haltAnimation(cancelCallback) {
if (this.isAnimating) {
if (!cancelCallback && typeof this.transitionCallback == 'function') {
this.transitionCallback();
}
this.transitionCallback = undefined;
this.animationTransition.halt();
}
}
/**
* @override
*/
}, {
key: 'render',
value: function render() {
// Blur the content if this.options.blur is true, and the animation is moveBack.
//
// TODO: Make the item to to be blur specifiable, perhaps with a method on
// this.
if (this.options.blur && this.options.fade && this.options.animationType == 'moveBack') {
var momentaryBlur = this.animationTransition.get() * this.options.blurRadius;
var filter = {
"-webkit-filter": 'blur(' + momentaryBlur + 'px)',
"-moz-filter": 'blur(' + momentaryBlur + 'px)',
"-ms-filter": 'blur(' + momentaryBlur + 'px)',
"-o-filter": 'blur(' + momentaryBlur + 'px)',
filter: 'blur(' + momentaryBlur + 'px)'
// TODO TODO TODO v0.1.0: Make fadePlane a sibling with menu and
// content molecules or the following breaks if fade is false.
// Then remove the check for this.options.fade in the previous if
// statement above.
};if (this.contentMol._child[1].get() instanceof Surface_1) {
this.contentMol.get().setProperties(filter);
} else if (this.contentMol._child[1] instanceof Plane) {
this.contentMol._child[1].surface.setProperties(filter);
}
}
return _get(PushMenuLayout.prototype.__proto__ || _Object$getPrototypeOf(PushMenuLayout.prototype), 'render', this).call(this);
}
}]);
return PushMenuLayout;
}(Molecule);
'use strict';
var HAS_INSTANCE = _wks('hasInstance');
var FunctionProto = Function.prototype;
// 19.2.3.6 Function.prototype[@@hasInstance](V)
if (!(HAS_INSTANCE in FunctionProto)) { _objectDp.f(FunctionProto, HAS_INSTANCE, { value: function (O) {
var this$1 = this;
if (typeof this != 'function' || !_isObject(O)) { return false; }
if (!_isObject(this.prototype)) { return O instanceof this; }
// for environment w/o native `@@hasInstance` logic enough `instanceof`, but add this:
while (O = _objectGpo(O)) { if (this$1.prototype === O) { return true; } }
return false;
} }); }
var hasInstance$1 = _wksExt.f('hasInstance');
var hasInstance = createCommonjsModule(function (module) {
module.exports = { "default": hasInstance$1, __esModule: true };
});
var _Symbol$hasInstance = unwrapExports(hasInstance);
// getting tag from 19.1.3.6 Object.prototype.toString()
var TAG$1 = _wks('toStringTag');
// ES3 wrong here
var ARG = _cof(function () { return arguments; }()) == 'Arguments';
// fallback for IE11 Script Access Denied error
var tryGet = function (it, key) {
try {
return it[key];
} catch (e) { /* empty */ }
};
var _classof = function (it) {
var O, T, B;
return it === undefined ? 'Undefined' : it === null ? 'Null'
// @@toStringTag case
: typeof (T = tryGet(O = Object(it), TAG$1)) == 'string' ? T
// builtinTag case
: ARG ? _cof(O)
// ES3 arguments fallback
: (B = _cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
};
var _anInstance = function (it, Constructor, name, forbiddenField) {
if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {
throw TypeError(name + ': incorrect invocation!');
} return it;
};
// call something on iterator step with safe closing on error
var _iterCall = function (iterator, fn, value, entries) {
try {
return entries ? fn(_anObject(value)[0], value[1]) : fn(value);
// 7.4.6 IteratorClose(iterator, completion)
} catch (e) {
var ret = iterator['return'];
if (ret !== undefined) { _anObject(ret.call(iterator)); }
throw e;
}
};
// check on default Array iterator
var ITERATOR$1 = _wks('iterator');
var ArrayProto = Array.prototype;
var _isArrayIter = function (it) {
return it !== undefined && (_iterators.Array === it || ArrayProto[ITERATOR$1] === it);
};
var ITERATOR$2 = _wks('iterator');
var core_getIteratorMethod = _core.getIteratorMethod = function (it) {
if (it != undefined) { return it[ITERATOR$2]
|| it['@@iterator']
|| _iterators[_classof(it)]; }
};
var _forOf = createCommonjsModule(function (module) {
var BREAK = {};
var RETURN = {};
var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {
var iterFn = ITERATOR ? function () { return iterable; } : core_getIteratorMethod(iterable);
var f = _ctx(fn, that, entries ? 2 : 1);
var index = 0;
var length, step, iterator, result;
if (typeof iterFn != 'function') { throw TypeError(iterable + ' is not iterable!'); }
// fast case for arrays with default iterator
if (_isArrayIter(iterFn)) { for (length = _toLength(iterable.length); length > index; index++) {
result = entries ? f(_anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
if (result === BREAK || result === RETURN) { return result; }
} } else { for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {
result = _iterCall(iterator, f, step.value, entries);
if (result === BREAK || result === RETURN) { return result; }
} }
};
exports.BREAK = BREAK;
exports.RETURN = RETURN;
});
// 7.3.20 SpeciesConstructor(O, defaultConstructor)
var SPECIES = _wks('species');
var _speciesConstructor = function (O, D) {
var C = _anObject(O).constructor;
var S;
return C === undefined || (S = _anObject(C)[SPECIES]) == undefined ? D : _aFunction(S);
};
// fast apply, http://jsperf.lnkit.com/fast-apply/5
var _invoke = function (fn, args, that) {
var un = that === undefined;
switch (args.length) {
case 0: return un ? fn()
: fn.call(that);
case 1: return un ? fn(args[0])
: fn.call(that, args[0]);
case 2: return un ? fn(args[0], args[1])
: fn.call(that, args[0], args[1]);
case 3: return un ? fn(args[0], args[1], args[2])
: fn.call(that, args[0], args[1], args[2]);
case 4: return un ? fn(args[0], args[1], args[2], args[3])
: fn.call(that, args[0], args[1], args[2], args[3]);
} return fn.apply(that, args);
};
var process$1 = _global.process;
var setTask = _global.setImmediate;
var clearTask = _global.clearImmediate;
var MessageChannel = _global.MessageChannel;
var Dispatch = _global.Dispatch;
var counter = 0;
var queue = {};
var ONREADYSTATECHANGE = 'onreadystatechange';
var defer;
var channel;
var port;
var run = function () {
var id = +this;
// eslint-disable-next-line no-prototype-builtins
if (queue.hasOwnProperty(id)) {
var fn = queue[id];
delete queue[id];
fn();
}
};
var listener = function (event) {
run.call(event.data);
};
// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
if (!setTask || !clearTask) {
setTask = function setImmediate(fn) {
var arguments$1 = arguments;
var args = [];
var i = 1;
while (arguments.length > i) { args.push(arguments$1[i++]); }
queue[++counter] = function () {
// eslint-disable-next-line no-new-func
_invoke(typeof fn == 'function' ? fn : Function(fn), args);
};
defer(counter);
return counter;
};
clearTask = function clearImmediate(id) {
delete queue[id];
};
// Node.js 0.8-
if (_cof(process$1) == 'process') {
defer = function (id) {
process$1.nextTick(_ctx(run, id, 1));
};
// Sphere (JS game engine) Dispatch API
} else if (Dispatch && Dispatch.now) {
defer = function (id) {
Dispatch.now(_ctx(run, id, 1));
};
// Browsers with MessageChannel, includes WebWorkers
} else if (MessageChannel) {
channel = new MessageChannel();
port = channel.port2;
channel.port1.onmessage = listener;
defer = _ctx(port.postMessage, port, 1);
// Browsers with postMessage, skip WebWorkers
// IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
} else if (_global.addEventListener && typeof postMessage == 'function' && !_global.importScripts) {
defer = function (id) {
_global.postMessage(id + '', '*');
};
_global.addEventListener('message', listener, false);
// IE8-
} else if (ONREADYSTATECHANGE in _domCreate('script')) {
defer = function (id) {
_html.appendChild(_domCreate('script'))[ONREADYSTATECHANGE] = function () {
_html.removeChild(this);
run.call(id);
};
};
// Rest old browsers
} else {
defer = function (id) {
setTimeout(_ctx(run, id, 1), 0);
};
}
}
var _task = {
set: setTask,
clear: clearTask
};
var macrotask = _task.set;
var Observer = _global.MutationObserver || _global.WebKitMutationObserver;
var process$2 = _global.process;
var Promise$1 = _global.Promise;
var isNode$1 = _cof(process$2) == 'process';
var _microtask = function () {
var head, last, notify;
var flush = function () {
var parent, fn;
if (isNode$1 && (parent = process$2.domain)) { parent.exit(); }
while (head) {
fn = head.fn;
head = head.next;
try {
fn();
} catch (e) {
if (head) { notify(); }
else { last = undefined; }
throw e;
}
} last = undefined;
if (parent) { parent.enter(); }
};
// Node.js
if (isNode$1) {
notify = function () {
process$2.nextTick(flush);
};
// browsers with MutationObserver
} else if (Observer) {
var toggle = true;
var node = document.createTextNode('');
new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new
notify = function () {
node.data = toggle = !toggle;
};
// environments with maybe non-completely correct, but existent Promise
} else if (Promise$1 && Promise$1.resolve) {
var promise = Promise$1.resolve();
notify = function () {
promise.then(flush);
};
// for other environments - macrotask based on:
// - setImmediate
// - MessageChannel
// - window.postMessag
// - onreadystatechange
// - setTimeout
} else {
notify = function () {
// strange IE + webpack dev server bug - use .call(global)
macrotask.call(_global, flush);
};
}
return function (fn) {
var task = { fn: fn, next: undefined };
if (last) { last.next = task; }
if (!head) {
head = task;
notify();
} last = task;
};
};
'use strict';
// 25.4.1.5 NewPromiseCapability(C)
function PromiseCapability(C) {
var resolve, reject;
this.promise = new C(function ($$resolve, $$reject) {
if (resolve !== undefined || reject !== undefined) { throw TypeError('Bad Promise constructor'); }
resolve = $$resolve;
reject = $$reject;
});
this.resolve = _aFunction(resolve);
this.reject = _aFunction(reject);
}
var f$7 = function (C) {
return new PromiseCapability(C);
};
var _newPromiseCapability = {
f: f$7
};
var _perform = function (exec) {
try {
return { e: false, v: exec() };
} catch (e) {
return { e: true, v: e };
}
};
var _promiseResolve = function (C, x) {
var promiseCapability = _newPromiseCapability.f(C);
var resolve = promiseCapability.resolve;
resolve(x);
return promiseCapability.promise;
};
var _redefineAll = function (target, src, safe) {
for (var key in src) {
if (safe && target[key]) { target[key] = src[key]; }
else { _hide(target, key, src[key]); }
} return target;
};
'use strict';
var SPECIES$1 = _wks('species');
var _setSpecies = function (KEY) {
var C = typeof _core[KEY] == 'function' ? _core[KEY] : _global[KEY];
if (_descriptors && C && !C[SPECIES$1]) { _objectDp.f(C, SPECIES$1, {
configurable: true,
get: function () { return this; }
}); }
};
var ITERATOR$3 = _wks('iterator');
var SAFE_CLOSING = false;
try {
var riter = [7][ITERATOR$3]();
riter['return'] = function () { SAFE_CLOSING = true; };
// eslint-disable-next-line no-throw-literal
} catch (e) { /* empty */ }
var _iterDetect = function (exec, skipClosing) {
if (!skipClosing && !SAFE_CLOSING) { return false; }
var safe = false;
try {
var arr = [7];
var iter = arr[ITERATOR$3]();
iter.next = function () { return { done: safe = true }; };
arr[ITERATOR$3] = function () { return iter; };
exec(arr);
} catch (e) { /* empty */ }
return safe;
};
'use strict';
var task = _task.set;
var microtask = _microtask();
var PROMISE = 'Promise';
var TypeError$1 = _global.TypeError;
var process = _global.process;
var $Promise = _global[PROMISE];
var isNode = _classof(process) == 'process';
var empty = function () { /* empty */ };
var Internal;
var newGenericPromiseCapability;
var OwnPromiseCapability;
var Wrapper;
var newPromiseCapability = newGenericPromiseCapability = _newPromiseCapability.f;
var USE_NATIVE$1 = !!function () {
try {
// correct subclassing with @@species support
var promise = $Promise.resolve(1);
var FakePromise = (promise.constructor = {})[_wks('species')] = function (exec) {
exec(empty, empty);
};
// unhandled rejections tracking support, NodeJS Promise without it fails @@species test
return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;
} catch (e) { /* empty */ }
}();
// helpers
var sameConstructor = _library ? function (a, b) {
// with library wrapper special case
return a === b || a === $Promise && b === Wrapper;
} : function (a, b) {
return a === b;
};
var isThenable = function (it) {
var then;
return _isObject(it) && typeof (then = it.then) == 'function' ? then : false;
};
var notify = function (promise, isReject) {
if (promise._n) { return; }
promise._n = true;
var chain = promise._c;
microtask(function () {
var value = promise._v;
var ok = promise._s == 1;
var i = 0;
var run = function (reaction) {
var handler = ok ? reaction.ok : reaction.fail;
var resolve = reaction.resolve;
var reject = reaction.reject;
var domain = reaction.domain;
var result, then;
try {
if (handler) {
if (!ok) {
if (promise._h == 2) { onHandleUnhandled(promise); }
promise._h = 1;
}
if (handler === true) { result = value; }
else {
if (domain) { domain.enter(); }
result = handler(value);
if (domain) { domain.exit(); }
}
if (result === reaction.promise) {
reject(TypeError$1('Promise-chain cycle'));
} else if (then = isThenable(result)) {
then.call(result, resolve, reject);
} else { resolve(result); }
} else { reject(value); }
} catch (e) {
reject(e);
}
};
while (chain.length > i) { run(chain[i++]); } // variable length - can't use forEach
promise._c = [];
promise._n = false;
if (isReject && !promise._h) { onUnhandled(promise); }
});
};
var onUnhandled = function (promise) {
task.call(_global, function () {
var value = promise._v;
var unhandled = isUnhandled(promise);
var result, handler, console;
if (unhandled) {
result = _perform(function () {
if (isNode) {
process.emit('unhandledRejection', value, promise);
} else if (handler = _global.onunhandledrejection) {
handler({ promise: promise, reason: value });
} else if ((console = _global.console) && console.error) {
console.error('Unhandled promise rejection', value);
}
});
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
promise._h = isNode || isUnhandled(promise) ? 2 : 1;
} promise._a = undefined;
if (unhandled && result.e) { throw result.v; }
});
};
var isUnhandled = function (promise) {
if (promise._h == 1) { return false; }
var chain = promise._a || promise._c;
var i = 0;
var reaction;
while (chain.length > i) {
reaction = chain[i++];
if (reaction.fail || !isUnhandled(reaction.promise)) { return false; }
} return true;
};
var onHandleUnhandled = function (promise) {
task.call(_global, function () {
var handler;
if (isNode) {
process.emit('rejectionHandled', promise);
} else if (handler = _global.onrejectionhandled) {
handler({ promise: promise, reason: promise._v });
}
});
};
var $reject = function (value) {
var promise = this;
if (promise._d) { return; }
promise._d = true;
promise = promise._w || promise; // unwrap
promise._v = value;
promise._s = 2;
if (!promise._a) { promise._a = promise._c.slice(); }
notify(promise, true);
};
var $resolve = function (value) {
var promise = this;
var then;
if (promise._d) { return; }
promise._d = true;
promise = promise._w || promise; // unwrap
try {
if (promise === value) { throw TypeError$1("Promise can't be resolved itself"); }
if (then = isThenable(value)) {
microtask(function () {
var wrapper = { _w: promise, _d: false }; // wrap
try {
then.call(value, _ctx($resolve, wrapper, 1), _ctx($reject, wrapper, 1));
} catch (e) {
$reject.call(wrapper, e);
}
});
} else {
promise._v = value;
promise._s = 1;
notify(promise, false);
}
} catch (e) {
$reject.call({ _w: promise, _d: false }, e); // wrap
}
};
// constructor polyfill
if (!USE_NATIVE$1) {
// 25.4.3.1 Promise(executor)
$Promise = function Promise(executor) {
_anInstance(this, $Promise, PROMISE, '_h');
_aFunction(executor);
Internal.call(this);
try {
executor(_ctx($resolve, this, 1), _ctx($reject, this, 1));
} catch (err) {
$reject.call(this, err);
}
};
// eslint-disable-next-line no-unused-vars
Internal = function Promise(executor) {
this._c = []; // <- awaiting reactions
this._a = undefined; // <- checked in isUnhandled reactions
this._s = 0; // <- state
this._d = false; // <- done
this._v = undefined; // <- value
this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled
this._n = false; // <- notify
};
Internal.prototype = _redefineAll($Promise.prototype, {
// 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
then: function then(onFulfilled, onRejected) {
var reaction = newPromiseCapability(_speciesConstructor(this, $Promise));
reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
reaction.fail = typeof onRejected == 'function' && onRejected;
reaction.domain = isNode ? process.domain : undefined;
this._c.push(reaction);
if (this._a) { this._a.push(reaction); }
if (this._s) { notify(this, false); }
return reaction.promise;
},
// 25.4.5.1 Promise.prototype.catch(onRejected)
'catch': function (onRejected) {
return this.then(undefined, onRejected);
}
});
OwnPromiseCapability = function () {
var promise = new Internal();
this.promise = promise;
this.resolve = _ctx($resolve, promise, 1);
this.reject = _ctx($reject, promise, 1);
};
_newPromiseCapability.f = newPromiseCapability = function (C) {
return sameConstructor($Promise, C)
? new OwnPromiseCapability(C)
: newGenericPromiseCapability(C);
};
}
_export(_export.G + _export.W + _export.F * !USE_NATIVE$1, { Promise: $Promise });
_setToStringTag($Promise, PROMISE);
_setSpecies(PROMISE);
Wrapper = _core[PROMISE];
// statics
_export(_export.S + _export.F * !USE_NATIVE$1, PROMISE, {
// 25.4.4.5 Promise.reject(r)
reject: function reject(r) {
var capability = newPromiseCapability(this);
var $$reject = capability.reject;
$$reject(r);
return capability.promise;
}
});
_export(_export.S + _export.F * (_library || !USE_NATIVE$1), PROMISE, {
// 25.4.4.6 Promise.resolve(x)
resolve: function resolve(x) {
// instanceof instead of internal slot check because we should fix it without replacement native Promise core
if (x instanceof $Promise && sameConstructor(x.constructor, this)) { return x; }
return _promiseResolve(this, x);
}
});
_export(_export.S + _export.F * !(USE_NATIVE$1 && _iterDetect(function (iter) {
$Promise.all(iter)['catch'](empty);
})), PROMISE, {
// 25.4.4.1 Promise.all(iterable)
all: function all(iterable) {
var C = this;
var capability = newPromiseCapability(C);
var resolve = capability.resolve;
var reject = capability.reject;
var result = _perform(function () {
var values = [];
var index = 0;
var remaining = 1;
_forOf(iterable, false, function (promise) {
var $index = index++;
var alreadyCalled = false;
values.push(undefined);
remaining++;
C.resolve(promise).then(function (value) {
if (alreadyCalled) { return; }
alreadyCalled = true;
values[$index] = value;
--remaining || resolve(values);
}, reject);
});
--remaining || resolve(values);
});
if (result.e) { reject(result.v); }
return capability.promise;
},
// 25.4.4.4 Promise.race(iterable)
race: function race(iterable) {
var C = this;
var capability = newPromiseCapability(C);
var reject = capability.reject;
var result = _perform(function () {
_forOf(iterable, false, function (promise) {
C.resolve(promise).then(capability.resolve, reject);
});
});
if (result.e) { reject(result.v); }
return capability.promise;
}
});
// https://github.com/tc39/proposal-promise-finally
'use strict';
_export(_export.P + _export.R, 'Promise', { 'finally': function (onFinally) {
var C = _speciesConstructor(this, _core.Promise || _global.Promise);
var isFunction = typeof onFinally == 'function';
return this.then(
isFunction ? function (x) {
return _promiseResolve(C, onFinally()).then(function () { return x; });
} : onFinally,
isFunction ? function (e) {
return _promiseResolve(C, onFinally()).then(function () { throw e; });
} : onFinally
);
} });
'use strict';
// https://github.com/tc39/proposal-promise-try
_export(_export.S, 'Promise', { 'try': function (callbackfn) {
var promiseCapability = _newPromiseCapability.f(this);
var result = _perform(callbackfn);
(result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v);
return promiseCapability.promise;
} });
var promise$1 = _core.Promise;
var promise = createCommonjsModule(function (module) {
module.exports = { "default": promise$1, __esModule: true };
});
var _Promise = unwrapExports(promise);
// A reusable array, to avoid allocating new arrays during multiplication.
// in column-major order:
var scratch = [
/*m11*/0, /*m12*/0, /*m13*/0, /*m14*/0,
/*m21*/0, /*m22*/0, /*m23*/0, /*m24*/0,
/*m31*/0, /*m32*/0, /*m33*/0, /*m34*/0,
/*m41*/0, /*m42*/0, /*m43*/0, /*m44*/0 ];
function multiplyAndApply(A, B, target) {
//XXX: Are the following calculations faster hard coded (current), or as a loop?
scratch[0] = (A.m11 * B.m11) + (A.m21 * B.m12) + (A.m31 * B.m13) + (A.m41 * B.m14);
scratch[4] = (A.m11 * B.m21) + (A.m21 * B.m22) + (A.m31 * B.m23) + (A.m41 * B.m24);
scratch[8] = (A.m11 * B.m31) + (A.m21 * B.m32) + (A.m31 * B.m33) + (A.m41 * B.m34);
scratch[12] = (A.m11 * B.m41) + (A.m21 * B.m42) + (A.m31 * B.m43) + (A.m41 * B.m44);
scratch[1] = (A.m12 * B.m11) + (A.m22 * B.m12) + (A.m32 * B.m13) + (A.m42 * B.m14);
scratch[5] = (A.m12 * B.m21) + (A.m22 * B.m22) + (A.m32 * B.m23) + (A.m42 * B.m24);
scratch[9] = (A.m12 * B.m31) + (A.m22 * B.m32) + (A.m32 * B.m33) + (A.m42 * B.m34);
scratch[13] = (A.m12 * B.m41) + (A.m22 * B.m42) + (A.m32 * B.m43) + (A.m42 * B.m44);
scratch[2] = (A.m13 * B.m11) + (A.m23 * B.m12) + (A.m33 * B.m13) + (A.m43 * B.m14);
scratch[6] = (A.m13 * B.m21) + (A.m23 * B.m22) + (A.m33 * B.m23) + (A.m43 * B.m24);
scratch[10] = (A.m13 * B.m31) + (A.m23 * B.m32) + (A.m33 * B.m33) + (A.m43 * B.m34);
scratch[14] = (A.m13 * B.m41) + (A.m23 * B.m42) + (A.m33 * B.m43) + (A.m43 * B.m44);
scratch[3] = (A.m14 * B.m11) + (A.m24 * B.m12) + (A.m34 * B.m13) + (A.m44 * B.m14);
scratch[7] = (A.m14 * B.m21) + (A.m24 * B.m22) + (A.m34 * B.m23) + (A.m44 * B.m24);
scratch[11] = (A.m14 * B.m31) + (A.m24 * B.m32) + (A.m34 * B.m33) + (A.m44 * B.m34);
scratch[15] = (A.m14 * B.m41) + (A.m24 * B.m42) + (A.m34 * B.m43) + (A.m44 * B.m44);
applyArrayValuesToDOMMatrix(scratch, target);
}
function applyArrayValuesToDOMMatrix(array, matrix) {
var length = array.length;
if (length === 6) {
matrix.m11 = array[0];
matrix.m12 = array[1];
matrix.m21 = array[2];
matrix.m22 = array[3];
matrix.m41 = array[4];
matrix.m42 = array[5];
}
else if (length === 16) {
matrix.m11 = array[0];
matrix.m12 = array[1];
matrix.m13 = array[2];
matrix.m14 = array[3];
matrix.m21 = array[4];
matrix.m22 = array[5];
matrix.m23 = array[6];
matrix.m24 = array[7];
matrix.m31 = array[8];
matrix.m32 = array[9];
matrix.m33 = array[10];
matrix.m34 = array[11];
matrix.m41 = array[12];
matrix.m42 = array[13];
matrix.m43 = array[14];
matrix.m44 = array[15];
}
}
function rotateAxisAngleArray(x, y, z, angle) {
var sin = Math.sin;
var cos = Math.cos;
var pow = Math.pow;
var halfAngle = degreesToRadians(angle/2);
// TODO: should we provide a 6-item array here to signify 2D when the
// rotation is about the Z axis (for example when calling rotateSelf)?
// TODO: Performance can be improved by first detecting when x, y, or z of
// the axis are zero or 1, and using a pre-simplified version of the
// folowing math based on that condition.
// TODO: Performance can be improved by using different equations (use trig
// identities to find alternate formulas).
return [
1-2*(y*y + z*z)*pow(sin(halfAngle), 2), 2*(x*y*pow(sin(halfAngle), 2) + z*sin(halfAngle)*cos(halfAngle)), 2*(x*z*pow(sin(halfAngle), 2) - y*sin(halfAngle)*cos(halfAngle)), 0,
2*(x*y*pow(sin(halfAngle), 2) - z*sin(halfAngle)*cos(halfAngle)), 1-2*(x*x + z*z)*pow(sin(halfAngle), 2), 2*(y*z*pow(sin(halfAngle), 2) + x*sin(halfAngle)*cos(halfAngle)), 0,
2*(x*z*pow(sin(halfAngle), 2) + y*sin(halfAngle)*cos(halfAngle)), 2*(y*z*pow(sin(halfAngle), 2) - x*sin(halfAngle)*cos(halfAngle)), 1-2*(x*x + y*y)*pow(sin(halfAngle), 2), 0,
0, 0, 0, 1 ]
}
function degreesToRadians(degrees) {
return Math.PI/180 * degrees
}
// This matrix is represented internally in row-major format so that it is easy
// to look at visually. In a pair of coordinates (as in "m23") the first number
// is the column and the second is the row (so "m23" means column 2 row 3).
var identity = [
/*m11*/1, /*m21*/0, /*m31*/0, /*m41*/0,
/*m12*/0, /*m22*/1, /*m32*/0, /*m42*/0,
/*m13*/0, /*m23*/0, /*m33*/1, /*m43*/0,
/*m14*/0, /*m24*/0, /*m34*/0, /*m44*/1 ];
var DOMMatrixReadOnly = null;
function initDOMMatrixReadOnly() {
if (DOMMatrixReadOnly) { return }
DOMMatrixReadOnly = (function () {
function DOMMatrixReadOnly(numberSequence) {
if ( numberSequence === void 0 ) { numberSequence = []; }
if (!(this instanceof DOMMatrix))
{ throw new TypeError("DOMMatrixReadOnly can't be instantiated directly. Use DOMMatrix instead.") }
var length = numberSequence.length;
if (length === undefined || !(length === 6 || length === 16))
{ throw new TypeError('DOMMatrix constructor argument "numberSequence" must be an array-like with 6 or 16 numbers.') }
this._matrix = new Float64Array(identity);
this._isIdentity = true;
this._is2D = length === 6 ? true : false;
applyArrayValuesToDOMMatrix(numberSequence, this);
}
var prototypeAccessors = { is2D: {},isIdentity: {},a: {},b: {},c: {},d: {},e: {},f: {},m11: {},m12: {},m13: {},m14: {},m21: {},m22: {},m23: {},m24: {},m31: {},m32: {},m33: {},m34: {},m41: {},m42: {},m43: {},m44: {} };
// Immutable transform methods -------------------------------------------
DOMMatrixReadOnly.prototype.translate = function translate (tx, ty, tz) {
if ( tz === void 0 ) { tz = 0; }
return new DOMMatrix(this).translateSelf(tx, ty, tz)
};
DOMMatrixReadOnly.prototype.scale = function scale (scale$1, originX, originY) {
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
return new DOMMatrix(this).scaleSelf(scale$1, originX, originY)
};
DOMMatrixReadOnly.prototype.scale3d = function scale3d (scale, originX, originY, originZ) {
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
if ( originZ === void 0 ) { originZ = 0; }
return new DOMMatrix(this).scale3dSelf(scale, originX, originY, originZ)
};
DOMMatrixReadOnly.prototype.scaleNonUniform = function scaleNonUniform (scaleX, scaleY, scaleZ, originX, originY, originZ) {
if ( scaleY === void 0 ) { scaleY = 1; }
if ( scaleZ === void 0 ) { scaleZ = 1; }
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
if ( originZ === void 0 ) { originZ = 0; }
return new DOMMatrix(this).scaleNonUniformSelf(scaleX, scaleY, scaleZ, originX, originY, originZ)
};
DOMMatrixReadOnly.prototype.rotate = function rotate (angle, originX, originY) {
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
return new DOMMatrix(this).rotateSelf(angle, originX, originY)
};
// TODO
DOMMatrixReadOnly.prototype.rotateFromVector = function rotateFromVector (x, y) {
throw new Error('rotateFromVector is not implemented yet.')
};
DOMMatrixReadOnly.prototype.rotateAxisAngle = function rotateAxisAngle (x, y, z, angle) {
return new DOMMatrix(this).rotateAxisAngleSelf(x, y, z, angle)
};
DOMMatrixReadOnly.prototype.skewX = function skewX (sx) {
throw new Error('skewX is not implemented yet.')
};
DOMMatrixReadOnly.prototype.skewY = function skewY (sy) {
throw new Error('skewY is not implemented yet.')
};
DOMMatrixReadOnly.prototype.multiply = function multiply (other) {
return new DOMMatrix(this).multiplySelf(other)
};
DOMMatrixReadOnly.prototype.flipX = function flipX () {
throw new Error('flipX is not implemented yet.')
};
DOMMatrixReadOnly.prototype.flipY = function flipY () {
throw new Error('flipY is not implemented yet.')
};
DOMMatrixReadOnly.prototype.inverse = function inverse () {
throw new Error('inverse is not implemented yet.')
};
DOMMatrixReadOnly.prototype.transformPoint = function transformPoint (/*optional DOMPointInit*/ point) {
throw new Error('transformPoint is not implemented yet.')
};
DOMMatrixReadOnly.prototype.toFloat32Array = function toFloat32Array () {
return Float32Array.from(this._matrix)
};
DOMMatrixReadOnly.prototype.toFloat64Array = function toFloat64Array () {
return Float64Array.from(this._matrix)
};
//stringifier() {} // What's this?
prototypeAccessors.is2D.get = function () {
return this._is2D
};
/*
* TODO: make sure this matches the spec.
* TODO: Instead of calculating here, perhaps calculate and set
* this._isIdentity in other operations, and simply return the internal one
* here.
*/
prototypeAccessors.isIdentity.get = function () {
var this$1 = this;
for (var i = 0, len = this._matrix.length; i < len; i+=1) {
if (this$1._matrix[i] != identity[i])
{ return (this$1._isIdentity = false) }
}
return (this._isIdentity = true)
};
prototypeAccessors.a.get = function () { return this.m11 };
prototypeAccessors.b.get = function () { return this.m12 };
prototypeAccessors.c.get = function () { return this.m21 };
prototypeAccessors.d.get = function () { return this.m22 };
prototypeAccessors.e.get = function () { return this.m41 };
prototypeAccessors.f.get = function () { return this.m42 };
prototypeAccessors.m11.get = function () { return this._matrix[0] };
prototypeAccessors.m12.get = function () { return this._matrix[4] };
prototypeAccessors.m13.get = function () { return this._matrix[8] };
prototypeAccessors.m14.get = function () { return this._matrix[12] };
prototypeAccessors.m21.get = function () { return this._matrix[1] };
prototypeAccessors.m22.get = function () { return this._matrix[5] };
prototypeAccessors.m23.get = function () { return this._matrix[9] };
prototypeAccessors.m24.get = function () { return this._matrix[13] };
prototypeAccessors.m31.get = function () { return this._matrix[2] };
prototypeAccessors.m32.get = function () { return this._matrix[6] };
prototypeAccessors.m33.get = function () { return this._matrix[10] };
prototypeAccessors.m34.get = function () { return this._matrix[14] };
prototypeAccessors.m41.get = function () { return this._matrix[3] };
prototypeAccessors.m42.get = function () { return this._matrix[7] };
prototypeAccessors.m43.get = function () { return this._matrix[11] };
prototypeAccessors.m44.get = function () { return this._matrix[15] };
Object.defineProperties( DOMMatrixReadOnly.prototype, prototypeAccessors );
return DOMMatrixReadOnly;
}());
}
initDOMMatrixReadOnly();
initDOMMatrixReadOnly();
var DOMMatrix = (function (DOMMatrixReadOnly$$1) {
function DOMMatrix(arg) {
var numArgs = arguments.length;
if (numArgs === 0) {
DOMMatrixReadOnly$$1.call(this, [1, 0, 0, 1, 0, 0]);
}
else if (numArgs === 1) {
if (typeof arg == 'string') {
throw new Error('CSS transformList arg not yet implemented.')
// TODO validate that syntax of transformList matches transform-list (http://www.w3.org/TR/css-transforms-1/#typedef-transform-list).
}
else if (arg instanceof DOMMatrix) {
DOMMatrixReadOnly$$1.call(this, arg._matrix);
}
else if (arg instanceof Float32Array || arg instanceof Float64Array || arg instanceof Array) {
DOMMatrixReadOnly$$1.call(this, arg);
}
}
else {
throw new Error('Wrong number of arguments to DOMMatrix constructor.')
}
}
if ( DOMMatrixReadOnly$$1 ) { DOMMatrix.__proto__ = DOMMatrixReadOnly$$1; }
DOMMatrix.prototype = Object.create( DOMMatrixReadOnly$$1 && DOMMatrixReadOnly$$1.prototype );
DOMMatrix.prototype.constructor = DOMMatrix;
var prototypeAccessors = { a: {},b: {},c: {},d: {},e: {},f: {},m11: {},m12: {},m13: {},m14: {},m21: {},m22: {},m23: {},m24: {},m31: {},m32: {},m33: {},m34: {},m41: {},m42: {},m43: {},m44: {} };
// Mutable transform methods
DOMMatrix.prototype.multiplySelf = function multiplySelf (other) {
if (!(other instanceof DOMMatrix))
{ throw new Error('The argument to multiplySelf must be an instance of DOMMatrix') }
// TODO: avoid creating a new array, just apply values directly.
multiplyAndApply(this, other, this);
if (!other.is2D) { this._is2D = false; }
return this
};
DOMMatrix.prototype.preMultiplySelf = function preMultiplySelf (other) {
if (!(other instanceof DOMMatrix))
{ throw new Error('The argument to multiplySelf must be an instance of DOMMatrix') }
// TODO: avoid creating a new array, just apply values directly.
multiplyAndApply(other, this, this);
if (!other.is2D) { this._is2D = false; }
return this
};
DOMMatrix.prototype.translateSelf = function translateSelf (tx, ty, tz) {
if ( tz === void 0 ) { tz = 0; }
// TODO: check args are numbers
if (arguments.length === 1)
{ throw new Error('The first two arguments (X and Y translation values) are required (the third, Z translation, is optional).') }
// http://www.w3.org/TR/2012/WD-css3-transforms-20120911/#Translate3dDefined
var translationMatrix = new DOMMatrix([
// column-major:
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx,ty,tz,1 ]);
this.multiplySelf(translationMatrix);
if (tz != 0) {
this._is2D = false;
}
return this
};
DOMMatrix.prototype.scaleSelf = function scaleSelf (scale, originX, originY) {
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
this.translateSelf(originX, originY);
this.multiplySelf(new DOMMatrix([
// 2D:
/*a*/scale, /*b*/0,
/*c*/0, /*d*/scale,
/*e*/0, /*f*/0 ]));
this.translateSelf(-originX, -originY);
return this
};
DOMMatrix.prototype.scale3dSelf = function scale3dSelf (scale, originX, originY, originZ) {
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
if ( originZ === void 0 ) { originZ = 0; }
this.translateSelf(originX, originY, originZ);
this.multiplySelf(new DOMMatrix([
// 3D
scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, scale, 0,
0, 0, 0, 1 ]));
this.translateSelf(-originX, -originY, -originZ);
return this
};
DOMMatrix.prototype.scaleNonUniformSelf = function scaleNonUniformSelf (scaleX, scaleY, scaleZ, originX, originY, originZ) {
if ( scaleY === void 0 ) { scaleY = 1; }
if ( scaleZ === void 0 ) { scaleZ = 1; }
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
if ( originZ === void 0 ) { originZ = 0; }
this.translateSelf(originX, originY, originZ);
this.multiplySelf(new DOMMatrix([
// 3D
scaleX, 0, 0, 0,
0, scaleY, 0, 0,
0, 0, scaleZ, 0,
0, 0, 0, 1 ]));
this.translateSelf(-originX, -originY, -originZ);
if (scaleZ !== 1 || originZ !== 0) { this._is2D = false; }
return this
};
DOMMatrix.prototype.rotateSelf = function rotateSelf (angle, originX, originY) {
if ( originX === void 0 ) { originX = 0; }
if ( originY === void 0 ) { originY = 0; }
this.translateSelf(originX, originY);
// axis of rotation
var ref = [0,0,1];
var x = ref[0];
var y = ref[1];
var z = ref[2]; // We're rotating around the Z axis.
this.rotateAxisAngleSelf(x, y, z, angle);
this.translateSelf(-originX, -originY);
return this
};
// TODO
DOMMatrix.prototype.rotateFromVectorSelf = function rotateFromVectorSelf (x, y) {
throw new Error('rotateFromVectorSelf is not implemented yet.')
};
DOMMatrix.prototype.rotateAxisAngleSelf = function rotateAxisAngleSelf (x, y, z, angle) {
var rotationMatrix = new DOMMatrix(rotateAxisAngleArray(x,y,z,angle));
this.multiplySelf(rotationMatrix);
return this
};
DOMMatrix.prototype.skewXSelf = function skewXSelf (sx) {
throw new Error('skewXSelf is not implemented yet.')
};
DOMMatrix.prototype.skewYSelf = function skewYSelf (sy) {
throw new Error('skewYSelf is not implemented yet.')
};
DOMMatrix.prototype.invertSelf = function invertSelf () {
throw new Error('invertSelf is not implemented yet.')
};
DOMMatrix.prototype.setMatrixValue = function setMatrixValue (/*DOMString*/ transformList) {
throw new Error('setMatrixValue is not implemented yet.')
};
prototypeAccessors.a.get = function () { return this.m11 };
prototypeAccessors.b.get = function () { return this.m12 };
prototypeAccessors.c.get = function () { return this.m21 };
prototypeAccessors.d.get = function () { return this.m22 };
prototypeAccessors.e.get = function () { return this.m41 };
prototypeAccessors.f.get = function () { return this.m42 };
prototypeAccessors.m11.get = function () { return this._matrix[0] };
prototypeAccessors.m12.get = function () { return this._matrix[4] };
prototypeAccessors.m13.get = function () { return this._matrix[8] };
prototypeAccessors.m14.get = function () { return this._matrix[12] };
prototypeAccessors.m21.get = function () { return this._matrix[1] };
prototypeAccessors.m22.get = function () { return this._matrix[5] };
prototypeAccessors.m23.get = function () { return this._matrix[9] };
prototypeAccessors.m24.get = function () { return this._matrix[13] };
prototypeAccessors.m31.get = function () { return this._matrix[2] };
prototypeAccessors.m32.get = function () { return this._matrix[6] };
prototypeAccessors.m33.get = function () { return this._matrix[10] };
prototypeAccessors.m34.get = function () { return this._matrix[14] };
prototypeAccessors.m41.get = function () { return this._matrix[3] };
prototypeAccessors.m42.get = function () { return this._matrix[7] };
prototypeAccessors.m43.get = function () { return this._matrix[11] };
prototypeAccessors.m44.get = function () { return this._matrix[15] };
prototypeAccessors.a.set = function (value) { this.m11 = value; };
prototypeAccessors.b.set = function (value) { this.m12 = value; };
prototypeAccessors.c.set = function (value) { this.m21 = value; };
prototypeAccessors.d.set = function (value) { this.m22 = value; };
prototypeAccessors.e.set = function (value) { this.m41 = value; };
prototypeAccessors.f.set = function (value) { this.m42 = value; };
prototypeAccessors.m11.set = function (value) { this._matrix[0] = value; };
prototypeAccessors.m12.set = function (value) { this._matrix[4] = value; };
prototypeAccessors.m13.set = function (value) { this._matrix[8] = value; };
prototypeAccessors.m14.set = function (value) { this._matrix[12] = value; };
prototypeAccessors.m21.set = function (value) { this._matrix[1] = value; };
prototypeAccessors.m22.set = function (value) { this._matrix[5] = value; };
prototypeAccessors.m23.set = function (value) { this._matrix[9] = value; };
prototypeAccessors.m24.set = function (value) { this._matrix[13] = value; };
prototypeAccessors.m31.set = function (value) { this._matrix[2] = value; };
prototypeAccessors.m32.set = function (value) { this._matrix[6] = value; };
prototypeAccessors.m33.set = function (value) { this._matrix[10] = value; };
prototypeAccessors.m34.set = function (value) { this._matrix[14] = value; };
prototypeAccessors.m41.set = function (value) { this._matrix[3] = value; };
prototypeAccessors.m42.set = function (value) { this._matrix[7] = value; };
prototypeAccessors.m43.set = function (value) { this._matrix[11] = value; };
prototypeAccessors.m44.set = function (value) { this._matrix[15] = value; };
Object.defineProperties( DOMMatrix.prototype, prototypeAccessors );
return DOMMatrix;
}(DOMMatrixReadOnly));
var privatesMap;
var _ = function (o) {
if (!privatesMap) {
privatesMap = new WeakMap;
var privates = {};
privatesMap.set(o, privates);
return privates
}
else {
var privates$1 = privatesMap.get(o);
if (privates$1 === undefined) {
privates$1 = {};
privatesMap.set(o, privates$1);
}
return privates$1
}
};
var DOMPointReadOnly = function DOMPointReadOnly(x,y,z,w) {
if (arguments.length === 1) {
if (!isDOMPointInit(x))
{ throw new TypeError('Expected an object with x, y, z, and w properties') }
_(this).x = x.x;
_(this).y = x.y;
_(this).z = x.z;
_(this).w = x.w;
}
else if (arguments.length === 4) {
_(this).x = x || 0;
_(this).y = y || 0;
_(this).z = z || 0;
_(this).w = w || 0;
}
else {
throw new TypeError('Expected 1 or 4 arguments')
}
};
var prototypeAccessors = { x: {},y: {},z: {},w: {} };
prototypeAccessors.x.get = function () { return _(this).x };
prototypeAccessors.y.get = function () { return _(this).y };
prototypeAccessors.z.get = function () { return _(this).z };
prototypeAccessors.w.get = function () { return _(this).w };
DOMPointReadOnly.prototype.matrixTransform = function matrixTransform (matrix) {
var result = new this.constructor(this);
// TODO
//const x
//const y
//const z
//const w
return result
};
DOMPointReadOnly.fromPoint = function fromPoint (other) {
return new this(other)
};
Object.defineProperties( DOMPointReadOnly.prototype, prototypeAccessors );
var DOMPoint = (function (DOMPointReadOnly) {
function DOMPoint () {
DOMPointReadOnly.apply(this, arguments);
}
if ( DOMPointReadOnly ) { DOMPoint.__proto__ = DOMPointReadOnly; }
DOMPoint.prototype = Object.create( DOMPointReadOnly && DOMPointReadOnly.prototype );
DOMPoint.prototype.constructor = DOMPoint;
var prototypeAccessors$1 = { x: {},y: {},z: {},w: {} };
prototypeAccessors$1.x.set = function (value) { _(this).x = value; };
prototypeAccessors$1.y.set = function (value) { _(this).y = value; };
prototypeAccessors$1.z.set = function (value) { _(this).z = value; };
prototypeAccessors$1.w.set = function (value) { _(this).w = value; };
Object.defineProperties( DOMPoint.prototype, prototypeAccessors$1 );
return DOMPoint;
}(DOMPointReadOnly));
function isDOMPointInit(o) {
if (typeof o != 'object') { return false }
if (
'x' in o &&
'y' in o &&
'z' in o &&
'w' in o
) { return true }
return false
}
var _global$2 = null;
// browser
if (typeof window != 'undefined') {
_global$2 = window;
}
else if (typeof global != 'undefined') {
_global$2 = global;
}
if (_global$2) {
_global$2.DOMMatrix = DOMMatrix;
_global$2.DOMMatrixReadOnly = DOMMatrixReadOnly;
_global$2.DOMPoint = DOMPoint;
_global$2.DOMPointReadOnly = DOMPointReadOnly;
}
// 7.2.9 SameValue(x, y)
var _sameValue = Object.is || function is(x, y) {
// eslint-disable-next-line no-self-compare
return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
};
// 19.1.3.10 Object.is(value1, value2)
_export(_export.S, 'Object', { is: _sameValue });
var is$2 = _core.Object.is;
var is$1 = createCommonjsModule(function (module) {
module.exports = { "default": is$2, __esModule: true };
});
var _Object$is = unwrapExports(is$1);
'use strict';
// 19.1.2.1 Object.assign(target, source, ...)
var $assign = Object.assign;
// should work with symbols and should have deterministic property order (V8 bug)
var _objectAssign = !$assign || _fails(function () {
var A = {};
var B = {};
// eslint-disable-next-line no-undef
var S = Symbol();
var K = 'abcdefghijklmnopqrst';
A[S] = 7;
K.split('').forEach(function (k) { B[k] = k; });
return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
}) ? function assign(target, source) {
var arguments$1 = arguments;
// eslint-disable-line no-unused-vars
var T = _toObject(target);
var aLen = arguments.length;
var index = 1;
var getSymbols = _objectGops.f;
var isEnum = _objectPie.f;
while (aLen > index) {
var S = _iobject(arguments$1[index++]);
var keys = getSymbols ? _objectKeys(S).concat(getSymbols(S)) : _objectKeys(S);
var length = keys.length;
var j = 0;
var key;
while (length > j) { if (isEnum.call(S, key = keys[j++])) { T[key] = S[key]; } }
} return T;
} : $assign;
// 19.1.3.1 Object.assign(target, source)
_export(_export.S + _export.F, 'Object', { assign: _objectAssign });
var assign$1 = _core.Object.assign;
var assign = createCommonjsModule(function (module) {
module.exports = { "default": assign$1, __esModule: true };
});
var _Object$assign = unwrapExports(assign);
var set$1 = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _getPrototypeOf2 = _interopRequireDefault(getPrototypeOf);
var _getOwnPropertyDescriptor2 = _interopRequireDefault(getOwnPropertyDescriptor);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function set(object, property, value, receiver) {
var desc = (0, _getOwnPropertyDescriptor2.default)(object, property);
if (desc === undefined) {
var parent = (0, _getPrototypeOf2.default)(object);
if (parent !== null) {
set(parent, property, value, receiver);
}
} else if ("value" in desc && desc.writable) {
desc.value = value;
} else {
var setter = desc.set;
if (setter !== undefined) {
setter.call(receiver, value);
}
}
return value;
};
});
var _set = unwrapExports(set$1);
var _validateCollection = function (it, TYPE) {
if (!_isObject(it) || it._t !== TYPE) { throw TypeError('Incompatible receiver, ' + TYPE + ' required!'); }
return it;
};
'use strict';
var dP$2 = _objectDp.f;
var fastKey = _meta.fastKey;
var SIZE = _descriptors ? '_s' : 'size';
var getEntry = function (that, key) {
// fast case
var index = fastKey(key);
var entry;
if (index !== 'F') { return that._i[index]; }
// frozen object case
for (entry = that._f; entry; entry = entry.n) {
if (entry.k == key) { return entry; }
}
};
var _collectionStrong = {
getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {
var C = wrapper(function (that, iterable) {
_anInstance(that, C, NAME, '_i');
that._t = NAME; // collection type
that._i = _objectCreate(null); // index
that._f = undefined; // first entry
that._l = undefined; // last entry
that[SIZE] = 0; // size
if (iterable != undefined) { _forOf(iterable, IS_MAP, that[ADDER], that); }
});
_redefineAll(C.prototype, {
// 23.1.3.1 Map.prototype.clear()
// 23.2.3.2 Set.prototype.clear()
clear: function clear() {
for (var that = _validateCollection(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {
entry.r = true;
if (entry.p) { entry.p = entry.p.n = undefined; }
delete data[entry.i];
}
that._f = that._l = undefined;
that[SIZE] = 0;
},
// 23.1.3.3 Map.prototype.delete(key)
// 23.2.3.4 Set.prototype.delete(value)
'delete': function (key) {
var that = _validateCollection(this, NAME);
var entry = getEntry(that, key);
if (entry) {
var next = entry.n;
var prev = entry.p;
delete that._i[entry.i];
entry.r = true;
if (prev) { prev.n = next; }
if (next) { next.p = prev; }
if (that._f == entry) { that._f = next; }
if (that._l == entry) { that._l = prev; }
that[SIZE]--;
} return !!entry;
},
// 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
// 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
forEach: function forEach(callbackfn /* , that = undefined */) {
var this$1 = this;
_validateCollection(this, NAME);
var f = _ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);
var entry;
while (entry = entry ? entry.n : this._f) {
f(entry.v, entry.k, this$1);
// revert to the last existing entry
while (entry && entry.r) { entry = entry.p; }
}
},
// 23.1.3.7 Map.prototype.has(key)
// 23.2.3.7 Set.prototype.has(value)
has: function has(key) {
return !!getEntry(_validateCollection(this, NAME), key);
}
});
if (_descriptors) { dP$2(C.prototype, 'size', {
get: function () {
return _validateCollection(this, NAME)[SIZE];
}
}); }
return C;
},
def: function (that, key, value) {
var entry = getEntry(that, key);
var prev, index;
// change existing entry
if (entry) {
entry.v = value;
// create new entry
} else {
that._l = entry = {
i: index = fastKey(key, true), // <- index
k: key, // <- key
v: value, // <- value
p: prev = that._l, // <- previous entry
n: undefined, // <- next entry
r: false // <- removed
};
if (!that._f) { that._f = entry; }
if (prev) { prev.n = entry; }
that[SIZE]++;
// add to index
if (index !== 'F') { that._i[index] = entry; }
} return that;
},
getEntry: getEntry,
setStrong: function (C, NAME, IS_MAP) {
// add .keys, .values, .entries, [@@iterator]
// 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
_iterDefine(C, NAME, function (iterated, kind) {
this._t = _validateCollection(iterated, NAME); // target
this._k = kind; // kind
this._l = undefined; // previous
}, function () {
var that = this;
var kind = that._k;
var entry = that._l;
// revert to the last existing entry
while (entry && entry.r) { entry = entry.p; }
// get next entry
if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {
// or finish the iteration
that._t = undefined;
return _iterStep(1);
}
// return step by kind
if (kind == 'keys') { return _iterStep(0, entry.k); }
if (kind == 'values') { return _iterStep(0, entry.v); }
return _iterStep(0, [entry.k, entry.v]);
}, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
// add [@@species], 23.1.2.2, 23.2.2.2
_setSpecies(NAME);
}
};
var SPECIES$2 = _wks('species');
var _arraySpeciesConstructor = function (original) {
var C;
if (_isArray(original)) {
C = original.constructor;
// cross-realm fallback
if (typeof C == 'function' && (C === Array || _isArray(C.prototype))) { C = undefined; }
if (_isObject(C)) {
C = C[SPECIES$2];
if (C === null) { C = undefined; }
}
} return C === undefined ? Array : C;
};
// 9.4.2.3 ArraySpeciesCreate(originalArray, length)
var _arraySpeciesCreate = function (original, length) {
return new (_arraySpeciesConstructor(original))(length);
};
// 0 -> Array#forEach
// 1 -> Array#map
// 2 -> Array#filter
// 3 -> Array#some
// 4 -> Array#every
// 5 -> Array#find
// 6 -> Array#findIndex
var _arrayMethods = function (TYPE, $create) {
var IS_MAP = TYPE == 1;
var IS_FILTER = TYPE == 2;
var IS_SOME = TYPE == 3;
var IS_EVERY = TYPE == 4;
var IS_FIND_INDEX = TYPE == 6;
var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
var create = $create || _arraySpeciesCreate;
return function ($this, callbackfn, that) {
var O = _toObject($this);
var self = _iobject(O);
var f = _ctx(callbackfn, that, 3);
var length = _toLength(self.length);
var index = 0;
var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
var val, res;
for (;length > index; index++) { if (NO_HOLES || index in self) {
val = self[index];
res = f(val, index, O);
if (TYPE) {
if (IS_MAP) { result[index] = res; } // map
else if (res) { switch (TYPE) {
case 3: return true; // some
case 5: return val; // find
case 6: return index; // findIndex
case 2: result.push(val); // filter
} } else if (IS_EVERY) { return false; } // every
}
} }
return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
};
};
'use strict';
var dP$3 = _objectDp.f;
var each = _arrayMethods(0);
var _collection = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
var Base = _global[NAME];
var C = Base;
var ADDER = IS_MAP ? 'set' : 'add';
var proto = C && C.prototype;
var O = {};
if (!_descriptors || typeof C != 'function' || !(IS_WEAK || proto.forEach && !_fails(function () {
new C().entries().next();
}))) {
// create collection constructor
C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
_redefineAll(C.prototype, methods);
_meta.NEED = true;
} else {
C = wrapper(function (target, iterable) {
_anInstance(target, C, NAME, '_c');
target._c = new Base();
if (iterable != undefined) { _forOf(iterable, IS_MAP, target[ADDER], target); }
});
each('add,clear,delete,forEach,get,has,set,keys,values,entries,toJSON'.split(','), function (KEY) {
var IS_ADDER = KEY == 'add' || KEY == 'set';
if (KEY in proto && !(IS_WEAK && KEY == 'clear')) { _hide(C.prototype, KEY, function (a, b) {
_anInstance(this, C, KEY);
if (!IS_ADDER && IS_WEAK && !_isObject(a)) { return KEY == 'get' ? undefined : false; }
var result = this._c[KEY](a === 0 ? 0 : a, b);
return IS_ADDER ? this : result;
}); }
});
IS_WEAK || dP$3(C.prototype, 'size', {
get: function () {
return this._c.size;
}
});
}
_setToStringTag(C, NAME);
O[NAME] = C;
_export(_export.G + _export.W + _export.F, O);
if (!IS_WEAK) { common.setStrong(C, NAME, IS_MAP); }
return C;
};
'use strict';
var MAP = 'Map';
// 23.1 Map Objects
var es6_map = _collection(MAP, function (get) {
return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };
}, {
// 23.1.3.6 Map.prototype.get(key)
get: function get(key) {
var entry = _collectionStrong.getEntry(_validateCollection(this, MAP), key);
return entry && entry.v;
},
// 23.1.3.9 Map.prototype.set(key, value)
set: function set(key, value) {
return _collectionStrong.def(_validateCollection(this, MAP), key === 0 ? 0 : key, value);
}
}, _collectionStrong, true);
var _arrayFromIterable = function (iter, ITERATOR) {
var result = [];
_forOf(iter, false, result.push, result, ITERATOR);
return result;
};
// https://github.com/DavidBruant/Map-Set.prototype.toJSON
var _collectionToJson = function (NAME) {
return function toJSON() {
if (_classof(this) != NAME) { throw TypeError(NAME + "#toJSON isn't generic"); }
return _arrayFromIterable(this);
};
};
// https://github.com/DavidBruant/Map-Set.prototype.toJSON
_export(_export.P + _export.R, 'Map', { toJSON: _collectionToJson('Map') });
'use strict';
// https://tc39.github.io/proposal-setmap-offrom/
var _setCollectionOf = function (COLLECTION) {
_export(_export.S, COLLECTION, { of: function of() {
var arguments$1 = arguments;
var length = arguments.length;
var A = Array(length);
while (length--) { A[length] = arguments$1[length]; }
return new this(A);
} });
};
// https://tc39.github.io/proposal-setmap-offrom/#sec-map.of
_setCollectionOf('Map');
'use strict';
// https://tc39.github.io/proposal-setmap-offrom/
var _setCollectionFrom = function (COLLECTION) {
_export(_export.S, COLLECTION, { from: function from(source /* , mapFn, thisArg */) {
var mapFn = arguments[1];
var mapping, A, n, cb;
_aFunction(this);
mapping = mapFn !== undefined;
if (mapping) { _aFunction(mapFn); }
if (source == undefined) { return new this(); }
A = [];
if (mapping) {
n = 0;
cb = _ctx(mapFn, arguments[2], 2);
_forOf(source, false, function (nextItem) {
A.push(cb(nextItem, n++));
});
} else {
_forOf(source, false, A.push, A);
}
return new this(A);
} });
};
// https://tc39.github.io/proposal-setmap-offrom/#sec-map.from
_setCollectionFrom('Map');
var map$1 = _core.Map;
var map = createCommonjsModule(function (module) {
module.exports = { "default": map$1, __esModule: true };
});
var _Map = unwrapExports(map);
var instanceofSymbol$2 = _Symbol('instanceofSymbol');
var ObservableMixin = function (base) {
var Observable = function (_base) {
_inherits(Observable, _base);
function Observable() {
_classCallCheck(this, Observable);
return _possibleConstructorReturn(this, (Observable.__proto__ || _Object$getPrototypeOf(Observable)).apply(this, arguments));
}
_createClass(Observable, [{
key: 'construct',
value: function construct() {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
(ref = _get(Observable.prototype.__proto__ || _Object$getPrototypeOf(Observable.prototype), 'construct', this)).call.apply(ref, [ this ].concat( args ));
var ref;
}
}, {
key: 'on',
value: function on(eventName, callback) {
if (!this._eventMap) { this._eventMap = new _Map(); }
if (!this._eventMap.has(eventName)) { this._eventMap.set(eventName, []); }
if (typeof callback == 'function') { this._eventMap.get(eventName).push(callback); }else { throw new Error('Expected a function in callback argument of Observable#on.'); }
}
}, {
key: 'off',
value: function off(eventName, callback) {
if (!this._eventMap || !this._eventMap.has(eventName)) { return; }
var callbacks = this._eventMap.get(eventName);
if (callbacks.indexOf(callback) === -1) { return; }
callbacks.splice(callbacks.indexOf(callback), 1);
if (callbacks.length === 0) { this._eventMap.delete(eventName); }
if (this._eventMap.size === 0) { this._eventMap = null; }
}
}, {
key: 'trigger',
value: function trigger(eventName, data) {
if (!this._eventMap || !this._eventMap.has(eventName)) { return; }
var callbacks = this._eventMap.get(eventName);
for (var i = 0, len = callbacks.length; i < len; i += 1) {
callbacks[i](data);
}
}
}, {
key: 'triggerEvent',
value: function triggerEvent() {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (ref = this).trigger.apply(ref, args);
var ref;
}
}]);
return Observable;
}(base);
_Object$defineProperty(Observable, _Symbol$hasInstance, {
value: function (obj) {
if (this !== Observable) { return _Object$getPrototypeOf(Observable)[_Symbol$hasInstance].call(this, obj); }
var currentProto = obj;
while (currentProto) {
var desc = _Object$getOwnPropertyDescriptor(currentProto, "constructor");
if (desc && desc.value && desc.value.hasOwnProperty(instanceofSymbol$2)) { return true; }
currentProto = _Object$getPrototypeOf(currentProto);
}
return false;
}
});
Observable[instanceofSymbol$2] = true;
return Observable;
};
var Observable = ObservableMixin(function () {
function _class() {
_classCallCheck(this, _class);
}
return _class;
}());
Observable.mixin = ObservableMixin;
/**
* Represents a set of values for the X, Y, and Z axes. For example, the
* position of an object can be described using a set of 3 numbers, one for each
* axis in 3D space: {x:10, y:10, z:10}.
*
* The value don't have to be numerical. For example,
* {x:'foo', y:'bar', z:'baz'}
*/
var XYZValues = function (_Observable) {
_inherits(XYZValues, _Observable);
function XYZValues(x, y, z) {
if ( x === void 0 ) x = 0;
if ( y === void 0 ) y = 0;
if ( z === void 0 ) z = 0;
_classCallCheck(this, XYZValues);
var _this = _possibleConstructorReturn(this, (XYZValues.__proto__ || _Object$getPrototypeOf(XYZValues)).call(this));
_this._x = x;
_this._y = y;
_this._z = z;
return _this;
}
_createClass(XYZValues, [{
key: 'x',
set: function (value) {
this._x = value;
this.trigger('valuechanged', { x: value });
},
get: function () {
return this._x;
}
}, {
key: 'y',
set: function (value) {
this._y = value;
this.trigger('valuechanged', { y: value });
},
get: function () {
return this._y;
}
}, {
key: 'z',
set: function (value) {
this._z = value;
this.trigger('valuechanged', { z: value });
},
get: function () {
return this._z;
}
}]);
return XYZValues;
}(Observable);
var _extends = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _assign2 = _interopRequireDefault(assign);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = _assign2.default || function (target) {
var arguments$1 = arguments;
for (var i = 1; i < arguments.length; i++) {
var source = arguments$1[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
});
var _extends$1 = unwrapExports(_extends);
'use strict';
var _createProperty = function (object, index, value) {
if (index in object) { _objectDp.f(object, index, _propertyDesc(0, value)); }
else { object[index] = value; }
};
'use strict';
_export(_export.S + _export.F * !_iterDetect(function (iter) { }), 'Array', {
// 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)
from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
var O = _toObject(arrayLike);
var C = typeof this == 'function' ? this : Array;
var aLen = arguments.length;
var mapfn = aLen > 1 ? arguments[1] : undefined;
var mapping = mapfn !== undefined;
var index = 0;
var iterFn = core_getIteratorMethod(O);
var length, result, step, iterator;
if (mapping) { mapfn = _ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); }
// if object isn't iterable or it's array with default iterator - use simple case
if (iterFn != undefined && !(C == Array && _isArrayIter(iterFn))) {
for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {
_createProperty(result, index, mapping ? _iterCall(iterator, mapfn, [step.value, index], true) : step.value);
}
} else {
length = _toLength(O.length);
for (result = new C(length); length > index; index++) {
_createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);
}
}
result.length = index;
return result;
}
});
var from$2 = _core.Array.from;
var from$1 = createCommonjsModule(function (module) {
module.exports = { "default": from$2, __esModule: true };
});
var _Array$from = unwrapExports(from$1);
// 19.1.2.7 Object.getOwnPropertyNames(O)
_objectSap('getOwnPropertyNames', function () {
return _objectGopnExt.f;
});
var $Object$3 = _core.Object;
var getOwnPropertyNames$1 = function getOwnPropertyNames(it) {
return $Object$3.getOwnPropertyNames(it);
};
var getOwnPropertyNames = createCommonjsModule(function (module) {
module.exports = { "default": getOwnPropertyNames$1, __esModule: true };
});
var _Object$getOwnPropertyNames = unwrapExports(getOwnPropertyNames);
function epsilon(value) {
return Math.abs(value) < 0.000001 ? 0 : value;
}
function applyCSSLabel(value, label) {
if (value === 0) {
return '0px';
} else if (label === '%') {
return value * 100 + '%';
} else if (label === 'px') {
return value + 'px';
}
}
function animationFrame() {
var resolve = null;
var promise$$1 = new _Promise(function (r) { return resolve = r; });
window.requestAnimationFrame(resolve);
return promise$$1;
}
// Create lowercase versions of each setter property.
// we care only about the setters, for now.
function makeLowercaseSetterAliases(object) {
var props = _Object$getOwnPropertyNames(object);
for (var l = props.length, i = 0; i < l; i += 1) {
var prop = props[i];
var lowercaseProp = prop.toLowerCase();
if (lowercaseProp != prop) {
var descriptor = _Object$getOwnPropertyDescriptor(object, prop);
if (typeof descriptor.set != 'undefined') {
_Object$defineProperty(object, lowercaseProp, descriptor);
}
}
}
}
var childObservationHandlers = null;
var childObserver = null;
function observeChildren(ctx, onConnect, onDisconnect) {
// TODO this Map is never cleaned, leaks memory.
if (!childObservationHandlers) { childObservationHandlers = new _Map(); }
if (!childObserver) { childObserver = createChildObserver(); }
childObservationHandlers.set(ctx, { onConnect: onConnect, onDisconnect: onDisconnect });
childObserver.observe(ctx, { childList: true });
return true;
}
// NOTE: If a child is disconnected then connected to the same parent in the
// same turn, then the onConnect and onDisconnect callbacks won't be called
// because the DOM tree will be back in the exact state as before (this is
// possible thanks to the logic associated with weightsPerTarget).
function createChildObserver() {
return new MutationObserver(function (changes) {
var weightsPerTarget = new _Map();
// We're just counting how many times each child node was added and
// removed from the parent we're observing.
for (var i = 0, l = changes.length; i < l; i += 1) {
var change = changes[i];
if (change.type != 'childList') { continue; }
if (!weightsPerTarget.has(change.target)) { weightsPerTarget.set(change.target, new _Map()); }
var weights = weightsPerTarget.get(change.target);
var addedNodes = change.addedNodes;
for (var l$1 = addedNodes.length, i$1 = 0; i$1 < l$1; i$1 += 1) { weights.set(addedNodes[i$1], (weights.get(addedNodes[i$1]) || 0) + 1); }
var removedNodes = change.removedNodes;
for (var l$2 = removedNodes.length, i$2 = 0; i$2 < l$2; i$2 += 1) { weights.set(removedNodes[i$2], (weights.get(removedNodes[i$2]) || 0) - 1); }
}
for (var i$3 = 0, list = _Array$from(weightsPerTarget); i$3 < list.length; i$3 += 1) {
var ref = list[i$3];
var target = ref[0];
var weights$1 = ref[1];
var ref$1 = childObservationHandlers.get(target);
var onConnect = ref$1.onConnect;
var onDisconnect = ref$1.onDisconnect;
for (var i$4 = 0, list$1 = _Array$from(weights$1); i$4 < list$1.length; i$4 += 1) {
// If the number of times a child was added is greater than the
// number of times it was removed, then the net result is that
// it was added, so we call onConnect just once.
var ref$2 = list$1[i$4];
var node = ref$2[0];
var weight = ref$2[1];
if (weight > 0 && typeof onConnect == 'function') { onConnect.call(target, node); }
// If the number of times a child was added is less than the
// number of times it was removed, then the net result is that
// it was removed, so we call onConnect just once.
else if (weight < 0 && typeof onDisconnect == 'function') { onDisconnect.call(target, node); }
// If the number of times a child was added is equal to the
// number of times it was removed, then it was essentially left
// in place, so we don't call anything.
}
}
});
}
var hasShadowDomV0 = typeof Element.prototype.createShadowRoot == 'function' && typeof HTMLContentElement == 'function' ? true : false;
var hasShadowDomV1 = typeof Element.prototype.attachShadow == 'function' && typeof HTMLSlotElement == 'function' ? true : false;
function getShadowRootVersion(shadowRoot) {
console.log('getShadowRootVersion');
if (!shadowRoot) { return null; }
var slot = document.createElement('slot');
shadowRoot.appendChild(slot);
slot.appendChild(document.createElement('div'));
var assignedNodes = slot.assignedNodes({ flatten: true });
slot.remove();
console.log('hmm', assignedNodes.length, assignedNodes.length > 0 ? 'v1' : 'v0');
return assignedNodes.length > 0 ? 'v1' : 'v0';
}
function getAncestorShadowRoot(node) {
var current = node;
while (current && !(current instanceof ShadowRoot)) {
current = current.parentNode;
}
return current;
}
// in the future, the user will be able to toggle the HTML API.
var hasHtmlApi = true;
// Traverses a tree while considering ShadowDOM disribution.
function traverse(node, isShadowChild) {
console.log(isShadowChild ? 'distributedNode:' : 'node:', node);
var children = node.children;
for (var l = children.length, i = 0; i < l; i += 1) {
// skip nodes that are possiblyDistributed, i.e. they have a parent
// that has a ShadowRoot.
if (!hasHtmlApi || !children[i]._isPossiblyDistributed) { traverse(children[i]); }
}
var shadowChildren = node._shadowChildren;
if (hasHtmlApi && shadowChildren) {
for (var l$1 = shadowChildren.length, i$1 = 0; i$1 < l$1; i$1 += 1) { traverse(shadowChildren[i$1], true); }
}
}
// helper function to use instead of instanceof for classes that implement the
// static Symbol.hasInstance method, because the behavior of instanceof isn't
// polyfillable.
function isInstanceof(lhs, rhs) {
if (typeof rhs == 'function' && rhs[_Symbol$hasInstance]) { return rhs[_Symbol$hasInstance](lhs); }else { return lhs instanceof rhs; }
}
var Utility$2 = Object.freeze({
epsilon: epsilon,
applyCSSLabel: applyCSSLabel,
animationFrame: animationFrame,
makeLowercaseSetterAliases: makeLowercaseSetterAliases,
observeChildren: observeChildren,
getShadowRootVersion: getShadowRootVersion,
hasShadowDomV0: hasShadowDomV0,
hasShadowDomV1: hasShadowDomV1,
getAncestorShadowRoot: getAncestorShadowRoot,
traverse: traverse,
isInstanceof: isInstanceof
});
var instanceofSymbol$4 = _Symbol('instanceofSymbol');
var TreeNodeMixin = function (base) {
var TreeNode = function (_base) {
_inherits(TreeNode, _base);
function TreeNode() {
_classCallCheck(this, TreeNode);
return _possibleConstructorReturn(this, (TreeNode.__proto__ || _Object$getPrototypeOf(TreeNode)).apply(this, arguments));
}
_createClass(TreeNode, [{
key: 'construct',
value: function construct() {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
(ref = _get(TreeNode.prototype.__proto__ || _Object$getPrototypeOf(TreeNode.prototype), 'construct', this)).call.apply(ref, [ this ].concat( args ));
this._parent = null; // default to no parent.
this._children = [];
var ref;
}
/**
* this._parent is protected (node's can access other node._parent).
* The user should use the add() method, which automatically handles
* setting a parent.
*
* @readonly
*/
}, {
key: 'add',
/**
* Add a child node to this TreeNode.
*
* @param {TreeNode} childNode The child node to add.
*/
value: function add(childNode) {
var this$1 = this;
if (!isInstanceof(childNode, TreeNode)) { throw new TypeError('TreeNode.add() expects the childNode argument to be a TreeNode instance.'); }
if (childNode._parent === this) { throw new ReferenceError('childNode is already a child of this parent.'); }
if (childNode._parent) { childNode._parent.remove(childNode); }
childNode._parent = this;
this._children.push(childNode);
_Promise.resolve().then(function () {
childNode.connected();
this$1.childConnected(childNode);
});
return this;
}
/**
* Add all the child nodes in the given array to this node.
*
* @param {Array.TreeNode} nodes The nodes to add.
*/
}, {
key: 'addChildren',
value: function addChildren(nodes) {
var this$1 = this;
nodes.forEach(function (node) { return this$1.add()(node); });
return this;
}
/**
* Remove a child node from this node.
*
* @param {TreeNode} childNode The node to remove.
*/
}, {
key: 'remove',
value: function remove(childNode) {
var this$1 = this;
if (!isInstanceof(childNode, TreeNode)) { throw new Error("\n TreeNode.remove expects the childNode argument to be an\n instance of TreeNode. There should only be TreeNodes in the\n tree.\n "); }
if (childNode._parent !== this) { throw new ReferenceError('childNode is not a child of this parent.'); }
childNode._parent = null;
this._children.splice(this._children.indexOf(childNode), 1);
_Promise.resolve().then(function () {
childNode.disconnected();
this$1.childDisconnected(childNode);
});
return this;
}
/**
* Remove all the child nodes in the given array from this node.
*
* @param {Array.TreeNode} nodes The nodes to remove.
*/
}, {
key: 'removeChildren',
value: function removeChildren(nodes) {
var this$1 = this;
nodes.forEach(function (node) { return this$1.remove(node); });
return this;
}
/**
* Shortcut to remove all children.
*/
}, {
key: 'removeAllChildren',
value: function removeAllChildren() {
this.removeChildren(this._children);
return this;
}
/**
* @readonly
* @return {number} How many children this TreeNode has.
*/
}, {
key: 'connected',
// generic life cycle methods
value: function connected() {}
}, {
key: 'disconnected',
value: function disconnected() {}
}, {
key: 'childConnected',
value: function childConnected(child) {}
}, {
key: 'childDisconnected',
value: function childDisconnected(child) {}
}, {
key: 'propertyChanged',
value: function propertyChanged() {}
}, {
key: 'parent',
get: function () {
return this._parent;
}
/**
* Named "subnodes" to avoid conflict with HTML Elements' "children"
* @readonly
*/
}, {
key: 'subnodes',
get: function () {
// return a new array, so that the user modifying it doesn't affect
// this node's actual children.
return [].concat( this._children );
}
}, {
key: 'childCount',
get: function () {
return this._children.length;
}
}]);
return TreeNode;
}(base);
_Object$defineProperty(TreeNode, _Symbol$hasInstance, {
value: function (obj) {
if (this !== TreeNode) { return _Object$getPrototypeOf(TreeNode)[_Symbol$hasInstance].call(this, obj); }
var currentProto = obj;
while (currentProto) {
var desc = _Object$getOwnPropertyDescriptor(currentProto, "constructor");
if (desc && desc.value && desc.value.hasOwnProperty(instanceofSymbol$4)) { return true; }
currentProto = _Object$getPrototypeOf(currentProto);
}
return false;
}
});
TreeNode[instanceofSymbol$4] = true;
return TreeNode;
};
var TreeNode = TreeNodeMixin(function () {
function _class() {
_classCallCheck(this, _class);
}
return _class;
}());
TreeNode.mixin = TreeNodeMixin;
var XYZNonNegativeValues = function (_XYZValues) {
_inherits(XYZNonNegativeValues, _XYZValues);
function XYZNonNegativeValues(x, y, z) {
if ( x === void 0 ) x = 0;
if ( y === void 0 ) y = 0;
if ( z === void 0 ) z = 0;
_classCallCheck(this, XYZNonNegativeValues);
return _possibleConstructorReturn(this, (XYZNonNegativeValues.__proto__ || _Object$getPrototypeOf(XYZNonNegativeValues)).call(this, x, y, z));
}
_createClass(XYZNonNegativeValues, [{
key: "_checkForNegative",
value: function _checkForNegative(axisName, value) {
if (value < 0) {
throw new Error(axisName + " value was " + value + ". Size values cannot be negative.");
}
}
}, {
key: "x",
set: function (value) {
this._checkForNegative("X", value);
_set(XYZNonNegativeValues.prototype.__proto__ || _Object$getPrototypeOf(XYZNonNegativeValues.prototype), "x", value, this);
},
get: function () {
return _get(XYZNonNegativeValues.prototype.__proto__ || _Object$getPrototypeOf(XYZNonNegativeValues.prototype), "x", this);
}
}, {
key: "y",
set: function (value) {
this._checkForNegative("Y", value);
_set(XYZNonNegativeValues.prototype.__proto__ || _Object$getPrototypeOf(XYZNonNegativeValues.prototype), "y", value, this);
},
get: function () {
return _get(XYZNonNegativeValues.prototype.__proto__ || _Object$getPrototypeOf(XYZNonNegativeValues.prototype), "y", this);
}
}, {
key: "z",
set: function (value) {
this._checkForNegative("Z", value);
_set(XYZNonNegativeValues.prototype.__proto__ || _Object$getPrototypeOf(XYZNonNegativeValues.prototype), "z", value, this);
},
get: function () {
return _get(XYZNonNegativeValues.prototype.__proto__ || _Object$getPrototypeOf(XYZNonNegativeValues.prototype), "z", this);
}
}]);
return XYZNonNegativeValues;
}(XYZValues);
var runtime = createCommonjsModule(function (module) {
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
* additional grant of patent rights can be found in the PATENTS file in
* the same directory.
*/
!(function(global) {
"use strict";
var Op = Object.prototype;
var hasOwn = Op.hasOwnProperty;
var undefined; // More compressible than void 0.
var $Symbol = typeof Symbol === "function" ? Symbol : {};
var iteratorSymbol = $Symbol.iterator || "@@iterator";
var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
var inModule = 'object' === "object";
var runtime = global.regeneratorRuntime;
if (runtime) {
if (inModule) {
// If regeneratorRuntime is defined globally and we're in a module,
// make the exports object identical to regeneratorRuntime.
module.exports = runtime;
}
// Don't bother evaluating the rest of this file if the runtime was
// already defined globally.
return;
}
// Define the runtime globally (as expected by generated code) as either
// module.exports (if we're in a module) or a new, empty object.
runtime = global.regeneratorRuntime = inModule ? module.exports : {};
function wrap(innerFn, outerFn, self, tryLocsList) {
// If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
var generator = Object.create(protoGenerator.prototype);
var context = new Context(tryLocsList || []);
// The ._invoke method unifies the implementations of the .next,
// .throw, and .return methods.
generator._invoke = makeInvokeMethod(innerFn, self, context);
return generator;
}
runtime.wrap = wrap;
// Try/catch helper to minimize deoptimizations. Returns a completion
// record like context.tryEntries[i].completion. This interface could
// have been (and was previously) designed to take a closure to be
// invoked without arguments, but in all the cases we care about we
// already have an existing method we want to call, so there's no need
// to create a new function object. We can even get away with assuming
// the method takes exactly one argument, since that happens to be true
// in every case, so we don't have to touch the arguments object. The
// only additional allocation required is the completion record, which
// has a stable shape and so hopefully should be cheap to allocate.
function tryCatch(fn, obj, arg) {
try {
return { type: "normal", arg: fn.call(obj, arg) };
} catch (err) {
return { type: "throw", arg: err };
}
}
var GenStateSuspendedStart = "suspendedStart";
var GenStateSuspendedYield = "suspendedYield";
var GenStateExecuting = "executing";
var GenStateCompleted = "completed";
// Returning this object from the innerFn has the same effect as
// breaking out of the dispatch switch statement.
var ContinueSentinel = {};
// Dummy constructor functions that we use as the .constructor and
// .constructor.prototype properties for functions that return Generator
// objects. For full spec compliance, you may wish to configure your
// minifier not to mangle the names of these two functions.
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
// This is a polyfill for %IteratorPrototype% for environments that
// don't natively support it.
var IteratorPrototype = {};
IteratorPrototype[iteratorSymbol] = function () {
return this;
};
var getProto = Object.getPrototypeOf;
var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
if (NativeIteratorPrototype &&
NativeIteratorPrototype !== Op &&
hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
// This environment has a native %IteratorPrototype%; use it instead
// of the polyfill.
IteratorPrototype = NativeIteratorPrototype;
}
var Gp = GeneratorFunctionPrototype.prototype =
Generator.prototype = Object.create(IteratorPrototype);
GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
GeneratorFunctionPrototype.constructor = GeneratorFunction;
GeneratorFunctionPrototype[toStringTagSymbol] =
GeneratorFunction.displayName = "GeneratorFunction";
// Helper for defining the .next, .throw, and .return methods of the
// Iterator interface in terms of a single ._invoke method.
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function(method) {
prototype[method] = function(arg) {
return this._invoke(method, arg);
};
});
}
runtime.isGeneratorFunction = function(genFun) {
var ctor = typeof genFun === "function" && genFun.constructor;
return ctor
? ctor === GeneratorFunction ||
// For the native GeneratorFunction constructor, the best we can
// do is to check its .name property.
(ctor.displayName || ctor.name) === "GeneratorFunction"
: false;
};
runtime.mark = function(genFun) {
if (Object.setPrototypeOf) {
Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
} else {
genFun.__proto__ = GeneratorFunctionPrototype;
if (!(toStringTagSymbol in genFun)) {
genFun[toStringTagSymbol] = "GeneratorFunction";
}
}
genFun.prototype = Object.create(Gp);
return genFun;
};
// Within the body of any async function, `await x` is transformed to
// `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
// `hasOwn.call(value, "__await")` to determine if the yielded value is
// meant to be awaited.
runtime.awrap = function(arg) {
return { __await: arg };
};
function AsyncIterator(generator) {
function invoke(method, arg, resolve, reject) {
var record = tryCatch(generator[method], generator, arg);
if (record.type === "throw") {
reject(record.arg);
} else {
var result = record.arg;
var value = result.value;
if (value &&
typeof value === "object" &&
hasOwn.call(value, "__await")) {
return Promise.resolve(value.__await).then(function(value) {
invoke("next", value, resolve, reject);
}, function(err) {
invoke("throw", err, resolve, reject);
});
}
return Promise.resolve(value).then(function(unwrapped) {
// When a yielded Promise is resolved, its final value becomes
// the .value of the Promise<{value,done}> result for the
// current iteration. If the Promise is rejected, however, the
// result for this iteration will be rejected with the same
// reason. Note that rejections of yielded Promises are not
// thrown back into the generator function, as is the case
// when an awaited Promise is rejected. This difference in
// behavior between yield and await is important, because it
// allows the consumer to decide what to do with the yielded
// rejection (swallow it and continue, manually .throw it back
// into the generator, abandon iteration, whatever). With
// await, by contrast, there is no opportunity to examine the
// rejection reason outside the generator function, so the
// only option is to throw it from the await expression, and
// let the generator function handle the exception.
result.value = unwrapped;
resolve(result);
}, reject);
}
}
if (typeof global.process === "object" && global.process.domain) {
invoke = global.process.domain.bind(invoke);
}
var previousPromise;
function enqueue(method, arg) {
function callInvokeWithMethodAndArg() {
return new Promise(function(resolve, reject) {
invoke(method, arg, resolve, reject);
});
}
return previousPromise =
// If enqueue has been called before, then we want to wait until
// all previous Promises have been resolved before calling invoke,
// so that results are always delivered in the correct order. If
// enqueue has not been called before, then it is important to
// call invoke immediately, without waiting on a callback to fire,
// so that the async generator function has the opportunity to do
// any necessary setup in a predictable way. This predictability
// is why the Promise constructor synchronously invokes its
// executor callback, and why async functions synchronously
// execute code before the first await. Since we implement simple
// async functions in terms of async generators, it is especially
// important to get this right, even though it requires care.
previousPromise ? previousPromise.then(
callInvokeWithMethodAndArg,
// Avoid propagating failures to Promises returned by later
// invocations of the iterator.
callInvokeWithMethodAndArg
) : callInvokeWithMethodAndArg();
}
// Define the unified helper method that is used to implement .next,
// .throw, and .return (see defineIteratorMethods).
this._invoke = enqueue;
}
defineIteratorMethods(AsyncIterator.prototype);
AsyncIterator.prototype[asyncIteratorSymbol] = function () {
return this;
};
runtime.AsyncIterator = AsyncIterator;
// Note that simple async functions are implemented on top of
// AsyncIterator objects; they just return a Promise for the value of
// the final result produced by the iterator.
runtime.async = function(innerFn, outerFn, self, tryLocsList) {
var iter = new AsyncIterator(
wrap(innerFn, outerFn, self, tryLocsList)
);
return runtime.isGeneratorFunction(outerFn)
? iter // If outerFn is a generator, return the full iterator.
: iter.next().then(function(result) {
return result.done ? result.value : iter.next();
});
};
function makeInvokeMethod(innerFn, self, context) {
var state = GenStateSuspendedStart;
return function invoke(method, arg) {
if (state === GenStateExecuting) {
throw new Error("Generator is already running");
}
if (state === GenStateCompleted) {
if (method === "throw") {
throw arg;
}
// Be forgiving, per 25.3.3.3.3 of the spec:
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
return doneResult();
}
context.method = method;
context.arg = arg;
while (true) {
var delegate = context.delegate;
if (delegate) {
var delegateResult = maybeInvokeDelegate(delegate, context);
if (delegateResult) {
if (delegateResult === ContinueSentinel) { continue; }
return delegateResult;
}
}
if (context.method === "next") {
// Setting context._sent for legacy support of Babel's
// function.sent implementation.
context.sent = context._sent = context.arg;
} else if (context.method === "throw") {
if (state === GenStateSuspendedStart) {
state = GenStateCompleted;
throw context.arg;
}
context.dispatchException(context.arg);
} else if (context.method === "return") {
context.abrupt("return", context.arg);
}
state = GenStateExecuting;
var record = tryCatch(innerFn, self, context);
if (record.type === "normal") {
// If an exception is thrown from innerFn, we leave state ===
// GenStateExecuting and loop back for another invocation.
state = context.done
? GenStateCompleted
: GenStateSuspendedYield;
if (record.arg === ContinueSentinel) {
continue;
}
return {
value: record.arg,
done: context.done
};
} else if (record.type === "throw") {
state = GenStateCompleted;
// Dispatch the exception by looping back around to the
// context.dispatchException(context.arg) call above.
context.method = "throw";
context.arg = record.arg;
}
}
};
}
// Call delegate.iterator[context.method](context.arg) and handle the
// result, either by returning a { value, done } result from the
// delegate iterator, or by modifying context.method and context.arg,
// setting context.delegate to null, and returning the ContinueSentinel.
function maybeInvokeDelegate(delegate, context) {
var method = delegate.iterator[context.method];
if (method === undefined) {
// A .throw or .return when the delegate iterator has no .throw
// method always terminates the yield* loop.
context.delegate = null;
if (context.method === "throw") {
if (delegate.iterator.return) {
// If the delegate iterator has a return method, give it a
// chance to clean up.
context.method = "return";
context.arg = undefined;
maybeInvokeDelegate(delegate, context);
if (context.method === "throw") {
// If maybeInvokeDelegate(context) changed context.method from
// "return" to "throw", let that override the TypeError below.
return ContinueSentinel;
}
}
context.method = "throw";
context.arg = new TypeError(
"The iterator does not provide a 'throw' method");
}
return ContinueSentinel;
}
var record = tryCatch(method, delegate.iterator, context.arg);
if (record.type === "throw") {
context.method = "throw";
context.arg = record.arg;
context.delegate = null;
return ContinueSentinel;
}
var info = record.arg;
if (! info) {
context.method = "throw";
context.arg = new TypeError("iterator result is not an object");
context.delegate = null;
return ContinueSentinel;
}
if (info.done) {
// Assign the result of the finished delegate to the temporary
// variable specified by delegate.resultName (see delegateYield).
context[delegate.resultName] = info.value;
// Resume execution at the desired location (see delegateYield).
context.next = delegate.nextLoc;
// If context.method was "throw" but the delegate handled the
// exception, let the outer generator proceed normally. If
// context.method was "next", forget context.arg since it has been
// "consumed" by the delegate iterator. If context.method was
// "return", allow the original .return call to continue in the
// outer generator.
if (context.method !== "return") {
context.method = "next";
context.arg = undefined;
}
} else {
// Re-yield the result returned by the delegate method.
return info;
}
// The delegate iterator is finished, so forget it and continue with
// the outer generator.
context.delegate = null;
return ContinueSentinel;
}
// Define Generator.prototype.{next,throw,return} in terms of the
// unified ._invoke helper method.
defineIteratorMethods(Gp);
Gp[toStringTagSymbol] = "Generator";
// A Generator should always return itself as the iterator object when the
// @@iterator function is called on it. Some browsers' implementations of the
// iterator prototype chain incorrectly implement this, causing the Generator
// object to not be returned from this call. This ensures that doesn't happen.
// See https://github.com/facebook/regenerator/issues/274 for more details.
Gp[iteratorSymbol] = function() {
return this;
};
Gp.toString = function() {
return "[object Generator]";
};
function pushTryEntry(locs) {
var entry = { tryLoc: locs[0] };
if (1 in locs) {
entry.catchLoc = locs[1];
}
if (2 in locs) {
entry.finallyLoc = locs[2];
entry.afterLoc = locs[3];
}
this.tryEntries.push(entry);
}
function resetTryEntry(entry) {
var record = entry.completion || {};
record.type = "normal";
delete record.arg;
entry.completion = record;
}
function Context(tryLocsList) {
// The root entry object (effectively a try statement without a catch
// or a finally block) gives us a place to store values thrown from
// locations where there is no enclosing try statement.
this.tryEntries = [{ tryLoc: "root" }];
tryLocsList.forEach(pushTryEntry, this);
this.reset(true);
}
runtime.keys = function(object) {
var keys = [];
for (var key in object) {
keys.push(key);
}
keys.reverse();
// Rather than returning an object with a next method, we keep
// things simple and return the next function itself.
return function next() {
while (keys.length) {
var key = keys.pop();
if (key in object) {
next.value = key;
next.done = false;
return next;
}
}
// To avoid creating an additional object, we just hang the .value
// and .done properties off the next function object itself. This
// also ensures that the minifier will not anonymize the function.
next.done = true;
return next;
};
};
function values(iterable) {
if (iterable) {
var iteratorMethod = iterable[iteratorSymbol];
if (iteratorMethod) {
return iteratorMethod.call(iterable);
}
if (typeof iterable.next === "function") {
return iterable;
}
if (!isNaN(iterable.length)) {
var i = -1, next = function next() {
while (++i < iterable.length) {
if (hasOwn.call(iterable, i)) {
next.value = iterable[i];
next.done = false;
return next;
}
}
next.value = undefined;
next.done = true;
return next;
};
return next.next = next;
}
}
// Return an iterator with no values.
return { next: doneResult };
}
runtime.values = values;
function doneResult() {
return { value: undefined, done: true };
}
Context.prototype = {
constructor: Context,
reset: function(skipTempReset) {
var this$1 = this;
this.prev = 0;
this.next = 0;
// Resetting context._sent for legacy support of Babel's
// function.sent implementation.
this.sent = this._sent = undefined;
this.done = false;
this.delegate = null;
this.method = "next";
this.arg = undefined;
this.tryEntries.forEach(resetTryEntry);
if (!skipTempReset) {
for (var name in this$1) {
// Not sure about the optimal order of these conditions:
if (name.charAt(0) === "t" &&
hasOwn.call(this$1, name) &&
!isNaN(+name.slice(1))) {
this$1[name] = undefined;
}
}
}
},
stop: function() {
this.done = true;
var rootEntry = this.tryEntries[0];
var rootRecord = rootEntry.completion;
if (rootRecord.type === "throw") {
throw rootRecord.arg;
}
return this.rval;
},
dispatchException: function(exception) {
var this$1 = this;
if (this.done) {
throw exception;
}
var context = this;
function handle(loc, caught) {
record.type = "throw";
record.arg = exception;
context.next = loc;
if (caught) {
// If the dispatched exception was caught by a catch block,
// then let that catch block handle the exception normally.
context.method = "next";
context.arg = undefined;
}
return !! caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this$1.tryEntries[i];
var record = entry.completion;
if (entry.tryLoc === "root") {
// Exception thrown outside of any try block that could handle
// it, so set the completion value of the entire function to
// throw the exception.
return handle("end");
}
if (entry.tryLoc <= this$1.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc");
var hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this$1.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
} else if (this$1.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else if (hasCatch) {
if (this$1.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
}
} else if (hasFinally) {
if (this$1.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else {
throw new Error("try statement without catch or finally");
}
}
}
},
abrupt: function(type, arg) {
var this$1 = this;
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this$1.tryEntries[i];
if (entry.tryLoc <= this$1.prev &&
hasOwn.call(entry, "finallyLoc") &&
this$1.prev < entry.finallyLoc) {
var finallyEntry = entry;
break;
}
}
if (finallyEntry &&
(type === "break" ||
type === "continue") &&
finallyEntry.tryLoc <= arg &&
arg <= finallyEntry.finallyLoc) {
// Ignore the finally entry if control is not jumping to a
// location outside the try/catch block.
finallyEntry = null;
}
var record = finallyEntry ? finallyEntry.completion : {};
record.type = type;
record.arg = arg;
if (finallyEntry) {
this.method = "next";
this.next = finallyEntry.finallyLoc;
return ContinueSentinel;
}
return this.complete(record);
},
complete: function(record, afterLoc) {
if (record.type === "throw") {
throw record.arg;
}
if (record.type === "break" ||
record.type === "continue") {
this.next = record.arg;
} else if (record.type === "return") {
this.rval = this.arg = record.arg;
this.method = "return";
this.next = "end";
} else if (record.type === "normal" && afterLoc) {
this.next = afterLoc;
}
return ContinueSentinel;
},
finish: function(finallyLoc) {
var this$1 = this;
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this$1.tryEntries[i];
if (entry.finallyLoc === finallyLoc) {
this$1.complete(entry.completion, entry.afterLoc);
resetTryEntry(entry);
return ContinueSentinel;
}
}
},
"catch": function(tryLoc) {
var this$1 = this;
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this$1.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if (record.type === "throw") {
var thrown = record.arg;
resetTryEntry(entry);
}
return thrown;
}
}
// The context.catch method must only be called with a location
// argument that corresponds to a known catch block.
throw new Error("illegal catch attempt");
},
delegateYield: function(iterable, resultName, nextLoc) {
this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
};
if (this.method === "next") {
// Deliberately forget the last sent value so that we don't
// accidentally pass it on to the delegate.
this.arg = undefined;
}
return ContinueSentinel;
}
};
})(
// Among the various tricks for obtaining a reference to the global
// object, this seems to be the most reliable technique that does not
// use indirect eval (which violates Content Security Policy).
typeof commonjsGlobal === "object" ? commonjsGlobal :
typeof window === "object" ? window :
typeof self === "object" ? self : commonjsGlobal
);
});
// This method of obtaining a reference to the global object needs to be
// kept identical to the way it is obtained in runtime.js
var g =
typeof commonjsGlobal === "object" ? commonjsGlobal :
typeof window === "object" ? window :
typeof self === "object" ? self : commonjsGlobal;
// Use `getOwnPropertyNames` because not all browsers support calling
// `hasOwnProperty` on the global `self` object in a worker. See #183.
var hadRuntime = g.regeneratorRuntime &&
Object.getOwnPropertyNames(g).indexOf("regeneratorRuntime") >= 0;
// Save the old regeneratorRuntime in case it needs to be restored later.
var oldRuntime = hadRuntime && g.regeneratorRuntime;
// Force reevalutation of runtime.js.
g.regeneratorRuntime = undefined;
var runtimeModule = runtime;
if (hadRuntime) {
// Restore the original runtime.
g.regeneratorRuntime = oldRuntime;
} else {
// Remove the global property added by runtime.js.
try {
delete g.regeneratorRuntime;
} catch(e) {
g.regeneratorRuntime = undefined;
}
}
var regenerator = runtimeModule;
var asyncToGenerator = createCommonjsModule(function (module, exports) {
"use strict";
exports.__esModule = true;
var _promise2 = _interopRequireDefault(promise);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function (fn) {
return function () {
var gen = fn.apply(this, arguments);
return new _promise2.default(function (resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return _promise2.default.resolve(value).then(function (value) {
step("next", value);
}, function (err) {
step("throw", err);
});
}
}
return step("next");
});
};
};
});
unwrapExports(asyncToGenerator);
var documentReady = createCommonjsModule(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _regenerator2 = _interopRequireDefault(regenerator);
var _promise2 = _interopRequireDefault(promise);
var _asyncToGenerator3 = _interopRequireDefault(asyncToGenerator);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Await for this to run code after the DOM has been parsed and loaded (but not
* sub-resources like images, scripts, etc).
*
* @example
* ```js
* async function main() {
* await documentReady()
* console.log('Document ready!')
* }
* main()
* ```
*/
exports.default = function () {
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() {
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!(document.readyState === 'loading')) {
_context.next = 3;
break;
}
_context.next = 3;
return new _promise2.default(function (resolve) {
document.addEventListener('DOMContentLoaded', resolve);
});
case 3:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function documentReady() {
return _ref.apply(this, arguments);
}
return documentReady;
}();
});
var documentReady$1 = unwrapExports(documentReady);
'use strict';
var getWeak = _meta.getWeak;
var arrayFind = _arrayMethods(5);
var arrayFindIndex = _arrayMethods(6);
var id$1 = 0;
// fallback for uncaught frozen keys
var uncaughtFrozenStore = function (that) {
return that._l || (that._l = new UncaughtFrozenStore());
};
var UncaughtFrozenStore = function () {
this.a = [];
};
var findUncaughtFrozen = function (store, key) {
return arrayFind(store.a, function (it) {
return it[0] === key;
});
};
UncaughtFrozenStore.prototype = {
get: function (key) {
var entry = findUncaughtFrozen(this, key);
if (entry) { return entry[1]; }
},
has: function (key) {
return !!findUncaughtFrozen(this, key);
},
set: function (key, value) {
var entry = findUncaughtFrozen(this, key);
if (entry) { entry[1] = value; }
else { this.a.push([key, value]); }
},
'delete': function (key) {
var index = arrayFindIndex(this.a, function (it) {
return it[0] === key;
});
if (~index) { this.a.splice(index, 1); }
return !!~index;
}
};
var _collectionWeak = {
getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {
var C = wrapper(function (that, iterable) {
_anInstance(that, C, NAME, '_i');
that._t = NAME; // collection type
that._i = id$1++; // collection id
that._l = undefined; // leak store for uncaught frozen objects
if (iterable != undefined) { _forOf(iterable, IS_MAP, that[ADDER], that); }
});
_redefineAll(C.prototype, {
// 23.3.3.2 WeakMap.prototype.delete(key)
// 23.4.3.3 WeakSet.prototype.delete(value)
'delete': function (key) {
if (!_isObject(key)) { return false; }
var data = getWeak(key);
if (data === true) { return uncaughtFrozenStore(_validateCollection(this, NAME))['delete'](key); }
return data && _has(data, this._i) && delete data[this._i];
},
// 23.3.3.4 WeakMap.prototype.has(key)
// 23.4.3.4 WeakSet.prototype.has(value)
has: function has(key) {
if (!_isObject(key)) { return false; }
var data = getWeak(key);
if (data === true) { return uncaughtFrozenStore(_validateCollection(this, NAME)).has(key); }
return data && _has(data, this._i);
}
});
return C;
},
def: function (that, key, value) {
var data = getWeak(_anObject(key), true);
if (data === true) { uncaughtFrozenStore(that).set(key, value); }
else { data[that._i] = value; }
return that;
},
ufstore: uncaughtFrozenStore
};
var es6_weakMap = createCommonjsModule(function (module) {
'use strict';
var each = _arrayMethods(0);
var WEAK_MAP = 'WeakMap';
var getWeak = _meta.getWeak;
var isExtensible = Object.isExtensible;
var uncaughtFrozenStore = _collectionWeak.ufstore;
var tmp = {};
var InternalMap;
var wrapper = function (get) {
return function WeakMap() {
return get(this, arguments.length > 0 ? arguments[0] : undefined);
};
};
var methods = {
// 23.3.3.3 WeakMap.prototype.get(key)
get: function get(key) {
if (_isObject(key)) {
var data = getWeak(key);
if (data === true) { return uncaughtFrozenStore(_validateCollection(this, WEAK_MAP)).get(key); }
return data ? data[this._i] : undefined;
}
},
// 23.3.3.5 WeakMap.prototype.set(key, value)
set: function set(key, value) {
return _collectionWeak.def(_validateCollection(this, WEAK_MAP), key, value);
}
};
// 23.3 WeakMap Objects
var $WeakMap = module.exports = _collection(WEAK_MAP, wrapper, methods, _collectionWeak, true, true);
// IE11 WeakMap frozen keys fix
if (_fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) {
InternalMap = _collectionWeak.getConstructor(wrapper, WEAK_MAP);
_objectAssign(InternalMap.prototype, methods);
_meta.NEED = true;
each(['delete', 'has', 'get', 'set'], function (key) {
var proto = $WeakMap.prototype;
var method = proto[key];
_redefine(proto, key, function (a, b) {
// store frozen objects on internal weakmap shim
if (_isObject(a) && !isExtensible(a)) {
if (!this._f) { this._f = new InternalMap(); }
var result = this._f[key](a, b);
return key == 'set' ? this : result;
// store all the rest on native weakmap
} return method.call(this, a, b);
});
});
}
});
// https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.of
_setCollectionOf('WeakMap');
// https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.from
_setCollectionFrom('WeakMap');
var weakMap$1 = _core.WeakMap;
var weakMap = createCommonjsModule(function (module) {
module.exports = { "default": weakMap$1, __esModule: true };
});
var _WeakMap = unwrapExports(weakMap);
// Polyfills
if ( Number.EPSILON === undefined ) {
Number.EPSILON = Math.pow( 2, - 52 );
}
if ( Number.isInteger === undefined ) {
// Missing in IE
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
Number.isInteger = function ( value ) {
return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;
};
}
//
if ( Math.sign === undefined ) {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
Math.sign = function ( x ) {
return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
};
}
if ( 'name' in Function.prototype === false ) {
// Missing in IE
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
Object.defineProperty( Function.prototype, 'name', {
get: function () {
return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ];
}
} );
}
if ( Object.assign === undefined ) {
// Missing in IE
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
( function () {
Object.assign = function ( target ) {
'use strict';
var arguments$1 = arguments;
if ( target === undefined || target === null ) {
throw new TypeError( 'Cannot convert undefined or null to object' );
}
var output = Object( target );
for ( var index = 1; index < arguments.length; index ++ ) {
var source = arguments$1[ index ];
if ( source !== undefined && source !== null ) {
for ( var nextKey in source ) {
if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
output[ nextKey ] = source[ nextKey ];
}
}
}
}
return output;
};
} )();
}
/**
* https://github.com/mrdoob/eventdispatcher.js/
*/
function EventDispatcher() {}
Object.assign( EventDispatcher.prototype, {
addEventListener: function ( type, listener ) {
if ( this._listeners === undefined ) { this._listeners = {}; }
var listeners = this._listeners;
if ( listeners[ type ] === undefined ) {
listeners[ type ] = [];
}
if ( listeners[ type ].indexOf( listener ) === - 1 ) {
listeners[ type ].push( listener );
}
},
hasEventListener: function ( type, listener ) {
if ( this._listeners === undefined ) { return false; }
var listeners = this._listeners;
return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
},
removeEventListener: function ( type, listener ) {
if ( this._listeners === undefined ) { return; }
var listeners = this._listeners;
var listenerArray = listeners[ type ];
if ( listenerArray !== undefined ) {
var index = listenerArray.indexOf( listener );
if ( index !== - 1 ) {
listenerArray.splice( index, 1 );
}
}
},
dispatchEvent: function ( event ) {
var this$1 = this;
if ( this._listeners === undefined ) { return; }
var listeners = this._listeners;
var listenerArray = listeners[ event.type ];
if ( listenerArray !== undefined ) {
event.target = this;
var array = listenerArray.slice( 0 );
for ( var i = 0, l = array.length; i < l; i ++ ) {
array[ i ].call( this$1, event );
}
}
}
} );
var REVISION = '88';
var CullFaceNone = 0;
var CullFaceBack = 1;
var CullFaceFront = 2;
var FrontFaceDirectionCW = 0;
var BasicShadowMap = 0;
var PCFShadowMap = 1;
var PCFSoftShadowMap = 2;
var FrontSide = 0;
var BackSide = 1;
var DoubleSide = 2;
var FlatShading = 1;
var NoColors = 0;
var FaceColors = 1;
var VertexColors = 2;
var NoBlending = 0;
var NormalBlending = 1;
var AdditiveBlending = 2;
var SubtractiveBlending = 3;
var MultiplyBlending = 4;
var CustomBlending = 5;
var AddEquation = 100;
var SubtractEquation = 101;
var ReverseSubtractEquation = 102;
var MinEquation = 103;
var MaxEquation = 104;
var ZeroFactor = 200;
var OneFactor = 201;
var SrcColorFactor = 202;
var OneMinusSrcColorFactor = 203;
var SrcAlphaFactor = 204;
var OneMinusSrcAlphaFactor = 205;
var DstAlphaFactor = 206;
var OneMinusDstAlphaFactor = 207;
var DstColorFactor = 208;
var OneMinusDstColorFactor = 209;
var SrcAlphaSaturateFactor = 210;
var NeverDepth = 0;
var AlwaysDepth = 1;
var LessDepth = 2;
var LessEqualDepth = 3;
var EqualDepth = 4;
var GreaterEqualDepth = 5;
var GreaterDepth = 6;
var NotEqualDepth = 7;
var MultiplyOperation = 0;
var MixOperation = 1;
var AddOperation = 2;
var NoToneMapping = 0;
var LinearToneMapping = 1;
var ReinhardToneMapping = 2;
var Uncharted2ToneMapping = 3;
var CineonToneMapping = 4;
var UVMapping = 300;
var CubeReflectionMapping = 301;
var CubeRefractionMapping = 302;
var EquirectangularReflectionMapping = 303;
var EquirectangularRefractionMapping = 304;
var SphericalReflectionMapping = 305;
var CubeUVReflectionMapping = 306;
var CubeUVRefractionMapping = 307;
var RepeatWrapping = 1000;
var ClampToEdgeWrapping = 1001;
var MirroredRepeatWrapping = 1002;
var NearestFilter = 1003;
var NearestMipMapNearestFilter = 1004;
var NearestMipMapLinearFilter = 1005;
var LinearFilter = 1006;
var LinearMipMapNearestFilter = 1007;
var LinearMipMapLinearFilter = 1008;
var UnsignedByteType = 1009;
var ByteType = 1010;
var ShortType = 1011;
var UnsignedShortType = 1012;
var IntType = 1013;
var UnsignedIntType = 1014;
var FloatType = 1015;
var HalfFloatType = 1016;
var UnsignedShort4444Type = 1017;
var UnsignedShort5551Type = 1018;
var UnsignedShort565Type = 1019;
var UnsignedInt248Type = 1020;
var AlphaFormat = 1021;
var RGBFormat = 1022;
var RGBAFormat = 1023;
var LuminanceFormat = 1024;
var LuminanceAlphaFormat = 1025;
var DepthFormat = 1026;
var DepthStencilFormat = 1027;
var RGB_S3TC_DXT1_Format = 2001;
var RGBA_S3TC_DXT1_Format = 2002;
var RGBA_S3TC_DXT3_Format = 2003;
var RGBA_S3TC_DXT5_Format = 2004;
var RGB_PVRTC_4BPPV1_Format = 2100;
var RGB_PVRTC_2BPPV1_Format = 2101;
var RGBA_PVRTC_4BPPV1_Format = 2102;
var RGBA_PVRTC_2BPPV1_Format = 2103;
var RGB_ETC1_Format = 2151;
var LoopOnce = 2200;
var LoopRepeat = 2201;
var LoopPingPong = 2202;
var InterpolateDiscrete = 2300;
var InterpolateLinear = 2301;
var InterpolateSmooth = 2302;
var ZeroCurvatureEnding = 2400;
var ZeroSlopeEnding = 2401;
var WrapAroundEnding = 2402;
var TrianglesDrawMode = 0;
var TriangleStripDrawMode = 1;
var TriangleFanDrawMode = 2;
var LinearEncoding = 3000;
var sRGBEncoding = 3001;
var GammaEncoding = 3007;
var RGBEEncoding = 3002;
var RGBM7Encoding = 3004;
var RGBM16Encoding = 3005;
var RGBDEncoding = 3006;
var BasicDepthPacking = 3200;
var RGBADepthPacking = 3201;
/**
* @author alteredq / http://alteredqualia.com/
* @author mrdoob / http://mrdoob.com/
*/
var _Math = {
DEG2RAD: Math.PI / 180,
RAD2DEG: 180 / Math.PI,
generateUUID: function () {
// http://www.broofa.com/Tools/Math.uuid.htm
// Replaced .join with string concatenation (@takahirox)
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split( '' );
var rnd = 0, r;
return function generateUUID() {
var uuid = '';
for ( var i = 0; i < 36; i ++ ) {
if ( i === 8 || i === 13 || i === 18 || i === 23 ) {
uuid += '-';
} else if ( i === 14 ) {
uuid += '4';
} else {
if ( rnd <= 0x02 ) { rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0; }
r = rnd & 0xf;
rnd = rnd >> 4;
uuid += chars[ ( i === 19 ) ? ( r & 0x3 ) | 0x8 : r ];
}
}
return uuid;
};
}(),
clamp: function ( value, min, max ) {
return Math.max( min, Math.min( max, value ) );
},
// compute euclidian modulo of m % n
// https://en.wikipedia.org/wiki/Modulo_operation
euclideanModulo: function ( n, m ) {
return ( ( n % m ) + m ) % m;
},
// Linear mapping from range <a1, a2> to range <b1, b2>
mapLinear: function ( x, a1, a2, b1, b2 ) {
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
},
// https://en.wikipedia.org/wiki/Linear_interpolation
lerp: function ( x, y, t ) {
return ( 1 - t ) * x + t * y;
},
// http://en.wikipedia.org/wiki/Smoothstep
smoothstep: function ( x, min, max ) {
if ( x <= min ) { return 0; }
if ( x >= max ) { return 1; }
x = ( x - min ) / ( max - min );
return x * x * ( 3 - 2 * x );
},
smootherstep: function ( x, min, max ) {
if ( x <= min ) { return 0; }
if ( x >= max ) { return 1; }
x = ( x - min ) / ( max - min );
return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
},
// Random integer from <low, high> interval
randInt: function ( low, high ) {
return low + Math.floor( Math.random() * ( high - low + 1 ) );
},
// Random float from <low, high> interval
randFloat: function ( low, high ) {
return low + Math.random() * ( high - low );
},
// Random float from <-range/2, range/2> interval
randFloatSpread: function ( range ) {
return range * ( 0.5 - Math.random() );
},
degToRad: function ( degrees ) {
return degrees * _Math.DEG2RAD;
},
radToDeg: function ( radians ) {
return radians * _Math.RAD2DEG;
},
isPowerOfTwo: function ( value ) {
return ( value & ( value - 1 ) ) === 0 && value !== 0;
},
ceilPowerOfTwo: function ( value ) {
return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
},
floorPowerOfTwo: function ( value ) {
return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
}
};
/**
* @author mrdoob / http://mrdoob.com/
* @author philogb / http://blog.thejit.org/
* @author egraether / http://egraether.com/
* @author zz85 / http://www.lab4games.net/zz85/blog
*/
function Vector2( x, y ) {
this.x = x || 0;
this.y = y || 0;
}
Object.defineProperties( Vector2.prototype, {
"width": {
get: function () {
return this.x;
},
set: function ( value ) {
this.x = value;
}
},
"height": {
get: function () {
return this.y;
},
set: function ( value ) {
this.y = value;
}
}
} );
Object.assign( Vector2.prototype, {
isVector2: true,
set: function ( x, y ) {
this.x = x;
this.y = y;
return this;
},
setScalar: function ( scalar ) {
this.x = scalar;
this.y = scalar;
return this;
},
setX: function ( x ) {
this.x = x;
return this;
},
setY: function ( y ) {
this.y = y;
return this;
},
setComponent: function ( index, value ) {
switch ( index ) {
case 0: this.x = value; break;
case 1: this.y = value; break;
default: throw new Error( 'index is out of range: ' + index );
}
return this;
},
getComponent: function ( index ) {
switch ( index ) {
case 0: return this.x;
case 1: return this.y;
default: throw new Error( 'index is out of range: ' + index );
}
},
clone: function () {
return new this.constructor( this.x, this.y );
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
return this;
},
add: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
return this.addVectors( v, w );
}
this.x += v.x;
this.y += v.y;
return this;
},
addScalar: function ( s ) {
this.x += s;
this.y += s;
return this;
},
addVectors: function ( a, b ) {
this.x = a.x + b.x;
this.y = a.y + b.y;
return this;
},
addScaledVector: function ( v, s ) {
this.x += v.x * s;
this.y += v.y * s;
return this;
},
sub: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
return this.subVectors( v, w );
}
this.x -= v.x;
this.y -= v.y;
return this;
},
subScalar: function ( s ) {
this.x -= s;
this.y -= s;
return this;
},
subVectors: function ( a, b ) {
this.x = a.x - b.x;
this.y = a.y - b.y;
return this;
},
multiply: function ( v ) {
this.x *= v.x;
this.y *= v.y;
return this;
},
multiplyScalar: function ( scalar ) {
this.x *= scalar;
this.y *= scalar;
return this;
},
divide: function ( v ) {
this.x /= v.x;
this.y /= v.y;
return this;
},
divideScalar: function ( scalar ) {
return this.multiplyScalar( 1 / scalar );
},
applyMatrix3: function ( m ) {
var x = this.x, y = this.y;
var e = m.elements;
this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
return this;
},
min: function ( v ) {
this.x = Math.min( this.x, v.x );
this.y = Math.min( this.y, v.y );
return this;
},
max: function ( v ) {
this.x = Math.max( this.x, v.x );
this.y = Math.max( this.y, v.y );
return this;
},
clamp: function ( min, max ) {
// assumes min < max, componentwise
this.x = Math.max( min.x, Math.min( max.x, this.x ) );
this.y = Math.max( min.y, Math.min( max.y, this.y ) );
return this;
},
clampScalar: function () {
var min = new Vector2();
var max = new Vector2();
return function clampScalar( minVal, maxVal ) {
min.set( minVal, minVal );
max.set( maxVal, maxVal );
return this.clamp( min, max );
};
}(),
clampLength: function ( min, max ) {
var length = this.length();
return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
},
floor: function () {
this.x = Math.floor( this.x );
this.y = Math.floor( this.y );
return this;
},
ceil: function () {
this.x = Math.ceil( this.x );
this.y = Math.ceil( this.y );
return this;
},
round: function () {
this.x = Math.round( this.x );
this.y = Math.round( this.y );
return this;
},
roundToZero: function () {
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
return this;
},
negate: function () {
this.x = - this.x;
this.y = - this.y;
return this;
},
dot: function ( v ) {
return this.x * v.x + this.y * v.y;
},
lengthSq: function () {
return this.x * this.x + this.y * this.y;
},
length: function () {
return Math.sqrt( this.x * this.x + this.y * this.y );
},
manhattanLength: function () {
return Math.abs( this.x ) + Math.abs( this.y );
},
normalize: function () {
return this.divideScalar( this.length() || 1 );
},
angle: function () {
// computes the angle in radians with respect to the positive x-axis
var angle = Math.atan2( this.y, this.x );
if ( angle < 0 ) { angle += 2 * Math.PI; }
return angle;
},
distanceTo: function ( v ) {
return Math.sqrt( this.distanceToSquared( v ) );
},
distanceToSquared: function ( v ) {
var dx = this.x - v.x, dy = this.y - v.y;
return dx * dx + dy * dy;
},
manhattanDistanceTo: function ( v ) {
return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
},
setLength: function ( length ) {
return this.normalize().multiplyScalar( length );
},
lerp: function ( v, alpha ) {
this.x += ( v.x - this.x ) * alpha;
this.y += ( v.y - this.y ) * alpha;
return this;
},
lerpVectors: function ( v1, v2, alpha ) {
return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
},
equals: function ( v ) {
return ( ( v.x === this.x ) && ( v.y === this.y ) );
},
fromArray: function ( array, offset ) {
if ( offset === undefined ) { offset = 0; }
this.x = array[ offset ];
this.y = array[ offset + 1 ];
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
array[ offset ] = this.x;
array[ offset + 1 ] = this.y;
return array;
},
fromBufferAttribute: function ( attribute, index, offset ) {
if ( offset !== undefined ) {
console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
}
this.x = attribute.getX( index );
this.y = attribute.getY( index );
return this;
},
rotateAround: function ( center, angle ) {
var c = Math.cos( angle ), s = Math.sin( angle );
var x = this.x - center.x;
var y = this.y - center.y;
this.x = x * c - y * s + center.x;
this.y = x * s + y * c + center.y;
return this;
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author supereggbert / http://www.paulbrunt.co.uk/
* @author philogb / http://blog.thejit.org/
* @author jordi_ros / http://plattsoft.com
* @author D1plo1d / http://github.com/D1plo1d
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
* @author timknip / http://www.floorplanner.com/
* @author bhouston / http://clara.io
* @author WestLangley / http://github.com/WestLangley
*/
function Matrix4() {
this.elements = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
];
if ( arguments.length > 0 ) {
console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
}
}
Object.assign( Matrix4.prototype, {
isMatrix4: true,
set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
var te = this.elements;
te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
return this;
},
identity: function () {
this.set(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
return this;
},
clone: function () {
return new Matrix4().fromArray( this.elements );
},
copy: function ( m ) {
var te = this.elements;
var me = m.elements;
te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
return this;
},
copyPosition: function ( m ) {
var te = this.elements, me = m.elements;
te[ 12 ] = me[ 12 ];
te[ 13 ] = me[ 13 ];
te[ 14 ] = me[ 14 ];
return this;
},
extractBasis: function ( xAxis, yAxis, zAxis ) {
xAxis.setFromMatrixColumn( this, 0 );
yAxis.setFromMatrixColumn( this, 1 );
zAxis.setFromMatrixColumn( this, 2 );
return this;
},
makeBasis: function ( xAxis, yAxis, zAxis ) {
this.set(
xAxis.x, yAxis.x, zAxis.x, 0,
xAxis.y, yAxis.y, zAxis.y, 0,
xAxis.z, yAxis.z, zAxis.z, 0,
0, 0, 0, 1
);
return this;
},
extractRotation: function () {
var v1 = new Vector3();
return function extractRotation( m ) {
var te = this.elements;
var me = m.elements;
var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
te[ 0 ] = me[ 0 ] * scaleX;
te[ 1 ] = me[ 1 ] * scaleX;
te[ 2 ] = me[ 2 ] * scaleX;
te[ 4 ] = me[ 4 ] * scaleY;
te[ 5 ] = me[ 5 ] * scaleY;
te[ 6 ] = me[ 6 ] * scaleY;
te[ 8 ] = me[ 8 ] * scaleZ;
te[ 9 ] = me[ 9 ] * scaleZ;
te[ 10 ] = me[ 10 ] * scaleZ;
return this;
};
}(),
makeRotationFromEuler: function ( euler ) {
if ( ! ( euler && euler.isEuler ) ) {
console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
}
var te = this.elements;
var x = euler.x, y = euler.y, z = euler.z;
var a = Math.cos( x ), b = Math.sin( x );
var c = Math.cos( y ), d = Math.sin( y );
var e = Math.cos( z ), f = Math.sin( z );
if ( euler.order === 'XYZ' ) {
var ae = a * e, af = a * f, be = b * e, bf = b * f;
te[ 0 ] = c * e;
te[ 4 ] = - c * f;
te[ 8 ] = d;
te[ 1 ] = af + be * d;
te[ 5 ] = ae - bf * d;
te[ 9 ] = - b * c;
te[ 2 ] = bf - ae * d;
te[ 6 ] = be + af * d;
te[ 10 ] = a * c;
} else if ( euler.order === 'YXZ' ) {
var ce = c * e, cf = c * f, de = d * e, df = d * f;
te[ 0 ] = ce + df * b;
te[ 4 ] = de * b - cf;
te[ 8 ] = a * d;
te[ 1 ] = a * f;
te[ 5 ] = a * e;
te[ 9 ] = - b;
te[ 2 ] = cf * b - de;
te[ 6 ] = df + ce * b;
te[ 10 ] = a * c;
} else if ( euler.order === 'ZXY' ) {
var ce = c * e, cf = c * f, de = d * e, df = d * f;
te[ 0 ] = ce - df * b;
te[ 4 ] = - a * f;
te[ 8 ] = de + cf * b;
te[ 1 ] = cf + de * b;
te[ 5 ] = a * e;
te[ 9 ] = df - ce * b;
te[ 2 ] = - a * d;
te[ 6 ] = b;
te[ 10 ] = a * c;
} else if ( euler.order === 'ZYX' ) {
var ae = a * e, af = a * f, be = b * e, bf = b * f;
te[ 0 ] = c * e;
te[ 4 ] = be * d - af;
te[ 8 ] = ae * d + bf;
te[ 1 ] = c * f;
te[ 5 ] = bf * d + ae;
te[ 9 ] = af * d - be;
te[ 2 ] = - d;
te[ 6 ] = b * c;
te[ 10 ] = a * c;
} else if ( euler.order === 'YZX' ) {
var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
te[ 0 ] = c * e;
te[ 4 ] = bd - ac * f;
te[ 8 ] = bc * f + ad;
te[ 1 ] = f;
te[ 5 ] = a * e;
te[ 9 ] = - b * e;
te[ 2 ] = - d * e;
te[ 6 ] = ad * f + bc;
te[ 10 ] = ac - bd * f;
} else if ( euler.order === 'XZY' ) {
var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
te[ 0 ] = c * e;
te[ 4 ] = - f;
te[ 8 ] = d * e;
te[ 1 ] = ac * f + bd;
te[ 5 ] = a * e;
te[ 9 ] = ad * f - bc;
te[ 2 ] = bc * f - ad;
te[ 6 ] = b * e;
te[ 10 ] = bd * f + ac;
}
// last column
te[ 3 ] = 0;
te[ 7 ] = 0;
te[ 11 ] = 0;
// bottom row
te[ 12 ] = 0;
te[ 13 ] = 0;
te[ 14 ] = 0;
te[ 15 ] = 1;
return this;
},
makeRotationFromQuaternion: function ( q ) {
var te = this.elements;
var x = q._x, y = q._y, z = q._z, w = q._w;
var x2 = x + x, y2 = y + y, z2 = z + z;
var xx = x * x2, xy = x * y2, xz = x * z2;
var yy = y * y2, yz = y * z2, zz = z * z2;
var wx = w * x2, wy = w * y2, wz = w * z2;
te[ 0 ] = 1 - ( yy + zz );
te[ 4 ] = xy - wz;
te[ 8 ] = xz + wy;
te[ 1 ] = xy + wz;
te[ 5 ] = 1 - ( xx + zz );
te[ 9 ] = yz - wx;
te[ 2 ] = xz - wy;
te[ 6 ] = yz + wx;
te[ 10 ] = 1 - ( xx + yy );
// last column
te[ 3 ] = 0;
te[ 7 ] = 0;
te[ 11 ] = 0;
// bottom row
te[ 12 ] = 0;
te[ 13 ] = 0;
te[ 14 ] = 0;
te[ 15 ] = 1;
return this;
},
lookAt: function () {
var x = new Vector3();
var y = new Vector3();
var z = new Vector3();
return function lookAt( eye, target, up ) {
var te = this.elements;
z.subVectors( eye, target );
if ( z.lengthSq() === 0 ) {
// eye and target are in the same position
z.z = 1;
}
z.normalize();
x.crossVectors( up, z );
if ( x.lengthSq() === 0 ) {
// up and z are parallel
if ( Math.abs( up.z ) === 1 ) {
z.x += 0.0001;
} else {
z.z += 0.0001;
}
z.normalize();
x.crossVectors( up, z );
}
x.normalize();
y.crossVectors( z, x );
te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
return this;
};
}(),
multiply: function ( m, n ) {
if ( n !== undefined ) {
console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
return this.multiplyMatrices( m, n );
}
return this.multiplyMatrices( this, m );
},
premultiply: function ( m ) {
return this.multiplyMatrices( m, this );
},
multiplyMatrices: function ( a, b ) {
var ae = a.elements;
var be = b.elements;
var te = this.elements;
var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
return this;
},
multiplyScalar: function ( s ) {
var te = this.elements;
te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
return this;
},
applyToBufferAttribute: function () {
var v1 = new Vector3();
return function applyToBufferAttribute( attribute ) {
var this$1 = this;
for ( var i = 0, l = attribute.count; i < l; i ++ ) {
v1.x = attribute.getX( i );
v1.y = attribute.getY( i );
v1.z = attribute.getZ( i );
v1.applyMatrix4( this$1 );
attribute.setXYZ( i, v1.x, v1.y, v1.z );
}
return attribute;
};
}(),
determinant: function () {
var te = this.elements;
var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
//TODO: make this more efficient
//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
return (
n41 * (
+ n14 * n23 * n32
- n13 * n24 * n32
- n14 * n22 * n33
+ n12 * n24 * n33
+ n13 * n22 * n34
- n12 * n23 * n34
) +
n42 * (
+ n11 * n23 * n34
- n11 * n24 * n33
+ n14 * n21 * n33
- n13 * n21 * n34
+ n13 * n24 * n31
- n14 * n23 * n31
) +
n43 * (
+ n11 * n24 * n32
- n11 * n22 * n34
- n14 * n21 * n32
+ n12 * n21 * n34
+ n14 * n22 * n31
- n12 * n24 * n31
) +
n44 * (
- n13 * n22 * n31
- n11 * n23 * n32
+ n11 * n22 * n33
+ n13 * n21 * n32
- n12 * n21 * n33
+ n12 * n23 * n31
)
);
},
transpose: function () {
var te = this.elements;
var tmp;
tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
return this;
},
setPosition: function ( v ) {
var te = this.elements;
te[ 12 ] = v.x;
te[ 13 ] = v.y;
te[ 14 ] = v.z;
return this;
},
getInverse: function ( m, throwOnDegenerate ) {
// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
var te = this.elements,
me = m.elements,
n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
if ( det === 0 ) {
var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
if ( throwOnDegenerate === true ) {
throw new Error( msg );
} else {
console.warn( msg );
}
return this.identity();
}
var detInv = 1 / det;
te[ 0 ] = t11 * detInv;
te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
te[ 4 ] = t12 * detInv;
te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
te[ 8 ] = t13 * detInv;
te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
te[ 12 ] = t14 * detInv;
te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
return this;
},
scale: function ( v ) {
var te = this.elements;
var x = v.x, y = v.y, z = v.z;
te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
return this;
},
getMaxScaleOnAxis: function () {
var te = this.elements;
var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
},
makeTranslation: function ( x, y, z ) {
this.set(
1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1
);
return this;
},
makeRotationX: function ( theta ) {
var c = Math.cos( theta ), s = Math.sin( theta );
this.set(
1, 0, 0, 0,
0, c, - s, 0,
0, s, c, 0,
0, 0, 0, 1
);
return this;
},
makeRotationY: function ( theta ) {
var c = Math.cos( theta ), s = Math.sin( theta );
this.set(
c, 0, s, 0,
0, 1, 0, 0,
- s, 0, c, 0,
0, 0, 0, 1
);
return this;
},
makeRotationZ: function ( theta ) {
var c = Math.cos( theta ), s = Math.sin( theta );
this.set(
c, - s, 0, 0,
s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
return this;
},
makeRotationAxis: function ( axis, angle ) {
// Based on http://www.gamedev.net/reference/articles/article1199.asp
var c = Math.cos( angle );
var s = Math.sin( angle );
var t = 1 - c;
var x = axis.x, y = axis.y, z = axis.z;
var tx = t * x, ty = t * y;
this.set(
tx * x + c, tx * y - s * z, tx * z + s * y, 0,
tx * y + s * z, ty * y + c, ty * z - s * x, 0,
tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
0, 0, 0, 1
);
return this;
},
makeScale: function ( x, y, z ) {
this.set(
x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1
);
return this;
},
makeShear: function ( x, y, z ) {
this.set(
1, y, z, 0,
x, 1, z, 0,
x, y, 1, 0,
0, 0, 0, 1
);
return this;
},
compose: function ( position, quaternion, scale ) {
this.makeRotationFromQuaternion( quaternion );
this.scale( scale );
this.setPosition( position );
return this;
},
decompose: function () {
var vector = new Vector3();
var matrix = new Matrix4();
return function decompose( position, quaternion, scale ) {
var te = this.elements;
var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
// if determine is negative, we need to invert one scale
var det = this.determinant();
if ( det < 0 ) { sx = - sx; }
position.x = te[ 12 ];
position.y = te[ 13 ];
position.z = te[ 14 ];
// scale the rotation part
matrix.copy( this );
var invSX = 1 / sx;
var invSY = 1 / sy;
var invSZ = 1 / sz;
matrix.elements[ 0 ] *= invSX;
matrix.elements[ 1 ] *= invSX;
matrix.elements[ 2 ] *= invSX;
matrix.elements[ 4 ] *= invSY;
matrix.elements[ 5 ] *= invSY;
matrix.elements[ 6 ] *= invSY;
matrix.elements[ 8 ] *= invSZ;
matrix.elements[ 9 ] *= invSZ;
matrix.elements[ 10 ] *= invSZ;
quaternion.setFromRotationMatrix( matrix );
scale.x = sx;
scale.y = sy;
scale.z = sz;
return this;
};
}(),
makePerspective: function ( left, right, top, bottom, near, far ) {
if ( far === undefined ) {
console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
}
var te = this.elements;
var x = 2 * near / ( right - left );
var y = 2 * near / ( top - bottom );
var a = ( right + left ) / ( right - left );
var b = ( top + bottom ) / ( top - bottom );
var c = - ( far + near ) / ( far - near );
var d = - 2 * far * near / ( far - near );
te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
return this;
},
makeOrthographic: function ( left, right, top, bottom, near, far ) {
var te = this.elements;
var w = 1.0 / ( right - left );
var h = 1.0 / ( top - bottom );
var p = 1.0 / ( far - near );
var x = ( right + left ) * w;
var y = ( top + bottom ) * h;
var z = ( far + near ) * p;
te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z;
te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
return this;
},
equals: function ( matrix ) {
var te = this.elements;
var me = matrix.elements;
for ( var i = 0; i < 16; i ++ ) {
if ( te[ i ] !== me[ i ] ) { return false; }
}
return true;
},
fromArray: function ( array, offset ) {
var this$1 = this;
if ( offset === undefined ) { offset = 0; }
for ( var i = 0; i < 16; i ++ ) {
this$1.elements[ i ] = array[ i + offset ];
}
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
var te = this.elements;
array[ offset ] = te[ 0 ];
array[ offset + 1 ] = te[ 1 ];
array[ offset + 2 ] = te[ 2 ];
array[ offset + 3 ] = te[ 3 ];
array[ offset + 4 ] = te[ 4 ];
array[ offset + 5 ] = te[ 5 ];
array[ offset + 6 ] = te[ 6 ];
array[ offset + 7 ] = te[ 7 ];
array[ offset + 8 ] = te[ 8 ];
array[ offset + 9 ] = te[ 9 ];
array[ offset + 10 ] = te[ 10 ];
array[ offset + 11 ] = te[ 11 ];
array[ offset + 12 ] = te[ 12 ];
array[ offset + 13 ] = te[ 13 ];
array[ offset + 14 ] = te[ 14 ];
array[ offset + 15 ] = te[ 15 ];
return array;
}
} );
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
* @author WestLangley / http://github.com/WestLangley
* @author bhouston / http://clara.io
*/
function Quaternion( x, y, z, w ) {
this._x = x || 0;
this._y = y || 0;
this._z = z || 0;
this._w = ( w !== undefined ) ? w : 1;
}
Object.assign( Quaternion, {
slerp: function ( qa, qb, qm, t ) {
return qm.copy( qa ).slerp( qb, t );
},
slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
// fuzz-free, array-based Quaternion SLERP operation
var x0 = src0[ srcOffset0 + 0 ],
y0 = src0[ srcOffset0 + 1 ],
z0 = src0[ srcOffset0 + 2 ],
w0 = src0[ srcOffset0 + 3 ],
x1 = src1[ srcOffset1 + 0 ],
y1 = src1[ srcOffset1 + 1 ],
z1 = src1[ srcOffset1 + 2 ],
w1 = src1[ srcOffset1 + 3 ];
if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
var s = 1 - t,
cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
dir = ( cos >= 0 ? 1 : - 1 ),
sqrSin = 1 - cos * cos;
// Skip the Slerp for tiny steps to avoid numeric problems:
if ( sqrSin > Number.EPSILON ) {
var sin = Math.sqrt( sqrSin ),
len = Math.atan2( sin, cos * dir );
s = Math.sin( s * len ) / sin;
t = Math.sin( t * len ) / sin;
}
var tDir = t * dir;
x0 = x0 * s + x1 * tDir;
y0 = y0 * s + y1 * tDir;
z0 = z0 * s + z1 * tDir;
w0 = w0 * s + w1 * tDir;
// Normalize in case we just did a lerp:
if ( s === 1 - t ) {
var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
x0 *= f;
y0 *= f;
z0 *= f;
w0 *= f;
}
}
dst[ dstOffset ] = x0;
dst[ dstOffset + 1 ] = y0;
dst[ dstOffset + 2 ] = z0;
dst[ dstOffset + 3 ] = w0;
}
} );
Object.defineProperties( Quaternion.prototype, {
x: {
get: function () {
return this._x;
},
set: function ( value ) {
this._x = value;
this.onChangeCallback();
}
},
y: {
get: function () {
return this._y;
},
set: function ( value ) {
this._y = value;
this.onChangeCallback();
}
},
z: {
get: function () {
return this._z;
},
set: function ( value ) {
this._z = value;
this.onChangeCallback();
}
},
w: {
get: function () {
return this._w;
},
set: function ( value ) {
this._w = value;
this.onChangeCallback();
}
}
} );
Object.assign( Quaternion.prototype, {
set: function ( x, y, z, w ) {
this._x = x;
this._y = y;
this._z = z;
this._w = w;
this.onChangeCallback();
return this;
},
clone: function () {
return new this.constructor( this._x, this._y, this._z, this._w );
},
copy: function ( quaternion ) {
this._x = quaternion.x;
this._y = quaternion.y;
this._z = quaternion.z;
this._w = quaternion.w;
this.onChangeCallback();
return this;
},
setFromEuler: function ( euler, update ) {
if ( ! ( euler && euler.isEuler ) ) {
throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
}
var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
// http://www.mathworks.com/matlabcentral/fileexchange/
// 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
// content/SpinCalc.m
var cos = Math.cos;
var sin = Math.sin;
var c1 = cos( x / 2 );
var c2 = cos( y / 2 );
var c3 = cos( z / 2 );
var s1 = sin( x / 2 );
var s2 = sin( y / 2 );
var s3 = sin( z / 2 );
if ( order === 'XYZ' ) {
this._x = s1 * c2 * c3 + c1 * s2 * s3;
this._y = c1 * s2 * c3 - s1 * c2 * s3;
this._z = c1 * c2 * s3 + s1 * s2 * c3;
this._w = c1 * c2 * c3 - s1 * s2 * s3;
} else if ( order === 'YXZ' ) {
this._x = s1 * c2 * c3 + c1 * s2 * s3;
this._y = c1 * s2 * c3 - s1 * c2 * s3;
this._z = c1 * c2 * s3 - s1 * s2 * c3;
this._w = c1 * c2 * c3 + s1 * s2 * s3;
} else if ( order === 'ZXY' ) {
this._x = s1 * c2 * c3 - c1 * s2 * s3;
this._y = c1 * s2 * c3 + s1 * c2 * s3;
this._z = c1 * c2 * s3 + s1 * s2 * c3;
this._w = c1 * c2 * c3 - s1 * s2 * s3;
} else if ( order === 'ZYX' ) {
this._x = s1 * c2 * c3 - c1 * s2 * s3;
this._y = c1 * s2 * c3 + s1 * c2 * s3;
this._z = c1 * c2 * s3 - s1 * s2 * c3;
this._w = c1 * c2 * c3 + s1 * s2 * s3;
} else if ( order === 'YZX' ) {
this._x = s1 * c2 * c3 + c1 * s2 * s3;
this._y = c1 * s2 * c3 + s1 * c2 * s3;
this._z = c1 * c2 * s3 - s1 * s2 * c3;
this._w = c1 * c2 * c3 - s1 * s2 * s3;
} else if ( order === 'XZY' ) {
this._x = s1 * c2 * c3 - c1 * s2 * s3;
this._y = c1 * s2 * c3 - s1 * c2 * s3;
this._z = c1 * c2 * s3 + s1 * s2 * c3;
this._w = c1 * c2 * c3 + s1 * s2 * s3;
}
if ( update !== false ) { this.onChangeCallback(); }
return this;
},
setFromAxisAngle: function ( axis, angle ) {
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
// assumes axis is normalized
var halfAngle = angle / 2, s = Math.sin( halfAngle );
this._x = axis.x * s;
this._y = axis.y * s;
this._z = axis.z * s;
this._w = Math.cos( halfAngle );
this.onChangeCallback();
return this;
},
setFromRotationMatrix: function ( m ) {
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
var te = m.elements,
m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
trace = m11 + m22 + m33,
s;
if ( trace > 0 ) {
s = 0.5 / Math.sqrt( trace + 1.0 );
this._w = 0.25 / s;
this._x = ( m32 - m23 ) * s;
this._y = ( m13 - m31 ) * s;
this._z = ( m21 - m12 ) * s;
} else if ( m11 > m22 && m11 > m33 ) {
s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
this._w = ( m32 - m23 ) / s;
this._x = 0.25 * s;
this._y = ( m12 + m21 ) / s;
this._z = ( m13 + m31 ) / s;
} else if ( m22 > m33 ) {
s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
this._w = ( m13 - m31 ) / s;
this._x = ( m12 + m21 ) / s;
this._y = 0.25 * s;
this._z = ( m23 + m32 ) / s;
} else {
s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
this._w = ( m21 - m12 ) / s;
this._x = ( m13 + m31 ) / s;
this._y = ( m23 + m32 ) / s;
this._z = 0.25 * s;
}
this.onChangeCallback();
return this;
},
setFromUnitVectors: function () {
// assumes direction vectors vFrom and vTo are normalized
var v1 = new Vector3();
var r;
var EPS = 0.000001;
return function setFromUnitVectors( vFrom, vTo ) {
if ( v1 === undefined ) { v1 = new Vector3(); }
r = vFrom.dot( vTo ) + 1;
if ( r < EPS ) {
r = 0;
if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
v1.set( - vFrom.y, vFrom.x, 0 );
} else {
v1.set( 0, - vFrom.z, vFrom.y );
}
} else {
v1.crossVectors( vFrom, vTo );
}
this._x = v1.x;
this._y = v1.y;
this._z = v1.z;
this._w = r;
return this.normalize();
};
}(),
inverse: function () {
return this.conjugate().normalize();
},
conjugate: function () {
this._x *= - 1;
this._y *= - 1;
this._z *= - 1;
this.onChangeCallback();
return this;
},
dot: function ( v ) {
return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
},
lengthSq: function () {
return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
},
length: function () {
return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
},
normalize: function () {
var l = this.length();
if ( l === 0 ) {
this._x = 0;
this._y = 0;
this._z = 0;
this._w = 1;
} else {
l = 1 / l;
this._x = this._x * l;
this._y = this._y * l;
this._z = this._z * l;
this._w = this._w * l;
}
this.onChangeCallback();
return this;
},
multiply: function ( q, p ) {
if ( p !== undefined ) {
console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
return this.multiplyQuaternions( q, p );
}
return this.multiplyQuaternions( this, q );
},
premultiply: function ( q ) {
return this.multiplyQuaternions( q, this );
},
multiplyQuaternions: function ( a, b ) {
// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
this.onChangeCallback();
return this;
},
slerp: function ( qb, t ) {
if ( t === 0 ) { return this; }
if ( t === 1 ) { return this.copy( qb ); }
var x = this._x, y = this._y, z = this._z, w = this._w;
// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
if ( cosHalfTheta < 0 ) {
this._w = - qb._w;
this._x = - qb._x;
this._y = - qb._y;
this._z = - qb._z;
cosHalfTheta = - cosHalfTheta;
} else {
this.copy( qb );
}
if ( cosHalfTheta >= 1.0 ) {
this._w = w;
this._x = x;
this._y = y;
this._z = z;
return this;
}
var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
if ( Math.abs( sinHalfTheta ) < 0.001 ) {
this._w = 0.5 * ( w + this._w );
this._x = 0.5 * ( x + this._x );
this._y = 0.5 * ( y + this._y );
this._z = 0.5 * ( z + this._z );
return this;
}
var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
this._w = ( w * ratioA + this._w * ratioB );
this._x = ( x * ratioA + this._x * ratioB );
this._y = ( y * ratioA + this._y * ratioB );
this._z = ( z * ratioA + this._z * ratioB );
this.onChangeCallback();
return this;
},
equals: function ( quaternion ) {
return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
},
fromArray: function ( array, offset ) {
if ( offset === undefined ) { offset = 0; }
this._x = array[ offset ];
this._y = array[ offset + 1 ];
this._z = array[ offset + 2 ];
this._w = array[ offset + 3 ];
this.onChangeCallback();
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
array[ offset ] = this._x;
array[ offset + 1 ] = this._y;
array[ offset + 2 ] = this._z;
array[ offset + 3 ] = this._w;
return array;
},
onChange: function ( callback ) {
this.onChangeCallback = callback;
return this;
},
onChangeCallback: function () {}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author kile / http://kile.stravaganza.org/
* @author philogb / http://blog.thejit.org/
* @author mikael emtinger / http://gomo.se/
* @author egraether / http://egraether.com/
* @author WestLangley / http://github.com/WestLangley
*/
function Vector3( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
}
Object.assign( Vector3.prototype, {
isVector3: true,
set: function ( x, y, z ) {
this.x = x;
this.y = y;
this.z = z;
return this;
},
setScalar: function ( scalar ) {
this.x = scalar;
this.y = scalar;
this.z = scalar;
return this;
},
setX: function ( x ) {
this.x = x;
return this;
},
setY: function ( y ) {
this.y = y;
return this;
},
setZ: function ( z ) {
this.z = z;
return this;
},
setComponent: function ( index, value ) {
switch ( index ) {
case 0: this.x = value; break;
case 1: this.y = value; break;
case 2: this.z = value; break;
default: throw new Error( 'index is out of range: ' + index );
}
return this;
},
getComponent: function ( index ) {
switch ( index ) {
case 0: return this.x;
case 1: return this.y;
case 2: return this.z;
default: throw new Error( 'index is out of range: ' + index );
}
},
clone: function () {
return new this.constructor( this.x, this.y, this.z );
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
return this;
},
add: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
return this.addVectors( v, w );
}
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
},
addScalar: function ( s ) {
this.x += s;
this.y += s;
this.z += s;
return this;
},
addVectors: function ( a, b ) {
this.x = a.x + b.x;
this.y = a.y + b.y;
this.z = a.z + b.z;
return this;
},
addScaledVector: function ( v, s ) {
this.x += v.x * s;
this.y += v.y * s;
this.z += v.z * s;
return this;
},
sub: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
return this.subVectors( v, w );
}
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
return this;
},
subScalar: function ( s ) {
this.x -= s;
this.y -= s;
this.z -= s;
return this;
},
subVectors: function ( a, b ) {
this.x = a.x - b.x;
this.y = a.y - b.y;
this.z = a.z - b.z;
return this;
},
multiply: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
return this.multiplyVectors( v, w );
}
this.x *= v.x;
this.y *= v.y;
this.z *= v.z;
return this;
},
multiplyScalar: function ( scalar ) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
return this;
},
multiplyVectors: function ( a, b ) {
this.x = a.x * b.x;
this.y = a.y * b.y;
this.z = a.z * b.z;
return this;
},
applyEuler: function () {
var quaternion = new Quaternion();
return function applyEuler( euler ) {
if ( ! ( euler && euler.isEuler ) ) {
console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
}
return this.applyQuaternion( quaternion.setFromEuler( euler ) );
};
}(),
applyAxisAngle: function () {
var quaternion = new Quaternion();
return function applyAxisAngle( axis, angle ) {
return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
};
}(),
applyMatrix3: function ( m ) {
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
return this;
},
applyMatrix4: function ( m ) {
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
return this;
},
applyQuaternion: function ( q ) {
var x = this.x, y = this.y, z = this.z;
var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
// calculate quat * vector
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = - qx * x - qy * y - qz * z;
// calculate result * inverse quat
this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
return this;
},
project: function () {
var matrix = new Matrix4();
return function project( camera ) {
matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
return this.applyMatrix4( matrix );
};
}(),
unproject: function () {
var matrix = new Matrix4();
return function unproject( camera ) {
matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
return this.applyMatrix4( matrix );
};
}(),
transformDirection: function ( m ) {
// input: THREE.Matrix4 affine matrix
// vector interpreted as a direction
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
return this.normalize();
},
divide: function ( v ) {
this.x /= v.x;
this.y /= v.y;
this.z /= v.z;
return this;
},
divideScalar: function ( scalar ) {
return this.multiplyScalar( 1 / scalar );
},
min: function ( v ) {
this.x = Math.min( this.x, v.x );
this.y = Math.min( this.y, v.y );
this.z = Math.min( this.z, v.z );
return this;
},
max: function ( v ) {
this.x = Math.max( this.x, v.x );
this.y = Math.max( this.y, v.y );
this.z = Math.max( this.z, v.z );
return this;
},
clamp: function ( min, max ) {
// assumes min < max, componentwise
this.x = Math.max( min.x, Math.min( max.x, this.x ) );
this.y = Math.max( min.y, Math.min( max.y, this.y ) );
this.z = Math.max( min.z, Math.min( max.z, this.z ) );
return this;
},
clampScalar: function () {
var min = new Vector3();
var max = new Vector3();
return function clampScalar( minVal, maxVal ) {
min.set( minVal, minVal, minVal );
max.set( maxVal, maxVal, maxVal );
return this.clamp( min, max );
};
}(),
clampLength: function ( min, max ) {
var length = this.length();
return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
},
floor: function () {
this.x = Math.floor( this.x );
this.y = Math.floor( this.y );
this.z = Math.floor( this.z );
return this;
},
ceil: function () {
this.x = Math.ceil( this.x );
this.y = Math.ceil( this.y );
this.z = Math.ceil( this.z );
return this;
},
round: function () {
this.x = Math.round( this.x );
this.y = Math.round( this.y );
this.z = Math.round( this.z );
return this;
},
roundToZero: function () {
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
return this;
},
negate: function () {
this.x = - this.x;
this.y = - this.y;
this.z = - this.z;
return this;
},
dot: function ( v ) {
return this.x * v.x + this.y * v.y + this.z * v.z;
},
// TODO lengthSquared?
lengthSq: function () {
return this.x * this.x + this.y * this.y + this.z * this.z;
},
length: function () {
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
},
manhattanLength: function () {
return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
},
normalize: function () {
return this.divideScalar( this.length() || 1 );
},
setLength: function ( length ) {
return this.normalize().multiplyScalar( length );
},
lerp: function ( v, alpha ) {
this.x += ( v.x - this.x ) * alpha;
this.y += ( v.y - this.y ) * alpha;
this.z += ( v.z - this.z ) * alpha;
return this;
},
lerpVectors: function ( v1, v2, alpha ) {
return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
},
cross: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
return this.crossVectors( v, w );
}
return this.crossVectors( this, v );
},
crossVectors: function ( a, b ) {
var ax = a.x, ay = a.y, az = a.z;
var bx = b.x, by = b.y, bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
},
projectOnVector: function ( vector ) {
var scalar = vector.dot( this ) / vector.lengthSq();
return this.copy( vector ).multiplyScalar( scalar );
},
projectOnPlane: function () {
var v1 = new Vector3();
return function projectOnPlane( planeNormal ) {
v1.copy( this ).projectOnVector( planeNormal );
return this.sub( v1 );
};
}(),
reflect: function () {
// reflect incident vector off plane orthogonal to normal
// normal is assumed to have unit length
var v1 = new Vector3();
return function reflect( normal ) {
return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
};
}(),
angleTo: function ( v ) {
var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
// clamp, to handle numerical problems
return Math.acos( _Math.clamp( theta, - 1, 1 ) );
},
distanceTo: function ( v ) {
return Math.sqrt( this.distanceToSquared( v ) );
},
distanceToSquared: function ( v ) {
var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
return dx * dx + dy * dy + dz * dz;
},
manhattanDistanceTo: function ( v ) {
return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
},
setFromSpherical: function ( s ) {
var sinPhiRadius = Math.sin( s.phi ) * s.radius;
this.x = sinPhiRadius * Math.sin( s.theta );
this.y = Math.cos( s.phi ) * s.radius;
this.z = sinPhiRadius * Math.cos( s.theta );
return this;
},
setFromCylindrical: function ( c ) {
this.x = c.radius * Math.sin( c.theta );
this.y = c.y;
this.z = c.radius * Math.cos( c.theta );
return this;
},
setFromMatrixPosition: function ( m ) {
var e = m.elements;
this.x = e[ 12 ];
this.y = e[ 13 ];
this.z = e[ 14 ];
return this;
},
setFromMatrixScale: function ( m ) {
var sx = this.setFromMatrixColumn( m, 0 ).length();
var sy = this.setFromMatrixColumn( m, 1 ).length();
var sz = this.setFromMatrixColumn( m, 2 ).length();
this.x = sx;
this.y = sy;
this.z = sz;
return this;
},
setFromMatrixColumn: function ( m, index ) {
return this.fromArray( m.elements, index * 4 );
},
equals: function ( v ) {
return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
},
fromArray: function ( array, offset ) {
if ( offset === undefined ) { offset = 0; }
this.x = array[ offset ];
this.y = array[ offset + 1 ];
this.z = array[ offset + 2 ];
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
array[ offset ] = this.x;
array[ offset + 1 ] = this.y;
array[ offset + 2 ] = this.z;
return array;
},
fromBufferAttribute: function ( attribute, index, offset ) {
if ( offset !== undefined ) {
console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
}
this.x = attribute.getX( index );
this.y = attribute.getY( index );
this.z = attribute.getZ( index );
return this;
}
} );
/**
* @author alteredq / http://alteredqualia.com/
* @author WestLangley / http://github.com/WestLangley
* @author bhouston / http://clara.io
* @author tschw
*/
function Matrix3() {
this.elements = [
1, 0, 0,
0, 1, 0,
0, 0, 1
];
if ( arguments.length > 0 ) {
console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
}
}
Object.assign( Matrix3.prototype, {
isMatrix3: true,
set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
var te = this.elements;
te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
return this;
},
identity: function () {
this.set(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
return this;
},
clone: function () {
return new this.constructor().fromArray( this.elements );
},
copy: function ( m ) {
var te = this.elements;
var me = m.elements;
te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
return this;
},
setFromMatrix4: function ( m ) {
var me = m.elements;
this.set(
me[ 0 ], me[ 4 ], me[ 8 ],
me[ 1 ], me[ 5 ], me[ 9 ],
me[ 2 ], me[ 6 ], me[ 10 ]
);
return this;
},
applyToBufferAttribute: function () {
var v1 = new Vector3();
return function applyToBufferAttribute( attribute ) {
var this$1 = this;
for ( var i = 0, l = attribute.count; i < l; i ++ ) {
v1.x = attribute.getX( i );
v1.y = attribute.getY( i );
v1.z = attribute.getZ( i );
v1.applyMatrix3( this$1 );
attribute.setXYZ( i, v1.x, v1.y, v1.z );
}
return attribute;
};
}(),
multiply: function ( m ) {
return this.multiplyMatrices( this, m );
},
premultiply: function ( m ) {
return this.multiplyMatrices( m, this );
},
multiplyMatrices: function ( a, b ) {
var ae = a.elements;
var be = b.elements;
var te = this.elements;
var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
return this;
},
multiplyScalar: function ( s ) {
var te = this.elements;
te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
return this;
},
determinant: function () {
var te = this.elements;
var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
},
getInverse: function ( matrix, throwOnDegenerate ) {
if ( matrix && matrix.isMatrix4 ) {
console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." );
}
var me = matrix.elements,
te = this.elements,
n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
t11 = n33 * n22 - n32 * n23,
t12 = n32 * n13 - n33 * n12,
t13 = n23 * n12 - n22 * n13,
det = n11 * t11 + n21 * t12 + n31 * t13;
if ( det === 0 ) {
var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
if ( throwOnDegenerate === true ) {
throw new Error( msg );
} else {
console.warn( msg );
}
return this.identity();
}
var detInv = 1 / det;
te[ 0 ] = t11 * detInv;
te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
te[ 3 ] = t12 * detInv;
te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
te[ 6 ] = t13 * detInv;
te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
return this;
},
transpose: function () {
var tmp, m = this.elements;
tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
return this;
},
getNormalMatrix: function ( matrix4 ) {
return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
},
transposeIntoArray: function ( r ) {
var m = this.elements;
r[ 0 ] = m[ 0 ];
r[ 1 ] = m[ 3 ];
r[ 2 ] = m[ 6 ];
r[ 3 ] = m[ 1 ];
r[ 4 ] = m[ 4 ];
r[ 5 ] = m[ 7 ];
r[ 6 ] = m[ 2 ];
r[ 7 ] = m[ 5 ];
r[ 8 ] = m[ 8 ];
return this;
},
setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {
var c = Math.cos( rotation );
var s = Math.sin( rotation );
this.set(
sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
0, 0, 1
);
},
scale: function ( sx, sy ) {
var te = this.elements;
te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
return this;
},
rotate: function ( theta ) {
var c = Math.cos( theta );
var s = Math.sin( theta );
var te = this.elements;
var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
te[ 0 ] = c * a11 + s * a21;
te[ 3 ] = c * a12 + s * a22;
te[ 6 ] = c * a13 + s * a23;
te[ 1 ] = - s * a11 + c * a21;
te[ 4 ] = - s * a12 + c * a22;
te[ 7 ] = - s * a13 + c * a23;
return this;
},
translate: function ( tx, ty ) {
var te = this.elements;
te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
return this;
},
equals: function ( matrix ) {
var te = this.elements;
var me = matrix.elements;
for ( var i = 0; i < 9; i ++ ) {
if ( te[ i ] !== me[ i ] ) { return false; }
}
return true;
},
fromArray: function ( array, offset ) {
var this$1 = this;
if ( offset === undefined ) { offset = 0; }
for ( var i = 0; i < 9; i ++ ) {
this$1.elements[ i ] = array[ i + offset ];
}
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
var te = this.elements;
array[ offset ] = te[ 0 ];
array[ offset + 1 ] = te[ 1 ];
array[ offset + 2 ] = te[ 2 ];
array[ offset + 3 ] = te[ 3 ];
array[ offset + 4 ] = te[ 4 ];
array[ offset + 5 ] = te[ 5 ];
array[ offset + 6 ] = te[ 6 ];
array[ offset + 7 ] = te[ 7 ];
array[ offset + 8 ] = te[ 8 ];
return array;
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
* @author szimek / https://github.com/szimek/
*/
var textureId = 0;
function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
Object.defineProperty( this, 'id', { value: textureId ++ } );
this.uuid = _Math.generateUUID();
this.name = '';
this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
this.mipmaps = [];
this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
this.format = format !== undefined ? format : RGBAFormat;
this.type = type !== undefined ? type : UnsignedByteType;
this.offset = new Vector2( 0, 0 );
this.repeat = new Vector2( 1, 1 );
this.center = new Vector2( 0, 0 );
this.rotation = 0;
this.matrixAutoUpdate = true;
this.matrix = new Matrix3();
this.generateMipmaps = true;
this.premultiplyAlpha = false;
this.flipY = true;
this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
//
// Also changing the encoding after already used by a Material will not automatically make the Material
// update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
this.encoding = encoding !== undefined ? encoding : LinearEncoding;
this.version = 0;
this.onUpdate = null;
}
Texture.DEFAULT_IMAGE = undefined;
Texture.DEFAULT_MAPPING = UVMapping;
Object.defineProperty( Texture.prototype, "needsUpdate", {
set: function ( value ) {
if ( value === true ) { this.version ++; }
}
} );
Object.assign( Texture.prototype, EventDispatcher.prototype, {
constructor: Texture,
isTexture: true,
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( source ) {
this.name = source.name;
this.image = source.image;
this.mipmaps = source.mipmaps.slice( 0 );
this.mapping = source.mapping;
this.wrapS = source.wrapS;
this.wrapT = source.wrapT;
this.magFilter = source.magFilter;
this.minFilter = source.minFilter;
this.anisotropy = source.anisotropy;
this.format = source.format;
this.type = source.type;
this.offset.copy( source.offset );
this.repeat.copy( source.repeat );
this.center.copy( source.center );
this.rotation = source.rotation;
this.matrixAutoUpdate = source.matrixAutoUpdate;
this.matrix.copy( source.matrix );
this.generateMipmaps = source.generateMipmaps;
this.premultiplyAlpha = source.premultiplyAlpha;
this.flipY = source.flipY;
this.unpackAlignment = source.unpackAlignment;
this.encoding = source.encoding;
return this;
},
toJSON: function ( meta ) {
var isRootObject = ( meta === undefined || typeof meta === 'string' );
if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
return meta.textures[ this.uuid ];
}
function getDataURL( image ) {
var canvas;
if ( image instanceof HTMLCanvasElement ) {
canvas = image;
} else {
canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext( '2d' );
if ( image instanceof ImageData ) {
context.putImageData( image, 0, 0 );
} else {
context.drawImage( image, 0, 0, image.width, image.height );
}
}
if ( canvas.width > 2048 || canvas.height > 2048 ) {
return canvas.toDataURL( 'image/jpeg', 0.6 );
} else {
return canvas.toDataURL( 'image/png' );
}
}
var output = {
metadata: {
version: 4.5,
type: 'Texture',
generator: 'Texture.toJSON'
},
uuid: this.uuid,
name: this.name,
mapping: this.mapping,
repeat: [ this.repeat.x, this.repeat.y ],
offset: [ this.offset.x, this.offset.y ],
center: [ this.center.x, this.center.y ],
rotation: this.rotation,
wrap: [ this.wrapS, this.wrapT ],
minFilter: this.minFilter,
magFilter: this.magFilter,
anisotropy: this.anisotropy,
flipY: this.flipY
};
if ( this.image !== undefined ) {
// TODO: Move to THREE.Image
var image = this.image;
if ( image.uuid === undefined ) {
image.uuid = _Math.generateUUID(); // UGH
}
if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
meta.images[ image.uuid ] = {
uuid: image.uuid,
url: getDataURL( image )
};
}
output.image = image.uuid;
}
if ( ! isRootObject ) {
meta.textures[ this.uuid ] = output;
}
return output;
},
dispose: function () {
this.dispatchEvent( { type: 'dispose' } );
},
transformUv: function ( uv ) {
if ( this.mapping !== UVMapping ) { return; }
uv.applyMatrix3( this.matrix );
if ( uv.x < 0 || uv.x > 1 ) {
switch ( this.wrapS ) {
case RepeatWrapping:
uv.x = uv.x - Math.floor( uv.x );
break;
case ClampToEdgeWrapping:
uv.x = uv.x < 0 ? 0 : 1;
break;
case MirroredRepeatWrapping:
if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
uv.x = Math.ceil( uv.x ) - uv.x;
} else {
uv.x = uv.x - Math.floor( uv.x );
}
break;
}
}
if ( uv.y < 0 || uv.y > 1 ) {
switch ( this.wrapT ) {
case RepeatWrapping:
uv.y = uv.y - Math.floor( uv.y );
break;
case ClampToEdgeWrapping:
uv.y = uv.y < 0 ? 0 : 1;
break;
case MirroredRepeatWrapping:
if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
uv.y = Math.ceil( uv.y ) - uv.y;
} else {
uv.y = uv.y - Math.floor( uv.y );
}
break;
}
}
if ( this.flipY ) {
uv.y = 1 - uv.y;
}
}
} );
/**
* @author supereggbert / http://www.paulbrunt.co.uk/
* @author philogb / http://blog.thejit.org/
* @author mikael emtinger / http://gomo.se/
* @author egraether / http://egraether.com/
* @author WestLangley / http://github.com/WestLangley
*/
function Vector4( x, y, z, w ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = ( w !== undefined ) ? w : 1;
}
Object.assign( Vector4.prototype, {
isVector4: true,
set: function ( x, y, z, w ) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
return this;
},
setScalar: function ( scalar ) {
this.x = scalar;
this.y = scalar;
this.z = scalar;
this.w = scalar;
return this;
},
setX: function ( x ) {
this.x = x;
return this;
},
setY: function ( y ) {
this.y = y;
return this;
},
setZ: function ( z ) {
this.z = z;
return this;
},
setW: function ( w ) {
this.w = w;
return this;
},
setComponent: function ( index, value ) {
switch ( index ) {
case 0: this.x = value; break;
case 1: this.y = value; break;
case 2: this.z = value; break;
case 3: this.w = value; break;
default: throw new Error( 'index is out of range: ' + index );
}
return this;
},
getComponent: function ( index ) {
switch ( index ) {
case 0: return this.x;
case 1: return this.y;
case 2: return this.z;
case 3: return this.w;
default: throw new Error( 'index is out of range: ' + index );
}
},
clone: function () {
return new this.constructor( this.x, this.y, this.z, this.w );
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
this.w = ( v.w !== undefined ) ? v.w : 1;
return this;
},
add: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
return this.addVectors( v, w );
}
this.x += v.x;
this.y += v.y;
this.z += v.z;
this.w += v.w;
return this;
},
addScalar: function ( s ) {
this.x += s;
this.y += s;
this.z += s;
this.w += s;
return this;
},
addVectors: function ( a, b ) {
this.x = a.x + b.x;
this.y = a.y + b.y;
this.z = a.z + b.z;
this.w = a.w + b.w;
return this;
},
addScaledVector: function ( v, s ) {
this.x += v.x * s;
this.y += v.y * s;
this.z += v.z * s;
this.w += v.w * s;
return this;
},
sub: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
return this.subVectors( v, w );
}
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
this.w -= v.w;
return this;
},
subScalar: function ( s ) {
this.x -= s;
this.y -= s;
this.z -= s;
this.w -= s;
return this;
},
subVectors: function ( a, b ) {
this.x = a.x - b.x;
this.y = a.y - b.y;
this.z = a.z - b.z;
this.w = a.w - b.w;
return this;
},
multiplyScalar: function ( scalar ) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
this.w *= scalar;
return this;
},
applyMatrix4: function ( m ) {
var x = this.x, y = this.y, z = this.z, w = this.w;
var e = m.elements;
this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
return this;
},
divideScalar: function ( scalar ) {
return this.multiplyScalar( 1 / scalar );
},
setAxisAngleFromQuaternion: function ( q ) {
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
// q is assumed to be normalized
this.w = 2 * Math.acos( q.w );
var s = Math.sqrt( 1 - q.w * q.w );
if ( s < 0.0001 ) {
this.x = 1;
this.y = 0;
this.z = 0;
} else {
this.x = q.x / s;
this.y = q.y / s;
this.z = q.z / s;
}
return this;
},
setAxisAngleFromRotationMatrix: function ( m ) {
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
var angle, x, y, z, // variables for result
epsilon = 0.01, // margin to allow for rounding errors
epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
te = m.elements,
m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
( Math.abs( m13 - m31 ) < epsilon ) &&
( Math.abs( m23 - m32 ) < epsilon ) ) {
// singularity found
// first check for identity matrix which must have +1 for all terms
// in leading diagonal and zero in other terms
if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
( Math.abs( m13 + m31 ) < epsilon2 ) &&
( Math.abs( m23 + m32 ) < epsilon2 ) &&
( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
// this singularity is identity matrix so angle = 0
this.set( 1, 0, 0, 0 );
return this; // zero angle, arbitrary axis
}
// otherwise this singularity is angle = 180
angle = Math.PI;
var xx = ( m11 + 1 ) / 2;
var yy = ( m22 + 1 ) / 2;
var zz = ( m33 + 1 ) / 2;
var xy = ( m12 + m21 ) / 4;
var xz = ( m13 + m31 ) / 4;
var yz = ( m23 + m32 ) / 4;
if ( ( xx > yy ) && ( xx > zz ) ) {
// m11 is the largest diagonal term
if ( xx < epsilon ) {
x = 0;
y = 0.707106781;
z = 0.707106781;
} else {
x = Math.sqrt( xx );
y = xy / x;
z = xz / x;
}
} else if ( yy > zz ) {
// m22 is the largest diagonal term
if ( yy < epsilon ) {
x = 0.707106781;
y = 0;
z = 0.707106781;
} else {
y = Math.sqrt( yy );
x = xy / y;
z = yz / y;
}
} else {
// m33 is the largest diagonal term so base result on this
if ( zz < epsilon ) {
x = 0.707106781;
y = 0.707106781;
z = 0;
} else {
z = Math.sqrt( zz );
x = xz / z;
y = yz / z;
}
}
this.set( x, y, z, angle );
return this; // return 180 deg rotation
}
// as we have reached here there are no singularities so we can handle normally
var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
( m13 - m31 ) * ( m13 - m31 ) +
( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
if ( Math.abs( s ) < 0.001 ) { s = 1; }
// prevent divide by zero, should not happen if matrix is orthogonal and should be
// caught by singularity test above, but I've left it in just in case
this.x = ( m32 - m23 ) / s;
this.y = ( m13 - m31 ) / s;
this.z = ( m21 - m12 ) / s;
this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
return this;
},
min: function ( v ) {
this.x = Math.min( this.x, v.x );
this.y = Math.min( this.y, v.y );
this.z = Math.min( this.z, v.z );
this.w = Math.min( this.w, v.w );
return this;
},
max: function ( v ) {
this.x = Math.max( this.x, v.x );
this.y = Math.max( this.y, v.y );
this.z = Math.max( this.z, v.z );
this.w = Math.max( this.w, v.w );
return this;
},
clamp: function ( min, max ) {
// assumes min < max, componentwise
this.x = Math.max( min.x, Math.min( max.x, this.x ) );
this.y = Math.max( min.y, Math.min( max.y, this.y ) );
this.z = Math.max( min.z, Math.min( max.z, this.z ) );
this.w = Math.max( min.w, Math.min( max.w, this.w ) );
return this;
},
clampScalar: function () {
var min, max;
return function clampScalar( minVal, maxVal ) {
if ( min === undefined ) {
min = new Vector4();
max = new Vector4();
}
min.set( minVal, minVal, minVal, minVal );
max.set( maxVal, maxVal, maxVal, maxVal );
return this.clamp( min, max );
};
}(),
clampLength: function ( min, max ) {
var length = this.length();
return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
},
floor: function () {
this.x = Math.floor( this.x );
this.y = Math.floor( this.y );
this.z = Math.floor( this.z );
this.w = Math.floor( this.w );
return this;
},
ceil: function () {
this.x = Math.ceil( this.x );
this.y = Math.ceil( this.y );
this.z = Math.ceil( this.z );
this.w = Math.ceil( this.w );
return this;
},
round: function () {
this.x = Math.round( this.x );
this.y = Math.round( this.y );
this.z = Math.round( this.z );
this.w = Math.round( this.w );
return this;
},
roundToZero: function () {
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
return this;
},
negate: function () {
this.x = - this.x;
this.y = - this.y;
this.z = - this.z;
this.w = - this.w;
return this;
},
dot: function ( v ) {
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
},
lengthSq: function () {
return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
},
length: function () {
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
},
manhattanLength: function () {
return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
},
normalize: function () {
return this.divideScalar( this.length() || 1 );
},
setLength: function ( length ) {
return this.normalize().multiplyScalar( length );
},
lerp: function ( v, alpha ) {
this.x += ( v.x - this.x ) * alpha;
this.y += ( v.y - this.y ) * alpha;
this.z += ( v.z - this.z ) * alpha;
this.w += ( v.w - this.w ) * alpha;
return this;
},
lerpVectors: function ( v1, v2, alpha ) {
return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
},
equals: function ( v ) {
return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
},
fromArray: function ( array, offset ) {
if ( offset === undefined ) { offset = 0; }
this.x = array[ offset ];
this.y = array[ offset + 1 ];
this.z = array[ offset + 2 ];
this.w = array[ offset + 3 ];
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
array[ offset ] = this.x;
array[ offset + 1 ] = this.y;
array[ offset + 2 ] = this.z;
array[ offset + 3 ] = this.w;
return array;
},
fromBufferAttribute: function ( attribute, index, offset ) {
if ( offset !== undefined ) {
console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
}
this.x = attribute.getX( index );
this.y = attribute.getY( index );
this.z = attribute.getZ( index );
this.w = attribute.getW( index );
return this;
}
} );
/**
* @author szimek / https://github.com/szimek/
* @author alteredq / http://alteredqualia.com/
* @author Marius Kintel / https://github.com/kintel
*/
/*
In options, we can specify:
* Texture parameters for an auto-generated target texture
* depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
*/
function WebGLRenderTarget( width, height, options ) {
this.uuid = _Math.generateUUID();
this.width = width;
this.height = height;
this.scissor = new Vector4( 0, 0, width, height );
this.scissorTest = false;
this.viewport = new Vector4( 0, 0, width, height );
options = options || {};
if ( options.minFilter === undefined ) { options.minFilter = LinearFilter; }
this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
}
Object.assign( WebGLRenderTarget.prototype, EventDispatcher.prototype, {
isWebGLRenderTarget: true,
setSize: function ( width, height ) {
if ( this.width !== width || this.height !== height ) {
this.width = width;
this.height = height;
this.dispose();
}
this.viewport.set( 0, 0, width, height );
this.scissor.set( 0, 0, width, height );
},
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( source ) {
this.width = source.width;
this.height = source.height;
this.viewport.copy( source.viewport );
this.texture = source.texture.clone();
this.depthBuffer = source.depthBuffer;
this.stencilBuffer = source.stencilBuffer;
this.depthTexture = source.depthTexture;
return this;
},
dispose: function () {
this.dispatchEvent( { type: 'dispose' } );
}
} );
/**
* @author alteredq / http://alteredqualia.com
*/
function WebGLRenderTargetCube( width, height, options ) {
WebGLRenderTarget.call( this, width, height, options );
this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
this.activeMipMapLevel = 0;
}
WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );
WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
/**
* @author alteredq / http://alteredqualia.com/
*/
function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
this.image = { data: data, width: width, height: height };
this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
this.generateMipmaps = false;
this.flipY = false;
this.unpackAlignment = 1;
}
DataTexture.prototype = Object.create( Texture.prototype );
DataTexture.prototype.constructor = DataTexture;
DataTexture.prototype.isDataTexture = true;
/**
* @author mrdoob / http://mrdoob.com/
*/
function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
images = images !== undefined ? images : [];
mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
this.flipY = false;
}
CubeTexture.prototype = Object.create( Texture.prototype );
CubeTexture.prototype.constructor = CubeTexture;
CubeTexture.prototype.isCubeTexture = true;
Object.defineProperty( CubeTexture.prototype, 'images', {
get: function () {
return this.image;
},
set: function ( value ) {
this.image = value;
}
} );
/**
* @author tschw
*
* Uniforms of a program.
* Those form a tree structure with a special top-level container for the root,
* which you get by calling 'new WebGLUniforms( gl, program, renderer )'.
*
*
* Properties of inner nodes including the top-level container:
*
* .seq - array of nested uniforms
* .map - nested uniforms by name
*
*
* Methods of all nodes except the top-level container:
*
* .setValue( gl, value, [renderer] )
*
* uploads a uniform value(s)
* the 'renderer' parameter is needed for sampler uniforms
*
*
* Static methods of the top-level container (renderer factorizations):
*
* .upload( gl, seq, values, renderer )
*
* sets uniforms in 'seq' to 'values[id].value'
*
* .seqWithValue( seq, values ) : filteredSeq
*
* filters 'seq' entries with corresponding entry in values
*
*
* Methods of the top-level container (renderer factorizations):
*
* .setValue( gl, name, value )
*
* sets uniform with name 'name' to 'value'
*
* .set( gl, obj, prop )
*
* sets uniform from object and property with same name than uniform
*
* .setOptional( gl, obj, prop )
*
* like .set for an optional property of the object
*
*/
var emptyTexture = new Texture();
var emptyCubeTexture = new CubeTexture();
// --- Base for inner nodes (including the root) ---
function UniformContainer() {
this.seq = [];
this.map = {};
}
// --- Utilities ---
// Array Caches (provide typed arrays for temporary by size)
var arrayCacheF32 = [];
var arrayCacheI32 = [];
// Float32Array caches used for uploading Matrix uniforms
var mat4array = new Float32Array( 16 );
var mat3array = new Float32Array( 9 );
// Flattening for arrays of vectors and matrices
function flatten( array, nBlocks, blockSize ) {
var firstElem = array[ 0 ];
if ( firstElem <= 0 || firstElem > 0 ) { return array; }
// unoptimized: ! isNaN( firstElem )
// see http://jacksondunstan.com/articles/983
var n = nBlocks * blockSize,
r = arrayCacheF32[ n ];
if ( r === undefined ) {
r = new Float32Array( n );
arrayCacheF32[ n ] = r;
}
if ( nBlocks !== 0 ) {
firstElem.toArray( r, 0 );
for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
offset += blockSize;
array[ i ].toArray( r, offset );
}
}
return r;
}
// Texture unit allocation
function allocTexUnits( renderer, n ) {
var r = arrayCacheI32[ n ];
if ( r === undefined ) {
r = new Int32Array( n );
arrayCacheI32[ n ] = r;
}
for ( var i = 0; i !== n; ++ i )
{ r[ i ] = renderer.allocTextureUnit(); }
return r;
}
// --- Setters ---
// Note: Defining these methods externally, because they come in a bunch
// and this way their names minify.
// Single scalar
function setValue1f( gl, v ) {
gl.uniform1f( this.addr, v );
}
function setValue1i( gl, v ) {
gl.uniform1i( this.addr, v );
}
// Single float vector (from flat array or THREE.VectorN)
function setValue2fv( gl, v ) {
if ( v.x === undefined ) {
gl.uniform2fv( this.addr, v );
} else {
gl.uniform2f( this.addr, v.x, v.y );
}
}
function setValue3fv( gl, v ) {
if ( v.x !== undefined ) {
gl.uniform3f( this.addr, v.x, v.y, v.z );
} else if ( v.r !== undefined ) {
gl.uniform3f( this.addr, v.r, v.g, v.b );
} else {
gl.uniform3fv( this.addr, v );
}
}
function setValue4fv( gl, v ) {
if ( v.x === undefined ) {
gl.uniform4fv( this.addr, v );
} else {
gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
}
}
// Single matrix (from flat array or MatrixN)
function setValue2fm( gl, v ) {
gl.uniformMatrix2fv( this.addr, false, v.elements || v );
}
function setValue3fm( gl, v ) {
if ( v.elements === undefined ) {
gl.uniformMatrix3fv( this.addr, false, v );
} else {
mat3array.set( v.elements );
gl.uniformMatrix3fv( this.addr, false, mat3array );
}
}
function setValue4fm( gl, v ) {
if ( v.elements === undefined ) {
gl.uniformMatrix4fv( this.addr, false, v );
} else {
mat4array.set( v.elements );
gl.uniformMatrix4fv( this.addr, false, mat4array );
}
}
// Single texture (2D / Cube)
function setValueT1( gl, v, renderer ) {
var unit = renderer.allocTextureUnit();
gl.uniform1i( this.addr, unit );
renderer.setTexture2D( v || emptyTexture, unit );
}
function setValueT6( gl, v, renderer ) {
var unit = renderer.allocTextureUnit();
gl.uniform1i( this.addr, unit );
renderer.setTextureCube( v || emptyCubeTexture, unit );
}
// Integer / Boolean vectors or arrays thereof (always flat arrays)
function setValue2iv( gl, v ) {
gl.uniform2iv( this.addr, v );
}
function setValue3iv( gl, v ) {
gl.uniform3iv( this.addr, v );
}
function setValue4iv( gl, v ) {
gl.uniform4iv( this.addr, v );
}
// Helper to pick the right setter for the singular case
function getSingularSetter( type ) {
switch ( type ) {
case 0x1406: return setValue1f; // FLOAT
case 0x8b50: return setValue2fv; // _VEC2
case 0x8b51: return setValue3fv; // _VEC3
case 0x8b52: return setValue4fv; // _VEC4
case 0x8b5a: return setValue2fm; // _MAT2
case 0x8b5b: return setValue3fm; // _MAT3
case 0x8b5c: return setValue4fm; // _MAT4
case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES
case 0x8b60: return setValueT6; // SAMPLER_CUBE
case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL
case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
}
}
// Array of scalars
function setValue1fv( gl, v ) {
gl.uniform1fv( this.addr, v );
}
function setValue1iv( gl, v ) {
gl.uniform1iv( this.addr, v );
}
// Array of vectors (flat or from THREE classes)
function setValueV2a( gl, v ) {
gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) );
}
function setValueV3a( gl, v ) {
gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) );
}
function setValueV4a( gl, v ) {
gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) );
}
// Array of matrices (flat or from THREE clases)
function setValueM2a( gl, v ) {
gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) );
}
function setValueM3a( gl, v ) {
gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) );
}
function setValueM4a( gl, v ) {
gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) );
}
// Array of textures (2D / Cube)
function setValueT1a( gl, v, renderer ) {
var n = v.length,
units = allocTexUnits( renderer, n );
gl.uniform1iv( this.addr, units );
for ( var i = 0; i !== n; ++ i ) {
renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
}
}
function setValueT6a( gl, v, renderer ) {
var n = v.length,
units = allocTexUnits( renderer, n );
gl.uniform1iv( this.addr, units );
for ( var i = 0; i !== n; ++ i ) {
renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
}
}
// Helper to pick the right setter for a pure (bottom-level) array
function getPureArraySetter( type ) {
switch ( type ) {
case 0x1406: return setValue1fv; // FLOAT
case 0x8b50: return setValueV2a; // _VEC2
case 0x8b51: return setValueV3a; // _VEC3
case 0x8b52: return setValueV4a; // _VEC4
case 0x8b5a: return setValueM2a; // _MAT2
case 0x8b5b: return setValueM3a; // _MAT3
case 0x8b5c: return setValueM4a; // _MAT4
case 0x8b5e: return setValueT1a; // SAMPLER_2D
case 0x8b60: return setValueT6a; // SAMPLER_CUBE
case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL
case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
}
}
// --- Uniform Classes ---
function SingleUniform( id, activeInfo, addr ) {
this.id = id;
this.addr = addr;
this.setValue = getSingularSetter( activeInfo.type );
// this.path = activeInfo.name; // DEBUG
}
function PureArrayUniform( id, activeInfo, addr ) {
this.id = id;
this.addr = addr;
this.size = activeInfo.size;
this.setValue = getPureArraySetter( activeInfo.type );
// this.path = activeInfo.name; // DEBUG
}
function StructuredUniform( id ) {
this.id = id;
UniformContainer.call( this ); // mix-in
}
StructuredUniform.prototype.setValue = function ( gl, value ) {
// Note: Don't need an extra 'renderer' parameter, since samplers
// are not allowed in structured uniforms.
var seq = this.seq;
for ( var i = 0, n = seq.length; i !== n; ++ i ) {
var u = seq[ i ];
u.setValue( gl, value[ u.id ] );
}
};
// --- Top-level ---
// Parser - builds up the property tree from the path strings
var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
// extracts
// - the identifier (member name or array index)
// - followed by an optional right bracket (found when array index)
// - followed by an optional left bracket or dot (type of subscript)
//
// Note: These portions can be read in a non-overlapping fashion and
// allow straightforward parsing of the hierarchy that WebGL encodes
// in the uniform names.
function addUniform( container, uniformObject ) {
container.seq.push( uniformObject );
container.map[ uniformObject.id ] = uniformObject;
}
function parseUniform( activeInfo, addr, container ) {
var path = activeInfo.name,
pathLength = path.length;
// reset RegExp object, because of the early exit of a previous run
RePathPart.lastIndex = 0;
for ( ; ; ) {
var match = RePathPart.exec( path ),
matchEnd = RePathPart.lastIndex,
id = match[ 1 ],
idIsIndex = match[ 2 ] === ']',
subscript = match[ 3 ];
if ( idIsIndex ) { id = id | 0; } // convert to integer
if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
// bare name or "pure" bottom-level array "[0]" suffix
addUniform( container, subscript === undefined ?
new SingleUniform( id, activeInfo, addr ) :
new PureArrayUniform( id, activeInfo, addr ) );
break;
} else {
// step into inner node / create it in case it doesn't exist
var map = container.map, next = map[ id ];
if ( next === undefined ) {
next = new StructuredUniform( id );
addUniform( container, next );
}
container = next;
}
}
}
// Root Container
function WebGLUniforms( gl, program, renderer ) {
var this$1 = this;
UniformContainer.call( this );
this.renderer = renderer;
var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
for ( var i = 0; i < n; ++ i ) {
var info = gl.getActiveUniform( program, i ),
path = info.name,
addr = gl.getUniformLocation( program, path );
parseUniform( info, addr, this$1 );
}
}
WebGLUniforms.prototype.setValue = function ( gl, name, value ) {
var u = this.map[ name ];
if ( u !== undefined ) { u.setValue( gl, value, this.renderer ); }
};
WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
var v = object[ name ];
if ( v !== undefined ) { this.setValue( gl, name, v ); }
};
// Static interface
WebGLUniforms.upload = function ( gl, seq, values, renderer ) {
for ( var i = 0, n = seq.length; i !== n; ++ i ) {
var u = seq[ i ],
v = values[ u.id ];
if ( v.needsUpdate !== false ) {
// note: always updating when .needsUpdate is undefined
u.setValue( gl, v.value, renderer );
}
}
};
WebGLUniforms.seqWithValue = function ( seq, values ) {
var r = [];
for ( var i = 0, n = seq.length; i !== n; ++ i ) {
var u = seq[ i ];
if ( u.id in values ) { r.push( u ); }
}
return r;
};
/**
* @author mrdoob / http://mrdoob.com/
*/
var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
function Color( r, g, b ) {
if ( g === undefined && b === undefined ) {
// r is THREE.Color, hex or string
return this.set( r );
}
return this.setRGB( r, g, b );
}
Object.assign( Color.prototype, {
isColor: true,
r: 1, g: 1, b: 1,
set: function ( value ) {
if ( value && value.isColor ) {
this.copy( value );
} else if ( typeof value === 'number' ) {
this.setHex( value );
} else if ( typeof value === 'string' ) {
this.setStyle( value );
}
return this;
},
setScalar: function ( scalar ) {
this.r = scalar;
this.g = scalar;
this.b = scalar;
return this;
},
setHex: function ( hex ) {
hex = Math.floor( hex );
this.r = ( hex >> 16 & 255 ) / 255;
this.g = ( hex >> 8 & 255 ) / 255;
this.b = ( hex & 255 ) / 255;
return this;
},
setRGB: function ( r, g, b ) {
this.r = r;
this.g = g;
this.b = b;
return this;
},
setHSL: function () {
function hue2rgb( p, q, t ) {
if ( t < 0 ) { t += 1; }
if ( t > 1 ) { t -= 1; }
if ( t < 1 / 6 ) { return p + ( q - p ) * 6 * t; }
if ( t < 1 / 2 ) { return q; }
if ( t < 2 / 3 ) { return p + ( q - p ) * 6 * ( 2 / 3 - t ); }
return p;
}
return function setHSL( h, s, l ) {
// h,s,l ranges are in 0.0 - 1.0
h = _Math.euclideanModulo( h, 1 );
s = _Math.clamp( s, 0, 1 );
l = _Math.clamp( l, 0, 1 );
if ( s === 0 ) {
this.r = this.g = this.b = l;
} else {
var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
var q = ( 2 * l ) - p;
this.r = hue2rgb( q, p, h + 1 / 3 );
this.g = hue2rgb( q, p, h );
this.b = hue2rgb( q, p, h - 1 / 3 );
}
return this;
};
}(),
setStyle: function ( style ) {
function handleAlpha( string ) {
if ( string === undefined ) { return; }
if ( parseFloat( string ) < 1 ) {
console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
}
}
var m;
if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
// rgb / hsl
var color;
var name = m[ 1 ];
var components = m[ 2 ];
switch ( name ) {
case 'rgb':
case 'rgba':
if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
// rgb(255,0,0) rgba(255,0,0,0.5)
this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
handleAlpha( color[ 5 ] );
return this;
}
if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
handleAlpha( color[ 5 ] );
return this;
}
break;
case 'hsl':
case 'hsla':
if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
var h = parseFloat( color[ 1 ] ) / 360;
var s = parseInt( color[ 2 ], 10 ) / 100;
var l = parseInt( color[ 3 ], 10 ) / 100;
handleAlpha( color[ 5 ] );
return this.setHSL( h, s, l );
}
break;
}
} else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
// hex color
var hex = m[ 1 ];
var size = hex.length;
if ( size === 3 ) {
// #ff0
this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
return this;
} else if ( size === 6 ) {
// #ff0000
this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
return this;
}
}
if ( style && style.length > 0 ) {
// color keywords
var hex = ColorKeywords[ style ];
if ( hex !== undefined ) {
// red
this.setHex( hex );
} else {
// unknown color
console.warn( 'THREE.Color: Unknown color ' + style );
}
}
return this;
},
clone: function () {
return new this.constructor( this.r, this.g, this.b );
},
copy: function ( color ) {
this.r = color.r;
this.g = color.g;
this.b = color.b;
return this;
},
copyGammaToLinear: function ( color, gammaFactor ) {
if ( gammaFactor === undefined ) { gammaFactor = 2.0; }
this.r = Math.pow( color.r, gammaFactor );
this.g = Math.pow( color.g, gammaFactor );
this.b = Math.pow( color.b, gammaFactor );
return this;
},
copyLinearToGamma: function ( color, gammaFactor ) {
if ( gammaFactor === undefined ) { gammaFactor = 2.0; }
var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
this.r = Math.pow( color.r, safeInverse );
this.g = Math.pow( color.g, safeInverse );
this.b = Math.pow( color.b, safeInverse );
return this;
},
convertGammaToLinear: function () {
var r = this.r, g = this.g, b = this.b;
this.r = r * r;
this.g = g * g;
this.b = b * b;
return this;
},
convertLinearToGamma: function () {
this.r = Math.sqrt( this.r );
this.g = Math.sqrt( this.g );
this.b = Math.sqrt( this.b );
return this;
},
getHex: function () {
return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
},
getHexString: function () {
return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
},
getHSL: function ( optionalTarget ) {
// h,s,l ranges are in 0.0 - 1.0
var hsl = optionalTarget || { h: 0, s: 0, l: 0 };
var r = this.r, g = this.g, b = this.b;
var max = Math.max( r, g, b );
var min = Math.min( r, g, b );
var hue, saturation;
var lightness = ( min + max ) / 2.0;
if ( min === max ) {
hue = 0;
saturation = 0;
} else {
var delta = max - min;
saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
switch ( max ) {
case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
case g: hue = ( b - r ) / delta + 2; break;
case b: hue = ( r - g ) / delta + 4; break;
}
hue /= 6;
}
hsl.h = hue;
hsl.s = saturation;
hsl.l = lightness;
return hsl;
},
getStyle: function () {
return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
},
offsetHSL: function ( h, s, l ) {
var hsl = this.getHSL();
hsl.h += h; hsl.s += s; hsl.l += l;
this.setHSL( hsl.h, hsl.s, hsl.l );
return this;
},
add: function ( color ) {
this.r += color.r;
this.g += color.g;
this.b += color.b;
return this;
},
addColors: function ( color1, color2 ) {
this.r = color1.r + color2.r;
this.g = color1.g + color2.g;
this.b = color1.b + color2.b;
return this;
},
addScalar: function ( s ) {
this.r += s;
this.g += s;
this.b += s;
return this;
},
sub: function ( color ) {
this.r = Math.max( 0, this.r - color.r );
this.g = Math.max( 0, this.g - color.g );
this.b = Math.max( 0, this.b - color.b );
return this;
},
multiply: function ( color ) {
this.r *= color.r;
this.g *= color.g;
this.b *= color.b;
return this;
},
multiplyScalar: function ( s ) {
this.r *= s;
this.g *= s;
this.b *= s;
return this;
},
lerp: function ( color, alpha ) {
this.r += ( color.r - this.r ) * alpha;
this.g += ( color.g - this.g ) * alpha;
this.b += ( color.b - this.b ) * alpha;
return this;
},
equals: function ( c ) {
return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
},
fromArray: function ( array, offset ) {
if ( offset === undefined ) { offset = 0; }
this.r = array[ offset ];
this.g = array[ offset + 1 ];
this.b = array[ offset + 2 ];
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
array[ offset ] = this.r;
array[ offset + 1 ] = this.g;
array[ offset + 2 ] = this.b;
return array;
},
toJSON: function () {
return this.getHex();
}
} );
/**
* Uniforms library for shared webgl shaders
*/
var UniformsLib = {
common: {
diffuse: { value: new Color( 0xeeeeee ) },
opacity: { value: 1.0 },
map: { value: null },
uvTransform: { value: new Matrix3() },
alphaMap: { value: null },
},
specularmap: {
specularMap: { value: null },
},
envmap: {
envMap: { value: null },
flipEnvMap: { value: - 1 },
reflectivity: { value: 1.0 },
refractionRatio: { value: 0.98 }
},
aomap: {
aoMap: { value: null },
aoMapIntensity: { value: 1 }
},
lightmap: {
lightMap: { value: null },
lightMapIntensity: { value: 1 }
},
emissivemap: {
emissiveMap: { value: null }
},
bumpmap: {
bumpMap: { value: null },
bumpScale: { value: 1 }
},
normalmap: {
normalMap: { value: null },
normalScale: { value: new Vector2( 1, 1 ) }
},
displacementmap: {
displacementMap: { value: null },
displacementScale: { value: 1 },
displacementBias: { value: 0 }
},
roughnessmap: {
roughnessMap: { value: null }
},
metalnessmap: {
metalnessMap: { value: null }
},
gradientmap: {
gradientMap: { value: null }
},
fog: {
fogDensity: { value: 0.00025 },
fogNear: { value: 1 },
fogFar: { value: 2000 },
fogColor: { value: new Color( 0xffffff ) }
},
lights: {
ambientLightColor: { value: [] },
directionalLights: { value: [], properties: {
direction: {},
color: {},
shadow: {},
shadowBias: {},
shadowRadius: {},
shadowMapSize: {}
} },
directionalShadowMap: { value: [] },
directionalShadowMatrix: { value: [] },
spotLights: { value: [], properties: {
color: {},
position: {},
direction: {},
distance: {},
coneCos: {},
penumbraCos: {},
decay: {},
shadow: {},
shadowBias: {},
shadowRadius: {},
shadowMapSize: {}
} },
spotShadowMap: { value: [] },
spotShadowMatrix: { value: [] },
pointLights: { value: [], properties: {
color: {},
position: {},
decay: {},
distance: {},
shadow: {},
shadowBias: {},
shadowRadius: {},
shadowMapSize: {},
shadowCameraNear: {},
shadowCameraFar: {}
} },
pointShadowMap: { value: [] },
pointShadowMatrix: { value: [] },
hemisphereLights: { value: [], properties: {
direction: {},
skyColor: {},
groundColor: {}
} },
// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
rectAreaLights: { value: [], properties: {
color: {},
position: {},
width: {},
height: {}
} }
},
points: {
diffuse: { value: new Color( 0xeeeeee ) },
opacity: { value: 1.0 },
size: { value: 1.0 },
scale: { value: 1.0 },
map: { value: null },
uvTransform: { value: new Matrix3() }
}
};
/**
* Uniform Utilities
*/
var UniformsUtils = {
merge: function ( uniforms ) {
var this$1 = this;
var merged = {};
for ( var u = 0; u < uniforms.length; u ++ ) {
var tmp = this$1.clone( uniforms[ u ] );
for ( var p in tmp ) {
merged[ p ] = tmp[ p ];
}
}
return merged;
},
clone: function ( uniforms_src ) {
var uniforms_dst = {};
for ( var u in uniforms_src ) {
uniforms_dst[ u ] = {};
for ( var p in uniforms_src[ u ] ) {
var parameter_src = uniforms_src[ u ][ p ];
if ( parameter_src && ( parameter_src.isColor ||
parameter_src.isMatrix3 || parameter_src.isMatrix4 ||
parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 ||
parameter_src.isTexture ) ) {
uniforms_dst[ u ][ p ] = parameter_src.clone();
} else if ( Array.isArray( parameter_src ) ) {
uniforms_dst[ u ][ p ] = parameter_src.slice();
} else {
uniforms_dst[ u ][ p ] = parameter_src;
}
}
}
return uniforms_dst;
}
};
var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n";
var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n";
var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
var begin_vertex = "\nvec3 transformed = vec3( position );\n";
var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n";
var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n";
var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n";
var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n";
var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n";
var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n";
var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";
var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n";
var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n";
var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n";
var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n";
var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n";
var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n";
var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n";
var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n";
var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n";
var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif";
var fog_pars_vertex = "#ifdef USE_FOG\n varying float fogDepth;\n#endif\n";
var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n";
var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n";
var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";
var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n";
var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n";
var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n";
var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n";
var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n";
var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif";
var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n";
var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n";
var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n";
var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n";
var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n";
var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n";
var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n";
var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n";
var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n";
var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n";
var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n";
var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n";
var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n";
var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n";
var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n";
var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n";
var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n";
var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n";
var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n";
var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif";
var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n";
var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif";
var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif";
var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n";
var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n";
var cube_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}\n";
var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n";
var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n}\n";
var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n";
var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}\n";
var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n";
var equirect_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}\n";
var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}\n";
var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}\n";
var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_template>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_template>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n";
var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n";
var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <fog_fragment>\n}\n";
var shadow_vert = "#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
var ShaderChunk = {
alphamap_fragment: alphamap_fragment,
alphamap_pars_fragment: alphamap_pars_fragment,
alphatest_fragment: alphatest_fragment,
aomap_fragment: aomap_fragment,
aomap_pars_fragment: aomap_pars_fragment,
begin_vertex: begin_vertex,
beginnormal_vertex: beginnormal_vertex,
bsdfs: bsdfs,
bumpmap_pars_fragment: bumpmap_pars_fragment,
clipping_planes_fragment: clipping_planes_fragment,
clipping_planes_pars_fragment: clipping_planes_pars_fragment,
clipping_planes_pars_vertex: clipping_planes_pars_vertex,
clipping_planes_vertex: clipping_planes_vertex,
color_fragment: color_fragment,
color_pars_fragment: color_pars_fragment,
color_pars_vertex: color_pars_vertex,
color_vertex: color_vertex,
common: common,
cube_uv_reflection_fragment: cube_uv_reflection_fragment,
defaultnormal_vertex: defaultnormal_vertex,
displacementmap_pars_vertex: displacementmap_pars_vertex,
displacementmap_vertex: displacementmap_vertex,
emissivemap_fragment: emissivemap_fragment,
emissivemap_pars_fragment: emissivemap_pars_fragment,
encodings_fragment: encodings_fragment,
encodings_pars_fragment: encodings_pars_fragment,
envmap_fragment: envmap_fragment,
envmap_pars_fragment: envmap_pars_fragment,
envmap_pars_vertex: envmap_pars_vertex,
envmap_vertex: envmap_vertex,
fog_vertex: fog_vertex,
fog_pars_vertex: fog_pars_vertex,
fog_fragment: fog_fragment,
fog_pars_fragment: fog_pars_fragment,
gradientmap_pars_fragment: gradientmap_pars_fragment,
lightmap_fragment: lightmap_fragment,
lightmap_pars_fragment: lightmap_pars_fragment,
lights_lambert_vertex: lights_lambert_vertex,
lights_pars: lights_pars,
lights_phong_fragment: lights_phong_fragment,
lights_phong_pars_fragment: lights_phong_pars_fragment,
lights_physical_fragment: lights_physical_fragment,
lights_physical_pars_fragment: lights_physical_pars_fragment,
lights_template: lights_template,
logdepthbuf_fragment: logdepthbuf_fragment,
logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
logdepthbuf_vertex: logdepthbuf_vertex,
map_fragment: map_fragment,
map_pars_fragment: map_pars_fragment,
map_particle_fragment: map_particle_fragment,
map_particle_pars_fragment: map_particle_pars_fragment,
metalnessmap_fragment: metalnessmap_fragment,
metalnessmap_pars_fragment: metalnessmap_pars_fragment,
morphnormal_vertex: morphnormal_vertex,
morphtarget_pars_vertex: morphtarget_pars_vertex,
morphtarget_vertex: morphtarget_vertex,
normal_fragment: normal_fragment,
normalmap_pars_fragment: normalmap_pars_fragment,
packing: packing,
premultiplied_alpha_fragment: premultiplied_alpha_fragment,
project_vertex: project_vertex,
dithering_fragment: dithering_fragment,
dithering_pars_fragment: dithering_pars_fragment,
roughnessmap_fragment: roughnessmap_fragment,
roughnessmap_pars_fragment: roughnessmap_pars_fragment,
shadowmap_pars_fragment: shadowmap_pars_fragment,
shadowmap_pars_vertex: shadowmap_pars_vertex,
shadowmap_vertex: shadowmap_vertex,
shadowmask_pars_fragment: shadowmask_pars_fragment,
skinbase_vertex: skinbase_vertex,
skinning_pars_vertex: skinning_pars_vertex,
skinning_vertex: skinning_vertex,
skinnormal_vertex: skinnormal_vertex,
specularmap_fragment: specularmap_fragment,
specularmap_pars_fragment: specularmap_pars_fragment,
tonemapping_fragment: tonemapping_fragment,
tonemapping_pars_fragment: tonemapping_pars_fragment,
uv_pars_fragment: uv_pars_fragment,
uv_pars_vertex: uv_pars_vertex,
uv_vertex: uv_vertex,
uv2_pars_fragment: uv2_pars_fragment,
uv2_pars_vertex: uv2_pars_vertex,
uv2_vertex: uv2_vertex,
worldpos_vertex: worldpos_vertex,
cube_frag: cube_frag,
cube_vert: cube_vert,
depth_frag: depth_frag,
depth_vert: depth_vert,
distanceRGBA_frag: distanceRGBA_frag,
distanceRGBA_vert: distanceRGBA_vert,
equirect_frag: equirect_frag,
equirect_vert: equirect_vert,
linedashed_frag: linedashed_frag,
linedashed_vert: linedashed_vert,
meshbasic_frag: meshbasic_frag,
meshbasic_vert: meshbasic_vert,
meshlambert_frag: meshlambert_frag,
meshlambert_vert: meshlambert_vert,
meshphong_frag: meshphong_frag,
meshphong_vert: meshphong_vert,
meshphysical_frag: meshphysical_frag,
meshphysical_vert: meshphysical_vert,
normal_frag: normal_frag,
normal_vert: normal_vert,
points_frag: points_frag,
points_vert: points_vert,
shadow_frag: shadow_frag,
shadow_vert: shadow_vert
};
/**
* @author alteredq / http://alteredqualia.com/
* @author mrdoob / http://mrdoob.com/
* @author mikael emtinger / http://gomo.se/
*/
var ShaderLib = {
basic: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.specularmap,
UniformsLib.envmap,
UniformsLib.aomap,
UniformsLib.lightmap,
UniformsLib.fog
] ),
vertexShader: ShaderChunk.meshbasic_vert,
fragmentShader: ShaderChunk.meshbasic_frag
},
lambert: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.specularmap,
UniformsLib.envmap,
UniformsLib.aomap,
UniformsLib.lightmap,
UniformsLib.emissivemap,
UniformsLib.fog,
UniformsLib.lights,
{
emissive: { value: new Color( 0x000000 ) }
}
] ),
vertexShader: ShaderChunk.meshlambert_vert,
fragmentShader: ShaderChunk.meshlambert_frag
},
phong: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.specularmap,
UniformsLib.envmap,
UniformsLib.aomap,
UniformsLib.lightmap,
UniformsLib.emissivemap,
UniformsLib.bumpmap,
UniformsLib.normalmap,
UniformsLib.displacementmap,
UniformsLib.gradientmap,
UniformsLib.fog,
UniformsLib.lights,
{
emissive: { value: new Color( 0x000000 ) },
specular: { value: new Color( 0x111111 ) },
shininess: { value: 30 }
}
] ),
vertexShader: ShaderChunk.meshphong_vert,
fragmentShader: ShaderChunk.meshphong_frag
},
standard: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.envmap,
UniformsLib.aomap,
UniformsLib.lightmap,
UniformsLib.emissivemap,
UniformsLib.bumpmap,
UniformsLib.normalmap,
UniformsLib.displacementmap,
UniformsLib.roughnessmap,
UniformsLib.metalnessmap,
UniformsLib.fog,
UniformsLib.lights,
{
emissive: { value: new Color( 0x000000 ) },
roughness: { value: 0.5 },
metalness: { value: 0.5 },
envMapIntensity: { value: 1 } // temporary
}
] ),
vertexShader: ShaderChunk.meshphysical_vert,
fragmentShader: ShaderChunk.meshphysical_frag
},
points: {
uniforms: UniformsUtils.merge( [
UniformsLib.points,
UniformsLib.fog
] ),
vertexShader: ShaderChunk.points_vert,
fragmentShader: ShaderChunk.points_frag
},
dashed: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.fog,
{
scale: { value: 1 },
dashSize: { value: 1 },
totalSize: { value: 2 }
}
] ),
vertexShader: ShaderChunk.linedashed_vert,
fragmentShader: ShaderChunk.linedashed_frag
},
depth: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.displacementmap
] ),
vertexShader: ShaderChunk.depth_vert,
fragmentShader: ShaderChunk.depth_frag
},
normal: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.bumpmap,
UniformsLib.normalmap,
UniformsLib.displacementmap,
{
opacity: { value: 1.0 }
}
] ),
vertexShader: ShaderChunk.normal_vert,
fragmentShader: ShaderChunk.normal_frag
},
/* -------------------------------------------------------------------------
// Cube map shader
------------------------------------------------------------------------- */
cube: {
uniforms: {
tCube: { value: null },
tFlip: { value: - 1 },
opacity: { value: 1.0 }
},
vertexShader: ShaderChunk.cube_vert,
fragmentShader: ShaderChunk.cube_frag
},
equirect: {
uniforms: {
tEquirect: { value: null },
},
vertexShader: ShaderChunk.equirect_vert,
fragmentShader: ShaderChunk.equirect_frag
},
distanceRGBA: {
uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.displacementmap,
{
referencePosition: { value: new Vector3() },
nearDistance: { value: 1 },
farDistance: { value: 1000 }
}
] ),
vertexShader: ShaderChunk.distanceRGBA_vert,
fragmentShader: ShaderChunk.distanceRGBA_frag
},
shadow: {
uniforms: UniformsUtils.merge( [
UniformsLib.lights,
UniformsLib.fog,
{
color: { value: new Color( 0x00000 ) },
opacity: { value: 1.0 }
} ] ),
vertexShader: ShaderChunk.shadow_vert,
fragmentShader: ShaderChunk.shadow_frag
}
};
ShaderLib.physical = {
uniforms: UniformsUtils.merge( [
ShaderLib.standard.uniforms,
{
clearCoat: { value: 0 },
clearCoatRoughness: { value: 0 }
}
] ),
vertexShader: ShaderChunk.meshphysical_vert,
fragmentShader: ShaderChunk.meshphysical_frag
};
/**
* @author bhouston / http://clara.io
*/
function Box2( min, max ) {
this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
}
Object.assign( Box2.prototype, {
set: function ( min, max ) {
this.min.copy( min );
this.max.copy( max );
return this;
},
setFromPoints: function ( points ) {
var this$1 = this;
this.makeEmpty();
for ( var i = 0, il = points.length; i < il; i ++ ) {
this$1.expandByPoint( points[ i ] );
}
return this;
},
setFromCenterAndSize: function () {
var v1 = new Vector2();
return function setFromCenterAndSize( center, size ) {
var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
this.min.copy( center ).sub( halfSize );
this.max.copy( center ).add( halfSize );
return this;
};
}(),
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( box ) {
this.min.copy( box.min );
this.max.copy( box.max );
return this;
},
makeEmpty: function () {
this.min.x = this.min.y = + Infinity;
this.max.x = this.max.y = - Infinity;
return this;
},
isEmpty: function () {
// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
},
getCenter: function ( optionalTarget ) {
var result = optionalTarget || new Vector2();
return this.isEmpty() ? result.set( 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
},
getSize: function ( optionalTarget ) {
var result = optionalTarget || new Vector2();
return this.isEmpty() ? result.set( 0, 0 ) : result.subVectors( this.max, this.min );
},
expandByPoint: function ( point ) {
this.min.min( point );
this.max.max( point );
return this;
},
expandByVector: function ( vector ) {
this.min.sub( vector );
this.max.add( vector );
return this;
},
expandByScalar: function ( scalar ) {
this.min.addScalar( - scalar );
this.max.addScalar( scalar );
return this;
},
containsPoint: function ( point ) {
return point.x < this.min.x || point.x > this.max.x ||
point.y < this.min.y || point.y > this.max.y ? false : true;
},
containsBox: function ( box ) {
return this.min.x <= box.min.x && box.max.x <= this.max.x &&
this.min.y <= box.min.y && box.max.y <= this.max.y;
},
getParameter: function ( point, optionalTarget ) {
// This can potentially have a divide by zero if the box
// has a size dimension of 0.
var result = optionalTarget || new Vector2();
return result.set(
( point.x - this.min.x ) / ( this.max.x - this.min.x ),
( point.y - this.min.y ) / ( this.max.y - this.min.y )
);
},
intersectsBox: function ( box ) {
// using 4 splitting planes to rule out intersections
return box.max.x < this.min.x || box.min.x > this.max.x ||
box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
},
clampPoint: function ( point, optionalTarget ) {
var result = optionalTarget || new Vector2();
return result.copy( point ).clamp( this.min, this.max );
},
distanceToPoint: function () {
var v1 = new Vector2();
return function distanceToPoint( point ) {
var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
return clampedPoint.sub( point ).length();
};
}(),
intersect: function ( box ) {
this.min.max( box.min );
this.max.min( box.max );
return this;
},
union: function ( box ) {
this.min.min( box.min );
this.max.max( box.max );
return this;
},
translate: function ( offset ) {
this.min.add( offset );
this.max.add( offset );
return this;
},
equals: function ( box ) {
return box.min.equals( this.min ) && box.max.equals( this.max );
}
} );
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
*/
function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) {
var vertexBuffer, elementBuffer;
var shader, program, attributes, uniforms;
var tempTexture, occlusionTexture;
function init() {
var vertices = new Float32Array( [
- 1, - 1, 0, 0,
1, - 1, 1, 0,
1, 1, 1, 1,
- 1, 1, 0, 1
] );
var faces = new Uint16Array( [
0, 1, 2,
0, 2, 3
] );
// buffers
vertexBuffer = gl.createBuffer();
elementBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
// textures
tempTexture = gl.createTexture();
occlusionTexture = gl.createTexture();
state.bindTexture( gl.TEXTURE_2D, tempTexture );
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
shader = {
vertexShader: [
'uniform lowp int renderType;',
'uniform vec3 screenPosition;',
'uniform vec2 scale;',
'uniform float rotation;',
'uniform sampler2D occlusionMap;',
'attribute vec2 position;',
'attribute vec2 uv;',
'varying vec2 vUV;',
'varying float vVisibility;',
'void main() {',
' vUV = uv;',
' vec2 pos = position;',
' if ( renderType == 2 ) {',
' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );',
' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );',
' vVisibility = visibility.r / 9.0;',
' vVisibility *= 1.0 - visibility.g / 9.0;',
' vVisibility *= visibility.b / 9.0;',
' vVisibility *= 1.0 - visibility.a / 9.0;',
' pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;',
' pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;',
' }',
' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );',
'}'
].join( '\n' ),
fragmentShader: [
'uniform lowp int renderType;',
'uniform sampler2D map;',
'uniform float opacity;',
'uniform vec3 color;',
'varying vec2 vUV;',
'varying float vVisibility;',
'void main() {',
// pink square
' if ( renderType == 0 ) {',
' gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );',
// restore
' } else if ( renderType == 1 ) {',
' gl_FragColor = texture2D( map, vUV );',
// flare
' } else {',
' vec4 texture = texture2D( map, vUV );',
' texture.a *= opacity * vVisibility;',
' gl_FragColor = texture;',
' gl_FragColor.rgb *= color;',
' }',
'}'
].join( '\n' )
};
program = createProgram( shader );
attributes = {
vertex: gl.getAttribLocation( program, 'position' ),
uv: gl.getAttribLocation( program, 'uv' )
};
uniforms = {
renderType: gl.getUniformLocation( program, 'renderType' ),
map: gl.getUniformLocation( program, 'map' ),
occlusionMap: gl.getUniformLocation( program, 'occlusionMap' ),
opacity: gl.getUniformLocation( program, 'opacity' ),
color: gl.getUniformLocation( program, 'color' ),
scale: gl.getUniformLocation( program, 'scale' ),
rotation: gl.getUniformLocation( program, 'rotation' ),
screenPosition: gl.getUniformLocation( program, 'screenPosition' )
};
}
/*
* Render lens flares
* Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
* reads these back and calculates occlusion.
*/
this.render = function ( flares, scene, camera, viewport ) {
if ( flares.length === 0 ) { return; }
var tempPosition = new Vector3();
var invAspect = viewport.w / viewport.z,
halfViewportWidth = viewport.z * 0.5,
halfViewportHeight = viewport.w * 0.5;
var size = 16 / viewport.w,
scale = new Vector2( size * invAspect, size );
var screenPosition = new Vector3( 1, 1, 0 ),
screenPositionPixels = new Vector2( 1, 1 );
var validArea = new Box2();
validArea.min.set( viewport.x, viewport.y );
validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) );
if ( program === undefined ) {
init();
}
state.useProgram( program );
state.initAttributes();
state.enableAttribute( attributes.vertex );
state.enableAttribute( attributes.uv );
state.disableUnusedAttributes();
// loop through all lens flares to update their occlusion and positions
// setup gl and common used attribs/uniforms
gl.uniform1i( uniforms.occlusionMap, 0 );
gl.uniform1i( uniforms.map, 1 );
gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 );
gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
state.disable( gl.CULL_FACE );
state.buffers.depth.setMask( false );
for ( var i = 0, l = flares.length; i < l; i ++ ) {
size = 16 / viewport.w;
scale.set( size * invAspect, size );
// calc object screen position
var flare = flares[ i ];
tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] );
tempPosition.applyMatrix4( camera.matrixWorldInverse );
tempPosition.applyMatrix4( camera.projectionMatrix );
// setup arrays for gl programs
screenPosition.copy( tempPosition );
// horizontal and vertical coordinate of the lower left corner of the pixels to copy
screenPositionPixels.x = viewport.x + ( screenPosition.x * halfViewportWidth ) + halfViewportWidth - 8;
screenPositionPixels.y = viewport.y + ( screenPosition.y * halfViewportHeight ) + halfViewportHeight - 8;
// screen cull
if ( validArea.containsPoint( screenPositionPixels ) === true ) {
// save current RGB to temp texture
state.activeTexture( gl.TEXTURE0 );
state.bindTexture( gl.TEXTURE_2D, null );
state.activeTexture( gl.TEXTURE1 );
state.bindTexture( gl.TEXTURE_2D, tempTexture );
gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 );
// render pink quad
gl.uniform1i( uniforms.renderType, 0 );
gl.uniform2f( uniforms.scale, scale.x, scale.y );
gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
state.disable( gl.BLEND );
state.enable( gl.DEPTH_TEST );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
// copy result to occlusionMap
state.activeTexture( gl.TEXTURE0 );
state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 );
// restore graphics
gl.uniform1i( uniforms.renderType, 1 );
state.disable( gl.DEPTH_TEST );
state.activeTexture( gl.TEXTURE1 );
state.bindTexture( gl.TEXTURE_2D, tempTexture );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
// update object positions
flare.positionScreen.copy( screenPosition );
if ( flare.customUpdateCallback ) {
flare.customUpdateCallback( flare );
} else {
flare.updateLensFlares();
}
// render flares
gl.uniform1i( uniforms.renderType, 2 );
state.enable( gl.BLEND );
for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
var sprite = flare.lensFlares[ j ];
if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
screenPosition.x = sprite.x;
screenPosition.y = sprite.y;
screenPosition.z = sprite.z;
size = sprite.size * sprite.scale / viewport.w;
scale.x = size * invAspect;
scale.y = size;
gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
gl.uniform2f( uniforms.scale, scale.x, scale.y );
gl.uniform1f( uniforms.rotation, sprite.rotation );
gl.uniform1f( uniforms.opacity, sprite.opacity );
gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
textures.setTexture2D( sprite.texture, 1 );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
}
}
}
}
// restore gl
state.enable( gl.CULL_FACE );
state.enable( gl.DEPTH_TEST );
state.buffers.depth.setMask( true );
state.reset();
};
function createProgram( shader ) {
var program = gl.createProgram();
var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
var vertexShader = gl.createShader( gl.VERTEX_SHADER );
var prefix = 'precision ' + capabilities.precision + ' float;\n';
gl.shaderSource( fragmentShader, prefix + shader.fragmentShader );
gl.shaderSource( vertexShader, prefix + shader.vertexShader );
gl.compileShader( fragmentShader );
gl.compileShader( vertexShader );
gl.attachShader( program, fragmentShader );
gl.attachShader( program, vertexShader );
gl.linkProgram( program );
return program;
}
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
this.needsUpdate = true;
}
CanvasTexture.prototype = Object.create( Texture.prototype );
CanvasTexture.prototype.constructor = CanvasTexture;
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
*/
function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) {
var vertexBuffer, elementBuffer;
var program, attributes, uniforms;
var texture;
// decompose matrixWorld
var spritePosition = new Vector3();
var spriteRotation = new Quaternion();
var spriteScale = new Vector3();
function init() {
var vertices = new Float32Array( [
- 0.5, - 0.5, 0, 0,
0.5, - 0.5, 1, 0,
0.5, 0.5, 1, 1,
- 0.5, 0.5, 0, 1
] );
var faces = new Uint16Array( [
0, 1, 2,
0, 2, 3
] );
vertexBuffer = gl.createBuffer();
elementBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
program = createProgram();
attributes = {
position: gl.getAttribLocation( program, 'position' ),
uv: gl.getAttribLocation( program, 'uv' )
};
uniforms = {
uvOffset: gl.getUniformLocation( program, 'uvOffset' ),
uvScale: gl.getUniformLocation( program, 'uvScale' ),
rotation: gl.getUniformLocation( program, 'rotation' ),
scale: gl.getUniformLocation( program, 'scale' ),
color: gl.getUniformLocation( program, 'color' ),
map: gl.getUniformLocation( program, 'map' ),
opacity: gl.getUniformLocation( program, 'opacity' ),
modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ),
projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ),
fogType: gl.getUniformLocation( program, 'fogType' ),
fogDensity: gl.getUniformLocation( program, 'fogDensity' ),
fogNear: gl.getUniformLocation( program, 'fogNear' ),
fogFar: gl.getUniformLocation( program, 'fogFar' ),
fogColor: gl.getUniformLocation( program, 'fogColor' ),
fogDepth: gl.getUniformLocation( program, 'fogDepth' ),
alphaTest: gl.getUniformLocation( program, 'alphaTest' )
};
var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
canvas.width = 8;
canvas.height = 8;
var context = canvas.getContext( '2d' );
context.fillStyle = 'white';
context.fillRect( 0, 0, 8, 8 );
texture = new CanvasTexture( canvas );
}
this.render = function ( sprites, scene, camera ) {
if ( sprites.length === 0 ) { return; }
// setup gl
if ( program === undefined ) {
init();
}
state.useProgram( program );
state.initAttributes();
state.enableAttribute( attributes.position );
state.enableAttribute( attributes.uv );
state.disableUnusedAttributes();
state.disable( gl.CULL_FACE );
state.enable( gl.BLEND );
gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 );
gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
state.activeTexture( gl.TEXTURE0 );
gl.uniform1i( uniforms.map, 0 );
var oldFogType = 0;
var sceneFogType = 0;
var fog = scene.fog;
if ( fog ) {
gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
if ( fog.isFog ) {
gl.uniform1f( uniforms.fogNear, fog.near );
gl.uniform1f( uniforms.fogFar, fog.far );
gl.uniform1i( uniforms.fogType, 1 );
oldFogType = 1;
sceneFogType = 1;
} else if ( fog.isFogExp2 ) {
gl.uniform1f( uniforms.fogDensity, fog.density );
gl.uniform1i( uniforms.fogType, 2 );
oldFogType = 2;
sceneFogType = 2;
}
} else {
gl.uniform1i( uniforms.fogType, 0 );
oldFogType = 0;
sceneFogType = 0;
}
// update positions and sort
for ( var i = 0, l = sprites.length; i < l; i ++ ) {
var sprite = sprites[ i ];
sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
}
sprites.sort( painterSortStable );
// render all sprites
var scale = [];
for ( var i = 0, l = sprites.length; i < l; i ++ ) {
var sprite = sprites[ i ];
var material = sprite.material;
if ( material.visible === false ) { continue; }
sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined );
gl.uniform1f( uniforms.alphaTest, material.alphaTest );
gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
scale[ 0 ] = spriteScale.x;
scale[ 1 ] = spriteScale.y;
var fogType = 0;
if ( scene.fog && material.fog ) {
fogType = sceneFogType;
}
if ( oldFogType !== fogType ) {
gl.uniform1i( uniforms.fogType, fogType );
oldFogType = fogType;
}
if ( material.map !== null ) {
gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
} else {
gl.uniform2f( uniforms.uvOffset, 0, 0 );
gl.uniform2f( uniforms.uvScale, 1, 1 );
}
gl.uniform1f( uniforms.opacity, material.opacity );
gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
gl.uniform1f( uniforms.rotation, material.rotation );
gl.uniform2fv( uniforms.scale, scale );
state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
state.buffers.depth.setTest( material.depthTest );
state.buffers.depth.setMask( material.depthWrite );
state.buffers.color.setMask( material.colorWrite );
textures.setTexture2D( material.map || texture, 0 );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined );
}
// restore gl
state.enable( gl.CULL_FACE );
state.reset();
};
function createProgram() {
var program = gl.createProgram();
var vertexShader = gl.createShader( gl.VERTEX_SHADER );
var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
gl.shaderSource( vertexShader, [
'precision ' + capabilities.precision + ' float;',
'#define SHADER_NAME ' + 'SpriteMaterial',
'uniform mat4 modelViewMatrix;',
'uniform mat4 projectionMatrix;',
'uniform float rotation;',
'uniform vec2 scale;',
'uniform vec2 uvOffset;',
'uniform vec2 uvScale;',
'attribute vec2 position;',
'attribute vec2 uv;',
'varying vec2 vUV;',
'varying float fogDepth;',
'void main() {',
' vUV = uvOffset + uv * uvScale;',
' vec2 alignedPosition = position * scale;',
' vec2 rotatedPosition;',
' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
' vec4 mvPosition;',
' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
' mvPosition.xy += rotatedPosition;',
' gl_Position = projectionMatrix * mvPosition;',
' fogDepth = - mvPosition.z;',
'}'
].join( '\n' ) );
gl.shaderSource( fragmentShader, [
'precision ' + capabilities.precision + ' float;',
'#define SHADER_NAME ' + 'SpriteMaterial',
'uniform vec3 color;',
'uniform sampler2D map;',
'uniform float opacity;',
'uniform int fogType;',
'uniform vec3 fogColor;',
'uniform float fogDensity;',
'uniform float fogNear;',
'uniform float fogFar;',
'uniform float alphaTest;',
'varying vec2 vUV;',
'varying float fogDepth;',
'void main() {',
' vec4 texture = texture2D( map, vUV );',
' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
' if ( gl_FragColor.a < alphaTest ) discard;',
' if ( fogType > 0 ) {',
' float fogFactor = 0.0;',
' if ( fogType == 1 ) {',
' fogFactor = smoothstep( fogNear, fogFar, fogDepth );',
' } else {',
' const float LOG2 = 1.442695;',
' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );',
' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
' }',
' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );',
' }',
'}'
].join( '\n' ) );
gl.compileShader( vertexShader );
gl.compileShader( fragmentShader );
gl.attachShader( program, vertexShader );
gl.attachShader( program, fragmentShader );
gl.linkProgram( program );
return program;
}
function painterSortStable( a, b ) {
if ( a.renderOrder !== b.renderOrder ) {
return a.renderOrder - b.renderOrder;
} else if ( a.z !== b.z ) {
return b.z - a.z;
} else {
return b.id - a.id;
}
}
}
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
*/
var materialId = 0;
function Material() {
Object.defineProperty( this, 'id', { value: materialId ++ } );
this.uuid = _Math.generateUUID();
this.name = '';
this.type = 'Material';
this.fog = true;
this.lights = true;
this.blending = NormalBlending;
this.side = FrontSide;
this.flatShading = false;
this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
this.opacity = 1;
this.transparent = false;
this.blendSrc = SrcAlphaFactor;
this.blendDst = OneMinusSrcAlphaFactor;
this.blendEquation = AddEquation;
this.blendSrcAlpha = null;
this.blendDstAlpha = null;
this.blendEquationAlpha = null;
this.depthFunc = LessEqualDepth;
this.depthTest = true;
this.depthWrite = true;
this.clippingPlanes = null;
this.clipIntersection = false;
this.clipShadows = false;
this.colorWrite = true;
this.precision = null; // override the renderer's default precision for this material
this.polygonOffset = false;
this.polygonOffsetFactor = 0;
this.polygonOffsetUnits = 0;
this.dithering = false;
this.alphaTest = 0;
this.premultipliedAlpha = false;
this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
this.visible = true;
this.userData = {};
this.needsUpdate = true;
}
Object.assign( Material.prototype, EventDispatcher.prototype, {
isMaterial: true,
onBeforeCompile: function () {},
setValues: function ( values ) {
var this$1 = this;
if ( values === undefined ) { return; }
for ( var key in values ) {
var newValue = values[ key ];
if ( newValue === undefined ) {
console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
continue;
}
// for backward compatability if shading is set in the constructor
if ( key === 'shading' ) {
console.warn( 'THREE.' + this$1.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
this$1.flatShading = ( newValue === FlatShading ) ? true : false;
continue;
}
var currentValue = this$1[ key ];
if ( currentValue === undefined ) {
console.warn( "THREE." + this$1.type + ": '" + key + "' is not a property of this material." );
continue;
}
if ( currentValue && currentValue.isColor ) {
currentValue.set( newValue );
} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
currentValue.copy( newValue );
} else if ( key === 'overdraw' ) {
// ensure overdraw is backwards-compatible with legacy boolean type
this$1[ key ] = Number( newValue );
} else {
this$1[ key ] = newValue;
}
}
},
toJSON: function ( meta ) {
var isRoot = ( meta === undefined || typeof meta === 'string' );
if ( isRoot ) {
meta = {
textures: {},
images: {}
};
}
var data = {
metadata: {
version: 4.5,
type: 'Material',
generator: 'Material.toJSON'
}
};
// standard Material serialization
data.uuid = this.uuid;
data.type = this.type;
if ( this.name !== '' ) { data.name = this.name; }
if ( this.color && this.color.isColor ) { data.color = this.color.getHex(); }
if ( this.roughness !== undefined ) { data.roughness = this.roughness; }
if ( this.metalness !== undefined ) { data.metalness = this.metalness; }
if ( this.emissive && this.emissive.isColor ) { data.emissive = this.emissive.getHex(); }
if ( this.emissiveIntensity !== 1 ) { data.emissiveIntensity = this.emissiveIntensity; }
if ( this.specular && this.specular.isColor ) { data.specular = this.specular.getHex(); }
if ( this.shininess !== undefined ) { data.shininess = this.shininess; }
if ( this.clearCoat !== undefined ) { data.clearCoat = this.clearCoat; }
if ( this.clearCoatRoughness !== undefined ) { data.clearCoatRoughness = this.clearCoatRoughness; }
if ( this.map && this.map.isTexture ) { data.map = this.map.toJSON( meta ).uuid; }
if ( this.alphaMap && this.alphaMap.isTexture ) { data.alphaMap = this.alphaMap.toJSON( meta ).uuid; }
if ( this.lightMap && this.lightMap.isTexture ) { data.lightMap = this.lightMap.toJSON( meta ).uuid; }
if ( this.bumpMap && this.bumpMap.isTexture ) {
data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
data.bumpScale = this.bumpScale;
}
if ( this.normalMap && this.normalMap.isTexture ) {
data.normalMap = this.normalMap.toJSON( meta ).uuid;
data.normalScale = this.normalScale.toArray();
}
if ( this.displacementMap && this.displacementMap.isTexture ) {
data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
data.displacementScale = this.displacementScale;
data.displacementBias = this.displacementBias;
}
if ( this.roughnessMap && this.roughnessMap.isTexture ) { data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; }
if ( this.metalnessMap && this.metalnessMap.isTexture ) { data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; }
if ( this.emissiveMap && this.emissiveMap.isTexture ) { data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; }
if ( this.specularMap && this.specularMap.isTexture ) { data.specularMap = this.specularMap.toJSON( meta ).uuid; }
if ( this.envMap && this.envMap.isTexture ) {
data.envMap = this.envMap.toJSON( meta ).uuid;
data.reflectivity = this.reflectivity; // Scale behind envMap
}
if ( this.gradientMap && this.gradientMap.isTexture ) {
data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
}
if ( this.size !== undefined ) { data.size = this.size; }
if ( this.sizeAttenuation !== undefined ) { data.sizeAttenuation = this.sizeAttenuation; }
if ( this.blending !== NormalBlending ) { data.blending = this.blending; }
if ( this.flatShading === true ) { data.flatShading = this.flatShading; }
if ( this.side !== FrontSide ) { data.side = this.side; }
if ( this.vertexColors !== NoColors ) { data.vertexColors = this.vertexColors; }
if ( this.opacity < 1 ) { data.opacity = this.opacity; }
if ( this.transparent === true ) { data.transparent = this.transparent; }
data.depthFunc = this.depthFunc;
data.depthTest = this.depthTest;
data.depthWrite = this.depthWrite;
// rotation (SpriteMaterial)
if ( this.rotation !== 0 ) { data.rotation = this.rotation; }
if ( this.linewidth !== 1 ) { data.linewidth = this.linewidth; }
if ( this.dashSize !== undefined ) { data.dashSize = this.dashSize; }
if ( this.gapSize !== undefined ) { data.gapSize = this.gapSize; }
if ( this.scale !== undefined ) { data.scale = this.scale; }
if ( this.dithering === true ) { data.dithering = true; }
if ( this.alphaTest > 0 ) { data.alphaTest = this.alphaTest; }
if ( this.premultipliedAlpha === true ) { data.premultipliedAlpha = this.premultipliedAlpha; }
if ( this.wireframe === true ) { data.wireframe = this.wireframe; }
if ( this.wireframeLinewidth > 1 ) { data.wireframeLinewidth = this.wireframeLinewidth; }
if ( this.wireframeLinecap !== 'round' ) { data.wireframeLinecap = this.wireframeLinecap; }
if ( this.wireframeLinejoin !== 'round' ) { data.wireframeLinejoin = this.wireframeLinejoin; }
if ( this.morphTargets === true ) { data.morphTargets = true; }
if ( this.skinning === true ) { data.skinning = true; }
if ( this.visible === false ) { data.visible = false; }
if ( JSON.stringify( this.userData ) !== '{}' ) { data.userData = this.userData; }
// TODO: Copied from Object3D.toJSON
function extractFromCache( cache ) {
var values = [];
for ( var key in cache ) {
var data = cache[ key ];
delete data.metadata;
values.push( data );
}
return values;
}
if ( isRoot ) {
var textures = extractFromCache( meta.textures );
var images = extractFromCache( meta.images );
if ( textures.length > 0 ) { data.textures = textures; }
if ( images.length > 0 ) { data.images = images; }
}
return data;
},
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( source ) {
this.name = source.name;
this.fog = source.fog;
this.lights = source.lights;
this.blending = source.blending;
this.side = source.side;
this.flatShading = source.flatShading;
this.vertexColors = source.vertexColors;
this.opacity = source.opacity;
this.transparent = source.transparent;
this.blendSrc = source.blendSrc;
this.blendDst = source.blendDst;
this.blendEquation = source.blendEquation;
this.blendSrcAlpha = source.blendSrcAlpha;
this.blendDstAlpha = source.blendDstAlpha;
this.blendEquationAlpha = source.blendEquationAlpha;
this.depthFunc = source.depthFunc;
this.depthTest = source.depthTest;
this.depthWrite = source.depthWrite;
this.colorWrite = source.colorWrite;
this.precision = source.precision;
this.polygonOffset = source.polygonOffset;
this.polygonOffsetFactor = source.polygonOffsetFactor;
this.polygonOffsetUnits = source.polygonOffsetUnits;
this.dithering = source.dithering;
this.alphaTest = source.alphaTest;
this.premultipliedAlpha = source.premultipliedAlpha;
this.overdraw = source.overdraw;
this.visible = source.visible;
this.userData = JSON.parse( JSON.stringify( source.userData ) );
this.clipShadows = source.clipShadows;
this.clipIntersection = source.clipIntersection;
var srcPlanes = source.clippingPlanes,
dstPlanes = null;
if ( srcPlanes !== null ) {
var n = srcPlanes.length;
dstPlanes = new Array( n );
for ( var i = 0; i !== n; ++ i )
{ dstPlanes[ i ] = srcPlanes[ i ].clone(); }
}
this.clippingPlanes = dstPlanes;
return this;
},
dispose: function () {
this.dispatchEvent( { type: 'dispose' } );
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
* @author bhouston / https://clara.io
* @author WestLangley / http://github.com/WestLangley
*
* parameters = {
*
* opacity: <float>,
*
* map: new THREE.Texture( <Image> ),
*
* alphaMap: new THREE.Texture( <Image> ),
*
* displacementMap: new THREE.Texture( <Image> ),
* displacementScale: <float>,
* displacementBias: <float>,
*
* wireframe: <boolean>,
* wireframeLinewidth: <float>
* }
*/
function MeshDepthMaterial( parameters ) {
Material.call( this );
this.type = 'MeshDepthMaterial';
this.depthPacking = BasicDepthPacking;
this.skinning = false;
this.morphTargets = false;
this.map = null;
this.alphaMap = null;
this.displacementMap = null;
this.displacementScale = 1;
this.displacementBias = 0;
this.wireframe = false;
this.wireframeLinewidth = 1;
this.fog = false;
this.lights = false;
this.setValues( parameters );
}
MeshDepthMaterial.prototype = Object.create( Material.prototype );
MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
MeshDepthMaterial.prototype.copy = function ( source ) {
Material.prototype.copy.call( this, source );
this.depthPacking = source.depthPacking;
this.skinning = source.skinning;
this.morphTargets = source.morphTargets;
this.map = source.map;
this.alphaMap = source.alphaMap;
this.displacementMap = source.displacementMap;
this.displacementScale = source.displacementScale;
this.displacementBias = source.displacementBias;
this.wireframe = source.wireframe;
this.wireframeLinewidth = source.wireframeLinewidth;
return this;
};
/**
* @author WestLangley / http://github.com/WestLangley
*
* parameters = {
*
* referencePosition: <float>,
* nearDistance: <float>,
* farDistance: <float>,
*
* skinning: <bool>,
* morphTargets: <bool>,
*
* map: new THREE.Texture( <Image> ),
*
* alphaMap: new THREE.Texture( <Image> ),
*
* displacementMap: new THREE.Texture( <Image> ),
* displacementScale: <float>,
* displacementBias: <float>
*
* }
*/
function MeshDistanceMaterial( parameters ) {
Material.call( this );
this.type = 'MeshDistanceMaterial';
this.referencePosition = new Vector3();
this.nearDistance = 1;
this.farDistance = 1000;
this.skinning = false;
this.morphTargets = false;
this.map = null;
this.alphaMap = null;
this.displacementMap = null;
this.displacementScale = 1;
this.displacementBias = 0;
this.fog = false;
this.lights = false;
this.setValues( parameters );
}
MeshDistanceMaterial.prototype = Object.create( Material.prototype );
MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
MeshDistanceMaterial.prototype.copy = function ( source ) {
Material.prototype.copy.call( this, source );
this.referencePosition.copy( source.referencePosition );
this.nearDistance = source.nearDistance;
this.farDistance = source.farDistance;
this.skinning = source.skinning;
this.morphTargets = source.morphTargets;
this.map = source.map;
this.alphaMap = source.alphaMap;
this.displacementMap = source.displacementMap;
this.displacementScale = source.displacementScale;
this.displacementBias = source.displacementBias;
return this;
};
/**
* @author bhouston / http://clara.io
* @author WestLangley / http://github.com/WestLangley
*/
function Box3( min, max ) {
this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
}
Object.assign( Box3.prototype, {
isBox3: true,
set: function ( min, max ) {
this.min.copy( min );
this.max.copy( max );
return this;
},
setFromArray: function ( array ) {
var minX = + Infinity;
var minY = + Infinity;
var minZ = + Infinity;
var maxX = - Infinity;
var maxY = - Infinity;
var maxZ = - Infinity;
for ( var i = 0, l = array.length; i < l; i += 3 ) {
var x = array[ i ];
var y = array[ i + 1 ];
var z = array[ i + 2 ];
if ( x < minX ) { minX = x; }
if ( y < minY ) { minY = y; }
if ( z < minZ ) { minZ = z; }
if ( x > maxX ) { maxX = x; }
if ( y > maxY ) { maxY = y; }
if ( z > maxZ ) { maxZ = z; }
}
this.min.set( minX, minY, minZ );
this.max.set( maxX, maxY, maxZ );
return this;
},
setFromBufferAttribute: function ( attribute ) {
var minX = + Infinity;
var minY = + Infinity;
var minZ = + Infinity;
var maxX = - Infinity;
var maxY = - Infinity;
var maxZ = - Infinity;
for ( var i = 0, l = attribute.count; i < l; i ++ ) {
var x = attribute.getX( i );
var y = attribute.getY( i );
var z = attribute.getZ( i );
if ( x < minX ) { minX = x; }
if ( y < minY ) { minY = y; }
if ( z < minZ ) { minZ = z; }
if ( x > maxX ) { maxX = x; }
if ( y > maxY ) { maxY = y; }
if ( z > maxZ ) { maxZ = z; }
}
this.min.set( minX, minY, minZ );
this.max.set( maxX, maxY, maxZ );
return this;
},
setFromPoints: function ( points ) {
var this$1 = this;
this.makeEmpty();
for ( var i = 0, il = points.length; i < il; i ++ ) {
this$1.expandByPoint( points[ i ] );
}
return this;
},
setFromCenterAndSize: function () {
var v1 = new Vector3();
return function setFromCenterAndSize( center, size ) {
var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
this.min.copy( center ).sub( halfSize );
this.max.copy( center ).add( halfSize );
return this;
};
}(),
setFromObject: function ( object ) {
this.makeEmpty();
return this.expandByObject( object );
},
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( box ) {
this.min.copy( box.min );
this.max.copy( box.max );
return this;
},
makeEmpty: function () {
this.min.x = this.min.y = this.min.z = + Infinity;
this.max.x = this.max.y = this.max.z = - Infinity;
return this;
},
isEmpty: function () {
// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
},
getCenter: function ( optionalTarget ) {
var result = optionalTarget || new Vector3();
return this.isEmpty() ? result.set( 0, 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
},
getSize: function ( optionalTarget ) {
var result = optionalTarget || new Vector3();
return this.isEmpty() ? result.set( 0, 0, 0 ) : result.subVectors( this.max, this.min );
},
expandByPoint: function ( point ) {
this.min.min( point );
this.max.max( point );
return this;
},
expandByVector: function ( vector ) {
this.min.sub( vector );
this.max.add( vector );
return this;
},
expandByScalar: function ( scalar ) {
this.min.addScalar( - scalar );
this.max.addScalar( scalar );
return this;
},
expandByObject: function () {
// Computes the world-axis-aligned bounding box of an object (including its children),
// accounting for both the object's, and children's, world transforms
var scope, i, l;
var v1 = new Vector3();
function traverse( node ) {
var geometry = node.geometry;
if ( geometry !== undefined ) {
if ( geometry.isGeometry ) {
var vertices = geometry.vertices;
for ( i = 0, l = vertices.length; i < l; i ++ ) {
v1.copy( vertices[ i ] );
v1.applyMatrix4( node.matrixWorld );
scope.expandByPoint( v1 );
}
} else if ( geometry.isBufferGeometry ) {
var attribute = geometry.attributes.position;
if ( attribute !== undefined ) {
for ( i = 0, l = attribute.count; i < l; i ++ ) {
v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld );
scope.expandByPoint( v1 );
}
}
}
}
}
return function expandByObject( object ) {
scope = this;
object.updateMatrixWorld( true );
object.traverse( traverse );
return this;
};
}(),
containsPoint: function ( point ) {
return point.x < this.min.x || point.x > this.max.x ||
point.y < this.min.y || point.y > this.max.y ||
point.z < this.min.z || point.z > this.max.z ? false : true;
},
containsBox: function ( box ) {
return this.min.x <= box.min.x && box.max.x <= this.max.x &&
this.min.y <= box.min.y && box.max.y <= this.max.y &&
this.min.z <= box.min.z && box.max.z <= this.max.z;
},
getParameter: function ( point, optionalTarget ) {
// This can potentially have a divide by zero if the box
// has a size dimension of 0.
var result = optionalTarget || new Vector3();
return result.set(
( point.x - this.min.x ) / ( this.max.x - this.min.x ),
( point.y - this.min.y ) / ( this.max.y - this.min.y ),
( point.z - this.min.z ) / ( this.max.z - this.min.z )
);
},
intersectsBox: function ( box ) {
// using 6 splitting planes to rule out intersections.
return box.max.x < this.min.x || box.min.x > this.max.x ||
box.max.y < this.min.y || box.min.y > this.max.y ||
box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
},
intersectsSphere: ( function () {
var closestPoint = new Vector3();
return function intersectsSphere( sphere ) {
// Find the point on the AABB closest to the sphere center.
this.clampPoint( sphere.center, closestPoint );
// If that point is inside the sphere, the AABB and sphere intersect.
return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
};
} )(),
intersectsPlane: function ( plane ) {
// We compute the minimum and maximum dot product values. If those values
// are on the same side (back or front) of the plane, then there is no intersection.
var min, max;
if ( plane.normal.x > 0 ) {
min = plane.normal.x * this.min.x;
max = plane.normal.x * this.max.x;
} else {
min = plane.normal.x * this.max.x;
max = plane.normal.x * this.min.x;
}
if ( plane.normal.y > 0 ) {
min += plane.normal.y * this.min.y;
max += plane.normal.y * this.max.y;
} else {
min += plane.normal.y * this.max.y;
max += plane.normal.y * this.min.y;
}
if ( plane.normal.z > 0 ) {
min += plane.normal.z * this.min.z;
max += plane.normal.z * this.max.z;
} else {
min += plane.normal.z * this.max.z;
max += plane.normal.z * this.min.z;
}
return ( min <= plane.constant && max >= plane.constant );
},
clampPoint: function ( point, optionalTarget ) {
var result = optionalTarget || new Vector3();
return result.copy( point ).clamp( this.min, this.max );
},
distanceToPoint: function () {
var v1 = new Vector3();
return function distanceToPoint( point ) {
var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
return clampedPoint.sub( point ).length();
};
}(),
getBoundingSphere: function () {
var v1 = new Vector3();
return function getBoundingSphere( optionalTarget ) {
var result = optionalTarget || new Sphere();
this.getCenter( result.center );
result.radius = this.getSize( v1 ).length() * 0.5;
return result;
};
}(),
intersect: function ( box ) {
this.min.max( box.min );
this.max.min( box.max );
// ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.
if ( this.isEmpty() ) { this.makeEmpty(); }
return this;
},
union: function ( box ) {
this.min.min( box.min );
this.max.max( box.max );
return this;
},
applyMatrix4: function () {
var points = [
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3()
];
return function applyMatrix4( matrix ) {
// transform of empty box is an empty box.
if ( this.isEmpty() ) { return this; }
// NOTE: I am using a binary pattern to specify all 2^3 combinations below
points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
this.setFromPoints( points );
return this;
};
}(),
translate: function ( offset ) {
this.min.add( offset );
this.max.add( offset );
return this;
},
equals: function ( box ) {
return box.min.equals( this.min ) && box.max.equals( this.max );
}
} );
/**
* @author bhouston / http://clara.io
* @author mrdoob / http://mrdoob.com/
*/
function Sphere( center, radius ) {
this.center = ( center !== undefined ) ? center : new Vector3();
this.radius = ( radius !== undefined ) ? radius : 0;
}
Object.assign( Sphere.prototype, {
set: function ( center, radius ) {
this.center.copy( center );
this.radius = radius;
return this;
},
setFromPoints: function () {
var box = new Box3();
return function setFromPoints( points, optionalCenter ) {
var center = this.center;
if ( optionalCenter !== undefined ) {
center.copy( optionalCenter );
} else {
box.setFromPoints( points ).getCenter( center );
}
var maxRadiusSq = 0;
for ( var i = 0, il = points.length; i < il; i ++ ) {
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
}
this.radius = Math.sqrt( maxRadiusSq );
return this;
};
}(),
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( sphere ) {
this.center.copy( sphere.center );
this.radius = sphere.radius;
return this;
},
empty: function () {
return ( this.radius <= 0 );
},
containsPoint: function ( point ) {
return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
},
distanceToPoint: function ( point ) {
return ( point.distanceTo( this.center ) - this.radius );
},
intersectsSphere: function ( sphere ) {
var radiusSum = this.radius + sphere.radius;
return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
},
intersectsBox: function ( box ) {
return box.intersectsSphere( this );
},
intersectsPlane: function ( plane ) {
return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
},
clampPoint: function ( point, optionalTarget ) {
var deltaLengthSq = this.center.distanceToSquared( point );
var result = optionalTarget || new Vector3();
result.copy( point );
if ( deltaLengthSq > ( this.radius * this.radius ) ) {
result.sub( this.center ).normalize();
result.multiplyScalar( this.radius ).add( this.center );
}
return result;
},
getBoundingBox: function ( optionalTarget ) {
var box = optionalTarget || new Box3();
box.set( this.center, this.center );
box.expandByScalar( this.radius );
return box;
},
applyMatrix4: function ( matrix ) {
this.center.applyMatrix4( matrix );
this.radius = this.radius * matrix.getMaxScaleOnAxis();
return this;
},
translate: function ( offset ) {
this.center.add( offset );
return this;
},
equals: function ( sphere ) {
return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
}
} );
/**
* @author bhouston / http://clara.io
*/
function Plane$2( normal, constant ) {
// normal is assumed to be normalized
this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
this.constant = ( constant !== undefined ) ? constant : 0;
}
Object.assign( Plane$2.prototype, {
set: function ( normal, constant ) {
this.normal.copy( normal );
this.constant = constant;
return this;
},
setComponents: function ( x, y, z, w ) {
this.normal.set( x, y, z );
this.constant = w;
return this;
},
setFromNormalAndCoplanarPoint: function ( normal, point ) {
this.normal.copy( normal );
this.constant = - point.dot( this.normal );
return this;
},
setFromCoplanarPoints: function () {
var v1 = new Vector3();
var v2 = new Vector3();
return function setFromCoplanarPoints( a, b, c ) {
var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
this.setFromNormalAndCoplanarPoint( normal, a );
return this;
};
}(),
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( plane ) {
this.normal.copy( plane.normal );
this.constant = plane.constant;
return this;
},
normalize: function () {
// Note: will lead to a divide by zero if the plane is invalid.
var inverseNormalLength = 1.0 / this.normal.length();
this.normal.multiplyScalar( inverseNormalLength );
this.constant *= inverseNormalLength;
return this;
},
negate: function () {
this.constant *= - 1;
this.normal.negate();
return this;
},
distanceToPoint: function ( point ) {
return this.normal.dot( point ) + this.constant;
},
distanceToSphere: function ( sphere ) {
return this.distanceToPoint( sphere.center ) - sphere.radius;
},
projectPoint: function ( point, optionalTarget ) {
var result = optionalTarget || new Vector3();
return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
},
intersectLine: function () {
var v1 = new Vector3();
return function intersectLine( line, optionalTarget ) {
var result = optionalTarget || new Vector3();
var direction = line.delta( v1 );
var denominator = this.normal.dot( direction );
if ( denominator === 0 ) {
// line is coplanar, return origin
if ( this.distanceToPoint( line.start ) === 0 ) {
return result.copy( line.start );
}
// Unsure if this is the correct method to handle this case.
return undefined;
}
var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
if ( t < 0 || t > 1 ) {
return undefined;
}
return result.copy( direction ).multiplyScalar( t ).add( line.start );
};
}(),
intersectsLine: function ( line ) {
// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
var startSign = this.distanceToPoint( line.start );
var endSign = this.distanceToPoint( line.end );
return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
},
intersectsBox: function ( box ) {
return box.intersectsPlane( this );
},
intersectsSphere: function ( sphere ) {
return sphere.intersectsPlane( this );
},
coplanarPoint: function ( optionalTarget ) {
var result = optionalTarget || new Vector3();
return result.copy( this.normal ).multiplyScalar( - this.constant );
},
applyMatrix4: function () {
var v1 = new Vector3();
var m1 = new Matrix3();
return function applyMatrix4( matrix, optionalNormalMatrix ) {
var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
this.constant = - referencePoint.dot( normal );
return this;
};
}(),
translate: function ( offset ) {
this.constant -= offset.dot( this.normal );
return this;
},
equals: function ( plane ) {
return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
* @author bhouston / http://clara.io
*/
function Frustum( p0, p1, p2, p3, p4, p5 ) {
this.planes = [
( p0 !== undefined ) ? p0 : new Plane$2(),
( p1 !== undefined ) ? p1 : new Plane$2(),
( p2 !== undefined ) ? p2 : new Plane$2(),
( p3 !== undefined ) ? p3 : new Plane$2(),
( p4 !== undefined ) ? p4 : new Plane$2(),
( p5 !== undefined ) ? p5 : new Plane$2()
];
}
Object.assign( Frustum.prototype, {
set: function ( p0, p1, p2, p3, p4, p5 ) {
var planes = this.planes;
planes[ 0 ].copy( p0 );
planes[ 1 ].copy( p1 );
planes[ 2 ].copy( p2 );
planes[ 3 ].copy( p3 );
planes[ 4 ].copy( p4 );
planes[ 5 ].copy( p5 );
return this;
},
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( frustum ) {
var planes = this.planes;
for ( var i = 0; i < 6; i ++ ) {
planes[ i ].copy( frustum.planes[ i ] );
}
return this;
},
setFromMatrix: function ( m ) {
var planes = this.planes;
var me = m.elements;
var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
return this;
},
intersectsObject: function () {
var sphere = new Sphere();
return function intersectsObject( object ) {
var geometry = object.geometry;
if ( geometry.boundingSphere === null )
{ geometry.computeBoundingSphere(); }
sphere.copy( geometry.boundingSphere )
.applyMatrix4( object.matrixWorld );
return this.intersectsSphere( sphere );
};
}(),
intersectsSprite: function () {
var sphere = new Sphere();
return function intersectsSprite( sprite ) {
sphere.center.set( 0, 0, 0 );
sphere.radius = 0.7071067811865476;
sphere.applyMatrix4( sprite.matrixWorld );
return this.intersectsSphere( sphere );
};
}(),
intersectsSphere: function ( sphere ) {
var planes = this.planes;
var center = sphere.center;
var negRadius = - sphere.radius;
for ( var i = 0; i < 6; i ++ ) {
var distance = planes[ i ].distanceToPoint( center );
if ( distance < negRadius ) {
return false;
}
}
return true;
},
intersectsBox: function () {
var p1 = new Vector3(),
p2 = new Vector3();
return function intersectsBox( box ) {
var planes = this.planes;
for ( var i = 0; i < 6; i ++ ) {
var plane = planes[ i ];
p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
var d1 = plane.distanceToPoint( p1 );
var d2 = plane.distanceToPoint( p2 );
// if both outside plane, no intersection
if ( d1 < 0 && d2 < 0 ) {
return false;
}
}
return true;
};
}(),
containsPoint: function ( point ) {
var planes = this.planes;
for ( var i = 0; i < 6; i ++ ) {
if ( planes[ i ].distanceToPoint( point ) < 0 ) {
return false;
}
}
return true;
}
} );
/**
* @author alteredq / http://alteredqualia.com/
* @author mrdoob / http://mrdoob.com/
*/
function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
var _frustum = new Frustum(),
_projScreenMatrix = new Matrix4(),
_shadowMapSize = new Vector2(),
_maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),
_lookTarget = new Vector3(),
_lightPositionWorld = new Vector3(),
_MorphingFlag = 1,
_SkinningFlag = 2,
_NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
_depthMaterials = new Array( _NumberOfMaterialVariants ),
_distanceMaterials = new Array( _NumberOfMaterialVariants ),
_materialCache = {};
var cubeDirections = [
new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
];
var cubeUps = [
new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
];
var cube2DViewPorts = [
new Vector4(), new Vector4(), new Vector4(),
new Vector4(), new Vector4(), new Vector4()
];
// init
for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
var useMorphing = ( i & _MorphingFlag ) !== 0;
var useSkinning = ( i & _SkinningFlag ) !== 0;
var depthMaterial = new MeshDepthMaterial( {
depthPacking: RGBADepthPacking,
morphTargets: useMorphing,
skinning: useSkinning
} );
_depthMaterials[ i ] = depthMaterial;
//
var distanceMaterial = new MeshDistanceMaterial( {
morphTargets: useMorphing,
skinning: useSkinning
} );
_distanceMaterials[ i ] = distanceMaterial;
}
//
var scope = this;
this.enabled = false;
this.autoUpdate = true;
this.needsUpdate = false;
this.type = PCFShadowMap;
this.renderReverseSided = true;
this.renderSingleSided = true;
this.render = function ( lights, scene, camera ) {
if ( scope.enabled === false ) { return; }
if ( scope.autoUpdate === false && scope.needsUpdate === false ) { return; }
if ( lights.length === 0 ) { return; }
// TODO Clean up (needed in case of contextlost)
var _gl = _renderer.context;
var _state = _renderer.state;
// Set GL state for depth map.
_state.disable( _gl.BLEND );
_state.buffers.color.setClear( 1, 1, 1, 1 );
_state.buffers.depth.setTest( true );
_state.setScissorTest( false );
// render depth map
var faceCount;
for ( var i = 0, il = lights.length; i < il; i ++ ) {
var light = lights[ i ];
var shadow = light.shadow;
var isPointLight = light && light.isPointLight;
if ( shadow === undefined ) {
console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
continue;
}
var shadowCamera = shadow.camera;
_shadowMapSize.copy( shadow.mapSize );
_shadowMapSize.min( _maxShadowMapSize );
if ( isPointLight ) {
var vpWidth = _shadowMapSize.x;
var vpHeight = _shadowMapSize.y;
// These viewports map a cube-map onto a 2D texture with the
// following orientation:
//
// xzXZ
// y Y
//
// X - Positive x direction
// x - Negative x direction
// Y - Positive y direction
// y - Negative y direction
// Z - Positive z direction
// z - Negative z direction
// positive X
cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
// negative X
cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
// positive Z
cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
// negative Z
cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
// positive Y
cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
// negative Y
cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
_shadowMapSize.x *= 4.0;
_shadowMapSize.y *= 2.0;
}
if ( shadow.map === null ) {
var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
shadow.map.texture.name = light.name + ".shadowMap";
shadowCamera.updateProjectionMatrix();
}
if ( shadow.isSpotLightShadow ) {
shadow.update( light );
}
var shadowMap = shadow.map;
var shadowMatrix = shadow.matrix;
_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
shadowCamera.position.copy( _lightPositionWorld );
if ( isPointLight ) {
faceCount = 6;
// for point lights we set the shadow matrix to be a translation-only matrix
// equal to inverse of the light's position
shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
} else {
faceCount = 1;
_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
shadowCamera.lookAt( _lookTarget );
shadowCamera.updateMatrixWorld();
// compute shadow matrix
shadowMatrix.set(
0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0
);
shadowMatrix.multiply( shadowCamera.projectionMatrix );
shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
}
_renderer.setRenderTarget( shadowMap );
_renderer.clear();
// render shadow map for each cube face (if omni-directional) or
// run a single pass if not
for ( var face = 0; face < faceCount; face ++ ) {
if ( isPointLight ) {
_lookTarget.copy( shadowCamera.position );
_lookTarget.add( cubeDirections[ face ] );
shadowCamera.up.copy( cubeUps[ face ] );
shadowCamera.lookAt( _lookTarget );
shadowCamera.updateMatrixWorld();
var vpDimensions = cube2DViewPorts[ face ];
_state.viewport( vpDimensions );
}
// update camera matrices and frustum
_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
_frustum.setFromMatrix( _projScreenMatrix );
// set object matrices & frustum culling
renderObject( scene, camera, shadowCamera, isPointLight );
}
}
scope.needsUpdate = false;
};
function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {
var geometry = object.geometry;
var result = null;
var materialVariants = _depthMaterials;
var customMaterial = object.customDepthMaterial;
if ( isPointLight ) {
materialVariants = _distanceMaterials;
customMaterial = object.customDistanceMaterial;
}
if ( ! customMaterial ) {
var useMorphing = false;
if ( material.morphTargets ) {
if ( geometry && geometry.isBufferGeometry ) {
useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
} else if ( geometry && geometry.isGeometry ) {
useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
}
}
if ( object.isSkinnedMesh && material.skinning === false ) {
console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
}
var useSkinning = object.isSkinnedMesh && material.skinning;
var variantIndex = 0;
if ( useMorphing ) { variantIndex |= _MorphingFlag; }
if ( useSkinning ) { variantIndex |= _SkinningFlag; }
result = materialVariants[ variantIndex ];
} else {
result = customMaterial;
}
if ( _renderer.localClippingEnabled &&
material.clipShadows === true &&
material.clippingPlanes.length !== 0 ) {
// in this case we need a unique material instance reflecting the
// appropriate state
var keyA = result.uuid, keyB = material.uuid;
var materialsForVariant = _materialCache[ keyA ];
if ( materialsForVariant === undefined ) {
materialsForVariant = {};
_materialCache[ keyA ] = materialsForVariant;
}
var cachedMaterial = materialsForVariant[ keyB ];
if ( cachedMaterial === undefined ) {
cachedMaterial = result.clone();
materialsForVariant[ keyB ] = cachedMaterial;
}
result = cachedMaterial;
}
result.visible = material.visible;
result.wireframe = material.wireframe;
var side = material.side;
if ( scope.renderSingleSided && side == DoubleSide ) {
side = FrontSide;
}
if ( scope.renderReverseSided ) {
if ( side === FrontSide ) { side = BackSide; }
else if ( side === BackSide ) { side = FrontSide; }
}
result.side = side;
result.clipShadows = material.clipShadows;
result.clippingPlanes = material.clippingPlanes;
result.clipIntersection = material.clipIntersection;
result.wireframeLinewidth = material.wireframeLinewidth;
result.linewidth = material.linewidth;
if ( isPointLight && result.isMeshDistanceMaterial ) {
result.referencePosition.copy( lightPositionWorld );
result.nearDistance = shadowCameraNear;
result.farDistance = shadowCameraFar;
}
return result;
}
function renderObject( object, camera, shadowCamera, isPointLight ) {
if ( object.visible === false ) { return; }
var visible = object.layers.test( camera.layers );
if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
var geometry = _objects.update( object );
var material = object.material;
if ( Array.isArray( material ) ) {
var groups = geometry.groups;
for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
var group = groups[ k ];
var groupMaterial = material[ group.materialIndex ];
if ( groupMaterial && groupMaterial.visible ) {
var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
}
}
} else if ( material.visible ) {
var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
}
}
}
var children = object.children;
for ( var i = 0, l = children.length; i < l; i ++ ) {
renderObject( children[ i ], camera, shadowCamera, isPointLight );
}
}
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLAttributes( gl ) {
var buffers = {};
function createBuffer( attribute, bufferType ) {
var array = attribute.array;
var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
var buffer = gl.createBuffer();
gl.bindBuffer( bufferType, buffer );
gl.bufferData( bufferType, array, usage );
attribute.onUploadCallback();
var type = gl.FLOAT;
if ( array instanceof Float32Array ) {
type = gl.FLOAT;
} else if ( array instanceof Float64Array ) {
console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
} else if ( array instanceof Uint16Array ) {
type = gl.UNSIGNED_SHORT;
} else if ( array instanceof Int16Array ) {
type = gl.SHORT;
} else if ( array instanceof Uint32Array ) {
type = gl.UNSIGNED_INT;
} else if ( array instanceof Int32Array ) {
type = gl.INT;
} else if ( array instanceof Int8Array ) {
type = gl.BYTE;
} else if ( array instanceof Uint8Array ) {
type = gl.UNSIGNED_BYTE;
}
return {
buffer: buffer,
type: type,
bytesPerElement: array.BYTES_PER_ELEMENT,
version: attribute.version
};
}
function updateBuffer( buffer, attribute, bufferType ) {
var array = attribute.array;
var updateRange = attribute.updateRange;
gl.bindBuffer( bufferType, buffer );
if ( attribute.dynamic === false ) {
gl.bufferData( bufferType, array, gl.STATIC_DRAW );
} else if ( updateRange.count === - 1 ) {
// Not using update ranges
gl.bufferSubData( bufferType, 0, array );
} else if ( updateRange.count === 0 ) {
console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );
} else {
gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
updateRange.count = - 1; // reset range
}
}
//
function get( attribute ) {
if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }
return buffers[ attribute.uuid ];
}
function remove( attribute ) {
if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }
var data = buffers[ attribute.uuid ];
if ( data ) {
gl.deleteBuffer( data.buffer );
delete buffers[ attribute.uuid ];
}
}
function update( attribute, bufferType ) {
if ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }
var data = buffers[ attribute.uuid ];
if ( data === undefined ) {
buffers[ attribute.uuid ] = createBuffer( attribute, bufferType );
} else if ( data.version < attribute.version ) {
updateBuffer( data.buffer, attribute, bufferType );
data.version = attribute.version;
}
}
return {
get: get,
remove: remove,
update: update
};
}
/**
* @author mrdoob / http://mrdoob.com/
* @author WestLangley / http://github.com/WestLangley
* @author bhouston / http://clara.io
*/
function Euler( x, y, z, order ) {
this._x = x || 0;
this._y = y || 0;
this._z = z || 0;
this._order = order || Euler.DefaultOrder;
}
Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
Euler.DefaultOrder = 'XYZ';
Object.defineProperties( Euler.prototype, {
x: {
get: function () {
return this._x;
},
set: function ( value ) {
this._x = value;
this.onChangeCallback();
}
},
y: {
get: function () {
return this._y;
},
set: function ( value ) {
this._y = value;
this.onChangeCallback();
}
},
z: {
get: function () {
return this._z;
},
set: function ( value ) {
this._z = value;
this.onChangeCallback();
}
},
order: {
get: function () {
return this._order;
},
set: function ( value ) {
this._order = value;
this.onChangeCallback();
}
}
} );
Object.assign( Euler.prototype, {
isEuler: true,
set: function ( x, y, z, order ) {
this._x = x;
this._y = y;
this._z = z;
this._order = order || this._order;
this.onChangeCallback();
return this;
},
clone: function () {
return new this.constructor( this._x, this._y, this._z, this._order );
},
copy: function ( euler ) {
this._x = euler._x;
this._y = euler._y;
this._z = euler._z;
this._order = euler._order;
this.onChangeCallback();
return this;
},
setFromRotationMatrix: function ( m, order, update ) {
var clamp = _Math.clamp;
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
var te = m.elements;
var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
order = order || this._order;
if ( order === 'XYZ' ) {
this._y = Math.asin( clamp( m13, - 1, 1 ) );
if ( Math.abs( m13 ) < 0.99999 ) {
this._x = Math.atan2( - m23, m33 );
this._z = Math.atan2( - m12, m11 );
} else {
this._x = Math.atan2( m32, m22 );
this._z = 0;
}
} else if ( order === 'YXZ' ) {
this._x = Math.asin( - clamp( m23, - 1, 1 ) );
if ( Math.abs( m23 ) < 0.99999 ) {
this._y = Math.atan2( m13, m33 );
this._z = Math.atan2( m21, m22 );
} else {
this._y = Math.atan2( - m31, m11 );
this._z = 0;
}
} else if ( order === 'ZXY' ) {
this._x = Math.asin( clamp( m32, - 1, 1 ) );
if ( Math.abs( m32 ) < 0.99999 ) {
this._y = Math.atan2( - m31, m33 );
this._z = Math.atan2( - m12, m22 );
} else {
this._y = 0;
this._z = Math.atan2( m21, m11 );
}
} else if ( order === 'ZYX' ) {
this._y = Math.asin( - clamp( m31, - 1, 1 ) );
if ( Math.abs( m31 ) < 0.99999 ) {
this._x = Math.atan2( m32, m33 );
this._z = Math.atan2( m21, m11 );
} else {
this._x = 0;
this._z = Math.atan2( - m12, m22 );
}
} else if ( order === 'YZX' ) {
this._z = Math.asin( clamp( m21, - 1, 1 ) );
if ( Math.abs( m21 ) < 0.99999 ) {
this._x = Math.atan2( - m23, m22 );
this._y = Math.atan2( - m31, m11 );
} else {
this._x = 0;
this._y = Math.atan2( m13, m33 );
}
} else if ( order === 'XZY' ) {
this._z = Math.asin( - clamp( m12, - 1, 1 ) );
if ( Math.abs( m12 ) < 0.99999 ) {
this._x = Math.atan2( m32, m22 );
this._y = Math.atan2( m13, m11 );
} else {
this._x = Math.atan2( - m23, m33 );
this._y = 0;
}
} else {
console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
}
this._order = order;
if ( update !== false ) { this.onChangeCallback(); }
return this;
},
setFromQuaternion: function () {
var matrix = new Matrix4();
return function setFromQuaternion( q, order, update ) {
matrix.makeRotationFromQuaternion( q );
return this.setFromRotationMatrix( matrix, order, update );
};
}(),
setFromVector3: function ( v, order ) {
return this.set( v.x, v.y, v.z, order || this._order );
},
reorder: function () {
// WARNING: this discards revolution information -bhouston
var q = new Quaternion();
return function reorder( newOrder ) {
q.setFromEuler( this );
return this.setFromQuaternion( q, newOrder );
};
}(),
equals: function ( euler ) {
return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
},
fromArray: function ( array ) {
this._x = array[ 0 ];
this._y = array[ 1 ];
this._z = array[ 2 ];
if ( array[ 3 ] !== undefined ) { this._order = array[ 3 ]; }
this.onChangeCallback();
return this;
},
toArray: function ( array, offset ) {
if ( array === undefined ) { array = []; }
if ( offset === undefined ) { offset = 0; }
array[ offset ] = this._x;
array[ offset + 1 ] = this._y;
array[ offset + 2 ] = this._z;
array[ offset + 3 ] = this._order;
return array;
},
toVector3: function ( optionalResult ) {
if ( optionalResult ) {
return optionalResult.set( this._x, this._y, this._z );
} else {
return new Vector3( this._x, this._y, this._z );
}
},
onChange: function ( callback ) {
this.onChangeCallback = callback;
return this;
},
onChangeCallback: function () {}
} );
/**
* @author mrdoob / http://mrdoob.com/
*/
function Layers() {
this.mask = 1 | 0;
}
Object.assign( Layers.prototype, {
set: function ( channel ) {
this.mask = 1 << channel | 0;
},
enable: function ( channel ) {
this.mask |= 1 << channel | 0;
},
toggle: function ( channel ) {
this.mask ^= 1 << channel | 0;
},
disable: function ( channel ) {
this.mask &= ~ ( 1 << channel | 0 );
},
test: function ( layers ) {
return ( this.mask & layers.mask ) !== 0;
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
* @author WestLangley / http://github.com/WestLangley
* @author elephantatwork / www.elephantatwork.ch
*/
var object3DId = 0;
function Object3D() {
Object.defineProperty( this, 'id', { value: object3DId ++ } );
this.uuid = _Math.generateUUID();
this.name = '';
this.type = 'Object3D';
this.parent = null;
this.children = [];
this.up = Object3D.DefaultUp.clone();
var position = new Vector3();
var rotation = new Euler();
var quaternion = new Quaternion();
var scale = new Vector3( 1, 1, 1 );
function onRotationChange() {
quaternion.setFromEuler( rotation, false );
}
function onQuaternionChange() {
rotation.setFromQuaternion( quaternion, undefined, false );
}
rotation.onChange( onRotationChange );
quaternion.onChange( onQuaternionChange );
Object.defineProperties( this, {
position: {
enumerable: true,
value: position
},
rotation: {
enumerable: true,
value: rotation
},
quaternion: {
enumerable: true,
value: quaternion
},
scale: {
enumerable: true,
value: scale
},
modelViewMatrix: {
value: new Matrix4()
},
normalMatrix: {
value: new Matrix3()
}
} );
this.matrix = new Matrix4();
this.matrixWorld = new Matrix4();
this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
this.matrixWorldNeedsUpdate = false;
this.layers = new Layers();
this.visible = true;
this.castShadow = false;
this.receiveShadow = false;
this.frustumCulled = true;
this.renderOrder = 0;
this.userData = {};
}
Object3D.DefaultUp = new Vector3( 0, 1, 0 );
Object3D.DefaultMatrixAutoUpdate = true;
Object.assign( Object3D.prototype, EventDispatcher.prototype, {
isObject3D: true,
onBeforeRender: function () {},
onAfterRender: function () {},
applyMatrix: function ( matrix ) {
this.matrix.multiplyMatrices( matrix, this.matrix );
this.matrix.decompose( this.position, this.quaternion, this.scale );
},
applyQuaternion: function ( q ) {
this.quaternion.premultiply( q );
return this;
},
setRotationFromAxisAngle: function ( axis, angle ) {
// assumes axis is normalized
this.quaternion.setFromAxisAngle( axis, angle );
},
setRotationFromEuler: function ( euler ) {
this.quaternion.setFromEuler( euler, true );
},
setRotationFromMatrix: function ( m ) {
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
this.quaternion.setFromRotationMatrix( m );
},
setRotationFromQuaternion: function ( q ) {
// assumes q is normalized
this.quaternion.copy( q );
},
rotateOnAxis: function () {
// rotate object on axis in object space
// axis is assumed to be normalized
var q1 = new Quaternion();
return function rotateOnAxis( axis, angle ) {
q1.setFromAxisAngle( axis, angle );
this.quaternion.multiply( q1 );
return this;
};
}(),
rotateOnWorldAxis: function () {
// rotate object on axis in world space
// axis is assumed to be normalized
// method assumes no rotated parent
var q1 = new Quaternion();
return function rotateOnWorldAxis( axis, angle ) {
q1.setFromAxisAngle( axis, angle );
this.quaternion.premultiply( q1 );
return this;
};
}(),
rotateX: function () {
var v1 = new Vector3( 1, 0, 0 );
return function rotateX( angle ) {
return this.rotateOnAxis( v1, angle );
};
}(),
rotateY: function () {
var v1 = new Vector3( 0, 1, 0 );
return function rotateY( angle ) {
return this.rotateOnAxis( v1, angle );
};
}(),
rotateZ: function () {
var v1 = new Vector3( 0, 0, 1 );
return function rotateZ( angle ) {
return this.rotateOnAxis( v1, angle );
};
}(),
translateOnAxis: function () {
// translate object by distance along axis in object space
// axis is assumed to be normalized
var v1 = new Vector3();
return function translateOnAxis( axis, distance ) {
v1.copy( axis ).applyQuaternion( this.quaternion );
this.position.add( v1.multiplyScalar( distance ) );
return this;
};
}(),
translateX: function () {
var v1 = new Vector3( 1, 0, 0 );
return function translateX( distance ) {
return this.translateOnAxis( v1, distance );
};
}(),
translateY: function () {
var v1 = new Vector3( 0, 1, 0 );
return function translateY( distance ) {
return this.translateOnAxis( v1, distance );
};
}(),
translateZ: function () {
var v1 = new Vector3( 0, 0, 1 );
return function translateZ( distance ) {
return this.translateOnAxis( v1, distance );
};
}(),
localToWorld: function ( vector ) {
return vector.applyMatrix4( this.matrixWorld );
},
worldToLocal: function () {
var m1 = new Matrix4();
return function worldToLocal( vector ) {
return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
};
}(),
lookAt: function () {
// This method does not support objects with rotated and/or translated parent(s)
var m1 = new Matrix4();
var vector = new Vector3();
return function lookAt( x, y, z ) {
if ( x.isVector3 ) {
vector.copy( x );
} else {
vector.set( x, y, z );
}
if ( this.isCamera ) {
m1.lookAt( this.position, vector, this.up );
} else {
m1.lookAt( vector, this.position, this.up );
}
this.quaternion.setFromRotationMatrix( m1 );
};
}(),
add: function ( object ) {
var arguments$1 = arguments;
var this$1 = this;
if ( arguments.length > 1 ) {
for ( var i = 0; i < arguments.length; i ++ ) {
this$1.add( arguments$1[ i ] );
}
return this;
}
if ( object === this ) {
console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
return this;
}
if ( ( object && object.isObject3D ) ) {
if ( object.parent !== null ) {
object.parent.remove( object );
}
object.parent = this;
object.dispatchEvent( { type: 'added' } );
this.children.push( object );
} else {
console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
}
return this;
},
remove: function ( object ) {
var arguments$1 = arguments;
var this$1 = this;
if ( arguments.length > 1 ) {
for ( var i = 0; i < arguments.length; i ++ ) {
this$1.remove( arguments$1[ i ] );
}
return this;
}
var index = this.children.indexOf( object );
if ( index !== - 1 ) {
object.parent = null;
object.dispatchEvent( { type: 'removed' } );
this.children.splice( index, 1 );
}
return this;
},
getObjectById: function ( id ) {
return this.getObjectByProperty( 'id', id );
},
getObjectByName: function ( name ) {
return this.getObjectByProperty( 'name', name );
},
getObjectByProperty: function ( name, value ) {
var this$1 = this;
if ( this[ name ] === value ) { return this; }
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
var child = this$1.children[ i ];
var object = child.getObjectByProperty( name, value );
if ( object !== undefined ) {
return object;
}
}
return undefined;
},
getWorldPosition: function ( optionalTarget ) {
var result = optionalTarget || new Vector3();
this.updateMatrixWorld( true );
return result.setFromMatrixPosition( this.matrixWorld );
},
getWorldQuaternion: function () {
var position = new Vector3();
var scale = new Vector3();
return function getWorldQuaternion( optionalTarget ) {
var result = optionalTarget || new Quaternion();
this.updateMatrixWorld( true );
this.matrixWorld.decompose( position, result, scale );
return result;
};
}(),
getWorldRotation: function () {
var quaternion = new Quaternion();
return function getWorldRotation( optionalTarget ) {
var result = optionalTarget || new Euler();
this.getWorldQuaternion( quaternion );
return result.setFromQuaternion( quaternion, this.rotation.order, false );
};
}(),
getWorldScale: function () {
var position = new Vector3();
var quaternion = new Quaternion();
return function getWorldScale( optionalTarget ) {
var result = optionalTarget || new Vector3();
this.updateMatrixWorld( true );
this.matrixWorld.decompose( position, quaternion, result );
return result;
};
}(),
getWorldDirection: function () {
var quaternion = new Quaternion();
return function getWorldDirection( optionalTarget ) {
var result = optionalTarget || new Vector3();
this.getWorldQuaternion( quaternion );
return result.set( 0, 0, 1 ).applyQuaternion( quaternion );
};
}(),
raycast: function () {},
traverse: function ( callback ) {
callback( this );
var children = this.children;
for ( var i = 0, l = children.length; i < l; i ++ ) {
children[ i ].traverse( callback );
}
},
traverseVisible: function ( callback ) {
if ( this.visible === false ) { return; }
callback( this );
var children = this.children;
for ( var i = 0, l = children.length; i < l; i ++ ) {
children[ i ].traverseVisible( callback );
}
},
traverseAncestors: function ( callback ) {
var parent = this.parent;
if ( parent !== null ) {
callback( parent );
parent.traverseAncestors( callback );
}
},
updateMatrix: function () {
this.matrix.compose( this.position, this.quaternion, this.scale );
this.matrixWorldNeedsUpdate = true;
},
updateMatrixWorld: function ( force ) {
if ( this.matrixAutoUpdate ) { this.updateMatrix(); }
if ( this.matrixWorldNeedsUpdate || force ) {
if ( this.parent === null ) {
this.matrixWorld.copy( this.matrix );
} else {
this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
}
this.matrixWorldNeedsUpdate = false;
force = true;
}
// update children
var children = this.children;
for ( var i = 0, l = children.length; i < l; i ++ ) {
children[ i ].updateMatrixWorld( force );
}
},
toJSON: function ( meta ) {
var this$1 = this;
// meta is a string when called from JSON.stringify
var isRootObject = ( meta === undefined || typeof meta === 'string' );
var output = {};
// meta is a hash used to collect geometries, materials.
// not providing it implies that this is the root object
// being serialized.
if ( isRootObject ) {
// initialize meta obj
meta = {
geometries: {},
materials: {},
textures: {},
images: {}
};
output.metadata = {
version: 4.5,
type: 'Object',
generator: 'Object3D.toJSON'
};
}
// standard Object3D serialization
var object = {};
object.uuid = this.uuid;
object.type = this.type;
if ( this.name !== '' ) { object.name = this.name; }
if ( this.castShadow === true ) { object.castShadow = true; }
if ( this.receiveShadow === true ) { object.receiveShadow = true; }
if ( this.visible === false ) { object.visible = false; }
if ( JSON.stringify( this.userData ) !== '{}' ) { object.userData = this.userData; }
object.matrix = this.matrix.toArray();
//
function serialize( library, element ) {
if ( library[ element.uuid ] === undefined ) {
library[ element.uuid ] = element.toJSON( meta );
}
return element.uuid;
}
if ( this.geometry !== undefined ) {
object.geometry = serialize( meta.geometries, this.geometry );
}
if ( this.material !== undefined ) {
if ( Array.isArray( this.material ) ) {
var uuids = [];
for ( var i = 0, l = this.material.length; i < l; i ++ ) {
uuids.push( serialize( meta.materials, this$1.material[ i ] ) );
}
object.material = uuids;
} else {
object.material = serialize( meta.materials, this.material );
}
}
//
if ( this.children.length > 0 ) {
object.children = [];
for ( var i = 0; i < this.children.length; i ++ ) {
object.children.push( this$1.children[ i ].toJSON( meta ).object );
}
}
if ( isRootObject ) {
var geometries = extractFromCache( meta.geometries );
var materials = extractFromCache( meta.materials );
var textures = extractFromCache( meta.textures );
var images = extractFromCache( meta.images );
if ( geometries.length > 0 ) { output.geometries = geometries; }
if ( materials.length > 0 ) { output.materials = materials; }
if ( textures.length > 0 ) { output.textures = textures; }
if ( images.length > 0 ) { output.images = images; }
}
output.object = object;
return output;
// extract data from the cache hash
// remove metadata on each item
// and return as array
function extractFromCache( cache ) {
var values = [];
for ( var key in cache ) {
var data = cache[ key ];
delete data.metadata;
values.push( data );
}
return values;
}
},
clone: function ( recursive ) {
return new this.constructor().copy( this, recursive );
},
copy: function ( source, recursive ) {
var this$1 = this;
if ( recursive === undefined ) { recursive = true; }
this.name = source.name;
this.up.copy( source.up );
this.position.copy( source.position );
this.quaternion.copy( source.quaternion );
this.scale.copy( source.scale );
this.matrix.copy( source.matrix );
this.matrixWorld.copy( source.matrixWorld );
this.matrixAutoUpdate = source.matrixAutoUpdate;
this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
this.layers.mask = source.layers.mask;
this.visible = source.visible;
this.castShadow = source.castShadow;
this.receiveShadow = source.receiveShadow;
this.frustumCulled = source.frustumCulled;
this.renderOrder = source.renderOrder;
this.userData = JSON.parse( JSON.stringify( source.userData ) );
if ( recursive === true ) {
for ( var i = 0; i < source.children.length; i ++ ) {
var child = source.children[ i ];
this$1.add( child.clone() );
}
}
return this;
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author mikael emtinger / http://gomo.se/
* @author WestLangley / http://github.com/WestLangley
*/
function Camera() {
Object3D.call( this );
this.type = 'Camera';
this.matrixWorldInverse = new Matrix4();
this.projectionMatrix = new Matrix4();
}
Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Camera,
isCamera: true,
copy: function ( source, recursive ) {
Object3D.prototype.copy.call( this, source, recursive );
this.matrixWorldInverse.copy( source.matrixWorldInverse );
this.projectionMatrix.copy( source.projectionMatrix );
return this;
},
getWorldDirection: function () {
var quaternion = new Quaternion();
return function getWorldDirection( optionalTarget ) {
var result = optionalTarget || new Vector3();
this.getWorldQuaternion( quaternion );
return result.set( 0, 0, - 1 ).applyQuaternion( quaternion );
};
}(),
updateMatrixWorld: function ( force ) {
Object3D.prototype.updateMatrixWorld.call( this, force );
this.matrixWorldInverse.getInverse( this.matrixWorld );
},
clone: function () {
return new this.constructor().copy( this );
}
} );
/**
* @author alteredq / http://alteredqualia.com/
* @author arose / http://github.com/arose
*/
function OrthographicCamera( left, right, top, bottom, near, far ) {
Camera.call( this );
this.type = 'OrthographicCamera';
this.zoom = 1;
this.view = null;
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
this.near = ( near !== undefined ) ? near : 0.1;
this.far = ( far !== undefined ) ? far : 2000;
this.updateProjectionMatrix();
}
OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
constructor: OrthographicCamera,
isOrthographicCamera: true,
copy: function ( source, recursive ) {
Camera.prototype.copy.call( this, source, recursive );
this.left = source.left;
this.right = source.right;
this.top = source.top;
this.bottom = source.bottom;
this.near = source.near;
this.far = source.far;
this.zoom = source.zoom;
this.view = source.view === null ? null : Object.assign( {}, source.view );
return this;
},
setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
if ( this.view === null ) {
this.view = {
enabled: true,
fullWidth: 1,
fullHeight: 1,
offsetX: 0,
offsetY: 0,
width: 1,
height: 1
};
}
this.view.enabled = true;
this.view.fullWidth = fullWidth;
this.view.fullHeight = fullHeight;
this.view.offsetX = x;
this.view.offsetY = y;
this.view.width = width;
this.view.height = height;
this.updateProjectionMatrix();
},
clearViewOffset: function () {
if ( this.view !== null ) {
this.view.enabled = false;
}
this.updateProjectionMatrix();
},
updateProjectionMatrix: function () {
var dx = ( this.right - this.left ) / ( 2 * this.zoom );
var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
var cx = ( this.right + this.left ) / 2;
var cy = ( this.top + this.bottom ) / 2;
var left = cx - dx;
var right = cx + dx;
var top = cy + dy;
var bottom = cy - dy;
if ( this.view !== null && this.view.enabled ) {
var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
var scaleW = ( this.right - this.left ) / this.view.width;
var scaleH = ( this.top - this.bottom ) / this.view.height;
left += scaleW * ( this.view.offsetX / zoomW );
right = left + scaleW * ( this.view.width / zoomW );
top -= scaleH * ( this.view.offsetY / zoomH );
bottom = top - scaleH * ( this.view.height / zoomH );
}
this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
},
toJSON: function ( meta ) {
var data = Object3D.prototype.toJSON.call( this, meta );
data.object.zoom = this.zoom;
data.object.left = this.left;
data.object.right = this.right;
data.object.top = this.top;
data.object.bottom = this.bottom;
data.object.near = this.near;
data.object.far = this.far;
if ( this.view !== null ) { data.object.view = Object.assign( {}, this.view ); }
return data;
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
*/
function Face3( a, b, c, normal, color, materialIndex ) {
this.a = a;
this.b = b;
this.c = c;
this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
this.vertexNormals = Array.isArray( normal ) ? normal : [];
this.color = ( color && color.isColor ) ? color : new Color();
this.vertexColors = Array.isArray( color ) ? color : [];
this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
}
Object.assign( Face3.prototype, {
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( source ) {
var this$1 = this;
this.a = source.a;
this.b = source.b;
this.c = source.c;
this.normal.copy( source.normal );
this.color.copy( source.color );
this.materialIndex = source.materialIndex;
for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
this$1.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
}
for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
this$1.vertexColors[ i ] = source.vertexColors[ i ].clone();
}
return this;
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author kile / http://kile.stravaganza.org/
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
* @author zz85 / http://www.lab4games.net/zz85/blog
* @author bhouston / http://clara.io
*/
var geometryId = 0; // Geometry uses even numbers as Id
function Geometry() {
Object.defineProperty( this, 'id', { value: geometryId += 2 } );
this.uuid = _Math.generateUUID();
this.name = '';
this.type = 'Geometry';
this.vertices = [];
this.colors = [];
this.faces = [];
this.faceVertexUvs = [[]];
this.morphTargets = [];
this.morphNormals = [];
this.skinWeights = [];
this.skinIndices = [];
this.lineDistances = [];
this.boundingBox = null;
this.boundingSphere = null;
// update flags
this.elementsNeedUpdate = false;
this.verticesNeedUpdate = false;
this.uvsNeedUpdate = false;
this.normalsNeedUpdate = false;
this.colorsNeedUpdate = false;
this.lineDistancesNeedUpdate = false;
this.groupsNeedUpdate = false;
}
Object.assign( Geometry.prototype, EventDispatcher.prototype, {
isGeometry: true,
applyMatrix: function ( matrix ) {
var this$1 = this;
var normalMatrix = new Matrix3().getNormalMatrix( matrix );
for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
var vertex = this$1.vertices[ i ];
vertex.applyMatrix4( matrix );
}
for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
var face = this$1.faces[ i ];
face.normal.applyMatrix3( normalMatrix ).normalize();
for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
}
}
if ( this.boundingBox !== null ) {
this.computeBoundingBox();
}
if ( this.boundingSphere !== null ) {
this.computeBoundingSphere();
}
this.verticesNeedUpdate = true;
this.normalsNeedUpdate = true;
return this;
},
rotateX: function () {
// rotate geometry around world x-axis
var m1 = new Matrix4();
return function rotateX( angle ) {
m1.makeRotationX( angle );
this.applyMatrix( m1 );
return this;
};
}(),
rotateY: function () {
// rotate geometry around world y-axis
var m1 = new Matrix4();
return function rotateY( angle ) {
m1.makeRotationY( angle );
this.applyMatrix( m1 );
return this;
};
}(),
rotateZ: function () {
// rotate geometry around world z-axis
var m1 = new Matrix4();
return function rotateZ( angle ) {
m1.makeRotationZ( angle );
this.applyMatrix( m1 );
return this;
};
}(),
translate: function () {
// translate geometry
var m1 = new Matrix4();
return function translate( x, y, z ) {
m1.makeTranslation( x, y, z );
this.applyMatrix( m1 );
return this;
};
}(),
scale: function () {
// scale geometry
var m1 = new Matrix4();
return function scale( x, y, z ) {
m1.makeScale( x, y, z );
this.applyMatrix( m1 );
return this;
};
}(),
lookAt: function () {
var obj = new Object3D();
return function lookAt( vector ) {
obj.lookAt( vector );
obj.updateMatrix();
this.applyMatrix( obj.matrix );
};
}(),
fromBufferGeometry: function ( geometry ) {
var scope = this;
var indices = geometry.index !== null ? geometry.index.array : undefined;
var attributes = geometry.attributes;
var positions = attributes.position.array;
var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
var colors = attributes.color !== undefined ? attributes.color.array : undefined;
var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
if ( uvs2 !== undefined ) { this.faceVertexUvs[ 1 ] = []; }
var tempNormals = [];
var tempUVs = [];
var tempUVs2 = [];
for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) );
if ( normals !== undefined ) {
tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
}
if ( colors !== undefined ) {
scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
}
if ( uvs !== undefined ) {
tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) );
}
if ( uvs2 !== undefined ) {
tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
}
}
function addFace( a, b, c, materialIndex ) {
var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
scope.faces.push( face );
if ( uvs !== undefined ) {
scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
}
if ( uvs2 !== undefined ) {
scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
}
}
var groups = geometry.groups;
if ( groups.length > 0 ) {
for ( var i = 0; i < groups.length; i ++ ) {
var group = groups[ i ];
var start = group.start;
var count = group.count;
for ( var j = start, jl = start + count; j < jl; j += 3 ) {
if ( indices !== undefined ) {
addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
} else {
addFace( j, j + 1, j + 2, group.materialIndex );
}
}
}
} else {
if ( indices !== undefined ) {
for ( var i = 0; i < indices.length; i += 3 ) {
addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
}
} else {
for ( var i = 0; i < positions.length / 3; i += 3 ) {
addFace( i, i + 1, i + 2 );
}
}
}
this.computeFaceNormals();
if ( geometry.boundingBox !== null ) {
this.boundingBox = geometry.boundingBox.clone();
}
if ( geometry.boundingSphere !== null ) {
this.boundingSphere = geometry.boundingSphere.clone();
}
return this;
},
center: function () {
this.computeBoundingBox();
var offset = this.boundingBox.getCenter().negate();
this.translate( offset.x, offset.y, offset.z );
return offset;
},
normalize: function () {
this.computeBoundingSphere();
var center = this.boundingSphere.center;
var radius = this.boundingSphere.radius;
var s = radius === 0 ? 1 : 1.0 / radius;
var matrix = new Matrix4();
matrix.set(
s, 0, 0, - s * center.x,
0, s, 0, - s * center.y,
0, 0, s, - s * center.z,
0, 0, 0, 1
);
this.applyMatrix( matrix );
return this;
},
computeFaceNormals: function () {
var this$1 = this;
var cb = new Vector3(), ab = new Vector3();
for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
var face = this$1.faces[ f ];
var vA = this$1.vertices[ face.a ];
var vB = this$1.vertices[ face.b ];
var vC = this$1.vertices[ face.c ];
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
cb.normalize();
face.normal.copy( cb );
}
},
computeVertexNormals: function ( areaWeighted ) {
var this$1 = this;
if ( areaWeighted === undefined ) { areaWeighted = true; }
var v, vl, f, fl, face, vertices;
vertices = new Array( this.vertices.length );
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
vertices[ v ] = new Vector3();
}
if ( areaWeighted ) {
// vertex normals weighted by triangle areas
// http://www.iquilezles.org/www/articles/normals/normals.htm
var vA, vB, vC;
var cb = new Vector3(), ab = new Vector3();
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this$1.faces[ f ];
vA = this$1.vertices[ face.a ];
vB = this$1.vertices[ face.b ];
vC = this$1.vertices[ face.c ];
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
vertices[ face.a ].add( cb );
vertices[ face.b ].add( cb );
vertices[ face.c ].add( cb );
}
} else {
this.computeFaceNormals();
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this$1.faces[ f ];
vertices[ face.a ].add( face.normal );
vertices[ face.b ].add( face.normal );
vertices[ face.c ].add( face.normal );
}
}
for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
vertices[ v ].normalize();
}
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this$1.faces[ f ];
var vertexNormals = face.vertexNormals;
if ( vertexNormals.length === 3 ) {
vertexNormals[ 0 ].copy( vertices[ face.a ] );
vertexNormals[ 1 ].copy( vertices[ face.b ] );
vertexNormals[ 2 ].copy( vertices[ face.c ] );
} else {
vertexNormals[ 0 ] = vertices[ face.a ].clone();
vertexNormals[ 1 ] = vertices[ face.b ].clone();
vertexNormals[ 2 ] = vertices[ face.c ].clone();
}
}
if ( this.faces.length > 0 ) {
this.normalsNeedUpdate = true;
}
},
computeFlatVertexNormals: function () {
var this$1 = this;
var f, fl, face;
this.computeFaceNormals();
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this$1.faces[ f ];
var vertexNormals = face.vertexNormals;
if ( vertexNormals.length === 3 ) {
vertexNormals[ 0 ].copy( face.normal );
vertexNormals[ 1 ].copy( face.normal );
vertexNormals[ 2 ].copy( face.normal );
} else {
vertexNormals[ 0 ] = face.normal.clone();
vertexNormals[ 1 ] = face.normal.clone();
vertexNormals[ 2 ] = face.normal.clone();
}
}
if ( this.faces.length > 0 ) {
this.normalsNeedUpdate = true;
}
},
computeMorphNormals: function () {
var this$1 = this;
var i, il, f, fl, face;
// save original normals
// - create temp variables on first access
// otherwise just copy (for faster repeated calls)
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this$1.faces[ f ];
if ( ! face.__originalFaceNormal ) {
face.__originalFaceNormal = face.normal.clone();
} else {
face.__originalFaceNormal.copy( face.normal );
}
if ( ! face.__originalVertexNormals ) { face.__originalVertexNormals = []; }
for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
if ( ! face.__originalVertexNormals[ i ] ) {
face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
} else {
face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
}
}
}
// use temp geometry to compute face and vertex normals for each morph
var tmpGeo = new Geometry();
tmpGeo.faces = this.faces;
for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
// create on first access
if ( ! this$1.morphNormals[ i ] ) {
this$1.morphNormals[ i ] = {};
this$1.morphNormals[ i ].faceNormals = [];
this$1.morphNormals[ i ].vertexNormals = [];
var dstNormalsFace = this$1.morphNormals[ i ].faceNormals;
var dstNormalsVertex = this$1.morphNormals[ i ].vertexNormals;
var faceNormal, vertexNormals;
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
faceNormal = new Vector3();
vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
dstNormalsFace.push( faceNormal );
dstNormalsVertex.push( vertexNormals );
}
}
var morphNormals = this$1.morphNormals[ i ];
// set vertices to morph target
tmpGeo.vertices = this$1.morphTargets[ i ].vertices;
// compute morph normals
tmpGeo.computeFaceNormals();
tmpGeo.computeVertexNormals();
// store morph normals
var faceNormal, vertexNormals;
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this$1.faces[ f ];
faceNormal = morphNormals.faceNormals[ f ];
vertexNormals = morphNormals.vertexNormals[ f ];
faceNormal.copy( face.normal );
vertexNormals.a.copy( face.vertexNormals[ 0 ] );
vertexNormals.b.copy( face.vertexNormals[ 1 ] );
vertexNormals.c.copy( face.vertexNormals[ 2 ] );
}
}
// restore original normals
for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
face = this$1.faces[ f ];
face.normal = face.__originalFaceNormal;
face.vertexNormals = face.__originalVertexNormals;
}
},
computeLineDistances: function () {
var this$1 = this;
var d = 0;
var vertices = this.vertices;
for ( var i = 0, il = vertices.length; i < il; i ++ ) {
if ( i > 0 ) {
d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
}
this$1.lineDistances[ i ] = d;
}
},
computeBoundingBox: function () {
if ( this.boundingBox === null ) {
this.boundingBox = new Box3();
}
this.boundingBox.setFromPoints( this.vertices );
},
computeBoundingSphere: function () {
if ( this.boundingSphere === null ) {
this.boundingSphere = new Sphere();
}
this.boundingSphere.setFromPoints( this.vertices );
},
merge: function ( geometry, matrix, materialIndexOffset ) {
if ( ! ( geometry && geometry.isGeometry ) ) {
console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
return;
}
var normalMatrix,
vertexOffset = this.vertices.length,
vertices1 = this.vertices,
vertices2 = geometry.vertices,
faces1 = this.faces,
faces2 = geometry.faces,
uvs1 = this.faceVertexUvs[ 0 ],
uvs2 = geometry.faceVertexUvs[ 0 ],
colors1 = this.colors,
colors2 = geometry.colors;
if ( materialIndexOffset === undefined ) { materialIndexOffset = 0; }
if ( matrix !== undefined ) {
normalMatrix = new Matrix3().getNormalMatrix( matrix );
}
// vertices
for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
var vertex = vertices2[ i ];
var vertexCopy = vertex.clone();
if ( matrix !== undefined ) { vertexCopy.applyMatrix4( matrix ); }
vertices1.push( vertexCopy );
}
// colors
for ( var i = 0, il = colors2.length; i < il; i ++ ) {
colors1.push( colors2[ i ].clone() );
}
// faces
for ( i = 0, il = faces2.length; i < il; i ++ ) {
var face = faces2[ i ], faceCopy, normal, color,
faceVertexNormals = face.vertexNormals,
faceVertexColors = face.vertexColors;
faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
faceCopy.normal.copy( face.normal );
if ( normalMatrix !== undefined ) {
faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
}
for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
normal = faceVertexNormals[ j ].clone();
if ( normalMatrix !== undefined ) {
normal.applyMatrix3( normalMatrix ).normalize();
}
faceCopy.vertexNormals.push( normal );
}
faceCopy.color.copy( face.color );
for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
color = faceVertexColors[ j ];
faceCopy.vertexColors.push( color.clone() );
}
faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
faces1.push( faceCopy );
}
// uvs
for ( i = 0, il = uvs2.length; i < il; i ++ ) {
var uv = uvs2[ i ], uvCopy = [];
if ( uv === undefined ) {
continue;
}
for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
uvCopy.push( uv[ j ].clone() );
}
uvs1.push( uvCopy );
}
},
mergeMesh: function ( mesh ) {
if ( ! ( mesh && mesh.isMesh ) ) {
console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
return;
}
mesh.matrixAutoUpdate && mesh.updateMatrix();
this.merge( mesh.geometry, mesh.matrix );
},
/*
* Checks for duplicate vertices with hashmap.
* Duplicated vertices are removed
* and faces' vertices are updated.
*/
mergeVertices: function () {
var this$1 = this;
var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
var unique = [], changes = [];
var v, key;
var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
var precision = Math.pow( 10, precisionPoints );
var i, il, face;
var indices, j, jl;
for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
v = this$1.vertices[ i ];
key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
if ( verticesMap[ key ] === undefined ) {
verticesMap[ key ] = i;
unique.push( this$1.vertices[ i ] );
changes[ i ] = unique.length - 1;
} else {
//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
changes[ i ] = changes[ verticesMap[ key ] ];
}
}
// if faces are completely degenerate after merging vertices, we
// have to remove them from the geometry.
var faceIndicesToRemove = [];
for ( i = 0, il = this.faces.length; i < il; i ++ ) {
face = this$1.faces[ i ];
face.a = changes[ face.a ];
face.b = changes[ face.b ];
face.c = changes[ face.c ];
indices = [ face.a, face.b, face.c ];
// if any duplicate vertices are found in a Face3
// we have to remove the face as nothing can be saved
for ( var n = 0; n < 3; n ++ ) {
if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
faceIndicesToRemove.push( i );
break;
}
}
}
for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
var idx = faceIndicesToRemove[ i ];
this$1.faces.splice( idx, 1 );
for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
this$1.faceVertexUvs[ j ].splice( idx, 1 );
}
}
// Use unique set of vertices
var diff = this.vertices.length - unique.length;
this.vertices = unique;
return diff;
},
setFromPoints: function ( points ) {
var this$1 = this;
this.vertices = [];
for ( var i = 0, l = points.length; i < l; i ++ ) {
var point = points[ i ];
this$1.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
}
return this;
},
sortFacesByMaterialIndex: function () {
var faces = this.faces;
var length = faces.length;
// tag faces
for ( var i = 0; i < length; i ++ ) {
faces[ i ]._id = i;
}
// sort faces
function materialIndexSort( a, b ) {
return a.materialIndex - b.materialIndex;
}
faces.sort( materialIndexSort );
// sort uvs
var uvs1 = this.faceVertexUvs[ 0 ];
var uvs2 = this.faceVertexUvs[ 1 ];
var newUvs1, newUvs2;
if ( uvs1 && uvs1.length === length ) { newUvs1 = []; }
if ( uvs2 && uvs2.length === length ) { newUvs2 = []; }
for ( var i = 0; i < length; i ++ ) {
var id = faces[ i ]._id;
if ( newUvs1 ) { newUvs1.push( uvs1[ id ] ); }
if ( newUvs2 ) { newUvs2.push( uvs2[ id ] ); }
}
if ( newUvs1 ) { this.faceVertexUvs[ 0 ] = newUvs1; }
if ( newUvs2 ) { this.faceVertexUvs[ 1 ] = newUvs2; }
},
toJSON: function () {
var this$1 = this;
var data = {
metadata: {
version: 4.5,
type: 'Geometry',
generator: 'Geometry.toJSON'
}
};
// standard Geometry serialization
data.uuid = this.uuid;
data.type = this.type;
if ( this.name !== '' ) { data.name = this.name; }
if ( this.parameters !== undefined ) {
var parameters = this.parameters;
for ( var key in parameters ) {
if ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; }
}
return data;
}
var vertices = [];
for ( var i = 0; i < this.vertices.length; i ++ ) {
var vertex = this$1.vertices[ i ];
vertices.push( vertex.x, vertex.y, vertex.z );
}
var faces = [];
var normals = [];
var normalsHash = {};
var colors = [];
var colorsHash = {};
var uvs = [];
var uvsHash = {};
for ( var i = 0; i < this.faces.length; i ++ ) {
var face = this$1.faces[ i ];
var hasMaterial = true;
var hasFaceUv = false; // deprecated
var hasFaceVertexUv = this$1.faceVertexUvs[ 0 ][ i ] !== undefined;
var hasFaceNormal = face.normal.length() > 0;
var hasFaceVertexNormal = face.vertexNormals.length > 0;
var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
var hasFaceVertexColor = face.vertexColors.length > 0;
var faceType = 0;
faceType = setBit( faceType, 0, 0 ); // isQuad
faceType = setBit( faceType, 1, hasMaterial );
faceType = setBit( faceType, 2, hasFaceUv );
faceType = setBit( faceType, 3, hasFaceVertexUv );
faceType = setBit( faceType, 4, hasFaceNormal );
faceType = setBit( faceType, 5, hasFaceVertexNormal );
faceType = setBit( faceType, 6, hasFaceColor );
faceType = setBit( faceType, 7, hasFaceVertexColor );
faces.push( faceType );
faces.push( face.a, face.b, face.c );
faces.push( face.materialIndex );
if ( hasFaceVertexUv ) {
var faceVertexUvs = this$1.faceVertexUvs[ 0 ][ i ];
faces.push(
getUvIndex( faceVertexUvs[ 0 ] ),
getUvIndex( faceVertexUvs[ 1 ] ),
getUvIndex( faceVertexUvs[ 2 ] )
);
}
if ( hasFaceNormal ) {
faces.push( getNormalIndex( face.normal ) );
}
if ( hasFaceVertexNormal ) {
var vertexNormals = face.vertexNormals;
faces.push(
getNormalIndex( vertexNormals[ 0 ] ),
getNormalIndex( vertexNormals[ 1 ] ),
getNormalIndex( vertexNormals[ 2 ] )
);
}
if ( hasFaceColor ) {
faces.push( getColorIndex( face.color ) );
}
if ( hasFaceVertexColor ) {
var vertexColors = face.vertexColors;
faces.push(
getColorIndex( vertexColors[ 0 ] ),
getColorIndex( vertexColors[ 1 ] ),
getColorIndex( vertexColors[ 2 ] )
);
}
}
function setBit( value, position, enabled ) {
return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
}
function getNormalIndex( normal ) {
var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
if ( normalsHash[ hash ] !== undefined ) {
return normalsHash[ hash ];
}
normalsHash[ hash ] = normals.length / 3;
normals.push( normal.x, normal.y, normal.z );
return normalsHash[ hash ];
}
function getColorIndex( color ) {
var hash = color.r.toString() + color.g.toString() + color.b.toString();
if ( colorsHash[ hash ] !== undefined ) {
return colorsHash[ hash ];
}
colorsHash[ hash ] = colors.length;
colors.push( color.getHex() );
return colorsHash[ hash ];
}
function getUvIndex( uv ) {
var hash = uv.x.toString() + uv.y.toString();
if ( uvsHash[ hash ] !== undefined ) {
return uvsHash[ hash ];
}
uvsHash[ hash ] = uvs.length / 2;
uvs.push( uv.x, uv.y );
return uvsHash[ hash ];
}
data.data = {};
data.data.vertices = vertices;
data.data.normals = normals;
if ( colors.length > 0 ) { data.data.colors = colors; }
if ( uvs.length > 0 ) { data.data.uvs = [ uvs ]; } // temporal backward compatibility
data.data.faces = faces;
return data;
},
clone: function () {
/*
// Handle primitives
var parameters = this.parameters;
if ( parameters !== undefined ) {
var values = [];
for ( var key in parameters ) {
values.push( parameters[ key ] );
}
var geometry = Object.create( this.constructor.prototype );
this.constructor.apply( geometry, values );
return geometry;
}
return new this.constructor().copy( this );
*/
return new Geometry().copy( this );
},
copy: function ( source ) {
var this$1 = this;
var i, il, j, jl, k, kl;
// reset
this.vertices = [];
this.colors = [];
this.faces = [];
this.faceVertexUvs = [[]];
this.morphTargets = [];
this.morphNormals = [];
this.skinWeights = [];
this.skinIndices = [];
this.lineDistances = [];
this.boundingBox = null;
this.boundingSphere = null;
// name
this.name = source.name;
// vertices
var vertices = source.vertices;
for ( i = 0, il = vertices.length; i < il; i ++ ) {
this$1.vertices.push( vertices[ i ].clone() );
}
// colors
var colors = source.colors;
for ( i = 0, il = colors.length; i < il; i ++ ) {
this$1.colors.push( colors[ i ].clone() );
}
// faces
var faces = source.faces;
for ( i = 0, il = faces.length; i < il; i ++ ) {
this$1.faces.push( faces[ i ].clone() );
}
// face vertex uvs
for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
var faceVertexUvs = source.faceVertexUvs[ i ];
if ( this$1.faceVertexUvs[ i ] === undefined ) {
this$1.faceVertexUvs[ i ] = [];
}
for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
var uvs = faceVertexUvs[ j ], uvsCopy = [];
for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
var uv = uvs[ k ];
uvsCopy.push( uv.clone() );
}
this$1.faceVertexUvs[ i ].push( uvsCopy );
}
}
// morph targets
var morphTargets = source.morphTargets;
for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
var morphTarget = {};
morphTarget.name = morphTargets[ i ].name;
// vertices
if ( morphTargets[ i ].vertices !== undefined ) {
morphTarget.vertices = [];
for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
}
}
// normals
if ( morphTargets[ i ].normals !== undefined ) {
morphTarget.normals = [];
for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
}
}
this$1.morphTargets.push( morphTarget );
}
// morph normals
var morphNormals = source.morphNormals;
for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
var morphNormal = {};
// vertex normals
if ( morphNormals[ i ].vertexNormals !== undefined ) {
morphNormal.vertexNormals = [];
for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
var destVertexNormal = {};
destVertexNormal.a = srcVertexNormal.a.clone();
destVertexNormal.b = srcVertexNormal.b.clone();
destVertexNormal.c = srcVertexNormal.c.clone();
morphNormal.vertexNormals.push( destVertexNormal );
}
}
// face normals
if ( morphNormals[ i ].faceNormals !== undefined ) {
morphNormal.faceNormals = [];
for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
}
}
this$1.morphNormals.push( morphNormal );
}
// skin weights
var skinWeights = source.skinWeights;
for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
this$1.skinWeights.push( skinWeights[ i ].clone() );
}
// skin indices
var skinIndices = source.skinIndices;
for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
this$1.skinIndices.push( skinIndices[ i ].clone() );
}
// line distances
var lineDistances = source.lineDistances;
for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
this$1.lineDistances.push( lineDistances[ i ] );
}
// bounding box
var boundingBox = source.boundingBox;
if ( boundingBox !== null ) {
this.boundingBox = boundingBox.clone();
}
// bounding sphere
var boundingSphere = source.boundingSphere;
if ( boundingSphere !== null ) {
this.boundingSphere = boundingSphere.clone();
}
// update flags
this.elementsNeedUpdate = source.elementsNeedUpdate;
this.verticesNeedUpdate = source.verticesNeedUpdate;
this.uvsNeedUpdate = source.uvsNeedUpdate;
this.normalsNeedUpdate = source.normalsNeedUpdate;
this.colorsNeedUpdate = source.colorsNeedUpdate;
this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
this.groupsNeedUpdate = source.groupsNeedUpdate;
return this;
},
dispose: function () {
this.dispatchEvent( { type: 'dispose' } );
}
} );
/**
* @author mrdoob / http://mrdoob.com/
*/
function BufferAttribute( array, itemSize, normalized ) {
if ( Array.isArray( array ) ) {
throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
}
this.uuid = _Math.generateUUID();
this.name = '';
this.array = array;
this.itemSize = itemSize;
this.count = array !== undefined ? array.length / itemSize : 0;
this.normalized = normalized === true;
this.dynamic = false;
this.updateRange = { offset: 0, count: - 1 };
this.onUploadCallback = function () {};
this.version = 0;
}
Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
set: function ( value ) {
if ( value === true ) { this.version ++; }
}
} );
Object.assign( BufferAttribute.prototype, {
isBufferAttribute: true,
setArray: function ( array ) {
if ( Array.isArray( array ) ) {
throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
}
this.count = array !== undefined ? array.length / this.itemSize : 0;
this.array = array;
},
setDynamic: function ( value ) {
this.dynamic = value;
return this;
},
copy: function ( source ) {
this.array = new source.array.constructor( source.array );
this.itemSize = source.itemSize;
this.count = source.count;
this.normalized = source.normalized;
this.dynamic = source.dynamic;
return this;
},
copyAt: function ( index1, attribute, index2 ) {
var this$1 = this;
index1 *= this.itemSize;
index2 *= attribute.itemSize;
for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
this$1.array[ index1 + i ] = attribute.array[ index2 + i ];
}
return this;
},
copyArray: function ( array ) {
this.array.set( array );
return this;
},
copyColorsArray: function ( colors ) {
var array = this.array, offset = 0;
for ( var i = 0, l = colors.length; i < l; i ++ ) {
var color = colors[ i ];
if ( color === undefined ) {
console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
color = new Color();
}
array[ offset ++ ] = color.r;
array[ offset ++ ] = color.g;
array[ offset ++ ] = color.b;
}
return this;
},
copyIndicesArray: function ( indices ) {
var array = this.array, offset = 0;
for ( var i = 0, l = indices.length; i < l; i ++ ) {
var index = indices[ i ];
array[ offset ++ ] = index.a;
array[ offset ++ ] = index.b;
array[ offset ++ ] = index.c;
}
return this;
},
copyVector2sArray: function ( vectors ) {
var array = this.array, offset = 0;
for ( var i = 0, l = vectors.length; i < l; i ++ ) {
var vector = vectors[ i ];
if ( vector === undefined ) {
console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
vector = new Vector2();
}
array[ offset ++ ] = vector.x;
array[ offset ++ ] = vector.y;
}
return this;
},
copyVector3sArray: function ( vectors ) {
var array = this.array, offset = 0;
for ( var i = 0, l = vectors.length; i < l; i ++ ) {
var vector = vectors[ i ];
if ( vector === undefined ) {
console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
vector = new Vector3();
}
array[ offset ++ ] = vector.x;
array[ offset ++ ] = vector.y;
array[ offset ++ ] = vector.z;
}
return this;
},
copyVector4sArray: function ( vectors ) {
var array = this.array, offset = 0;
for ( var i = 0, l = vectors.length; i < l; i ++ ) {
var vector = vectors[ i ];
if ( vector === undefined ) {
console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
vector = new Vector4();
}
array[ offset ++ ] = vector.x;
array[ offset ++ ] = vector.y;
array[ offset ++ ] = vector.z;
array[ offset ++ ] = vector.w;
}
return this;
},
set: function ( value, offset ) {
if ( offset === undefined ) { offset = 0; }
this.array.set( value, offset );
return this;
},
getX: function ( index ) {
return this.array[ index * this.itemSize ];
},
setX: function ( index, x ) {
this.array[ index * this.itemSize ] = x;
return this;
},
getY: function ( index ) {
return this.array[ index * this.itemSize + 1 ];
},
setY: function ( index, y ) {
this.array[ index * this.itemSize + 1 ] = y;
return this;
},
getZ: function ( index ) {
return this.array[ index * this.itemSize + 2 ];
},
setZ: function ( index, z ) {
this.array[ index * this.itemSize + 2 ] = z;
return this;
},
getW: function ( index ) {
return this.array[ index * this.itemSize + 3 ];
},
setW: function ( index, w ) {
this.array[ index * this.itemSize + 3 ] = w;
return this;
},
setXY: function ( index, x, y ) {
index *= this.itemSize;
this.array[ index + 0 ] = x;
this.array[ index + 1 ] = y;
return this;
},
setXYZ: function ( index, x, y, z ) {
index *= this.itemSize;
this.array[ index + 0 ] = x;
this.array[ index + 1 ] = y;
this.array[ index + 2 ] = z;
return this;
},
setXYZW: function ( index, x, y, z, w ) {
index *= this.itemSize;
this.array[ index + 0 ] = x;
this.array[ index + 1 ] = y;
this.array[ index + 2 ] = z;
this.array[ index + 3 ] = w;
return this;
},
onUpload: function ( callback ) {
this.onUploadCallback = callback;
return this;
},
clone: function () {
return new this.constructor( this.array, this.itemSize ).copy( this );
}
} );
//
function Int8BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
}
Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
function Uint8BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
}
Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
}
Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
function Int16BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
}
Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
function Uint16BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
}
Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
function Int32BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
}
Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
function Uint32BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
}
Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
function Float32BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
}
Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
function Float64BufferAttribute( array, itemSize, normalized ) {
BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
}
Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
/**
* @author mrdoob / http://mrdoob.com/
*/
function DirectGeometry() {
this.indices = [];
this.vertices = [];
this.normals = [];
this.colors = [];
this.uvs = [];
this.uvs2 = [];
this.groups = [];
this.morphTargets = {};
this.skinWeights = [];
this.skinIndices = [];
// this.lineDistances = [];
this.boundingBox = null;
this.boundingSphere = null;
// update flags
this.verticesNeedUpdate = false;
this.normalsNeedUpdate = false;
this.colorsNeedUpdate = false;
this.uvsNeedUpdate = false;
this.groupsNeedUpdate = false;
}
Object.assign( DirectGeometry.prototype, {
computeGroups: function ( geometry ) {
var group;
var groups = [];
var materialIndex = undefined;
var faces = geometry.faces;
for ( var i = 0; i < faces.length; i ++ ) {
var face = faces[ i ];
// materials
if ( face.materialIndex !== materialIndex ) {
materialIndex = face.materialIndex;
if ( group !== undefined ) {
group.count = ( i * 3 ) - group.start;
groups.push( group );
}
group = {
start: i * 3,
materialIndex: materialIndex
};
}
}
if ( group !== undefined ) {
group.count = ( i * 3 ) - group.start;
groups.push( group );
}
this.groups = groups;
},
fromGeometry: function ( geometry ) {
var this$1 = this;
var faces = geometry.faces;
var vertices = geometry.vertices;
var faceVertexUvs = geometry.faceVertexUvs;
var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
// morphs
var morphTargets = geometry.morphTargets;
var morphTargetsLength = morphTargets.length;
var morphTargetsPosition;
if ( morphTargetsLength > 0 ) {
morphTargetsPosition = [];
for ( var i = 0; i < morphTargetsLength; i ++ ) {
morphTargetsPosition[ i ] = [];
}
this.morphTargets.position = morphTargetsPosition;
}
var morphNormals = geometry.morphNormals;
var morphNormalsLength = morphNormals.length;
var morphTargetsNormal;
if ( morphNormalsLength > 0 ) {
morphTargetsNormal = [];
for ( var i = 0; i < morphNormalsLength; i ++ ) {
morphTargetsNormal[ i ] = [];
}
this.morphTargets.normal = morphTargetsNormal;
}
// skins
var skinIndices = geometry.skinIndices;
var skinWeights = geometry.skinWeights;
var hasSkinIndices = skinIndices.length === vertices.length;
var hasSkinWeights = skinWeights.length === vertices.length;
//
for ( var i = 0; i < faces.length; i ++ ) {
var face = faces[ i ];
this$1.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
var vertexNormals = face.vertexNormals;
if ( vertexNormals.length === 3 ) {
this$1.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
} else {
var normal = face.normal;
this$1.normals.push( normal, normal, normal );
}
var vertexColors = face.vertexColors;
if ( vertexColors.length === 3 ) {
this$1.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
} else {
var color = face.color;
this$1.colors.push( color, color, color );
}
if ( hasFaceVertexUv === true ) {
var vertexUvs = faceVertexUvs[ 0 ][ i ];
if ( vertexUvs !== undefined ) {
this$1.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
} else {
console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
this$1.uvs.push( new Vector2(), new Vector2(), new Vector2() );
}
}
if ( hasFaceVertexUv2 === true ) {
var vertexUvs = faceVertexUvs[ 1 ][ i ];
if ( vertexUvs !== undefined ) {
this$1.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
} else {
console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
this$1.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
}
}
// morphs
for ( var j = 0; j < morphTargetsLength; j ++ ) {
var morphTarget = morphTargets[ j ].vertices;
morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
}
for ( var j = 0; j < morphNormalsLength; j ++ ) {
var morphNormal = morphNormals[ j ].vertexNormals[ i ];
morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
}
// skins
if ( hasSkinIndices ) {
this$1.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
}
if ( hasSkinWeights ) {
this$1.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
}
}
this.computeGroups( geometry );
this.verticesNeedUpdate = geometry.verticesNeedUpdate;
this.normalsNeedUpdate = geometry.normalsNeedUpdate;
this.colorsNeedUpdate = geometry.colorsNeedUpdate;
this.uvsNeedUpdate = geometry.uvsNeedUpdate;
this.groupsNeedUpdate = geometry.groupsNeedUpdate;
return this;
}
} );
/**
* @author mrdoob / http://mrdoob.com/
*/
function arrayMax( array ) {
if ( array.length === 0 ) { return - Infinity; }
var max = array[ 0 ];
for ( var i = 1, l = array.length; i < l; ++ i ) {
if ( array[ i ] > max ) { max = array[ i ]; }
}
return max;
}
/**
* @author alteredq / http://alteredqualia.com/
* @author mrdoob / http://mrdoob.com/
*/
var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
function BufferGeometry() {
Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } );
this.uuid = _Math.generateUUID();
this.name = '';
this.type = 'BufferGeometry';
this.index = null;
this.attributes = {};
this.morphAttributes = {};
this.groups = [];
this.boundingBox = null;
this.boundingSphere = null;
this.drawRange = { start: 0, count: Infinity };
}
Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, {
isBufferGeometry: true,
getIndex: function () {
return this.index;
},
setIndex: function ( index ) {
if ( Array.isArray( index ) ) {
this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
} else {
this.index = index;
}
},
addAttribute: function ( name, attribute ) {
if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
return;
}
if ( name === 'index' ) {
console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
this.setIndex( attribute );
return;
}
this.attributes[ name ] = attribute;
return this;
},
getAttribute: function ( name ) {
return this.attributes[ name ];
},
removeAttribute: function ( name ) {
delete this.attributes[ name ];
return this;
},
addGroup: function ( start, count, materialIndex ) {
this.groups.push( {
start: start,
count: count,
materialIndex: materialIndex !== undefined ? materialIndex : 0
} );
},
clearGroups: function () {
this.groups = [];
},
setDrawRange: function ( start, count ) {
this.drawRange.start = start;
this.drawRange.count = count;
},
applyMatrix: function ( matrix ) {
var position = this.attributes.position;
if ( position !== undefined ) {
matrix.applyToBufferAttribute( position );
position.needsUpdate = true;
}
var normal = this.attributes.normal;
if ( normal !== undefined ) {
var normalMatrix = new Matrix3().getNormalMatrix( matrix );
normalMatrix.applyToBufferAttribute( normal );
normal.needsUpdate = true;
}
if ( this.boundingBox !== null ) {
this.computeBoundingBox();
}
if ( this.boundingSphere !== null ) {
this.computeBoundingSphere();
}
return this;
},
rotateX: function () {
// rotate geometry around world x-axis
var m1 = new Matrix4();
return function rotateX( angle ) {
m1.makeRotationX( angle );
this.applyMatrix( m1 );
return this;
};
}(),
rotateY: function () {
// rotate geometry around world y-axis
var m1 = new Matrix4();
return function rotateY( angle ) {
m1.makeRotationY( angle );
this.applyMatrix( m1 );
return this;
};
}(),
rotateZ: function () {
// rotate geometry around world z-axis
var m1 = new Matrix4();
return function rotateZ( angle ) {
m1.makeRotationZ( angle );
this.applyMatrix( m1 );
return this;
};
}(),
translate: function () {
// translate geometry
var m1 = new Matrix4();
return function translate( x, y, z ) {
m1.makeTranslation( x, y, z );
this.applyMatrix( m1 );
return this;
};
}(),
scale: function () {
// scale geometry
var m1 = new Matrix4();
return function scale( x, y, z ) {
m1.makeScale( x, y, z );
this.applyMatrix( m1 );
return this;
};
}(),
lookAt: function () {
var obj = new Object3D();
return function lookAt( vector ) {
obj.lookAt( vector );
obj.updateMatrix();
this.applyMatrix( obj.matrix );
};
}(),
center: function () {
this.computeBoundingBox();
var offset = this.boundingBox.getCenter().negate();
this.translate( offset.x, offset.y, offset.z );
return offset;
},
setFromObject: function ( object ) {
// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
var geometry = object.geometry;
if ( object.isPoints || object.isLine ) {
var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
}
if ( geometry.boundingSphere !== null ) {
this.boundingSphere = geometry.boundingSphere.clone();
}
if ( geometry.boundingBox !== null ) {
this.boundingBox = geometry.boundingBox.clone();
}
} else if ( object.isMesh ) {
if ( geometry && geometry.isGeometry ) {
this.fromGeometry( geometry );
}
}
return this;
},
setFromPoints: function ( points ) {
var position = [];
for ( var i = 0, l = points.length; i < l; i ++ ) {
var point = points[ i ];
position.push( point.x, point.y, point.z || 0 );
}
this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
return this;
},
updateFromObject: function ( object ) {
var geometry = object.geometry;
if ( object.isMesh ) {
var direct = geometry.__directGeometry;
if ( geometry.elementsNeedUpdate === true ) {
direct = undefined;
geometry.elementsNeedUpdate = false;
}
if ( direct === undefined ) {
return this.fromGeometry( geometry );
}
direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
geometry.verticesNeedUpdate = false;
geometry.normalsNeedUpdate = false;
geometry.colorsNeedUpdate = false;
geometry.uvsNeedUpdate = false;
geometry.groupsNeedUpdate = false;
geometry = direct;
}
var attribute;
if ( geometry.verticesNeedUpdate === true ) {
attribute = this.attributes.position;
if ( attribute !== undefined ) {
attribute.copyVector3sArray( geometry.vertices );
attribute.needsUpdate = true;
}
geometry.verticesNeedUpdate = false;
}
if ( geometry.normalsNeedUpdate === true ) {
attribute = this.attributes.normal;
if ( attribute !== undefined ) {
attribute.copyVector3sArray( geometry.normals );
attribute.needsUpdate = true;
}
geometry.normalsNeedUpdate = false;
}
if ( geometry.colorsNeedUpdate === true ) {
attribute = this.attributes.color;
if ( attribute !== undefined ) {
attribute.copyColorsArray( geometry.colors );
attribute.needsUpdate = true;
}
geometry.colorsNeedUpdate = false;
}
if ( geometry.uvsNeedUpdate ) {
attribute = this.attributes.uv;
if ( attribute !== undefined ) {
attribute.copyVector2sArray( geometry.uvs );
attribute.needsUpdate = true;
}
geometry.uvsNeedUpdate = false;
}
if ( geometry.lineDistancesNeedUpdate ) {
attribute = this.attributes.lineDistance;
if ( attribute !== undefined ) {
attribute.copyArray( geometry.lineDistances );
attribute.needsUpdate = true;
}
geometry.lineDistancesNeedUpdate = false;
}
if ( geometry.groupsNeedUpdate ) {
geometry.computeGroups( object.geometry );
this.groups = geometry.groups;
geometry.groupsNeedUpdate = false;
}
return this;
},
fromGeometry: function ( geometry ) {
geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
return this.fromDirectGeometry( geometry.__directGeometry );
},
fromDirectGeometry: function ( geometry ) {
var this$1 = this;
var positions = new Float32Array( geometry.vertices.length * 3 );
this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
if ( geometry.normals.length > 0 ) {
var normals = new Float32Array( geometry.normals.length * 3 );
this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
}
if ( geometry.colors.length > 0 ) {
var colors = new Float32Array( geometry.colors.length * 3 );
this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
}
if ( geometry.uvs.length > 0 ) {
var uvs = new Float32Array( geometry.uvs.length * 2 );
this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
}
if ( geometry.uvs2.length > 0 ) {
var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
}
if ( geometry.indices.length > 0 ) {
var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array;
var indices = new TypeArray( geometry.indices.length * 3 );
this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) );
}
// groups
this.groups = geometry.groups;
// morphs
for ( var name in geometry.morphTargets ) {
var array = [];
var morphTargets = geometry.morphTargets[ name ];
for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
var morphTarget = morphTargets[ i ];
var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 );
array.push( attribute.copyVector3sArray( morphTarget ) );
}
this$1.morphAttributes[ name ] = array;
}
// skinning
if ( geometry.skinIndices.length > 0 ) {
var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
}
if ( geometry.skinWeights.length > 0 ) {
var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
}
//
if ( geometry.boundingSphere !== null ) {
this.boundingSphere = geometry.boundingSphere.clone();
}
if ( geometry.boundingBox !== null ) {
this.boundingBox = geometry.boundingBox.clone();
}
return this;
},
computeBoundingBox: function () {
if ( this.boundingBox === null ) {
this.boundingBox = new Box3();
}
var position = this.attributes.position;
if ( position !== undefined ) {
this.boundingBox.setFromBufferAttribute( position );
} else {
this.boundingBox.makeEmpty();
}
if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
}
},
computeBoundingSphere: function () {
var box = new Box3();
var vector = new Vector3();
return function computeBoundingSphere() {
if ( this.boundingSphere === null ) {
this.boundingSphere = new Sphere();
}
var position = this.attributes.position;
if ( position ) {
var center = this.boundingSphere.center;
box.setFromBufferAttribute( position );
box.getCenter( center );
// hoping to find a boundingSphere with a radius smaller than the
// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
var maxRadiusSq = 0;
for ( var i = 0, il = position.count; i < il; i ++ ) {
vector.x = position.getX( i );
vector.y = position.getY( i );
vector.z = position.getZ( i );
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
}
this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
if ( isNaN( this.boundingSphere.radius ) ) {
console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
}
}
};
}(),
computeFaceNormals: function () {
// backwards compatibility
},
computeVertexNormals: function () {
var index = this.index;
var attributes = this.attributes;
var groups = this.groups;
if ( attributes.position ) {
var positions = attributes.position.array;
if ( attributes.normal === undefined ) {
this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
} else {
// reset existing normals to zero
var array = attributes.normal.array;
for ( var i = 0, il = array.length; i < il; i ++ ) {
array[ i ] = 0;
}
}
var normals = attributes.normal.array;
var vA, vB, vC;
var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
var cb = new Vector3(), ab = new Vector3();
// indexed elements
if ( index ) {
var indices = index.array;
if ( groups.length === 0 ) {
this.addGroup( 0, indices.length );
}
for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
var group = groups[ j ];
var start = group.start;
var count = group.count;
for ( var i = start, il = start + count; i < il; i += 3 ) {
vA = indices[ i + 0 ] * 3;
vB = indices[ i + 1 ] * 3;
vC = indices[ i + 2 ] * 3;
pA.fromArray( positions, vA );
pB.fromArray( positions, vB );
pC.fromArray( positions, vC );
cb.subVectors( pC, pB );
ab.subVectors( pA, pB );
cb.cross( ab );
normals[ vA ] += cb.x;
normals[ vA + 1 ] += cb.y;
normals[ vA + 2 ] += cb.z;
normals[ vB ] += cb.x;
normals[ vB + 1 ] += cb.y;
normals[ vB + 2 ] += cb.z;
normals[ vC ] += cb.x;
normals[ vC + 1 ] += cb.y;
normals[ vC + 2 ] += cb.z;
}
}
} else {
// non-indexed elements (unconnected triangle soup)
for ( var i = 0, il = positions.length; i < il; i += 9 ) {
pA.fromArray( positions, i );
pB.fromArray( positions, i + 3 );
pC.fromArray( positions, i + 6 );
cb.subVectors( pC, pB );
ab.subVectors( pA, pB );
cb.cross( ab );
normals[ i ] = cb.x;
normals[ i + 1 ] = cb.y;
normals[ i + 2 ] = cb.z;
normals[ i + 3 ] = cb.x;
normals[ i + 4 ] = cb.y;
normals[ i + 5 ] = cb.z;
normals[ i + 6 ] = cb.x;
normals[ i + 7 ] = cb.y;
normals[ i + 8 ] = cb.z;
}
}
this.normalizeNormals();
attributes.normal.needsUpdate = true;
}
},
merge: function ( geometry, offset ) {
if ( ! ( geometry && geometry.isBufferGeometry ) ) {
console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
return;
}
if ( offset === undefined ) { offset = 0; }
var attributes = this.attributes;
for ( var key in attributes ) {
if ( geometry.attributes[ key ] === undefined ) { continue; }
var attribute1 = attributes[ key ];
var attributeArray1 = attribute1.array;
var attribute2 = geometry.attributes[ key ];
var attributeArray2 = attribute2.array;
var attributeSize = attribute2.itemSize;
for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
attributeArray1[ j ] = attributeArray2[ i ];
}
}
return this;
},
normalizeNormals: function () {
var vector = new Vector3();
return function normalizeNormals() {
var normals = this.attributes.normal;
for ( var i = 0, il = normals.count; i < il; i ++ ) {
vector.x = normals.getX( i );
vector.y = normals.getY( i );
vector.z = normals.getZ( i );
vector.normalize();
normals.setXYZ( i, vector.x, vector.y, vector.z );
}
};
}(),
toNonIndexed: function () {
if ( this.index === null ) {
console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
return this;
}
var geometry2 = new BufferGeometry();
var indices = this.index.array;
var attributes = this.attributes;
for ( var name in attributes ) {
var attribute = attributes[ name ];
var array = attribute.array;
var itemSize = attribute.itemSize;
var array2 = new array.constructor( indices.length * itemSize );
var index = 0, index2 = 0;
for ( var i = 0, l = indices.length; i < l; i ++ ) {
index = indices[ i ] * itemSize;
for ( var j = 0; j < itemSize; j ++ ) {
array2[ index2 ++ ] = array[ index ++ ];
}
}
geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) );
}
return geometry2;
},
toJSON: function () {
var data = {
metadata: {
version: 4.5,
type: 'BufferGeometry',
generator: 'BufferGeometry.toJSON'
}
};
// standard BufferGeometry serialization
data.uuid = this.uuid;
data.type = this.type;
if ( this.name !== '' ) { data.name = this.name; }
if ( this.parameters !== undefined ) {
var parameters = this.parameters;
for ( var key in parameters ) {
if ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; }
}
return data;
}
data.data = { attributes: {} };
var index = this.index;
if ( index !== null ) {
var array = Array.prototype.slice.call( index.array );
data.data.index = {
type: index.array.constructor.name,
array: array
};
}
var attributes = this.attributes;
for ( var key in attributes ) {
var attribute = attributes[ key ];
var array = Array.prototype.slice.call( attribute.array );
data.data.attributes[ key ] = {
itemSize: attribute.itemSize,
type: attribute.array.constructor.name,
array: array,
normalized: attribute.normalized
};
}
var groups = this.groups;
if ( groups.length > 0 ) {
data.data.groups = JSON.parse( JSON.stringify( groups ) );
}
var boundingSphere = this.boundingSphere;
if ( boundingSphere !== null ) {
data.data.boundingSphere = {
center: boundingSphere.center.toArray(),
radius: boundingSphere.radius
};
}
return data;
},
clone: function () {
/*
// Handle primitives
var parameters = this.parameters;
if ( parameters !== undefined ) {
var values = [];
for ( var key in parameters ) {
values.push( parameters[ key ] );
}
var geometry = Object.create( this.constructor.prototype );
this.constructor.apply( geometry, values );
return geometry;
}
return new this.constructor().copy( this );
*/
return new BufferGeometry().copy( this );
},
copy: function ( source ) {
var this$1 = this;
var name, i, l;
// reset
this.index = null;
this.attributes = {};
this.morphAttributes = {};
this.groups = [];
this.boundingBox = null;
this.boundingSphere = null;
// name
this.name = source.name;
// index
var index = source.index;
if ( index !== null ) {
this.setIndex( index.clone() );
}
// attributes
var attributes = source.attributes;
for ( name in attributes ) {
var attribute = attributes[ name ];
this$1.addAttribute( name, attribute.clone() );
}
// morph attributes
var morphAttributes = source.morphAttributes;
for ( name in morphAttributes ) {
var array = [];
var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
array.push( morphAttribute[ i ].clone() );
}
this$1.morphAttributes[ name ] = array;
}
// groups
var groups = source.groups;
for ( i = 0, l = groups.length; i < l; i ++ ) {
var group = groups[ i ];
this$1.addGroup( group.start, group.count, group.materialIndex );
}
// bounding box
var boundingBox = source.boundingBox;
if ( boundingBox !== null ) {
this.boundingBox = boundingBox.clone();
}
// bounding sphere
var boundingSphere = source.boundingSphere;
if ( boundingSphere !== null ) {
this.boundingSphere = boundingSphere.clone();
}
// draw range
this.drawRange.start = source.drawRange.start;
this.drawRange.count = source.drawRange.count;
return this;
},
dispose: function () {
this.dispatchEvent( { type: 'dispose' } );
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author Mugen87 / https://github.com/Mugen87
*/
// BoxGeometry
function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
Geometry.call( this );
this.type = 'BoxGeometry';
this.parameters = {
width: width,
height: height,
depth: depth,
widthSegments: widthSegments,
heightSegments: heightSegments,
depthSegments: depthSegments
};
this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
this.mergeVertices();
}
BoxGeometry.prototype = Object.create( Geometry.prototype );
BoxGeometry.prototype.constructor = BoxGeometry;
// BoxBufferGeometry
function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
BufferGeometry.call( this );
this.type = 'BoxBufferGeometry';
this.parameters = {
width: width,
height: height,
depth: depth,
widthSegments: widthSegments,
heightSegments: heightSegments,
depthSegments: depthSegments
};
var scope = this;
width = width || 1;
height = height || 1;
depth = depth || 1;
// segments
widthSegments = Math.floor( widthSegments ) || 1;
heightSegments = Math.floor( heightSegments ) || 1;
depthSegments = Math.floor( depthSegments ) || 1;
// buffers
var indices = [];
var vertices = [];
var normals = [];
var uvs = [];
// helper variables
var numberOfVertices = 0;
var groupStart = 0;
// build each side of the box geometry
buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
// build geometry
this.setIndex( indices );
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
var segmentWidth = width / gridX;
var segmentHeight = height / gridY;
var widthHalf = width / 2;
var heightHalf = height / 2;
var depthHalf = depth / 2;
var gridX1 = gridX + 1;
var gridY1 = gridY + 1;
var vertexCounter = 0;
var groupCount = 0;
var ix, iy;
var vector = new Vector3();
// generate vertices, normals and uvs
for ( iy = 0; iy < gridY1; iy ++ ) {
var y = iy * segmentHeight - heightHalf;
for ( ix = 0; ix < gridX1; ix ++ ) {
var x = ix * segmentWidth - widthHalf;
// set values to correct vector component
vector[ u ] = x * udir;
vector[ v ] = y * vdir;
vector[ w ] = depthHalf;
// now apply vector to vertex buffer
vertices.push( vector.x, vector.y, vector.z );
// set values to correct vector component
vector[ u ] = 0;
vector[ v ] = 0;
vector[ w ] = depth > 0 ? 1 : - 1;
// now apply vector to normal buffer
normals.push( vector.x, vector.y, vector.z );
// uvs
uvs.push( ix / gridX );
uvs.push( 1 - ( iy / gridY ) );
// counters
vertexCounter += 1;
}
}
// indices
// 1. you need three indices to draw a single face
// 2. a single segment consists of two faces
// 3. so we need to generate six (2*3) indices per segment
for ( iy = 0; iy < gridY; iy ++ ) {
for ( ix = 0; ix < gridX; ix ++ ) {
var a = numberOfVertices + ix + gridX1 * iy;
var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
// faces
indices.push( a, b, d );
indices.push( b, c, d );
// increase counter
groupCount += 6;
}
}
// add a group to the geometry. this will ensure multi material support
scope.addGroup( groupStart, groupCount, materialIndex );
// calculate new start value for groups
groupStart += groupCount;
// update total number of vertices
numberOfVertices += vertexCounter;
}
}
BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
/**
* @author mrdoob / http://mrdoob.com/
* @author Mugen87 / https://github.com/Mugen87
*/
// PlaneGeometry
function PlaneGeometry( width, height, widthSegments, heightSegments ) {
Geometry.call( this );
this.type = 'PlaneGeometry';
this.parameters = {
width: width,
height: height,
widthSegments: widthSegments,
heightSegments: heightSegments
};
this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
this.mergeVertices();
}
PlaneGeometry.prototype = Object.create( Geometry.prototype );
PlaneGeometry.prototype.constructor = PlaneGeometry;
// PlaneBufferGeometry
function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
BufferGeometry.call( this );
this.type = 'PlaneBufferGeometry';
this.parameters = {
width: width,
height: height,
widthSegments: widthSegments,
heightSegments: heightSegments
};
width = width || 1;
height = height || 1;
var width_half = width / 2;
var height_half = height / 2;
var gridX = Math.floor( widthSegments ) || 1;
var gridY = Math.floor( heightSegments ) || 1;
var gridX1 = gridX + 1;
var gridY1 = gridY + 1;
var segment_width = width / gridX;
var segment_height = height / gridY;
var ix, iy;
// buffers
var indices = [];
var vertices = [];
var normals = [];
var uvs = [];
// generate vertices, normals and uvs
for ( iy = 0; iy < gridY1; iy ++ ) {
var y = iy * segment_height - height_half;
for ( ix = 0; ix < gridX1; ix ++ ) {
var x = ix * segment_width - width_half;
vertices.push( x, - y, 0 );
normals.push( 0, 0, 1 );
uvs.push( ix / gridX );
uvs.push( 1 - ( iy / gridY ) );
}
}
// indices
for ( iy = 0; iy < gridY; iy ++ ) {
for ( ix = 0; ix < gridX; ix ++ ) {
var a = ix + gridX1 * iy;
var b = ix + gridX1 * ( iy + 1 );
var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
var d = ( ix + 1 ) + gridX1 * iy;
// faces
indices.push( a, b, d );
indices.push( b, c, d );
}
}
// build geometry
this.setIndex( indices );
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
}
PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
*
* parameters = {
* color: <hex>,
* opacity: <float>,
* map: new THREE.Texture( <Image> ),
*
* lightMap: new THREE.Texture( <Image> ),
* lightMapIntensity: <float>
*
* aoMap: new THREE.Texture( <Image> ),
* aoMapIntensity: <float>
*
* specularMap: new THREE.Texture( <Image> ),
*
* alphaMap: new THREE.Texture( <Image> ),
*
* envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
* combine: THREE.Multiply,
* reflectivity: <float>,
* refractionRatio: <float>,
*
* depthTest: <bool>,
* depthWrite: <bool>,
*
* wireframe: <boolean>,
* wireframeLinewidth: <float>,
*
* skinning: <bool>,
* morphTargets: <bool>
* }
*/
function MeshBasicMaterial( parameters ) {
Material.call( this );
this.type = 'MeshBasicMaterial';
this.color = new Color( 0xffffff ); // emissive
this.map = null;
this.lightMap = null;
this.lightMapIntensity = 1.0;
this.aoMap = null;
this.aoMapIntensity = 1.0;
this.specularMap = null;
this.alphaMap = null;
this.envMap = null;
this.combine = MultiplyOperation;
this.reflectivity = 1;
this.refractionRatio = 0.98;
this.wireframe = false;
this.wireframeLinewidth = 1;
this.wireframeLinecap = 'round';
this.wireframeLinejoin = 'round';
this.skinning = false;
this.morphTargets = false;
this.lights = false;
this.setValues( parameters );
}
MeshBasicMaterial.prototype = Object.create( Material.prototype );
MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
MeshBasicMaterial.prototype.copy = function ( source ) {
Material.prototype.copy.call( this, source );
this.color.copy( source.color );
this.map = source.map;
this.lightMap = source.lightMap;
this.lightMapIntensity = source.lightMapIntensity;
this.aoMap = source.aoMap;
this.aoMapIntensity = source.aoMapIntensity;
this.specularMap = source.specularMap;
this.alphaMap = source.alphaMap;
this.envMap = source.envMap;
this.combine = source.combine;
this.reflectivity = source.reflectivity;
this.refractionRatio = source.refractionRatio;
this.wireframe = source.wireframe;
this.wireframeLinewidth = source.wireframeLinewidth;
this.wireframeLinecap = source.wireframeLinecap;
this.wireframeLinejoin = source.wireframeLinejoin;
this.skinning = source.skinning;
this.morphTargets = source.morphTargets;
return this;
};
/**
* @author alteredq / http://alteredqualia.com/
*
* parameters = {
* defines: { "label" : "value" },
* uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
*
* fragmentShader: <string>,
* vertexShader: <string>,
*
* wireframe: <boolean>,
* wireframeLinewidth: <float>,
*
* lights: <bool>,
*
* skinning: <bool>,
* morphTargets: <bool>,
* morphNormals: <bool>
* }
*/
function ShaderMaterial( parameters ) {
Material.call( this );
this.type = 'ShaderMaterial';
this.defines = {};
this.uniforms = {};
this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
this.linewidth = 1;
this.wireframe = false;
this.wireframeLinewidth = 1;
this.fog = false; // set to use scene fog
this.lights = false; // set to use scene lights
this.clipping = false; // set to use user-defined clipping planes
this.skinning = false; // set to use skinning attribute streams
this.morphTargets = false; // set to use morph targets
this.morphNormals = false; // set to use morph normals
this.extensions = {
derivatives: false, // set to use derivatives
fragDepth: false, // set to use fragment depth values
drawBuffers: false, // set to use draw buffers
shaderTextureLOD: false // set to use shader texture LOD
};
// When rendered geometry doesn't include these attributes but the material does,
// use these default values in WebGL. This avoids errors when buffer data is missing.
this.defaultAttributeValues = {
'color': [ 1, 1, 1 ],
'uv': [ 0, 0 ],
'uv2': [ 0, 0 ]
};
this.index0AttributeName = undefined;
if ( parameters !== undefined ) {
if ( parameters.attributes !== undefined ) {
console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
}
this.setValues( parameters );
}
}
ShaderMaterial.prototype = Object.create( Material.prototype );
ShaderMaterial.prototype.constructor = ShaderMaterial;
ShaderMaterial.prototype.isShaderMaterial = true;
ShaderMaterial.prototype.copy = function ( source ) {
Material.prototype.copy.call( this, source );
this.fragmentShader = source.fragmentShader;
this.vertexShader = source.vertexShader;
this.uniforms = UniformsUtils.clone( source.uniforms );
this.defines = source.defines;
this.wireframe = source.wireframe;
this.wireframeLinewidth = source.wireframeLinewidth;
this.lights = source.lights;
this.clipping = source.clipping;
this.skinning = source.skinning;
this.morphTargets = source.morphTargets;
this.morphNormals = source.morphNormals;
this.extensions = source.extensions;
return this;
};
ShaderMaterial.prototype.toJSON = function ( meta ) {
var data = Material.prototype.toJSON.call( this, meta );
data.uniforms = this.uniforms;
data.vertexShader = this.vertexShader;
data.fragmentShader = this.fragmentShader;
return data;
};
/**
* @author bhouston / http://clara.io
*/
function Ray( origin, direction ) {
this.origin = ( origin !== undefined ) ? origin : new Vector3();
this.direction = ( direction !== undefined ) ? direction : new Vector3();
}
Object.assign( Ray.prototype, {
set: function ( origin, direction ) {
this.origin.copy( origin );
this.direction.copy( direction );
return this;
},
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( ray ) {
this.origin.copy( ray.origin );
this.direction.copy( ray.direction );
return this;
},
at: function ( t, optionalTarget ) {
var result = optionalTarget || new Vector3();
return result.copy( this.direction ).multiplyScalar( t ).add( this.origin );
},
lookAt: function ( v ) {
this.direction.copy( v ).sub( this.origin ).normalize();
return this;
},
recast: function () {
var v1 = new Vector3();
return function recast( t ) {
this.origin.copy( this.at( t, v1 ) );
return this;
};
}(),
closestPointToPoint: function ( point, optionalTarget ) {
var result = optionalTarget || new Vector3();
result.subVectors( point, this.origin );
var directionDistance = result.dot( this.direction );
if ( directionDistance < 0 ) {
return result.copy( this.origin );
}
return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
},
distanceToPoint: function ( point ) {
return Math.sqrt( this.distanceSqToPoint( point ) );
},
distanceSqToPoint: function () {
var v1 = new Vector3();
return function distanceSqToPoint( point ) {
var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
// point behind the ray
if ( directionDistance < 0 ) {
return this.origin.distanceToSquared( point );
}
v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
return v1.distanceToSquared( point );
};
}(),
distanceSqToSegment: function () {
var segCenter = new Vector3();
var segDir = new Vector3();
var diff = new Vector3();
return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
// It returns the min distance between the ray and the segment
// defined by v0 and v1
// It can also set two optional targets :
// - The closest point on the ray
// - The closest point on the segment
segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
segDir.copy( v1 ).sub( v0 ).normalize();
diff.copy( this.origin ).sub( segCenter );
var segExtent = v0.distanceTo( v1 ) * 0.5;
var a01 = - this.direction.dot( segDir );
var b0 = diff.dot( this.direction );
var b1 = - diff.dot( segDir );
var c = diff.lengthSq();
var det = Math.abs( 1 - a01 * a01 );
var s0, s1, sqrDist, extDet;
if ( det > 0 ) {
// The ray and segment are not parallel.
s0 = a01 * b1 - b0;
s1 = a01 * b0 - b1;
extDet = segExtent * det;
if ( s0 >= 0 ) {
if ( s1 >= - extDet ) {
if ( s1 <= extDet ) {
// region 0
// Minimum at interior points of ray and segment.
var invDet = 1 / det;
s0 *= invDet;
s1 *= invDet;
sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
} else {
// region 1
s1 = segExtent;
s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
}
} else {
// region 5
s1 = - segExtent;
s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
}
} else {
if ( s1 <= - extDet ) {
// region 4
s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
} else if ( s1 <= extDet ) {
// region 3
s0 = 0;
s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
sqrDist = s1 * ( s1 + 2 * b1 ) + c;
} else {
// region 2
s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
}
}
} else {
// Ray and segment are parallel.
s1 = ( a01 > 0 ) ? - segExtent : segExtent;
s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
}
if ( optionalPointOnRay ) {
optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
}
if ( optionalPointOnSegment ) {
optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
}
return sqrDist;
};
}(),
intersectSphere: function () {
var v1 = new Vector3();
return function intersectSphere( sphere, optionalTarget ) {
v1.subVectors( sphere.center, this.origin );
var tca = v1.dot( this.direction );
var d2 = v1.dot( v1 ) - tca * tca;
var radius2 = sphere.radius * sphere.radius;
if ( d2 > radius2 ) { return null; }
var thc = Math.sqrt( radius2 - d2 );
// t0 = first intersect point - entrance on front of sphere
var t0 = tca - thc;
// t1 = second intersect point - exit point on back of sphere
var t1 = tca + thc;
// test to see if both t0 and t1 are behind the ray - if so, return null
if ( t0 < 0 && t1 < 0 ) { return null; }
// test to see if t0 is behind the ray:
// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
// in order to always return an intersect point that is in front of the ray.
if ( t0 < 0 ) { return this.at( t1, optionalTarget ); }
// else t0 is in front of the ray, so return the first collision point scaled by t0
return this.at( t0, optionalTarget );
};
}(),
intersectsSphere: function ( sphere ) {
return this.distanceToPoint( sphere.center ) <= sphere.radius;
},
distanceToPlane: function ( plane ) {
var denominator = plane.normal.dot( this.direction );
if ( denominator === 0 ) {
// line is coplanar, return origin
if ( plane.distanceToPoint( this.origin ) === 0 ) {
return 0;
}
// Null is preferable to undefined since undefined means.... it is undefined
return null;
}
var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
// Return if the ray never intersects the plane
return t >= 0 ? t : null;
},
intersectPlane: function ( plane, optionalTarget ) {
var t = this.distanceToPlane( plane );
if ( t === null ) {
return null;
}
return this.at( t, optionalTarget );
},
intersectsPlane: function ( plane ) {
// check if the ray lies on the plane first
var distToPoint = plane.distanceToPoint( this.origin );
if ( distToPoint === 0 ) {
return true;
}
var denominator = plane.normal.dot( this.direction );
if ( denominator * distToPoint < 0 ) {
return true;
}
// ray origin is behind the plane (and is pointing behind it)
return false;
},
intersectBox: function ( box, optionalTarget ) {
var tmin, tmax, tymin, tymax, tzmin, tzmax;
var invdirx = 1 / this.direction.x,
invdiry = 1 / this.direction.y,
invdirz = 1 / this.direction.z;
var origin = this.origin;
if ( invdirx >= 0 ) {
tmin = ( box.min.x - origin.x ) * invdirx;
tmax = ( box.max.x - origin.x ) * invdirx;
} else {
tmin = ( box.max.x - origin.x ) * invdirx;
tmax = ( box.min.x - origin.x ) * invdirx;
}
if ( invdiry >= 0 ) {
tymin = ( box.min.y - origin.y ) * invdiry;
tymax = ( box.max.y - origin.y ) * invdiry;
} else {
tymin = ( box.max.y - origin.y ) * invdiry;
tymax = ( box.min.y - origin.y ) * invdiry;
}
if ( ( tmin > tymax ) || ( tymin > tmax ) ) { return null; }
// These lines also handle the case where tmin or tmax is NaN
// (result of 0 * Infinity). x !== x returns true if x is NaN
if ( tymin > tmin || tmin !== tmin ) { tmin = tymin; }
if ( tymax < tmax || tmax !== tmax ) { tmax = tymax; }
if ( invdirz >= 0 ) {
tzmin = ( box.min.z - origin.z ) * invdirz;
tzmax = ( box.max.z - origin.z ) * invdirz;
} else {
tzmin = ( box.max.z - origin.z ) * invdirz;
tzmax = ( box.min.z - origin.z ) * invdirz;
}
if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) { return null; }
if ( tzmin > tmin || tmin !== tmin ) { tmin = tzmin; }
if ( tzmax < tmax || tmax !== tmax ) { tmax = tzmax; }
//return point closest to the ray (positive side)
if ( tmax < 0 ) { return null; }
return this.at( tmin >= 0 ? tmin : tmax, optionalTarget );
},
intersectsBox: ( function () {
var v = new Vector3();
return function intersectsBox( box ) {
return this.intersectBox( box, v ) !== null;
};
} )(),
intersectTriangle: function () {
// Compute the offset origin, edges, and normal.
var diff = new Vector3();
var edge1 = new Vector3();
var edge2 = new Vector3();
var normal = new Vector3();
return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) {
// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
edge1.subVectors( b, a );
edge2.subVectors( c, a );
normal.crossVectors( edge1, edge2 );
// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
// |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
// |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
// |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
var DdN = this.direction.dot( normal );
var sign;
if ( DdN > 0 ) {
if ( backfaceCulling ) { return null; }
sign = 1;
} else if ( DdN < 0 ) {
sign = - 1;
DdN = - DdN;
} else {
return null;
}
diff.subVectors( this.origin, a );
var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
// b1 < 0, no intersection
if ( DdQxE2 < 0 ) {
return null;
}
var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
// b2 < 0, no intersection
if ( DdE1xQ < 0 ) {
return null;
}
// b1+b2 > 1, no intersection
if ( DdQxE2 + DdE1xQ > DdN ) {
return null;
}
// Line intersects triangle, check if ray does.
var QdN = - sign * diff.dot( normal );
// t < 0, no intersection
if ( QdN < 0 ) {
return null;
}
// Ray intersects triangle.
return this.at( QdN / DdN, optionalTarget );
};
}(),
applyMatrix4: function ( matrix4 ) {
this.origin.applyMatrix4( matrix4 );
this.direction.transformDirection( matrix4 );
return this;
},
equals: function ( ray ) {
return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
}
} );
/**
* @author bhouston / http://clara.io
*/
function Line3( start, end ) {
this.start = ( start !== undefined ) ? start : new Vector3();
this.end = ( end !== undefined ) ? end : new Vector3();
}
Object.assign( Line3.prototype, {
set: function ( start, end ) {
this.start.copy( start );
this.end.copy( end );
return this;
},
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( line ) {
this.start.copy( line.start );
this.end.copy( line.end );
return this;
},
getCenter: function ( optionalTarget ) {
var result = optionalTarget || new Vector3();
return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
},
delta: function ( optionalTarget ) {
var result = optionalTarget || new Vector3();
return result.subVectors( this.end, this.start );
},
distanceSq: function () {
return this.start.distanceToSquared( this.end );
},
distance: function () {
return this.start.distanceTo( this.end );
},
at: function ( t, optionalTarget ) {
var result = optionalTarget || new Vector3();
return this.delta( result ).multiplyScalar( t ).add( this.start );
},
closestPointToPointParameter: function () {
var startP = new Vector3();
var startEnd = new Vector3();
return function closestPointToPointParameter( point, clampToLine ) {
startP.subVectors( point, this.start );
startEnd.subVectors( this.end, this.start );
var startEnd2 = startEnd.dot( startEnd );
var startEnd_startP = startEnd.dot( startP );
var t = startEnd_startP / startEnd2;
if ( clampToLine ) {
t = _Math.clamp( t, 0, 1 );
}
return t;
};
}(),
closestPointToPoint: function ( point, clampToLine, optionalTarget ) {
var t = this.closestPointToPointParameter( point, clampToLine );
var result = optionalTarget || new Vector3();
return this.delta( result ).multiplyScalar( t ).add( this.start );
},
applyMatrix4: function ( matrix ) {
this.start.applyMatrix4( matrix );
this.end.applyMatrix4( matrix );
return this;
},
equals: function ( line ) {
return line.start.equals( this.start ) && line.end.equals( this.end );
}
} );
/**
* @author bhouston / http://clara.io
* @author mrdoob / http://mrdoob.com/
*/
function Triangle( a, b, c ) {
this.a = ( a !== undefined ) ? a : new Vector3();
this.b = ( b !== undefined ) ? b : new Vector3();
this.c = ( c !== undefined ) ? c : new Vector3();
}
Object.assign( Triangle, {
normal: function () {
var v0 = new Vector3();
return function normal( a, b, c, optionalTarget ) {
var result = optionalTarget || new Vector3();
result.subVectors( c, b );
v0.subVectors( a, b );
result.cross( v0 );
var resultLengthSq = result.lengthSq();
if ( resultLengthSq > 0 ) {
return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) );
}
return result.set( 0, 0, 0 );
};
}(),
// static/instance method to calculate barycentric coordinates
// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
barycoordFromPoint: function () {
var v0 = new Vector3();
var v1 = new Vector3();
var v2 = new Vector3();
return function barycoordFromPoint( point, a, b, c, optionalTarget ) {
v0.subVectors( c, a );
v1.subVectors( b, a );
v2.subVectors( point, a );
var dot00 = v0.dot( v0 );
var dot01 = v0.dot( v1 );
var dot02 = v0.dot( v2 );
var dot11 = v1.dot( v1 );
var dot12 = v1.dot( v2 );
var denom = ( dot00 * dot11 - dot01 * dot01 );
var result = optionalTarget || new Vector3();
// collinear or singular triangle
if ( denom === 0 ) {
// arbitrary location outside of triangle?
// not sure if this is the best idea, maybe should be returning undefined
return result.set( - 2, - 1, - 1 );
}
var invDenom = 1 / denom;
var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
// barycentric coordinates must always sum to 1
return result.set( 1 - u - v, v, u );
};
}(),
containsPoint: function () {
var v1 = new Vector3();
return function containsPoint( point, a, b, c ) {
var result = Triangle.barycoordFromPoint( point, a, b, c, v1 );
return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 );
};
}()
} );
Object.assign( Triangle.prototype, {
set: function ( a, b, c ) {
this.a.copy( a );
this.b.copy( b );
this.c.copy( c );
return this;
},
setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
this.a.copy( points[ i0 ] );
this.b.copy( points[ i1 ] );
this.c.copy( points[ i2 ] );
return this;
},
clone: function () {
return new this.constructor().copy( this );
},
copy: function ( triangle ) {
this.a.copy( triangle.a );
this.b.copy( triangle.b );
this.c.copy( triangle.c );
return this;
},
area: function () {
var v0 = new Vector3();
var v1 = new Vector3();
return function area() {
v0.subVectors( this.c, this.b );
v1.subVectors( this.a, this.b );
return v0.cross( v1 ).length() * 0.5;
};
}(),
midpoint: function ( optionalTarget ) {
var result = optionalTarget || new Vector3();
return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
},
normal: function ( optionalTarget ) {
return Triangle.normal( this.a, this.b, this.c, optionalTarget );
},
plane: function ( optionalTarget ) {
var result = optionalTarget || new Plane$2();
return result.setFromCoplanarPoints( this.a, this.b, this.c );
},
barycoordFromPoint: function ( point, optionalTarget ) {
return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget );
},
containsPoint: function ( point ) {
return Triangle.containsPoint( point, this.a, this.b, this.c );
},
closestPointToPoint: function () {
var plane = new Plane$2();
var edgeList = [ new Line3(), new Line3(), new Line3() ];
var projectedPoint = new Vector3();
var closestPoint = new Vector3();
return function closestPointToPoint( point, optionalTarget ) {
var result = optionalTarget || new Vector3();
var minDistance = Infinity;
// project the point onto the plane of the triangle
plane.setFromCoplanarPoints( this.a, this.b, this.c );
plane.projectPoint( point, projectedPoint );
// check if the projection lies within the triangle
if ( this.containsPoint( projectedPoint ) === true ) {
// if so, this is the closest point
result.copy( projectedPoint );
} else {
// if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices
edgeList[ 0 ].set( this.a, this.b );
edgeList[ 1 ].set( this.b, this.c );
edgeList[ 2 ].set( this.c, this.a );
for ( var i = 0; i < edgeList.length; i ++ ) {
edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint );
var distance = projectedPoint.distanceToSquared( closestPoint );
if ( distance < minDistance ) {
minDistance = distance;
result.copy( closestPoint );
}
}
}
return result;
};
}(),
equals: function ( triangle ) {
return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
}
} );
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
* @author mikael emtinger / http://gomo.se/
* @author jonobr1 / http://jonobr1.com/
*/
function Mesh( geometry, material ) {
Object3D.call( this );
this.type = 'Mesh';
this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
this.drawMode = TrianglesDrawMode;
this.updateMorphTargets();
}
Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Mesh,
isMesh: true,
setDrawMode: function ( value ) {
this.drawMode = value;
},
copy: function ( source ) {
Object3D.prototype.copy.call( this, source );
this.drawMode = source.drawMode;
if ( source.morphTargetInfluences !== undefined ) {
this.morphTargetInfluences = source.morphTargetInfluences.slice();
}
if ( source.morphTargetDictionary !== undefined ) {
this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
}
return this;
},
updateMorphTargets: function () {
var this$1 = this;
var geometry = this.geometry;
var m, ml, name;
if ( geometry.isBufferGeometry ) {
var morphAttributes = geometry.morphAttributes;
var keys = Object.keys( morphAttributes );
if ( keys.length > 0 ) {
var morphAttribute = morphAttributes[ keys[ 0 ] ];
if ( morphAttribute !== undefined ) {
this.morphTargetInfluences = [];
this.morphTargetDictionary = {};
for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
name = morphAttribute[ m ].name || String( m );
this$1.morphTargetInfluences.push( 0 );
this$1.morphTargetDictionary[ name ] = m;
}
}
}
} else {
var morphTargets = geometry.morphTargets;
if ( morphTargets !== undefined && morphTargets.length > 0 ) {
this.morphTargetInfluences = [];
this.morphTargetDictionary = {};
for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) {
name = morphTargets[ m ].name || String( m );
this$1.morphTargetInfluences.push( 0 );
this$1.morphTargetDictionary[ name ] = m;
}
}
}
},
raycast: ( function () {
var inverseMatrix = new Matrix4();
var ray = new Ray();
var sphere = new Sphere();
var vA = new Vector3();
var vB = new Vector3();
var vC = new Vector3();
var tempA = new Vector3();
var tempB = new Vector3();
var tempC = new Vector3();
var uvA = new Vector2();
var uvB = new Vector2();
var uvC = new Vector2();
var barycoord = new Vector3();
var intersectionPoint = new Vector3();
var intersectionPointWorld = new Vector3();
function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord );
uv1.multiplyScalar( barycoord.x );
uv2.multiplyScalar( barycoord.y );
uv3.multiplyScalar( barycoord.z );
uv1.add( uv2 ).add( uv3 );
return uv1.clone();
}
function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
var intersect;
if ( material.side === BackSide ) {
intersect = ray.intersectTriangle( pC, pB, pA, true, point );
} else {
intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
}
if ( intersect === null ) { return null; }
intersectionPointWorld.copy( point );
intersectionPointWorld.applyMatrix4( object.matrixWorld );
var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
if ( distance < raycaster.near || distance > raycaster.far ) { return null; }
return {
distance: distance,
point: intersectionPointWorld.clone(),
object: object
};
}
function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) {
vA.fromBufferAttribute( position, a );
vB.fromBufferAttribute( position, b );
vC.fromBufferAttribute( position, c );
var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint );
if ( intersection ) {
if ( uv ) {
uvA.fromBufferAttribute( uv, a );
uvB.fromBufferAttribute( uv, b );
uvC.fromBufferAttribute( uv, c );
intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC );
}
intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) );
intersection.faceIndex = a;
}
return intersection;
}
return function raycast( raycaster, intersects ) {
var this$1 = this;
var geometry = this.geometry;
var material = this.material;
var matrixWorld = this.matrixWorld;
if ( material === undefined ) { return; }
// Checking boundingSphere distance to ray
if ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }
sphere.copy( geometry.boundingSphere );
sphere.applyMatrix4( matrixWorld );
if ( raycaster.ray.intersectsSphere( sphere ) === false ) { return; }
//
inverseMatrix.getInverse( matrixWorld );
ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
// Check boundingBox before continuing
if ( geometry.boundingBox !== null ) {
if ( ray.intersectsBox( geometry.boundingBox ) === false ) { return; }
}
var intersection;
if ( geometry.isBufferGeometry ) {
var a, b, c;
var index = geometry.index;
var position = geometry.attributes.position;
var uv = geometry.attributes.uv;
var i, l;
if ( index !== null ) {
// indexed buffer geometry
for ( i = 0, l = index.count; i < l; i += 3 ) {
a = index.getX( i );
b = index.getX( i + 1 );
c = index.getX( i + 2 );
intersection = checkBufferGeometryIntersection( this$1, raycaster, ray, position, uv, a, b, c );
if ( intersection ) {
intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics
intersects.push( intersection );
}
}
} else if ( position !== undefined ) {
// non-indexed buffer geometry
for ( i = 0, l = position.count; i < l; i += 3 ) {
a = i;
b = i + 1;
c = i + 2;
intersection = checkBufferGeometryIntersection( this$1, raycaster, ray, position, uv, a, b, c );
if ( intersection ) {
intersection.index = a; // triangle number in positions buffer semantics
intersects.push( intersection );
}
}
}
} else if ( geometry.isGeometry ) {
var fvA, fvB, fvC;
var isMultiMaterial = Array.isArray( material );
var vertices = geometry.vertices;
var faces = geometry.faces;
var uvs;
var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
if ( faceVertexUvs.length > 0 ) { uvs = faceVertexUvs; }
for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
var face = faces[ f ];
var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
if ( faceMaterial === undefined ) { continue; }
fvA = vertices[ face.a ];
fvB = vertices[ face.b ];
fvC = vertices[ face.c ];
if ( faceMaterial.morphTargets === true ) {
var morphTargets = geometry.morphTargets;
var morphInfluences = this$1.morphTargetInfluences;
vA.set( 0, 0, 0 );
vB.set( 0, 0, 0 );
vC.set( 0, 0, 0 );
for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
var influence = morphInfluences[ t ];
if ( influence === 0 ) { continue; }
var targets = morphTargets[ t ].vertices;
vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
}
vA.add( fvA );
vB.add( fvB );
vC.add( fvC );
fvA = vA;
fvB = vB;
fvC = vC;
}
intersection = checkIntersection( this$1, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
if ( intersection ) {
if ( uvs && uvs[ f ] ) {
var uvs_f = uvs[ f ];
uvA.copy( uvs_f[ 0 ] );
uvB.copy( uvs_f[ 1 ] );
uvC.copy( uvs_f[ 2 ] );
intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
}
intersection.face = face;
intersection.faceIndex = f;
intersects.push( intersection );
}
}
}
};
}() ),
clone: function () {
return new this.constructor( this.geometry, this.material ).copy( this );
}
} );
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) {
var clearColor = new Color( 0x000000 );
var clearAlpha = 0;
var planeCamera, planeMesh;
var boxMesh;
function render( renderList, scene, camera, forceClear ) {
var background = scene.background;
if ( background === null ) {
setClear( clearColor, clearAlpha );
} else if ( background && background.isColor ) {
setClear( background, 1 );
forceClear = true;
}
if ( renderer.autoClear || forceClear ) {
renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
}
if ( background && background.isCubeTexture ) {
if ( boxMesh === undefined ) {
boxMesh = new Mesh(
new BoxBufferGeometry( 1, 1, 1 ),
new ShaderMaterial( {
uniforms: ShaderLib.cube.uniforms,
vertexShader: ShaderLib.cube.vertexShader,
fragmentShader: ShaderLib.cube.fragmentShader,
side: BackSide,
depthTest: true,
depthWrite: false,
fog: false
} )
);
boxMesh.geometry.removeAttribute( 'normal' );
boxMesh.geometry.removeAttribute( 'uv' );
boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
this.matrixWorld.copyPosition( camera.matrixWorld );
};
geometries.update( boxMesh.geometry );
}
boxMesh.material.uniforms.tCube.value = background;
renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null );
} else if ( background && background.isTexture ) {
if ( planeCamera === undefined ) {
planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
planeMesh = new Mesh(
new PlaneBufferGeometry( 2, 2 ),
new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } )
);
geometries.update( planeMesh.geometry );
}
planeMesh.material.map = background;
// TODO Push this to renderList
renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null );
}
}
function setClear( color, alpha ) {
state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
}
return {
getClearColor: function () {
return clearColor;
},
setClearColor: function ( color, alpha ) {
clearColor.set( color );
clearAlpha = alpha !== undefined ? alpha : 1;
setClear( clearColor, clearAlpha );
},
getClearAlpha: function () {
return clearAlpha;
},
setClearAlpha: function ( alpha ) {
clearAlpha = alpha;
setClear( clearColor, clearAlpha );
},
render: render
};
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function painterSortStable( a, b ) {
if ( a.renderOrder !== b.renderOrder ) {
return a.renderOrder - b.renderOrder;
} else if ( a.program && b.program && a.program !== b.program ) {
return a.program.id - b.program.id;
} else if ( a.material.id !== b.material.id ) {
return a.material.id - b.material.id;
} else if ( a.z !== b.z ) {
return a.z - b.z;
} else {
return a.id - b.id;
}
}
function reversePainterSortStable( a, b ) {
if ( a.renderOrder !== b.renderOrder ) {
return a.renderOrder - b.renderOrder;
} if ( a.z !== b.z ) {
return b.z - a.z;
} else {
return a.id - b.id;
}
}
function WebGLRenderList() {
var renderItems = [];
var renderItemsIndex = 0;
var opaque = [];
var transparent = [];
function init() {
renderItemsIndex = 0;
opaque.length = 0;
transparent.length = 0;
}
function push( object, geometry, material, z, group ) {
var renderItem = renderItems[ renderItemsIndex ];
if ( renderItem === undefined ) {
renderItem = {
id: object.id,
object: object,
geometry: geometry,
material: material,
program: material.program,
renderOrder: object.renderOrder,
z: z,
group: group
};
renderItems[ renderItemsIndex ] = renderItem;
} else {
renderItem.id = object.id;
renderItem.object = object;
renderItem.geometry = geometry;
renderItem.material = material;
renderItem.program = material.program;
renderItem.renderOrder = object.renderOrder;
renderItem.z = z;
renderItem.group = group;
}
( material.transparent === true ? transparent : opaque ).push( renderItem );
renderItemsIndex ++;
}
function sort() {
if ( opaque.length > 1 ) { opaque.sort( painterSortStable ); }
if ( transparent.length > 1 ) { transparent.sort( reversePainterSortStable ); }
}
return {
opaque: opaque,
transparent: transparent,
init: init,
push: push,
sort: sort
};
}
function WebGLRenderLists() {
var lists = {};
function get( scene, camera ) {
var hash = scene.id + ',' + camera.id;
var list = lists[ hash ];
if ( list === undefined ) {
// console.log( 'THREE.WebGLRenderLists:', hash );
list = new WebGLRenderList();
lists[ hash ] = list;
}
return list;
}
function dispose() {
lists = {};
}
return {
get: get,
dispose: dispose
};
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function absNumericalSort( a, b ) {
return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
}
function WebGLMorphtargets( gl ) {
var influencesList = {};
var morphInfluences = new Float32Array( 8 );
function update( object, geometry, material, program ) {
var objectInfluences = object.morphTargetInfluences;
var length = objectInfluences.length;
var influences = influencesList[ geometry.id ];
if ( influences === undefined ) {
// initialise list
influences = [];
for ( var i = 0; i < length; i ++ ) {
influences[ i ] = [ i, 0 ];
}
influencesList[ geometry.id ] = influences;
}
var morphTargets = material.morphTargets && geometry.morphAttributes.position;
var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
// Remove current morphAttributes
for ( var i = 0; i < length; i ++ ) {
var influence = influences[ i ];
if ( influence[ 1 ] !== 0 ) {
if ( morphTargets ) { geometry.removeAttribute( 'morphTarget' + i ); }
if ( morphNormals ) { geometry.removeAttribute( 'morphNormal' + i ); }
}
}
// Collect influences
for ( var i = 0; i < length; i ++ ) {
var influence = influences[ i ];
influence[ 0 ] = i;
influence[ 1 ] = objectInfluences[ i ];
}
influences.sort( absNumericalSort );
// Add morphAttributes
for ( var i = 0; i < 8; i ++ ) {
var influence = influences[ i ];
if ( influence ) {
var index = influence[ 0 ];
var value = influence[ 1 ];
if ( value ) {
if ( morphTargets ) { geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); }
if ( morphNormals ) { geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); }
morphInfluences[ i ] = value;
continue;
}
}
morphInfluences[ i ] = 0;
}
program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
}
return {
update: update
};
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) {
var mode;
function setMode( value ) {
mode = value;
}
var type, bytesPerElement;
function setIndex( value ) {
type = value.type;
bytesPerElement = value.bytesPerElement;
}
function render( start, count ) {
gl.drawElements( mode, count, type, start * bytesPerElement );
infoRender.calls ++;
infoRender.vertices += count;
if ( mode === gl.TRIANGLES ) { infoRender.faces += count / 3; }
else if ( mode === gl.POINTS ) { infoRender.points += count; }
}
function renderInstances( geometry, start, count ) {
var extension = extensions.get( 'ANGLE_instanced_arrays' );
if ( extension === null ) {
console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
return;
}
extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
infoRender.calls ++;
infoRender.vertices += count * geometry.maxInstancedCount;
if ( mode === gl.TRIANGLES ) { infoRender.faces += geometry.maxInstancedCount * count / 3; }
else if ( mode === gl.POINTS ) { infoRender.points += geometry.maxInstancedCount * count; }
}
//
this.setMode = setMode;
this.setIndex = setIndex;
this.render = render;
this.renderInstances = renderInstances;
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLBufferRenderer( gl, extensions, infoRender ) {
var mode;
function setMode( value ) {
mode = value;
}
function render( start, count ) {
gl.drawArrays( mode, start, count );
infoRender.calls ++;
infoRender.vertices += count;
if ( mode === gl.TRIANGLES ) { infoRender.faces += count / 3; }
else if ( mode === gl.POINTS ) { infoRender.points += count; }
}
function renderInstances( geometry, start, count ) {
var extension = extensions.get( 'ANGLE_instanced_arrays' );
if ( extension === null ) {
console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
return;
}
var position = geometry.attributes.position;
if ( position.isInterleavedBufferAttribute ) {
count = position.data.count;
extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount );
} else {
extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
}
infoRender.calls ++;
infoRender.vertices += count * geometry.maxInstancedCount;
if ( mode === gl.TRIANGLES ) { infoRender.faces += geometry.maxInstancedCount * count / 3; }
else if ( mode === gl.POINTS ) { infoRender.points += geometry.maxInstancedCount * count; }
}
//
this.setMode = setMode;
this.render = render;
this.renderInstances = renderInstances;
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLGeometries( gl, attributes, infoMemory ) {
var geometries = {};
var wireframeAttributes = {};
function onGeometryDispose( event ) {
var geometry = event.target;
var buffergeometry = geometries[ geometry.id ];
if ( buffergeometry.index !== null ) {
attributes.remove( buffergeometry.index );
}
for ( var name in buffergeometry.attributes ) {
attributes.remove( buffergeometry.attributes[ name ] );
}
geometry.removeEventListener( 'dispose', onGeometryDispose );
delete geometries[ geometry.id ];
// TODO Remove duplicate code
var attribute = wireframeAttributes[ geometry.id ];
if ( attribute ) {
attributes.remove( attribute );
delete wireframeAttributes[ geometry.id ];
}
attribute = wireframeAttributes[ buffergeometry.id ];
if ( attribute ) {
attributes.remove( attribute );
delete wireframeAttributes[ buffergeometry.id ];
}
//
infoMemory.geometries --;
}
function get( object, geometry ) {
var buffergeometry = geometries[ geometry.id ];
if ( buffergeometry ) { return buffergeometry; }
geometry.addEventListener( 'dispose', onGeometryDispose );
if ( geometry.isBufferGeometry ) {
buffergeometry = geometry;
} else if ( geometry.isGeometry ) {
if ( geometry._bufferGeometry === undefined ) {
geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
}
buffergeometry = geometry._bufferGeometry;
}
geometries[ geometry.id ] = buffergeometry;
infoMemory.geometries ++;
return buffergeometry;
}
function update( geometry ) {
var index = geometry.index;
var geometryAttributes = geometry.attributes;
if ( index !== null ) {
attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
}
for ( var name in geometryAttributes ) {
attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
}
// morph targets
var morphAttributes = geometry.morphAttributes;
for ( var name in morphAttributes ) {
var array = morphAttributes[ name ];
for ( var i = 0, l = array.length; i < l; i ++ ) {
attributes.update( array[ i ], gl.ARRAY_BUFFER );
}
}
}
function getWireframeAttribute( geometry ) {
var attribute = wireframeAttributes[ geometry.id ];
if ( attribute ) { return attribute; }
var indices = [];
var geometryIndex = geometry.index;
var geometryAttributes = geometry.attributes;
// console.time( 'wireframe' );
if ( geometryIndex !== null ) {
var array = geometryIndex.array;
for ( var i = 0, l = array.length; i < l; i += 3 ) {
var a = array[ i + 0 ];
var b = array[ i + 1 ];
var c = array[ i + 2 ];
indices.push( a, b, b, c, c, a );
}
} else {
var array = geometryAttributes.position.array;
for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
var a = i + 0;
var b = i + 1;
var c = i + 2;
indices.push( a, b, b, c, c, a );
}
}
// console.timeEnd( 'wireframe' );
attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );
wireframeAttributes[ geometry.id ] = attribute;
return attribute;
}
return {
get: get,
update: update,
getWireframeAttribute: getWireframeAttribute
};
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function UniformsCache() {
var lights = {};
return {
get: function ( light ) {
if ( lights[ light.id ] !== undefined ) {
return lights[ light.id ];
}
var uniforms;
switch ( light.type ) {
case 'DirectionalLight':
uniforms = {
direction: new Vector3(),
color: new Color(),
shadow: false,
shadowBias: 0,
shadowRadius: 1,
shadowMapSize: new Vector2()
};
break;
case 'SpotLight':
uniforms = {
position: new Vector3(),
direction: new Vector3(),
color: new Color(),
distance: 0,
coneCos: 0,
penumbraCos: 0,
decay: 0,
shadow: false,
shadowBias: 0,
shadowRadius: 1,
shadowMapSize: new Vector2()
};
break;
case 'PointLight':
uniforms = {
position: new Vector3(),
color: new Color(),
distance: 0,
decay: 0,
shadow: false,
shadowBias: 0,
shadowRadius: 1,
shadowMapSize: new Vector2(),
shadowCameraNear: 1,
shadowCameraFar: 1000
};
break;
case 'HemisphereLight':
uniforms = {
direction: new Vector3(),
skyColor: new Color(),
groundColor: new Color()
};
break;
case 'RectAreaLight':
uniforms = {
color: new Color(),
position: new Vector3(),
halfWidth: new Vector3(),
halfHeight: new Vector3()
// TODO (abelnation): set RectAreaLight shadow uniforms
};
break;
}
lights[ light.id ] = uniforms;
return uniforms;
}
};
}
function WebGLLights() {
var cache = new UniformsCache();
var state = {
hash: '',
ambient: [ 0, 0, 0 ],
directional: [],
directionalShadowMap: [],
directionalShadowMatrix: [],
spot: [],
spotShadowMap: [],
spotShadowMatrix: [],
rectArea: [],
point: [],
pointShadowMap: [],
pointShadowMatrix: [],
hemi: []
};
var vector3 = new Vector3();
var matrix4 = new Matrix4();
var matrix42 = new Matrix4();
function setup( lights, shadows, camera ) {
var r = 0, g = 0, b = 0;
var directionalLength = 0;
var pointLength = 0;
var spotLength = 0;
var rectAreaLength = 0;
var hemiLength = 0;
var viewMatrix = camera.matrixWorldInverse;
for ( var i = 0, l = lights.length; i < l; i ++ ) {
var light = lights[ i ];
var color = light.color;
var intensity = light.intensity;
var distance = light.distance;
var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
if ( light.isAmbientLight ) {
r += color.r * intensity;
g += color.g * intensity;
b += color.b * intensity;
} else if ( light.isDirectionalLight ) {
var uniforms = cache.get( light );
uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
vector3.setFromMatrixPosition( light.target.matrixWorld );
uniforms.direction.sub( vector3 );
uniforms.direction.transformDirection( viewMatrix );
uniforms.shadow = light.castShadow;
if ( light.castShadow ) {
var shadow = light.shadow;
uniforms.shadowBias = shadow.bias;
uniforms.shadowRadius = shadow.radius;
uniforms.shadowMapSize = shadow.mapSize;
}
state.directionalShadowMap[ directionalLength ] = shadowMap;
state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
state.directional[ directionalLength ] = uniforms;
directionalLength ++;
} else if ( light.isSpotLight ) {
var uniforms = cache.get( light );
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
uniforms.color.copy( color ).multiplyScalar( intensity );
uniforms.distance = distance;
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
vector3.setFromMatrixPosition( light.target.matrixWorld );
uniforms.direction.sub( vector3 );
uniforms.direction.transformDirection( viewMatrix );
uniforms.coneCos = Math.cos( light.angle );
uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
uniforms.shadow = light.castShadow;
if ( light.castShadow ) {
var shadow = light.shadow;
uniforms.shadowBias = shadow.bias;
uniforms.shadowRadius = shadow.radius;
uniforms.shadowMapSize = shadow.mapSize;
}
state.spotShadowMap[ spotLength ] = shadowMap;
state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
state.spot[ spotLength ] = uniforms;
spotLength ++;
} else if ( light.isRectAreaLight ) {
var uniforms = cache.get( light );
// (a) intensity controls irradiance of entire light
uniforms.color
.copy( color )
.multiplyScalar( intensity / ( light.width * light.height ) );
// (b) intensity controls the radiance per light area
// uniforms.color.copy( color ).multiplyScalar( intensity );
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
// extract local rotation of light to derive width/height half vectors
matrix42.identity();
matrix4.copy( light.matrixWorld );
matrix4.premultiply( viewMatrix );
matrix42.extractRotation( matrix4 );
uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
uniforms.halfWidth.applyMatrix4( matrix42 );
uniforms.halfHeight.applyMatrix4( matrix42 );
// TODO (abelnation): RectAreaLight distance?
// uniforms.distance = distance;
state.rectArea[ rectAreaLength ] = uniforms;
rectAreaLength ++;
} else if ( light.isPointLight ) {
var uniforms = cache.get( light );
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
uniforms.distance = light.distance;
uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
uniforms.shadow = light.castShadow;
if ( light.castShadow ) {
var shadow = light.shadow;
uniforms.shadowBias = shadow.bias;
uniforms.shadowRadius = shadow.radius;
uniforms.shadowMapSize = shadow.mapSize;
uniforms.shadowCameraNear = shadow.camera.near;
uniforms.shadowCameraFar = shadow.camera.far;
}
state.pointShadowMap[ pointLength ] = shadowMap;
state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
state.point[ pointLength ] = uniforms;
pointLength ++;
} else if ( light.isHemisphereLight ) {
var uniforms = cache.get( light );
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
uniforms.direction.transformDirection( viewMatrix );
uniforms.direction.normalize();
uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
state.hemi[ hemiLength ] = uniforms;
hemiLength ++;
}
}
state.ambient[ 0 ] = r;
state.ambient[ 1 ] = g;
state.ambient[ 2 ] = b;
state.directional.length = directionalLength;
state.spot.length = spotLength;
state.rectArea.length = rectAreaLength;
state.point.length = pointLength;
state.hemi.length = hemiLength;
// TODO (sam-g-steel) why aren't we using join
state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;
}
return {
setup: setup,
state: state
};
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLObjects( geometries, infoRender ) {
var updateList = {};
function update( object ) {
var frame = infoRender.frame;
var geometry = object.geometry;
var buffergeometry = geometries.get( object, geometry );
// Update once per frame
if ( updateList[ buffergeometry.id ] !== frame ) {
if ( geometry.isGeometry ) {
buffergeometry.updateFromObject( object );
}
geometries.update( buffergeometry );
updateList[ buffergeometry.id ] = frame;
}
return buffergeometry;
}
function clear() {
updateList = {};
}
return {
update: update,
clear: clear
};
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function addLineNumbers( string ) {
var lines = string.split( '\n' );
for ( var i = 0; i < lines.length; i ++ ) {
lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
}
return lines.join( '\n' );
}
function WebGLShader( gl, type, string ) {
var shader = gl.createShader( type );
gl.shaderSource( shader, string );
gl.compileShader( shader );
if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
}
if ( gl.getShaderInfoLog( shader ) !== '' ) {
console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
}
// --enable-privileged-webgl-extension
// console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
return shader;
}
/**
* @author mrdoob / http://mrdoob.com/
*/
var programIdCount = 0;
function getEncodingComponents( encoding ) {
switch ( encoding ) {
case LinearEncoding:
return [ 'Linear', '( value )' ];
case sRGBEncoding:
return [ 'sRGB', '( value )' ];
case RGBEEncoding:
return [ 'RGBE', '( value )' ];
case RGBM7Encoding:
return [ 'RGBM', '( value, 7.0 )' ];
case RGBM16Encoding:
return [ 'RGBM', '( value, 16.0 )' ];
case RGBDEncoding:
return [ 'RGBD', '( value, 256.0 )' ];
case GammaEncoding:
return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
default:
throw new Error( 'unsupported encoding: ' + encoding );
}
}
function getTexelDecodingFunction( functionName, encoding ) {
var components = getEncodingComponents( encoding );
return "vec4 " + functionName + "( vec4 value ) { return " + components[ 0 ] + "ToLinear" + components[ 1 ] + "; }";
}
function getTexelEncodingFunction( functionName, encoding ) {
var components = getEncodingComponents( encoding );
return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[ 0 ] + components[ 1 ] + "; }";
}
function getToneMappingFunction( functionName, toneMapping ) {
var toneMappingName;
switch ( toneMapping ) {
case LinearToneMapping:
toneMappingName = "Linear";
break;
case ReinhardToneMapping:
toneMappingName = "Reinhard";
break;
case Uncharted2ToneMapping:
toneMappingName = "Uncharted2";
break;
case CineonToneMapping:
toneMappingName = "OptimizedCineon";
break;
default:
throw new Error( 'unsupported toneMapping: ' + toneMapping );
}
return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }";
}
function generateExtensions( extensions, parameters, rendererExtensions ) {
extensions = extensions || {};
var chunks = [
( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
];
return chunks.filter( filterEmptyLine ).join( '\n' );
}
function generateDefines( defines ) {
var chunks = [];
for ( var name in defines ) {
var value = defines[ name ];
if ( value === false ) { continue; }
chunks.push( '#define ' + name + ' ' + value );
}
return chunks.join( '\n' );
}
function fetchAttributeLocations( gl, program ) {
var attributes = {};
var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
for ( var i = 0; i < n; i ++ ) {
var info = gl.getActiveAttrib( program, i );
var name = info.name;
// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
attributes[ name ] = gl.getAttribLocation( program, name );
}
return attributes;
}
function filterEmptyLine( string ) {
return string !== '';
}
function replaceLightNums( string, parameters ) {
return string
.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
}
function parseIncludes( string ) {
var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
function replace( match, include ) {
var replace = ShaderChunk[ include ];
if ( replace === undefined ) {
throw new Error( 'Can not resolve #include <' + include + '>' );
}
return parseIncludes( replace );
}
return string.replace( pattern, replace );
}
function unrollLoops( string ) {
var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
function replace( match, start, end, snippet ) {
var unroll = '';
for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
}
return unroll;
}
return string.replace( pattern, replace );
}
function WebGLProgram( renderer, extensions, code, material, shader, parameters ) {
var gl = renderer.context;
var defines = material.defines;
var vertexShader = shader.vertexShader;
var fragmentShader = shader.fragmentShader;
var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
if ( parameters.shadowMapType === PCFShadowMap ) {
shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
}
var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
if ( parameters.envMap ) {
switch ( material.envMap.mapping ) {
case CubeReflectionMapping:
case CubeRefractionMapping:
envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
break;
case CubeUVReflectionMapping:
case CubeUVRefractionMapping:
envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
break;
case EquirectangularReflectionMapping:
case EquirectangularRefractionMapping:
envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
break;
case SphericalReflectionMapping:
envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
break;
}
switch ( material.envMap.mapping ) {
case CubeRefractionMapping:
case EquirectangularRefractionMapping:
envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
break;
}
switch ( material.combine ) {
case MultiplyOperation:
envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
break;
case MixOperation:
envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
break;
case AddOperation:
envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
break;
}
}
var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
// console.log( 'building new program ' );
//
var customExtensions = generateExtensions( material.extensions, parameters, extensions );
var customDefines = generateDefines( defines );
//
var program = gl.createProgram();
var prefixVertex, prefixFragment;
if ( material.isRawShaderMaterial ) {
prefixVertex = [
customDefines
].filter( filterEmptyLine ).join( '\n' );
if ( prefixVertex.length > 0 ) {
prefixVertex += '\n';
}
prefixFragment = [
customExtensions,
customDefines
].filter( filterEmptyLine ).join( '\n' );
if ( prefixFragment.length > 0 ) {
prefixFragment += '\n';
}
} else {
prefixVertex = [
'precision ' + parameters.precision + ' float;',
'precision ' + parameters.precision + ' int;',
'#define SHADER_NAME ' + shader.name,
customDefines,
parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
'#define GAMMA_FACTOR ' + gammaFactorDefine,
'#define MAX_BONES ' + parameters.maxBones,
( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
parameters.map ? '#define USE_MAP' : '',
parameters.envMap ? '#define USE_ENVMAP' : '',
parameters.envMap ? '#define ' + envMapModeDefine : '',
parameters.lightMap ? '#define USE_LIGHTMAP' : '',
parameters.aoMap ? '#define USE_AOMAP' : '',
parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
parameters.bumpMap ? '#define USE_BUMPMAP' : '',
parameters.normalMap ? '#define USE_NORMALMAP' : '',
parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
parameters.specularMap ? '#define USE_SPECULARMAP' : '',
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.vertexColors ? '#define USE_COLOR' : '',
parameters.flatShading ? '#define FLAT_SHADED' : '',
parameters.skinning ? '#define USE_SKINNING' : '',
parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
parameters.flipSided ? '#define FLIP_SIDED' : '',
'#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
'uniform mat4 modelMatrix;',
'uniform mat4 modelViewMatrix;',
'uniform mat4 projectionMatrix;',
'uniform mat4 viewMatrix;',
'uniform mat3 normalMatrix;',
'uniform vec3 cameraPosition;',
'attribute vec3 position;',
'attribute vec3 normal;',
'attribute vec2 uv;',
'#ifdef USE_COLOR',
' attribute vec3 color;',
'#endif',
'#ifdef USE_MORPHTARGETS',
' attribute vec3 morphTarget0;',
' attribute vec3 morphTarget1;',
' attribute vec3 morphTarget2;',
' attribute vec3 morphTarget3;',
' #ifdef USE_MORPHNORMALS',
' attribute vec3 morphNormal0;',
' attribute vec3 morphNormal1;',
' attribute vec3 morphNormal2;',
' attribute vec3 morphNormal3;',
' #else',
' attribute vec3 morphTarget4;',
' attribute vec3 morphTarget5;',
' attribute vec3 morphTarget6;',
' attribute vec3 morphTarget7;',
' #endif',
'#endif',
'#ifdef USE_SKINNING',
' attribute vec4 skinIndex;',
' attribute vec4 skinWeight;',
'#endif',
'\n'
].filter( filterEmptyLine ).join( '\n' );
prefixFragment = [
customExtensions,
'precision ' + parameters.precision + ' float;',
'precision ' + parameters.precision + ' int;',
'#define SHADER_NAME ' + shader.name,
customDefines,
parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
'#define GAMMA_FACTOR ' + gammaFactorDefine,
( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
parameters.map ? '#define USE_MAP' : '',
parameters.envMap ? '#define USE_ENVMAP' : '',
parameters.envMap ? '#define ' + envMapTypeDefine : '',
parameters.envMap ? '#define ' + envMapModeDefine : '',
parameters.envMap ? '#define ' + envMapBlendingDefine : '',
parameters.lightMap ? '#define USE_LIGHTMAP' : '',
parameters.aoMap ? '#define USE_AOMAP' : '',
parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
parameters.bumpMap ? '#define USE_BUMPMAP' : '',
parameters.normalMap ? '#define USE_NORMALMAP' : '',
parameters.specularMap ? '#define USE_SPECULARMAP' : '',
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
parameters.vertexColors ? '#define USE_COLOR' : '',
parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
parameters.flatShading ? '#define FLAT_SHADED' : '',
parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
parameters.flipSided ? '#define FLIP_SIDED' : '',
'#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
'#define UNION_CLIPPING_PLANES ' + ( parameters.numClippingPlanes - parameters.numClipIntersection ),
parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '',
parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '',
parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
'uniform mat4 viewMatrix;',
'uniform vec3 cameraPosition;',
( parameters.toneMapping !== NoToneMapping ) ? "#define TONE_MAPPING" : '',
( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( "toneMapping", parameters.toneMapping ) : '',
parameters.dithering ? '#define DITHERING' : '',
( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
parameters.outputEncoding ? getTexelEncodingFunction( "linearToOutputTexel", parameters.outputEncoding ) : '',
parameters.depthPacking ? "#define DEPTH_PACKING " + material.depthPacking : '',
'\n'
].filter( filterEmptyLine ).join( '\n' );
}
vertexShader = parseIncludes( vertexShader );
vertexShader = replaceLightNums( vertexShader, parameters );
fragmentShader = parseIncludes( fragmentShader );
fragmentShader = replaceLightNums( fragmentShader, parameters );
if ( ! material.isShaderMaterial ) {
vertexShader = unrollLoops( vertexShader );
fragmentShader = unrollLoops( fragmentShader );
}
var vertexGlsl = prefixVertex + vertexShader;
var fragmentGlsl = prefixFragment + fragmentShader;
// console.log( '*VERTEX*', vertexGlsl );
// console.log( '*FRAGMENT*', fragmentGlsl );
var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
gl.attachShader( program, glVertexShader );
gl.attachShader( program, glFragmentShader );
// Force a particular attribute to index 0.
if ( material.index0AttributeName !== undefined ) {
gl.bindAttribLocation( program, 0, material.index0AttributeName );
} else if ( parameters.morphTargets === true ) {
// programs with morphTargets displace position out of attribute 0
gl.bindAttribLocation( program, 0, 'position' );
}
gl.linkProgram( program );
var programLog = gl.getProgramInfoLog( program );
var vertexLog = gl.getShaderInfoLog( glVertexShader );
var fragmentLog = gl.getShaderInfoLog( glFragmentShader );
var runnable = true;
var haveDiagnostics = true;
// console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
// console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
runnable = false;
console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
} else if ( programLog !== '' ) {
console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
} else if ( vertexLog === '' || fragmentLog === '' ) {
haveDiagnostics = false;
}
if ( haveDiagnostics ) {
this.diagnostics = {
runnable: runnable,
material: material,
programLog: programLog,
vertexShader: {
log: vertexLog,
prefix: prefixVertex
},
fragmentShader: {
log: fragmentLog,
prefix: prefixFragment
}
};
}
// clean up
gl.deleteShader( glVertexShader );
gl.deleteShader( glFragmentShader );
// set up caching for uniform locations
var cachedUniforms;
this.getUniforms = function () {
if ( cachedUniforms === undefined ) {
cachedUniforms = new WebGLUniforms( gl, program, renderer );
}
return cachedUniforms;
};
// set up caching for attribute locations
var cachedAttributes;
this.getAttributes = function () {
if ( cachedAttributes === undefined ) {
cachedAttributes = fetchAttributeLocations( gl, program );
}
return cachedAttributes;
};
// free resource
this.destroy = function () {
gl.deleteProgram( program );
this.program = undefined;
};
// DEPRECATED
Object.defineProperties( this, {
uniforms: {
get: function () {
console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
return this.getUniforms();
}
},
attributes: {
get: function () {
console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
return this.getAttributes();
}
}
} );
//
this.id = programIdCount ++;
this.code = code;
this.usedTimes = 1;
this.program = program;
this.vertexShader = glVertexShader;
this.fragmentShader = glFragmentShader;
return this;
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLPrograms( renderer, extensions, capabilities ) {
var programs = [];
var shaderIDs = {
MeshDepthMaterial: 'depth',
MeshDistanceMaterial: 'distanceRGBA',
MeshNormalMaterial: 'normal',
MeshBasicMaterial: 'basic',
MeshLambertMaterial: 'lambert',
MeshPhongMaterial: 'phong',
MeshToonMaterial: 'phong',
MeshStandardMaterial: 'physical',
MeshPhysicalMaterial: 'physical',
LineBasicMaterial: 'basic',
LineDashedMaterial: 'dashed',
PointsMaterial: 'points',
ShadowMaterial: 'shadow'
};
var parameterNames = [
"precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
"roughnessMap", "metalnessMap", "gradientMap",
"alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
"numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
"shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
"alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"
];
function allocateBones( object ) {
var skeleton = object.skeleton;
var bones = skeleton.bones;
if ( capabilities.floatVertexTextures ) {
return 1024;
} else {
// default for when object is not specified
// ( for example when prebuilding shader to be used with multiple objects )
//
// - leave some extra space for other uniforms
// - limit here is ANGLE's 254 max uniform vectors
// (up to 54 should be safe)
var nVertexUniforms = capabilities.maxVertexUniforms;
var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
var maxBones = Math.min( nVertexMatrices, bones.length );
if ( maxBones < bones.length ) {
console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
return 0;
}
return maxBones;
}
}
function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
var encoding;
if ( ! map ) {
encoding = LinearEncoding;
} else if ( map.isTexture ) {
encoding = map.encoding;
} else if ( map.isWebGLRenderTarget ) {
console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
encoding = map.texture.encoding;
}
// add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
if ( encoding === LinearEncoding && gammaOverrideLinear ) {
encoding = GammaEncoding;
}
return encoding;
}
this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {
var shaderID = shaderIDs[ material.type ];
// heuristics to create shader parameters according to lights in the scene
// (not to blow over maxLights budget)
var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
var precision = capabilities.precision;
if ( material.precision !== null ) {
precision = capabilities.getMaxPrecision( material.precision );
if ( precision !== material.precision ) {
console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
}
}
var currentRenderTarget = renderer.getRenderTarget();
var parameters = {
shaderID: shaderID,
precision: precision,
supportsVertexTextures: capabilities.vertexTextures,
outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
map: !! material.map,
mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
envMap: !! material.envMap,
envMapMode: material.envMap && material.envMap.mapping,
envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
lightMap: !! material.lightMap,
aoMap: !! material.aoMap,
emissiveMap: !! material.emissiveMap,
emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
bumpMap: !! material.bumpMap,
normalMap: !! material.normalMap,
displacementMap: !! material.displacementMap,
roughnessMap: !! material.roughnessMap,
metalnessMap: !! material.metalnessMap,
specularMap: !! material.specularMap,
alphaMap: !! material.alphaMap,
gradientMap: !! material.gradientMap,
combine: material.combine,
vertexColors: material.vertexColors,
fog: !! fog,
useFog: material.fog,
fogExp: ( fog && fog.isFogExp2 ),
flatShading: material.flatShading,
sizeAttenuation: material.sizeAttenuation,
logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
skinning: material.skinning && maxBones > 0,
maxBones: maxBones,
useVertexTexture: capabilities.floatVertexTextures,
morphTargets: material.morphTargets,
morphNormals: material.morphNormals,
maxMorphTargets: renderer.maxMorphTargets,
maxMorphNormals: renderer.maxMorphNormals,
numDirLights: lights.directional.length,
numPointLights: lights.point.length,
numSpotLights: lights.spot.length,
numRectAreaLights: lights.rectArea.length,
numHemiLights: lights.hemi.length,
numClippingPlanes: nClipPlanes,
numClipIntersection: nClipIntersection,
dithering: material.dithering,
shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
shadowMapType: renderer.shadowMap.type,
toneMapping: renderer.toneMapping,
physicallyCorrectLights: renderer.physicallyCorrectLights,
premultipliedAlpha: material.premultipliedAlpha,
alphaTest: material.alphaTest,
doubleSided: material.side === DoubleSide,
flipSided: material.side === BackSide,
depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
};
return parameters;
};
this.getProgramCode = function ( material, parameters ) {
var array = [];
if ( parameters.shaderID ) {
array.push( parameters.shaderID );
} else {
array.push( material.fragmentShader );
array.push( material.vertexShader );
}
if ( material.defines !== undefined ) {
for ( var name in material.defines ) {
array.push( name );
array.push( material.defines[ name ] );
}
}
for ( var i = 0; i < parameterNames.length; i ++ ) {
array.push( parameters[ parameterNames[ i ] ] );
}
array.push( material.onBeforeCompile.toString() );
array.push( renderer.gammaOutput );
return array.join();
};
this.acquireProgram = function ( material, shader, parameters, code ) {
var program;
// Check if code has been already compiled
for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
var programInfo = programs[ p ];
if ( programInfo.code === code ) {
program = programInfo;
++ program.usedTimes;
break;
}
}
if ( program === undefined ) {
program = new WebGLProgram( renderer, extensions, code, material, shader, parameters );
programs.push( program );
}
return program;
};
this.releaseProgram = function ( program ) {
if ( -- program.usedTimes === 0 ) {
// Remove from unordered set
var i = programs.indexOf( program );
programs[ i ] = programs[ programs.length - 1 ];
programs.pop();
// Free WebGL resources
program.destroy();
}
};
// Exposed for resource monitoring & error feedback via renderer.info:
this.programs = programs;
}
/**
* @author mrdoob / http://mrdoob.com/
*/
function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) {
var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof window.WebGL2RenderingContext );
//
function clampToMaxSize( image, maxSize ) {
if ( image.width > maxSize || image.height > maxSize ) {
// Warning: Scaling through the canvas will only work with images that use
// premultiplied alpha.
var scale = maxSize / Math.max( image.width, image.height );
var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
canvas.width = Math.floor( image.width * scale );
canvas.height = Math.floor( image.height * scale );
var context = canvas.getContext( '2d' );
context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
return canvas;
}
return image;
}
function isPowerOfTwo( image ) {
return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );
}
function makePowerOfTwo( image ) {
if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) {
var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
canvas.width = _Math.floorPowerOfTwo( image.width );
canvas.height = _Math.floorPowerOfTwo( image.height );
var context = canvas.getContext( '2d' );
context.drawImage( image, 0, 0, canvas.width, canvas.height );
console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
return canvas;
}
return image;
}
function textureNeedsPowerOfTwo( texture ) {
return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
}
function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) {
return texture.generateMipmaps && isPowerOfTwo &&
texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
}
// Fallback filters for non-power-of-2 textures
function filterFallback( f ) {
if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
return _gl.NEAREST;
}
return _gl.LINEAR;
}
//
function onTextureDispose( event ) {
var texture = event.target;
texture.removeEventListener( 'dispose', onTextureDispose );
deallocateTexture( texture );
infoMemory.textures --;
}
function onRenderTargetDispose( event ) {
var renderTarget = event.target;
renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
deallocateRenderTarget( renderTarget );
infoMemory.textures --;
}
//
function deallocateTexture( texture ) {
var textureProperties = properties.get( texture );
if ( texture.image && textureProperties.__image__webglTextureCube ) {
// cube texture
_gl.deleteTexture( textureProperties.__image__webglTextureCube );
} else {
// 2D texture
if ( textureProperties.__webglInit === undefined ) { return; }
_gl.deleteTexture( textureProperties.__webglTexture );
}
// remove all webgl properties
properties.remove( texture );
}
function deallocateRenderTarget( renderTarget ) {
var renderTargetProperties = properties.get( renderTarget );
var textureProperties = properties.get( renderTarget.texture );
if ( ! renderTarget ) { return; }
if ( textureProperties.__webglTexture !== undefined ) {
_gl.deleteTexture( textureProperties.__webglTexture );
}
if ( renderTarget.depthTexture ) {
renderTarget.depthTexture.dispose();
}
if ( renderTarget.isWebGLRenderTargetCube ) {
for ( var i = 0; i < 6; i ++ ) {
_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
if ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); }
}
} else {
_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
if ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); }
}
properties.remove( renderTarget.texture );
properties.remove( renderTarget );
}
//
function setTexture2D( texture, slot ) {
var textureProperties = properties.get( texture );
if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
var image = texture.image;
if ( image === undefined ) {
console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
} else if ( image.complete === false ) {
console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
} else {
uploadTexture( textureProperties, texture, slot );
return;
}
}
state.activeTexture( _gl.TEXTURE0 + slot );
state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
}
function setTextureCube( texture, slot ) {
var textureProperties = properties.get( texture );
if ( texture.image.length === 6 ) {
if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
if ( ! textureProperties.__image__webglTextureCube ) {
texture.addEventListener( 'dispose', onTextureDispose );
textureProperties.__image__webglTextureCube = _gl.createTexture();
infoMemory.textures ++;
}
state.activeTexture( _gl.TEXTURE0 + slot );
state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
var isCompressed = ( texture && texture.isCompressedTexture );
var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
var cubeImage = [];
for ( var i = 0; i < 6; i ++ ) {
if ( ! isCompressed && ! isDataTexture ) {
cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
} else {
cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
}
}
var image = cubeImage[ 0 ],
isPowerOfTwoImage = isPowerOfTwo( image ),
glFormat = utils.convert( texture.format ),
glType = utils.convert( texture.type );
setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
for ( var i = 0; i < 6; i ++ ) {
if ( ! isCompressed ) {
if ( isDataTexture ) {
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
} else {
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
}
} else {
var mipmap, mipmaps = cubeImage[ i ].mipmaps;
for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
mipmap = mipmaps[ j ];
if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
} else {
console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
}
} else {
state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
}
}
}
}
if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
}
textureProperties.__version = texture.version;
if ( texture.onUpdate ) { texture.onUpdate( texture ); }
} else {
state.activeTexture( _gl.TEXTURE0 + slot );
state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
}
}
}
function setTextureCubeDynamic( texture, slot ) {
state.activeTexture( _gl.TEXTURE0 + slot );
state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
}
function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
var extension;
if ( isPowerOfTwoImage ) {
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
} else {
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );
}
_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );
}
}
extension = extensions.get( 'EXT_texture_filter_anisotropic' );
if ( extension ) {
if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) { return; }
if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) { return; }
if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
properties.get( texture ).__currentAnisotropy = texture.anisotropy;
}
}
}
function uploadTexture( textureProperties, texture, slot ) {
if ( textureProperties.__webglInit === undefined ) {
textureProperties.__webglInit = true;
texture.addEventListe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment