Created
December 12, 2017 23:18
-
-
Save trusktr/e203c64925f9690661aa9a1cd1791a54 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: 'triggerEvent', | |
value: function triggerEvent(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); | |
} | |
} | |
}]); | |
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.triggerEvent('valuechanged', { x: value }); | |
}, | |
get: function () { | |
return this._x; | |
} | |
}, { | |
key: 'y', | |
set: function (value) { | |
this._y = value; | |
this.triggerEvent('valuechanged', { y: value }); | |
}, | |
get: function () { | |
return this._y; | |
} | |
}, { | |
key: 'z', | |
set: function (value) { | |
this._z = value; | |
this.triggerEvent('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.addEventListener( 'dispose', onTextureDispose ); | |
textureProperties.__webglTexture = _gl.createTexture(); | |
infoMemory.textures ++; | |
} | |
state.activeTexture( _gl.TEXTURE0 + slot ); | |
state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); | |
_gl.pixelStorei( _gl.UNPACK_FLIP_Y_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment