From 893671fa2b6b1f022d005d288b3c53f4318b5d09 Mon Sep 17 00:00:00 2001 From: cTn Date: Mon, 1 Sep 2014 14:46:46 +0200 Subject: [PATCH 001/213] check if result exists before comparison --- js/serial.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/serial.js b/js/serial.js index ade6c7ab..31ad3218 100644 --- a/js/serial.js +++ b/js/serial.js @@ -30,7 +30,7 @@ var serial = { switch (info.error) { case 'system_error': // we might be able to recover from this one var crunch_status = function (info) { - if (!info.paused) { + if (info && !info.paused) { console.log('SERIAL: Connection recovered from last onReceiveError'); googleAnalytics.sendException('Serial: onReceiveError - recovered', false); } else { From 0bd4af89c92dc27106ffe8b354013b005f872f98 Mon Sep 17 00:00:00 2001 From: cTn Date: Mon, 1 Sep 2014 14:56:13 +0200 Subject: [PATCH 002/213] catch lastError cleanly in current context --- js/serial.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/js/serial.js b/js/serial.js index 31ad3218..2a4092bd 100644 --- a/js/serial.js +++ b/js/serial.js @@ -30,18 +30,24 @@ var serial = { switch (info.error) { case 'system_error': // we might be able to recover from this one var crunch_status = function (info) { - if (info && !info.paused) { - console.log('SERIAL: Connection recovered from last onReceiveError'); - googleAnalytics.sendException('Serial: onReceiveError - recovered', false); - } else { - console.log('SERIAL: Connection did not recover from last onReceiveError, disconnecting'); - GUI.log('Unrecoverable failure of serial connection, disconnecting...'); - googleAnalytics.sendException('Serial: onReceiveError - unrecoverable', false); - - if (GUI.connected_to || GUI.connecting_to) { - $('a.connect').click(); + if (info) { + if (!info.paused) { + console.log('SERIAL: Connection recovered from last onReceiveError'); + googleAnalytics.sendException('Serial: onReceiveError - recovered', false); } else { - self.disconnect(); + console.log('SERIAL: Connection did not recover from last onReceiveError, disconnecting'); + GUI.log('Unrecoverable failure of serial connection, disconnecting...'); + googleAnalytics.sendException('Serial: onReceiveError - unrecoverable', false); + + if (GUI.connected_to || GUI.connecting_to) { + $('a.connect').click(); + } else { + self.disconnect(); + } + } + } else { + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError.message); } } } From 8528e3f0668dfbfdcdf19f00ab36469df43dc261 Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 4 Sep 2014 08:57:58 +0200 Subject: [PATCH 003/213] pixel perfect block alignment for initial setup tab --- tabs/initial_setup.css | 6 +-- tabs/initial_setup.html | 90 ++++++++++++++++++++--------------------- 2 files changed, 46 insertions(+), 50 deletions(-) diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index 767e98d9..17aab25b 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -192,8 +192,8 @@ .tab-initial_setup .acc-trim, .tab-initial_setup .magnetometer, .tab-initial_setup .info { - float: left; - display: block; + display: inline-block; + vertical-align: top; margin: 0 0 10px 10px; @@ -244,7 +244,7 @@ line-height: 22px; } .tab-initial_setup .battery input { - width: 60px; + width: 58px; height: 20px; line-height: 20px; diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index fe226ee2..8665b459 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -41,58 +41,54 @@ -
-
- -
-
-
-
-
-
-
-
+
+ +
+
+
+
+
+
+
-
- -
-
-
-
-
-
-
+
+
+ +
+
+
+
+
+
-
- -
-
-
-
-
-
+
+
+ +
+
+
+
+
-
-
- -
-
-
-
-
+
+
+ +
+
+
+
-
- -
-
-
0 V
-
0 mAh
-
0 A
-
0 %
-
-
+
+
+ +
+
+
0 V
+
0 mAh
+
0 A
+
0 %
+
-
From 3aa8d6aa71402534594269abbe7c165fa5020c3b Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 4 Sep 2014 09:33:00 +0200 Subject: [PATCH 004/213] minimize the primary padding/margin UI footprint to get some more space for log and content area --- main.css | 20 ++++++++++---------- tabs/initial_setup.css | 12 ++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/main.css b/main.css index 7fd7d071..902179b1 100644 --- a/main.css +++ b/main.css @@ -44,16 +44,16 @@ input[type="number"]::-webkit-inner-spin-button { float: right; } #main-wrapper { - margin: 10px auto 0 auto; - padding: 0 10px 0 10px; + margin: 0 auto 0 auto; + padding: 5px 5px 0 5px; - height: calc(100% - 10px); /* - padding */ + height: calc(100% - 5px); } #port-picker { float: left; - height: 22px; - margin-bottom: 10px; + height: 20px; + margin-bottom: 5px; } #port-picker li { float: left; @@ -63,7 +63,7 @@ input[type="number"]::-webkit-inner-spin-button { line-height: 20px; float: left; - margin-right: 10px; + margin-right: 5px; border: 1px solid silver; } @@ -191,9 +191,9 @@ input[type="number"]::-webkit-inner-spin-button { margin-right: 5px; } #log { - margin-bottom: 10px; + margin-bottom: 4px; - height: 60px; + height: 65px; border: 1px solid silver; background-color: white; @@ -253,10 +253,10 @@ input[type="number"]::-webkit-inner-spin-button { background-color: white; } #content { - margin-top: 37px; + margin-top: 31px; padding: 10px; - height: calc(100% - 184px); /* - (port picker, log, tab, status bar) */ + height: calc(100% - 171px); /* - (port picker, log, tab, status bar) */ background-color: white; diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index 17aab25b..80c47e15 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -60,7 +60,6 @@ font-weight: bold; } - #interactive_block .modelMixDiagram { position: absolute; @@ -69,17 +68,14 @@ height: 30%; /* interactive_block height set to inherit */ } - #interactive_block .modelMixAirplane { /* Position airplane correctly */ height: 35%; padding-left: 0px; } - #interactive_block .modelMixCustom { /* Position question mark correctly */ height: 20%; /* resize question mark */ padding-left: 25px; } - #interactive_block .heading { float: right; height: 15px; @@ -244,7 +240,7 @@ line-height: 22px; } .tab-initial_setup .battery input { - width: 58px; + width: 68px; height: 20px; line-height: 20px; @@ -327,16 +323,16 @@ .tab-initial_setup .info dt { float: left; - width: 100px; + width: 99px; height: 20px; line-height: 20px; } .tab-initial_setup .info dd { - width: 70px; + width: 76px; height: 20px; line-height: 20px; - margin-left: 100px; + margin-left: 99px; } .tab-initial_setup .buttons { width: calc(100% - 20px); From 21065c8acbbc6ff81de5b4ab264698c0e9eb123b Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 4 Sep 2014 09:33:13 +0200 Subject: [PATCH 005/213] speed up options window animation --- main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index e947fecb..686669d9 100644 --- a/main.js +++ b/main.js @@ -160,7 +160,7 @@ $(document).ready(function () { if (e.type == 'click' && !$.contains($('div#options-window')[0], e.target) || e.type == 'keyup' && e.keyCode == 27) { $(document).unbind('click keyup', close_and_cleanup); - $('div#options-window').slideUp(function () { + $('div#options-window').slideUp(250, function () { el.removeClass('active'); $(this).empty().remove(); }); @@ -169,7 +169,7 @@ $(document).ready(function () { $(document).bind('click keyup', close_and_cleanup); - $(this).slideDown(); + $(this).slideDown(250); }); } }); From cc357440e3b248248c6ac451f48974cfc353c269 Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 4 Sep 2014 10:03:45 +0200 Subject: [PATCH 006/213] remove block centering (no need) --- main.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/main.css b/main.css index 902179b1..014d7e54 100644 --- a/main.css +++ b/main.css @@ -44,9 +44,7 @@ input[type="number"]::-webkit-inner-spin-button { float: right; } #main-wrapper { - margin: 0 auto 0 auto; padding: 5px 5px 0 5px; - height: calc(100% - 5px); } #port-picker { From 91e0e8764bd396801dd9021829267876d17e1780 Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 4 Sep 2014 10:06:51 +0200 Subject: [PATCH 007/213] adjust position of options window for the new layout --- main.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.css b/main.css index 014d7e54..8ad942d1 100644 --- a/main.css +++ b/main.css @@ -172,8 +172,8 @@ input[type="number"]::-webkit-inner-spin-button { display: none; position: fixed; - right: 10px; - top: 32px; + right: 30px; + top: 15px; padding: 5px; From 9c6d80333465bbcdf013ed261474877c9162d26e Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 4 Sep 2014 17:16:13 +0200 Subject: [PATCH 008/213] firmware received from the github server can now be saved locally (as requested) --- tabs/firmware_flasher.css | 6 +++++ tabs/firmware_flasher.js | 55 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/tabs/firmware_flasher.css b/tabs/firmware_flasher.css index be3f0df8..49401f38 100644 --- a/tabs/firmware_flasher.css +++ b/tabs/firmware_flasher.css @@ -19,6 +19,12 @@ /* text-shadow: 1px 0px 2px rgba(0, 0, 0, 0.9);*/ } + .tab-firmware_flasher .info .progressLabel a { + color: white; + } + .tab-firmware_flasher .info .progressLabel a:hover { + text-decoration: underline; + } .tab-firmware_flasher .info .progress { width: 100%; height: 26px; diff --git a/tabs/firmware_flasher.js b/tabs/firmware_flasher.js index c38eed33..3d74ecb1 100644 --- a/tabs/firmware_flasher.js +++ b/tabs/firmware_flasher.js @@ -16,9 +16,9 @@ TABS.firmware_flasher.initialize = function (callback) { // UI Hooks $('a.load_file').click(function () { chrome.fileSystem.chooseEntry({type: 'openFile', accepts: [{extensions: ['hex']}]}, function (fileEntry) { - if (!fileEntry) { - // no "valid" file selected/created, aborting - console.log('No valid file selected, aborting'); + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError.message); + return; } @@ -75,7 +75,54 @@ TABS.firmware_flasher.initialize = function (callback) { if (parsed_hex) { googleAnalytics.sendEvent('Flashing', 'Firmware', 'online'); - $('span.progressLabel').text('Loaded Online Firmware: (' + parsed_hex.bytes_total + ' bytes)'); + $('span.progressLabel').html('Loaded Online Firmware: (' + parsed_hex.bytes_total + ' bytes)'); + + $('span.progressLabel a').click(function () { + chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'baseflight', accepts: [{extensions: ['hex']}]}, function (fileEntry) { + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError.message); + + return; + } + + chrome.fileSystem.getDisplayPath(fileEntry, function (path) { + console.log('Saving firmware to: ' + path); + + // check if file is writable + chrome.fileSystem.isWritableEntry(fileEntry, function (isWritable) { + if (isWritable) { + var blob = new Blob([intel_hex], {type: 'text/plain'}); + + fileEntry.createWriter(function (writer) { + var truncated = false; + + writer.onerror = function (e) { + console.error(e); + }; + + writer.onwriteend = function() { + if (!truncated) { + // onwriteend will be fired again when truncation is finished + truncated = true; + writer.truncate(blob.size); + + return; + } + }; + + writer.write(blob); + }, function (e) { + console.error(e); + }); + } else { + console.log('You don\'t have write permissions for this file, sorry.'); + GUI.log('You don\'t have write permissions for this file'); + } + }); + }); + }); + }); + $('a.flash_firmware').removeClass('locked'); $.get('https://api.github.com/repos/multiwii/baseflight/commits?page=1&per_page=1&path=obj/baseflight.hex', function (data) { From 4623853b0a98b43b6c525d83baad1febd533c973 Mon Sep 17 00:00:00 2001 From: cTn Date: Fri, 5 Sep 2014 15:10:32 +0200 Subject: [PATCH 009/213] initial work on scalable cube --- tabs/initial_setup.css | 24 ++++++----- tabs/initial_setup.html | 88 +++++++++++++++++++++-------------------- 2 files changed, 60 insertions(+), 52 deletions(-) diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index 80c47e15..f858c5da 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -1,4 +1,5 @@ .tab-initial_setup { + height: 100%; } .tab-initial_setup .section { clear: both; @@ -47,8 +48,8 @@ float: left; position: relative; - height: 280px; - width: 400px; + height: calc(100% - 142px); + width: calc(100% - 522px); border: 1px solid silver; background-color: white; @@ -107,13 +108,13 @@ background-color: #dedcdc; } #perspective { + height: calc(100% - 25px); -webkit-perspective: 800; - -webkit-perspective-origin: 50% 150px; /* 150px = (350px / 2) - 25px */ } #cube { position: relative; - top: 110px; - left: 150px; /* (916px / 2) - 50px */ + top: calc(50% - 50px); /* - half of height */ + left: calc(50% - 50px); /* - half of width */ height: 100px; width: 100px; @@ -134,7 +135,7 @@ text-align: center; } #cube .face.one { - width: 100px; + width: 100%; height: 200px; line-height: 200px; @@ -144,7 +145,7 @@ background-color: purple; } #cube .face.two { - width: 100px; + width: 100%; height: 50px; line-height: 50px; @@ -160,7 +161,7 @@ background-color: green; } #cube .face.four { - width: 100px; + width: 100%; height: 50px; line-height: 50px; @@ -176,13 +177,16 @@ background-color: red; } #cube .face.six { - width: 100px; + width: 100%; height: 200px; line-height: 200px; -webkit-transform: rotateX(90deg) translateZ(100px); background-color: silver; } + .tab-initial_setup .block_wrapper { + font-size: 0; + } .tab-initial_setup .battery, .tab-initial_setup .throttle, .tab-initial_setup .acc-trim, @@ -193,6 +197,8 @@ margin: 0 0 10px 10px; + font-size: 12px; + border: 1px solid silver; } .tab-initial_setup .battery .head, diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index 8665b459..f3732e7e 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -41,53 +41,55 @@
-
- -
-
-
-
-
-
-
+
+
+ +
+
+
+
+
+
+
+
-
-
- -
-
-
-
-
-
+
+ +
+
+
+
+
+
+
-
-
- -
-
-
-
-
+
+ +
+
+
+
+
+
-
-
- -
-
-
-
+
+ +
+
+
+
+
-
-
- -
-
-
0 V
-
0 mAh
-
0 A
-
0 %
-
+
+ +
+
+
0 V
+
0 mAh
+
0 A
+
0 %
+
+
From 36bce25ba8bae137a461d2af4c13b524d010f1de Mon Sep 17 00:00:00 2001 From: cTn Date: Fri, 5 Sep 2014 22:45:08 +0200 Subject: [PATCH 010/213] add three.js to libraries --- js/libraries/three.min.js | 827 ++++++++++++++++++++++++++++++++++++++ main.html | 2 + 2 files changed, 829 insertions(+) create mode 100644 js/libraries/three.min.js diff --git a/js/libraries/three.min.js b/js/libraries/three.min.js new file mode 100644 index 00000000..6c2757dc --- /dev/null +++ b/js/libraries/three.min.js @@ -0,0 +1,827 @@ +// threejs.org/license +'use strict';var THREE={REVISION:"68"};"object"===typeof module&&(module.exports=THREE);THREE.CullFaceNone=0;THREE.CullFaceBack=1;THREE.CullFaceFront=2;THREE.CullFaceFrontBack=3;THREE.FrontFaceDirectionCW=0;THREE.FrontFaceDirectionCCW=1;THREE.BasicShadowMap=0;THREE.PCFShadowMap=1;THREE.PCFSoftShadowMap=2;THREE.FrontSide=0;THREE.BackSide=1;THREE.DoubleSide=2;THREE.NoShading=0;THREE.FlatShading=1;THREE.SmoothShading=2;THREE.NoColors=0;THREE.FaceColors=1;THREE.VertexColors=2;THREE.NoBlending=0; +THREE.NormalBlending=1;THREE.AdditiveBlending=2;THREE.SubtractiveBlending=3;THREE.MultiplyBlending=4;THREE.CustomBlending=5;THREE.AddEquation=100;THREE.SubtractEquation=101;THREE.ReverseSubtractEquation=102;THREE.ZeroFactor=200;THREE.OneFactor=201;THREE.SrcColorFactor=202;THREE.OneMinusSrcColorFactor=203;THREE.SrcAlphaFactor=204;THREE.OneMinusSrcAlphaFactor=205;THREE.DstAlphaFactor=206;THREE.OneMinusDstAlphaFactor=207;THREE.DstColorFactor=208;THREE.OneMinusDstColorFactor=209; +THREE.SrcAlphaSaturateFactor=210;THREE.MultiplyOperation=0;THREE.MixOperation=1;THREE.AddOperation=2;THREE.UVMapping=function(){};THREE.CubeReflectionMapping=function(){};THREE.CubeRefractionMapping=function(){};THREE.SphericalReflectionMapping=function(){};THREE.SphericalRefractionMapping=function(){};THREE.RepeatWrapping=1E3;THREE.ClampToEdgeWrapping=1001;THREE.MirroredRepeatWrapping=1002;THREE.NearestFilter=1003;THREE.NearestMipMapNearestFilter=1004;THREE.NearestMipMapLinearFilter=1005; +THREE.LinearFilter=1006;THREE.LinearMipMapNearestFilter=1007;THREE.LinearMipMapLinearFilter=1008;THREE.UnsignedByteType=1009;THREE.ByteType=1010;THREE.ShortType=1011;THREE.UnsignedShortType=1012;THREE.IntType=1013;THREE.UnsignedIntType=1014;THREE.FloatType=1015;THREE.UnsignedShort4444Type=1016;THREE.UnsignedShort5551Type=1017;THREE.UnsignedShort565Type=1018;THREE.AlphaFormat=1019;THREE.RGBFormat=1020;THREE.RGBAFormat=1021;THREE.LuminanceFormat=1022;THREE.LuminanceAlphaFormat=1023; +THREE.RGB_S3TC_DXT1_Format=2001;THREE.RGBA_S3TC_DXT1_Format=2002;THREE.RGBA_S3TC_DXT3_Format=2003;THREE.RGBA_S3TC_DXT5_Format=2004;THREE.Color=function(a){return 3===arguments.length?this.setRGB(arguments[0],arguments[1],arguments[2]):this.set(a)}; +THREE.Color.prototype={constructor:THREE.Color,r:1,g:1,b:1,set:function(a){a instanceof THREE.Color?this.copy(a):"number"===typeof a?this.setHex(a):"string"===typeof a&&this.setStyle(a);return this},setHex:function(a){a=Math.floor(a);this.r=(a>>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},setRGB:function(a,b,c){this.r=a;this.g=b;this.b=c;return this},setHSL:function(a,b,c){if(0===b)this.r=this.g=this.b=c;else{var d=function(a,b,c){0>c&&(c+=1);1c?b:c<2/3?a+6*(b-a)*(2/3-c):a};b=0.5>=c?c*(1+b):c+b-c*b;c=2*c-b;this.r=d(c,b,a+1/3);this.g=d(c,b,a);this.b=d(c,b,a-1/3)}return this},setStyle:function(a){if(/^rgb\((\d+), ?(\d+), ?(\d+)\)$/i.test(a))return a=/^rgb\((\d+), ?(\d+), ?(\d+)\)$/i.exec(a),this.r=Math.min(255,parseInt(a[1],10))/255,this.g=Math.min(255,parseInt(a[2],10))/255,this.b=Math.min(255,parseInt(a[3],10))/255,this;if(/^rgb\((\d+)\%, ?(\d+)\%, ?(\d+)\%\)$/i.test(a))return a=/^rgb\((\d+)\%, ?(\d+)\%, ?(\d+)\%\)$/i.exec(a),this.r= +Math.min(100,parseInt(a[1],10))/100,this.g=Math.min(100,parseInt(a[2],10))/100,this.b=Math.min(100,parseInt(a[3],10))/100,this;if(/^\#([0-9a-f]{6})$/i.test(a))return a=/^\#([0-9a-f]{6})$/i.exec(a),this.setHex(parseInt(a[1],16)),this;if(/^\#([0-9a-f])([0-9a-f])([0-9a-f])$/i.test(a))return a=/^\#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a),this.setHex(parseInt(a[1]+a[1]+a[2]+a[2]+a[3]+a[3],16)),this;if(/^(\w+)$/i.test(a))return this.setHex(THREE.ColorKeywords[a]),this},copy:function(a){this.r=a.r;this.g= +a.g;this.b=a.b;return this},copyGammaToLinear:function(a){this.r=a.r*a.r;this.g=a.g*a.g;this.b=a.b*a.b;return this},copyLinearToGamma:function(a){this.r=Math.sqrt(a.r);this.g=Math.sqrt(a.g);this.b=Math.sqrt(a.b);return this},convertGammaToLinear:function(){var a=this.r,b=this.g,c=this.b;this.r=a*a;this.g=b*b;this.b=c*c;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 255*this.r<<16^255*this.g<< +8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(a){a=a||{h:0,s:0,l:0};var b=this.r,c=this.g,d=this.b,e=Math.max(b,c,d),f=Math.min(b,c,d),g,h=(f+e)/2;if(f===e)f=g=0;else{var k=e-f,f=0.5>=h?k/(e+f):k/(2-e-f);switch(e){case b:g=(c-d)/k+(cf&&c>b?(c=2*Math.sqrt(1+c-f-b),this._w=(k-g)/c,this._x=0.25*c,this._y=(a+e)/c,this._z=(d+h)/c):f>b?(c=2*Math.sqrt(1+f-c-b),this._w=(d-h)/c,this._x=(a+e)/c,this._y= +0.25*c,this._z=(g+k)/c):(c=2*Math.sqrt(1+b-c-f),this._w=(e-a)/c,this._x=(d+h)/c,this._y=(g+k)/c,this._z=0.25*c);this.onChangeCallback();return this},setFromUnitVectors:function(){var a,b;return function(c,d){void 0===a&&(a=new THREE.Vector3);b=c.dot(d)+1;1E-6>b?(b=0,Math.abs(c.x)>Math.abs(c.z)?a.set(-c.y,c.x,0):a.set(0,-c.z,c.y)):a.crossVectors(c,d);this._x=a.x;this._y=a.y;this._z=a.z;this._w=b;this.normalize();return this}}(),inverse:function(){this.conjugate().normalize();return this},conjugate:function(){this._x*= +-1;this._y*=-1;this._z*=-1;this.onChangeCallback();return this},dot:function(a){return this._x*a._x+this._y*a._y+this._z*a._z+this._w*a._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 a=this.length();0===a?(this._z=this._y=this._x=0,this._w=1):(a=1/a,this._x*=a,this._y*=a,this._z*=a,this._w*=a);this.onChangeCallback();return this}, +multiply:function(a,b){return void 0!==b?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(a,b)):this.multiplyQuaternions(this,a)},multiplyQuaternions:function(a,b){var c=a._x,d=a._y,e=a._z,f=a._w,g=b._x,h=b._y,k=b._z,l=b._w;this._x=c*l+f*g+d*k-e*h;this._y=d*l+f*h+e*g-c*k;this._z=e*l+f*k+c*h-d*g;this._w=f*l-c*g-d*h-e*k;this.onChangeCallback();return this},multiplyVector3:function(a){console.warn("THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead."); +return a.applyQuaternion(this)},slerp:function(a,b){var c=this._x,d=this._y,e=this._z,f=this._w,g=f*a._w+c*a._x+d*a._y+e*a._z;0>g?(this._w=-a._w,this._x=-a._x,this._y=-a._y,this._z=-a._z,g=-g):this.copy(a);if(1<=g)return this._w=f,this._x=c,this._y=d,this._z=e,this;var h=Math.acos(g),k=Math.sqrt(1-g*g);if(0.001>Math.abs(k))return this._w=0.5*(f+this._w),this._x=0.5*(c+this._x),this._y=0.5*(d+this._y),this._z=0.5*(e+this._z),this;g=Math.sin((1-b)*h)/k;h=Math.sin(b*h)/k;this._w=f*g+this._w*h;this._x= +c*g+this._x*h;this._y=d*g+this._y*h;this._z=e*g+this._z*h;this.onChangeCallback();return this},equals:function(a){return a._x===this._x&&a._y===this._y&&a._z===this._z&&a._w===this._w},fromArray:function(a){this._x=a[0];this._y=a[1];this._z=a[2];this._w=a[3];this.onChangeCallback();return this},toArray:function(){return[this._x,this._y,this._z,this._w]},onChange:function(a){this.onChangeCallback=a;return this},onChangeCallback:function(){},clone:function(){return new THREE.Quaternion(this._x,this._y, +this._z,this._w)}};THREE.Quaternion.slerp=function(a,b,c,d){return c.copy(a).slerp(b,d)};THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; +THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;default:throw Error("index is out of range: "+a);}},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;default:throw Error("index is out of range: "+a);}},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a, +b){if(void 0!==b)return console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addScalar:function(a){this.x+=a;this.y+=a;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;return this}, +subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},multiply:function(a){this.x*=a.x;this.y*=a.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this},divide:function(a){this.x/=a.x;this.y/=a.y;return this},divideScalar:function(a){0!==a?(a=1/a,this.x*=a,this.y*=a):this.y=this.x=0;return this},min:function(a){this.x>a.x&&(this.x=a.x);this.y>a.y&&(this.y=a.y);return this},max:function(a){this.xb.x&&(this.x=b.x);this.yb.y&&(this.y=b.y);return this},clampScalar:function(){var a,b;return function(c,d){void 0===a&&(a=new THREE.Vector2,b=new THREE.Vector2);a.set(c,c);b.set(d,d);return this.clamp(a,b)}}(),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=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);return this},negate:function(){this.x=-this.x;this.y=-this.y;return this},dot:function(a){return this.x*a.x+this.y*a.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)},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b= +this.x-a.x;a=this.y-a.y;return b*b+a*a},setLength:function(a){var b=this.length();0!==b&&a!==b&&this.multiplyScalar(a/b);return this},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},fromArray:function(a){this.x=a[0];this.y=a[1];return this},toArray:function(){return[this.x,this.y]},clone:function(){return new THREE.Vector2(this.x,this.y)}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; +THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;case 2:this.z=b;break;default:throw Error("index is out of range: "+a);}},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw Error("index is out of range: "+ +a);}},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;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},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."), +this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;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(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(a,b);this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;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 a;return function(b){!1===b instanceof THREE.Euler&&console.error("THREE.Vector3: .applyEuler() now expects a Euler rotation rather than a Vector3 and order.");void 0===a&&(a=new THREE.Quaternion);this.applyQuaternion(a.setFromEuler(b));return this}}(),applyAxisAngle:function(){var a;return function(b,c){void 0===a&&(a=new THREE.Quaternion);this.applyQuaternion(a.setFromAxisAngle(b,c));return this}}(),applyMatrix3:function(a){var b=this.x, +c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[3]*c+a[6]*d;this.y=a[1]*b+a[4]*c+a[7]*d;this.z=a[2]*b+a[5]*c+a[8]*d;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12];this.y=a[1]*b+a[5]*c+a[9]*d+a[13];this.z=a[2]*b+a[6]*c+a[10]*d+a[14];return this},applyProjection:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;var e=1/(a[3]*b+a[7]*c+a[11]*d+a[15]);this.x=(a[0]*b+a[4]*c+a[8]*d+a[12])*e;this.y=(a[1]*b+a[5]*c+a[9]*d+a[13])*e;this.z= +(a[2]*b+a[6]*c+a[10]*d+a[14])*e;return this},applyQuaternion:function(a){var b=this.x,c=this.y,d=this.z,e=a.x,f=a.y,g=a.z;a=a.w;var h=a*b+f*d-g*c,k=a*c+g*b-e*d,l=a*d+e*c-f*b,b=-e*b-f*c-g*d;this.x=h*a+b*-e+k*-g-l*-f;this.y=k*a+b*-f+l*-e-h*-g;this.z=l*a+b*-g+h*-f-k*-e;return this},transformDirection:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d;this.y=a[1]*b+a[5]*c+a[9]*d;this.z=a[2]*b+a[6]*c+a[10]*d;this.normalize();return this},divide:function(a){this.x/=a.x; +this.y/=a.y;this.z/=a.z;return this},divideScalar:function(a){0!==a?(a=1/a,this.x*=a,this.y*=a,this.z*=a):this.z=this.y=this.x=0;return this},min:function(a){this.x>a.x&&(this.x=a.x);this.y>a.y&&(this.y=a.y);this.z>a.z&&(this.z=a.z);return this},max:function(a){this.xb.x&&(this.x=b.x);this.yb.y&&(this.y=b.y);this.zb.z&&(this.z= +b.z);return this},clampScalar:function(){var a,b;return function(c,d){void 0===a&&(a=new THREE.Vector3,b=new THREE.Vector3);a.set(c,c,c);b.set(d,d,d);return this.clamp(a,b)}}(),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= +0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);this.z=0>this.z?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(a){return this.x*a.x+this.y*a.y+this.z*a.z},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)},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+ +Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){var b=this.length();0!==b&&a!==b&&this.multiplyScalar(a/b);return this},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},cross:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(a,b);var c=this.x,d=this.y,e=this.z;this.x=d*a.z-e*a.y;this.y= +e*a.x-c*a.z;this.z=c*a.y-d*a.x;return this},crossVectors:function(a,b){var c=a.x,d=a.y,e=a.z,f=b.x,g=b.y,h=b.z;this.x=d*h-e*g;this.y=e*f-c*h;this.z=c*g-d*f;return this},projectOnVector:function(){var a,b;return function(c){void 0===a&&(a=new THREE.Vector3);a.copy(c).normalize();b=this.dot(a);return this.copy(a).multiplyScalar(b)}}(),projectOnPlane:function(){var a;return function(b){void 0===a&&(a=new THREE.Vector3);a.copy(this).projectOnVector(b);return this.sub(a)}}(),reflect:function(){var a;return function(b){void 0=== +a&&(a=new THREE.Vector3);return this.sub(a.copy(b).multiplyScalar(2*this.dot(b)))}}(),angleTo:function(a){a=this.dot(a)/(this.length()*a.length());return Math.acos(THREE.Math.clamp(a,-1,1))},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,c=this.y-a.y;a=this.z-a.z;return b*b+c*c+a*a},setEulerFromRotationMatrix:function(a,b){console.error("THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.")}, +setEulerFromQuaternion:function(a,b){console.error("THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.")},getPositionFromMatrix:function(a){console.warn("THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().");return this.setFromMatrixPosition(a)},getScaleFromMatrix:function(a){console.warn("THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().");return this.setFromMatrixScale(a)},getColumnFromMatrix:function(a, +b){console.warn("THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().");return this.setFromMatrixColumn(a,b)},setFromMatrixPosition:function(a){this.x=a.elements[12];this.y=a.elements[13];this.z=a.elements[14];return this},setFromMatrixScale:function(a){var b=this.set(a.elements[0],a.elements[1],a.elements[2]).length(),c=this.set(a.elements[4],a.elements[5],a.elements[6]).length();a=this.set(a.elements[8],a.elements[9],a.elements[10]).length();this.x=b;this.y=c;this.z= +a;return this},setFromMatrixColumn:function(a,b){var c=4*a,d=b.elements;this.x=d[c];this.y=d[c+1];this.z=d[c+2];return this},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},fromArray:function(a){this.x=a[0];this.y=a[1];this.z=a[2];return this},toArray:function(){return[this.x,this.y,this.z]},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1}; +THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},setW:function(a){this.w=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;case 2:this.z=b;break;case 3:this.w=b;break;default:throw Error("index is out of range: "+a);}},getComponent:function(a){switch(a){case 0:return this.x; +case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw Error("index is out of range: "+a);}},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;this.w+=a;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},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;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(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},applyMatrix4:function(a){var b= +this.x,c=this.y,d=this.z,e=this.w;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12]*e;this.y=a[1]*b+a[5]*c+a[9]*d+a[13]*e;this.z=a[2]*b+a[6]*c+a[10]*d+a[14]*e;this.w=a[3]*b+a[7]*c+a[11]*d+a[15]*e;return this},divideScalar:function(a){0!==a?(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a):(this.z=this.y=this.x=0,this.w=1);return this},setAxisAngleFromQuaternion:function(a){this.w=2*Math.acos(a.w);var b=Math.sqrt(1-a.w*a.w);1E-4>b?(this.x=1,this.z=this.y=0):(this.x=a.x/b,this.y=a.y/b,this.z=a.z/b);return this}, +setAxisAngleFromRotationMatrix:function(a){var b,c,d;a=a.elements;var e=a[0];d=a[4];var f=a[8],g=a[1],h=a[5],k=a[9];c=a[2];b=a[6];var l=a[10];if(0.01>Math.abs(d-g)&&0.01>Math.abs(f-c)&&0.01>Math.abs(k-b)){if(0.1>Math.abs(d+g)&&0.1>Math.abs(f+c)&&0.1>Math.abs(k+b)&&0.1>Math.abs(e+h+l-3))return this.set(1,0,0,0),this;a=Math.PI;e=(e+1)/2;h=(h+1)/2;l=(l+1)/2;d=(d+g)/4;f=(f+c)/4;k=(k+b)/4;e>h&&e>l?0.01>e?(b=0,d=c=0.707106781):(b=Math.sqrt(e),c=d/b,d=f/b):h>l?0.01>h?(b=0.707106781,c=0,d=0.707106781):(c= +Math.sqrt(h),b=d/c,d=k/c):0.01>l?(c=b=0.707106781,d=0):(d=Math.sqrt(l),b=f/d,c=k/d);this.set(b,c,d,a);return this}a=Math.sqrt((b-k)*(b-k)+(f-c)*(f-c)+(g-d)*(g-d));0.001>Math.abs(a)&&(a=1);this.x=(b-k)/a;this.y=(f-c)/a;this.z=(g-d)/a;this.w=Math.acos((e+h+l-1)/2);return this},min:function(a){this.x>a.x&&(this.x=a.x);this.y>a.y&&(this.y=a.y);this.z>a.z&&(this.z=a.z);this.w>a.w&&(this.w=a.w);return this},max:function(a){this.xb.x&&(this.x=b.x);this.yb.y&&(this.y=b.y);this.zb.z&&(this.z=b.z);this.wb.w&&(this.w=b.w);return this},clampScalar:function(){var a,b;return function(c,d){void 0===a&&(a=new THREE.Vector4,b=new THREE.Vector4);a.set(c,c,c,c);b.set(d,d,d,d);return this.clamp(a,b)}}(),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=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);this.z=0>this.z?Math.ceil(this.z):Math.floor(this.z);this.w=0>this.w?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(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.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)},lengthManhattan: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())}, +setLength:function(a){var b=this.length();0!==b&&a!==b&&this.multiplyScalar(a/b);return this},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z&&a.w===this.w},fromArray:function(a){this.x=a[0];this.y=a[1];this.z=a[2];this.w=a[3];return this},toArray:function(){return[this.x,this.y,this.z,this.w]},clone:function(){return new THREE.Vector4(this.x,this.y,this.z, +this.w)}};THREE.Euler=function(a,b,c,d){this._x=a||0;this._y=b||0;this._z=c||0;this._order=d||THREE.Euler.DefaultOrder};THREE.Euler.RotationOrders="XYZ YZX ZXY XZY YXZ ZYX".split(" ");THREE.Euler.DefaultOrder="XYZ"; +THREE.Euler.prototype={constructor:THREE.Euler,_x:0,_y:0,_z:0,_order:THREE.Euler.DefaultOrder,get x(){return this._x},set x(a){this._x=a;this.onChangeCallback()},get y(){return this._y},set y(a){this._y=a;this.onChangeCallback()},get z(){return this._z},set z(a){this._z=a;this.onChangeCallback()},get order(){return this._order},set order(a){this._order=a;this.onChangeCallback()},set:function(a,b,c,d){this._x=a;this._y=b;this._z=c;this._order=d||this._order;this.onChangeCallback();return this},copy:function(a){this._x= +a._x;this._y=a._y;this._z=a._z;this._order=a._order;this.onChangeCallback();return this},setFromRotationMatrix:function(a,b){var c=THREE.Math.clamp,d=a.elements,e=d[0],f=d[4],g=d[8],h=d[1],k=d[5],l=d[9],n=d[2],q=d[6],d=d[10];b=b||this._order;"XYZ"===b?(this._y=Math.asin(c(g,-1,1)),0.99999>Math.abs(g)?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-f,e)):(this._x=Math.atan2(q,k),this._z=0)):"YXZ"===b?(this._x=Math.asin(-c(l,-1,1)),0.99999>Math.abs(l)?(this._y=Math.atan2(g,d),this._z=Math.atan2(h,k)): +(this._y=Math.atan2(-n,e),this._z=0)):"ZXY"===b?(this._x=Math.asin(c(q,-1,1)),0.99999>Math.abs(q)?(this._y=Math.atan2(-n,d),this._z=Math.atan2(-f,k)):(this._y=0,this._z=Math.atan2(h,e))):"ZYX"===b?(this._y=Math.asin(-c(n,-1,1)),0.99999>Math.abs(n)?(this._x=Math.atan2(q,d),this._z=Math.atan2(h,e)):(this._x=0,this._z=Math.atan2(-f,k))):"YZX"===b?(this._z=Math.asin(c(h,-1,1)),0.99999>Math.abs(h)?(this._x=Math.atan2(-l,k),this._y=Math.atan2(-n,e)):(this._x=0,this._y=Math.atan2(g,d))):"XZY"===b?(this._z= +Math.asin(-c(f,-1,1)),0.99999>Math.abs(f)?(this._x=Math.atan2(q,k),this._y=Math.atan2(g,e)):(this._x=Math.atan2(-l,d),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+b);this._order=b;this.onChangeCallback();return this},setFromQuaternion:function(a,b,c){var d=THREE.Math.clamp,e=a.x*a.x,f=a.y*a.y,g=a.z*a.z,h=a.w*a.w;b=b||this._order;"XYZ"===b?(this._x=Math.atan2(2*(a.x*a.w-a.y*a.z),h-e-f+g),this._y=Math.asin(d(2*(a.x*a.z+a.y*a.w),-1,1)),this._z=Math.atan2(2* +(a.z*a.w-a.x*a.y),h+e-f-g)):"YXZ"===b?(this._x=Math.asin(d(2*(a.x*a.w-a.y*a.z),-1,1)),this._y=Math.atan2(2*(a.x*a.z+a.y*a.w),h-e-f+g),this._z=Math.atan2(2*(a.x*a.y+a.z*a.w),h-e+f-g)):"ZXY"===b?(this._x=Math.asin(d(2*(a.x*a.w+a.y*a.z),-1,1)),this._y=Math.atan2(2*(a.y*a.w-a.z*a.x),h-e-f+g),this._z=Math.atan2(2*(a.z*a.w-a.x*a.y),h-e+f-g)):"ZYX"===b?(this._x=Math.atan2(2*(a.x*a.w+a.z*a.y),h-e-f+g),this._y=Math.asin(d(2*(a.y*a.w-a.x*a.z),-1,1)),this._z=Math.atan2(2*(a.x*a.y+a.z*a.w),h+e-f-g)):"YZX"=== +b?(this._x=Math.atan2(2*(a.x*a.w-a.z*a.y),h-e+f-g),this._y=Math.atan2(2*(a.y*a.w-a.x*a.z),h+e-f-g),this._z=Math.asin(d(2*(a.x*a.y+a.z*a.w),-1,1))):"XZY"===b?(this._x=Math.atan2(2*(a.x*a.w+a.y*a.z),h-e+f-g),this._y=Math.atan2(2*(a.x*a.z+a.y*a.w),h+e-f-g),this._z=Math.asin(d(2*(a.z*a.w-a.x*a.y),-1,1))):console.warn("THREE.Euler: .setFromQuaternion() given unsupported order: "+b);this._order=b;if(!1!==c)this.onChangeCallback();return this},reorder:function(){var a=new THREE.Quaternion;return function(b){a.setFromEuler(this); +this.setFromQuaternion(a,b)}}(),equals:function(a){return a._x===this._x&&a._y===this._y&&a._z===this._z&&a._order===this._order},fromArray:function(a){this._x=a[0];this._y=a[1];this._z=a[2];void 0!==a[3]&&(this._order=a[3]);this.onChangeCallback();return this},toArray:function(){return[this._x,this._y,this._z,this._order]},onChange:function(a){this.onChangeCallback=a;return this},onChangeCallback:function(){},clone:function(){return new THREE.Euler(this._x,this._y,this._z,this._order)}}; +THREE.Line3=function(a,b){this.start=void 0!==a?a:new THREE.Vector3;this.end=void 0!==b?b:new THREE.Vector3}; +THREE.Line3.prototype={constructor:THREE.Line3,set:function(a,b){this.start.copy(a);this.end.copy(b);return this},copy:function(a){this.start.copy(a.start);this.end.copy(a.end);return this},center:function(a){return(a||new THREE.Vector3).addVectors(this.start,this.end).multiplyScalar(0.5)},delta:function(a){return(a||new THREE.Vector3).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(a, +b){var c=b||new THREE.Vector3;return this.delta(c).multiplyScalar(a).add(this.start)},closestPointToPointParameter:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c,d){a.subVectors(c,this.start);b.subVectors(this.end,this.start);var e=b.dot(b),e=b.dot(a)/e;d&&(e=THREE.Math.clamp(e,0,1));return e}}(),closestPointToPoint:function(a,b,c){a=this.closestPointToPointParameter(a,b);c=c||new THREE.Vector3;return this.delta(c).multiplyScalar(a).add(this.start)},applyMatrix4:function(a){this.start.applyMatrix4(a); +this.end.applyMatrix4(a);return this},equals:function(a){return a.start.equals(this.start)&&a.end.equals(this.end)},clone:function(){return(new THREE.Line3).copy(this)}};THREE.Box2=function(a,b){this.min=void 0!==a?a:new THREE.Vector2(Infinity,Infinity);this.max=void 0!==b?b:new THREE.Vector2(-Infinity,-Infinity)}; +THREE.Box2.prototype={constructor:THREE.Box2,set:function(a,b){this.min.copy(a);this.max.copy(b);return this},setFromPoints:function(a){this.makeEmpty();for(var b=0,c=a.length;bthis.max.x||a.ythis.max.y?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y?!0:!1},getParameter:function(a,b){return(b||new THREE.Vector2).set((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y))},isIntersectionBox:function(a){return a.max.xthis.max.x||a.max.y +this.max.y?!1:!0},clampPoint:function(a,b){return(b||new THREE.Vector2).copy(a).clamp(this.min,this.max)},distanceToPoint:function(){var a=new THREE.Vector2;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&& +a.max.equals(this.max)},clone:function(){return(new THREE.Box2).copy(this)}};THREE.Box3=function(a,b){this.min=void 0!==a?a:new THREE.Vector3(Infinity,Infinity,Infinity);this.max=void 0!==b?b:new THREE.Vector3(-Infinity,-Infinity,-Infinity)}; +THREE.Box3.prototype={constructor:THREE.Box3,set:function(a,b){this.min.copy(a);this.max.copy(b);return this},setFromPoints:function(a){this.makeEmpty();for(var b=0,c=a.length;bthis.max.x||a.ythis.max.y|| +a.zthis.max.z?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y&&this.min.z<=a.min.z&&a.max.z<=this.max.z?!0:!1},getParameter:function(a,b){return(b||new THREE.Vector3).set((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y),(a.z-this.min.z)/(this.max.z-this.min.z))},isIntersectionBox:function(a){return a.max.xthis.max.x||a.max.ythis.max.y|| +a.max.zthis.max.z?!1:!0},clampPoint:function(a,b){return(b||new THREE.Vector3).copy(a).clamp(this.min,this.max)},distanceToPoint:function(){var a=new THREE.Vector3;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),getBoundingSphere:function(){var a=new THREE.Vector3;return function(b){b=b||new THREE.Sphere;b.center=this.center();b.radius=0.5*this.size(a).length();return b}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);return this}, +union:function(a){this.min.min(a.min);this.max.max(a.max);return this},applyMatrix4:function(){var a=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];return function(b){a[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(b);a[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(b);a[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(b);a[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(b); +a[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(b);a[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(b);a[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(b);a[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(b);this.makeEmpty();this.setFromPoints(a);return this}}(),translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)},clone:function(){return(new THREE.Box3).copy(this)}}; +THREE.Matrix3=function(a,b,c,d,e,f,g,h,k){var l=this.elements=new Float32Array(9);l[0]=void 0!==a?a:1;l[3]=b||0;l[6]=c||0;l[1]=d||0;l[4]=void 0!==e?e:1;l[7]=f||0;l[2]=g||0;l[5]=h||0;l[8]=void 0!==k?k:1}; +THREE.Matrix3.prototype={constructor:THREE.Matrix3,set:function(a,b,c,d,e,f,g,h,k){var l=this.elements;l[0]=a;l[3]=b;l[6]=c;l[1]=d;l[4]=e;l[7]=f;l[2]=g;l[5]=h;l[8]=k;return this},identity:function(){this.set(1,0,0,0,1,0,0,0,1);return this},copy:function(a){a=a.elements;this.set(a[0],a[3],a[6],a[1],a[4],a[7],a[2],a[5],a[8]);return this},multiplyVector3:function(a){console.warn("THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.");return a.applyMatrix3(this)}, +multiplyVector3Array:function(a){console.warn("THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.");return this.applyToVector3Array(a)},applyToVector3Array:function(){var a=new THREE.Vector3;return function(b,c,d){void 0===c&&(c=0);void 0===d&&(d=b.length);for(var e=0;ethis.determinant()&&(g=-g);c.x=f[12];c.y=f[13];c.z=f[14];b.elements.set(this.elements);c=1/g;var f=1/h,l=1/k;b.elements[0]*=c;b.elements[1]*= +c;b.elements[2]*=c;b.elements[4]*=f;b.elements[5]*=f;b.elements[6]*=f;b.elements[8]*=l;b.elements[9]*=l;b.elements[10]*=l;d.setFromRotationMatrix(b);e.x=g;e.y=h;e.z=k;return this}}(),makeFrustum:function(a,b,c,d,e,f){var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(d-c);g[9]=(d+c)/(d-c);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makePerspective:function(a,b,c,d){a=c*Math.tan(THREE.Math.degToRad(0.5*a)); +var e=-a;return this.makeFrustum(e*b,a*b,e,a,c,d)},makeOrthographic:function(a,b,c,d,e,f){var g=this.elements,h=b-a,k=c-d,l=f-e;g[0]=2/h;g[4]=0;g[8]=0;g[12]=-((b+a)/h);g[1]=0;g[5]=2/k;g[9]=0;g[13]=-((c+d)/k);g[2]=0;g[6]=0;g[10]=-2/l;g[14]=-((f+e)/l);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},fromArray:function(a){this.elements.set(a);return this},toArray:function(){var a=this.elements;return[a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15]]},clone:function(){var a= +this.elements;return new THREE.Matrix4(a[0],a[4],a[8],a[12],a[1],a[5],a[9],a[13],a[2],a[6],a[10],a[14],a[3],a[7],a[11],a[15])}};THREE.Ray=function(a,b){this.origin=void 0!==a?a:new THREE.Vector3;this.direction=void 0!==b?b:new THREE.Vector3}; +THREE.Ray.prototype={constructor:THREE.Ray,set:function(a,b){this.origin.copy(a);this.direction.copy(b);return this},copy:function(a){this.origin.copy(a.origin);this.direction.copy(a.direction);return this},at:function(a,b){return(b||new THREE.Vector3).copy(this.direction).multiplyScalar(a).add(this.origin)},recast:function(){var a=new THREE.Vector3;return function(b){this.origin.copy(this.at(b,a));return this}}(),closestPointToPoint:function(a,b){var c=b||new THREE.Vector3;c.subVectors(a,this.origin); +var d=c.dot(this.direction);return 0>d?c.copy(this.origin):c.copy(this.direction).multiplyScalar(d).add(this.origin)},distanceToPoint:function(){var a=new THREE.Vector3;return function(b){var c=a.subVectors(b,this.origin).dot(this.direction);if(0>c)return this.origin.distanceTo(b);a.copy(this.direction).multiplyScalar(c).add(this.origin);return a.distanceTo(b)}}(),distanceSqToSegment:function(a,b,c,d){var e=a.clone().add(b).multiplyScalar(0.5),f=b.clone().sub(a).normalize(),g=0.5*a.distanceTo(b), +h=this.origin.clone().sub(e);a=-this.direction.dot(f);b=h.dot(this.direction);var k=-h.dot(f),l=h.lengthSq(),n=Math.abs(1-a*a),q,r;0<=n?(h=a*k-b,q=a*b-k,r=g*n,0<=h?q>=-r?q<=r?(g=1/n,h*=g,q*=g,a=h*(h+a*q+2*b)+q*(a*h+q+2*k)+l):(q=g,h=Math.max(0,-(a*q+b)),a=-h*h+q*(q+2*k)+l):(q=-g,h=Math.max(0,-(a*q+b)),a=-h*h+q*(q+2*k)+l):q<=-r?(h=Math.max(0,-(-a*g+b)),q=0f)return null;f=Math.sqrt(f-e);e=d-f; +d+=f;return 0>e&&0>d?null:0>e?this.at(d,c):this.at(e,c)}}(),isIntersectionPlane:function(a){var b=a.distanceToPoint(this.origin);return 0===b||0>a.normal.dot(this.direction)*b?!0:!1},distanceToPlane:function(a){var b=a.normal.dot(this.direction);if(0==b)return 0==a.distanceToPoint(this.origin)?0:null;a=-(this.origin.dot(a.normal)+a.constant)/b;return 0<=a?a:null},intersectPlane:function(a,b){var c=this.distanceToPlane(a);return null===c?null:this.at(c,b)},isIntersectionBox:function(){var a=new THREE.Vector3; +return function(b){return null!==this.intersectBox(b,a)}}(),intersectBox:function(a,b){var c,d,e,f,g;d=1/this.direction.x;f=1/this.direction.y;g=1/this.direction.z;var h=this.origin;0<=d?(c=(a.min.x-h.x)*d,d*=a.max.x-h.x):(c=(a.max.x-h.x)*d,d*=a.min.x-h.x);0<=f?(e=(a.min.y-h.y)*f,f*=a.max.y-h.y):(e=(a.max.y-h.y)*f,f*=a.min.y-h.y);if(c>f||e>d)return null;if(e>c||c!==c)c=e;if(fg||e>d)return null;if(e>c||c!== +c)c=e;if(gd?null:this.at(0<=c?c:d,b)},intersectTriangle:function(){var a=new THREE.Vector3,b=new THREE.Vector3,c=new THREE.Vector3,d=new THREE.Vector3;return function(e,f,g,h,k){b.subVectors(f,e);c.subVectors(g,e);d.crossVectors(b,c);f=this.direction.dot(d);if(0f)h=-1,f=-f;else return null;a.subVectors(this.origin,e);e=h*this.direction.dot(c.crossVectors(a,c));if(0>e)return null;g=h*this.direction.dot(b.cross(a));if(0>g||e+g>f)return null; +e=-h*a.dot(d);return 0>e?null:this.at(e/f,k)}}(),applyMatrix4:function(a){this.direction.add(this.origin).applyMatrix4(a);this.origin.applyMatrix4(a);this.direction.sub(this.origin);this.direction.normalize();return this},equals:function(a){return a.origin.equals(this.origin)&&a.direction.equals(this.direction)},clone:function(){return(new THREE.Ray).copy(this)}};THREE.Sphere=function(a,b){this.center=void 0!==a?a:new THREE.Vector3;this.radius=void 0!==b?b:0}; +THREE.Sphere.prototype={constructor:THREE.Sphere,set:function(a,b){this.center.copy(a);this.radius=b;return this},setFromPoints:function(){var a=new THREE.Box3;return function(b,c){var d=this.center;void 0!==c?d.copy(c):a.setFromPoints(b).center(d);for(var e=0,f=0,g=b.length;f=this.radius},containsPoint:function(a){return a.distanceToSquared(this.center)<= +this.radius*this.radius},distanceToPoint:function(a){return a.distanceTo(this.center)-this.radius},intersectsSphere:function(a){var b=this.radius+a.radius;return a.center.distanceToSquared(this.center)<=b*b},clampPoint:function(a,b){var c=this.center.distanceToSquared(a),d=b||new THREE.Vector3;d.copy(a);c>this.radius*this.radius&&(d.sub(this.center).normalize(),d.multiplyScalar(this.radius).add(this.center));return d},getBoundingBox:function(a){a=a||new THREE.Box3;a.set(this.center,this.center);a.expandByScalar(this.radius); +return a},applyMatrix4:function(a){this.center.applyMatrix4(a);this.radius*=a.getMaxScaleOnAxis();return this},translate:function(a){this.center.add(a);return this},equals:function(a){return a.center.equals(this.center)&&a.radius===this.radius},clone:function(){return(new THREE.Sphere).copy(this)}}; +THREE.Frustum=function(a,b,c,d,e,f){this.planes=[void 0!==a?a:new THREE.Plane,void 0!==b?b:new THREE.Plane,void 0!==c?c:new THREE.Plane,void 0!==d?d:new THREE.Plane,void 0!==e?e:new THREE.Plane,void 0!==f?f:new THREE.Plane]}; +THREE.Frustum.prototype={constructor:THREE.Frustum,set:function(a,b,c,d,e,f){var g=this.planes;g[0].copy(a);g[1].copy(b);g[2].copy(c);g[3].copy(d);g[4].copy(e);g[5].copy(f);return this},copy:function(a){for(var b=this.planes,c=0;6>c;c++)b[c].copy(a.planes[c]);return this},setFromMatrix:function(a){var b=this.planes,c=a.elements;a=c[0];var d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],k=c[6],l=c[7],n=c[8],q=c[9],r=c[10],t=c[11],s=c[12],p=c[13],v=c[14],c=c[15];b[0].setComponents(f-a,l-g,t-n,c-s).normalize();b[1].setComponents(f+ +a,l+g,t+n,c+s).normalize();b[2].setComponents(f+d,l+h,t+q,c+p).normalize();b[3].setComponents(f-d,l-h,t-q,c-p).normalize();b[4].setComponents(f-e,l-k,t-r,c-v).normalize();b[5].setComponents(f+e,l+k,t+r,c+v).normalize();return this},intersectsObject:function(){var a=new THREE.Sphere;return function(b){var c=b.geometry;null===c.boundingSphere&&c.computeBoundingSphere();a.copy(c.boundingSphere);a.applyMatrix4(b.matrixWorld);return this.intersectsSphere(a)}}(),intersectsSphere:function(a){var b=this.planes, +c=a.center;a=-a.radius;for(var d=0;6>d;d++)if(b[d].distanceToPoint(c)e;e++){var f=d[e];a.x=0g&&0>f)return!1}return!0}}(), +containsPoint:function(a){for(var b=this.planes,c=0;6>c;c++)if(0>b[c].distanceToPoint(a))return!1;return!0},clone:function(){return(new THREE.Frustum).copy(this)}};THREE.Plane=function(a,b){this.normal=void 0!==a?a:new THREE.Vector3(1,0,0);this.constant=void 0!==b?b:0}; +THREE.Plane.prototype={constructor:THREE.Plane,set:function(a,b){this.normal.copy(a);this.constant=b;return this},setComponents:function(a,b,c,d){this.normal.set(a,b,c);this.constant=d;return this},setFromNormalAndCoplanarPoint:function(a,b){this.normal.copy(a);this.constant=-b.dot(this.normal);return this},setFromCoplanarPoints:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c,d,e){d=a.subVectors(e,d).cross(b.subVectors(c,d)).normalize();this.setFromNormalAndCoplanarPoint(d, +c);return this}}(),copy:function(a){this.normal.copy(a.normal);this.constant=a.constant;return this},normalize:function(){var a=1/this.normal.length();this.normal.multiplyScalar(a);this.constant*=a;return this},negate:function(){this.constant*=-1;this.normal.negate();return this},distanceToPoint:function(a){return this.normal.dot(a)+this.constant},distanceToSphere:function(a){return this.distanceToPoint(a.center)-a.radius},projectPoint:function(a,b){return this.orthoPoint(a,b).sub(a).negate()},orthoPoint:function(a, +b){var c=this.distanceToPoint(a);return(b||new THREE.Vector3).copy(this.normal).multiplyScalar(c)},isIntersectionLine:function(a){var b=this.distanceToPoint(a.start);a=this.distanceToPoint(a.end);return 0>b&&0a&&0f||1e;e++)8==e||13==e||18==e||23==e?b[e]="-":14==e?b[e]="4":(2>=c&&(c=33554432+16777216*Math.random()|0),d=c&15,c>>=4,b[e]=a[19==e?d&3|8:d]);return b.join("")}}(),clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return a=c)return 1;a=(a-b)/(c-b);return a*a*(3-2*a)},smootherstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*a*(a*(6*a-15)+10)},random16:function(){return(65280*Math.random()+255*Math.random())/65535},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,b){return a+Math.random()*(b-a)},randFloatSpread:function(a){return a*(0.5-Math.random())},sign:function(a){return 0>a?-1:0this.points.length-2?this.points.length-1:f+1;c[3]=f>this.points.length-3?this.points.length-1: +f+2;l=this.points[c[0]];n=this.points[c[1]];q=this.points[c[2]];r=this.points[c[3]];h=g*g;k=g*h;d.x=b(l.x,n.x,q.x,r.x,g,h,k);d.y=b(l.y,n.y,q.y,r.y,g,h,k);d.z=b(l.z,n.z,q.z,r.z,g,h,k);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;a=b.x+b.y}}(); +THREE.Triangle.prototype={constructor:THREE.Triangle,set:function(a,b,c){this.a.copy(a);this.b.copy(b);this.c.copy(c);return this},setFromPointsAndIndices:function(a,b,c,d){this.a.copy(a[b]);this.b.copy(a[c]);this.c.copy(a[d]);return this},copy:function(a){this.a.copy(a.a);this.b.copy(a.b);this.c.copy(a.c);return this},area:function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(){a.subVectors(this.c,this.b);b.subVectors(this.a,this.b);return 0.5*a.cross(b).length()}}(),midpoint:function(a){return(a|| +new THREE.Vector3).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(a){return THREE.Triangle.normal(this.a,this.b,this.c,a)},plane:function(a){return(a||new THREE.Plane).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(a,b){return THREE.Triangle.barycoordFromPoint(a,this.a,this.b,this.c,b)},containsPoint:function(a){return THREE.Triangle.containsPoint(a,this.a,this.b,this.c)},equals:function(a){return a.a.equals(this.a)&&a.b.equals(this.b)&&a.c.equals(this.c)}, +clone:function(){return(new THREE.Triangle).copy(this)}};THREE.Clock=function(a){this.autoStart=void 0!==a?a:!0;this.elapsedTime=this.oldTime=this.startTime=0;this.running=!1}; +THREE.Clock.prototype={constructor:THREE.Clock,start:function(){this.oldTime=this.startTime=void 0!==self.performance&&void 0!==self.performance.now?self.performance.now():Date.now();this.running=!0},stop:function(){this.getElapsedTime();this.running=!1},getElapsedTime:function(){this.getDelta();return this.elapsedTime},getDelta:function(){var a=0;this.autoStart&&!this.running&&this.start();if(this.running){var b=void 0!==self.performance&&void 0!==self.performance.now?self.performance.now():Date.now(), +a=0.001*(b-this.oldTime);this.oldTime=b;this.elapsedTime+=a}return a}};THREE.EventDispatcher=function(){}; +THREE.EventDispatcher.prototype={constructor:THREE.EventDispatcher,apply:function(a){a.addEventListener=THREE.EventDispatcher.prototype.addEventListener;a.hasEventListener=THREE.EventDispatcher.prototype.hasEventListener;a.removeEventListener=THREE.EventDispatcher.prototype.removeEventListener;a.dispatchEvent=THREE.EventDispatcher.prototype.dispatchEvent},addEventListener:function(a,b){void 0===this._listeners&&(this._listeners={});var c=this._listeners;void 0===c[a]&&(c[a]=[]);-1===c[a].indexOf(b)&& +c[a].push(b)},hasEventListener:function(a,b){if(void 0===this._listeners)return!1;var c=this._listeners;return void 0!==c[a]&&-1!==c[a].indexOf(b)?!0:!1},removeEventListener:function(a,b){if(void 0!==this._listeners){var c=this._listeners[a];if(void 0!==c){var d=c.indexOf(b);-1!==d&&c.splice(d,1)}}},dispatchEvent:function(a){if(void 0!==this._listeners){var b=this._listeners[a.type];if(void 0!==b){a.target=this;for(var c=[],d=b.length,e=0;ee&&0>f||0>g&&0>h)return!1;0>e?c=Math.max(c,e/(e-f)):0>f&&(d=Math.min(d,e/(e-f)));0>g?c=Math.max(c,g/(g-h)):0>h&&(d=Math.min(d,g/(g-h)));if(d=c.x&&-1<=c.y&&1>=c.y&&-1<=c.z&&1>=c.z},l=function(a, +b,c){if(!0===a.visible||!0===b.visible||!0===c.visible)return!0;L[0]=a.positionScreen;L[1]=b.positionScreen;L[2]=c.positionScreen;return E.isIntersectionBox(Q.setFromPoints(L))},q=function(a,b,c){return 0>(c.positionScreen.x-a.positionScreen.x)*(b.positionScreen.y-a.positionScreen.y)-(c.positionScreen.y-a.positionScreen.y)*(b.positionScreen.x-a.positionScreen.x)};return{setObject:function(a){f=a;g=f.material;h.getNormalMatrix(f.matrixWorld);d.length=0;e.length=0},projectVertex:k,checkTriangleVisibility:l, +checkBackfaceCulling:q,pushVertex:function(b,c,d){n=a();n.position.set(b,c,d);k(n)},pushNormal:function(a,b,c){d.push(a,b,c)},pushUv:function(a,b){e.push(a,b)},pushLine:function(a,b){var d=r[a],e=r[b];u=c();u.id=f.id;u.v1.copy(d);u.v2.copy(e);u.z=(d.positionScreen.z+e.positionScreen.z)/2;u.material=f.material;K.elements.push(u)},pushTriangle:function(a,c,k){var n=r[a],p=r[c],t=r[k];if(!1!==l(n,p,t)&&(g.side===THREE.DoubleSide||!0===q(n,p,t))){s=b();s.id=f.id;s.v1.copy(n);s.v2.copy(p);s.v3.copy(t); +s.z=(n.positionScreen.z+p.positionScreen.z+t.positionScreen.z)/3;for(n=0;3>n;n++)p=3*arguments[n],t=s.vertexNormalsModel[n],t.set(d[p],d[p+1],d[p+2]),t.applyMatrix3(h).normalize(),p=2*arguments[n],s.uvs[n].set(e[p],e[p+1]);s.vertexNormalsLength=3;s.material=f.material;K.elements.push(s)}}}};this.projectScene=function(n,t,w,v){I=D=p=0;K.elements.length=0;!0===n.autoUpdate&&n.updateMatrixWorld();void 0===t.parent&&t.updateMatrixWorld();R.copy(t.matrixWorldInverse.getInverse(t.matrixWorld));B.multiplyMatrices(t.projectionMatrix, +R);H.setFromMatrix(B);h=0;K.objects.length=0;K.lights.length=0;n.traverseVisible(function(a){if(a instanceof THREE.Light)K.lights.push(a);else if(a instanceof THREE.Mesh||a instanceof THREE.Line||a instanceof THREE.Sprite)if(!1===a.frustumCulled||!0===H.intersectsObject(a)){if(h===l){var b=new THREE.RenderableObject;k.push(b);l++;h++;g=b}else g=k[h++];g.id=a.id;g.object=a;null!==a.renderDepth?g.z=a.renderDepth:(O.setFromMatrixPosition(a.matrixWorld),O.applyProjection(B),g.z=O.z);K.objects.push(g)}}); +!0===w&&K.objects.sort(e);n=0;for(w=K.objects.length;nva;va++)s.uvs[va].copy(ua[va]); +s.color=ca.color;s.material=qa;s.z=(la.positionScreen.z+ja.positionScreen.z+Fa.positionScreen.z)/3;K.elements.push(s)}}}}}else if(A instanceof THREE.Line)if(x instanceof THREE.BufferGeometry){if(z=x.attributes,void 0!==z.position){G=z.position.array;x=0;for(y=G.length;x=J.z&&(C=d(),C.id=A.id,C.x=J.x*x,C.y=J.y*x,C.z=J.z,C.object=A,C.rotation=A.rotation,C.scale.x=A.scale.x*Math.abs(C.x-(J.x+t.projectionMatrix.elements[0])/(J.w+t.projectionMatrix.elements[12])),C.scale.y=A.scale.y*Math.abs(C.y-(J.y+t.projectionMatrix.elements[5])/ +(J.w+t.projectionMatrix.elements[13])),C.material=A.material,K.elements.push(C)))}!0===v&&K.elements.sort(e);return K}};THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=void 0!==f?f:0}; +THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.materialIndex=this.materialIndex;for(var b=0,c=this.vertexNormals.length;bb.max.x&&(b.max.x=e);fb.max.y&& +(b.max.y=f);gb.max.z&&(b.max.z=g)}}if(void 0===a||0===a.length)this.boundingBox.min.set(0,0,0),this.boundingBox.max.set(0,0,0);(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.')},computeBoundingSphere:function(){var a=new THREE.Box3,b=new THREE.Vector3;return function(){null===this.boundingSphere&& +(this.boundingSphere=new THREE.Sphere);var c=this.attributes.position.array;if(c){a.makeEmpty();for(var d=this.boundingSphere.center,e=0,f=c.length;eBa?-1:1;h[4*a]=Ea.x;h[4*a+1]=Ea.y;h[4*a+2]=Ea.z;h[4*a+3]=Pa}if(void 0===this.attributes.index||void 0===this.attributes.position||void 0===this.attributes.normal||void 0===this.attributes.uv)console.warn("Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()");else{var c=this.attributes.index.array,d=this.attributes.position.array,e=this.attributes.normal.array,f=this.attributes.uv.array,g=d.length/3;void 0===this.attributes.tangent&&(this.attributes.tangent= +{itemSize:4,array:new Float32Array(4*g)});for(var h=this.attributes.tangent.array,k=[],l=[],n=0;np;p++)s=a[3*c+p],-1==r[s]?(q[2*p]=s,q[2*p+1]=-1,n++):r[s]k.index+b)for(k={start:f,count:0,index:g},h.push(k),n=0;6>n;n+=2)p=q[n+1],-1n;n+=2)s=q[n],p=q[n+1],-1===p&&(p=g++),r[s]=p,t[p]=s,e[f++]=p-k.index,k.count++}this.reorderBuffers(e,t,g);return this.offsets=h},merge:function(){console.log("BufferGeometry.merge(): TODO")},normalizeNormals:function(){for(var a=this.attributes.normal.array, +b,c,d,e=0,f=a.length;ed?-1:1,e.vertexTangents[c]=new THREE.Vector4(A.x,A.y,A.z,d);this.hasTangents=!0},computeLineDistances:function(){for(var a=0,b=this.vertices,c=0,d=b.length;cd;d++)if(e[d]==e[(d+1)%3]){a.push(f);break}for(f=a.length-1;0<=f;f--)for(e=a[f],this.faces.splice(e,1),c=0,g=this.faceVertexUvs.length;cc&&(h[f].counter+=1,g=h[f].hash+"_"+h[f].counter,g in this.geometryGroups||(k={id:a++,faces3:[],materialIndex:f,vertices:0,numMorphTargets:l,numMorphNormals:n},this.geometryGroups[g]=k,this.geometryGroupsList.push(k))),this.geometryGroups[g].faces3.push(d),this.geometryGroups[g].vertices+=3}}(),clone:function(){for(var a=new THREE.Geometry,b=this.vertices,c=0,d=b.length;ca.opacity)h.transparent=a.transparent;void 0!==a.depthTest&&(h.depthTest=a.depthTest);void 0!==a.depthWrite&&(h.depthWrite=a.depthWrite);void 0!==a.visible&&(h.visible=a.visible);void 0!==a.flipSided&&(h.side=THREE.BackSide);void 0!==a.doubleSided&&(h.side=THREE.DoubleSide);void 0!==a.wireframe&&(h.wireframe=a.wireframe);void 0!==a.vertexColors&&("face"=== +a.vertexColors?h.vertexColors=THREE.FaceColors:a.vertexColors&&(h.vertexColors=THREE.VertexColors));a.colorDiffuse?h.color=e(a.colorDiffuse):a.DbgColor&&(h.color=a.DbgColor);a.colorSpecular&&(h.specular=e(a.colorSpecular));a.colorAmbient&&(h.ambient=e(a.colorAmbient));a.colorEmissive&&(h.emissive=e(a.colorEmissive));a.transparency&&(h.opacity=a.transparency);a.specularCoef&&(h.shininess=a.specularCoef);a.mapDiffuse&&b&&d(h,"map",a.mapDiffuse,a.mapDiffuseRepeat,a.mapDiffuseOffset,a.mapDiffuseWrap, +a.mapDiffuseAnisotropy);a.mapLight&&b&&d(h,"lightMap",a.mapLight,a.mapLightRepeat,a.mapLightOffset,a.mapLightWrap,a.mapLightAnisotropy);a.mapBump&&b&&d(h,"bumpMap",a.mapBump,a.mapBumpRepeat,a.mapBumpOffset,a.mapBumpWrap,a.mapBumpAnisotropy);a.mapNormal&&b&&d(h,"normalMap",a.mapNormal,a.mapNormalRepeat,a.mapNormalOffset,a.mapNormalWrap,a.mapNormalAnisotropy);a.mapSpecular&&b&&d(h,"specularMap",a.mapSpecular,a.mapSpecularRepeat,a.mapSpecularOffset,a.mapSpecularWrap,a.mapSpecularAnisotropy);a.mapAlpha&& +b&&d(h,"alphaMap",a.mapAlpha,a.mapAlphaRepeat,a.mapAlphaOffset,a.mapAlphaWrap,a.mapAlphaAnisotropy);a.mapBumpScale&&(h.bumpScale=a.mapBumpScale);a.mapNormal?(g=THREE.ShaderLib.normalmap,k=THREE.UniformsUtils.clone(g.uniforms),k.tNormal.value=h.normalMap,a.mapNormalFactor&&k.uNormalScale.value.set(a.mapNormalFactor,a.mapNormalFactor),h.map&&(k.tDiffuse.value=h.map,k.enableDiffuse.value=!0),h.specularMap&&(k.tSpecular.value=h.specularMap,k.enableSpecular.value=!0),h.lightMap&&(k.tAO.value=h.lightMap, +k.enableAO.value=!0),k.diffuse.value.setHex(h.color),k.specular.value.setHex(h.specular),k.ambient.value.setHex(h.ambient),k.shininess.value=h.shininess,void 0!==h.opacity&&(k.opacity.value=h.opacity),g=new THREE.ShaderMaterial({fragmentShader:g.fragmentShader,vertexShader:g.vertexShader,uniforms:k,lights:!0,fog:!0}),h.transparent&&(g.transparent=!0)):g=new THREE[g](h);void 0!==a.DbgName&&(g.name=a.DbgName);return g}}; +THREE.Loader.Handlers={handlers:[],add:function(a,b){this.handlers.push(a,b)},get:function(a){for(var b=0,c=this.handlers.length;bg;g++)r=u[k++],w=v[2*r],r=v[2*r+1],w=new THREE.Vector2(w,r),2!==g&&c.faceVertexUvs[d][h].push(w),0!==g&&c.faceVertexUvs[d][h+1].push(w);q&&(q=3*u[k++],t.normal.set(D[q++],D[q++],D[q]),p.normal.copy(t.normal));if(s)for(d=0;4>d;d++)q=3*u[k++],s=new THREE.Vector3(D[q++], +D[q++],D[q]),2!==d&&t.vertexNormals.push(s),0!==d&&p.vertexNormals.push(s);n&&(n=u[k++],n=A[n],t.color.setHex(n),p.color.setHex(n));if(b)for(d=0;4>d;d++)n=u[k++],n=A[n],2!==d&&t.vertexColors.push(new THREE.Color(n)),0!==d&&p.vertexColors.push(new THREE.Color(n));c.faces.push(t);c.faces.push(p)}else{t=new THREE.Face3;t.a=u[k++];t.b=u[k++];t.c=u[k++];h&&(h=u[k++],t.materialIndex=h);h=c.faces.length;if(d)for(d=0;dg;g++)r=u[k++],w=v[2*r],r=v[2*r+1], +w=new THREE.Vector2(w,r),c.faceVertexUvs[d][h].push(w);q&&(q=3*u[k++],t.normal.set(D[q++],D[q++],D[q]));if(s)for(d=0;3>d;d++)q=3*u[k++],s=new THREE.Vector3(D[q++],D[q++],D[q]),t.vertexNormals.push(s);n&&(n=u[k++],t.color.setHex(A[n]));if(b)for(d=0;3>d;d++)n=u[k++],t.vertexColors.push(new THREE.Color(A[n]));c.faces.push(t)}})(d);(function(){var b=void 0!==a.influencesPerVertex?a.influencesPerVertex:2;if(a.skinWeights)for(var d=0,g=a.skinWeights.length;df)){var r=b.origin.distanceTo(l);rd.far||e.push({distance:r,point:k.clone().applyMatrix4(this.matrixWorld),face:null,faceIndex:null,object:this})}}}();THREE.Line.prototype.clone=function(a){void 0===a&&(a=new THREE.Line(this.geometry,this.material,this.type));THREE.Object3D.prototype.clone.call(this,a);return a}; +THREE.Mesh=function(a,b){THREE.Object3D.call(this);this.geometry=void 0!==a?a:new THREE.Geometry;this.material=void 0!==b?b:new THREE.MeshBasicMaterial({color:16777215*Math.random()});this.updateMorphTargets()};THREE.Mesh.prototype=Object.create(THREE.Object3D.prototype); +THREE.Mesh.prototype.updateMorphTargets=function(){if(void 0!==this.geometry.morphTargets&&0g.far||h.push({distance:C,point:x,indices:[n,q,r],face:null,faceIndex:null,object:this})}}}else for(p=n.position.array,s=k=0,A=p.length;kg.far||h.push({distance:C,point:x,indices:[n,q,r],face:null,faceIndex:null,object:this}))}}else if(k instanceof THREE.Geometry)for(s=this.material instanceof THREE.MeshFaceMaterial,p=!0===s?this.material.materials:null,t=g.precision,v=k.vertices,w=0,u=k.faces.length;wg.far||h.push({distance:C,point:x,face:D,faceIndex:w,object:this}))}}}();THREE.Mesh.prototype.clone=function(a,b){void 0===a&&(a=new THREE.Mesh(this.geometry,this.material));THREE.Object3D.prototype.clone.call(this,a,b);return a};THREE.Bone=function(a){THREE.Object3D.call(this);this.skin=a;this.accumulatedSclWeight=this.accumulatedPosWeight=this.accumulatedRotWeight=0};THREE.Bone.prototype=Object.create(THREE.Object3D.prototype); +THREE.Bone.prototype.updateMatrixWorld=function(a){THREE.Object3D.prototype.updateMatrixWorld.call(this,a);this.accumulatedSclWeight=this.accumulatedPosWeight=this.accumulatedRotWeight=0}; +THREE.Skeleton=function(a,b,c){this.useVertexTexture=void 0!==c?c:!0;this.identityMatrix=new THREE.Matrix4;a=a||[];this.bones=a.slice(0);this.useVertexTexture?(this.boneTextureHeight=this.boneTextureWidth=a=256h.end&&(h.end=e);b||(b=g)}}a.firstAnimation=b}; +THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){this.geometry.animations||(this.geometry.animations={});this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];c?(this.setFrameRange(c.start,c.end),this.duration=(c.end-c.start)/b*1E3,this.time=0):console.warn("animation["+a+"] undefined")}; +THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time+=this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||0>this.time)this.direction*=-1,this.time>this.duration&&(this.time=this.duration,this.directionBackwards=!0),0>this.time&&(this.time=0,this.directionBackwards=!1)}else this.time%=this.duration,0>this.time&&(this.time+=this.duration);a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/b),0,this.length-1);a!==this.currentKeyframe&& +(this.morphTargetInfluences[this.lastKeyframe]=0,this.morphTargetInfluences[this.currentKeyframe]=1,this.morphTargetInfluences[a]=0,this.lastKeyframe=this.currentKeyframe,this.currentKeyframe=a);b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b}; +THREE.MorphAnimMesh.prototype.interpolateTargets=function(a,b,c){for(var d=this.morphTargetInfluences,e=0,f=d.length;e=this.objects[d].distance)this.objects[d-1].object.visible=!1,this.objects[d].object.visible=!0;else break;for(;dthis.scale.x||c.push({distance:d,point:this.position,face:null,object:this})}}();THREE.Sprite.prototype.updateMatrix=function(){this.matrix.compose(this.position,this.quaternion,this.scale);this.matrixWorldNeedsUpdate=!0}; +THREE.Sprite.prototype.clone=function(a){void 0===a&&(a=new THREE.Sprite(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Particle=THREE.Sprite;THREE.Scene=function(){THREE.Object3D.call(this);this.overrideMaterial=this.fog=null;this.autoUpdate=!0;this.matrixAutoUpdate=!1;this.__lights=[];this.__objectsAdded=[];this.__objectsRemoved=[]};THREE.Scene.prototype=Object.create(THREE.Object3D.prototype); +THREE.Scene.prototype.__addObject=function(a){if(a instanceof THREE.Light)-1===this.__lights.indexOf(a)&&this.__lights.push(a),a.target&&void 0===a.target.parent&&this.add(a.target);else if(!(a instanceof THREE.Camera||a instanceof THREE.Bone)){this.__objectsAdded.push(a);var b=this.__objectsRemoved.indexOf(a);-1!==b&&this.__objectsRemoved.splice(b,1)}this.dispatchEvent({type:"objectAdded",object:a});a.dispatchEvent({type:"addedToScene",scene:this});for(b=0;bE&&O.clearRect(aa.min.x|0,aa.min.y|0,aa.max.x-aa.min.x|0,aa.max.y-aa.min.y|0),0$.positionScreen.z||1<$.positionScreen.z)continue;if(-1>X.positionScreen.z||1T.positionScreen.z||1=S||(S*=V.intensity,R.add(Za.multiplyScalar(S)))):V instanceof THREE.PointLight&&(da=Ga.setFromMatrixPosition(V.matrixWorld),S=ea.dot(Ga.subVectors(da,H).normalize()),0>=S||(S*=0==V.distance?1:1-Math.min(H.distanceTo(da)/V.distance,1),0!=S&&(S*=V.intensity,R.add(Za.multiplyScalar(S)))));G.multiply(Ba).add(Ya);!0===E.wireframe?b(G,E.wireframeLinewidth,E.wireframeLinecap,E.wireframeLinejoin):c(G)}else E instanceof THREE.MeshBasicMaterial||E instanceof THREE.MeshLambertMaterial||E instanceof +THREE.MeshPhongMaterial?null!==E.map?E.map.mapping instanceof THREE.UVMapping&&(ca=J.uvs,f(ya,Ea,Aa,za,Oa,Pa,ca[0].x,ca[0].y,ca[1].x,ca[1].y,ca[2].x,ca[2].y,E.map)):null!==E.envMap?E.envMap.mapping instanceof THREE.SphericalReflectionMapping?(ma.copy(J.vertexNormalsModel[0]).applyMatrix3(Ja),la=0.5*ma.x+0.5,qa=0.5*ma.y+0.5,ma.copy(J.vertexNormalsModel[1]).applyMatrix3(Ja),ua=0.5*ma.x+0.5,ja=0.5*ma.y+0.5,ma.copy(J.vertexNormalsModel[2]).applyMatrix3(Ja),Fa=0.5*ma.x+0.5,va=0.5*ma.y+0.5,f(ya,Ea,Aa,za, +Oa,Pa,la,qa,ua,ja,Fa,va,E.envMap)):E.envMap.mapping instanceof THREE.SphericalRefractionMapping&&(ma.copy(J.vertexNormalsModel[0]).applyMatrix3(Ja),la=-0.5*ma.x+0.5,qa=-0.5*ma.y+0.5,ma.copy(J.vertexNormalsModel[1]).applyMatrix3(Ja),ua=-0.5*ma.x+0.5,ja=-0.5*ma.y+0.5,ma.copy(J.vertexNormalsModel[2]).applyMatrix3(Ja),Fa=-0.5*ma.x+0.5,va=-0.5*ma.y+0.5,f(ya,Ea,Aa,za,Oa,Pa,la,qa,ua,ja,Fa,va,E.envMap)):(G.copy(E.color),E.vertexColors===THREE.FaceColors&&G.multiply(J.color),!0===E.wireframe?b(G,E.wireframeLinewidth, +E.wireframeLinecap,E.wireframeLinejoin):c(G)):(E instanceof THREE.MeshDepthMaterial?G.r=G.g=G.b=1-p(H.positionScreen.z*H.positionScreen.w,oa.near,oa.far):E instanceof THREE.MeshNormalMaterial?(ma.copy(J.normalModel).applyMatrix3(Ja),G.setRGB(ma.x,ma.y,ma.z).multiplyScalar(0.5).addScalar(0.5)):G.setRGB(1,1,1),!0===E.wireframe?b(G,E.wireframeLinewidth,E.wireframeLinecap,E.wireframeLinejoin):c(G))}}aa.union(ra)}}O.setTransform(1,0,0,1,0,0)}}};THREE.ShaderChunk={}; +THREE.ShaderChunk.alphatest_fragment="#ifdef ALPHATEST\n\n\tif ( gl_FragColor.a < ALPHATEST ) discard;\n\n#endif\n";THREE.ShaderChunk.lights_lambert_vertex="vLightFront = vec3( 0.0 );\n\n#ifdef DOUBLE_SIDED\n\n\tvLightBack = vec3( 0.0 );\n\n#endif\n\ntransformedNormal = normalize( transformedNormal );\n\n#if MAX_DIR_LIGHTS > 0\n\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n\tvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\n\tvec3 dirVector = normalize( lDirection.xyz );\n\n\tfloat dotProduct = dot( transformedNormal, dirVector );\n\tvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n\t#ifdef DOUBLE_SIDED\n\n\t\tvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n\t\t#ifdef WRAP_AROUND\n\n\t\t\tvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n\t\t#endif\n\n\t#endif\n\n\t#ifdef WRAP_AROUND\n\n\t\tvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n\t\tdirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tdirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n\n\t\t#endif\n\n\t#endif\n\n\tvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n\n\t#ifdef DOUBLE_SIDED\n\n\t\tvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n\n\t#endif\n\n}\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n\tfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n\t\tvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n\t\tvec3 lVector = lPosition.xyz - mvPosition.xyz;\n\n\t\tfloat lDistance = 1.0;\n\t\tif ( pointLightDistance[ i ] > 0.0 )\n\t\t\tlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\n\n\t\tlVector = normalize( lVector );\n\t\tfloat dotProduct = dot( transformedNormal, lVector );\n\n\t\tvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n\t\t\t#ifdef WRAP_AROUND\n\n\t\t\t\tvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n\t\t\t#endif\n\n\t\t#endif\n\n\t\t#ifdef WRAP_AROUND\n\n\t\t\tvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n\t\t\tpointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n\n\t\t\t#ifdef DOUBLE_SIDED\n\n\t\t\t\tpointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n\n\t\t\t#endif\n\n\t\t#endif\n\n\t\tvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n\n\t\t#endif\n\n\t}\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n\tfor( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n\t\tvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n\t\tvec3 lVector = lPosition.xyz - mvPosition.xyz;\n\n\t\tfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );\n\n\t\tif ( spotEffect > spotLightAngleCos[ i ] ) {\n\n\t\t\tspotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n\t\t\tfloat lDistance = 1.0;\n\t\t\tif ( spotLightDistance[ i ] > 0.0 )\n\t\t\t\tlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\n\n\t\t\tlVector = normalize( lVector );\n\n\t\t\tfloat dotProduct = dot( transformedNormal, lVector );\n\t\t\tvec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n\t\t\t#ifdef DOUBLE_SIDED\n\n\t\t\t\tvec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n\t\t\t\t#ifdef WRAP_AROUND\n\n\t\t\t\t\tvec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n\t\t\t\t#endif\n\n\t\t\t#endif\n\n\t\t\t#ifdef WRAP_AROUND\n\n\t\t\t\tvec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n\t\t\t\tspotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n\n\t\t\t\t#ifdef DOUBLE_SIDED\n\n\t\t\t\t\tspotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n\n\t\t\t\t#endif\n\n\t\t\t#endif\n\n\t\t\tvLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n\n\t\t\t#ifdef DOUBLE_SIDED\n\n\t\t\t\tvLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n\n\t\t\t#endif\n\n\t\t}\n\n\t}\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n\tfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n\t\tvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\n\t\tvec3 lVector = normalize( lDirection.xyz );\n\n\t\tfloat dotProduct = dot( transformedNormal, lVector );\n\n\t\tfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\t\tfloat hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;\n\n\t\tvLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );\n\n\t\t#endif\n\n\t}\n\n#endif\n\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n\n#ifdef DOUBLE_SIDED\n\n\tvLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n\n#endif"; +THREE.ShaderChunk.map_particle_pars_fragment="#ifdef USE_MAP\n\n\tuniform sampler2D map;\n\n#endif";THREE.ShaderChunk.default_vertex="vec4 mvPosition;\n\n#ifdef USE_SKINNING\n\n\tmvPosition = modelViewMatrix * skinned;\n\n#endif\n\n#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )\n\n\tmvPosition = modelViewMatrix * vec4( morphed, 1.0 );\n\n#endif\n\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )\n\n\tmvPosition = modelViewMatrix * vec4( position, 1.0 );\n\n#endif\n\ngl_Position = projectionMatrix * mvPosition;"; +THREE.ShaderChunk.map_pars_fragment="#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )\n\n\tvarying vec2 vUv;\n\n#endif\n\n#ifdef USE_MAP\n\n\tuniform sampler2D map;\n\n#endif";THREE.ShaderChunk.skinnormal_vertex="#ifdef USE_SKINNING\n\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\n\t#ifdef USE_MORPHNORMALS\n\n\tvec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );\n\n\t#else\n\n\tvec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );\n\n\t#endif\n\n#endif\n"; +THREE.ShaderChunk.logdepthbuf_pars_vertex="#ifdef USE_LOGDEPTHBUF\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\tvarying float vFragDepth;\n\n\t#endif\n\n\tuniform float logDepthBufFC;\n\n#endif";THREE.ShaderChunk.lightmap_pars_vertex="#ifdef USE_LIGHTMAP\n\n\tvarying vec2 vUv2;\n\n#endif";THREE.ShaderChunk.lights_phong_fragment="vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n\n#ifdef DOUBLE_SIDED\n\n\tnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n\n#endif\n\n#ifdef USE_NORMALMAP\n\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n\n#elif defined( USE_BUMPMAP )\n\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n\tvec3 pointDiffuse = vec3( 0.0 );\n\tvec3 pointSpecular = vec3( 0.0 );\n\n\tfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n\t\tvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n\t\tvec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n\t\tfloat lDistance = 1.0;\n\t\tif ( pointLightDistance[ i ] > 0.0 )\n\t\t\tlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\n\n\t\tlVector = normalize( lVector );\n\n\t\t\t\t// diffuse\n\n\t\tfloat dotProduct = dot( normal, lVector );\n\n\t\t#ifdef WRAP_AROUND\n\n\t\t\tfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\n\t\t\tfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n\t\t\tvec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n\n\t\t#else\n\n\t\t\tfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n\n\t\t#endif\n\n\t\tpointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\n\n\t\t\t\t// specular\n\n\t\tvec3 pointHalfVector = normalize( lVector + viewPosition );\n\t\tfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\n\t\tfloat pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n\n\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n\t\tvec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );\n\t\tpointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n\n\t}\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n\tvec3 spotDiffuse = vec3( 0.0 );\n\tvec3 spotSpecular = vec3( 0.0 );\n\n\tfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n\t\tvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n\t\tvec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n\t\tfloat lDistance = 1.0;\n\t\tif ( spotLightDistance[ i ] > 0.0 )\n\t\t\tlDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\n\n\t\tlVector = normalize( lVector );\n\n\t\tfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\n\n\t\tif ( spotEffect > spotLightAngleCos[ i ] ) {\n\n\t\t\tspotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n\t\t\t\t\t// diffuse\n\n\t\t\tfloat dotProduct = dot( normal, lVector );\n\n\t\t\t#ifdef WRAP_AROUND\n\n\t\t\t\tfloat spotDiffuseWeightFull = max( dotProduct, 0.0 );\n\t\t\t\tfloat spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n\t\t\t\tvec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n\n\t\t\t#else\n\n\t\t\t\tfloat spotDiffuseWeight = max( dotProduct, 0.0 );\n\n\t\t\t#endif\n\n\t\t\tspotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\n\n\t\t\t\t\t// specular\n\n\t\t\tvec3 spotHalfVector = normalize( lVector + viewPosition );\n\t\t\tfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\n\t\t\tfloat spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n\n\t\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n\t\t\tvec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );\n\t\t\tspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n\n\t\t}\n\n\t}\n\n#endif\n\n#if MAX_DIR_LIGHTS > 0\n\n\tvec3 dirDiffuse = vec3( 0.0 );\n\tvec3 dirSpecular = vec3( 0.0 );\n\n\tfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n\t\tvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\n\t\tvec3 dirVector = normalize( lDirection.xyz );\n\n\t\t\t\t// diffuse\n\n\t\tfloat dotProduct = dot( normal, dirVector );\n\n\t\t#ifdef WRAP_AROUND\n\n\t\t\tfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\n\t\t\tfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n\t\t\tvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n\n\t\t#else\n\n\t\t\tfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n\n\t\t#endif\n\n\t\tdirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\n\n\t\t// specular\n\n\t\tvec3 dirHalfVector = normalize( dirVector + viewPosition );\n\t\tfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\n\t\tfloat dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n\n\t\t/*\n\t\t// fresnel term from skin shader\n\t\tconst float F0 = 0.128;\n\n\t\tfloat base = 1.0 - dot( viewPosition, dirHalfVector );\n\t\tfloat exponential = pow( base, 5.0 );\n\n\t\tfloat fresnel = exponential + F0 * ( 1.0 - exponential );\n\t\t*/\n\n\t\t/*\n\t\t// fresnel term from fresnel shader\n\t\tconst float mFresnelBias = 0.08;\n\t\tconst float mFresnelScale = 0.3;\n\t\tconst float mFresnelPower = 5.0;\n\n\t\tfloat fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );\n\t\t*/\n\n\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n\t\t// \t\tdirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;\n\n\t\tvec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );\n\t\tdirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n\n\n\t}\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n\tvec3 hemiDiffuse = vec3( 0.0 );\n\tvec3 hemiSpecular = vec3( 0.0 );\n\n\tfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n\t\tvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\n\t\tvec3 lVector = normalize( lDirection.xyz );\n\n\t\t// diffuse\n\n\t\tfloat dotProduct = dot( normal, lVector );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\n\t\tvec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n\t\themiDiffuse += diffuse * hemiColor;\n\n\t\t// specular (sky light)\n\n\t\tvec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\n\t\tfloat hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\n\t\tfloat hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );\n\n\t\t// specular (ground light)\n\n\t\tvec3 lVectorGround = -lVector;\n\n\t\tvec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\n\t\tfloat hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\n\t\tfloat hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );\n\n\t\tfloat dotProductGround = dot( normal, lVectorGround );\n\n\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n\t\tvec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );\n\t\tvec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );\n\t\themiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n\n\t}\n\n#endif\n\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n\n#if MAX_DIR_LIGHTS > 0\n\n\ttotalDiffuse += dirDiffuse;\n\ttotalSpecular += dirSpecular;\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n\ttotalDiffuse += hemiDiffuse;\n\ttotalSpecular += hemiSpecular;\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n\ttotalDiffuse += pointDiffuse;\n\ttotalSpecular += pointSpecular;\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n\ttotalDiffuse += spotDiffuse;\n\ttotalSpecular += spotSpecular;\n\n#endif\n\n#ifdef METAL\n\n\tgl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n\n#else\n\n\tgl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n\n#endif"; +THREE.ShaderChunk.fog_pars_fragment="#ifdef USE_FOG\n\n\tuniform vec3 fogColor;\n\n\t#ifdef FOG_EXP2\n\n\t\tuniform float fogDensity;\n\n\t#else\n\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n\n#endif";THREE.ShaderChunk.morphnormal_vertex="#ifdef USE_MORPHNORMALS\n\n\tvec3 morphedNormal = vec3( 0.0 );\n\n\tmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n\n\tmorphedNormal += normal;\n\n#endif"; +THREE.ShaderChunk.envmap_pars_fragment="#ifdef USE_ENVMAP\n\n\tuniform float reflectivity;\n\tuniform samplerCube envMap;\n\tuniform float flipEnvMap;\n\tuniform int combine;\n\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\n\t\tuniform bool useRefract;\n\t\tuniform float refractionRatio;\n\n\t#else\n\n\t\tvarying vec3 vReflect;\n\n\t#endif\n\n#endif";THREE.ShaderChunk.logdepthbuf_fragment="#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n\n\tgl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n\n#endif"; +THREE.ShaderChunk.normalmap_pars_fragment="#ifdef USE_NORMALMAP\n\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\n\t\t\t// Per-Pixel Tangent Space Normal Mapping\n\t\t\t// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\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\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\n\t}\n\n#endif\n"; +THREE.ShaderChunk.lights_phong_pars_vertex="#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )\n\n\tvarying vec3 vWorldPosition;\n\n#endif\n";THREE.ShaderChunk.lightmap_pars_fragment="#ifdef USE_LIGHTMAP\n\n\tvarying vec2 vUv2;\n\tuniform sampler2D lightMap;\n\n#endif";THREE.ShaderChunk.shadowmap_vertex="#ifdef USE_SHADOWMAP\n\n\tfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n\n\t\tvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n\n\t}\n\n#endif"; +THREE.ShaderChunk.lights_phong_vertex="#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )\n\n\tvWorldPosition = worldPosition.xyz;\n\n#endif";THREE.ShaderChunk.map_fragment="#ifdef USE_MAP\n\n\tvec4 texelColor = texture2D( map, vUv );\n\n\t#ifdef GAMMA_INPUT\n\n\t\ttexelColor.xyz *= texelColor.xyz;\n\n\t#endif\n\n\tgl_FragColor = gl_FragColor * texelColor;\n\n#endif";THREE.ShaderChunk.lightmap_vertex="#ifdef USE_LIGHTMAP\n\n\tvUv2 = uv2;\n\n#endif"; +THREE.ShaderChunk.map_particle_fragment="#ifdef USE_MAP\n\n\tgl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );\n\n#endif";THREE.ShaderChunk.color_pars_fragment="#ifdef USE_COLOR\n\n\tvarying vec3 vColor;\n\n#endif\n";THREE.ShaderChunk.color_vertex="#ifdef USE_COLOR\n\n\t#ifdef GAMMA_INPUT\n\n\t\tvColor = color * color;\n\n\t#else\n\n\t\tvColor = color;\n\n\t#endif\n\n#endif";THREE.ShaderChunk.skinning_vertex="#ifdef USE_SKINNING\n\n\t#ifdef USE_MORPHTARGETS\n\n\tvec4 skinVertex = bindMatrix * vec4( morphed, 1.0 );\n\n\t#else\n\n\tvec4 skinVertex = bindMatrix * vec4( position, 1.0 );\n\n\t#endif\n\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\tskinned = bindMatrixInverse * skinned;\n\n#endif\n"; +THREE.ShaderChunk.envmap_pars_vertex="#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\n\n\tvarying vec3 vReflect;\n\n\tuniform float refractionRatio;\n\tuniform bool useRefract;\n\n#endif\n";THREE.ShaderChunk.linear_to_gamma_fragment="#ifdef GAMMA_OUTPUT\n\n\tgl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n\n#endif";THREE.ShaderChunk.color_pars_vertex="#ifdef USE_COLOR\n\n\tvarying vec3 vColor;\n\n#endif";THREE.ShaderChunk.lights_lambert_pars_vertex="uniform vec3 ambient;\nuniform vec3 diffuse;\nuniform vec3 emissive;\n\nuniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n\tuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n\tuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n\tuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n\tuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n\tuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n\tuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\tuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n\tuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n\tuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n\tuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n\tuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#ifdef WRAP_AROUND\n\n\tuniform vec3 wrapRGB;\n\n#endif\n"; +THREE.ShaderChunk.map_pars_vertex="#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )\n\n\tvarying vec2 vUv;\n\tuniform vec4 offsetRepeat;\n\n#endif\n";THREE.ShaderChunk.envmap_fragment="#ifdef USE_ENVMAP\n\n\tvec3 reflectVec;\n\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\n\t\t// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations\n\t\t// Transforming Normal Vectors with the Inverse Transformation\n\n\t\tvec3 worldNormal = normalize( vec3( vec4( normal, 0.0 ) * viewMatrix ) );\n\n\t\tif ( useRefract ) {\n\n\t\t\treflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\n\t\t} else { \n\n\t\t\treflectVec = reflect( cameraToVertex, worldNormal );\n\n\t\t}\n\n\t#else\n\n\t\treflectVec = vReflect;\n\n\t#endif\n\n\t#ifdef DOUBLE_SIDED\n\n\t\tfloat flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n\t\tvec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n\t#else\n\n\t\tvec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n\t#endif\n\n\t#ifdef GAMMA_INPUT\n\n\t\tcubeColor.xyz *= cubeColor.xyz;\n\n\t#endif\n\n\tif ( combine == 1 ) {\n\n\t\tgl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );\n\n\t} else if ( combine == 2 ) {\n\n\t\tgl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;\n\n\t} else {\n\n\t\tgl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );\n\n\t}\n\n#endif"; +THREE.ShaderChunk.specularmap_pars_fragment="#ifdef USE_SPECULARMAP\n\n\tuniform sampler2D specularMap;\n\n#endif";THREE.ShaderChunk.logdepthbuf_vertex="#ifdef USE_LOGDEPTHBUF\n\n\tgl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC;\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\n#else\n\n\t\tgl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\n\t#endif\n\n#endif";THREE.ShaderChunk.morphtarget_pars_vertex="#ifdef USE_MORPHTARGETS\n\n\t#ifndef USE_MORPHNORMALS\n\n\tuniform float morphTargetInfluences[ 8 ];\n\n\t#else\n\n\tuniform float morphTargetInfluences[ 4 ];\n\n\t#endif\n\n#endif"; +THREE.ShaderChunk.specularmap_fragment="float specularStrength;\n\n#ifdef USE_SPECULARMAP\n\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n\n#else\n\n\tspecularStrength = 1.0;\n\n#endif";THREE.ShaderChunk.fog_fragment="#ifdef USE_FOG\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\tfloat depth = gl_FragDepthEXT / gl_FragCoord.w;\n\n\t#else\n\n\t\tfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n\n\t#endif\n\n\t#ifdef FOG_EXP2\n\n\t\tconst float LOG2 = 1.442695;\n\t\tfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\n\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n\n\t#else\n\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n\n\t#endif\n\t\n\tgl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n\n#endif"; +THREE.ShaderChunk.bumpmap_pars_fragment="#ifdef USE_BUMPMAP\n\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\n\t\t\t// Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen\n\t\t\t//\thttp://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html\n\n\t\t\t// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\n\n\tvec2 dHdxy_fwd() {\n\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\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\n\t\treturn vec2( dBx, dBy );\n\n\t}\n\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n\t\tvec3 vSigmaX = dFdx( surf_pos );\n\t\tvec3 vSigmaY = dFdy( surf_pos );\n\t\tvec3 vN = surf_norm;\t\t// normalized\n\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\n\t}\n\n#endif"; +THREE.ShaderChunk.defaultnormal_vertex="vec3 objectNormal;\n\n#ifdef USE_SKINNING\n\n\tobjectNormal = skinnedNormal.xyz;\n\n#endif\n\n#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )\n\n\tobjectNormal = morphedNormal;\n\n#endif\n\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )\n\n\tobjectNormal = normal;\n\n#endif\n\n#ifdef FLIP_SIDED\n\n\tobjectNormal = -objectNormal;\n\n#endif\n\nvec3 transformedNormal = normalMatrix * objectNormal;"; +THREE.ShaderChunk.lights_phong_pars_fragment="uniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n\tuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n\tuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n\tuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n\tuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n\tuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n\tuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\n\tuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n\tuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n\tuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n\tuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n\tuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n\n\tuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )\n\n\tvarying vec3 vWorldPosition;\n\n#endif\n\n#ifdef WRAP_AROUND\n\n\tuniform vec3 wrapRGB;\n\n#endif\n\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;"; +THREE.ShaderChunk.skinbase_vertex="#ifdef USE_SKINNING\n\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\n#endif";THREE.ShaderChunk.map_vertex="#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )\n\n\tvUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n\n#endif"; +THREE.ShaderChunk.lightmap_fragment="#ifdef USE_LIGHTMAP\n\n\tgl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );\n\n#endif";THREE.ShaderChunk.shadowmap_pars_vertex="#ifdef USE_SHADOWMAP\n\n\tvarying vec4 vShadowCoord[ MAX_SHADOWS ];\n\tuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n\n#endif";THREE.ShaderChunk.color_fragment="#ifdef USE_COLOR\n\n\tgl_FragColor = gl_FragColor * vec4( vColor, 1.0 );\n\n#endif";THREE.ShaderChunk.morphtarget_vertex="#ifdef USE_MORPHTARGETS\n\n\tvec3 morphed = vec3( 0.0 );\n\tmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\tmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\tmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\tmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\n\t#ifndef USE_MORPHNORMALS\n\n\tmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\tmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\tmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\tmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\n\t#endif\n\n\tmorphed += position;\n\n#endif"; +THREE.ShaderChunk.envmap_vertex="#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )\n\n\tvec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;\n\tworldNormal = normalize( worldNormal );\n\n\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\n\tif ( useRefract ) {\n\n\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\n\t} else {\n\n\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\n\t}\n\n#endif"; +THREE.ShaderChunk.shadowmap_fragment="#ifdef USE_SHADOWMAP\n\n\t#ifdef SHADOWMAP_DEBUG\n\n\t\tvec3 frustumColors[3];\n\t\tfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\n\t\tfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\n\t\tfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n\n\t#endif\n\n\t#ifdef SHADOWMAP_CASCADE\n\n\t\tint inFrustumCount = 0;\n\n\t#endif\n\n\tfloat fDepth;\n\tvec3 shadowColor = vec3( 1.0 );\n\n\tfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n\n\t\tvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\n\n\t\t\t\t// if ( something && something ) breaks ATI OpenGL shader compiler\n\t\t\t\t// if ( all( something, something ) ) using this instead\n\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\n\t\t\t\t// don't shadow pixels outside of light frustum\n\t\t\t\t// use just first frustum (for cascades)\n\t\t\t\t// don't shadow pixels behind far plane of light frustum\n\n\t\t#ifdef SHADOWMAP_CASCADE\n\n\t\t\tinFrustumCount += int( inFrustum );\n\t\t\tbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n\n\t\t#else\n\n\t\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\n\t\t#endif\n\n\t\tbool frustumTest = all( frustumTestVec );\n\n\t\tif ( frustumTest ) {\n\n\t\t\tshadowCoord.z += shadowBias[ i ];\n\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\n\t\t\t\t\t\t// Percentage-close filtering\n\t\t\t\t\t\t// (9 pixel kernel)\n\t\t\t\t\t\t// http://fabiensanglard.net/shadowmappingPCF/\n\n\t\t\t\tfloat shadow = 0.0;\n\n\t\t/*\n\t\t\t\t\t\t// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL\n\t\t\t\t\t\t// must enroll loop manually\n\n\t\t\t\tfor ( float y = -1.25; y <= 1.25; y += 1.25 )\n\t\t\t\t\tfor ( float x = -1.25; x <= 1.25; x += 1.25 ) {\n\n\t\t\t\t\t\tvec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );\n\n\t\t\t\t\t\t\t\t// doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup\n\t\t\t\t\t\t\t\t//vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );\n\n\t\t\t\t\t\tfloat fDepth = unpackDepth( rgbaDepth );\n\n\t\t\t\t\t\tif ( fDepth < shadowCoord.z )\n\t\t\t\t\t\t\tshadow += 1.0;\n\n\t\t\t\t}\n\n\t\t\t\tshadow /= 9.0;\n\n\t\t*/\n\n\t\t\t\tconst float shadowDelta = 1.0 / 9.0;\n\n\t\t\t\tfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\n\t\t\t\tfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\n\n\t\t\t\tfloat dx0 = -1.25 * xPixelOffset;\n\t\t\t\tfloat dy0 = -1.25 * yPixelOffset;\n\t\t\t\tfloat dx1 = 1.25 * xPixelOffset;\n\t\t\t\tfloat dy1 = 1.25 * yPixelOffset;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n\t\t\t\tif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n\t\t\t\tshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n\n\t\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\n\t\t\t\t\t\t// Percentage-close filtering\n\t\t\t\t\t\t// (9 pixel kernel)\n\t\t\t\t\t\t// http://fabiensanglard.net/shadowmappingPCF/\n\n\t\t\t\tfloat shadow = 0.0;\n\n\t\t\t\tfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\n\t\t\t\tfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\n\n\t\t\t\tfloat dx0 = -1.0 * xPixelOffset;\n\t\t\t\tfloat dy0 = -1.0 * yPixelOffset;\n\t\t\t\tfloat dx1 = 1.0 * xPixelOffset;\n\t\t\t\tfloat dy1 = 1.0 * yPixelOffset;\n\n\t\t\t\tmat3 shadowKernel;\n\t\t\t\tmat3 depthKernel;\n\n\t\t\t\tdepthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n\t\t\t\tdepthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n\t\t\t\tdepthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n\t\t\t\tdepthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n\t\t\t\tdepthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n\t\t\t\tdepthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n\t\t\t\tdepthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n\t\t\t\tdepthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n\t\t\t\tdepthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n\n\t\t\t\tvec3 shadowZ = vec3( shadowCoord.z );\n\t\t\t\tshadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));\n\t\t\t\tshadowKernel[0] *= vec3(0.25);\n\n\t\t\t\tshadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));\n\t\t\t\tshadowKernel[1] *= vec3(0.25);\n\n\t\t\t\tshadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));\n\t\t\t\tshadowKernel[2] *= vec3(0.25);\n\n\t\t\t\tvec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );\n\n\t\t\t\tshadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );\n\t\t\t\tshadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );\n\n\t\t\t\tvec4 shadowValues;\n\t\t\t\tshadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );\n\t\t\t\tshadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );\n\t\t\t\tshadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );\n\t\t\t\tshadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );\n\n\t\t\t\tshadow = dot( shadowValues, vec4( 1.0 ) );\n\n\t\t\t\tshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n\n\t\t\t#else\n\n\t\t\t\tvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\n\t\t\t\tfloat fDepth = unpackDepth( rgbaDepth );\n\n\t\t\t\tif ( fDepth < shadowCoord.z )\n\n\t\t// spot with multiple shadows is darker\n\n\t\t\t\t\tshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n\n\t\t// spot with multiple shadows has the same color as single shadow spot\n\n\t\t// \t\t\t\t\tshadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );\n\n\t\t\t#endif\n\n\t\t}\n\n\n\t\t#ifdef SHADOWMAP_DEBUG\n\n\t\t\t#ifdef SHADOWMAP_CASCADE\n\n\t\t\t\tif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n\n\t\t\t#else\n\n\t\t\t\tif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n\n\t\t\t#endif\n\n\t\t#endif\n\n\t}\n\n\t#ifdef GAMMA_OUTPUT\n\n\t\tshadowColor *= shadowColor;\n\n\t#endif\n\n\tgl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n\n#endif\n"; +THREE.ShaderChunk.worldpos_vertex="#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n\n\t#ifdef USE_SKINNING\n\n\t\tvec4 worldPosition = modelMatrix * skinned;\n\n\t#endif\n\n\t#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\n\n\t\tvec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );\n\n\t#endif\n\n\t#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\n\n\t\tvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n\n\t#endif\n\n#endif"; +THREE.ShaderChunk.shadowmap_pars_fragment="#ifdef USE_SHADOWMAP\n\n\tuniform sampler2D shadowMap[ MAX_SHADOWS ];\n\tuniform vec2 shadowMapSize[ MAX_SHADOWS ];\n\n\tuniform float shadowDarkness[ MAX_SHADOWS ];\n\tuniform float shadowBias[ MAX_SHADOWS ];\n\n\tvarying vec4 vShadowCoord[ MAX_SHADOWS ];\n\n\tfloat unpackDepth( const in vec4 rgba_depth ) {\n\n\t\tconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\n\t\tfloat depth = dot( rgba_depth, bit_shift );\n\t\treturn depth;\n\n\t}\n\n#endif"; +THREE.ShaderChunk.skinning_pars_vertex="#ifdef USE_SKINNING\n\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\n\t#ifdef BONE_TEXTURE\n\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureWidth;\n\t\tuniform int boneTextureHeight;\n\n\t\tmat4 getBoneMatrix( const in float i ) {\n\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureWidth ) );\n\t\t\tfloat y = floor( j / float( boneTextureWidth ) );\n\n\t\t\tfloat dx = 1.0 / float( boneTextureWidth );\n\t\t\tfloat dy = 1.0 / float( boneTextureHeight );\n\n\t\t\ty = dy * ( y + 0.5 );\n\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\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\n\t\t\treturn bone;\n\n\t\t}\n\n\t#else\n\n\t\tuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n\n\t\tmat4 getBoneMatrix( const in float i ) {\n\n\t\t\tmat4 bone = boneGlobalMatrices[ int(i) ];\n\t\t\treturn bone;\n\n\t\t}\n\n\t#endif\n\n#endif\n"; +THREE.ShaderChunk.logdepthbuf_pars_fragment="#ifdef USE_LOGDEPTHBUF\n\n\tuniform float logDepthBufFC;\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\t#extension GL_EXT_frag_depth : enable\n\t\tvarying float vFragDepth;\n\n\t#endif\n\n#endif";THREE.ShaderChunk.alphamap_fragment="#ifdef USE_ALPHAMAP\n\n\tgl_FragColor.a *= texture2D( alphaMap, vUv ).g;\n\n#endif\n";THREE.ShaderChunk.alphamap_pars_fragment="#ifdef USE_ALPHAMAP\n\n\tuniform sampler2D alphaMap;\n\n#endif\n"; +THREE.UniformsUtils={merge:function(a){var b,c,d,e={};for(b=0;b dashSize ) {\n\t\tdiscard;\n\t}\n\tgl_FragColor = vec4( diffuse, opacity );",THREE.ShaderChunk.logdepthbuf_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.fog_fragment, +"}"].join("\n")},depth:{uniforms:{mNear:{type:"f",value:1},mFar:{type:"f",value:2E3},opacity:{type:"f",value:1}},vertexShader:[THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform float mNear;\nuniform float mFar;\nuniform float opacity;",THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {",THREE.ShaderChunk.logdepthbuf_fragment, +"\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tfloat depth = gl_FragDepthEXT / gl_FragCoord.w;\n\t#else\n\t\tfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n\t#endif\n\tfloat color = 1.0 - smoothstep( mNear, mFar, depth );\n\tgl_FragColor = vec4( vec3( color ), opacity );\n}"].join("\n")},normal:{uniforms:{opacity:{type:"f",value:1}},vertexShader:["varying vec3 vNormal;",THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {\n\tvNormal = normalize( normalMatrix * normal );", +THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform float opacity;\nvarying vec3 vNormal;",THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\n\tgl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",THREE.ShaderChunk.logdepthbuf_fragment,"}"].join("\n")},normalmap:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.fog,THREE.UniformsLib.lights,THREE.UniformsLib.shadowmap,{enableAO:{type:"i", +value:0},enableDiffuse:{type:"i",value:0},enableSpecular:{type:"i",value:0},enableReflection:{type:"i",value:0},enableDisplacement:{type:"i",value:0},tDisplacement:{type:"t",value:null},tDiffuse:{type:"t",value:null},tCube:{type:"t",value:null},tNormal:{type:"t",value:null},tSpecular:{type:"t",value:null},tAO:{type:"t",value:null},uNormalScale:{type:"v2",value:new THREE.Vector2(1,1)},uDisplacementBias:{type:"f",value:0},uDisplacementScale:{type:"f",value:1},diffuse:{type:"c",value:new THREE.Color(16777215)}, +specular:{type:"c",value:new THREE.Color(1118481)},ambient:{type:"c",value:new THREE.Color(16777215)},shininess:{type:"f",value:30},opacity:{type:"f",value:1},useRefract:{type:"i",value:0},refractionRatio:{type:"f",value:0.98},reflectivity:{type:"f",value:0.5},uOffset:{type:"v2",value:new THREE.Vector2(0,0)},uRepeat:{type:"v2",value:new THREE.Vector2(1,1)},wrapRGB:{type:"v3",value:new THREE.Vector3(1,1,1)}}]),fragmentShader:["uniform vec3 ambient;\nuniform vec3 diffuse;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\nuniform bool enableDiffuse;\nuniform bool enableSpecular;\nuniform bool enableAO;\nuniform bool enableReflection;\nuniform sampler2D tDiffuse;\nuniform sampler2D tNormal;\nuniform sampler2D tSpecular;\nuniform sampler2D tAO;\nuniform samplerCube tCube;\nuniform vec2 uNormalScale;\nuniform bool useRefract;\nuniform float refractionRatio;\nuniform float reflectivity;\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\n\tuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n\tuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_HEMI_LIGHTS > 0\n\tuniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n\tuniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n\tuniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\n\tuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\tuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n\tuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#if MAX_SPOT_LIGHTS > 0\n\tuniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n\tuniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n\tuniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n\tuniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\n\tuniform vec3 wrapRGB;\n#endif\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;", +THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {",THREE.ShaderChunk.logdepthbuf_fragment,"\tgl_FragColor = vec4( vec3( 1.0 ), opacity );\n\tvec3 specularTex = vec3( 1.0 );\n\tvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\n\tnormalTex.xy *= uNormalScale;\n\tnormalTex = normalize( normalTex );\n\tif( enableDiffuse ) {\n\t\t#ifdef GAMMA_INPUT\n\t\t\tvec4 texelColor = texture2D( tDiffuse, vUv );\n\t\t\ttexelColor.xyz *= texelColor.xyz;\n\t\t\tgl_FragColor = gl_FragColor * texelColor;\n\t\t#else\n\t\t\tgl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n\t\t#endif\n\t}\n\tif( enableAO ) {\n\t\t#ifdef GAMMA_INPUT\n\t\t\tvec4 aoColor = texture2D( tAO, vUv );\n\t\t\taoColor.xyz *= aoColor.xyz;\n\t\t\tgl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n\t\t#else\n\t\t\tgl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n\t\t#endif\n\t}", +THREE.ShaderChunk.alphatest_fragment,"\tif( enableSpecular )\n\t\tspecularTex = texture2D( tSpecular, vUv ).xyz;\n\tmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\n\tvec3 finalNormal = tsb * normalTex;\n\t#ifdef FLIP_SIDED\n\t\tfinalNormal = -finalNormal;\n\t#endif\n\tvec3 normal = normalize( finalNormal );\n\tvec3 viewPosition = normalize( vViewPosition );\n\t#if MAX_POINT_LIGHTS > 0\n\t\tvec3 pointDiffuse = vec3( 0.0 );\n\t\tvec3 pointSpecular = vec3( 0.0 );\n\t\tfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\t\t\tvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n\t\t\tvec3 pointVector = lPosition.xyz + vViewPosition.xyz;\n\t\t\tfloat pointDistance = 1.0;\n\t\t\tif ( pointLightDistance[ i ] > 0.0 )\n\t\t\t\tpointDistance = 1.0 - min( ( length( pointVector ) / pointLightDistance[ i ] ), 1.0 );\n\t\t\tpointVector = normalize( pointVector );\n\t\t\t#ifdef WRAP_AROUND\n\t\t\t\tfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\n\t\t\t\tfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\n\t\t\t\tvec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n\t\t\t#else\n\t\t\t\tfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n\t\t\t#endif\n\t\t\tpointDiffuse += pointDistance * pointLightColor[ i ] * diffuse * pointDiffuseWeight;\n\t\t\tvec3 pointHalfVector = normalize( pointVector + viewPosition );\n\t\t\tfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\n\t\t\tfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n\t\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\t\t\tvec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( pointVector, pointHalfVector ), 0.0 ), 5.0 );\n\t\t\tpointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;\n\t\t}\n\t#endif\n\t#if MAX_SPOT_LIGHTS > 0\n\t\tvec3 spotDiffuse = vec3( 0.0 );\n\t\tvec3 spotSpecular = vec3( 0.0 );\n\t\tfor ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\t\t\tvec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n\t\t\tvec3 spotVector = lPosition.xyz + vViewPosition.xyz;\n\t\t\tfloat spotDistance = 1.0;\n\t\t\tif ( spotLightDistance[ i ] > 0.0 )\n\t\t\t\tspotDistance = 1.0 - min( ( length( spotVector ) / spotLightDistance[ i ] ), 1.0 );\n\t\t\tspotVector = normalize( spotVector );\n\t\t\tfloat spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\n\t\t\tif ( spotEffect > spotLightAngleCos[ i ] ) {\n\t\t\t\tspotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\t\t\t\t#ifdef WRAP_AROUND\n\t\t\t\t\tfloat spotDiffuseWeightFull = max( dot( normal, spotVector ), 0.0 );\n\t\t\t\t\tfloat spotDiffuseWeightHalf = max( 0.5 * dot( normal, spotVector ) + 0.5, 0.0 );\n\t\t\t\t\tvec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n\t\t\t\t#else\n\t\t\t\t\tfloat spotDiffuseWeight = max( dot( normal, spotVector ), 0.0 );\n\t\t\t\t#endif\n\t\t\t\tspotDiffuse += spotDistance * spotLightColor[ i ] * diffuse * spotDiffuseWeight * spotEffect;\n\t\t\t\tvec3 spotHalfVector = normalize( spotVector + viewPosition );\n\t\t\t\tfloat spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\n\t\t\t\tfloat spotSpecularWeight = specularTex.r * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n\t\t\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\t\t\t\tvec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( spotVector, spotHalfVector ), 0.0 ), 5.0 );\n\t\t\t\tspotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;\n\t\t\t}\n\t\t}\n\t#endif\n\t#if MAX_DIR_LIGHTS > 0\n\t\tvec3 dirDiffuse = vec3( 0.0 );\n\t\tvec3 dirSpecular = vec3( 0.0 );\n\t\tfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\n\t\t\tvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\n\t\t\tvec3 dirVector = normalize( lDirection.xyz );\n\t\t\t#ifdef WRAP_AROUND\n\t\t\t\tfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\n\t\t\t\tfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\n\t\t\t\tvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n\t\t\t#else\n\t\t\t\tfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n\t\t\t#endif\n\t\t\tdirDiffuse += directionalLightColor[ i ] * diffuse * dirDiffuseWeight;\n\t\t\tvec3 dirHalfVector = normalize( dirVector + viewPosition );\n\t\t\tfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\n\t\t\tfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n\t\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\t\t\tvec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );\n\t\t\tdirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n\t\t}\n\t#endif\n\t#if MAX_HEMI_LIGHTS > 0\n\t\tvec3 hemiDiffuse = vec3( 0.0 );\n\t\tvec3 hemiSpecular = vec3( 0.0 );\n\t\tfor( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\t\t\tvec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\n\t\t\tvec3 lVector = normalize( lDirection.xyz );\n\t\t\tfloat dotProduct = dot( normal, lVector );\n\t\t\tfloat hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\t\t\tvec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\t\t\themiDiffuse += diffuse * hemiColor;\n\t\t\tvec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\n\t\t\tfloat hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\n\t\t\tfloat hemiSpecularWeightSky = specularTex.r * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );\n\t\t\tvec3 lVectorGround = -lVector;\n\t\t\tvec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\n\t\t\tfloat hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\n\t\t\tfloat hemiSpecularWeightGround = specularTex.r * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );\n\t\t\tfloat dotProductGround = dot( normal, lVectorGround );\n\t\t\tfloat specularNormalization = ( shininess + 2.0 ) / 8.0;\n\t\t\tvec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );\n\t\t\tvec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );\n\t\t\themiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n\t\t}\n\t#endif\n\tvec3 totalDiffuse = vec3( 0.0 );\n\tvec3 totalSpecular = vec3( 0.0 );\n\t#if MAX_DIR_LIGHTS > 0\n\t\ttotalDiffuse += dirDiffuse;\n\t\ttotalSpecular += dirSpecular;\n\t#endif\n\t#if MAX_HEMI_LIGHTS > 0\n\t\ttotalDiffuse += hemiDiffuse;\n\t\ttotalSpecular += hemiSpecular;\n\t#endif\n\t#if MAX_POINT_LIGHTS > 0\n\t\ttotalDiffuse += pointDiffuse;\n\t\ttotalSpecular += pointSpecular;\n\t#endif\n\t#if MAX_SPOT_LIGHTS > 0\n\t\ttotalDiffuse += spotDiffuse;\n\t\ttotalSpecular += spotSpecular;\n\t#endif\n\t#ifdef METAL\n\t\tgl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient + totalSpecular );\n\t#else\n\t\tgl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n\t#endif\n\tif ( enableReflection ) {\n\t\tvec3 vReflect;\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tif ( useRefract ) {\n\t\t\tvReflect = refract( cameraToVertex, normal, refractionRatio );\n\t\t} else {\n\t\t\tvReflect = reflect( cameraToVertex, normal );\n\t\t}\n\t\tvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n\t\t#ifdef GAMMA_INPUT\n\t\t\tcubeColor.xyz *= cubeColor.xyz;\n\t\t#endif\n\t\tgl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * reflectivity );\n\t}", +THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\nuniform bool enableDisplacement;\n#ifdef VERTEX_TEXTURES\n\tuniform sampler2D tDisplacement;\n\tuniform float uDisplacementScale;\n\tuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec3 vWorldPosition;\nvarying vec3 vViewPosition;", +THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,"\t#ifdef USE_SKINNING\n\t\tvNormal = normalize( normalMatrix * skinnedNormal.xyz );\n\t\tvec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );\n\t\tvTangent = normalize( normalMatrix * skinnedTangent.xyz );\n\t#else\n\t\tvNormal = normalize( normalMatrix * normal );\n\t\tvTangent = normalize( normalMatrix * tangent.xyz );\n\t#endif\n\tvBinormal = normalize( cross( vNormal, vTangent ) * tangent.w );\n\tvUv = uv * uRepeat + uOffset;\n\tvec3 displacedPosition;\n\t#ifdef VERTEX_TEXTURES\n\t\tif ( enableDisplacement ) {\n\t\t\tvec3 dv = texture2D( tDisplacement, uv ).xyz;\n\t\t\tfloat df = uDisplacementScale * dv.x + uDisplacementBias;\n\t\t\tdisplacedPosition = position + normalize( normal ) * df;\n\t\t} else {\n\t\t\t#ifdef USE_SKINNING\n\t\t\t\tvec4 skinVertex = bindMatrix * vec4( position, 1.0 );\n\t\t\t\tvec4 skinned = vec4( 0.0 );\n\t\t\t\tskinned += boneMatX * skinVertex * skinWeight.x;\n\t\t\t\tskinned += boneMatY * skinVertex * skinWeight.y;\n\t\t\t\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\t\t\t\tskinned += boneMatW * skinVertex * skinWeight.w;\n\t\t\t\tskinned = bindMatrixInverse * skinned;\n\t\t\t\tdisplacedPosition = skinned.xyz;\n\t\t\t#else\n\t\t\t\tdisplacedPosition = position;\n\t\t\t#endif\n\t\t}\n\t#else\n\t\t#ifdef USE_SKINNING\n\t\t\tvec4 skinVertex = bindMatrix * vec4( position, 1.0 );\n\t\t\tvec4 skinned = vec4( 0.0 );\n\t\t\tskinned += boneMatX * skinVertex * skinWeight.x;\n\t\t\tskinned += boneMatY * skinVertex * skinWeight.y;\n\t\t\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\t\t\tskinned += boneMatW * skinVertex * skinWeight.w;\n\t\t\tskinned = bindMatrixInverse * skinned;\n\t\t\tdisplacedPosition = skinned.xyz;\n\t\t#else\n\t\t\tdisplacedPosition = position;\n\t\t#endif\n\t#endif\n\tvec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );\n\tvec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;", +THREE.ShaderChunk.logdepthbuf_vertex,"\tvWorldPosition = worldPosition.xyz;\n\tvViewPosition = -mvPosition.xyz;\n\t#ifdef USE_SHADOWMAP\n\t\tfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n\t\t\tvShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n\t\t}\n\t#endif\n}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:["varying vec3 vWorldPosition;",THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {\n\tvec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n\tvWorldPosition = worldPosition.xyz;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", +THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;",THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",THREE.ShaderChunk.logdepthbuf_fragment,"}"].join("\n")},depthRGBA:{uniforms:{},vertexShader:[THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex, +"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:[THREE.ShaderChunk.logdepthbuf_pars_fragment,"vec4 pack_depth( const in float depth ) {\n\tconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\n\tconst vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\n\tvec4 res = mod( depth * bit_shift * vec4( 255 ), vec4( 256 ) ) / vec4( 255 );\n\tres -= res.xxyz * bit_mask;\n\treturn res;\n}\nvoid main() {", +THREE.ShaderChunk.logdepthbuf_fragment,"\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tgl_FragData[ 0 ] = pack_depth( gl_FragDepthEXT );\n\t#else\n\t\tgl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n\t#endif\n}"].join("\n")}}; +THREE.WebGLRenderer=function(a){function b(a,b){var c=a.vertices.length,d=b.material;if(d.attributes){void 0===a.__webglCustomAttributesList&&(a.__webglCustomAttributesList=[]);for(var e in d.attributes){var f=d.attributes[e];if(!f.__webglInitialized||f.createUniqueBuffers){f.__webglInitialized=!0;var g=1;"v2"===f.type?g=2:"v3"===f.type?g=3:"v4"===f.type?g=4:"c"===f.type&&(g=3);f.size=g;f.array=new Float32Array(c*g);f.buffer=m.createBuffer();f.buffer.belongsToAttribute=e;f.needsUpdate=!0}a.__webglCustomAttributesList.push(f)}}} +function c(a,b){var c=b.geometry,g=a.faces3,h=3*g.length,k=1*g.length,l=3*g.length,g=d(b,a),n=f(g),r=e(g),p=g.vertexColors?g.vertexColors:!1;a.__vertexArray=new Float32Array(3*h);r&&(a.__normalArray=new Float32Array(3*h));c.hasTangents&&(a.__tangentArray=new Float32Array(4*h));p&&(a.__colorArray=new Float32Array(3*h));n&&(0ja;ja++)Da=R[ja], +yb[gb]=Da.x,yb[gb+1]=Da.y,yb[gb+2]=Da.z,gb+=3;else for(ja=0;3>ja;ja++)yb[gb]=ba.x,yb[gb+1]=ba.y,yb[gb+2]=ba.z,gb+=3;m.bindBuffer(m.ARRAY_BUFFER,y.__webglNormalBuffer);m.bufferData(m.ARRAY_BUFFER,yb,I)}if(xb&&Hb&&Q){B=0;for(N=ka.length;Bja;ja++)Ga=V[ja],cb[Sa]=Ga.x,cb[Sa+1]=Ga.y,Sa+=2;0ja;ja++)Ya=za[ja],fb[Za]=Ya.x,fb[Za+1]=Ya.y,Za+=2;0c;c++)G.autoScaleCubemaps&&!U?(g=h,f=c,r=a.image[c],u=sc,r.width<=u&&r.height<=u||(v=Math.max(r.width,r.height),q=Math.floor(r.width*u/v),u=Math.floor(r.height*u/v),v=document.createElement("canvas"),v.width=q,v.height=u,v.getContext("2d").drawImage(r,0,0,r.width,r.height,0,0,q,u),r=v),g[f]=r):h[c]=a.image[c];c=h[0];g=THREE.Math.isPowerOfTwo(c.width)&&THREE.Math.isPowerOfTwo(c.height); +f=B(a.format);r=B(a.type);E(m.TEXTURE_CUBE_MAP,a,g);for(c=0;6>c;c++)if(U)for(u=h[c].mipmaps,v=0,x=u.length;v=Qb&&console.warn("WebGLRenderer: trying to use "+a+" texture units while this GPU supports only "+Qb);qa+=1;return a}function N(a,b){a._modelViewMatrix.multiplyMatrices(b.matrixWorldInverse,a.matrixWorld);a._normalMatrix.getNormalMatrix(a._modelViewMatrix)} +function ba(a,b,c,d){a[b]=c.r*c.r*d;a[b+1]=c.g*c.g*d;a[b+2]=c.b*c.b*d}function P(a,b,c,d){a[b]=c.r*d;a[b+1]=c.g*d;a[b+2]=c.b*d}function O(a){a!==xa&&(m.lineWidth(a),xa=a)}function J(a,b,c){Qa!==a&&(a?m.enable(m.POLYGON_OFFSET_FILL):m.disable(m.POLYGON_OFFSET_FILL),Qa=a);!a||cb===b&&Ga===c||(m.polygonOffset(b,c),cb=b,Ga=c)}function E(a,b,c){c?(m.texParameteri(a,m.TEXTURE_WRAP_S,B(b.wrapS)),m.texParameteri(a,m.TEXTURE_WRAP_T,B(b.wrapT)),m.texParameteri(a,m.TEXTURE_MAG_FILTER,B(b.magFilter)),m.texParameteri(a, +m.TEXTURE_MIN_FILTER,B(b.minFilter))):(m.texParameteri(a,m.TEXTURE_WRAP_S,m.CLAMP_TO_EDGE),m.texParameteri(a,m.TEXTURE_WRAP_T,m.CLAMP_TO_EDGE),m.texParameteri(a,m.TEXTURE_MAG_FILTER,R(b.magFilter)),m.texParameteri(a,m.TEXTURE_MIN_FILTER,R(b.minFilter)));Ta&&b.type!==THREE.FloatType&&(1b;b++)m.deleteFramebuffer(a.__webglFramebuffer[b]),m.deleteRenderbuffer(a.__webglRenderbuffer[b]);else m.deleteFramebuffer(a.__webglFramebuffer),m.deleteRenderbuffer(a.__webglRenderbuffer); +G.info.memory.textures--},ic=function(a){a=a.target;a.removeEventListener("dispose",ic);Nb(a)},Tb=function(a){void 0!==a.__webglVertexBuffer&&m.deleteBuffer(a.__webglVertexBuffer);void 0!==a.__webglNormalBuffer&&m.deleteBuffer(a.__webglNormalBuffer);void 0!==a.__webglTangentBuffer&&m.deleteBuffer(a.__webglTangentBuffer);void 0!==a.__webglColorBuffer&&m.deleteBuffer(a.__webglColorBuffer);void 0!==a.__webglUVBuffer&&m.deleteBuffer(a.__webglUVBuffer);void 0!==a.__webglUV2Buffer&&m.deleteBuffer(a.__webglUV2Buffer); +void 0!==a.__webglSkinIndicesBuffer&&m.deleteBuffer(a.__webglSkinIndicesBuffer);void 0!==a.__webglSkinWeightsBuffer&&m.deleteBuffer(a.__webglSkinWeightsBuffer);void 0!==a.__webglFaceBuffer&&m.deleteBuffer(a.__webglFaceBuffer);void 0!==a.__webglLineBuffer&&m.deleteBuffer(a.__webglLineBuffer);void 0!==a.__webglLineDistanceBuffer&&m.deleteBuffer(a.__webglLineDistanceBuffer);if(void 0!==a.__webglCustomAttributesList)for(var b in a.__webglCustomAttributesList)m.deleteBuffer(a.__webglCustomAttributesList[b].buffer); +G.info.memory.geometries--},Nb=function(a){var b=a.program.program;if(void 0!==b){a.program=void 0;var c,d,e=!1;a=0;for(c=Ba.length;ad.numSupportedMorphTargets?(h.sort(t),h.length=d.numSupportedMorphTargets):h.length>d.numSupportedMorphNormals?h.sort(t):0===h.length&&h.push([0,0]);for(p=0;pf;f++){a.__webglFramebuffer[f]=m.createFramebuffer();a.__webglRenderbuffer[f]=m.createRenderbuffer(); +m.texImage2D(m.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=m.TEXTURE_CUBE_MAP_POSITIVE_X+f;m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer[f]);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,h,g.__webglTexture,0);Q(a.__webglRenderbuffer[f],a)}c&&m.generateMipmap(m.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=m.createFramebuffer(),a.__webglRenderbuffer=a.shareDepthFrom?a.shareDepthFrom.__webglRenderbuffer:m.createRenderbuffer(),m.bindTexture(m.TEXTURE_2D,a.__webglTexture), +E(m.TEXTURE_2D,a,c),m.texImage2D(m.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=m.TEXTURE_2D,m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,d,a.__webglTexture,0),a.shareDepthFrom?a.depthBuffer&&!a.stencilBuffer?m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):a.depthBuffer&&a.stencilBuffer&&m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_STENCIL_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer): +Q(a.__webglRenderbuffer,a),c&&m.generateMipmap(m.TEXTURE_2D);b?m.bindTexture(m.TEXTURE_CUBE_MAP,null):m.bindTexture(m.TEXTURE_2D,null);m.bindRenderbuffer(m.RENDERBUFFER,null);m.bindFramebuffer(m.FRAMEBUFFER,null)}a?(b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=wb,a=sb,d=ma,e=Ja);b!==Za&&(m.bindFramebuffer(m.FRAMEBUFFER,b),m.viewport(d,e,c,a),Za=b);Hb=c;Ib=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin); +this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; +THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=void 0!==c.wrapS?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==c.wrapT?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==c.magFilter?c.magFilter:THREE.LinearFilter;this.minFilter=void 0!==c.minFilter?c.minFilter:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==c.anisotropy?c.anisotropy:1;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=void 0!==c.format?c.format: +THREE.RGBAFormat;this.type=void 0!==c.type?c.type:THREE.UnsignedByteType;this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.generateMipmaps=!0;this.shareDepthFrom=null}; +THREE.WebGLRenderTarget.prototype={constructor:THREE.WebGLRenderTarget,setSize:function(a,b){this.width=a;this.height=b},clone:function(){var a=new THREE.WebGLRenderTarget(this.width,this.height);a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.format=this.format;a.type=this.type;a.depthBuffer=this.depthBuffer;a.stencilBuffer=this.stencilBuffer;a.generateMipmaps=this.generateMipmaps; +a.shareDepthFrom=this.shareDepthFrom;return a},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.EventDispatcher.prototype.apply(THREE.WebGLRenderTarget.prototype);THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0};THREE.WebGLRenderTargetCube.prototype=Object.create(THREE.WebGLRenderTarget.prototype); +THREE.WebGLProgram=function(){var a=0;return function(b,c,d,e){var f=b.context,g=d.defines,h=d.__webglShader.uniforms,k=d.attributes,l=d.__webglShader.vertexShader,n=d.__webglShader.fragmentShader,q=d.index0AttributeName;void 0===q&&!0===e.morphTargets&&(q="position");var r="SHADOWMAP_TYPE_BASIC";e.shadowMapType===THREE.PCFShadowMap?r="SHADOWMAP_TYPE_PCF":e.shadowMapType===THREE.PCFSoftShadowMap&&(r="SHADOWMAP_TYPE_PCF_SOFT");var t,s;t=[];for(var p in g)s=g[p],!1!==s&&(s="#define "+p+" "+s,t.push(s)); +t=t.join("\n");g=f.createProgram();d instanceof THREE.RawShaderMaterial?b=d="":(d=["precision "+e.precision+" float;","precision "+e.precision+" int;",t,e.supportsVertexTextures?"#define VERTEX_TEXTURES":"",b.gammaInput?"#define GAMMA_INPUT":"",b.gammaOutput?"#define GAMMA_OUTPUT":"","#define MAX_DIR_LIGHTS "+e.maxDirLights,"#define MAX_POINT_LIGHTS "+e.maxPointLights,"#define MAX_SPOT_LIGHTS "+e.maxSpotLights,"#define MAX_HEMI_LIGHTS "+e.maxHemiLights,"#define MAX_SHADOWS "+e.maxShadows,"#define MAX_BONES "+ +e.maxBones,e.map?"#define USE_MAP":"",e.envMap?"#define USE_ENVMAP":"",e.lightMap?"#define USE_LIGHTMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.vertexColors?"#define USE_COLOR":"",e.skinning?"#define USE_SKINNING":"",e.useVertexTexture?"#define BONE_TEXTURE":"",e.morphTargets?"#define USE_MORPHTARGETS":"",e.morphNormals?"#define USE_MORPHNORMALS":"",e.wrapAround?"#define WRAP_AROUND": +"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP":"",e.shadowMapEnabled?"#define "+r:"",e.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",e.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",e.sizeAttenuation?"#define USE_SIZEATTENUATION":"",e.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\n\tattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\n\tattribute vec3 morphTarget0;\n\tattribute vec3 morphTarget1;\n\tattribute vec3 morphTarget2;\n\tattribute vec3 morphTarget3;\n\t#ifdef USE_MORPHNORMALS\n\t\tattribute vec3 morphNormal0;\n\t\tattribute vec3 morphNormal1;\n\t\tattribute vec3 morphNormal2;\n\t\tattribute vec3 morphNormal3;\n\t#else\n\t\tattribute vec3 morphTarget4;\n\t\tattribute vec3 morphTarget5;\n\t\tattribute vec3 morphTarget6;\n\t\tattribute vec3 morphTarget7;\n\t#endif\n#endif\n#ifdef USE_SKINNING\n\tattribute vec4 skinIndex;\n\tattribute vec4 skinWeight;\n#endif\n"].join("\n"), +b=["precision "+e.precision+" float;","precision "+e.precision+" int;",e.bumpMap||e.normalMap?"#extension GL_OES_standard_derivatives : enable":"",t,"#define MAX_DIR_LIGHTS "+e.maxDirLights,"#define MAX_POINT_LIGHTS "+e.maxPointLights,"#define MAX_SPOT_LIGHTS "+e.maxSpotLights,"#define MAX_HEMI_LIGHTS "+e.maxHemiLights,"#define MAX_SHADOWS "+e.maxShadows,e.alphaTest?"#define ALPHATEST "+e.alphaTest:"",b.gammaInput?"#define GAMMA_INPUT":"",b.gammaOutput?"#define GAMMA_OUTPUT":"",e.useFog&&e.fog?"#define USE_FOG": +"",e.useFog&&e.fogExp?"#define FOG_EXP2":"",e.map?"#define USE_MAP":"",e.envMap?"#define USE_ENVMAP":"",e.lightMap?"#define USE_LIGHTMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.vertexColors?"#define USE_COLOR":"",e.metal?"#define METAL":"",e.wrapAround?"#define WRAP_AROUND":"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP": +"",e.shadowMapEnabled?"#define "+r:"",e.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",e.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",e.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n"));l=new THREE.WebGLShader(f,f.VERTEX_SHADER,d+l);n=new THREE.WebGLShader(f,f.FRAGMENT_SHADER,b+n);f.attachShader(g,l);f.attachShader(g,n);void 0!==q&&f.bindAttribLocation(g,0,q);f.linkProgram(g);!1===f.getProgramParameter(g,f.LINK_STATUS)&&(console.error("THREE.WebGLProgram: Could not initialise shader."), +console.error("gl.VALIDATE_STATUS",f.getProgramParameter(g,f.VALIDATE_STATUS)),console.error("gl.getError()",f.getError()));""!==f.getProgramInfoLog(g)&&console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",f.getProgramInfoLog(g));f.deleteShader(l);f.deleteShader(n);q="viewMatrix modelViewMatrix projectionMatrix normalMatrix modelMatrix cameraPosition morphTargetInfluences bindMatrix bindMatrixInverse".split(" ");e.useVertexTexture?(q.push("boneTexture"),q.push("boneTextureWidth"),q.push("boneTextureHeight")): +q.push("boneGlobalMatrices");e.logarithmicDepthBuffer&&q.push("logDepthBufFC");for(var v in h)q.push(v);h=q;v={};q=0;for(b=h.length;qq-1?0:q-1,t=q+1>e-1?e-1:q+1,s=0>n-1?0:n-1,p=n+1>d-1?d-1:n+1,v=[],w=[0,0,h[4*(q*d+n)]/255*b];v.push([-1,0,h[4*(q*d+s)]/255*b]);v.push([-1,-1,h[4*(r*d+s)]/255*b]);v.push([0,-1,h[4*(r*d+n)]/255*b]);v.push([1,-1,h[4*(r*d+p)]/255*b]);v.push([1,0,h[4*(q*d+p)]/255*b]);v.push([1,1,h[4*(t*d+p)]/255*b]);v.push([0,1,h[4*(t*d+n)]/255* +b]);v.push([-1,1,h[4*(t*d+s)]/255*b]);r=[];s=v.length;for(t=0;te)return null;var f=[],g=[],h=[],k,l,n;if(0=q--){console.log("Warning, unable to triangulate polygon!");break}k=l;e<=k&&(k=0);l=k+1;e<=l&&(l=0);n=l+1;e<=n&&(n=0);var r;a:{var t=r=void 0,s=void 0,p=void 0,v=void 0,w=void 0,u=void 0,D=void 0,A= +void 0,t=a[g[k]].x,s=a[g[k]].y,p=a[g[l]].x,v=a[g[l]].y,w=a[g[n]].x,u=a[g[n]].y;if(1E-10>(p-t)*(u-s)-(v-s)*(w-t))r=!1;else{var x=void 0,C=void 0,I=void 0,z=void 0,y=void 0,K=void 0,N=void 0,ba=void 0,P=void 0,O=void 0,P=ba=N=A=D=void 0,x=w-p,C=u-v,I=t-w,z=s-u,y=p-t,K=v-s;for(r=0;rk)g=d+1;else if(0b&&(b=0);1=b)return b=c[a]-b,a=this.curves[a],b=1-b/a.getLength(),a.getPointAt(b);a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; +THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb?b=h.x:h.xc?c=h.y:h.yd?d=h.z:h.zMath.abs(d.x-c[0].x)&&1E-10>Math.abs(d.y-c[0].y)&&c.splice(c.length-1,1);b&&c.push(c[0]);return c}; +THREE.Path.prototype.toShapes=function(a,b){function c(a){for(var b=[],c=0,d=a.length;cl&&(g=b[f],k=-k,h=b[e],l=-l),!(a.yh.y))if(a.y==g.y){if(a.x==g.x)return!0}else{e=l*(a.x-g.x)-k*(a.y-g.y);if(0==e)return!0;0>e||(d=!d)}}else if(a.y==g.y&&(h.x<=a.x&&a.x<=g.x||g.x<=a.x&&a.x<= +h.x))return!0}return d}var e=function(a){var b,c,d,e,f=[],g=new THREE.Path;b=0;for(c=a.length;bz||z>I)return[];k=l*n-k*q;if(0>k||k>I)return[]}else{if(0d?[]:k==d?f?[]:[g]:a<=d?[g,h]: +[g,l]}function e(a,b,c,d){var e=b.x-a.x,f=b.y-a.y;b=c.x-a.x;c=c.y-a.y;var g=d.x-a.x;d=d.y-a.y;a=e*c-f*b;e=e*d-f*g;return 1E-10f&&(f=d);var g=a+1;g>d&&(g=0);d=e(h[a],h[f],h[g],k[b]);if(!d)return!1; +d=k.length-1;f=b-1;0>f&&(f=d);g=b+1;g>d&&(g=0);return(d=e(k[b],k[f],k[g],h[a]))?!0:!1}function f(a,b){var c,e;for(c=0;cO){console.log("Infinite Loop! Holes left:"+ +l.length+", Probably Hole outside Shape!");break}for(q=K;qh;h++)l=k[h].x+":"+k[h].y, +l=n[l],void 0!==l&&(k[h]=l);return q.concat()},isClockWise:function(a){return 0>THREE.FontUtils.Triangulate.area(a)},b2p0:function(a,b){var c=1-a;return c*c*b},b2p1:function(a,b){return 2*(1-a)*a*b},b2p2:function(a,b){return a*a*b},b2:function(a,b,c,d){return this.b2p0(a,b)+this.b2p1(a,c)+this.b2p2(a,d)},b3p0:function(a,b){var c=1-a;return c*c*c*b},b3p1:function(a,b){var c=1-a;return 3*c*c*a*b},b3p2:function(a,b){return 3*(1-a)*a*a*b},b3p3:function(a,b){return a*a*a*b},b3:function(a,b,c,d,e){return this.b3p0(a, +b)+this.b3p1(a,c)+this.b3p2(a,d)+this.b3p3(a,e)}};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=Object.create(THREE.Curve.prototype);THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().sub(this.v1);b.multiplyScalar(a).add(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)};THREE.LineCurve.prototype.getTangent=function(a){return this.v2.clone().sub(this.v1).normalize()}; +THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=Object.create(THREE.Curve.prototype);THREE.QuadraticBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);return new THREE.Vector2(b,a)}; +THREE.QuadraticBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.x,this.v1.x,this.v2.x);a=THREE.Curve.Utils.tangentQuadraticBezier(a,this.v0.y,this.v1.y,this.v2.y);b=new THREE.Vector2(b,a);b.normalize();return b};THREE.CubicBezierCurve=function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d};THREE.CubicBezierCurve.prototype=Object.create(THREE.Curve.prototype); +THREE.CubicBezierCurve.prototype.getPoint=function(a){var b;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);return new THREE.Vector2(b,a)};THREE.CubicBezierCurve.prototype.getTangent=function(a){var b;b=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);a=THREE.Curve.Utils.tangentCubicBezier(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);b=new THREE.Vector2(b,a);b.normalize();return b}; +THREE.SplineCurve=function(a){this.points=void 0==a?[]:a};THREE.SplineCurve.prototype=Object.create(THREE.Curve.prototype);THREE.SplineCurve.prototype.getPoint=function(a){var b=new THREE.Vector2,c=[],d=this.points,e;e=(d.length-1)*a;a=Math.floor(e);e-=a;c[0]=0==a?a:a-1;c[1]=a;c[2]=a>d.length-2?d.length-1:a+1;c[3]=a>d.length-3?d.length-1:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,e);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,e);return b}; +THREE.EllipseCurve=function(a,b,c,d,e,f,g){this.aX=a;this.aY=b;this.xRadius=c;this.yRadius=d;this.aStartAngle=e;this.aEndAngle=f;this.aClockwise=g};THREE.EllipseCurve.prototype=Object.create(THREE.Curve.prototype); +THREE.EllipseCurve.prototype.getPoint=function(a){var b;b=this.aEndAngle-this.aStartAngle;0>b&&(b+=2*Math.PI);b>2*Math.PI&&(b-=2*Math.PI);b=!0===this.aClockwise?this.aEndAngle+(1-a)*(2*Math.PI-b):this.aStartAngle+a*b;a=this.aX+this.xRadius*Math.cos(b);b=this.aY+this.yRadius*Math.sin(b);return new THREE.Vector2(a,b)};THREE.ArcCurve=function(a,b,c,d,e,f){THREE.EllipseCurve.call(this,a,b,c,c,d,e,f)};THREE.ArcCurve.prototype=Object.create(THREE.EllipseCurve.prototype); +THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.subVectors(this.v2,this.v1);b.multiplyScalar(a);b.add(this.v1);return b});THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); +THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); +THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=void 0==a?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;a*=d.length-1;e=Math.floor(a);a-=e;c[0]=0==e?e:e-1;c[1]=e;c[2]=e>d.length-2?d.length-1:e+1;c[3]=e>d.length-3?d.length-1:e+2;e=d[c[0]];var f=d[c[1]],g=d[c[2]],c=d[c[3]];b.x=THREE.Curve.Utils.interpolate(e.x,f.x,g.x,c.x,a);b.y=THREE.Curve.Utils.interpolate(e.y,f.y,g.y,c.y,a);b.z=THREE.Curve.Utils.interpolate(e.z,f.z,g.z,c.z,a);return b}); +THREE.ClosedSplineCurve3=THREE.Curve.create(function(a){this.points=void 0==a?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,e;e=(d.length-0)*a;a=Math.floor(e);e-=a;a+=0a.hierarchy[b].keys[c].time&&(a.hierarchy[b].keys[c].time= +0),void 0!==a.hierarchy[b].keys[c].rot&&!(a.hierarchy[b].keys[c].rot instanceof THREE.Quaternion)){var d=a.hierarchy[b].keys[c].rot;a.hierarchy[b].keys[c].rot=(new THREE.Quaternion).fromArray(d)}if(a.hierarchy[b].keys.length&&void 0!==a.hierarchy[b].keys[0].morphTargets){d={};for(c=0;cd;d++){for(var e= +this.keyTypes[d],f=this.data.hierarchy[a].keys[0],g=this.getNextKeyWith(e,a,1);g.timef.index;)f=g,g=this.getNextKeyWith(e,a,g.index+1);c.prevKey[e]=f;c.nextKey[e]=g}}}; +THREE.Animation.prototype.update=function(){var a=[],b=new THREE.Vector3,c=new THREE.Vector3,d=new THREE.Quaternion,e=function(a,b){var c=[],d=[],e,q,r,t,s,p;e=(a.length-1)*b;q=Math.floor(e);e-=q;c[0]=0===q?q:q-1;c[1]=q;c[2]=q>a.length-2?q:q+1;c[3]=q>a.length-3?q:q+2;q=a[c[0]];t=a[c[1]];s=a[c[2]];p=a[c[3]];c=e*e;r=e*c;d[0]=f(q[0],t[0],s[0],p[0],e,c,r);d[1]=f(q[1],t[1],s[1],p[1],e,c,r);d[2]=f(q[2],t[2],s[2],p[2],e,c,r);return d},f=function(a,b,c,d,e,f,r){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)* +r+(-3*(b-c)-2*a-d)*f+a*e+b};return function(f){if(!1!==this.isPlaying&&(this.currentTime+=f*this.timeScale,0!==this.weight)){f=this.data.length;if(!0===this.loop&&this.currentTime>f)this.currentTime%=f,this.reset();else if(!1===this.loop&&this.currentTime>f){this.stop();return}f=0;for(var h=this.hierarchy.length;fn;n++){var q=this.keyTypes[n],r=l.prevKey[q],t=l.nextKey[q];if(t.time<=this.currentTime){r=this.data.hierarchy[f].keys[0]; +for(t=this.getNextKeyWith(q,f,1);t.timer.index;)r=t,t=this.getNextKeyWith(q,f,t.index+1);l.prevKey[q]=r;l.nextKey[q]=t}k.matrixAutoUpdate=!0;k.matrixWorldNeedsUpdate=!0;var s=(this.currentTime-r.time)/(t.time-r.time),p=r[q],v=t[q];0>s&&(s=0);1a&&(this.currentTime%=a);this.currentTime=Math.min(this.currentTime,a);a=0;for(var b=this.hierarchy.length;af.index;)f=g,g=e[f.index+1];d.prevKey= +f;d.nextKey=g}g.time>=this.currentTime?f.interpolate(g,this.currentTime):f.interpolate(g,g.time);this.data.hierarchy[a].node.updateMatrix();c.matrixWorldNeedsUpdate=!0}}}};THREE.KeyFrameAnimation.prototype.getNextKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c%=b.length;cthis.duration&&(this.currentTime%=this.duration);this.currentTime=Math.min(this.currentTime,this.duration);c=this.duration/this.frames;var d=Math.floor(this.currentTime/c);d!=b&&(this.mesh.morphTargetInfluences[a]=0,this.mesh.morphTargetInfluences[b]=1,this.mesh.morphTargetInfluences[d]= +0,a=b,b=d);this.mesh.morphTargetInfluences[d]=this.currentTime%c/c;this.mesh.morphTargetInfluences[a]=1-this.mesh.morphTargetInfluences[d]}}}()}; +THREE.BoxGeometry=function(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,p){var v,w=h.widthSegments,u=h.heightSegments,D=e/2,A=f/2,x=h.vertices.length;if("x"===a&&"y"===b||"y"===a&&"x"===b)v="z";else if("x"===a&&"z"===b||"z"===a&&"x"===b)v="y",u=h.depthSegments;else if("z"===a&&"y"===b||"y"===a&&"z"===b)v="x",w=h.depthSegments;var C=w+1,I=u+1,z=e/w,y=f/u,K=new THREE.Vector3;K[v]=0=e)return new THREE.Vector2(c,a);e=Math.sqrt(e/2)}else a=!1,1E-10e?-1E-10>g&& +(a=!0):d(f)==d(h)&&(a=!0),a?(c=-f,a=e,e=Math.sqrt(k)):(c=e,a=f,e=Math.sqrt(k/2));return new THREE.Vector2(c/e,a/e)}function e(c,d){var e,f;for(H=c.length;0<=--H;){e=H;f=H-1;0>f&&(f=c.length-1);for(var g=0,h=t+2*n,g=0;gMath.abs(c-k)?[new THREE.Vector2(b,1-e),new THREE.Vector2(d,1-f),new THREE.Vector2(l,1-g),new THREE.Vector2(q,1-a)]:[new THREE.Vector2(c,1-e),new THREE.Vector2(k,1-f),new THREE.Vector2(n,1-g),new THREE.Vector2(r,1-a)]}};THREE.ExtrudeGeometry.__v1=new THREE.Vector2;THREE.ExtrudeGeometry.__v2=new THREE.Vector2;THREE.ExtrudeGeometry.__v3=new THREE.Vector2;THREE.ExtrudeGeometry.__v4=new THREE.Vector2; +THREE.ExtrudeGeometry.__v5=new THREE.Vector2;THREE.ExtrudeGeometry.__v6=new THREE.Vector2;THREE.ShapeGeometry=function(a,b){THREE.Geometry.call(this);!1===a instanceof Array&&(a=[a]);this.addShapeList(a,b);this.computeFaceNormals()};THREE.ShapeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ShapeGeometry.prototype.addShapeList=function(a,b){for(var c=0,d=a.length;cc&&1===a.x&&(a=new THREE.Vector2(a.x-1,a.y));0===b.x&&0===b.z&&(a=new THREE.Vector2(c/2/Math.PI+0.5, +a.y));return a.clone()}THREE.Geometry.call(this);c=c||1;d=d||0;for(var k=this,l=0,n=a.length;lt&&(0.2>d&&(b[0].x+=1),0.2>a&&(b[1].x+=1),0.2>q&&(b[2].x+=1));l=0;for(n=this.vertices.length;lc.y?this.quaternion.set(1,0,0,0):(a.set(c.z,0,-c.x).normalize(),b=Math.acos(c.y),this.quaternion.setFromAxisAngle(a,b))}}(); +THREE.ArrowHelper.prototype.setLength=function(a,b,c){void 0===b&&(b=0.2*a);void 0===c&&(c=0.2*b);this.line.scale.set(1,a,1);this.line.updateMatrix();this.cone.scale.set(c,b,c);this.cone.position.y=a;this.cone.updateMatrix()};THREE.ArrowHelper.prototype.setColor=function(a){this.line.material.color.set(a);this.cone.material.color.set(a)}; +THREE.BoxHelper=function(a){var b=new THREE.BufferGeometry;b.addAttribute("position",new THREE.BufferAttribute(new Float32Array(72),3));THREE.Line.call(this,b,new THREE.LineBasicMaterial({color:16776960}),THREE.LinePieces);void 0!==a&&this.update(a)};THREE.BoxHelper.prototype=Object.create(THREE.Line.prototype); +THREE.BoxHelper.prototype.update=function(a){var b=a.geometry;null===b.boundingBox&&b.computeBoundingBox();var c=b.boundingBox.min,b=b.boundingBox.max,d=this.geometry.attributes.position.array;d[0]=b.x;d[1]=b.y;d[2]=b.z;d[3]=c.x;d[4]=b.y;d[5]=b.z;d[6]=c.x;d[7]=b.y;d[8]=b.z;d[9]=c.x;d[10]=c.y;d[11]=b.z;d[12]=c.x;d[13]=c.y;d[14]=b.z;d[15]=b.x;d[16]=c.y;d[17]=b.z;d[18]=b.x;d[19]=c.y;d[20]=b.z;d[21]=b.x;d[22]=b.y;d[23]=b.z;d[24]=b.x;d[25]=b.y;d[26]=c.z;d[27]=c.x;d[28]=b.y;d[29]=c.z;d[30]=c.x;d[31]=b.y; +d[32]=c.z;d[33]=c.x;d[34]=c.y;d[35]=c.z;d[36]=c.x;d[37]=c.y;d[38]=c.z;d[39]=b.x;d[40]=c.y;d[41]=c.z;d[42]=b.x;d[43]=c.y;d[44]=c.z;d[45]=b.x;d[46]=b.y;d[47]=c.z;d[48]=b.x;d[49]=b.y;d[50]=b.z;d[51]=b.x;d[52]=b.y;d[53]=c.z;d[54]=c.x;d[55]=b.y;d[56]=b.z;d[57]=c.x;d[58]=b.y;d[59]=c.z;d[60]=c.x;d[61]=c.y;d[62]=b.z;d[63]=c.x;d[64]=c.y;d[65]=c.z;d[66]=b.x;d[67]=c.y;d[68]=b.z;d[69]=b.x;d[70]=c.y;d[71]=c.z;this.geometry.attributes.position.needsUpdate=!0;this.geometry.computeBoundingSphere();this.matrixAutoUpdate= +!1;this.matrixWorld=a.matrixWorld};THREE.BoundingBoxHelper=function(a,b){var c=void 0!==b?b:8947848;this.object=a;this.box=new THREE.Box3;THREE.Mesh.call(this,new THREE.BoxGeometry(1,1,1),new THREE.MeshBasicMaterial({color:c,wireframe:!0}))};THREE.BoundingBoxHelper.prototype=Object.create(THREE.Mesh.prototype);THREE.BoundingBoxHelper.prototype.update=function(){this.box.setFromObject(this.object);this.box.size(this.scale);this.box.center(this.position)}; +THREE.CameraHelper=function(a){function b(a,b,d){c(a,d);c(b,d)}function c(a,b){d.vertices.push(new THREE.Vector3);d.colors.push(new THREE.Color(b));void 0===f[a]&&(f[a]=[]);f[a].push(d.vertices.length-1)}var d=new THREE.Geometry,e=new THREE.LineBasicMaterial({color:16777215,vertexColors:THREE.FaceColors}),f={};b("n1","n2",16755200);b("n2","n4",16755200);b("n4","n3",16755200);b("n3","n1",16755200);b("f1","f2",16755200);b("f2","f4",16755200);b("f4","f3",16755200);b("f3","f1",16755200);b("n1","f1",16755200); +b("n2","f2",16755200);b("n3","f3",16755200);b("n4","f4",16755200);b("p","n1",16711680);b("p","n2",16711680);b("p","n3",16711680);b("p","n4",16711680);b("u1","u2",43775);b("u2","u3",43775);b("u3","u1",43775);b("c","t",16777215);b("p","c",3355443);b("cn1","cn2",3355443);b("cn3","cn4",3355443);b("cf1","cf2",3355443);b("cf3","cf4",3355443);THREE.Line.call(this,d,e,THREE.LinePieces);this.camera=a;this.matrixWorld=a.matrixWorld;this.matrixAutoUpdate=!1;this.pointMap=f;this.update()}; +THREE.CameraHelper.prototype=Object.create(THREE.Line.prototype); +THREE.CameraHelper.prototype.update=function(){var a=new THREE.Vector3,b=new THREE.Camera,c=new THREE.Projector;return function(){function d(d,g,h,k){a.set(g,h,k);c.unprojectVector(a,b);d=e.pointMap[d];if(void 0!==d)for(g=0,h=d.length;gs;s++){d[0]=t[g[s]];d[1]=t[g[(s+1)%3]];d.sort(f);var p=d.toString();void 0===e[p]?(e[p]={vert1:d[0],vert2:d[1],face1:q,face2:void 0},n++):e[p].face2=q}h.addAttribute("position",new THREE.Float32Attribute(6*n,3));d=h.attributes.position.array; +f=0;for(p in e)if(g=e[p],void 0===g.face2||0.9999>k[g.face1].normal.dot(k[g.face2].normal))n=l[g.vert1],d[f++]=n.x,d[f++]=n.y,d[f++]=n.z,n=l[g.vert2],d[f++]=n.x,d[f++]=n.y,d[f++]=n.z;THREE.Line.call(this,h,new THREE.LineBasicMaterial({color:c}),THREE.LinePieces);this.matrixAutoUpdate=!1;this.matrixWorld=a.matrixWorld};THREE.EdgesHelper.prototype=Object.create(THREE.Line.prototype); +THREE.FaceNormalsHelper=function(a,b,c,d){this.object=a;this.size=void 0!==b?b:1;a=void 0!==c?c:16776960;d=void 0!==d?d:1;b=new THREE.Geometry;c=0;for(var e=this.object.geometry.faces.length;cb;b++)a.faces[b].color=this.colors[4>b?0:1];b=new THREE.MeshBasicMaterial({vertexColors:THREE.FaceColors,wireframe:!0});this.lightSphere=new THREE.Mesh(a,b);this.add(this.lightSphere); +this.update()};THREE.HemisphereLightHelper.prototype=Object.create(THREE.Object3D.prototype);THREE.HemisphereLightHelper.prototype.dispose=function(){this.lightSphere.geometry.dispose();this.lightSphere.material.dispose()}; +THREE.HemisphereLightHelper.prototype.update=function(){var a=new THREE.Vector3;return function(){this.colors[0].copy(this.light.color).multiplyScalar(this.light.intensity);this.colors[1].copy(this.light.groundColor).multiplyScalar(this.light.intensity);this.lightSphere.lookAt(a.setFromMatrixPosition(this.light.matrixWorld).negate());this.lightSphere.geometry.colorsNeedUpdate=!0}}(); +THREE.PointLightHelper=function(a,b){this.light=a;this.light.updateMatrixWorld();var c=new THREE.SphereGeometry(b,4,2),d=new THREE.MeshBasicMaterial({wireframe:!0,fog:!1});d.color.copy(this.light.color).multiplyScalar(this.light.intensity);THREE.Mesh.call(this,c,d);this.matrixWorld=this.light.matrixWorld;this.matrixAutoUpdate=!1};THREE.PointLightHelper.prototype=Object.create(THREE.Mesh.prototype);THREE.PointLightHelper.prototype.dispose=function(){this.geometry.dispose();this.material.dispose()}; +THREE.PointLightHelper.prototype.update=function(){this.material.color.copy(this.light.color).multiplyScalar(this.light.intensity)}; +THREE.SkeletonHelper=function(a){this.bones=this.getBoneList(a);for(var b=new THREE.Geometry,c=0;cp;p++){d[0]=s[g[p]];d[1]=s[g[(p+1)%3]];d.sort(f);var v=d.toString();void 0===e[v]&&(q[2*n]=d[0],q[2*n+1]=d[1],e[v]=!0,n++)}d=new Float32Array(6*n);r=0;for(t=n;rp;p++)n= +k[q[2*r+p]],g=6*r+3*p,d[g+0]=n.x,d[g+1]=n.y,d[g+2]=n.z;h.addAttribute("position",new THREE.BufferAttribute(d,3))}else if(a.geometry instanceof THREE.BufferGeometry){if(void 0!==a.geometry.attributes.index){for(var k=a.geometry.attributes.position.array,t=a.geometry.attributes.index.array,l=a.geometry.offsets,n=0,q=new Uint32Array(2*t.length),s=0,w=l.length;sp;p++)d[0]=g+t[r+p],d[1]=g+t[r+(p+1)%3],d.sort(f),v=d.toString(), +void 0===e[v]&&(q[2*n]=d[0],q[2*n+1]=d[1],e[v]=!0,n++);d=new Float32Array(6*n);r=0;for(t=n;rp;p++)g=6*r+3*p,n=3*q[2*r+p],d[g+0]=k[n],d[g+1]=k[n+1],d[g+2]=k[n+2]}else for(k=a.geometry.attributes.position.array,n=k.length/3,q=n/3,d=new Float32Array(6*n),r=0,t=q;rp;p++)g=18*r+6*p,q=9*r+3*p,d[g+0]=k[q],d[g+1]=k[q+1],d[g+2]=k[q+2],n=9*r+(p+1)%3*3,d[g+3]=k[n],d[g+4]=k[n+1],d[g+5]=k[n+2];h.addAttribute("position",new THREE.BufferAttribute(d,3))}THREE.Line.call(this,h,new THREE.LineBasicMaterial({color:c}), +THREE.LinePieces);this.matrixAutoUpdate=!1;this.matrixWorld=a.matrixWorld};THREE.WireframeHelper.prototype=Object.create(THREE.Line.prototype);THREE.ImmediateRenderObject=function(){THREE.Object3D.call(this);this.render=function(a){}};THREE.ImmediateRenderObject.prototype=Object.create(THREE.Object3D.prototype);THREE.LensFlare=function(a,b,c,d,e){THREE.Object3D.call(this);this.lensFlares=[];this.positionScreen=new THREE.Vector3;this.customUpdateCallback=void 0;void 0!==a&&this.add(a,b,c,d,e)}; +THREE.LensFlare.prototype=Object.create(THREE.Object3D.prototype);THREE.LensFlare.prototype.add=function(a,b,c,d,e,f){void 0===b&&(b=-1);void 0===c&&(c=0);void 0===f&&(f=1);void 0===e&&(e=new THREE.Color(16777215));void 0===d&&(d=THREE.NormalBlending);c=Math.min(c,Math.max(0,c));this.lensFlares.push({texture:a,size:b,distance:c,x:0,y:0,z:0,scale:1,rotation:1,opacity:f,color:e,blending:d})}; +THREE.LensFlare.prototype.updateLensFlares=function(){var a,b=this.lensFlares.length,c,d=2*-this.positionScreen.x,e=2*-this.positionScreen.y;for(a=0;ah.end&&(h.end=f);c||(c=k)}}for(k in d)h=d[k],this.createAnimation(k,h.start,h.end,a);this.firstAnimation=c}; +THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a])a.direction=1,a.directionBackwards=!1};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a])a.direction=-1,a.directionBackwards=!0};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];c&&(c.fps=b,c.duration=(c.end-c.start)/c.fps)}; +THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];c&&(c.duration=b,c.fps=(c.end-c.start)/c.duration)};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];c&&(c.weight=b)};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];c&&(c.time=b)};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b}; +THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];b?(b.time=0,b.active=!0):console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=!1}; +THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||0>d.time)d.direction*=-1,d.time>d.duration&&(d.time=d.duration,d.directionBackwards=!0),0>d.time&&(d.time=0,d.directionBackwards=!1)}else d.time%=d.duration,0>d.time&&(d.time+=d.duration);var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/e),0,d.length-1),g=d.weight; +f!==d.currentFrame&&(this.morphTargetInfluences[d.lastFrame]=0,this.morphTargetInfluences[d.currentFrame]=1*g,this.morphTargetInfluences[f]=0,d.lastFrame=d.currentFrame,d.currentFrame=f);e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}}; +THREE.LensFlarePlugin=function(){function a(a,b){var d=c.createProgram(),e=c.createShader(c.FRAGMENT_SHADER),f=c.createShader(c.VERTEX_SHADER),g="precision "+b+" float;\n";c.shaderSource(e,g+a.fragmentShader);c.shaderSource(f,g+a.vertexShader);c.compileShader(e);c.compileShader(f);c.attachShader(d,e);c.attachShader(d,f);c.linkProgram(d);return d}var b=[],c,d,e,f,g,h,k,l,n,q,r,t,s;this.init=function(b){c=b.context;d=b;e=b.getPrecision();f=new Float32Array(16);g=new Uint16Array(6);b=0;f[b++]=-1;f[b++]= +-1;f[b++]=0;f[b++]=0;f[b++]=1;f[b++]=-1;f[b++]=1;f[b++]=0;f[b++]=1;f[b++]=1;f[b++]=1;f[b++]=1;f[b++]=-1;f[b++]=1;f[b++]=0;f[b++]=1;b=0;g[b++]=0;g[b++]=1;g[b++]=2;g[b++]=0;g[b++]=2;g[b++]=3;h=c.createBuffer();k=c.createBuffer();c.bindBuffer(c.ARRAY_BUFFER,h);c.bufferData(c.ARRAY_BUFFER,f,c.STATIC_DRAW);c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,k);c.bufferData(c.ELEMENT_ARRAY_BUFFER,g,c.STATIC_DRAW);l=c.createTexture();n=c.createTexture();c.bindTexture(c.TEXTURE_2D,l);c.texImage2D(c.TEXTURE_2D,0,c.RGB,16, +16,0,c.RGB,c.UNSIGNED_BYTE,null);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST);c.bindTexture(c.TEXTURE_2D,n);c.texImage2D(c.TEXTURE_2D,0,c.RGBA,16,16,0,c.RGBA,c.UNSIGNED_BYTE,null);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE); +c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST);c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST);0>=c.getParameter(c.MAX_VERTEX_TEXTURE_IMAGE_UNITS)?(q=!1,r=a(THREE.ShaderFlares.lensFlare,e)):(q=!0,r=a(THREE.ShaderFlares.lensFlareVertexTexture,e));t={};s={};t.vertex=c.getAttribLocation(r,"position");t.uv=c.getAttribLocation(r,"uv");s.renderType=c.getUniformLocation(r,"renderType");s.map=c.getUniformLocation(r,"map");s.occlusionMap=c.getUniformLocation(r,"occlusionMap");s.opacity= +c.getUniformLocation(r,"opacity");s.color=c.getUniformLocation(r,"color");s.scale=c.getUniformLocation(r,"scale");s.rotation=c.getUniformLocation(r,"rotation");s.screenPosition=c.getUniformLocation(r,"screenPosition")};this.render=function(a,e,f,g){b.length=0;a.traverseVisible(function(a){a instanceof THREE.LensFlare&&b.push(a)});if(0!==b.length){a=new THREE.Vector3;var D=g/f,A=0.5*f,x=0.5*g,C=16/g,I=new THREE.Vector2(C*D,C),z=new THREE.Vector3(1,1,0),y=new THREE.Vector2(1,1),K=s,C=t;c.useProgram(r); +c.enableVertexAttribArray(t.vertex);c.enableVertexAttribArray(t.uv);c.uniform1i(K.occlusionMap,0);c.uniform1i(K.map,1);c.bindBuffer(c.ARRAY_BUFFER,h);c.vertexAttribPointer(C.vertex,2,c.FLOAT,!1,16,0);c.vertexAttribPointer(C.uv,2,c.FLOAT,!1,16,8);c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,k);c.disable(c.CULL_FACE);c.depthMask(!1);for(var N=0,ba=b.length;NK;K++)C[K]=new THREE.Vector3,A[K]=new THREE.Vector3;C=x.shadowCascadeNearZ[y];x=x.shadowCascadeFarZ[y];A[0].set(-1,-1,C);A[1].set(1,-1,C);A[2].set(-1,1,C);A[3].set(1,1,C);A[4].set(-1,-1,x);A[5].set(1,-1,x);A[6].set(-1,1,x);A[7].set(1,1,x);z.originalCamera=s;A=new THREE.Gyroscope; +A.position.copy(w.shadowCascadeOffset);A.add(z);A.add(z.target);s.add(A);w.shadowCascadeArray[D]=z;console.log("Created virtualLight",z)}y=w;C=D;x=y.shadowCascadeArray[C];x.position.copy(y.position);x.target.position.copy(y.target.position);x.lookAt(x.target);x.shadowCameraVisible=y.shadowCameraVisible;x.shadowDarkness=y.shadowDarkness;x.shadowBias=y.shadowCascadeBias[C];A=y.shadowCascadeNearZ[C];y=y.shadowCascadeFarZ[C];x=x.pointsFrustum;x[0].z=A;x[1].z=A;x[2].z=A;x[3].z=A;x[4].z=y;x[5].z=y;x[6].z= +y;x[7].z=y;I[u]=z;u++}else I[u]=w,u++;p=0;for(v=I.length;py;y++)C=x[y],C.copy(A[y]),THREE.ShadowMapPlugin.__projector.unprojectVector(C,D),C.applyMatrix4(u.matrixWorldInverse),C.xn.x&&(n.x=C.x),C.yn.y&&(n.y=C.y),C.zn.z&&(n.z=C.z);u.left=l.x;u.right=n.x;u.top=n.y;u.bottom=l.y;u.updateProjectionMatrix()}u=w.shadowMap;A=w.shadowMatrix; +D=w.shadowCamera;D.position.setFromMatrixPosition(w.matrixWorld);q.setFromMatrixPosition(w.target.matrixWorld);D.lookAt(q);D.updateMatrixWorld();D.matrixWorldInverse.getInverse(D.matrixWorld);w.cameraHelper&&(w.cameraHelper.visible=w.shadowCameraVisible);w.shadowCameraVisible&&w.cameraHelper.update();A.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);A.multiply(D.projectionMatrix);A.multiply(D.matrixWorldInverse);k.multiplyMatrices(D.projectionMatrix,D.matrixWorldInverse);h.setFromMatrix(k);c.setRenderTarget(u); +c.clear();r.length=0;a(t,t,D);w=0;for(u=r.length;w 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}"].join("\n")); +u.compileShader(x);u.compileShader(P);u.attachShader(w,x);u.attachShader(w,P);u.linkProgram(w);K=w;p=u.getAttribLocation(K,"position");v=u.getAttribLocation(K,"uv");a=u.getUniformLocation(K,"uvOffset");b=u.getUniformLocation(K,"uvScale");c=u.getUniformLocation(K,"rotation");d=u.getUniformLocation(K,"scale");e=u.getUniformLocation(K,"color");f=u.getUniformLocation(K,"map");g=u.getUniformLocation(K,"opacity");h=u.getUniformLocation(K,"modelViewMatrix");k=u.getUniformLocation(K,"projectionMatrix");l= +u.getUniformLocation(K,"fogType");n=u.getUniformLocation(K,"fogDensity");q=u.getUniformLocation(K,"fogNear");r=u.getUniformLocation(K,"fogFar");t=u.getUniformLocation(K,"fogColor");s=u.getUniformLocation(K,"alphaTest");w=document.createElement("canvas");w.width=8;w.height=8;x=w.getContext("2d");x.fillStyle="white";x.fillRect(0,0,8,8);A=new THREE.Texture(w);A.needsUpdate=!0};this.render=function(C,I,P,O){x.length=0;C.traverseVisible(function(a){a instanceof THREE.Sprite&&x.push(a)});if(0!==x.length){u.useProgram(K); +u.enableVertexAttribArray(p);u.enableVertexAttribArray(v);u.disable(u.CULL_FACE);u.enable(u.BLEND);u.bindBuffer(u.ARRAY_BUFFER,z);u.vertexAttribPointer(p,2,u.FLOAT,!1,16,0);u.vertexAttribPointer(v,2,u.FLOAT,!1,16,8);u.bindBuffer(u.ELEMENT_ARRAY_BUFFER,y);u.uniformMatrix4fv(k,!1,I.projectionMatrix.elements);u.activeTexture(u.TEXTURE0);u.uniform1i(f,0);O=P=0;var J=C.fog;J?(u.uniform3f(t,J.color.r,J.color.g,J.color.b),J instanceof THREE.Fog?(u.uniform1f(q,J.near),u.uniform1f(r,J.far),u.uniform1i(l,1), +O=P=1):J instanceof THREE.FogExp2&&(u.uniform1f(n,J.density),u.uniform1i(l,2),O=P=2)):(u.uniform1i(l,0),O=P=0);for(var J=0,E=x.length;J + + From 125be0271f05950ac8fa005c2b670e5263dff0a0 Mon Sep 17 00:00:00 2001 From: cTn Date: Sat, 6 Sep 2014 11:02:54 +0200 Subject: [PATCH 011/213] static size for mix diagrams and adding missing custom definition in multitype switch --- tabs/initial_setup.css | 6 +++--- tabs/initial_setup.js | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index f858c5da..0eb0eddb 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -67,14 +67,14 @@ top: 32px; left: 10px; - height: 30%; /* interactive_block height set to inherit */ + height: 95px; } #interactive_block .modelMixAirplane { /* Position airplane correctly */ - height: 35%; + height: 115px; padding-left: 0px; } #interactive_block .modelMixCustom { /* Position question mark correctly */ - height: 20%; /* resize question mark */ + height: 75px; padding-left: 25px; } #interactive_block .heading { diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 8ebfb0e8..1b1a12b3 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -120,6 +120,10 @@ TABS.initial_setup.initialize = function (callback) { str = 'Singlecopter'; $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); break; + case 22: // Custom + str = 'Custom'; + $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); + break; } $('span.model').text(chrome.i18n.getMessage('initialSetupModel', [str])); From 78b282f458eefc0f4fd1bb93078b96420e1136af Mon Sep 17 00:00:00 2001 From: cTn Date: Mon, 8 Sep 2014 12:14:41 +0200 Subject: [PATCH 012/213] only trigger update notification on upgrade, bump version, update dev changelog --- changelog.html | 6 ++++++ eventPage.js | 6 +++--- manifest.json | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/changelog.html b/changelog.html index 31ac7668..72afe835 100644 --- a/changelog.html +++ b/changelog.html @@ -1,3 +1,9 @@ +xx.xx.2014 - 0.51 +

+ - Small global UI revamp to utilize space little bit better
+ - Online Firmware can be saved locally
+ - Added missing model information for custom model
+

08.31.2014 - 0.50

- Small UI revamp for Firmware Flasher
diff --git a/eventPage.js b/eventPage.js index be72ef57..8b34a0b2 100644 --- a/eventPage.js +++ b/eventPage.js @@ -75,11 +75,11 @@ chrome.app.runtime.onLaunched.addListener(function () { chrome.runtime.onInstalled.addListener(function (details) { if (details.reason == 'update') { - var previousVersionArr = details.previousVersion.split('.'); - var currentVersionArr = chrome.runtime.getManifest().version.split('.'); + var previousVersionArr = details.previousVersion.split('.'), + currentVersionArr = chrome.runtime.getManifest().version.split('.'); // only fire up notification sequence when one of the major version numbers changed - if (currentVersionArr[0] != previousVersionArr[0] || currentVersionArr[1] != previousVersionArr[1]) { + if (currentVersionArr[0] > previousVersionArr[0] || currentVersionArr[1] > previousVersionArr[1]) { chrome.storage.local.get('update_notify', function (result) { if (result.update_notify === 'undefined' || result.update_notify) { var manifest = chrome.runtime.getManifest(); diff --git a/manifest.json b/manifest.json index 68cf4b51..7f742b9f 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "minimum_chrome_version": "36", - "version": "0.50", + "version": "0.51", "author": "cTn", "name": "Baseflight - Configurator", From a96e80435992c5341b31d4fd41e2f2ef32ddb72a Mon Sep 17 00:00:00 2001 From: cTn Date: Mon, 8 Sep 2014 17:52:07 +0200 Subject: [PATCH 013/213] removing MSP pass through mode --- js/data_storage.js | 1 - js/serial_backend.js | 58 +++++++++++++++++++------------------------- main.js | 2 +- tabs/logging.js | 45 +++++----------------------------- 4 files changed, 32 insertions(+), 74 deletions(-) diff --git a/js/data_storage.js b/js/data_storage.js index ef80cc99..f073d195 100644 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -4,7 +4,6 @@ var CONFIGURATOR = { 'releaseDate': 1409496670288, // 08.31.2014 - new Date().getTime() 'firmwareVersionAccepted': 2.3, 'connectionValid': false, - 'mspPassThrough': false, 'cliActive': false, 'cliValid': false }; diff --git a/js/serial_backend.js b/js/serial_backend.js index f3f778cc..9de15538 100644 --- a/js/serial_backend.js +++ b/js/serial_backend.js @@ -35,7 +35,6 @@ $(document).ready(function () { MSP.disconnect_cleanup(); PortUsage.reset(); CONFIGURATOR.connectionValid = false; - CONFIGURATOR.mspPassThrough = false; // unlock port select & baud $('div#port-picker #port').prop('disabled', false); @@ -125,39 +124,34 @@ function onOpen(openInfo) { serial.onReceive.addListener(read_serial); - if (!CONFIGURATOR.mspPassThrough) { - // disconnect after 10 seconds with error if we don't get IDENT data - GUI.timeout_add('connecting', function () { - if (!CONFIGURATOR.connectionValid) { - GUI.log(chrome.i18n.getMessage('noConfigurationReceived')); + // disconnect after 10 seconds with error if we don't get IDENT data + GUI.timeout_add('connecting', function () { + if (!CONFIGURATOR.connectionValid) { + GUI.log(chrome.i18n.getMessage('noConfigurationReceived')); + $('div#port-picker a.connect').click(); // disconnect + } + }, 10000); + + // request configuration data + MSP.send_message(MSP_codes.MSP_UID, false, false, function () { + GUI.log(chrome.i18n.getMessage('uniqueDeviceIdReceived', [CONFIG.uid[0].toString(16) + CONFIG.uid[1].toString(16) + CONFIG.uid[2].toString(16)])); + MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () { + GUI.timeout_remove('connecting'); // kill connecting timer + + GUI.log(chrome.i18n.getMessage('firmwareVersion', [CONFIG.version])); + + if (CONFIG.version >= CONFIGURATOR.firmwareVersionAccepted) { + CONFIGURATOR.connectionValid = true; + + $('div#port-picker a.connect').text(chrome.i18n.getMessage('disconnect')).addClass('active'); + $('#tabs li a:first').click(); + } else { + GUI.log(chrome.i18n.getMessage('firmwareVersionNotSupported', [CONFIGURATOR.firmwareVersionAccepted])); $('div#port-picker a.connect').click(); // disconnect } - }, 10000); - - // request configuration data - MSP.send_message(MSP_codes.MSP_UID, false, false, function () { - GUI.log(chrome.i18n.getMessage('uniqueDeviceIdReceived', [CONFIG.uid[0].toString(16) + CONFIG.uid[1].toString(16) + CONFIG.uid[2].toString(16)])); - MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () { - GUI.timeout_remove('connecting'); // kill connecting timer - - GUI.log(chrome.i18n.getMessage('firmwareVersion', [CONFIG.version])); - - if (CONFIG.version >= CONFIGURATOR.firmwareVersionAccepted) { - CONFIGURATOR.connectionValid = true; - - $('div#port-picker a.connect').text(chrome.i18n.getMessage('disconnect')).addClass('active'); - $('#tabs li a:first').click(); - } else { - GUI.log(chrome.i18n.getMessage('firmwareVersionNotSupported', [CONFIGURATOR.firmwareVersionAccepted])); - $('div#port-picker a.connect').click(); // disconnect - } - }); }); - } else { - $('div#port-picker a.connect').text(chrome.i18n.getMessage('disconnect')).addClass('active'); - GUI.log('Connection opened in pass-through mode'); - } + }); } else { console.log('Failed to open serial port'); GUI.log(chrome.i18n.getMessage('serialPortOpenFail')); @@ -182,12 +176,10 @@ function onClosed(result) { } function read_serial(info) { - if (!CONFIGURATOR.cliActive && !CONFIGURATOR.mspPassThrough) { + if (!CONFIGURATOR.cliActive) { MSP.read(info); } else if (CONFIGURATOR.cliActive) { TABS.cli.read(info); - } else if (CONFIGURATOR.mspPassThrough) { - MSP.read(info); } } diff --git a/main.js b/main.js index 686669d9..85955b02 100644 --- a/main.js +++ b/main.js @@ -56,7 +56,7 @@ $(document).ready(function () { tab = $(self).parent().prop('class'); // if there is no active connection, return - if (!CONFIGURATOR.connectionValid && tab != 'tab_logging') { + if (!CONFIGURATOR.connectionValid) { GUI.log('You need to connect before you can view any of the tabs'); return; } diff --git a/tabs/logging.js b/tabs/logging.js index 5ffcb9ba..967da9f9 100644 --- a/tabs/logging.js +++ b/tabs/logging.js @@ -6,7 +6,10 @@ TABS.logging.initialize = function (callback) { GUI.active_tab = 'logging'; googleAnalytics.sendAppView('Logging'); - var requested_properties = []; + var requested_properties = [], + samples = 0, + requests = 0, + log_buffer = []; if (CONFIGURATOR.connectionValid) { var get_motor_data = function () { @@ -18,20 +21,6 @@ TABS.logging.initialize = function (callback) { } MSP.send_message(MSP_codes.MSP_RC, false, false, get_motor_data); - } else { - CONFIGURATOR.mspPassThrough = true; - - // we will initialize RC.channels array and MOTOR_DATA array manually - RC.active_channels = 8; - for (var i = 0; i < RC.active_channels; i++) { - RC.channels[i] = 0; - } - - for (var i = 0; i < 8; i++) { - MOTOR_DATA[i] = 0; - } - - $('#content').load("./tabs/logging.html", process_html); } function process_html() { @@ -68,10 +57,8 @@ TABS.logging.initialize = function (callback) { } // request new - if (!CONFIGURATOR.mspPassThrough) { - for (var i = 0; i < requested_properties.length; i++, requests++) { - MSP.send_message(MSP_codes[requested_properties[i]]); - } + for (var i = 0; i < requested_properties.length; i++, requests++) { + MSP.send_message(MSP_codes[requested_properties[i]]); } } @@ -111,22 +98,6 @@ TABS.logging.initialize = function (callback) { } }); - if (CONFIGURATOR.mspPassThrough) { - $('a.back').show(); - - $('a.back').click(function() { - if (GUI.connected_to) { - $('a.connect').click(); - } else { - GUI.tab_switch_cleanup(function () { - CONFIGURATOR.mspPassThrough = false; - $('#tabs > ul li').removeClass('active'); - TABS.default.initialize(); - }); - } - }); - } - chrome.storage.local.get('logging_file_entry', function (result) { if (result.logging_file_entry) { chrome.fileSystem.restoreEntry(result.logging_file_entry, function (entry) { @@ -201,10 +172,6 @@ TABS.logging.initialize = function (callback) { append_to_file(head); } - var samples = 0, - requests = 0, - log_buffer = []; - function crunch_data() { var sample = millitime(); From 2cbd91165345464058769f2b54ed204d4a1ae86e Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 9 Sep 2014 11:08:36 +0200 Subject: [PATCH 014/213] release --- changelog.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.html b/changelog.html index 72afe835..387e5490 100644 --- a/changelog.html +++ b/changelog.html @@ -1,5 +1,6 @@ -xx.xx.2014 - 0.51 +09.09.2014 - 0.51

+ - Configurator userbase is over 9000 now :-)
- Small global UI revamp to utilize space little bit better
- Online Firmware can be saved locally
- Added missing model information for custom model
From 46b3151e37896714be11331e0b7ec8a1f4bc13fe Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 9 Sep 2014 13:55:58 +0200 Subject: [PATCH 015/213] initial cleanup on the lowest level of serial layer, "system_error" bug is still unknown --- js/serial.js | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/js/serial.js b/js/serial.js index 2a4092bd..d7c4ac85 100644 --- a/js/serial.js +++ b/js/serial.js @@ -9,10 +9,10 @@ var serial = { transmitting: false, output_buffer: [], - connect: function(path, options, callback) { + connect: function (path, options, callback) { var self = this; - chrome.serial.connect(path, options, function(connectionInfo) { + chrome.serial.connect(path, options, function (connectionInfo) { if (connectionInfo) { self.connectionId = connectionInfo.connectionId; self.bitrate = connectionInfo.bitrate; @@ -78,7 +78,7 @@ var serial = { } }); }, - disconnect: function(callback) { + disconnect: function (callback) { var self = this; self.empty_output_buffer(); @@ -92,7 +92,7 @@ var serial = { self.onReceiveError.removeListener(self.onReceiveError.listeners[i]); } - chrome.serial.disconnect(this.connectionId, function(result) { + chrome.serial.disconnect(this.connectionId, function (result) { if (result) { console.log('SERIAL: Connection with ID: ' + self.connectionId + ' closed'); } else { @@ -108,26 +108,26 @@ var serial = { if (callback) callback(result); }); }, - getDevices: function(callback) { - chrome.serial.getDevices(function(devices_array) { + getDevices: function (callback) { + chrome.serial.getDevices(function (devices_array) { var devices = []; - devices_array.forEach(function(device) { + devices_array.forEach(function (device) { devices.push(device.path); }); callback(devices); }); }, - getInfo: function(callback) { + getInfo: function (callback) { chrome.serial.getInfo(this.connectionId, callback); }, - getControlSignals: function(callback) { + getControlSignals: function (callback) { chrome.serial.getControlSignals(this.connectionId, callback); }, - setControlSignals: function(signals, callback) { + setControlSignals: function (signals, callback) { chrome.serial.setControlSignals(this.connectionId, signals, callback); }, - send: function(data, callback) { + send: function (data, callback) { var self = this; self.output_buffer.push({'data': data, 'callback': callback}); @@ -136,10 +136,10 @@ var serial = { var sending = function () { // store inside separate variables in case array gets destroyed - var data = self.output_buffer[0].data; - var callback = self.output_buffer[0].callback; + var data = self.output_buffer[0].data, + callback = self.output_buffer[0].callback; - chrome.serial.send(self.connectionId, data, function(sendInfo) { + chrome.serial.send(self.connectionId, data, function (sendInfo) { callback(sendInfo); self.output_buffer.shift(); @@ -164,12 +164,11 @@ var serial = { onReceive: { listeners: [], - addListener: function(function_reference) { - var listener = chrome.serial.onReceive.addListener(function_reference); - + addListener: function (function_reference) { + chrome.serial.onReceive.addListener(function_reference); this.listeners.push(function_reference); }, - removeListener: function(function_reference) { + removeListener: function (function_reference) { for (var i = (this.listeners.length - 1); i >= 0; i--) { if (this.listeners[i] == function_reference) { chrome.serial.onReceive.removeListener(function_reference); @@ -183,12 +182,11 @@ var serial = { onReceiveError: { listeners: [], - addListener: function(function_reference) { - var listener = chrome.serial.onReceiveError.addListener(function_reference); - + addListener: function (function_reference) { + chrome.serial.onReceiveError.addListener(function_reference); this.listeners.push(function_reference); }, - removeListener: function(function_reference) { + removeListener: function (function_reference) { for (var i = (this.listeners.length - 1); i >= 0; i--) { if (this.listeners[i] == function_reference) { chrome.serial.onReceiveError.removeListener(function_reference); @@ -199,7 +197,7 @@ var serial = { } } }, - empty_output_buffer: function() { + empty_output_buffer: function () { this.output_buffer = []; this.transmitting = false; } From 8f0fe2f9ea50af4a491a429a495be297a10d663f Mon Sep 17 00:00:00 2001 From: cTn Date: Fri, 12 Sep 2014 14:00:39 +0200 Subject: [PATCH 016/213] print remaining time based on app last release date in console --- main.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index 85955b02..7d889081 100644 --- a/main.js +++ b/main.js @@ -43,7 +43,10 @@ $(document).ready(function () { } // check release time to inform people in case they are running old release - if (CONFIGURATOR.releaseDate < (new Date().getTime() - (86400000 * 60))) { // 1 day = 86400000 miliseconds, * 60 = 2 month window + if (CONFIGURATOR.releaseDate > (new Date().getTime() - (86400000 * 60))) { // 1 day = 86400000 miliseconds, * 60 = 2 month window + console.log('Application version is valid for another: ' + Math.round((CONFIGURATOR.releaseDate - (new Date().getTime() - (86400000 * 60))) / 86400000) + ' days'); + } else { + console.log('Application version expired'); GUI.log('You\'re using an old version of ' + chrome.runtime.getManifest().name + '. Please update so you can benefit from recently added features and bugfixes.'); } From 4b96bb39b50e96c3262ec67ace3e4ef28811b989 Mon Sep 17 00:00:00 2001 From: cTn Date: Sat, 13 Sep 2014 12:17:22 +0200 Subject: [PATCH 017/213] updating analytics lib --- js/libraries/google-analytics-bundle.js | 157 +++++++++++++----------- 1 file changed, 83 insertions(+), 74 deletions(-) diff --git a/js/libraries/google-analytics-bundle.js b/js/libraries/google-analytics-bundle.js index ab4e495d..7a88e8b9 100644 --- a/js/libraries/google-analytics-bundle.js +++ b/js/libraries/google-analytics-bundle.js @@ -1,78 +1,87 @@ -(function() { var h,aa=aa||{},k=this,ba=function(){},ca=function(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&& -!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"==b&&"undefined"==typeof a.call)return"object";return b},m=function(a){return"array"==ca(a)},da=function(a){var b=ca(a);return"array"==b||"object"==b&&"number"==typeof a.length},n=function(a){return"string"==typeof a},p=function(a){return"function"==ca(a)},ea=function(a){var b=typeof a;return"object"==b&&null!=a||"function"==b},fa=function(a,b,c){return a.call.apply(a.bind,arguments)},ga=function(a,b,c){if(!a)throw Error(); -if(2b?1:0};var ja=function(){};ja.prototype.Na=!1;ja.prototype.ra=function(){this.Na||(this.Na=!0,this.k())};ja.prototype.k=function(){if(this.ub)for(;this.ub.length;)this.ub.shift()()};var v=Array.prototype,ka=v.indexOf?function(a,b,c){return v.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(n(a))return n(b)&&1==b.length?a.indexOf(b,c):-1;for(;cb?null:n(a)?a.charAt(b):a[b]},pa=function(a,b){var c=ka(a,b),d;(d=0<=c)&&v.splice.call(a,c,1);return d},qa=function(a){return v.concat.apply(v,arguments)};var ra=function(a,b,c){for(var d in a)b.call(c,a[d],d,a)},sa=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b},ta=function(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b},ua=function(a,b){var c;t:{for(c in a)if(b.call(void 0,a[c],c,a))break t;c=void 0}return c&&a[c]},va="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),wa=function(a,b){for(var c,d,e=1;eparseFloat(a))?String(b):a}(),Da={},C=function(a){var b; -if(!(b=Da[a])){b=0;for(var c=String(Ca).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),e=Math.max(c.length,d.length),f=0;0==b&&f=a.keyCode)a.keyCode=-1}catch(b){}};D.prototype.k=function(){};var La="closure_listenable_"+(1E6*Math.random()|0),Ma=function(a){return!(!a||!a[La])},Na=0;var Oa=function(a,b,c,d,e){this.L=a;this.proxy=null;this.src=b;this.type=c;this.ja=!!d;this.ma=e;this.key=++Na;this.removed=this.ka=!1},Pa=function(a){a.removed=!0;a.L=null;a.proxy=null;a.src=null;a.ma=null};var E=function(a){this.src=a;this.h={};this.U=0};E.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.h[f];a||(a=this.h[f]=[],this.U++);var g=Qa(a,b,d,e);-1e.keyCode||void 0!=e.returnValue)){t:{var f=!1;if(0==e.keyCode)try{e.keyCode=-1;break t}catch(g){f=!0}if(f||void 0==e.returnValue)e.returnValue=!0}e=[];for(f=c.currentTarget;f;f=f.parentNode)e.push(f);for(var f=a.type,l=e.length-1;!c.P&&0<=l;l--)c.currentTarget=e[l],d&=fb(e[l],f,!0,c);for(l=0;!c.P&&l>>0),Wa=function(a){if(p(a))return a;a[gb]||(a[gb]=function(b){return a.handleEvent(b)});return a[gb]};var G=function(){this.w=new E(this);this.Wb=this;this.Ha=null};t(G,ja);G.prototype[La]=!0;h=G.prototype;h.addEventListener=function(a,b,c,d){Va(this,a,b,c,d)};h.removeEventListener=function(a,b,c,d){cb(this,a,b,c,d)}; -h.dispatchEvent=function(a){var b,c=this.Ha;if(c){b=[];for(var d=1;c;c=c.Ha)b.push(c),++d}c=this.Wb;d=a.type||a;if(n(a))a=new w(a,c);else if(a instanceof w)a.target=a.target||c;else{var e=a;a=new w(d,c);wa(a,e)}var e=!0,f;if(b)for(var g=b.length-1;!a.P&&0<=g;g--)f=a.currentTarget=b[g],e=hb(f,d,!0,a)&&e;a.P||(f=a.currentTarget=c,e=hb(f,d,!0,a)&&e,a.P||(e=hb(f,d,!1,a)&&e));if(b)for(g=0;!a.P&&g2*this.g&&kb(this),!0):!1};var kb=function(a){if(a.g!=a.b.length){for(var b=0,c=0;b=c.length)throw ib;var g=c[b++];return a?g:d[g]}};return g};var I=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};var lb,mb,nb={id:"hitType",name:"t",valueType:"text",maxLength:void 0,defaultValue:void 0},ob={id:"sessionControl",name:"sc",valueType:"text",maxLength:void 0,defaultValue:void 0},pb={id:"description",name:"cd",valueType:"text",maxLength:2048,defaultValue:void 0},qb={Wc:nb,wc:{id:"anonymizeIp",name:"aip",valueType:"boolean",maxLength:void 0,defaultValue:void 0},hd:{id:"queueTime",name:"qt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Cc:{id:"cacheBuster",name:"z",valueType:"text",maxLength:void 0, -defaultValue:void 0},od:ob,Ed:{id:"userId",name:"uid",valueType:"text",maxLength:void 0,defaultValue:void 0},ed:{id:"nonInteraction",name:"ni",valueType:"boolean",maxLength:void 0,defaultValue:void 0},Mc:pb,xd:{id:"title",name:"dt",valueType:"text",maxLength:1500,defaultValue:void 0},Nc:{id:"dimension",name:"cd[1-9][0-9]*",valueType:"text",maxLength:150,defaultValue:void 0},dd:{id:"metric",name:"cm[1-9][0-9]*",valueType:"integer",maxLength:void 0,defaultValue:void 0},yc:{id:"appId",name:"aid",valueType:"text", -maxLength:150,defaultValue:void 0},zc:{id:"appInstallerId",name:"aiid",valueType:"text",maxLength:150,defaultValue:void 0},Qc:{id:"eventCategory",name:"ec",valueType:"text",maxLength:150,defaultValue:void 0},Pc:{id:"eventAction",name:"ea",valueType:"text",maxLength:500,defaultValue:void 0},Rc:{id:"eventLabel",name:"el",valueType:"text",maxLength:500,defaultValue:void 0},Sc:{id:"eventValue",name:"ev",valueType:"integer",maxLength:void 0,defaultValue:void 0},qd:{id:"socialNetwork",name:"sn",valueType:"text", -maxLength:50,defaultValue:void 0},pd:{id:"socialAction",name:"sa",valueType:"text",maxLength:50,defaultValue:void 0},rd:{id:"socialTarget",name:"st",valueType:"text",maxLength:2048,defaultValue:void 0},Ad:{id:"transactionId",name:"ti",valueType:"text",maxLength:500,defaultValue:void 0},zd:{id:"transactionAffiliation",name:"ta",valueType:"text",maxLength:500,defaultValue:void 0},Bd:{id:"transactionRevenue",name:"tr",valueType:"currency",maxLength:void 0,defaultValue:void 0},Cd:{id:"transactionShipping", -name:"ts",valueType:"currency",maxLength:void 0,defaultValue:void 0},Dd:{id:"transactionTax",name:"tt",valueType:"currency",maxLength:void 0,defaultValue:void 0},Kc:{id:"currencyCode",name:"cu",valueType:"text",maxLength:10,defaultValue:void 0},$c:{id:"itemPrice",name:"ip",valueType:"currency",maxLength:void 0,defaultValue:void 0},ad:{id:"itemQuantity",name:"iq",valueType:"integer",maxLength:void 0,defaultValue:void 0},Yc:{id:"itemCode",name:"ic",valueType:"text",maxLength:500,defaultValue:void 0}, -Zc:{id:"itemName",name:"in",valueType:"text",maxLength:500,defaultValue:void 0},Xc:{id:"itemCategory",name:"iv",valueType:"text",maxLength:500,defaultValue:void 0},Ic:{id:"campaignSource",name:"cs",valueType:"text",maxLength:100,defaultValue:void 0},Gc:{id:"campaignMedium",name:"cm",valueType:"text",maxLength:50,defaultValue:void 0},Hc:{id:"campaignName",name:"cn",valueType:"text",maxLength:100,defaultValue:void 0},Fc:{id:"campaignKeyword",name:"ck",valueType:"text",maxLength:500,defaultValue:void 0}, -Dc:{id:"campaignContent",name:"cc",valueType:"text",maxLength:500,defaultValue:void 0},Ec:{id:"campaignId",name:"ci",valueType:"text",maxLength:100,defaultValue:void 0},Vc:{id:"gclid",name:"gclid",valueType:"text",maxLength:void 0,defaultValue:void 0},Lc:{id:"dclid",name:"dclid",valueType:"text",maxLength:void 0,defaultValue:void 0},gd:{id:"pageLoadTime",name:"plt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Oc:{id:"dnsTime",name:"dns",valueType:"integer",maxLength:void 0,defaultValue:void 0}, -sd:{id:"tcpConnectTime",name:"tcp",valueType:"integer",maxLength:void 0,defaultValue:void 0},nd:{id:"serverResponseTime",name:"srt",valueType:"integer",maxLength:void 0,defaultValue:void 0},fd:{id:"pageDownloadTime",name:"pdt",valueType:"integer",maxLength:void 0,defaultValue:void 0},jd:{id:"redirectResponseTime",name:"rrt",valueType:"integer",maxLength:void 0,defaultValue:void 0},td:{id:"timingCategory",name:"utc",valueType:"text",maxLength:150,defaultValue:void 0},wd:{id:"timingVar",name:"utv", -valueType:"text",maxLength:500,defaultValue:void 0},vd:{id:"timingValue",name:"utt",valueType:"integer",maxLength:void 0,defaultValue:void 0},ud:{id:"timingLabel",name:"utl",valueType:"text",maxLength:500,defaultValue:void 0},Tc:{id:"exDescription",name:"exd",valueType:"text",maxLength:150,defaultValue:void 0},Uc:{id:"exFatal",name:"exf",valueType:"boolean",maxLength:void 0,defaultValue:"1"}};var rb=function(a){k.setTimeout(function(){throw a;},0)},sb,tb=function(){var a=k.MessageChannel;"undefined"===typeof a&&"undefined"!==typeof window&&window.postMessage&&window.addEventListener&&(a=function(){var a=document.createElement("iframe");a.style.display="none";a.src="";document.documentElement.appendChild(a);var b=a.contentWindow,a=b.document;a.open();a.write("");a.close();var c="callImmediate"+Math.random(),d="file:"==b.location.protocol?"*":b.location.protocol+"//"+b.location.host,a=q(function(a){if(a.origin== -d||a.data==c)this.port1.onmessage()},this);b.addEventListener("message",a,!1);this.port1={};this.port2={postMessage:function(){b.postMessage(c,d)}}});if("undefined"!==typeof a){var b=new a,c={},d=c;b.port1.onmessage=function(){c=c.next;var a=c.rb;c.rb=null;a()};return function(a){d.next={rb:a};d=d.next;b.port2.postMessage(0)}}return"undefined"!==typeof document&&"onreadystatechange"in document.createElement("script")?function(a){var b=document.createElement("script");b.onreadystatechange=function(){b.onreadystatechange= -null;b.parentNode.removeChild(b);b=null;a();a=null};document.documentElement.appendChild(b)}:function(a){k.setTimeout(a,0)}};var zb=function(a,b){ub||vb();wb||(ub(),wb=!0);xb.push(new yb(a,b))},ub,vb=function(){if(k.Promise&&k.Promise.resolve){var a=k.Promise.resolve();ub=function(){a.then(Ab)}}else ub=function(){var a=Ab;p(k.setImmediate)?k.setImmediate(a):(sb||(sb=tb()),sb(a))}},wb=!1,xb=[],Ab=function(){for(;xb.length;){var a=xb;xb=[];for(var b=0;bb?1:0};var w=Array.prototype,ja=w.indexOf?function(a,b,c){return w.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(n(a))return n(b)&&1==b.length?a.indexOf(b,c):-1;for(;cb?null:n(a)?a.charAt(b):a[b]},pa=function(a,b){var c=ja(a,b),d;(d=0<=c)&&w.splice.call(a,c,1);return d},qa=function(a){return w.concat.apply(w, +arguments)},ra=function(a,b,c){return 2>=arguments.length?w.slice.call(a,b):w.slice.call(a,b,c)};var sa="StopIteration"in h?h.StopIteration:Error("StopIteration"),ta=function(){};ta.prototype.next=function(){throw sa;};ta.prototype.vc=function(){return this};var ua=function(a,b,c){for(var d in a)b.call(c,a[d],d,a)},va=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b},wa=function(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b},xa=function(a,b){var c;t:{for(c in a)if(b.call(void 0,a[c],c,a))break t;c=void 0}return c&&a[c]},ya="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),za=function(a,b){for(var c,d,e=1;e2*this.h&&Aa(this),!0):!1};var Aa=function(a){if(a.h!=a.b.length){for(var b=0,c=0;b=c.length)throw sa;var k=c[b++];return a?k:d[k]}};return k};var y=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};var Ba,Ca,Da={id:"hitType",name:"t",valueType:"text",maxLength:void 0,defaultValue:void 0},Ea={id:"sessionControl",name:"sc",valueType:"text",maxLength:void 0,defaultValue:void 0},Fa={id:"description",name:"cd",valueType:"text",maxLength:2048,defaultValue:void 0},Ga={id:"eventCategory",name:"ec",valueType:"text",maxLength:150,defaultValue:void 0},Ha={id:"eventAction",name:"ea",valueType:"text",maxLength:500,defaultValue:void 0},Ia={id:"eventLabel",name:"el",valueType:"text",maxLength:500,defaultValue:void 0}, +Ja={id:"eventValue",name:"ev",valueType:"integer",maxLength:void 0,defaultValue:void 0},Ka={pd:Da,Qc:{id:"anonymizeIp",name:"aip",valueType:"boolean",maxLength:void 0,defaultValue:void 0},Ad:{id:"queueTime",name:"qt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Wc:{id:"cacheBuster",name:"z",valueType:"text",maxLength:void 0,defaultValue:void 0},Gd:Ea,Wd:{id:"userId",name:"uid",valueType:"text",maxLength:void 0,defaultValue:void 0},xd:{id:"nonInteraction",name:"ni",valueType:"boolean", +maxLength:void 0,defaultValue:void 0},fd:Fa,Pd:{id:"title",name:"dt",valueType:"text",maxLength:1500,defaultValue:void 0},Sc:{id:"appId",name:"aid",valueType:"text",maxLength:150,defaultValue:void 0},Tc:{id:"appInstallerId",name:"aiid",valueType:"text",maxLength:150,defaultValue:void 0},jd:Ga,hd:Ha,kd:Ia,ld:Ja,Id:{id:"socialNetwork",name:"sn",valueType:"text",maxLength:50,defaultValue:void 0},Hd:{id:"socialAction",name:"sa",valueType:"text",maxLength:50,defaultValue:void 0},Jd:{id:"socialTarget", +name:"st",valueType:"text",maxLength:2048,defaultValue:void 0},Sd:{id:"transactionId",name:"ti",valueType:"text",maxLength:500,defaultValue:void 0},Rd:{id:"transactionAffiliation",name:"ta",valueType:"text",maxLength:500,defaultValue:void 0},Td:{id:"transactionRevenue",name:"tr",valueType:"currency",maxLength:void 0,defaultValue:void 0},Ud:{id:"transactionShipping",name:"ts",valueType:"currency",maxLength:void 0,defaultValue:void 0},Vd:{id:"transactionTax",name:"tt",valueType:"currency",maxLength:void 0, +defaultValue:void 0},dd:{id:"currencyCode",name:"cu",valueType:"text",maxLength:10,defaultValue:void 0},td:{id:"itemPrice",name:"ip",valueType:"currency",maxLength:void 0,defaultValue:void 0},ud:{id:"itemQuantity",name:"iq",valueType:"integer",maxLength:void 0,defaultValue:void 0},rd:{id:"itemCode",name:"ic",valueType:"text",maxLength:500,defaultValue:void 0},sd:{id:"itemName",name:"in",valueType:"text",maxLength:500,defaultValue:void 0},qd:{id:"itemCategory",name:"iv",valueType:"text",maxLength:500, +defaultValue:void 0},bd:{id:"campaignSource",name:"cs",valueType:"text",maxLength:100,defaultValue:void 0},$c:{id:"campaignMedium",name:"cm",valueType:"text",maxLength:50,defaultValue:void 0},ad:{id:"campaignName",name:"cn",valueType:"text",maxLength:100,defaultValue:void 0},Zc:{id:"campaignKeyword",name:"ck",valueType:"text",maxLength:500,defaultValue:void 0},Xc:{id:"campaignContent",name:"cc",valueType:"text",maxLength:500,defaultValue:void 0},Yc:{id:"campaignId",name:"ci",valueType:"text",maxLength:100, +defaultValue:void 0},od:{id:"gclid",name:"gclid",valueType:"text",maxLength:void 0,defaultValue:void 0},ed:{id:"dclid",name:"dclid",valueType:"text",maxLength:void 0,defaultValue:void 0},zd:{id:"pageLoadTime",name:"plt",valueType:"integer",maxLength:void 0,defaultValue:void 0},gd:{id:"dnsTime",name:"dns",valueType:"integer",maxLength:void 0,defaultValue:void 0},Kd:{id:"tcpConnectTime",name:"tcp",valueType:"integer",maxLength:void 0,defaultValue:void 0},Fd:{id:"serverResponseTime",name:"srt",valueType:"integer", +maxLength:void 0,defaultValue:void 0},yd:{id:"pageDownloadTime",name:"pdt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Bd:{id:"redirectResponseTime",name:"rrt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Ld:{id:"timingCategory",name:"utc",valueType:"text",maxLength:150,defaultValue:void 0},Od:{id:"timingVar",name:"utv",valueType:"text",maxLength:500,defaultValue:void 0},Nd:{id:"timingValue",name:"utt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Md:{id:"timingLabel", +name:"utl",valueType:"text",maxLength:500,defaultValue:void 0},md:{id:"exDescription",name:"exd",valueType:"text",maxLength:150,defaultValue:void 0},nd:{id:"exFatal",name:"exf",valueType:"boolean",maxLength:void 0,defaultValue:"1"}},La=function(a){if(1>a||200a||200a)return"0";if(3>a)return"1-2";a=Math.floor(Math.log(a-1)/Math.log(2));return Math.pow(2,a)+1+"-"+Math.pow(2,a+1)},Oa=function(a,b){for(var c=0,d=a.length-1,e=0;c<=d;){var f=Math.floor((c+d)/2),e=a[f];if(b<=e){d=0==f?0:a[f-1];if(b>d)return(d+1).toString()+"-"+e.toString();d=f-1}else if(b>e){if(f>=a.length-1)return(a[a.length-1]+1).toString()+"+";c=f+1}}return"<= 0"};var z=function(){this.ab=[]},Pa=function(){return new z};g=z.prototype;g.when=function(a){this.ab.push(a);return this};g.zb=function(a){var b=arguments;this.when(function(a){return 0<=ja(b,a.Gb())});return this};g.Oc=function(a,b){var c=ra(arguments,1);this.when(function(b){b=b.T().get(a);return 0<=ja(c,b)});return this};g.xb=function(a,b){if(q(this.e))throw Error("Filter has already been set.");this.e=q(b)?r(a,b):a;return this}; +g.Ca=function(){if(0==this.ab.length)throw Error("Must specify at least one predicate using #when or a helper method.");if(!q(this.e))throw Error("Must specify a delegate filter using #applyFilter.");return r(function(a){ma(this.ab,function(b){return b(a)})&&this.e(a)},this)};var A=function(){this.Ab=!1;this.Bb="";this.qb=!1;this.za=null};A.prototype.wc=function(a){this.Ab=!0;this.Bb=a||" - ";return this};A.prototype.Nc=function(){this.qb=!0;return this};A.prototype.Ec=function(){return Qa(this,Na)};A.prototype.Fc=function(a){return Qa(this,ha(Oa,a))}; +var Qa=function(a,b){if(null!=a.za)throw Error("LabelerBuilder: Only one labeling strategy may be used.");a.za=r(function(a){var d=a.T().get(Ja),e=a.T().get(Ia);ea(d)&&(d=b(d),null!=e&&this.Ab&&(d=e+this.Bb+d),a.T().set(Ia,d))},a);return a};A.prototype.Ca=function(){if(null==this.za)throw Error("LabelerBuilder: a labeling strategy must be specified prior to calling build().");return Pa().zb("event").xb(r(function(a){this.za(a);this.qb&&a.T().remove(Ja)},this)).Ca()};var Ra=function(a,b){var c=Array.prototype.slice.call(arguments),d=c.shift();if("undefined"==typeof d)throw Error("[goog.string.format] Template required");return d.replace(/%([0\-\ \+]*)(\d+)?(\.(\d+))?([%sfdiu])/g,function(a,b,d,l,N,J,U,V){if("%"==J)return"%";var Db=c.shift();if("undefined"==typeof Db)throw Error("[goog.string.format] Not enough arguments");arguments[0]=Db;return B[J].apply(null,arguments)})},B={s:function(a,b,c){return isNaN(c)||""==c||a.length>=c?a:a=-1a?"-":0<=b.indexOf("+")?"+":0<=b.indexOf(" ")?" ":"";0<=a&&(d=f+d);if(isNaN(c)||d.length>=c)return d;d=isNaN(e)?Math.abs(a).toString():Math.abs(a).toFixed(e);a=c-d.length-f.length;return d=0<=b.indexOf("-",0)?f+d+Array(a+1).join(" "):f+Array(a+1).join(0<=b.indexOf("0",0)?"0":" ")+d},d:function(a,b,c,d,e,f,k,l){return B.f(parseInt(a,10),b,c,d,0,f,k,l)}};B.i=B.d; +B.u=B.d;var Sa=function(a){if("function"==typeof a.t)return a.t();if(n(a))return a.split("");if(da(a)){for(var b=[],c=a.length,d=0;dparseFloat(a))?String(b):a}(),bb={},M=function(a){var b; +if(!(b=bb[a])){b=0;for(var c=String(ab).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),e=Math.max(c.length,d.length),f=0;0==b&&f=a.keyCode)a.keyCode=-1}catch(b){}};O.prototype.l=function(){};var jb="closure_listenable_"+(1E6*Math.random()|0),kb=function(a){return!(!a||!a[jb])},lb=0;var mb=function(a,b,c,d,e){this.O=a;this.proxy=null;this.src=b;this.type=c;this.pa=!!d;this.sa=e;this.key=++lb;this.removed=this.qa=!1},nb=function(a){a.removed=!0;a.O=null;a.proxy=null;a.src=null;a.sa=null};var P=function(a){this.src=a;this.j={};this.Z=0};P.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.j[f];a||(a=this.j[f]=[],this.Z++);var k=ob(a,b,d,e);-1e.keyCode||void 0!=e.returnValue)){t:{var f=!1;if(0==e.keyCode)try{e.keyCode=-1;break t}catch(k){f=!0}if(f||void 0==e.returnValue)e.returnValue=!0}e=[];for(f=c.currentTarget;f;f=f.parentNode)e.push(f);for(var f=a.type,l=e.length-1;!c.U&&0<=l;l--)c.currentTarget=e[l],d&=Fb(e[l],f,!0,c);for(l=0;!c.U&&l>>0),ub=function(a){if(p(a))return a;a[Gb]||(a[Gb]=function(b){return a.handleEvent(b)});return a[Gb]};var Q=function(){E.call(this);this.A=new P(this);this.kc=this;this.Qa=null};u(Q,E);Q.prototype[jb]=!0;g=Q.prototype;g.addEventListener=function(a,b,c,d){tb(this,a,b,c,d)};g.removeEventListener=function(a,b,c,d){Bb(this,a,b,c,d)}; +g.dispatchEvent=function(a){var b,c=this.Qa;if(c){b=[];for(var d=1;c;c=c.Qa)b.push(c),++d}c=this.kc;d=a.type||a;if(n(a))a=new F(a,c);else if(a instanceof F)a.target=a.target||c;else{var e=a;a=new F(d,c);za(a,e)}var e=!0,f;if(b)for(var k=b.length-1;!a.U&&0<=k;k--)f=a.currentTarget=b[k],e=Hb(f,d,!0,a)&&e;a.U||(f=a.currentTarget=c,e=Hb(f,d,!0,a)&&e,a.U||(e=Hb(f,d,!1,a)&&e));if(b)for(k=0;!a.U&&k=b.za&&b.cancel())}this.Ya?this.Ya.call(this.Xa,this):this.Ba=!0;this.C||this.v(new Mb)}};M.prototype.Za=function(a,b){this.Aa=!1;Nb(this,a,b)}; -var Nb=function(a,b,c){a.C=!0;a.t=c;a.R=!b;Ob(a)},Qb=function(a){if(a.C){if(!a.Ba)throw new Pb;a.Ba=!1}};M.prototype.F=function(a){Qb(this);Nb(this,!0,a)};M.prototype.v=function(a){Qb(this);Nb(this,!1,a)};M.prototype.H=function(a,b){return N(this,a,null,b)};var N=function(a,b,c,d){a.da.push([b,c,d]);a.C&&Ob(a);return a};M.prototype.then=function(a,b,c){var d,e,f=new L(function(a,b){d=a;e=b});N(this,d,function(a){a instanceof Mb?f.cancel():e(a)});return f.then(a,b,c)};Bb(M); -var Rb=function(a){var b=new M;N(a,b.F,b.v,b);return b},Tb=function(a){return ma(a.da,function(a){return p(a[1])})},Ob=function(a){if(a.ea&&a.C&&Tb(a)){var b=a.ea,c=Ub[b];c&&(k.clearTimeout(c.ga),delete Ub[b]);a.ea=0}a.n&&(a.n.za--,delete a.n);for(var b=a.t,d=c=!1;a.da.length&&!a.Aa;){var e=a.da.shift(),f=e[0],g=e[1],e=e[2];if(f=a.R?g:f)try{var l=f.call(e||a.Xa,b);void 0!==l&&(a.R=a.R&&(l==b||l instanceof Error),a.t=b=l);Cb(b)&&(d=!0,a.Aa=!0)}catch(J){b=J,a.R=!0,Tb(a)||(c=!0)}}a.t=b;d&&(l=q(a.Za, -a,!0),d=q(a.Za,a,!1),b instanceof M?(N(b,l,d),b.xb=!0):b.then(l,d));c&&(b=new Vb(b),Ub[b.ga]=b,a.ea=b.ga)},Wb=function(a){var b=new M;b.F(a);return b},Yb=function(){var a=Xb,b=new M;b.v(a);return b},Pb=function(){u.call(this)};t(Pb,u);Pb.prototype.message="Deferred has already fired";Pb.prototype.name="AlreadyCalledError";var Mb=function(){u.call(this)};t(Mb,u);Mb.prototype.message="Deferred was canceled";Mb.prototype.name="CanceledError"; -var Vb=function(a){this.ga=k.setTimeout(q(this.bc,this),0);this.ba=a};Vb.prototype.bc=function(){delete Ub[this.ga];throw this.ba;};var Ub={};var Zb=function(a,b){var c=Array.prototype.slice.call(arguments),d=c.shift();if("undefined"==typeof d)throw Error("[goog.string.format] Template required");return d.replace(/%([0\-\ \+]*)(\d+)?(\.(\d+))?([%sfdiu])/g,function(a,b,d,l,J,F,R,S){if("%"==F)return"%";var Sb=c.shift();if("undefined"==typeof Sb)throw Error("[goog.string.format] Not enough arguments");arguments[0]=Sb;return O[F].apply(null,arguments)})},O={s:function(a,b,c){return isNaN(c)||""==c||a.length>=c?a:a=-1a?"-":0<=b.indexOf("+")?"+":0<=b.indexOf(" ")?" ":"";0<=a&&(d=f+d);if(isNaN(c)||d.length>=c)return d;d=isNaN(e)?Math.abs(a).toString():Math.abs(a).toFixed(e);a=c-d.length-f.length;return d=0<=b.indexOf("-",0)?f+d+Array(a+1).join(" "):f+Array(a+1).join(0<=b.indexOf("0",0)?"0":" ")+d},d:function(a,b,c,d,e,f,g,l){return O.f(parseInt(a,10),b,c,d,0,f,g,l)}};O.i=O.d; -O.u=O.d;var $b=function(a){if("function"==typeof a.p)return a.p();if(n(a))return a.split("");if(da(a)){for(var b=[],c=a.length,d=0;db.maxLength&&a.set(b,c.substring(0,b.maxLength))})},Pc=function(a){bc(a,function(b,c){void 0!==b.defaultValue&&c==b.defaultValue&&a.remove(b)})};var Xb={status:"device-offline",ua:void 0},Qc={status:"rate-limited",ua:void 0},Rc={status:"sampled-out",ua:void 0},Sc={status:"sent",ua:void 0};var Tc=function(a,b){this.Mb=a;this.A=b};Tc.prototype.send=function(a,b){var c;c=this.Mb;var d=c.gb(),e=Math.floor((d-c.fb)*c.Hb);0c.V?c=!1:(c.V-=1,c=!0);return c||"item"==a||"transaction"==a?this.A.send(a,b):Wb(Qc)};var Uc=function(){this.V=60;this.Jb=500;this.Hb=5E-4;this.gb=function(){return(new Date).getTime()};this.fb=this.gb()};var Vc=function(a,b){this.j=a;this.A=b};Vc.prototype.send=function(a,b){var c=b.get(hc),c=parseInt(c.split("-")[1],16),d;"timing"!=a?d=this.j.Q:((d=b.get(kc))&&b.remove(kc),d||(d=this.j.Q));return c<655.36*d?this.A.send(a,b):Wb(Rc)};var Wc=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#(.*))?$/,Xc=B,Yc=function(a,b){if(Xc){Xc=!1;var c=k.location;if(c){var d=c.href;if(d&&(d=(d=Yc(3,d))&&decodeURIComponent(d))&&d!=c.hostname)throw Xc=!0,Error();}}return b.match(Wc)[a]||null};var Zc=function(){};Zc.prototype.qb=null;var ad=function(a){var b;(b=a.qb)||(b={},$c(a)&&(b[0]=!0,b[1]=!0),b=a.qb=b);return b};var bd,cd=function(){};t(cd,Zc);var dd=function(a){return(a=$c(a))?new ActiveXObject(a):new XMLHttpRequest},$c=function(a){if(!a.sb&&"undefined"==typeof XMLHttpRequest&&"undefined"!=typeof ActiveXObject){for(var b=["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],c=0;cthis.ia?c.v({status:"payload-too-big",ua:Zb("Encoded hit length == %s, but should be <= %s.",d.length,this.ia)}):hd(this.Lb,function(){c.F(Sc)},d);return c};var sd=function(a,b){var c=new pd;c.add(nb.name,a);bc(b,function(a,b){c.add(a.name,b.toString())});return c.toString()};var td=function(a,b,c){this.j=a;this.Cb=b;this.ia=c};td.prototype.Ja=function(){if(!this.q){var a=this.j;if(!Rb(a.ca).C)throw Error("Cannot construct shared channel prior to settings being ready.");new Y;var b=new Nc(new rd(this.Cb,this.ia)),c=new Uc;this.q=new Mc(a,new Vc(a,new Tc(c,b)))}return this.q};var ud=new H,vd=function(){if(!lb){var a=new Ec("google-analytics");lb=new V(a)}return lb};s("goog.async.Deferred",M);s("goog.async.Deferred.prototype.addCallback",M.prototype.H);s("goog.events.EventTarget",G);s("goog.events.EventTarget.prototype.listen",G.prototype.listen);s("analytics.getService",function(a){var b=ud.get(a,null);if(null===b){var b=chrome.runtime.getManifest().version,c=vd();if(!mb){var d=vd();mb=new Hc(d,new td(d,"https://www.google-analytics.com/collect",8192))}b=new U("ca1.5.0",a,b,c,mb);ud.set(a,b)}return b});s("analytics.internal.GoogleAnalyticsService",U); -s("analytics.internal.GoogleAnalyticsService.prototype.getTracker",U.prototype.nc);s("analytics.internal.GoogleAnalyticsService.prototype.getConfig",U.prototype.kc);s("analytics.internal.ServiceSettings",V);s("analytics.internal.ServiceSettings.prototype.setTrackingPermitted",V.prototype.tc);s("analytics.internal.ServiceSettings.prototype.isTrackingPermitted",V.prototype.pa);s("analytics.internal.ServiceSettings.prototype.setSampleRate",V.prototype.sc);s("analytics.internal.ServiceTracker",T); -s("analytics.internal.ServiceTracker.prototype.send",T.prototype.send);s("analytics.internal.ServiceTracker.prototype.sendAppView",T.prototype.oc);s("analytics.internal.ServiceTracker.prototype.sendEvent",T.prototype.pc);s("analytics.internal.ServiceTracker.prototype.sendSocial",T.prototype.rc);s("analytics.internal.ServiceTracker.prototype.sendException",T.prototype.qc);s("analytics.internal.ServiceTracker.prototype.sendTiming",T.prototype.ob); -s("analytics.internal.ServiceTracker.prototype.startTiming",T.prototype.uc);s("analytics.internal.ServiceTracker.Timing",sc);s("analytics.internal.ServiceTracker.Timing.prototype.send",sc.prototype.send);s("analytics.internal.ServiceTracker.prototype.forceSessionStart",T.prototype.jc);s("analytics.internal.ServiceTracker.prototype.addFilter",T.prototype.N);s("analytics.internal.FilterChannel.Hit",Q);s("analytics.internal.FilterChannel.Hit.prototype.getHitType",Q.prototype.lc); -s("analytics.internal.FilterChannel.Hit.prototype.getParameters",Q.prototype.mc);s("analytics.internal.FilterChannel.Hit.prototype.cancel",Q.prototype.cancel);s("analytics.ParameterMap",P);s("analytics.ParameterMap.Entry",P.Entry);s("analytics.ParameterMap.prototype.set",P.prototype.set);s("analytics.ParameterMap.prototype.get",P.prototype.get);s("analytics.ParameterMap.prototype.remove",P.prototype.remove);s("analytics.ParameterMap.prototype.toObject",P.prototype.vb); -s("analytics.HitTypes.APPVIEW","appview");s("analytics.HitTypes.EVENT","event");s("analytics.HitTypes.SOCIAL","social");s("analytics.HitTypes.TRANSACTION","transaction");s("analytics.HitTypes.ITEM","item");s("analytics.HitTypes.TIMING","timing");s("analytics.HitTypes.EXCEPTION","exception");ra(qb,function(a){var b=a.id.replace(/[A-Z]/,"_$&").toUpperCase();s("analytics.Parameters."+b,a)}); })() +var S=function(a,b){this.ja=[];this.hb=a;this.gb=b||null;this.W=this.C=!1;this.v=void 0;this.Ka=this.Lb=this.Ja=!1;this.ka=0;this.o=null;this.Ia=0};S.prototype.cancel=function(a){if(this.C)this.v instanceof S&&this.v.cancel();else{if(this.o){var b=this.o;delete this.o;a?b.cancel(a):(b.Ia--,0>=b.Ia&&b.cancel())}this.hb?this.hb.call(this.gb,this):this.Ka=!0;this.C||this.w(new dc)}};S.prototype.ib=function(a,b){this.Ja=!1;ec(this,a,b)}; +var ec=function(a,b,c){a.C=!0;a.v=c;a.W=!b;fc(a)},hc=function(a){if(a.C){if(!a.Ka)throw new gc;a.Ka=!1}};S.prototype.G=function(a){hc(this);ec(this,!0,a)};S.prototype.w=function(a){hc(this);ec(this,!1,a)};S.prototype.J=function(a,b){return ic(this,a,null,b)};var ic=function(a,b,c,d){a.ja.push([b,c,d]);a.C&&fc(a);return a};S.prototype.then=function(a,b,c){var d,e,f=new R(function(a,b){d=a;e=b});ic(this,d,function(a){a instanceof dc?f.cancel():e(a)});return f.then(a,b,c)};Sb(S); +var jc=function(a){var b=new S;ic(a,b.G,b.w,b);return b},kc=function(a){return la(a.ja,function(a){return p(a[1])})},fc=function(a){if(a.ka&&a.C&&kc(a)){var b=a.ka,c=lc[b];c&&(h.clearTimeout(c.ma),delete lc[b]);a.ka=0}a.o&&(a.o.Ia--,delete a.o);for(var b=a.v,d=c=!1;a.ja.length&&!a.Ja;){var e=a.ja.shift(),f=e[0],k=e[1],e=e[2];if(f=a.W?k:f)try{var l=f.call(e||a.gb,b);void 0!==l&&(a.W=a.W&&(l==b||l instanceof Error),a.v=b=l);Tb(b)&&(d=!0,a.Ja=!0)}catch(N){b=N,a.W=!0,kc(a)||(c=!0)}}a.v=b;d&&(l=r(a.ib, +a,!0),d=r(a.ib,a,!1),b instanceof S?(ic(b,l,d),b.Lb=!0):b.then(l,d));c&&(b=new mc(b),lc[b.ma]=b,a.ka=b.ma)},nc=function(a){var b=new S;b.G(a);return b},pc=function(){var a=oc,b=new S;b.w(a);return b},gc=function(){v.call(this)};u(gc,v);gc.prototype.message="Deferred has already fired";gc.prototype.name="AlreadyCalledError";var dc=function(){v.call(this)};u(dc,v);dc.prototype.message="Deferred was canceled";dc.prototype.name="CanceledError"; +var mc=function(a){this.ma=h.setTimeout(r(this.pc,this),0);this.ga=a};mc.prototype.pc=function(){delete lc[this.ma];throw this.ga;};var lc={};var qc=function(a){this.$a=[];this.e=a};qc.prototype.S=function(a){if(!p(a))throw Error("Invalid filter. Must be a function.");this.$a.push(a)};qc.prototype.send=function(a,b){for(var c=new T(a,b),d=0;db.maxLength&&a.set(b,c.substring(0,b.maxLength))})},ed=function(a){Ua(a,function(b,c){void 0!==b.defaultValue&&c==b.defaultValue&&a.remove(b)})};var oc={status:"device-offline",Ba:void 0},fd={status:"rate-limited",Ba:void 0},gd={status:"sampled-out",Ba:void 0},hd={status:"sent",Ba:void 0};var id=function(a,b){this.Wb=a;this.e=b};id.prototype.send=function(a,b){var c;c=this.Wb;var d=c.pb(),e=Math.floor((d-c.ob)*c.Sb);0c.$?c=!1:(c.$-=1,c=!0);return c||"item"==a||"transaction"==a?this.e.send(a,b):nc(fd)};var jd=function(){this.$=60;this.Tb=500;this.Sb=5E-4;this.pb=function(){return(new Date).getTime()};this.ob=this.pb()};var kd=function(a,b){this.k=a;this.e=b};kd.prototype.send=function(a,b){var c=b.get(vc),c=parseInt(c.split("-")[1],16),d;"timing"!=a?d=this.k.V:((d=b.get(yc))&&b.remove(yc),d||(d=this.k.V));return c<655.36*d?this.e.send(a,b):nc(gd)};var ld=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#(.*))?$/,md=L,nd=function(a,b){if(md){md=!1;var c=h.location;if(c){var d=c.href;if(d&&(d=(d=nd(3,d))?decodeURI(d):d)&&d!=c.hostname)throw md=!0,Error();}}return b.match(ld)[a]||null};var od=function(){};od.prototype.Eb=null;var qd=function(a){var b;(b=a.Eb)||(b={},pd(a)&&(b[0]=!0,b[1]=!0),b=a.Eb=b);return b};var rd,sd=function(){};u(sd,od);var td=function(a){return(a=pd(a))?new ActiveXObject(a):new XMLHttpRequest},pd=function(a){if(!a.Hb&&"undefined"==typeof XMLHttpRequest&&"undefined"!=typeof ActiveXObject){for(var b=["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],c=0;cthis.na?c.w({status:"payload-too-big",Ba:Ra("Encoded hit length == %s, but should be <= %s.",d.length,this.na)}):xd(this.$b,function(){c.G(hd)},d);return c};var Jd=function(a,b){var c=new Fd;c.add(Da.name,a);Ua(b,function(a,b){c.add(a.name,b.toString())});return c.toString()};var Kd=function(a,b,c){this.k=a;this.Qb=b;this.na=c};Kd.prototype.Sa=function(){if(!this.q){var a=this.k;if(!jc(a.ha).C)throw Error("Cannot construct shared channel prior to settings being ready.");new ad;var b=new cd(new Id(this.Qb,this.na)),c=new jd;this.q=new bd(a,new kd(a,new id(c,b)))}return this.q};var Ld=new x,Md=function(){if(!Ba){var a=new Tc("google-analytics");Ba=new X(a)}return Ba};t("goog.async.Deferred",S);t("goog.async.Deferred.prototype.addCallback",S.prototype.J);t("goog.events.EventTarget",Q);t("goog.events.EventTarget.prototype.listen",Q.prototype.listen);t("analytics.getService",function(a){var b=Ld.get(a,null);if(null===b){var b=chrome.runtime.getManifest().version,c=Md();if(!Ca){var d=Md();Ca=new Wc(d,new Kd(d,"https://www.google-analytics.com/collect",8192))}b=new Hc("ca1.5.2",a,b,c,Ca);Ld.set(a,b)}return b});t("analytics.internal.GoogleAnalyticsService",Hc); +t("analytics.internal.GoogleAnalyticsService.prototype.getTracker",Hc.prototype.Cc);t("analytics.internal.GoogleAnalyticsService.prototype.getConfig",Hc.prototype.Bc);t("analytics.internal.ServiceSettings",X);t("analytics.internal.ServiceSettings.prototype.setTrackingPermitted",X.prototype.Lc);t("analytics.internal.ServiceSettings.prototype.isTrackingPermitted",X.prototype.va);t("analytics.internal.ServiceSettings.prototype.setSampleRate",X.prototype.Kc);t("analytics.internal.ServiceTracker",W); +t("analytics.internal.ServiceTracker.prototype.send",W.prototype.send);t("analytics.internal.ServiceTracker.prototype.sendAppView",W.prototype.Gc);t("analytics.internal.ServiceTracker.prototype.sendEvent",W.prototype.Hc);t("analytics.internal.ServiceTracker.prototype.sendSocial",W.prototype.Jc);t("analytics.internal.ServiceTracker.prototype.sendException",W.prototype.Ic);t("analytics.internal.ServiceTracker.prototype.sendTiming",W.prototype.Cb); +t("analytics.internal.ServiceTracker.prototype.startTiming",W.prototype.Mc);t("analytics.internal.ServiceTracker.Timing",Gc);t("analytics.internal.ServiceTracker.Timing.prototype.send",Gc.prototype.send);t("analytics.internal.ServiceTracker.prototype.forceSessionStart",W.prototype.Ac);t("analytics.internal.ServiceTracker.prototype.addFilter",W.prototype.S);t("analytics.internal.FilterChannel.Hit",T);t("analytics.internal.FilterChannel.Hit.prototype.getHitType",T.prototype.Gb); +t("analytics.internal.FilterChannel.Hit.prototype.getParameters",T.prototype.T);t("analytics.internal.FilterChannel.Hit.prototype.cancel",T.prototype.cancel);t("analytics.ParameterMap",C);t("analytics.ParameterMap.Entry",C.Entry);t("analytics.ParameterMap.prototype.set",C.prototype.set);t("analytics.ParameterMap.prototype.get",C.prototype.get);t("analytics.ParameterMap.prototype.remove",C.prototype.remove);t("analytics.ParameterMap.prototype.toObject",C.prototype.Jb); +t("analytics.HitTypes.APPVIEW","appview");t("analytics.HitTypes.EVENT","event");t("analytics.HitTypes.SOCIAL","social");t("analytics.HitTypes.TRANSACTION","transaction");t("analytics.HitTypes.ITEM","item");t("analytics.HitTypes.TIMING","timing");t("analytics.HitTypes.EXCEPTION","exception");ua(Ka,function(a){var b=a.id.replace(/[A-Z]/,"_$&").toUpperCase();t("analytics.Parameters."+b,a)});t("analytics.filters.EventLabelerBuilder",A); +t("analytics.filters.EventLabelerBuilder.prototype.appendToExistingLabel",A.prototype.wc);t("analytics.filters.EventLabelerBuilder.prototype.stripValue",A.prototype.Nc);t("analytics.filters.EventLabelerBuilder.prototype.powersOfTwo",A.prototype.Ec);t("analytics.filters.EventLabelerBuilder.prototype.rangeBounds",A.prototype.Fc);t("analytics.filters.EventLabelerBuilder.prototype.build",A.prototype.Ca);t("analytics.filters.FilterBuilder",z);t("analytics.filters.FilterBuilder.builder",Pa); +t("analytics.filters.FilterBuilder.prototype.when",z.prototype.when);t("analytics.filters.FilterBuilder.prototype.whenHitType",z.prototype.zb);t("analytics.filters.FilterBuilder.prototype.whenValue",z.prototype.Oc);t("analytics.filters.FilterBuilder.prototype.applyFilter",z.prototype.xb);t("analytics.filters.FilterBuilder.prototype.build",z.prototype.Ca);t("analytics.EventBuilder",D);t("analytics.EventBuilder.builder",function(){return Va});t("analytics.EventBuilder.prototype.category",D.prototype.xc); +t("analytics.EventBuilder.prototype.action",D.prototype.action);t("analytics.EventBuilder.prototype.label",D.prototype.label);t("analytics.EventBuilder.prototype.value",D.prototype.value);t("analytics.EventBuilder.prototype.dimension",D.prototype.yc);t("analytics.EventBuilder.prototype.metric",D.prototype.Dc);t("analytics.EventBuilder.prototype.send",D.prototype.send); })() From 25edf3a4bfd78d0e573e3e1223540111c711733a Mon Sep 17 00:00:00 2001 From: cTn Date: Sat, 13 Sep 2014 15:01:32 +0200 Subject: [PATCH 018/213] improving the async transmission part in serial layer --- js/serial.js | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/js/serial.js b/js/serial.js index d7c4ac85..63558008 100644 --- a/js/serial.js +++ b/js/serial.js @@ -129,36 +129,48 @@ var serial = { }, send: function (data, callback) { var self = this; - self.output_buffer.push({'data': data, 'callback': callback}); + this.output_buffer.push({'data': data, 'callback': callback}); - if (!self.transmitting) { - self.transmitting = true; + if (!this.transmitting) { + this.transmitting = true; - var sending = function () { + var send = function () { // store inside separate variables in case array gets destroyed var data = self.output_buffer[0].data, callback = self.output_buffer[0].callback; chrome.serial.send(self.connectionId, data, function (sendInfo) { - callback(sendInfo); - self.output_buffer.shift(); - + // track sent bytes for statistics self.bytes_sent += sendInfo.bytesSent; + // fire callback + callback(sendInfo); + + // remove data for current transmission form the buffer + self.output_buffer.shift(); + + // if there is any data in the queue fire send immediately, otherwise stop trasmitting if (self.output_buffer.length) { // keep the buffer withing reasonable limits - while (self.output_buffer.length > 500) { - self.output_buffer.pop(); + if (self.output_buffer.length > 100) { + var counter = 0; + + while (self.output_buffer.length > 100) { + self.output_buffer.pop(); + counter++; + } + + console.log('SERIAL: Send buffer overflowing, dropped: ' + counter + ' entries'); } - sending(); + send(); } else { self.transmitting = false; } }); }; - sending(); + send(); } }, onReceive: { From 619f9032be9b9c3b6ab51113f49fb1f70018d8cc Mon Sep 17 00:00:00 2001 From: cTn Date: Sun, 14 Sep 2014 01:27:50 +0200 Subject: [PATCH 019/213] css3D hack replaced by a flying brick done in three js --- tabs/initial_setup.css | 84 ++++------------------------------------- tabs/initial_setup.html | 18 ++------- tabs/initial_setup.js | 77 +++++++++++++++++++++++++++++++++---- 3 files changed, 81 insertions(+), 98 deletions(-) diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index 0eb0eddb..6e7a0a26 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -107,83 +107,15 @@ #interactive_block a.reset:hover { background-color: #dedcdc; } - #perspective { - height: calc(100% - 25px); - -webkit-perspective: 800; + #canvas_wrapper { + position: absolute; + + width: 100%; + height: 100%; + + top: 0; + left: 0; } - #cube { - position: relative; - top: calc(50% - 50px); /* - half of height */ - left: calc(50% - 50px); /* - half of width */ - - height: 100px; - width: 100px; - - -webkit-transform-style: preserve-3d; - } - #cubePITCH { - -webkit-transform-style: preserve-3d; - } - #cubeROLL { - -webkit-transform-style: preserve-3d; - } - #cube .face { - position: absolute; - - color: white; - font-size: 25px; - text-align: center; - } - #cube .face.one { - width: 100%; - height: 200px; - line-height: 200px; - - font-size: 20px; - - -webkit-transform: rotateX(-90deg) translateZ(-50px); - background-color: purple; - } - #cube .face.two { - width: 100%; - height: 50px; - line-height: 50px; - - -webkit-transform: translateZ(100px); - background-color: blue; - } - #cube .face.three { - width: 200px; - height: 50px; - line-height: 50px; - - -webkit-transform: rotateY(90deg); - background-color: green; - } - #cube .face.four { - width: 100%; - height: 50px; - line-height: 50px; - - -webkit-transform: rotateY(180deg) translateZ(100px); - background-color: black; - } - #cube .face.five { - width: 200px; - height: 50px; - line-height: 50px; - - -webkit-transform: rotateY(-90deg) translateZ(100px); - background-color: red; - } - #cube .face.six { - width: 100%; - height: 200px; - line-height: 200px; - - -webkit-transform: rotateX(90deg) translateZ(100px); - background-color: silver; - } .tab-initial_setup .block_wrapper { font-size: 0; } diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index f3732e7e..0db8182e 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -21,25 +21,13 @@

+
+ +
-
-
-
-
-
-
BOTTOM
-
BACK
-
RIGHT
-
FRONT
-
LEFT
-
TOP
-
-
-
-
diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 1b1a12b3..4e868fdd 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -28,6 +28,9 @@ TABS.initial_setup.initialize = function (callback) { // translate to user-selected language localize(); + // initialize 3D + self.initialize3D(); + // Fill in misc stuff $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); @@ -273,15 +276,11 @@ TABS.initial_setup.initialize = function (callback) { $('.bat-mah-drawing').text(chrome.i18n.getMessage('initialSetupBatteryAValue', [ANALOG.amperage.toFixed(2)])); $('.rssi').text(chrome.i18n.getMessage('initialSetupRSSIValue', [((ANALOG.rssi / 1023) * 100).toFixed(0)])); - // Update cube - var cube = $('div#cube'); - - cube.css('-webkit-transform', 'rotateY(' + ((SENSOR_DATA.kinematics[2] * -1.0) - self.yaw_fix) + 'deg)'); - $('#cubePITCH', cube).css('-webkit-transform', 'rotateX(' + SENSOR_DATA.kinematics[1] + 'deg)'); - $('#cubeROLL', cube).css('-webkit-transform', 'rotateZ(' + SENSOR_DATA.kinematics[0] + 'deg)'); - // Update heading $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [SENSOR_DATA.kinematics[2]])); + + // Update 3D + self.render3D(); } GUI.interval_add('initial_setup_data_pull', get_analog_data, 50, true); @@ -295,6 +294,70 @@ TABS.initial_setup.initialize = function (callback) { } }; +TABS.initial_setup.initialize3D = function () { + var self = this; + var canvas = $('#canvas'); + var wrapper = $('#canvas_wrapper'); + + var camera = new THREE.PerspectiveCamera(50, wrapper.width() / wrapper.height(), 1, 10000); + var renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true}); + var scene = new THREE.Scene(); + + // some light + var light = new THREE.DirectionalLight(new THREE.Color(1,1,1), 0.5); + light.position.set(0, 1, 0); + + // flying brick + var modelWrapper = new THREE.Object3D(); + var geometry = new THREE.BoxGeometry(150, 80, 300); + var materialArray = [ + new THREE.MeshLambertMaterial({color: 0xff3333, emissive: 0x962020}), // right + new THREE.MeshLambertMaterial({color: 0xff8800, emissive: 0xa45a06}), // left + new THREE.MeshLambertMaterial({color: 0xffff33, emissive: 0x9a9a21}), // top + new THREE.MeshLambertMaterial({color: 0x33ff33, emissive: 0x1f901f}), // bottom + new THREE.MeshLambertMaterial({color: 0x3333ff, emissive: 0x212192}), // back + new THREE.MeshLambertMaterial({color: 0x8833ff, emissive: 0x5620a2}), // front + ]; + var materials = new THREE.MeshFaceMaterial(materialArray); + var model = new THREE.Mesh(geometry, materials); + + // initialize render size for current canvas size + renderer.setSize(wrapper.width(), wrapper.height()); + + // move camera away from the model + camera.position.z = 500; + + // modelWrapper just adds an extra axis of rotation to avoid gimbal lock withe euler angles + modelWrapper.add(model); + + // add camera, model, light to the foreground scene + scene.add(camera); + scene.add(modelWrapper); + scene.add(light); + + + this.render3D = function () { + // compute the changes + model.rotation.x = (SENSOR_DATA.kinematics[1] * -1.0) * 0.017453292519943295; + modelWrapper.rotation.y = ((SENSOR_DATA.kinematics[2] * -1.0) - self.yaw_fix) * 0.017453292519943295; + model.rotation.z = (SENSOR_DATA.kinematics[0] * -1.0) * 0.017453292519943295; + + // draw + renderer.render(scene, camera); + }; + + // handle canvas resize + $(window).resize(function () { + renderer.setSize(wrapper.width(), wrapper.height()); + camera.aspect = wrapper.width() / wrapper.height(); + camera.updateProjectionMatrix(); + + self.render3D(); + }); +}; + TABS.initial_setup.cleanup = function (callback) { + $(window).unbind('resize'); + if (callback) callback(); }; \ No newline at end of file From e20806c7a853f1747dc9a895be1fc341bb864bf2 Mon Sep 17 00:00:00 2001 From: cTn Date: Sun, 14 Sep 2014 14:08:28 +0200 Subject: [PATCH 020/213] only fire recovery routine once if bus is not recoverable --- js/serial.js | 56 ++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/js/serial.js b/js/serial.js index 63558008..faff2338 100644 --- a/js/serial.js +++ b/js/serial.js @@ -1,10 +1,11 @@ 'use strict'; var serial = { - connectionId: -1, - bitrate: 0, - bytes_received: 0, - bytes_sent: 0, + connectionId: -1, + bitrate: 0, + bytes_received: 0, + bytes_sent: 0, + failed: 0, transmitting: false, output_buffer: [], @@ -18,6 +19,7 @@ var serial = { self.bitrate = connectionInfo.bitrate; self.bytes_received = 0; self.bytes_sent = 0; + self.failed = 0; self.onReceive.addListener(function log_bytes_received(info) { self.bytes_received += info.data.byteLength; @@ -29,32 +31,34 @@ var serial = { switch (info.error) { case 'system_error': // we might be able to recover from this one - var crunch_status = function (info) { - if (info) { - if (!info.paused) { - console.log('SERIAL: Connection recovered from last onReceiveError'); - googleAnalytics.sendException('Serial: onReceiveError - recovered', false); - } else { - console.log('SERIAL: Connection did not recover from last onReceiveError, disconnecting'); - GUI.log('Unrecoverable failure of serial connection, disconnecting...'); - googleAnalytics.sendException('Serial: onReceiveError - unrecoverable', false); + if (!self.failed++) { + chrome.serial.setPaused(self.connectionId, false, function () { + self.getInfo(function (info) { + if (info) { + if (!info.paused) { + console.log('SERIAL: Connection recovered from last onReceiveError'); + googleAnalytics.sendException('Serial: onReceiveError - recovered', false); - if (GUI.connected_to || GUI.connecting_to) { - $('a.connect').click(); + self.failed = 0; + } else { + console.log('SERIAL: Connection did not recover from last onReceiveError, disconnecting'); + GUI.log('Unrecoverable failure of serial connection, disconnecting...'); + googleAnalytics.sendException('Serial: onReceiveError - unrecoverable', false); + + if (GUI.connected_to || GUI.connecting_to) { + $('a.connect').click(); + } else { + self.disconnect(); + } + } } else { - self.disconnect(); + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError.message); + } } - } - } else { - if (chrome.runtime.lastError) { - console.error(chrome.runtime.lastError.message); - } - } + }); + }); } - - chrome.serial.setPaused(self.connectionId, false, function () { - self.getInfo(crunch_status); - }); break; case 'timeout': // TODO From 5b3da95e0515ec82d17547906c5df6f32136c909 Mon Sep 17 00:00:00 2001 From: cTn Date: Sun, 14 Sep 2014 20:38:39 +0200 Subject: [PATCH 021/213] add fallback to canvasrenderer on cros and linux (temporary) --- tabs/initial_setup.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 4e868fdd..0b6aa204 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -300,7 +300,13 @@ TABS.initial_setup.initialize3D = function () { var wrapper = $('#canvas_wrapper'); var camera = new THREE.PerspectiveCamera(50, wrapper.width() / wrapper.height(), 1, 10000); - var renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true}); + + var renderer; + if (GUI.operating_system != 'Linux' || GUI.operating_system != 'CrOS') { + renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true}); + } else { + renderer = new THREE.CanvasRenderer({canvas: canvas.get(0), alpha: true}); + } var scene = new THREE.Scene(); // some light @@ -310,13 +316,13 @@ TABS.initial_setup.initialize3D = function () { // flying brick var modelWrapper = new THREE.Object3D(); var geometry = new THREE.BoxGeometry(150, 80, 300); - var materialArray = [ - new THREE.MeshLambertMaterial({color: 0xff3333, emissive: 0x962020}), // right - new THREE.MeshLambertMaterial({color: 0xff8800, emissive: 0xa45a06}), // left - new THREE.MeshLambertMaterial({color: 0xffff33, emissive: 0x9a9a21}), // top - new THREE.MeshLambertMaterial({color: 0x33ff33, emissive: 0x1f901f}), // bottom - new THREE.MeshLambertMaterial({color: 0x3333ff, emissive: 0x212192}), // back - new THREE.MeshLambertMaterial({color: 0x8833ff, emissive: 0x5620a2}), // front + var materialArray = [ // overdraw helps remove wireframe when using CanvasRenderer + new THREE.MeshLambertMaterial({color: 0xff3333, emissive: 0x962020, overdraw: true}), // right + new THREE.MeshLambertMaterial({color: 0xff8800, emissive: 0xa45a06, overdraw: true}), // left + new THREE.MeshLambertMaterial({color: 0xffff33, emissive: 0x9a9a21, overdraw: true}), // top + new THREE.MeshLambertMaterial({color: 0x33ff33, emissive: 0x1f901f, overdraw: true}), // bottom + new THREE.MeshLambertMaterial({color: 0x3333ff, emissive: 0x212192, overdraw: true}), // back + new THREE.MeshLambertMaterial({color: 0x8833ff, emissive: 0x5620a2, overdraw: true}), // front ]; var materials = new THREE.MeshFaceMaterial(materialArray); var model = new THREE.Mesh(geometry, materials); From 97d3a24787aabc850d212a8e10709473508e6802 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 13:36:10 +0200 Subject: [PATCH 022/213] update msp layer with new transmission codes, add transparent methods to handle the incoming data (temporary) --- js/msp.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/js/msp.js b/js/msp.js index be8c8124..36aa9122 100644 --- a/js/msp.js +++ b/js/msp.js @@ -50,7 +50,14 @@ var MSP_codes = { MSP_UID: 160, // Unique device ID MSP_ACC_TRIM: 240, // get acc angle trim values MSP_SET_ACC_TRIM: 239, // set acc angle trim values - MSP_GPSSVINFO: 164 // get Signal Strength (only U-Blox) + MSP_GPSSVINFO: 164, // get Signal Strength (only U-Blox) + + // Additional private MSP for baseflight configurator (yes thats us \o/) + MSP_RCMAP: 64, // get channel map (also returns number of channels total) + MSP_SET_RCMAP: 65, // set rc map, numchannels to set comes from MSP_RCMAP + MSP_CONFIG: 66, // baseflight-specific settings that aren't covered elsewhere + MSP_SET_CONFIG: 67, // baseflight-specific settings save + MSP_SET_REBOOT: 68 // reboot settings }; var MSP = { @@ -448,6 +455,17 @@ MSP.process_data = function(code, message_buffer, message_length) { } } break; + // Additional private MSP for baseflight configurator + case MSP_codes.MSP_RCMAP: + break; + case MSP_codes.MSP_SET_RCMAP: + break; + case MSP_codes.MSP_CONFIG: + break; + case MSP_codes.MSP_SET_CONFIG: + break; + case MSP_codes.MSP_SET_REBOOT: + break; default: console.log('Unknown code detected: ' + code); From 7e8b1781dadc753fe94a23a955eb29a0c8331601 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 14:48:36 +0200 Subject: [PATCH 023/213] add RC_MAP, BF_CONFIG for storing new info that is now available, working channelLetter mapping, unfinished MISCv2 --- js/data_storage.js | 30 ++++++++++++++++++++++++++++++ js/msp.js | 15 +++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/js/data_storage.js b/js/data_storage.js index f073d195..920a2046 100644 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -23,12 +23,24 @@ var CONFIG = { accelerometerTrims: [0, 0] }; +var BF_CONFIG = { + mixerConfiguration: 0, + features: 0, + serialrx_type: 0, + board_align_roll: 0, + board_align_pitch: 0, + board_align_yaw: 0 + // TBD +}; + var PID_names = []; var PIDs = new Array(10); for (var i = 0; i < 10; i++) { PIDs[i] = new Array(3); } +var RC_MAP = []; + // defaults // roll, pitch, yaw, throttle, aux 1, ... aux n var RC = { @@ -103,4 +115,22 @@ var MISC = { vbatmincellvoltage: 0, vbatmaxcellvoltage: 0, empty: 0 // unknown +}; + +var MISCV2 = { // TODO temporary, will figure out a better solution in the future + midrc: 0, + minthrottle: 0, + maxthrottle: 0, + mincommand: 0, + failsafe_throttle: 0, + gps_type: 0, + gps_baudrate: 0, + gps_ubx_sbas: 0, + placeholder1: 0, + placeholder2: 0, + mag_declination: 0, // not checked + vbatscale: 0, + vbatmincellvoltage: 0, + vbatmaxcellvoltage: 0, + placeholder3: 0 }; \ No newline at end of file diff --git a/js/msp.js b/js/msp.js index 36aa9122..9d25b817 100644 --- a/js/msp.js +++ b/js/msp.js @@ -457,14 +457,29 @@ MSP.process_data = function(code, message_buffer, message_length) { break; // Additional private MSP for baseflight configurator case MSP_codes.MSP_RCMAP: + var channelLetters = ['A', 'E', 'R', 'T', '1', '2', '3', '4']; + + RC_MAP = []; // empty the array as new data is coming in + + for (var i = 0; i < data.byteLength; i++) { + RC_MAP.push(channelLetters[data.getUint8(i)]); + } break; case MSP_codes.MSP_SET_RCMAP: + console.log('RCMAP Updated'); break; case MSP_codes.MSP_CONFIG: + BF_CONFIG.mixerConfiguration = data.getUint8(0); + BF_CONFIG.features = data.getUint32(1, 1); + BF_CONFIG.serialrx_type = data.getUint8(5); + BF_CONFIG.board_align_roll = data.getInt16(6, 1); + BF_CONFIG.board_align_pitch = data.getInt16(8, 1); + BF_CONFIG.board_align_yaw = data.getInt16(10, 1); break; case MSP_codes.MSP_SET_CONFIG: break; case MSP_codes.MSP_SET_REBOOT: + console.log('Reboot request accepted'); break; default: From c37b9ff0f1176e40dbb03b5d6a35d721194ab11f Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 15:43:04 +0200 Subject: [PATCH 024/213] merging MISCv2 into MISC since its both data structure and old fw/new fw compatible --- js/data_storage.js | 15 --------------- js/msp.js | 11 +++++++---- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/js/data_storage.js b/js/data_storage.js index 920a2046..e93ee330 100644 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -103,21 +103,6 @@ var ANALOG = { }; var MISC = { - PowerTrigger1: 0, // intPowerTrigger1 (aka useless trash) - minthrottle: 0, - maxthrottle: 0, - mincommand: 0, - failsafe_throttle: 0, - plog0: 0, // plog useless shit - plog1: 0, // plog useless shit - mag_declination: 0, // not checked - vbatscale: 0, - vbatmincellvoltage: 0, - vbatmaxcellvoltage: 0, - empty: 0 // unknown -}; - -var MISCV2 = { // TODO temporary, will figure out a better solution in the future midrc: 0, minthrottle: 0, maxthrottle: 0, diff --git a/js/msp.js b/js/msp.js index 9d25b817..0af8408c 100644 --- a/js/msp.js +++ b/js/msp.js @@ -301,18 +301,21 @@ MSP.process_data = function(code, message_buffer, message_length) { } break; case MSP_codes.MSP_MISC: // 22 bytes - MISC.PowerTrigger1 = data.getInt16(0, 1); + MISC.midrc = data.getInt16(0, 1); MISC.minthrottle = data.getUint16(2, 1); // 0-2000 MISC.maxthrottle = data.getUint16(4, 1); // 0-2000 MISC.mincommand = data.getUint16(6, 1); // 0-2000 MISC.failsafe_throttle = data.getUint16(8, 1); // 1000-2000 - MISC.plog0 = data.getUint16(10, 1); - MISC.plog1 = data.getUint32(12, 1); + MISC.gps_type = data.getUint8(10); + MISC.gps_baudrate = data.getUint8(11); + MISC.gps_ubx_sbas = data.getUint8(12); + MISC.placeholder1 = data.getUint8(13); + MISC.placeholder2 = data.getUint16(14, 1); MISC.mag_declination = data.getInt16(16, 1); // -18000-18000 MISC.vbatscale = data.getUint8(18, 1); // 10-200 MISC.vbatmincellvoltage = data.getUint8(19, 1) / 10; // 10-50 MISC.vbatmaxcellvoltage = data.getUint8(20, 1) / 10; // 10-50 - MISC.empty = data.getUint8(21, 1); + MISC.placeholder3 = data.getUint8(21, 1); break; case MSP_codes.MSP_MOTOR_PINS: console.log(data); From 8a951acb82e8d17b2732db426361ad10dd2ebe07 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 19:24:10 +0200 Subject: [PATCH 025/213] new generic crunching mechanism that will be used with all of the future set messages --- js/msp.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/js/msp.js b/js/msp.js index 0af8408c..939c39b3 100644 --- a/js/msp.js +++ b/js/msp.js @@ -570,4 +570,30 @@ MSP.send_message = function(code, data, callback_sent, callback_msp) { }); return true; -} \ No newline at end of file +}; + +MSP.crunch = function (name) { + var buffer = []; + + switch (name) { + case 'BF_CONFIG': + buffer.push(BF_CONFIG.mixerConfiguration); + buffer.push(specificByte(BF_CONFIG.features, 0)); + buffer.push(specificByte(BF_CONFIG.features, 1)); + buffer.push(specificByte(BF_CONFIG.features, 2)); + buffer.push(specificByte(BF_CONFIG.features, 3)); + buffer.push(BF_CONFIG.serialrx_type); + buffer.push(specificByte(BF_CONFIG.board_align_roll, 0)); + buffer.push(specificByte(BF_CONFIG.board_align_roll, 1)); + buffer.push(specificByte(BF_CONFIG.board_align_pitch, 0)); + buffer.push(specificByte(BF_CONFIG.board_align_pitch, 1)); + buffer.push(specificByte(BF_CONFIG.board_align_yaw, 0)); + buffer.push(specificByte(BF_CONFIG.board_align_yaw, 1)); + break; + + default: + return false; + } + + return buffer; +}; \ No newline at end of file From 0649a59b13a1803119cf2f982eb8cf82cf351718 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 19:26:06 +0200 Subject: [PATCH 026/213] function returning specific byte from 32 bit variables (untested) --- js/serial_backend.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/serial_backend.js b/js/serial_backend.js index 9de15538..083aaeaa 100644 --- a/js/serial_backend.js +++ b/js/serial_backend.js @@ -238,6 +238,10 @@ function lowByte(num) { return 0x00FF & num; } +function specificByte(num, pos) { + return 0x000000FF & (num >> (8 * pos)); +} + function bit_check(num, bit) { return ((num >> bit) % 2 != 0); } From df738f9daf555e14b1049f228dafd1e9822aaa4b Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 19:26:38 +0200 Subject: [PATCH 027/213] new device messages that indicate reboot and ready states --- _locales/en/messages.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 655abf57..6bed40ac 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -31,6 +31,13 @@ "autoConnectDisabled": { "message": "Auto-Connect: Disabled - User needs to select the correct serial port and click \"Connect\" button on its own" }, + "deviceRebooting": { + "message": "Device - Rebooting" + }, + "deviceReady": { + "message": "Device - Ready" + }, + "tab1": { "message": "Initial Setup" @@ -184,6 +191,9 @@ "initialSetupButtonResetZaxisValue": { "message": "Reset Z axis, offset: $1 deg" }, + "initialSetupMixerHead": { + "message": "Mixer Type" + }, "initialSetupThrottleHead": { "message": "Throttle Settings" }, From 875f3bfa15b84e6a572599ea37f0aeef55cb1bc0 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 19:27:30 +0200 Subject: [PATCH 028/213] first CAP_BASEFLIGHT_CONFIG implementation (unfinished) for initial tab, including temporary backwards compatibility support --- tabs/initial_setup.css | 62 ++++- tabs/initial_setup.html | 143 ++++++++---- tabs/initial_setup.js | 490 ++++++++++++++++++++++++++-------------- 3 files changed, 484 insertions(+), 211 deletions(-) diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index 6e7a0a26..c3e2cd0f 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -1,3 +1,14 @@ +/* temporary styles that are used during compatibility period */ +.tab-initial_setup .CAP_BASEFLIGHT_CONFIG, +.tab-initial_setup .COMPATIBILITY { + display: none; + height: calc(100% - 142px); +} +.tab-initial_setup .CAP_BASEFLIGHT_CONFIG #interactive_block { + width: calc(100% - 411px); +} +/* temporary styles end*/ + .tab-initial_setup { height: 100%; } @@ -48,7 +59,7 @@ float: left; position: relative; - height: calc(100% - 142px); + height: 100%; width: calc(100% - 522px); border: 1px solid silver; @@ -119,6 +130,55 @@ .tab-initial_setup .block_wrapper { font-size: 0; } + +.tab-initial_setup .block { + float: left; + display: block; + + margin-left: 10px; + + border: 1px solid silver; +} +.tab-initial_setup .block .head { + display: block; + + text-align: center; + line-height: 20px; + font-weight: bold; + + border-bottom: 1px solid silver; + background-color: #ececec; +} +.tab-initial_setup .mixer { + width: 200px; +} +.tab-initial_setup .mixer .preview { + display: block; + + width: 200px; + height: 140px; + + margin: 5px 0 5px 0; +} +.tab-initial_setup .mixer select { + display: block; + + padding-left: 5px; + + width: 100%; + height: 20px; + line-height: 20px; + + font-weight: bold; + + border-top: 1px solid silver; +} +.tab-initial_setup .block .info { + width: 200px; +} + + + .tab-initial_setup .battery, .tab-initial_setup .throttle, .tab-initial_setup .acc-trim, diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index 0db8182e..427593c8 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -20,55 +20,44 @@

-
-
- -
- - - - -
-
-
- -
-
-
-
-
-
-
+
+
+
+
+ + +
-
- -
-
-
-
-
-
-
+
+ + +
-
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
+
@@ -80,6 +69,68 @@
+
+
+
+ +
+ + + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
0 V
+
0 mAh
+
0 A
+
0 %
+
+
+
+
+
diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 0b6aa204..5e8482c2 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -11,7 +11,15 @@ TABS.initial_setup.initialize = function (callback) { googleAnalytics.sendAppView('Initial Setup'); function load_ident() { - MSP.send_message(MSP_codes.MSP_IDENT, false, false, load_misc_data); + MSP.send_message(MSP_codes.MSP_IDENT, false, false, load_config); + } + + function load_config() { + if (bit_check(CONFIG.capability, 30)) { + MSP.send_message(MSP_codes.MSP_CONFIG, false, false, load_misc_data); + } else { + load_misc_data(); + } } function load_misc_data() { @@ -28,112 +36,320 @@ TABS.initial_setup.initialize = function (callback) { // translate to user-selected language localize(); - // initialize 3D - self.initialize3D(); + // if CAP_BASEFLIGHT_CONFIG (30) + if (bit_check(CONFIG.capability, 30)) { + // current stuff, this will become default when the compatibility period ends + $('.CAP_BASEFLIGHT_CONFIG').show(); - // Fill in misc stuff - $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); - $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); - $('input[name="voltagescale"]').val(MISC.vbatscale); + // initialize 3D + self.initialize3D(false); - $('input[name="minthrottle"]').val(MISC.minthrottle); - $('input[name="maxthrottle"]').val(MISC.maxthrottle); - $('input[name="failsafe_throttle"]').val(MISC.failsafe_throttle); - $('input[name="mincommand"]').val(MISC.mincommand); + // Display multiType and motor diagram (if such exist) + var str; + switch (CONFIG.multiType) { + case 1: // TRI + str = 'TRI'; + break; + case 2: // QUAD + + str = 'Quad +'; + break; + case 3: // QUAD X + str = 'Quad X'; + break; + case 4: // BI + str = 'BI'; + break; + case 5: // GIMBAL + str = 'Gimbal'; + break; + case 6: // Y6 + str = 'Y6'; + break; + case 7: // HEX 6 + str = 'HEX 6'; + break; + case 8: // FLYING_WING + str = 'Flying Wing'; + break; + case 9: // Y4 + str = 'Y4'; + break; + case 10: // HEX6 X + str = 'HEX6 X'; + break; + case 11: // OCTO X8 + case 12: + case 13: + str = 'OCTO X8'; + break; + case 14: // AIRPLANE + str = 'Airplane'; + break; + case 15: // Heli 120 + str = 'Heli 120'; + break; + case 16: // Heli 90 + str = 'Heli 90'; + break; + case 17: // Vtail + str = 'Vtail'; + break; + case 18: // HEX6 H + str = 'HEX6 H'; + break; + case 19: // PPM to SERVO + str = 'PPM to SERVO'; + break; + case 20: // Dualcopter + str = 'Dualcopter'; + break; + case 21: // Singlecopter + str = 'Singlecopter'; + break; + case 22: // Custom + str = 'Custom'; + break; + } - $('input[name="mag_declination"]').val(MISC.mag_declination / 10); + // set model name in interactive block + $('span.model').text(chrome.i18n.getMessage('initialSetupModel', [str])); - // Fill in the accel trimms from CONFIG object - $('input[name="pitch"]').val(CONFIG.accelerometerTrims[0]); - $('input[name="roll"]').val(CONFIG.accelerometerTrims[1]); + // set heading in interactive block + $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [0])); - // Display multiType and motor diagram (if such exist) - var str = ''; - switch (CONFIG.multiType) { - case 1: // TRI - str = 'TRI'; - $('.modelMixDiagram').attr('src', './images/motor_order/tri.svg').addClass('modelMixTri'); - break; - case 2: // QUAD + - str = 'Quad +'; - $('.modelMixDiagram').attr('src', './images/motor_order/quadp.svg').addClass('modelMixQuadP'); - break; - case 3: // QUAD X - str = 'Quad X'; - $('.modelMixDiagram').attr('src', './images/motor_order/quadx.svg').addClass('modelMixQuadX'); - break; - case 4: // BI - str = 'BI'; - break; - case 5: // GIMBAL - str = 'Gimbal'; - break; - case 6: // Y6 - str = 'Y6'; - $('.modelMixDiagram').attr('src', './images/motor_order/y6.svg').addClass('modelMixY6'); - break; - case 7: // HEX 6 - str = 'HEX 6'; - $('.modelMixDiagram').attr('src', './images/motor_order/hex6p.svg').addClass('modelMixHex6P'); - break; - case 8: // FLYING_WING - str = 'Flying Wing'; - break; - case 9: // Y4 - str = 'Y4'; - $('.modelMixDiagram').attr('src', './images/motor_order/y4.svg').addClass('modelMixY4'); - break; - case 10: // HEX6 X - str = 'HEX6 X'; - $('.modelMixDiagram').attr('src', './images/motor_order/hex6x.svg').addClass('modelMixHex6X'); - break; - case 11: // OCTO X8 - case 12: - case 13: - str = 'OCTO X8'; - $('.modelMixDiagram').attr('src', './images/motor_order/octox.svg').addClass('modelMixOctoX'); - break; - case 14: // AIRPLANE - str = 'Airplane'; - $('.modelMixDiagram').attr('src', './images/motor_order/airplane.svg').addClass('modelMixAirplane'); - break; - case 15: // Heli 120 - str = 'Heli 120'; - break; - case 16: // Heli 90 - str = 'Heli 90'; - break; - case 17: // Vtail - str = 'Vtail'; - $('.modelMixDiagram').attr('src', './images/motor_order/vtail.svg').addClass('modelMixVtail'); - break; - case 18: // HEX6 H - str = 'HEX6 H'; - $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); - break; - case 19: // PPM to SERVO - str = 'PPM to SERVO'; - $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); - break; - case 20: // Dualcopter - str = 'Dualcopter'; - $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); - break; - case 21: // Singlecopter - str = 'Singlecopter'; - $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); - break; - case 22: // Custom - str = 'Custom'; - $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); - break; + // UI hook handling mixer type change that swaps the image representation + $('.mixer select').change(function () { + var val = $(this).val(); + + var imageArray = [ + 'custom', // there is no type 0, we will use custom image as spacer + 'tri', + 'quadp', + 'quadx', + 'custom', // bi + 'custom', // gimbal + 'y6', + 'hex6p', + 'custom', // flying wing + 'y4', + 'hex6x', + 'octox', + 'octox', + 'octox', + 'airplane', + 'custom', + 'custom', + 'vtail', + 'custom', + 'custom', + 'custom', + 'custom', + 'custom', + ]; + + $('.mixer .preview').attr('src', './images/motor_order/' + imageArray[val] + '.svg'); + }); + + // update mixer type with current value + $('.mixer select').val(BF_CONFIG.mixerConfiguration).change(); + + // save + $('a.update').click(function () { + // update object + BF_CONFIG.mixerConfiguration = parseInt($('.mixer select').val()); + + function save_to_eeprom() { + MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, reboot); + } + + function reboot() { + GUI.log(chrome.i18n.getMessage('initialSetupEepromSaved')); + GUI.tab_switch_cleanup(); + + MSP.send_message(MSP_codes.MSP_SET_REBOOT, false, false, reinitialize); + } + + function reinitialize() { + GUI.log(chrome.i18n.getMessage('deviceRebooting')); + + MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () { + GUI.log(chrome.i18n.getMessage('deviceReady')); + TABS.initial_setup.initialize(); + }); + } + + MSP.send_message(MSP_codes.MSP_SET_CONFIG, MSP.crunch('BF_CONFIG'), false, save_to_eeprom); // TODO reply byte is missing on the firmware side so this is where it fails + }); + } else { + // old stuff + $('.COMPATIBILITY').show(); + + // initialize 3D + self.initialize3D(true); + + // Fill in misc stuff + $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); + $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); + $('input[name="voltagescale"]').val(MISC.vbatscale); + + $('input[name="minthrottle"]').val(MISC.minthrottle); + $('input[name="maxthrottle"]').val(MISC.maxthrottle); + $('input[name="failsafe_throttle"]').val(MISC.failsafe_throttle); + $('input[name="mincommand"]').val(MISC.mincommand); + + $('input[name="mag_declination"]').val(MISC.mag_declination / 10); + + // Fill in the accel trimms from CONFIG object + $('input[name="pitch"]').val(CONFIG.accelerometerTrims[0]); + $('input[name="roll"]').val(CONFIG.accelerometerTrims[1]); + + // Display multiType and motor diagram (if such exist) + var str; + switch (CONFIG.multiType) { + case 1: // TRI + str = 'TRI'; + $('.modelMixDiagram').attr('src', './images/motor_order/tri.svg').addClass('modelMixTri'); + break; + case 2: // QUAD + + str = 'Quad +'; + $('.modelMixDiagram').attr('src', './images/motor_order/quadp.svg').addClass('modelMixQuadP'); + break; + case 3: // QUAD X + str = 'Quad X'; + $('.modelMixDiagram').attr('src', './images/motor_order/quadx.svg').addClass('modelMixQuadX'); + break; + case 4: // BI + str = 'BI'; + break; + case 5: // GIMBAL + str = 'Gimbal'; + break; + case 6: // Y6 + str = 'Y6'; + $('.modelMixDiagram').attr('src', './images/motor_order/y6.svg').addClass('modelMixY6'); + break; + case 7: // HEX 6 + str = 'HEX 6'; + $('.modelMixDiagram').attr('src', './images/motor_order/hex6p.svg').addClass('modelMixHex6P'); + break; + case 8: // FLYING_WING + str = 'Flying Wing'; + break; + case 9: // Y4 + str = 'Y4'; + $('.modelMixDiagram').attr('src', './images/motor_order/y4.svg').addClass('modelMixY4'); + break; + case 10: // HEX6 X + str = 'HEX6 X'; + $('.modelMixDiagram').attr('src', './images/motor_order/hex6x.svg').addClass('modelMixHex6X'); + break; + case 11: // OCTO X8 + case 12: + case 13: + str = 'OCTO X8'; + $('.modelMixDiagram').attr('src', './images/motor_order/octox.svg').addClass('modelMixOctoX'); + break; + case 14: // AIRPLANE + str = 'Airplane'; + $('.modelMixDiagram').attr('src', './images/motor_order/airplane.svg').addClass('modelMixAirplane'); + break; + case 15: // Heli 120 + str = 'Heli 120'; + break; + case 16: // Heli 90 + str = 'Heli 90'; + break; + case 17: // Vtail + str = 'Vtail'; + $('.modelMixDiagram').attr('src', './images/motor_order/vtail.svg').addClass('modelMixVtail'); + break; + case 18: // HEX6 H + str = 'HEX6 H'; + $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); + break; + case 19: // PPM to SERVO + str = 'PPM to SERVO'; + $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); + break; + case 20: // Dualcopter + str = 'Dualcopter'; + $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); + break; + case 21: // Singlecopter + str = 'Singlecopter'; + $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); + break; + case 22: // Custom + str = 'Custom'; + $('.modelMixDiagram').attr("src", './images/motor_order/custom.svg').addClass('modelMixCustom'); + break; + } + + $('span.model').text(chrome.i18n.getMessage('initialSetupModel', [str])); + + // Heading + $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [0])); + + $('a.update').click(function () { + CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val()); + CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val()); + + var buffer_out = new Array(); + buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]); + buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]); + buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]); + buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]); + + // Send over the new trims + MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out); + + MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; + MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; + MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); + + MISC.minthrottle = parseInt($('input[name="minthrottle"]').val()); + MISC.maxthrottle = parseInt($('input[name="maxthrottle"]').val()); + MISC.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val()); + MISC.mincommand = parseInt($('input[name="mincommand"]').val()); + + MISC.mag_declination = parseFloat($('input[name="mag_declination"]').val()) * 10; + + // we also have to fill the unsupported bytes + var buffer_out = new Array(); + buffer_out[0] = 0; // powerfailmeter + buffer_out[1] = 0; + buffer_out[2] = lowByte(MISC.minthrottle); + buffer_out[3] = highByte(MISC.minthrottle); + buffer_out[4] = lowByte(MISC.maxthrottle); + buffer_out[5] = highByte(MISC.maxthrottle); + buffer_out[6] = lowByte(MISC.mincommand); + buffer_out[7] = highByte(MISC.mincommand); + buffer_out[8] = lowByte(MISC.failsafe_throttle); + buffer_out[9] = highByte(MISC.failsafe_throttle); + buffer_out[10] = 0; + buffer_out[11] = 0; + buffer_out[12] = 0; + buffer_out[13] = 0; + buffer_out[14] = 0; + buffer_out[15] = 0; + buffer_out[16] = lowByte(MISC.mag_declination); + buffer_out[17] = highByte(MISC.mag_declination); + buffer_out[18] = MISC.vbatscale; + buffer_out[19] = MISC.vbatmincellvoltage; + buffer_out[20] = MISC.vbatmaxcellvoltage; + buffer_out[21] = 0; // vbatlevel_crit (unused) + + // Send over new misc + MSP.send_message(MSP_codes.MSP_SET_MISC, buffer_out, false, save_to_eeprom); + + function save_to_eeprom() { + MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { + GUI.log(chrome.i18n.getMessage('initialSetupEepromSaved')); + }); + } + }); } - $('span.model').text(chrome.i18n.getMessage('initialSetupModel', [str])); - - // Heading - $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [0])); - // UI Hooks $('a.calibrateAccel').click(function () { var self = $(this); @@ -185,66 +401,6 @@ TABS.initial_setup.initialize = function (callback) { }); }); - - $('a.update').click(function () { - CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val()); - CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val()); - - var buffer_out = new Array(); - buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]); - buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]); - buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]); - buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]); - - // Send over the new trims - MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out); - - MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; - MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; - MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); - - MISC.minthrottle = parseInt($('input[name="minthrottle"]').val()); - MISC.maxthrottle = parseInt($('input[name="maxthrottle"]').val()); - MISC.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val()); - MISC.mincommand = parseInt($('input[name="mincommand"]').val()); - - MISC.mag_declination = parseFloat($('input[name="mag_declination"]').val()) * 10; - - // we also have to fill the unsupported bytes - var buffer_out = new Array(); - buffer_out[0] = 0; // powerfailmeter - buffer_out[1] = 0; - buffer_out[2] = lowByte(MISC.minthrottle); - buffer_out[3] = highByte(MISC.minthrottle); - buffer_out[4] = lowByte(MISC.maxthrottle); - buffer_out[5] = highByte(MISC.maxthrottle); - buffer_out[6] = lowByte(MISC.mincommand); - buffer_out[7] = highByte(MISC.mincommand); - buffer_out[8] = lowByte(MISC.failsafe_throttle); - buffer_out[9] = highByte(MISC.failsafe_throttle); - buffer_out[10] = 0; - buffer_out[11] = 0; - buffer_out[12] = 0; - buffer_out[13] = 0; - buffer_out[14] = 0; - buffer_out[15] = 0; - buffer_out[16] = lowByte(MISC.mag_declination); - buffer_out[17] = highByte(MISC.mag_declination); - buffer_out[18] = MISC.vbatscale; - buffer_out[19] = MISC.vbatmincellvoltage; - buffer_out[20] = MISC.vbatmaxcellvoltage; - buffer_out[21] = 0; // vbatlevel_crit (unused) - - // Send over new misc - MSP.send_message(MSP_codes.MSP_SET_MISC, buffer_out, false, save_to_eeprom); - - function save_to_eeprom() { - MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { - GUI.log(chrome.i18n.getMessage('initialSetupEepromSaved')); - }); - } - }); - // display current yaw fix value (important during tab re-initialization) $('div#interactive_block > a.reset').text(chrome.i18n.getMessage('initialSetupButtonResetZaxisValue', [self.yaw_fix])); @@ -286,7 +442,7 @@ TABS.initial_setup.initialize = function (callback) { GUI.interval_add('initial_setup_data_pull', get_analog_data, 50, true); // status data pulled via separate timer with static speed - GUI.interval_add('status_pull', function () { + GUI.interval_add('status_pull', function status_pull () { MSP.send_message(MSP_codes.MSP_STATUS); }, 250, true); @@ -294,10 +450,16 @@ TABS.initial_setup.initialize = function (callback) { } }; -TABS.initial_setup.initialize3D = function () { +TABS.initial_setup.initialize3D = function (compatibility) { var self = this; - var canvas = $('#canvas'); - var wrapper = $('#canvas_wrapper'); + + if (compatibility) { + var canvas = $('.COMPATIBILITY #canvas'); + var wrapper = $('.COMPATIBILITY #canvas_wrapper'); + } else { + var canvas = $('.CAP_BASEFLIGHT_CONFIG #canvas'); + var wrapper = $('.CAP_BASEFLIGHT_CONFIG #canvas_wrapper'); + } var camera = new THREE.PerspectiveCamera(50, wrapper.width() / wrapper.height(), 1, 10000); From bfb6e17187452a9c4dfa261f71884ced5bccd758 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 21:17:53 +0200 Subject: [PATCH 029/213] removing obsolete code --- js/msp.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/js/msp.js b/js/msp.js index 939c39b3..c3c8e540 100644 --- a/js/msp.js +++ b/js/msp.js @@ -398,19 +398,6 @@ MSP.process_data = function(code, message_buffer, message_length) { break; case MSP_codes.MSP_RESET_CONF: console.log('Settings Reset'); - - // With new flight software settings in place, we have to re-pull - // latest values - MSP.send_message(MSP_codes.MSP_IDENT); - MSP.send_message(MSP_codes.MSP_STATUS); - MSP.send_message(MSP_codes.MSP_PID); - MSP.send_message(MSP_codes.MSP_RC_TUNING); - MSP.send_message(MSP_codes.MSP_BOXNAMES); - MSP.send_message(MSP_codes.MSP_BOX); - - // baseflight specific - MSP.send_message(MSP_codes.MSP_UID); - MSP.send_message(MSP_codes.MSP_ACC_TRIM); break; case MSP_codes.MSP_SELECT_SETTING: console.log('Profile selected'); From 57b4e3cafa700e7d5db87257cd8466c0c1f1a96e Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 21:18:14 +0200 Subject: [PATCH 030/213] wait for cleanup callback, then reboot --- tabs/initial_setup.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 5e8482c2..575bb17b 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -164,9 +164,10 @@ TABS.initial_setup.initialize = function (callback) { function reboot() { GUI.log(chrome.i18n.getMessage('initialSetupEepromSaved')); - GUI.tab_switch_cleanup(); - MSP.send_message(MSP_codes.MSP_SET_REBOOT, false, false, reinitialize); + GUI.tab_switch_cleanup(function() { + MSP.send_message(MSP_codes.MSP_SET_REBOOT, false, false, reinitialize); + }); } function reinitialize() { From 52afdb2928fdf0340bbad863ccaffc7b09cdea92 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 21:28:18 +0200 Subject: [PATCH 031/213] model type wont be displayed inside 3D area anymore --- tabs/initial_setup.html | 1 - tabs/initial_setup.js | 70 ----------------------------------------- 2 files changed, 71 deletions(-) diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index 427593c8..14c2f023 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -25,7 +25,6 @@
-
diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 575bb17b..938d441e 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -44,76 +44,6 @@ TABS.initial_setup.initialize = function (callback) { // initialize 3D self.initialize3D(false); - // Display multiType and motor diagram (if such exist) - var str; - switch (CONFIG.multiType) { - case 1: // TRI - str = 'TRI'; - break; - case 2: // QUAD + - str = 'Quad +'; - break; - case 3: // QUAD X - str = 'Quad X'; - break; - case 4: // BI - str = 'BI'; - break; - case 5: // GIMBAL - str = 'Gimbal'; - break; - case 6: // Y6 - str = 'Y6'; - break; - case 7: // HEX 6 - str = 'HEX 6'; - break; - case 8: // FLYING_WING - str = 'Flying Wing'; - break; - case 9: // Y4 - str = 'Y4'; - break; - case 10: // HEX6 X - str = 'HEX6 X'; - break; - case 11: // OCTO X8 - case 12: - case 13: - str = 'OCTO X8'; - break; - case 14: // AIRPLANE - str = 'Airplane'; - break; - case 15: // Heli 120 - str = 'Heli 120'; - break; - case 16: // Heli 90 - str = 'Heli 90'; - break; - case 17: // Vtail - str = 'Vtail'; - break; - case 18: // HEX6 H - str = 'HEX6 H'; - break; - case 19: // PPM to SERVO - str = 'PPM to SERVO'; - break; - case 20: // Dualcopter - str = 'Dualcopter'; - break; - case 21: // Singlecopter - str = 'Singlecopter'; - break; - case 22: // Custom - str = 'Custom'; - break; - } - - // set model name in interactive block - $('span.model').text(chrome.i18n.getMessage('initialSetupModel', [str])); - // set heading in interactive block $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [0])); From e626fbeb7b64530e1b9129ae99a9af9632e9abe5 Mon Sep 17 00:00:00 2001 From: cTn Date: Tue, 16 Sep 2014 23:07:52 +0200 Subject: [PATCH 032/213] utilizing the new data cruncher in various tabs (aux, pid, receiver) and in restore routines, unfinished (looking solid) --- js/backup_restore.js | 81 +++------------------------------ js/msp.js | 49 ++++++++++++++++++++ tabs/auxiliary_configuration.js | 18 ++------ tabs/pid_tuning.js | 53 +++------------------ tabs/receiver.js | 14 +----- 5 files changed, 70 insertions(+), 145 deletions(-) diff --git a/js/backup_restore.js b/js/backup_restore.js index 061aabe7..fae21370 100644 --- a/js/backup_restore.js +++ b/js/backup_restore.js @@ -187,86 +187,19 @@ function configuration_restore() { } function configuration_upload() { - // this "cloned" function contains all the upload sequences for the respective array/objects - // that are currently scattered in separate tabs (ergo - pid_tuning.js/initial_setup.js/etc) - // for current purposes, this approach works, but its not really "valid" and this approach - // should be reworked in the future, so the same code won't be cloned over !!! - - // PID section - var PID_buffer_out = new Array(), - PID_buffer_needle = 0; - - for (var i = 0; i < PIDs.length; i++) { - switch (i) { - case 0: - case 1: - case 2: - case 3: - case 7: - case 8: - case 9: - PID_buffer_out[PID_buffer_needle] = parseInt(PIDs[i][0] * 10); - PID_buffer_out[PID_buffer_needle + 1] = parseInt(PIDs[i][1] * 1000); - PID_buffer_out[PID_buffer_needle + 2] = parseInt(PIDs[i][2]); - break; - case 4: - PID_buffer_out[PID_buffer_needle] = parseInt(PIDs[i][0] * 100); - PID_buffer_out[PID_buffer_needle + 1] = parseInt(PIDs[i][1] * 100); - PID_buffer_out[PID_buffer_needle + 2] = parseInt(PIDs[i][2]); - break; - case 5: - case 6: - PID_buffer_out[PID_buffer_needle] = parseInt(PIDs[i][0] * 10); - PID_buffer_out[PID_buffer_needle + 1] = parseInt(PIDs[i][1] * 100); - PID_buffer_out[PID_buffer_needle + 2] = parseInt(PIDs[i][2] * 1000); - break; - } - - PID_buffer_needle += 3; - } - // Send over the PID changes - MSP.send_message(MSP_codes.MSP_SET_PID, PID_buffer_out, false, rc_tuning); + MSP.send_message(MSP_codes.MSP_SET_PID, MSP.crunch('PIDs'), false, rc_tuning); - function rc_tuning() { - // RC Tuning section - var RC_tuning_buffer_out = new Array(); - RC_tuning_buffer_out[0] = parseInt(RC_tuning.RC_RATE * 100); - RC_tuning_buffer_out[1] = parseInt(RC_tuning.RC_EXPO * 100); - RC_tuning_buffer_out[2] = parseInt(RC_tuning.roll_pitch_rate * 100); - RC_tuning_buffer_out[3] = parseInt(RC_tuning.yaw_rate * 100); - RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100); - RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100); - RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100); - - // Send over the RC_tuning changes - MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out, false, aux); + function rc_tuning() { // Send over the RC_tuning changes + MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch('RC_tuning'), false, aux); } - function aux() { - // AUX section - var AUX_val_buffer_out = new Array(), - needle = 0; - - for (var i = 0; i < AUX_CONFIG_values.length; i++) { - AUX_val_buffer_out[needle++] = lowByte(AUX_CONFIG_values[i]); - AUX_val_buffer_out[needle++] = highByte(AUX_CONFIG_values[i]); - } - - // Send over the AUX changes - MSP.send_message(MSP_codes.MSP_SET_BOX, AUX_val_buffer_out, false, trim); + function aux() { // Send over the AUX changes + MSP.send_message(MSP_codes.MSP_SET_BOX, MSP.crunch('AUX_CONFIG_values'), false, trim); } - // Trim section - function trim() { - var buffer_out = new Array(); - buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]); - buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]); - buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]); - buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]); - - // Send over the new trims - MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out, false, misc); + function trim() { // Send over the new trims + MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, MSP.crunch('accelerometerTrims'), false, misc); } function misc() { diff --git a/js/msp.js b/js/msp.js index c3c8e540..0d910a0f 100644 --- a/js/msp.js +++ b/js/msp.js @@ -577,6 +577,55 @@ MSP.crunch = function (name) { buffer.push(specificByte(BF_CONFIG.board_align_yaw, 0)); buffer.push(specificByte(BF_CONFIG.board_align_yaw, 1)); break; + case 'PIDs': + for (var i = 0; i < PIDs.length; i++) { + switch (i) { + case 0: + case 1: + case 2: + case 3: + case 7: + case 8: + case 9: + buffer.push(parseInt(PIDs[i][0] * 10)); + buffer.push(parseInt(PIDs[i][1] * 1000)); + buffer.push(parseInt(PIDs[i][2])); + break; + case 4: + buffer.push(parseInt(PIDs[i][0] * 100)); + buffer.push(parseInt(PIDs[i][1] * 100)); + buffer.push(parseInt(PIDs[i][2])); + break; + case 5: + case 6: + buffer.push(parseInt(PIDs[i][0] * 10)); + buffer.push(parseInt(PIDs[i][1] * 100)); + buffer.push(parseInt(PIDs[i][2] * 1000)); + break; + } + } + break; + case 'RC_tuning': + buffer.push(parseInt(RC_tuning.RC_RATE * 100)); + buffer.push(parseInt(RC_tuning.RC_EXPO * 100)); + buffer.push(parseInt(RC_tuning.roll_pitch_rate * 100)); + buffer.push(parseInt(RC_tuning.yaw_rate * 100)); + buffer.push(parseInt(RC_tuning.dynamic_THR_PID * 100)); + buffer.push(parseInt(RC_tuning.throttle_MID * 100)); + buffer.push(parseInt(RC_tuning.throttle_EXPO * 100)); + break; + case 'AUX_CONFIG_values': + for (var i = 0; i < AUX_CONFIG_values.length; i++) { + buffer.push(lowByte(AUX_CONFIG_values[i])); + buffer.push(highByte(AUX_CONFIG_values[i])); + } + break; + case 'accelerometerTrims': + buffer.push(lowByte(CONFIG.accelerometerTrims[0])); + buffer.push(highByte(CONFIG.accelerometerTrims[0])); + buffer.push(lowByte(CONFIG.accelerometerTrims[1])); + buffer.push(highByte(CONFIG.accelerometerTrims[1])); + break; default: return false; diff --git a/tabs/auxiliary_configuration.js b/tabs/auxiliary_configuration.js index 1e928ac3..8427b174 100644 --- a/tabs/auxiliary_configuration.js +++ b/tabs/auxiliary_configuration.js @@ -64,8 +64,9 @@ TABS.auxiliary_configuration.initialize = function (callback) { // UI Hooks $('a.update').click(function () { // catch the input changes - var main_needle = 0; - var needle = 0; + var main_needle = 0, + needle = 0; + $('.boxes input').each(function () { if ($(this).is(':checked')) { AUX_CONFIG_values[main_needle] = bit_set(AUX_CONFIG_values[main_needle], needle); @@ -77,26 +78,17 @@ TABS.auxiliary_configuration.initialize = function (callback) { if (needle >= (RC.active_channels - 4) * 3) { // 1 aux * 3 checkboxes, 4 AUX = 12 bits per line main_needle++; - needle = 0; } }); - // send over data - // current code will only handle 4 AUX as the variable length is 16bits - var AUX_val_buffer_out = []; - for (var i = 0; i < AUX_CONFIG_values.length; i++) { - AUX_val_buffer_out.push(lowByte(AUX_CONFIG_values[i])); - AUX_val_buffer_out.push(highByte(AUX_CONFIG_values[i])); - } - - MSP.send_message(MSP_codes.MSP_SET_BOX, AUX_val_buffer_out, false, save_to_eeprom); - function save_to_eeprom() { MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { GUI.log(chrome.i18n.getMessage('auxiliaryEepromSaved')); }); } + + MSP.send_message(MSP_codes.MSP_SET_BOX, MSP.crunch('AUX_CONFIG_values'), false, save_to_eeprom); }); // val = channel value diff --git a/tabs/pid_tuning.js b/tabs/pid_tuning.js index ffd053c4..e2c59b94 100644 --- a/tabs/pid_tuning.js +++ b/tabs/pid_tuning.js @@ -253,54 +253,13 @@ TABS.pid_tuning.initialize = function (callback) { PIDs[8][i++] = parseFloat($(this).val()); }); - var PID_buffer_out = new Array(); - for (var i = 0, needle = 0; i < PIDs.length; i++, needle += 3) { - switch (i) { - case 0: - case 1: - case 2: - case 3: - case 7: - case 8: - case 9: - PID_buffer_out[needle] = parseInt(PIDs[i][0] * 10); - PID_buffer_out[needle + 1] = parseInt(PIDs[i][1] * 1000); - PID_buffer_out[needle + 2] = parseInt(PIDs[i][2]); - break; - case 4: - PID_buffer_out[needle] = parseInt(PIDs[i][0] * 100); - PID_buffer_out[needle + 1] = parseInt(PIDs[i][1] * 100); - PID_buffer_out[needle + 2] = parseInt(PIDs[i][2]); - break; - case 5: - case 6: - PID_buffer_out[needle] = parseInt(PIDs[i][0] * 10); - PID_buffer_out[needle + 1] = parseInt(PIDs[i][1] * 100); - PID_buffer_out[needle + 2] = parseInt(PIDs[i][2] * 1000); - break; - } - } - - // Send over the PID changes - MSP.send_message(MSP_codes.MSP_SET_PID, PID_buffer_out, false, send_rc_tuning_changes); + // catch RC_tuning changes + RC_tuning.roll_pitch_rate = parseFloat($('.rate-tpa input[name="roll-pitch"]').val()); + RC_tuning.yaw_rate = parseFloat($('.rate-tpa input[name="yaw"]').val()); + RC_tuning.dynamic_THR_PID = parseFloat($('.rate-tpa input[name="tpa"]').val()); function send_rc_tuning_changes() { - // catch RC_tuning changes - RC_tuning.roll_pitch_rate = parseFloat($('.rate-tpa input[name="roll-pitch"]').val()); - RC_tuning.yaw_rate = parseFloat($('.rate-tpa input[name="yaw"]').val()); - RC_tuning.dynamic_THR_PID = parseFloat($('.rate-tpa input[name="tpa"]').val()); - - var RC_tuning_buffer_out = new Array(); - RC_tuning_buffer_out[0] = parseInt(RC_tuning.RC_RATE * 100); - RC_tuning_buffer_out[1] = parseInt(RC_tuning.RC_EXPO * 100); - RC_tuning_buffer_out[2] = parseInt(RC_tuning.roll_pitch_rate * 100); - RC_tuning_buffer_out[3] = parseInt(RC_tuning.yaw_rate * 100); - RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100); - RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100); - RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100); - - // Send over the RC_tuning changes - MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out, false, save_to_eeprom); + MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch('RC_tuning'), false, save_to_eeprom); } function save_to_eeprom() { @@ -308,6 +267,8 @@ TABS.pid_tuning.initialize = function (callback) { GUI.log(chrome.i18n.getMessage('pidTuningEepromSaved')); }); } + + MSP.send_message(MSP_codes.MSP_SET_PID, MSP.crunch('PIDs'), false, send_rc_tuning_changes); }); // status data pulled via separate timer with static speed diff --git a/tabs/receiver.js b/tabs/receiver.js index 9fab5def..0a9fda69 100644 --- a/tabs/receiver.js +++ b/tabs/receiver.js @@ -143,23 +143,13 @@ TABS.receiver.initialize = function (callback) { RC_tuning.RC_RATE = parseFloat($('.tunings .rate input[name="rate"]').val()); RC_tuning.RC_EXPO = parseFloat($('.tunings .rate input[name="expo"]').val()); - var RC_tuning_buffer_out = new Array(); - RC_tuning_buffer_out[0] = parseInt(RC_tuning.RC_RATE * 100, 10); - RC_tuning_buffer_out[1] = parseInt(RC_tuning.RC_EXPO * 100, 10); - RC_tuning_buffer_out[2] = parseInt(RC_tuning.roll_pitch_rate * 100, 10); - RC_tuning_buffer_out[3] = parseInt(RC_tuning.yaw_rate * 100, 10); - RC_tuning_buffer_out[4] = parseInt(RC_tuning.dynamic_THR_PID * 100, 10); - RC_tuning_buffer_out[5] = parseInt(RC_tuning.throttle_MID * 100, 10); - RC_tuning_buffer_out[6] = parseInt(RC_tuning.throttle_EXPO * 100, 10); - - // Send over the RC_tuning changes - MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, RC_tuning_buffer_out, false, save_to_eeprom); - function save_to_eeprom() { MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { GUI.log(chrome.i18n.getMessage('receiverEepromSaved')); }); } + + MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch('RC_tuning'), false, save_to_eeprom); }); $('select[name="rx_refresh_rate"]').change(function () { From e9c4a533af4b15f58443bb0762fa14d13f155eee Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 09:27:54 +0200 Subject: [PATCH 033/213] finishing touches to the crunching mechanism, backup and restore is all cleaned up now --- js/backup_restore.js | 56 +++++++++------------------------ js/msp.js | 38 +++++++++++++++++----- tabs/auxiliary_configuration.js | 2 +- tabs/initial_setup.js | 2 +- tabs/pid_tuning.js | 4 +-- tabs/receiver.js | 2 +- 6 files changed, 51 insertions(+), 53 deletions(-) diff --git a/js/backup_restore.js b/js/backup_restore.js index fae21370..73f3f472 100644 --- a/js/backup_restore.js +++ b/js/backup_restore.js @@ -43,11 +43,11 @@ function configuration_backup() { }]; // generate timestamp for the backup file - var d = new Date(); - var now = d.getUTCFullYear() + '.' + d.getDate() + '.' + (d.getMonth() + 1) + '.' + d.getHours() + '.' + d.getMinutes(); + var d = new Date(), + now = d.getUTCFullYear() + '.' + d.getDate() + '.' + (d.getMonth() + 1) + '.' + d.getHours() + '.' + d.getMinutes(); // create or load the file - chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'bf_mw_backup_' + now, accepts: accepts}, function (fileEntry) { + chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'baseflight_backup_' + now, accepts: accepts}, function (fileEntry) { if (!fileEntry) { console.log('No file selected, backup aborted.'); @@ -187,54 +187,28 @@ function configuration_restore() { } function configuration_upload() { - // Send over the PID changes - MSP.send_message(MSP_codes.MSP_SET_PID, MSP.crunch('PIDs'), false, rc_tuning); - function rc_tuning() { // Send over the RC_tuning changes - MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch('RC_tuning'), false, aux); + MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch(MSP_codes.MSP_SET_RC_TUNING), false, aux); } function aux() { // Send over the AUX changes - MSP.send_message(MSP_codes.MSP_SET_BOX, MSP.crunch('AUX_CONFIG_values'), false, trim); + MSP.send_message(MSP_codes.MSP_SET_BOX, MSP.crunch(MSP_codes.MSP_SET_BOX), false, trim); } function trim() { // Send over the new trims - MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, MSP.crunch('accelerometerTrims'), false, misc); + MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, MSP.crunch(MSP_codes.MSP_SET_ACC_TRIM), false, misc); } - function misc() { - // MISC - // we also have to fill the unsupported bytes - var buffer_out = new Array(); - buffer_out[0] = 0; // powerfailmeter - buffer_out[1] = 0; - buffer_out[2] = lowByte(MISC.minthrottle); - buffer_out[3] = highByte(MISC.minthrottle); - buffer_out[4] = lowByte(MISC.maxthrottle); - buffer_out[5] = highByte(MISC.maxthrottle); - buffer_out[6] = lowByte(MISC.mincommand); - buffer_out[7] = highByte(MISC.mincommand); - buffer_out[8] = lowByte(MISC.failsafe_throttle); - buffer_out[9] = highByte(MISC.failsafe_throttle); - buffer_out[10] = 0; - buffer_out[11] = 0; - buffer_out[12] = 0; - buffer_out[13] = 0; - buffer_out[14] = 0; - buffer_out[15] = 0; - buffer_out[16] = lowByte(MISC.mag_declination); - buffer_out[17] = highByte(MISC.mag_declination); - buffer_out[18] = MISC.vbatscale; - buffer_out[19] = MISC.vbatmincellvoltage; - buffer_out[20] = MISC.vbatmaxcellvoltage; - buffer_out[21] = 0; // vbatlevel_crit (unused) + function misc() { // Send ove the new MISC + MSP.send_message(MSP_codes.MSP_SET_MISC, MSP.crunch(MSP_codes.MSP_SET_MISC), false, save_eeprom); + } - // Send ove the new MISC - MSP.send_message(MSP_codes.MSP_SET_MISC, buffer_out, false, function () { - // Save changes to EEPROM - MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { - GUI.log(chrome.i18n.getMessage('eeprom_saved_ok')); - }); + function save_eeprom() { + MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { + GUI.log(chrome.i18n.getMessage('eeprom_saved_ok')); }); } + + // Send over the PID changes + MSP.send_message(MSP_codes.MSP_SET_PID, MSP.crunch(MSP_codes.MSP_SET_PID), false, rc_tuning); } \ No newline at end of file diff --git a/js/msp.js b/js/msp.js index 0d910a0f..2429500c 100644 --- a/js/msp.js +++ b/js/msp.js @@ -559,11 +559,11 @@ MSP.send_message = function(code, data, callback_sent, callback_msp) { return true; }; -MSP.crunch = function (name) { +MSP.crunch = function (code) { var buffer = []; - switch (name) { - case 'BF_CONFIG': + switch (code) { + case MSP_codes.MSP_SET_CONFIG: buffer.push(BF_CONFIG.mixerConfiguration); buffer.push(specificByte(BF_CONFIG.features, 0)); buffer.push(specificByte(BF_CONFIG.features, 1)); @@ -577,7 +577,7 @@ MSP.crunch = function (name) { buffer.push(specificByte(BF_CONFIG.board_align_yaw, 0)); buffer.push(specificByte(BF_CONFIG.board_align_yaw, 1)); break; - case 'PIDs': + case MSP_codes.MSP_SET_PID: for (var i = 0; i < PIDs.length; i++) { switch (i) { case 0: @@ -605,7 +605,7 @@ MSP.crunch = function (name) { } } break; - case 'RC_tuning': + case MSP_codes.MSP_SET_RC_TUNING: buffer.push(parseInt(RC_tuning.RC_RATE * 100)); buffer.push(parseInt(RC_tuning.RC_EXPO * 100)); buffer.push(parseInt(RC_tuning.roll_pitch_rate * 100)); @@ -614,18 +614,42 @@ MSP.crunch = function (name) { buffer.push(parseInt(RC_tuning.throttle_MID * 100)); buffer.push(parseInt(RC_tuning.throttle_EXPO * 100)); break; - case 'AUX_CONFIG_values': + case MSP_codes.MSP_SET_BOX: for (var i = 0; i < AUX_CONFIG_values.length; i++) { buffer.push(lowByte(AUX_CONFIG_values[i])); buffer.push(highByte(AUX_CONFIG_values[i])); } break; - case 'accelerometerTrims': + case MSP_codes.MSP_SET_ACC_TRIM: buffer.push(lowByte(CONFIG.accelerometerTrims[0])); buffer.push(highByte(CONFIG.accelerometerTrims[0])); buffer.push(lowByte(CONFIG.accelerometerTrims[1])); buffer.push(highByte(CONFIG.accelerometerTrims[1])); break; + case MSP_codes.MSP_SET_MISC: + buffer.push(lowByte(MISC.midrc)); + buffer.push(highByte(MISC.midrc)); + buffer.push(lowByte(MISC.minthrottle)); + buffer.push(highByte(MISC.minthrottle)); + buffer.push(lowByte(MISC.maxthrottle)); + buffer.push(highByte(MISC.maxthrottle)); + buffer.push(lowByte(MISC.mincommand)); + buffer.push(highByte(MISC.mincommand)); + buffer.push(lowByte(MISC.failsafe_throttle)); + buffer.push(highByte(MISC.failsafe_throttle)); + buffer.push(MISC.gps_type); + buffer.push(MISC.gps_baudrate); + buffer.push(MISC.gps_ubx_sbas); + buffer.push(MISC.placeholder1); + buffer.push(lowByte(MISC.placeholder2)); + buffer.push(highByte(MISC.placeholder2)); + buffer.push(lowByte(MISC.mag_declination)); + buffer.push(highByte(MISC.mag_declination)); + buffer.push(MISC.vbatscale); + buffer.push(MISC.vbatmincellvoltage); + buffer.push(MISC.vbatmaxcellvoltage); + buffer.push(MISC.placeholder3); + break; default: return false; diff --git a/tabs/auxiliary_configuration.js b/tabs/auxiliary_configuration.js index 8427b174..5baf5c48 100644 --- a/tabs/auxiliary_configuration.js +++ b/tabs/auxiliary_configuration.js @@ -88,7 +88,7 @@ TABS.auxiliary_configuration.initialize = function (callback) { }); } - MSP.send_message(MSP_codes.MSP_SET_BOX, MSP.crunch('AUX_CONFIG_values'), false, save_to_eeprom); + MSP.send_message(MSP_codes.MSP_SET_BOX, MSP.crunch(MSP_codes.MSP_SET_BOX), false, save_to_eeprom); }); // val = channel value diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 938d441e..aa1b857a 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -109,7 +109,7 @@ TABS.initial_setup.initialize = function (callback) { }); } - MSP.send_message(MSP_codes.MSP_SET_CONFIG, MSP.crunch('BF_CONFIG'), false, save_to_eeprom); // TODO reply byte is missing on the firmware side so this is where it fails + MSP.send_message(MSP_codes.MSP_SET_CONFIG, MSP.crunch(MSP_codes.MSP_SET_CONFIG), false, save_to_eeprom); }); } else { // old stuff diff --git a/tabs/pid_tuning.js b/tabs/pid_tuning.js index e2c59b94..0146f8e0 100644 --- a/tabs/pid_tuning.js +++ b/tabs/pid_tuning.js @@ -259,7 +259,7 @@ TABS.pid_tuning.initialize = function (callback) { RC_tuning.dynamic_THR_PID = parseFloat($('.rate-tpa input[name="tpa"]').val()); function send_rc_tuning_changes() { - MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch('RC_tuning'), false, save_to_eeprom); + MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch(MSP_codes.MSP_SET_RC_TUNING), false, save_to_eeprom); } function save_to_eeprom() { @@ -268,7 +268,7 @@ TABS.pid_tuning.initialize = function (callback) { }); } - MSP.send_message(MSP_codes.MSP_SET_PID, MSP.crunch('PIDs'), false, send_rc_tuning_changes); + MSP.send_message(MSP_codes.MSP_SET_PID, MSP.crunch(MSP_codes.MSP_SET_PID), false, send_rc_tuning_changes); }); // status data pulled via separate timer with static speed diff --git a/tabs/receiver.js b/tabs/receiver.js index 0a9fda69..bd4efa54 100644 --- a/tabs/receiver.js +++ b/tabs/receiver.js @@ -149,7 +149,7 @@ TABS.receiver.initialize = function (callback) { }); } - MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch('RC_tuning'), false, save_to_eeprom); + MSP.send_message(MSP_codes.MSP_SET_RC_TUNING, MSP.crunch(MSP_codes.MSP_SET_RC_TUNING), false, save_to_eeprom); }); $('select[name="rx_refresh_rate"]').change(function () { From 4fd36df425cf2e2f714ad25192655a4beac424b1 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 09:56:50 +0200 Subject: [PATCH 034/213] renaming auxiliary tab --- _locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 6bed40ac..041a6ed2 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -49,7 +49,7 @@ "message": "Receiver" }, "tab4": { - "message": "Auxiliary Configuration" + "message": "Mode Selection" }, "tab5": { "message": "Servos" From 945b86f9b2b8b53ced14c7094a08827fa1b64544 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 10:31:36 +0200 Subject: [PATCH 035/213] rename translation shortcuts, drop configuration files in --- _locales/en/messages.json | 25 +++++++++-------- main.html | 23 ++++++++------- main.js | 3 ++ tabs/configuration.css | 2 ++ tabs/configuration.html | 2 ++ tabs/configuration.js | 59 +++++++++++++++++++++++++++++++++++++++ tabs/initial_setup.js | 2 +- 7 files changed, 94 insertions(+), 22 deletions(-) create mode 100644 tabs/configuration.css create mode 100644 tabs/configuration.html create mode 100644 tabs/configuration.js diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 041a6ed2..95756133 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -39,34 +39,37 @@ }, - "tab1": { - "message": "Initial Setup" + "tabSetup": { + "message": "Setup" }, - "tab2": { + "tabConfiguration": { + "message": "Configuration" + }, + "tabPidTuning": { "message": "PID Tuning" }, - "tab3": { + "tabReceiver": { "message": "Receiver" }, - "tab4": { + "tabModeSelection": { "message": "Mode Selection" }, - "tab5": { + "tabServos": { "message": "Servos" }, - "tab6": { + "tabGPS": { "message": "GPS" }, - "tab7": { + "tabMotorTesting": { "message": "Motor Testing" }, - "tab8": { + "tabRawSensorData": { "message": "Raw Sensor Data" }, - "tab9": { + "tabCLI": { "message": "CLI" }, - "tab10": { + "tabLogging": { "message": "Logging" }, diff --git a/main.html b/main.html index bfb27045..a1b04da3 100644 --- a/main.html +++ b/main.html @@ -8,6 +8,7 @@ + @@ -41,6 +42,7 @@ + @@ -102,16 +104,17 @@
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
diff --git a/main.js b/main.js index 7d889081..01ba8659 100644 --- a/main.js +++ b/main.js @@ -88,6 +88,9 @@ $(document).ready(function () { case 'tab_initial_setup': TABS.initial_setup.initialize(content_ready); break; + case 'tab_configuration': + TABS.configuration.initialize(content_ready); + break; case 'tab_pid_tuning': TABS.pid_tuning.initialize(content_ready); break; diff --git a/tabs/configuration.css b/tabs/configuration.css new file mode 100644 index 00000000..3a4d3172 --- /dev/null +++ b/tabs/configuration.css @@ -0,0 +1,2 @@ +.tab-configuration { +} \ No newline at end of file diff --git a/tabs/configuration.html b/tabs/configuration.html new file mode 100644 index 00000000..8b9eda54 --- /dev/null +++ b/tabs/configuration.html @@ -0,0 +1,2 @@ +
+
\ No newline at end of file diff --git a/tabs/configuration.js b/tabs/configuration.js new file mode 100644 index 00000000..e4243b4e --- /dev/null +++ b/tabs/configuration.js @@ -0,0 +1,59 @@ +'use strict'; + +TABS.configuration = {}; + +TABS.configuration.initialize = function (callback) { + var self = this; + GUI.active_tab_ref = this; + GUI.active_tab = 'configuration'; + googleAnalytics.sendAppView('Configuration'); + + + function check_compatibility() { + if (bit_check(CONFIG.capability, 30)) { + // new stuff supported, continue fetching configuration data + load_config(); + } else { + // old version, deny access + $('#content').text('We are sorry, but advanced configuration is only available for boards with latest firmware, please update'); + + if (callback) callback(); + } + } + + function load_config() { + MSP.send_message(MSP_codes.MSP_CONFIG, false, false, load_rc_map); + } + + function load_rc_map() { + MSP.send_message(MSP_codes.MSP_RCMAP, false, false, load_misc); + } + + function load_misc() { + MSP.send_message(MSP_codes.MSP_MISC, false, false, load_acc_trim); + } + + function load_acc_trim() { + MSP.send_message(MSP_codes.MSP_ACC_TRIM, false, false, load_html); + } + + function load_html() { + $('#content').load("./tabs/configuration.html", process_html); + } + + MSP.send_message(MSP_codes.MSP_IDENT, false, false, check_compatibility); + + function process_html() { + // translate to user-selected language + localize(); + + console.log('all ready'); + + if (callback) callback(); + } + +}; + +TABS.configuration.cleanup = function (callback) { + if (callback) callback(); +}; \ No newline at end of file diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index aa1b857a..fe962bb1 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -8,7 +8,7 @@ TABS.initial_setup.initialize = function (callback) { var self = this; GUI.active_tab_ref = this; GUI.active_tab = 'initial_setup'; - googleAnalytics.sendAppView('Initial Setup'); + googleAnalytics.sendAppView('Setup'); function load_ident() { MSP.send_message(MSP_codes.MSP_IDENT, false, false, load_config); From 4894f7493a4b48576078ce00738bb29397227278 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 10:51:54 +0200 Subject: [PATCH 036/213] apply crunching mechanism to compatibility code in initial tab, disable magnetometer calib if magnetometer is missing --- tabs/initial_setup.css | 6 +++++ tabs/initial_setup.js | 50 ++++++++++-------------------------------- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index c3e2cd0f..578099d6 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -40,6 +40,12 @@ .tab-initial_setup .section a.calibrating:hover { cursor: default; background-color: #c1c1c1; + } + .tab-initial_setup .section a.disabled { + background-color: #c1c1c1; + } + .tab-initial_setup .section a.disabled:hover { + cursor: default; } .tab-initial_setup .section a.backup { width: 80px; diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index fe962bb1..301e2bd2 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -225,15 +225,6 @@ TABS.initial_setup.initialize = function (callback) { CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val()); CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val()); - var buffer_out = new Array(); - buffer_out[0] = lowByte(CONFIG.accelerometerTrims[0]); - buffer_out[1] = highByte(CONFIG.accelerometerTrims[0]); - buffer_out[2] = lowByte(CONFIG.accelerometerTrims[1]); - buffer_out[3] = highByte(CONFIG.accelerometerTrims[1]); - - // Send over the new trims - MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, buffer_out); - MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); @@ -245,42 +236,25 @@ TABS.initial_setup.initialize = function (callback) { MISC.mag_declination = parseFloat($('input[name="mag_declination"]').val()) * 10; - // we also have to fill the unsupported bytes - var buffer_out = new Array(); - buffer_out[0] = 0; // powerfailmeter - buffer_out[1] = 0; - buffer_out[2] = lowByte(MISC.minthrottle); - buffer_out[3] = highByte(MISC.minthrottle); - buffer_out[4] = lowByte(MISC.maxthrottle); - buffer_out[5] = highByte(MISC.maxthrottle); - buffer_out[6] = lowByte(MISC.mincommand); - buffer_out[7] = highByte(MISC.mincommand); - buffer_out[8] = lowByte(MISC.failsafe_throttle); - buffer_out[9] = highByte(MISC.failsafe_throttle); - buffer_out[10] = 0; - buffer_out[11] = 0; - buffer_out[12] = 0; - buffer_out[13] = 0; - buffer_out[14] = 0; - buffer_out[15] = 0; - buffer_out[16] = lowByte(MISC.mag_declination); - buffer_out[17] = highByte(MISC.mag_declination); - buffer_out[18] = MISC.vbatscale; - buffer_out[19] = MISC.vbatmincellvoltage; - buffer_out[20] = MISC.vbatmaxcellvoltage; - buffer_out[21] = 0; // vbatlevel_crit (unused) - - // Send over new misc - MSP.send_message(MSP_codes.MSP_SET_MISC, buffer_out, false, save_to_eeprom); - function save_to_eeprom() { MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, function () { GUI.log(chrome.i18n.getMessage('initialSetupEepromSaved')); }); } + + // Send over the new trims + MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, MSP.crunch(MSP_codes.MSP_SET_ACC_TRIM)); + + // Send over new misc + MSP.send_message(MSP_codes.MSP_SET_MISC, MSP.crunch(MSP_codes.MSP_SET_MISC), false, save_to_eeprom); }); } + // check if we have magnetometer + if (!bit_check(CONFIG.activeSensors, 2)) { + $('a.calibrateMag').addClass('disabled'); + } + // UI Hooks $('a.calibrateAccel').click(function () { var self = $(this); @@ -308,7 +282,7 @@ TABS.initial_setup.initialize = function (callback) { $('a.calibrateMag').click(function () { var self = $(this); - if (!self.hasClass('calibrating')) { + if (!self.hasClass('calibrating') && !self.hasClass('disabled')) { self.addClass('calibrating'); MSP.send_message(MSP_codes.MSP_MAG_CALIBRATION, false, false, function () { From fee5219a73d3ccc33103638651bbff36b4b49a84 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 11:23:31 +0200 Subject: [PATCH 037/213] move index to ascii conversion for rcmap out of msp protocol, define feature index array (will get a proper text polish in the future) updating mixer select with missing names --- js/msp.js | 4 +--- tabs/configuration.js | 21 +++++++++++++++++++++ tabs/initial_setup.html | 6 +++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/js/msp.js b/js/msp.js index 2429500c..219a6b39 100644 --- a/js/msp.js +++ b/js/msp.js @@ -447,12 +447,10 @@ MSP.process_data = function(code, message_buffer, message_length) { break; // Additional private MSP for baseflight configurator case MSP_codes.MSP_RCMAP: - var channelLetters = ['A', 'E', 'R', 'T', '1', '2', '3', '4']; - RC_MAP = []; // empty the array as new data is coming in for (var i = 0; i < data.byteLength; i++) { - RC_MAP.push(channelLetters[data.getUint8(i)]); + RC_MAP.push(data.getUint8(i)); } break; case MSP_codes.MSP_SET_RCMAP: diff --git a/tabs/configuration.js b/tabs/configuration.js index e4243b4e..36aee9aa 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -47,6 +47,27 @@ TABS.configuration.initialize = function (callback) { // translate to user-selected language localize(); + // index references + var featureNames = [ + 'PPM', + 'VBAT', + 'INFLIGHT_ACC_CAL', + 'SERIALRX', + 'MOTOR_STOP', + 'SERVO_TILT', + 'SOFTSERIAL', + 'LED_RING', + 'GPS', + 'FAILSAFE', + 'SONAR', + 'TELEMETRY', + 'POWERMETER', + 'VARIO', + '3D' + ]; + + var RCMAPlLetters = ['A', 'E', 'R', 'T', '1', '2', '3', '4']; + console.log('all ready'); if (callback) callback(); diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index 14c2f023..faf40d0d 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -43,12 +43,12 @@ - - + + - + From b11e4cde6a43febc779c2ce081ea46b04fff5b26 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 11:37:27 +0200 Subject: [PATCH 038/213] fixing -webkit-inner-spin-button once again (what is chromium doing to that style...) --- tabs/pid_tuning.css | 7 ++----- tabs/receiver.css | 5 ++--- tabs/servos.css | 4 +--- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/tabs/pid_tuning.css b/tabs/pid_tuning.css index b6c7fc06..baa0ab35 100644 --- a/tabs/pid_tuning.css +++ b/tabs/pid_tuning.css @@ -28,11 +28,10 @@ .tab-pid_tuning table input { display: block; - width: calc(100% - 10px); + width: 100%; height: 20px; line-height: 20px; - padding: 0 5px 0 5px; text-align: right; } .tab-pid_tuning .profile { @@ -55,12 +54,10 @@ .tab-pid_tuning .profile input { display: block; - width: calc(100% - 10px); + width: 100%; height: 20px; line-height: 20px; - - padding: 0 5px 0 5px; text-align: right; } .tab-pid_tuning .pid_tuning { diff --git a/tabs/receiver.css b/tabs/receiver.css index fbba80f8..257a686c 100644 --- a/tabs/receiver.css +++ b/tabs/receiver.css @@ -95,11 +95,10 @@ background-color: #ececec; } .tab-receiver .tunings table input { - width: 116px; + width: 100%; height: 20px; - line-height: 20px; - padding: 0 5px 0 5px; + line-height: 20px; text-align: right; } .tab-receiver .curves { diff --git a/tabs/servos.css b/tabs/servos.css index bbdaa2d3..b790639c 100644 --- a/tabs/servos.css +++ b/tabs/servos.css @@ -55,11 +55,9 @@ .tab-servos table input[type="number"] { display: block; - width: calc(100% - 5px); + width: 100%; height: 20px; - padding-right: 5px; - line-height: 20px; text-align: right; From fdbfdfd31dc1ecb2c47ce11deeaa66e70474ea23 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 13:01:46 +0200 Subject: [PATCH 039/213] working feature selection (both read and write), missing description and nicer text --- _locales/en/messages.json | 13 +++++++++ tabs/configuration.css | 55 +++++++++++++++++++++++++++++++++++++ tabs/configuration.html | 9 ++++++ tabs/configuration.js | 58 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 131 insertions(+), 4 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 95756133..4a5b169b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -294,6 +294,19 @@ "message": "EEPROM saved" }, + "configurationMixer": { + "message": "Mixer" + }, + "configurationFeatures": { + "message": "Features" + }, + "configurationEepromSaved": { + "message": "EEPROM saved" + }, + "configurationButtonSave": { + "message": "Save" + }, + "pidTuningName": { "message": "Name" }, diff --git a/tabs/configuration.css b/tabs/configuration.css index 3a4d3172..d14e9089 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -1,2 +1,57 @@ .tab-configuration { + position: relative; +} +.tab-configuration .groupTitle { + padding: 0 0 5px 0; + margin: 0 0 10px 0; + + font-size: 16px; + + border-bottom: 1px solid #dddddd; +} +.tab-configuration .hugeWhitespace { + height: 100px; +} +.tab-configuration dl.features { +} +.tab-configuration dl.features dt { + float: left; + + width: 10px; + height: 18px; + line-height: 18px; +} +.tab-configuration dl.features dt input { + margin-top: 2px; +} +.tab-configuration dl.features dd { + margin: 0 0 0 20px; + height: 18px; + + line-height: 18px; +} + +.tab-configuration .buttons { + position: fixed; + + width: calc(100% - 20px); + bottom: 10px; +} +.tab-configuration .save { + display: block; + float: right; + + height: 28px; + line-height: 28px; + + padding: 0 15px 0 15px; + + text-align: center; + font-weight: bold; + + border: 1px solid silver; + background-color: #ececec; +} +.tab-configuration .save:hover { + background-color: #dedcdc; } \ No newline at end of file diff --git a/tabs/configuration.html b/tabs/configuration.html index 8b9eda54..48af5d71 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -1,2 +1,11 @@
+
+
+
+
+ +
+
+ +
\ No newline at end of file diff --git a/tabs/configuration.js b/tabs/configuration.js index 36aee9aa..0c7e9c47 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -48,8 +48,10 @@ TABS.configuration.initialize = function (callback) { localize(); // index references + var RCMAPlLetters = ['A', 'E', 'R', 'T', '1', '2', '3', '4']; + var featureNames = [ - 'PPM', + 'PPM - Disable PWM input and enable PPM input', 'VBAT', 'INFLIGHT_ACC_CAL', 'SERIALRX', @@ -66,13 +68,61 @@ TABS.configuration.initialize = function (callback) { '3D' ]; - var RCMAPlLetters = ['A', 'E', 'R', 'T', '1', '2', '3', '4']; + // generate features + var features_e = $('.features'); + for (var i = 0; i < featureNames.length; i++) { + var element = $('
'); + element.find('input').attr('checked', bit_check(BF_CONFIG.features, i)); - console.log('all ready'); + features_e.append(element); + } + + + // UI hooks + $('input', features_e).change(function () { + var element = $(this), + index = $('input', features_e).index(element), + state = element.is(':checked'); + + if (state) { + BF_CONFIG.features = bit_set(BF_CONFIG.features, index); + } else { + BF_CONFIG.features = bit_clear(BF_CONFIG.features, index); + } + }); + + $('a.save').click(function () { + function save_to_eeprom() { + MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, reboot); + } + + function reboot() { + GUI.log(chrome.i18n.getMessage('configurationEepromSaved')); + + GUI.tab_switch_cleanup(function() { + MSP.send_message(MSP_codes.MSP_SET_REBOOT, false, false, reinitialize); + }); + } + + function reinitialize() { + GUI.log(chrome.i18n.getMessage('deviceRebooting')); + + MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () { + GUI.log(chrome.i18n.getMessage('deviceReady')); + TABS.configuration.initialize(); + }); + } + + MSP.send_message(MSP_codes.MSP_SET_CONFIG, MSP.crunch(MSP_codes.MSP_SET_CONFIG), false, save_to_eeprom); + }); + + // status data pulled via separate timer with static speed + GUI.interval_add('status_pull', function status_pull () { + MSP.send_message(MSP_codes.MSP_STATUS); + }, 250, true); if (callback) callback(); } - }; TABS.configuration.cleanup = function (callback) { From e8c46d1f25ece397206fee2be488c44dbdcd1669 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 14:21:42 +0200 Subject: [PATCH 040/213] removing various elements from initial tab --- tabs/initial_setup.html | 34 ++------------------- tabs/initial_setup.js | 65 ----------------------------------------- 2 files changed, 3 insertions(+), 96 deletions(-) diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index faf40d0d..eb4f166b 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -28,34 +28,6 @@
-
- - - -
@@ -129,8 +101,8 @@
-
-
- +
+ +
\ No newline at end of file diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 301e2bd2..0605e448 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -46,71 +46,6 @@ TABS.initial_setup.initialize = function (callback) { // set heading in interactive block $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [0])); - - // UI hook handling mixer type change that swaps the image representation - $('.mixer select').change(function () { - var val = $(this).val(); - - var imageArray = [ - 'custom', // there is no type 0, we will use custom image as spacer - 'tri', - 'quadp', - 'quadx', - 'custom', // bi - 'custom', // gimbal - 'y6', - 'hex6p', - 'custom', // flying wing - 'y4', - 'hex6x', - 'octox', - 'octox', - 'octox', - 'airplane', - 'custom', - 'custom', - 'vtail', - 'custom', - 'custom', - 'custom', - 'custom', - 'custom', - ]; - - $('.mixer .preview').attr('src', './images/motor_order/' + imageArray[val] + '.svg'); - }); - - // update mixer type with current value - $('.mixer select').val(BF_CONFIG.mixerConfiguration).change(); - - // save - $('a.update').click(function () { - // update object - BF_CONFIG.mixerConfiguration = parseInt($('.mixer select').val()); - - function save_to_eeprom() { - MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, reboot); - } - - function reboot() { - GUI.log(chrome.i18n.getMessage('initialSetupEepromSaved')); - - GUI.tab_switch_cleanup(function() { - MSP.send_message(MSP_codes.MSP_SET_REBOOT, false, false, reinitialize); - }); - } - - function reinitialize() { - GUI.log(chrome.i18n.getMessage('deviceRebooting')); - - MSP.send_message(MSP_codes.MSP_IDENT, false, false, function () { - GUI.log(chrome.i18n.getMessage('deviceReady')); - TABS.initial_setup.initialize(); - }); - } - - MSP.send_message(MSP_codes.MSP_SET_CONFIG, MSP.crunch(MSP_codes.MSP_SET_CONFIG), false, save_to_eeprom); - }); } else { // old stuff $('.COMPATIBILITY').show(); From c352199434a1c43fc85f9148ab32d53904381182 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 14:22:16 +0200 Subject: [PATCH 041/213] working mixer list with mixer preview --- _locales/en/messages.json | 3 +++ tabs/configuration.css | 26 ++++++++++++++++++----- tabs/configuration.html | 9 +++++++- tabs/configuration.js | 44 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 7 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 4a5b169b..2bdd11d7 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -300,6 +300,9 @@ "configurationFeatures": { "message": "Features" }, + "configurationThrottleAndRC": { + "message": "Throttle & RC" + }, "configurationEepromSaved": { "message": "EEPROM saved" }, diff --git a/tabs/configuration.css b/tabs/configuration.css index d14e9089..df098409 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -3,16 +3,33 @@ } .tab-configuration .groupTitle { padding: 0 0 5px 0; - margin: 0 0 10px 0; + margin: 10px 0 10px 0; font-size: 16px; border-bottom: 1px solid #dddddd; } -.tab-configuration .hugeWhitespace { - height: 100px; +.tab-configuration .groupTitle:nth-of-type(1){ + margin-top: 0; } -.tab-configuration dl.features { +.tab-configuration .mixerList { + float: left; + + height: 100px; + + border: 1px solid silver; +} +.tab-configuration .mixerPreview { + float: left; + + width: 100px; + height: 100px; + + margin: 0 0 0 15px; +} +.tab-configuration .mixerPreview img { + width: 100%; + height: 100%; } .tab-configuration dl.features dt { float: left; @@ -30,7 +47,6 @@ line-height: 18px; } - .tab-configuration .buttons { position: fixed; diff --git a/tabs/configuration.html b/tabs/configuration.html index 48af5d71..fef2ab28 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -1,10 +1,17 @@
-
+ +
+ +
+
+
diff --git a/tabs/configuration.js b/tabs/configuration.js index 0c7e9c47..ff2091a2 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -50,6 +50,49 @@ TABS.configuration.initialize = function (callback) { // index references var RCMAPlLetters = ['A', 'E', 'R', 'T', '1', '2', '3', '4']; + // generate mixer + var mixerList = [ + {name: 'Tricopter', image: 'tri'}, + {name: 'Quad +', image: 'quadp'}, + {name: 'Quad X', image: 'quadx'}, + {name: 'Bicopter', image: 'custom'}, + {name: 'Gimbal', image: 'custom'}, + {name: 'Y 6', image: 'y6'}, + {name: 'HEX 6', image: 'hex6p'}, + {name: 'Flying Wing', image: 'custom'}, + {name: 'Y 4', image: 'y4'}, + {name: 'HEX 6 X', image: 'hex6x'}, + {name: 'OCTO X8', image: 'octox'}, + {name: 'OCTO Flat +', image: 'octox'}, + {name: 'OCTO Flat X', image: 'octox'}, + {name: 'Airplane', image: 'airplane'}, + {name: 'Heli 120', image: 'custom'}, + {name: 'Heli 90', image: 'custom'}, + {name: 'Vtail 4', image: 'vtail'}, + {name: 'Hex 6 H', image: 'custom'}, + {name: 'PPM to SERVO', image: 'custom'}, + {name: 'Dualcopter', image: 'custom'}, + {name: 'Singlecopter', image: 'custom'}, + {name: 'Custom', image: 'custom'} + ]; + + var mixer_list_e = $('select.mixerList'); + for (var i = 0; i < mixerList.length; i++) { + mixer_list_e.append(''); + } + + mixer_list_e.change(function () { + var val = parseInt($(this).val()); + + BF_CONFIG.mixerConfiguration = val; + + $('.mixerPreview img').attr('src', './images/motor_order/' + mixerList[val - 1].image + '.svg'); + }); + + // select current configuration + mixer_list_e.val(BF_CONFIG.mixerConfiguration).change(); + + // generate features var featureNames = [ 'PPM - Disable PWM input and enable PPM input', 'VBAT', @@ -68,7 +111,6 @@ TABS.configuration.initialize = function (callback) { '3D' ]; - // generate features var features_e = $('.features'); for (var i = 0; i < featureNames.length; i++) { var element = $('
'); From a34357d92a4b07bc4986fbc2b8c0179b7158d171 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 15:20:21 +0200 Subject: [PATCH 042/213] initializing input elements for throttle and battery, changed to 2 row design --- _locales/en/messages.json | 7 ++-- main.css | 11 +----- tabs/configuration.css | 41 ++++++++++++++++----- tabs/configuration.html | 76 +++++++++++++++++++++++++++++++++------ tabs/configuration.js | 31 +++++++++++++++- 5 files changed, 134 insertions(+), 32 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 2bdd11d7..ea7e6fea 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -300,8 +300,11 @@ "configurationFeatures": { "message": "Features" }, - "configurationThrottleAndRC": { - "message": "Throttle & RC" + "configurationThrottle": { + "message": "Throttle" + }, + "configurationBattery": { + "message": "Battery" }, "configurationEepromSaved": { "message": "EEPROM saved" diff --git a/main.css b/main.css index 8ad942d1..a75d9e62 100644 --- a/main.css +++ b/main.css @@ -22,17 +22,8 @@ a:hover { text-decoration: none; } input[type="number"]::-webkit-inner-spin-button { - -webkit-appearance: none; - - display: block; opacity: 1; /* required for chromium 33+ beta */ - - width: 15px; - - background-image: url('../images/arrows.png'); - background-repeat: no-repeat; - - border-left: 1px solid silver; + margin-left: 5px; } .clear-both { clear: both; diff --git a/tabs/configuration.css b/tabs/configuration.css index df098409..836a5b34 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -3,33 +3,43 @@ } .tab-configuration .groupTitle { padding: 0 0 5px 0; - margin: 10px 0 10px 0; + margin: 0 0 10px 0; font-size: 16px; border-bottom: 1px solid #dddddd; } -.tab-configuration .groupTitle:nth-of-type(1){ - margin-top: 0; +.tab-configuration .leftWrapper { + float: left; + width: 50%; + + margin: 0 0 10px 0; +} +.tab-configuration .rightWrapper { + float: left; + + width: calc(50% - 10px); + margin: 0 0 10px 10px; } .tab-configuration .mixerList { float: left; - height: 100px; + width: 120px; + height: 250px; border: 1px solid silver; } .tab-configuration .mixerPreview { float: left; - width: 100px; - height: 100px; - - margin: 0 0 0 15px; + width: calc(100% - 120px); + height: 150px; } .tab-configuration .mixerPreview img { width: 100%; height: 100%; + + margin-top: 60px; } .tab-configuration dl.features dt { float: left; @@ -47,6 +57,21 @@ line-height: 18px; } +.tab-configuration .number { + margin-bottom: 5px; +} +.tab-configuration .number input { + width: 60px; + height: 20px; + line-height: 20px; + + text-align: right; + + border: 1px solid silver; +} +.tab-configuration .number span { + margin-left: 10px; +} .tab-configuration .buttons { position: fixed; diff --git a/tabs/configuration.html b/tabs/configuration.html index fef2ab28..d607bf7a 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -1,17 +1,71 @@
-
- -
- +
+
+ +
+ +
+
+
+
+
+
+ +
-
-
- -
-
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
diff --git a/tabs/configuration.js b/tabs/configuration.js index ff2091a2..649a1df4 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -119,6 +119,17 @@ TABS.configuration.initialize = function (callback) { features_e.append(element); } + // fill throttle data + $('input[name="minthrottle"]').val(MISC.minthrottle); + $('input[name="maxthrottle"]').val(MISC.maxthrottle); + $('input[name="failsafe_throttle"]').val(MISC.failsafe_throttle); + $('input[name="mincommand"]').val(MISC.mincommand); + + // fill battery data + $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); + $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); + $('input[name="voltagescale"]').val(MISC.vbatscale); + // UI hooks $('input', features_e).change(function () { @@ -134,6 +145,24 @@ TABS.configuration.initialize = function (callback) { }); $('a.save').click(function () { + // gather data that doesn't have automatic change event bound + MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; + MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; + MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); + + MISC.minthrottle = parseInt($('input[name="minthrottle"]').val()); + MISC.maxthrottle = parseInt($('input[name="maxthrottle"]').val()); + MISC.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val()); + MISC.mincommand = parseInt($('input[name="mincommand"]').val()); + + function save_misc() { + MSP.send_message(MSP_codes.MSP_SET_MISC, MSP.crunch(MSP_codes.MSP_SET_MISC), false, save_acc_trim); + } + + function save_acc_trim() { + MSP.send_message(MSP_codes.MSP_SET_ACC_TRIM, MSP.crunch(MSP_codes.MSP_SET_ACC_TRIM), false, save_to_eeprom); + } + function save_to_eeprom() { MSP.send_message(MSP_codes.MSP_EEPROM_WRITE, false, false, reboot); } @@ -155,7 +184,7 @@ TABS.configuration.initialize = function (callback) { }); } - MSP.send_message(MSP_codes.MSP_SET_CONFIG, MSP.crunch(MSP_codes.MSP_SET_CONFIG), false, save_to_eeprom); + MSP.send_message(MSP_codes.MSP_SET_CONFIG, MSP.crunch(MSP_codes.MSP_SET_CONFIG), false, save_misc); }); // status data pulled via separate timer with static speed From ab8d8e1a56e7e15812910ac282141b579bda816d Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 15:44:28 +0200 Subject: [PATCH 043/213] board alignment, accel trim, mag declination --- _locales/en/messages.json | 6 ++++++ tabs/configuration.html | 43 +++++++++++++++++++++++++++++++++++++++ tabs/configuration.js | 30 ++++++++++++++++++++++----- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index ea7e6fea..57e669db 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -300,6 +300,12 @@ "configurationFeatures": { "message": "Features" }, + "configurationBoardAlignment": { + "message": "Board Alignment" + }, + "configurationAccelTrimMagDec": { + "message": "Accelerometer & Magnetometer" + }, "configurationThrottle": { "message": "Throttle" }, diff --git a/tabs/configuration.html b/tabs/configuration.html index d607bf7a..6e9a2929 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -16,6 +16,49 @@
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
diff --git a/tabs/configuration.js b/tabs/configuration.js index 649a1df4..7d30da53 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -119,13 +119,25 @@ TABS.configuration.initialize = function (callback) { features_e.append(element); } - // fill throttle data + // fill board alignment + $('input[name="board_align_roll"]').val(BF_CONFIG.board_align_roll); + $('input[name="board_align_pitch"]').val(BF_CONFIG.board_align_pitch); + $('input[name="board_align_yaw"]').val(BF_CONFIG.board_align_yaw); + + // fill accel trims + $('input[name="pitch"]').val(CONFIG.accelerometerTrims[0]); + $('input[name="roll"]').val(CONFIG.accelerometerTrims[1]); + + // fill magnetometer + $('input[name="mag_declination"]').val(MISC.mag_declination / 10); + + // fill throttle $('input[name="minthrottle"]').val(MISC.minthrottle); $('input[name="maxthrottle"]').val(MISC.maxthrottle); $('input[name="failsafe_throttle"]').val(MISC.failsafe_throttle); $('input[name="mincommand"]').val(MISC.mincommand); - // fill battery data + // fill battery $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); $('input[name="voltagescale"]').val(MISC.vbatscale); @@ -146,15 +158,23 @@ TABS.configuration.initialize = function (callback) { $('a.save').click(function () { // gather data that doesn't have automatic change event bound - MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; - MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; - MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); + BF_CONFIG.board_align_roll = parseInt($('input[name="board_align_roll"]').val()); + BF_CONFIG.board_align_pitch = parseInt($('input[name="board_align_pitch"]').val()); + BF_CONFIG.board_align_yaw = parseInt($('input[name="board_align_yaw"]').val()); + + CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val()); + CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val()); + MISC.mag_declination = parseFloat($('input[name="mag_declination"]').val()) * 10; MISC.minthrottle = parseInt($('input[name="minthrottle"]').val()); MISC.maxthrottle = parseInt($('input[name="maxthrottle"]').val()); MISC.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val()); MISC.mincommand = parseInt($('input[name="mincommand"]').val()); + MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; + MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; + MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); + function save_misc() { MSP.send_message(MSP_codes.MSP_SET_MISC, MSP.crunch(MSP_codes.MSP_SET_MISC), false, save_acc_trim); } From c537616a3979dd6e22882c9e2d96a1a4725a59fb Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 16:08:40 +0200 Subject: [PATCH 044/213] hooked up (mostly palceholder) text to various inputs --- _locales/en/messages.json | 18 ++++++++++++++++++ tabs/configuration.css | 1 + tabs/configuration.html | 30 +++++++++++++++--------------- tabs/configuration.js | 4 ++-- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 57e669db..c9fd6756 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -303,9 +303,27 @@ "configurationBoardAlignment": { "message": "Board Alignment" }, + "configurationBoardAlignmentRoll": { + "message": "Roll Adjustment [deg]" + }, + "configurationBoardAlignmentPitch": { + "message": "Pitch Adjustment [deg]" + }, + "configurationBoardAlignmentYaw": { + "message": "Yaw Adjustment [deg]" + }, "configurationAccelTrimMagDec": { "message": "Accelerometer & Magnetometer" }, + "configurationAccelTrimRoll": { + "message": "Accelerometer Roll Trim" + }, + "configurationAccelTrimPitch": { + "message": "Accelerometer Pitch Trim" + }, + "configurationMagDeclination": { + "message": "Magnetometer Declination [deg]" + }, "configurationThrottle": { "message": "Throttle" }, diff --git a/tabs/configuration.css b/tabs/configuration.css index 836a5b34..48f278ac 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -71,6 +71,7 @@ } .tab-configuration .number span { margin-left: 10px; + line-height: 20px; } .tab-configuration .buttons { position: fixed; diff --git a/tabs/configuration.html b/tabs/configuration.html index 6e9a2929..2c5780d7 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -21,19 +21,19 @@
@@ -41,20 +41,20 @@
@@ -64,25 +64,25 @@
@@ -91,19 +91,19 @@
diff --git a/tabs/configuration.js b/tabs/configuration.js index 7d30da53..d300cc1e 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -125,8 +125,8 @@ TABS.configuration.initialize = function (callback) { $('input[name="board_align_yaw"]').val(BF_CONFIG.board_align_yaw); // fill accel trims - $('input[name="pitch"]').val(CONFIG.accelerometerTrims[0]); $('input[name="roll"]').val(CONFIG.accelerometerTrims[1]); + $('input[name="pitch"]').val(CONFIG.accelerometerTrims[0]); // fill magnetometer $('input[name="mag_declination"]').val(MISC.mag_declination / 10); @@ -162,8 +162,8 @@ TABS.configuration.initialize = function (callback) { BF_CONFIG.board_align_pitch = parseInt($('input[name="board_align_pitch"]').val()); BF_CONFIG.board_align_yaw = parseInt($('input[name="board_align_yaw"]').val()); - CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val()); CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val()); + CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val()); MISC.mag_declination = parseFloat($('input[name="mag_declination"]').val()) * 10; MISC.minthrottle = parseInt($('input[name="minthrottle"]').val()); From 370ad21f85d30d6aefe1a4b4e43d79d57b2b7df7 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 16:19:20 +0200 Subject: [PATCH 045/213] desc text for throttle and battery category --- _locales/en/messages.json | 24 ++++++++++++++++++++++++ tabs/configuration.html | 14 +++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index c9fd6756..0de767df 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -327,9 +327,33 @@ "configurationThrottle": { "message": "Throttle" }, + "configurationThrottleMinimum": { + "message": "Minimum Throttle" + }, + "configurationThrottleMaximum": { + "message": "Maximum Throttle" + }, + "configurationThrottleFailsafe": { + "message": "Failsafe Throttle" + }, + "configurationThrottleMinimumCommand": { + "message": "Minimum Command" + }, "configurationBattery": { "message": "Battery" }, + + "configurationBatteryMinimum": { + "message": "Minimum Cell Voltage" + }, + "configurationBatteryMaximum": { + "message": "Maximum Cell Voltage" + }, + "configurationBatteryScale": { + "message": "Voltage Scale" + }, + + "configurationEepromSaved": { "message": "EEPROM saved" }, diff --git a/tabs/configuration.html b/tabs/configuration.html index 2c5780d7..b37f1bc3 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -64,25 +64,25 @@
@@ -91,19 +91,19 @@
From a6adfe5c7dcfc8cb88625a945baac6ae6070167a Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 16:26:29 +0200 Subject: [PATCH 046/213] pretty feature descriptions from englishman --- tabs/configuration.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tabs/configuration.js b/tabs/configuration.js index d300cc1e..f466bec7 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -94,21 +94,21 @@ TABS.configuration.initialize = function (callback) { // generate features var featureNames = [ - 'PPM - Disable PWM input and enable PPM input', - 'VBAT', - 'INFLIGHT_ACC_CAL', - 'SERIALRX', - 'MOTOR_STOP', - 'SERVO_TILT', - 'SOFTSERIAL', - 'LED_RING', - 'GPS', - 'FAILSAFE', - 'SONAR', - 'TELEMETRY', - 'POWERMETER', - 'VARIO', - '3D' + 'Enable PPM input (and disable PWM input)', + 'Enable Battery voltage monitoring', + 'Enable in-flight level calibration', + 'Enable Serial-based receiver (SPEKSAT, SBUS, SUMD)', + 'Don\'t spin the motors when armed', + 'Enable servo gimbal', + 'Enable 3rd serial port', + 'Enable LED ring support', + 'Enable GPS (PPM or 3rd serial port required)', + 'Enable failsafe settings on PPM/PWM signal loss', + 'Enable sonar', + 'Enable FrSky- compatible telemetry output', + 'Enable battery current monitoring', + 'Enable VARIO', + 'Enable 3D mode (for use with reversible ESCs)' ]; var features_e = $('.features'); From ce53bc99f264cfb3111af56057117f54333d548b Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 17:02:16 +0200 Subject: [PATCH 047/213] add serial rx type configuration write/read working --- _locales/en/messages.json | 9 ++++++--- tabs/configuration.css | 5 +++++ tabs/configuration.html | 10 +++++++++- tabs/configuration.js | 24 +++++++++++++++++++++++- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 0de767df..26de3077 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -342,7 +342,6 @@ "configurationBattery": { "message": "Battery" }, - "configurationBatteryMinimum": { "message": "Minimum Cell Voltage" }, @@ -352,8 +351,12 @@ "configurationBatteryScale": { "message": "Voltage Scale" }, - - + "configurationGPS": { + "message": "GPS" + }, + "configurationSerialRX": { + "message": "Serial Receiver" + }, "configurationEepromSaved": { "message": "EEPROM saved" }, diff --git a/tabs/configuration.css b/tabs/configuration.css index 48f278ac..0c861d70 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -73,6 +73,11 @@ margin-left: 10px; line-height: 20px; } +.tab-configuration .serialRX { + width: 125px; + + border: 1px solid silver; +} .tab-configuration .buttons { position: fixed; diff --git a/tabs/configuration.html b/tabs/configuration.html index b37f1bc3..a85669ca 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -108,7 +108,15 @@
- +
+
+
+
+
+ +
+
diff --git a/tabs/configuration.js b/tabs/configuration.js index f466bec7..19411575 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -89,7 +89,7 @@ TABS.configuration.initialize = function (callback) { $('.mixerPreview img').attr('src', './images/motor_order/' + mixerList[val - 1].image + '.svg'); }); - // select current configuration + // select current mixer configuration mixer_list_e.val(BF_CONFIG.mixerConfiguration).change(); // generate features @@ -119,6 +119,28 @@ TABS.configuration.initialize = function (callback) { features_e.append(element); } + // generate serial RX + var serialRXtypes = [ + 'SPEKTRUM1024', + 'SPEKTRUM2048', + 'SBUS', + 'SUMD' + ]; + + var serialRX_e = $('select.serialRX'); + for (var i = 0; i < serialRXtypes.length; i++) { + serialRX_e.append(''); + } + + serialRX_e.change(function() { + var val = parseInt($(this).val()); + + BF_CONFIG.serialrx_type = val; + }); + + // select current serial RX type + serialRX_e.val(BF_CONFIG.serialrx_type); + // fill board alignment $('input[name="board_align_roll"]').val(BF_CONFIG.board_align_roll); $('input[name="board_align_pitch"]').val(BF_CONFIG.board_align_pitch); From ee0dec96d8025c09304326f8e12d248da4c096e4 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 17:46:21 +0200 Subject: [PATCH 048/213] gps related configuration --- _locales/en/messages.json | 9 ++++++ tabs/configuration.css | 16 ++++++++++ tabs/configuration.html | 25 +++++++++++++-- tabs/configuration.js | 67 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 112 insertions(+), 5 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 26de3077..6d7ac381 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -354,6 +354,15 @@ "configurationGPS": { "message": "GPS" }, + "configurationGPStype": { + "message": "Type" + }, + "configurationGPSbaudrate": { + "message": "Baudrate" + }, + "configurationGPSubxSbas": { + "message": "Ground Assistance Type" + }, "configurationSerialRX": { "message": "Serial Receiver" }, diff --git a/tabs/configuration.css b/tabs/configuration.css index 0c861d70..380b1bac 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -73,6 +73,22 @@ margin-left: 10px; line-height: 20px; } +.tab-configuration .gps .line { + clear: left; +} +.tab-configuration .gps select { + float: left; + + width: 100px; + height: 20px; + + margin: 0 10px 5px 0; + + border: 1px solid silver; +} +.tab-configuration .gps span { + line-height: 20px; +} .tab-configuration .serialRX { width: 125px; diff --git a/tabs/configuration.html b/tabs/configuration.html index a85669ca..a5e3741a 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -2,7 +2,7 @@
@@ -12,7 +12,7 @@
- +
@@ -108,12 +108,31 @@
-
+
+
+ + +
+
+ + +
+
+ + +
diff --git a/tabs/configuration.js b/tabs/configuration.js index 19411575..b801a9d3 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -119,6 +119,69 @@ TABS.configuration.initialize = function (callback) { features_e.append(element); } + // generate GPS + var gpsTypes = [ + 'NMEA', + 'UBLOX', + 'MTK_NMEA', + 'MTK_BINARY', + 'MAG_BINARY' + ]; + + var gpsBauds = [ + '115200', + '57600', + '38400', + '19200', + '9600' + ]; + + var gpsSbas = [ + 'Auto-detect', + 'European EGNOS', + 'North American WAAS', + 'Japanese MSAS', + 'Indian GAGAN' + ]; + + var gps_type_e = $('select.gps_type'); + for (var i = 0; i < gpsTypes.length; i++) { + gps_type_e.append(''); + } + + gps_type_e.change(function () { + var val = parseInt($(this).val()); + + MISC.gps_type = val; + }); + + var gps_baudrate_e = $('select.gps_baudrate'); + for (var i = 0; i < gpsBauds.length; i++) { + gps_baudrate_e.append(''); + } + + gps_baudrate_e.change(function () { + var val = parseInt($(this).val()); + + MISC.gps_baudrate = val; + }); + + var gps_ubx_sbas_e = $('select.gps_ubx_sbas'); + for (var i = 0; i < gpsSbas.length; i++) { + gps_ubx_sbas_e.append(''); + } + + gps_ubx_sbas_e.change(function () { + var val = parseInt($(this).val()); + + MISC.gps_ubx_sbas = val; + }); + + // select current gps configuration + gps_type_e.val(MISC.gps_type); + gps_baudrate_e.val(MISC.gps_baudrate); + gps_ubx_sbas_e.val(MISC.gps_ubx_sbas); + // generate serial RX var serialRXtypes = [ 'SPEKTRUM1024', @@ -129,10 +192,10 @@ TABS.configuration.initialize = function (callback) { var serialRX_e = $('select.serialRX'); for (var i = 0; i < serialRXtypes.length; i++) { - serialRX_e.append(''); + serialRX_e.append(''); } - serialRX_e.change(function() { + serialRX_e.change(function () { var val = parseInt($(this).val()); BF_CONFIG.serialrx_type = val; From ba046031ed2dbc66b213b09aaeffc8d987e69608 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 20:13:13 +0200 Subject: [PATCH 049/213] add midthrottle (midRc) as requested, placeholder multiwiicurrentoutput variable --- _locales/en/messages.json | 3 +++ js/data_storage.js | 13 +++++++------ tabs/configuration.html | 6 ++++++ tabs/configuration.js | 2 ++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 6d7ac381..646b529b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -330,6 +330,9 @@ "configurationThrottleMinimum": { "message": "Minimum Throttle" }, + "configurationThrottleMid": { + "message": "Middle Throttle [RC inputs center value]" + }, "configurationThrottleMaximum": { "message": "Maximum Throttle" }, diff --git a/js/data_storage.js b/js/data_storage.js index e93ee330..7b763c10 100644 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -24,12 +24,13 @@ var CONFIG = { }; var BF_CONFIG = { - mixerConfiguration: 0, - features: 0, - serialrx_type: 0, - board_align_roll: 0, - board_align_pitch: 0, - board_align_yaw: 0 + mixerConfiguration: 0, + features: 0, + serialrx_type: 0, + board_align_roll: 0, + board_align_pitch: 0, + board_align_yaw: 0, + multiwiicurrentoutput: 0 // TBD }; diff --git a/tabs/configuration.html b/tabs/configuration.html index a5e3741a..fb804f7b 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -67,6 +67,12 @@
+
+ +
-
-
-
- -
-
- -
-
- -
-
-
-
-
- -
-
- -
-
- -
-
-
@@ -93,28 +50,34 @@
-
+
-
+
+
+ +
+
+ + +
+
+ +
+
+ +
+
-
- +
+
+ +
+
+ +
+
+ +
From 6f9c5cb6f22930e9f6e1c7e51ae8b074dacc7c47 Mon Sep 17 00:00:00 2001 From: cTn Date: Wed, 17 Sep 2014 23:00:57 +0200 Subject: [PATCH 051/213] multiwiicurrentoutput checkbox, BF_CONFIG will be extended when firmware updates --- _locales/en/messages.json | 3 +++ tabs/configuration.css | 14 ++++++++++++++ tabs/configuration.html | 10 +++++++++- tabs/configuration.js | 2 ++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 2506ae2a..a600c5cd 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -354,6 +354,9 @@ "configurationBatteryScale": { "message": "Voltage Scale" }, + "configurationBatteryMultiwiiCurrent": { + "message": "Enable support for legacy Multiwii MSP current output" + }, "configurationGPS": { "message": "GPS" }, diff --git a/tabs/configuration.css b/tabs/configuration.css index 380b1bac..82cbab44 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -94,6 +94,20 @@ border: 1px solid silver; } +.tab-configuration .battery .checkbox { + margin-top: 2px; +} +.tab-configuration .battery .checkbox div { + float: left; + width: 60px; +} +.tab-configuration .battery .checkbox div input { + display: block; + margin: 2px auto 0 auto; +} +.tab-configuration .battery .checkbox span { + margin-left: 15px; +} .tab-configuration .buttons { position: fixed; diff --git a/tabs/configuration.html b/tabs/configuration.html index dbb8a401..831c8e8e 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -99,7 +99,7 @@
-
+
+
+ +
diff --git a/tabs/configuration.js b/tabs/configuration.js index 46310187..9429bd0d 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -227,6 +227,7 @@ TABS.configuration.initialize = function (callback) { $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); $('input[name="voltagescale"]').val(MISC.vbatscale); + $('input[name="multiwiicurrentoutput"]').prop('checked', BF_CONFIG.multiwiicurrentoutput); // UI hooks @@ -261,6 +262,7 @@ TABS.configuration.initialize = function (callback) { MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); + BF_CONFIG.multiwiicurrentoutput = ~~$('input[name="multiwiicurrentoutput"]').is(':checked'); // ~~ boolean to decimal conversion function save_misc() { MSP.send_message(MSP_codes.MSP_SET_MISC, MSP.crunch(MSP_codes.MSP_SET_MISC), false, save_acc_trim); From 800bfd59c88ec6fd43dde3ee830c74665a0a1d9e Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 18 Sep 2014 12:24:38 +0200 Subject: [PATCH 052/213] support for multiwiicurrentoutput --- js/data_storage.js | 33 ++++++++++++++++----------------- js/msp.js | 2 +- tabs/configuration.js | 4 ++-- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/js/data_storage.js b/js/data_storage.js index 7b763c10..23766651 100644 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -29,8 +29,7 @@ var BF_CONFIG = { serialrx_type: 0, board_align_roll: 0, board_align_pitch: 0, - board_align_yaw: 0, - multiwiicurrentoutput: 0 + board_align_yaw: 0 // TBD }; @@ -104,19 +103,19 @@ var ANALOG = { }; var MISC = { - midrc: 0, - minthrottle: 0, - maxthrottle: 0, - mincommand: 0, - failsafe_throttle: 0, - gps_type: 0, - gps_baudrate: 0, - gps_ubx_sbas: 0, - placeholder1: 0, - placeholder2: 0, - mag_declination: 0, // not checked - vbatscale: 0, - vbatmincellvoltage: 0, - vbatmaxcellvoltage: 0, - placeholder3: 0 + midrc: 0, + minthrottle: 0, + maxthrottle: 0, + mincommand: 0, + failsafe_throttle: 0, + gps_type: 0, + gps_baudrate: 0, + gps_ubx_sbas: 0, + multiwiicurrentoutput: 0, + placeholder2: 0, + mag_declination: 0, // not checked + vbatscale: 0, + vbatmincellvoltage: 0, + vbatmaxcellvoltage: 0, + placeholder3: 0 }; \ No newline at end of file diff --git a/js/msp.js b/js/msp.js index 219a6b39..b2033b59 100644 --- a/js/msp.js +++ b/js/msp.js @@ -638,7 +638,7 @@ MSP.crunch = function (code) { buffer.push(MISC.gps_type); buffer.push(MISC.gps_baudrate); buffer.push(MISC.gps_ubx_sbas); - buffer.push(MISC.placeholder1); + buffer.push(MISC.multiwiicurrentoutput); buffer.push(lowByte(MISC.placeholder2)); buffer.push(highByte(MISC.placeholder2)); buffer.push(lowByte(MISC.mag_declination)); diff --git a/tabs/configuration.js b/tabs/configuration.js index 9429bd0d..9eaa4866 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -227,7 +227,7 @@ TABS.configuration.initialize = function (callback) { $('input[name="mincellvoltage"]').val(MISC.vbatmincellvoltage); $('input[name="maxcellvoltage"]').val(MISC.vbatmaxcellvoltage); $('input[name="voltagescale"]').val(MISC.vbatscale); - $('input[name="multiwiicurrentoutput"]').prop('checked', BF_CONFIG.multiwiicurrentoutput); + $('input[name="multiwiicurrentoutput"]').prop('checked', MISC.multiwiicurrentoutput); // UI hooks @@ -262,7 +262,7 @@ TABS.configuration.initialize = function (callback) { MISC.vbatmincellvoltage = parseFloat($('input[name="mincellvoltage"]').val()) * 10; MISC.vbatmaxcellvoltage = parseFloat($('input[name="maxcellvoltage"]').val()) * 10; MISC.vbatscale = parseInt($('input[name="voltagescale"]').val()); - BF_CONFIG.multiwiicurrentoutput = ~~$('input[name="multiwiicurrentoutput"]').is(':checked'); // ~~ boolean to decimal conversion + MISC.multiwiicurrentoutput = ~~$('input[name="multiwiicurrentoutput"]').is(':checked'); // ~~ boolean to decimal conversion function save_misc() { MSP.send_message(MSP_codes.MSP_SET_MISC, MSP.crunch(MSP_codes.MSP_SET_MISC), false, save_acc_trim); From 287a1df96251733e5738b5e795a64e8221d94fec Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 18 Sep 2014 12:32:27 +0200 Subject: [PATCH 053/213] simplify some of the change events --- tabs/configuration.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tabs/configuration.js b/tabs/configuration.js index 9eaa4866..4705259f 100644 --- a/tabs/configuration.js +++ b/tabs/configuration.js @@ -150,9 +150,7 @@ TABS.configuration.initialize = function (callback) { } gps_type_e.change(function () { - var val = parseInt($(this).val()); - - MISC.gps_type = val; + MISC.gps_type = parseInt($(this).val()); }); var gps_baudrate_e = $('select.gps_baudrate'); @@ -161,9 +159,7 @@ TABS.configuration.initialize = function (callback) { } gps_baudrate_e.change(function () { - var val = parseInt($(this).val()); - - MISC.gps_baudrate = val; + MISC.gps_baudrate = parseInt($(this).val()); }); var gps_ubx_sbas_e = $('select.gps_ubx_sbas'); @@ -172,9 +168,7 @@ TABS.configuration.initialize = function (callback) { } gps_ubx_sbas_e.change(function () { - var val = parseInt($(this).val()); - - MISC.gps_ubx_sbas = val; + MISC.gps_ubx_sbas = parseInt($(this).val()); }); // select current gps configuration @@ -196,9 +190,7 @@ TABS.configuration.initialize = function (callback) { } serialRX_e.change(function () { - var val = parseInt($(this).val()); - - BF_CONFIG.serialrx_type = val; + BF_CONFIG.serialrx_type = parseInt($(this).val()); }); // select current serial RX type From f2ac7369ded0cb101063f2b5c4a99efc3cea215b Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 18 Sep 2014 12:54:59 +0200 Subject: [PATCH 054/213] add gps info block to fill some of the whitespace --- _locales/en/messages.json | 3 +++ tabs/initial_setup.css | 29 +++++++++++++++++++++++++---- tabs/initial_setup.html | 11 +++++++++++ tabs/initial_setup.js | 18 +++++++++++++++--- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index a600c5cd..6afe39df 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -266,6 +266,9 @@ "initialSetupRSSIValue": { "message": "$1 %" }, + "initialSetupGPSHead": { + "message": "GPS" + }, "initialSetupButtonSave": { "message": "Save" }, diff --git a/tabs/initial_setup.css b/tabs/initial_setup.css index 578099d6..b5baae42 100644 --- a/tabs/initial_setup.css +++ b/tabs/initial_setup.css @@ -5,7 +5,31 @@ height: calc(100% - 142px); } .tab-initial_setup .CAP_BASEFLIGHT_CONFIG #interactive_block { - width: calc(100% - 411px); + width: calc(100% - 199px); +} +.tab-initial_setup .CAP_BASEFLIGHT_CONFIG .gps { + width: 185px; +} +.tab-initial_setup .CAP_BASEFLIGHT_CONFIG .gps .fields { + padding: 5px 5px 3px 5px; +} +.tab-initial_setup .CAP_BASEFLIGHT_CONFIG .gps dt { + float: left; + + width: 85px; + height: 20px; + + margin-bottom: 2px; + + line-height: 20px; +} +.tab-initial_setup .CAP_BASEFLIGHT_CONFIG .gps dd { + height: 20px; + + margin-left: 85px; + margin-bottom: 2px; + + line-height: 20px; } /* temporary styles end*/ @@ -182,9 +206,6 @@ .tab-initial_setup .block .info { width: 200px; } - - - .tab-initial_setup .battery, .tab-initial_setup .throttle, .tab-initial_setup .acc-trim, diff --git a/tabs/initial_setup.html b/tabs/initial_setup.html index eb4f166b..2efb46c9 100644 --- a/tabs/initial_setup.html +++ b/tabs/initial_setup.html @@ -39,6 +39,17 @@
+
+ +
+
+
+
+
+
+
+
+
diff --git a/tabs/initial_setup.js b/tabs/initial_setup.js index 0605e448..cafc29ee 100644 --- a/tabs/initial_setup.js +++ b/tabs/initial_setup.js @@ -257,23 +257,35 @@ TABS.initial_setup.initialize = function (callback) { $('#content .restore').click(configuration_restore); // data pulling functions used inside interval timer + // this stuff will be reworked when compatibility period ends, to make the pulling more efficient function get_analog_data() { - MSP.send_message(MSP_codes.MSP_ANALOG, false, false, get_attitude_data); + MSP.send_message(MSP_codes.MSP_ANALOG, false, false, get_gps_data); + } + + function get_gps_data() { + MSP.send_message(MSP_codes.MSP_RAW_GPS, false, false, get_attitude_data); } function get_attitude_data() { MSP.send_message(MSP_codes.MSP_ATTITUDE, false, false, update_ui); } + // in future update selectors will be moved outside to specific variables to increase performance function update_ui() { + // Update heading + $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [SENSOR_DATA.kinematics[2]])); + // Update voltage indicator $('.bat-voltage').text(chrome.i18n.getMessage('initialSetupBatteryValue', [ANALOG.voltage])); $('.bat-mah-drawn').text(chrome.i18n.getMessage('initialSetupBatteryMahValue', [ANALOG.mAhdrawn])); $('.bat-mah-drawing').text(chrome.i18n.getMessage('initialSetupBatteryAValue', [ANALOG.amperage.toFixed(2)])); $('.rssi').text(chrome.i18n.getMessage('initialSetupRSSIValue', [((ANALOG.rssi / 1023) * 100).toFixed(0)])); - // Update heading - $('span.heading').text(chrome.i18n.getMessage('initialSetupheading', [SENSOR_DATA.kinematics[2]])); + // Update gps + $('.gpsFix').html((GPS_DATA.fix) ? chrome.i18n.getMessage('gpsFixTrue') : chrome.i18n.getMessage('gpsFixFalse')); + $('.gpsSats').text(GPS_DATA.numSat); + $('.gpsLat').text((GPS_DATA.lat / 10000000).toFixed(4) + ' deg'); + $('.gpsLon').text((GPS_DATA.lon / 10000000).toFixed(4) + ' deg'); // Update 3D self.render3D(); From 0c175725b1ab66958db2eba444342d0361e22236 Mon Sep 17 00:00:00 2001 From: cTn Date: Thu, 18 Sep 2014 13:21:48 +0200 Subject: [PATCH 055/213] support for currentscale and currentoffset, ui fully working both read and write --- _locales/en/messages.json | 13 +++++++++++-- js/data_storage.js | 4 +++- js/msp.js | 6 ++++++ tabs/configuration.css | 8 ++++---- tabs/configuration.html | 22 +++++++++++++++++++--- tabs/configuration.js | 7 +++++++ 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 6afe39df..cdf06316 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -345,8 +345,8 @@ "configurationThrottleMinimumCommand": { "message": "Minimum Command" }, - "configurationBatteryCurrent": { - "message": "Battery & Current" + "configurationBatteryVoltage": { + "message": "Battery Voltage" }, "configurationBatteryMinimum": { "message": "Minimum Cell Voltage" @@ -357,6 +357,15 @@ "configurationBatteryScale": { "message": "Voltage Scale" }, + "configurationCurrent": { + "message": "Current Sensor" + }, + "configurationCurrentScale": { + "message": "Scale the output voltage to milliamps [1/10th mV/A]" + }, + "configurationCurrentOffset": { + "message": "Offset in millivolt steps" + }, "configurationBatteryMultiwiiCurrent": { "message": "Enable support for legacy Multiwii MSP current output" }, diff --git a/js/data_storage.js b/js/data_storage.js index 23766651..dca5f2a9 100644 --- a/js/data_storage.js +++ b/js/data_storage.js @@ -29,7 +29,9 @@ var BF_CONFIG = { serialrx_type: 0, board_align_roll: 0, board_align_pitch: 0, - board_align_yaw: 0 + board_align_yaw: 0, + currentscale: 0, + currentoffset: 0 // TBD }; diff --git a/js/msp.js b/js/msp.js index b2033b59..4f5534de 100644 --- a/js/msp.js +++ b/js/msp.js @@ -463,6 +463,8 @@ MSP.process_data = function(code, message_buffer, message_length) { BF_CONFIG.board_align_roll = data.getInt16(6, 1); BF_CONFIG.board_align_pitch = data.getInt16(8, 1); BF_CONFIG.board_align_yaw = data.getInt16(10, 1); + BF_CONFIG.currentscale = data.getUint16(12, 1); + BF_CONFIG.currentoffset = data.getUint16(14, 1); break; case MSP_codes.MSP_SET_CONFIG: break; @@ -574,6 +576,10 @@ MSP.crunch = function (code) { buffer.push(specificByte(BF_CONFIG.board_align_pitch, 1)); buffer.push(specificByte(BF_CONFIG.board_align_yaw, 0)); buffer.push(specificByte(BF_CONFIG.board_align_yaw, 1)); + buffer.push(lowByte(BF_CONFIG.currentscale)); + buffer.push(highByte(BF_CONFIG.currentscale)); + buffer.push(lowByte(BF_CONFIG.currentoffset)); + buffer.push(highByte(BF_CONFIG.currentoffset)); break; case MSP_codes.MSP_SET_PID: for (var i = 0; i < PIDs.length; i++) { diff --git a/tabs/configuration.css b/tabs/configuration.css index 82cbab44..38d8cc49 100644 --- a/tabs/configuration.css +++ b/tabs/configuration.css @@ -94,18 +94,18 @@ border: 1px solid silver; } -.tab-configuration .battery .checkbox { +.tab-configuration .current .checkbox { margin-top: 2px; } -.tab-configuration .battery .checkbox div { +.tab-configuration .current .checkbox div { float: left; width: 60px; } -.tab-configuration .battery .checkbox div input { +.tab-configuration .current .checkbox div input { display: block; margin: 2px auto 0 auto; } -.tab-configuration .battery .checkbox span { +.tab-configuration .current .checkbox span { margin-left: 15px; } .tab-configuration .buttons { diff --git a/tabs/configuration.html b/tabs/configuration.html index 831c8e8e..fb89442c 100644 --- a/tabs/configuration.html +++ b/tabs/configuration.html @@ -99,8 +99,8 @@
-
-
+
+
+
+
+
+
+ +
+
+ +
-
+
+