diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e828e1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +**node_modules +**.git +**dist +**dist +**.firebase +**lock* +**_site** +**.jekyll** diff --git a/galaxy/bundler/webpack.common.js b/galaxy/bundler/webpack.common.js new file mode 100644 index 0000000..71ab148 --- /dev/null +++ b/galaxy/bundler/webpack.common.js @@ -0,0 +1,88 @@ +const CopyWebpackPlugin = require('copy-webpack-plugin') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const MiniCSSExtractPlugin = require('mini-css-extract-plugin') +const path = require('path') + +module.exports = { + entry: path.resolve(__dirname, '../src/script.js'), + output: + { + filename: 'bundle.[contenthash].js', + path: path.resolve(__dirname, '../dist') + }, + devtool: 'source-map', + plugins: + [ + new CopyWebpackPlugin({ + patterns: [ + { from: path.resolve(__dirname, '../static') } + ] + }), + new HtmlWebpackPlugin({ + template: path.resolve(__dirname, '../src/index.html'), + minify: true + }), + new MiniCSSExtractPlugin() + ], + module: + { + rules: + [ + // HTML + { + test: /\.(html)$/, + use: ['html-loader'] + }, + + // JS + { + test: /\.js$/, + exclude: /node_modules/, + use: + [ + 'babel-loader' + ] + }, + + // CSS + { + test: /\.css$/, + use: + [ + MiniCSSExtractPlugin.loader, + 'css-loader' + ] + }, + + // Images + { + test: /\.(jpg|png|gif|svg)$/, + use: + [ + { + loader: 'file-loader', + options: + { + outputPath: 'assets/images/' + } + } + ] + }, + + // Fonts + { + test: /\.(ttf|eot|woff|woff2)$/, + use: + [ + { + loader: 'file-loader', + options: + { + outputPath: 'assets/fonts/' + } + } + ] + } + ] + } +} diff --git a/galaxy/bundler/webpack.dev.js b/galaxy/bundler/webpack.dev.js new file mode 100644 index 0000000..919fd34 --- /dev/null +++ b/galaxy/bundler/webpack.dev.js @@ -0,0 +1,39 @@ +const { merge } = require('webpack-merge') +const commonConfiguration = require('./webpack.common.js') +const ip = require('internal-ip') +const portFinderSync = require('portfinder-sync') + +const infoColor = (_message) => +{ + return `\u001b[1m\u001b[34m${_message}\u001b[39m\u001b[22m` +} + +module.exports = merge( + commonConfiguration, + { + mode: 'development', + devServer: + { + host: '0.0.0.0', + port: portFinderSync.getPort(8080), + contentBase: './dist', + watchContentBase: true, + open: true, + https: false, + useLocalIp: true, + disableHostCheck: true, + overlay: true, + noInfo: true, + after: function(app, server, compiler) + { + const port = server.options.port + const https = server.options.https ? 's' : '' + const localIp = ip.v4.sync() + const domain1 = `http${https}://${localIp}:${port}` + const domain2 = `http${https}://localhost:${port}` + + console.log(`Project running at:\n - ${infoColor(domain1)}\n - ${infoColor(domain2)}`) + } + } + } +) diff --git a/galaxy/bundler/webpack.prod.js b/galaxy/bundler/webpack.prod.js new file mode 100644 index 0000000..295140e --- /dev/null +++ b/galaxy/bundler/webpack.prod.js @@ -0,0 +1,14 @@ +const { merge } = require('webpack-merge') +const commonConfiguration = require('./webpack.common.js') +const { CleanWebpackPlugin } = require('clean-webpack-plugin') + +module.exports = merge( + commonConfiguration, + { + mode: 'production', + plugins: + [ + new CleanWebpackPlugin() + ] + } +) diff --git a/galaxy/package.json b/galaxy/package.json new file mode 100644 index 0000000..f198f52 --- /dev/null +++ b/galaxy/package.json @@ -0,0 +1,28 @@ +{ + "scripts": { + "build": "webpack --config ./bundler/webpack.prod.js", + "dev": "webpack serve --config ./bundler/webpack.dev.js" + }, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/preset-env": "^7.12.11", + "babel-loader": "^8.2.2", + "clean-webpack-plugin": "^3.0.0", + "copy-webpack-plugin": "^7.0.0", + "css-loader": "^5.0.1", + "dat.gui": "^0.7.7", + "file-loader": "^6.2.0", + "firebase-tools": "^9.10.0", + "html-loader": "^1.3.2", + "html-webpack-plugin": "^5.0.0-alpha.7", + "mini-css-extract-plugin": "^1.3.4", + "portfinder-sync": "0.0.2", + "raw-loader": "^4.0.2", + "style-loader": "^2.0.0", + "three": "^0.124.0", + "webpack": "^5.14.0", + "webpack-cli": "^4.3.1", + "webpack-dev-server": "^3.11.2", + "webpack-merge": "^5.7.3" + } +} diff --git a/galaxy/src/index.html b/galaxy/src/index.html new file mode 100644 index 0000000..a25028c --- /dev/null +++ b/galaxy/src/index.html @@ -0,0 +1,11 @@ + + + + + + ai/galaxy + + + + + diff --git a/galaxy/src/script.js b/galaxy/src/script.js new file mode 100644 index 0000000..b9bba3b --- /dev/null +++ b/galaxy/src/script.js @@ -0,0 +1,253 @@ +import './style.css' +import * as THREE from 'three' +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' +//import * as dat from 'dat.gui' +import { AdditiveBlending, Float32BufferAttribute } from 'three' + +/** + * Base + */ +// Debug +//const gui = new dat.GUI({ +// width: 400, +// closed: true +//}) + +const textureLoader = new THREE.TextureLoader() +const shape = textureLoader.load('/pkg/galaxy/particleShape/1.png') + +// Canvas +const canvas = document.querySelector('canvas.webgl') + +// Scene +const scene = new THREE.Scene() + + +//Galaxy Generator + +const parameters = {} + +parameters.count = 70000 +parameters.size = 0.01 +parameters.radius = 5 +parameters.branches = 8 +parameters.spin = 1 +parameters.randomness = 0.3 +parameters.randomnessPower = 5 +parameters.stars = 9000 + +parameters.starColor = '#1b3984' +parameters.insideColor = '#ff6030' +parameters.outsideColor = '#1b3984' +let url_string = window.location.href; +let url = new URL(url_string); +if (url.searchParams.get("star") !== null) { + parameters.starColor = '#' + url.searchParams.get("star"); +} +if (url.searchParams.get("in") !== null) { + parameters.insideColor = '#' + url.searchParams.get("in"); +} +if (url.searchParams.get("out") !== null) { + parameters.outsideColor = '#' + url.searchParams.get("out"); +} + +//gui.add(parameters, 'count').min(100).max(100000).step(100).onChange(generateGalaxy).name('stars in galaxy') +//gui.add(parameters, 'stars').min(0).max(100000).step(100).onChange(generateBgStars).name('background stars') +//gui.addColor(parameters, 'starColor').onChange(generateBgStars).name('color of stars') +//gui.add(parameters, 'size').min(0.001).max(0.1).step(0.001).onChange(generateGalaxy).name('size of stars in galaxy') +//gui.add(parameters, 'radius').min(1).max(10).step(1).onChange(generateGalaxy).name('radius of galaxy') +//gui.add(parameters, 'branches').min(1).max(10).step(1).onChange(generateGalaxy).name('branches in galaxy') +//gui.add(parameters, 'spin').min(-5).max(5).step(0.001).onChange(generateGalaxy).name('spin of the galaxy') +//gui.add(parameters, 'randomness').min(0).max(2).step(0.01).onChange(generateGalaxy) +//gui.add(parameters, 'randomnessPower').min(1).max(10).step(1).onChange(generateGalaxy) +//gui.addColor(parameters, 'insideColor').onChange(generateGalaxy).name('color of core') +//gui.addColor(parameters, 'outsideColor').onChange(generateGalaxy).name('color of branches') + + +let bgStarsGeometry = null +let bgStarsMaterial = null +let bgStars = null + +//Background stars +function generateBgStars(){ + + if(bgStars!==null){ + bgStarsGeometry.dispose() + bgStarsMaterial.dispose() + scene.remove(bgStars) + } + + bgStarsGeometry = new THREE.BufferGeometry() + const bgStarsPositions = new Float32Array(parameters.stars * 3) + + for(let j = 0; j +{ + // Update sizes + sizes.width = window.innerWidth + sizes.height = window.innerHeight + + // Update camera + camera.aspect = sizes.width / sizes.height + camera.updateProjectionMatrix() + + // Update renderer + renderer.setSize(sizes.width, sizes.height) + renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) +}) + +/** + * Camera + */ +// Base camera +const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100) +camera.position.x = 4 +camera.position.y = 0.4 +camera.position.z = 4 +scene.add(camera) + +// Controls +const controls = new OrbitControls(camera, canvas) +controls.enableDamping = true + +/** + * Renderer + */ +const renderer = new THREE.WebGLRenderer({ + canvas: canvas +}) +renderer.setSize(sizes.width, sizes.height) +renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) + +/** + * Animate + */ +const clock = new THREE.Clock() + +const tick = () => +{ + const elapsedTime = clock.getElapsedTime() + + //Update the camera + points.rotation.y = elapsedTime*0.005 + bgStars.rotation.y = - elapsedTime*0.05 + + // Update controls + controls.update() + + // Render + renderer.render(scene, camera) + + // Call tick again on the next frame + window.requestAnimationFrame(tick) + +} + +tick() diff --git a/galaxy/src/style.css b/galaxy/src/style.css new file mode 100644 index 0000000..17374f6 --- /dev/null +++ b/galaxy/src/style.css @@ -0,0 +1,39 @@ +* +{ + margin: 0; + padding: 0; +} + +html, +body +{ + overflow: hidden; +} + +.webgl +{ + position: fixed; + top: 0; + left: 0; + outline: none; +} + +.heading{ + font-family: 'Space Mono', monospace; + z-index: 3; + position: absolute; + top: 30px; + left: 20px; + color: white; +} + +.heading h1{ + font-size: 3rem; + margin: 10px; +} + +.heading h4{ + font-size: 1rem; + font-weight: 400; + margin: 10px; +} diff --git a/galaxy/static/.DS_Store b/galaxy/static/.DS_Store new file mode 100644 index 0000000..1b18240 Binary files /dev/null and b/galaxy/static/.DS_Store differ diff --git a/galaxy/static/.gitkeep b/galaxy/static/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/galaxy/static/particleShape/1.png b/galaxy/static/particleShape/1.png new file mode 100644 index 0000000..b744f88 Binary files /dev/null and b/galaxy/static/particleShape/1.png differ diff --git a/galaxy/static/pkg/galaxy/.DS_Store b/galaxy/static/pkg/galaxy/.DS_Store new file mode 100644 index 0000000..1b18240 Binary files /dev/null and b/galaxy/static/pkg/galaxy/.DS_Store differ diff --git a/galaxy/static/pkg/galaxy/particleShape/1.png b/galaxy/static/pkg/galaxy/particleShape/1.png new file mode 100644 index 0000000..b744f88 Binary files /dev/null and b/galaxy/static/pkg/galaxy/particleShape/1.png differ diff --git a/icon/star.png b/icon/star.png new file mode 100644 index 0000000..f815d56 Binary files /dev/null and b/icon/star.png differ diff --git a/particles/css/style.css b/particles/css/style.css new file mode 100644 index 0000000..d3e8711 --- /dev/null +++ b/particles/css/style.css @@ -0,0 +1,10 @@ +body { + background:#313131; + color: #f1f1f1; +} +footer#footer { + text-align: center; +} +footer#footer a { + color: #f1f1f1; +} diff --git a/particles/index.html b/particles/index.html new file mode 100755 index 0000000..e691c96 --- /dev/null +++ b/particles/index.html @@ -0,0 +1,15 @@ + + + + + ai/star + + + + +
+ + + + + diff --git a/particles/pkg/particles/config.js b/particles/pkg/particles/config.js new file mode 100644 index 0000000..efdb732 --- /dev/null +++ b/particles/pkg/particles/config.js @@ -0,0 +1 @@ +particlesJS("particles-js", {"particles":{"number":{"value":91,"density":{"enable":true,"value_area":881.8766334760375}},"color":{"value":"#fff700"},"shape":{"type":"circle","stroke":{"width":2,"color":"#fff700"},"polygon":{"nb_sides":6},"image":{"src":"","width":100,"height":100}},"opacity":{"value":0.48102361825965684,"random":true,"anim":{"enable":true,"speed":1.0556403676876611,"opacity_min":0.11368434728944043,"sync":true}},"size":{"value":3,"random":true,"anim":{"enable":true,"speed":2,"size_min":0,"sync":true}},"line_linked":{"enable":false,"distance":849.808392258727,"color":"#fff700","opacity":0.44093831673801875,"width":6.894671861721749},"move":{"enable":true,"speed":0.1,"direction":"none","random":true,"straight":false,"out_mode":"out","bounce":false,"attract":{"enable":true,"rotateX":1000,"rotateY":5000}}},"interactivity":{"detect_on":"canvas","events":{"onhover":{"enable":false,"mode":"repulse"},"onclick":{"enable":true,"mode":"remove"},"resize":true},"modes":{"grab":{"distance":523.7600285834934,"line_linked":{"opacity":0.46067027525048987}},"bubble":{"distance":400,"size":40,"duration":2,"opacity":8,"speed":3},"repulse":{"distance":200,"duration":0.4},"push":{"particles_nb":4},"remove":{"particles_nb":2}}},"retina_detect":true});var count_particles, update; count_particles = document.querySelector('.js-count-particles'); update = function() { if (window.pJSDom[0].pJS.particles && window.pJSDom[0].pJS.particles.array) { } requestAnimationFrame(update); }; requestAnimationFrame(update);; diff --git a/particles/pkg/particles/particles.css b/particles/pkg/particles/particles.css new file mode 100644 index 0000000..b06817e --- /dev/null +++ b/particles/pkg/particles/particles.css @@ -0,0 +1,17 @@ +canvas{ + display: block; + vertical-align: bottom; +} +#particles-js{ + /* position:absolute; */ + position:static; + width: 100%; + height: 100%; + background-color: #313131; + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; +} +.count-particles{ + border-radius: 0 0 3px 3px; +} diff --git a/particles/pkg/particles/particles.json b/particles/pkg/particles/particles.json new file mode 100644 index 0000000..a1d64fd --- /dev/null +++ b/particles/pkg/particles/particles.json @@ -0,0 +1 @@ +{"particles":{"number":{"value":380,"density":{"enable":true,"value_area":2084.43567912518}},"color":{"value":"#fff700"},"shape":{"type":"circle","stroke":{"width":3,"color":"#fff700"},"polygon":{"nb_sides":5},"image":{"src":"img/github.svg","width":100,"height":100}},"opacity":{"value":0.32068241217310456,"random":true,"anim":{"enable":false,"speed":1,"opacity_min":0.1,"sync":false}},"size":{"value":4.008530152163807,"random":true,"anim":{"enable":true,"speed":4.87218631240459,"size_min":2.4360931562022947,"sync":false}},"line_linked":{"enable":false,"distance":641.3648243462092,"color":"#fff700","opacity":0.09620472365193136,"width":0.16034120608655228},"move":{"enable":true,"speed":1,"direction":"none","random":true,"straight":true,"out_mode":"out","bounce":false,"attract":{"enable":true,"rotateX":1000,"rotateY":5000}}},"interactivity":{"detect_on":"canvas","events":{"onhover":{"enable":false,"mode":"grab"},"onclick":{"enable":true,"mode":"push"},"resize":true},"modes":{"grab":{"distance":400,"line_linked":{"opacity":1}},"bubble":{"distance":400,"size":40,"duration":2,"opacity":8,"speed":3},"repulse":{"distance":200,"duration":0.4},"push":{"particles_nb":4},"remove":{"particles_nb":2}}},"retina_detect":true} diff --git a/particles/pkg/particles/particles.min.js b/particles/pkg/particles/particles.min.js new file mode 100644 index 0000000..b3d46d1 --- /dev/null +++ b/particles/pkg/particles/particles.min.js @@ -0,0 +1,9 @@ +/* ----------------------------------------------- +/* Author : Vincent Garreau - vincentgarreau.com +/* MIT license: http://opensource.org/licenses/MIT +/* Demo / Generator : vincentgarreau.com/particles.js +/* GitHub : github.com/VincentGarreau/particles.js +/* How to use? : Check the GitHub README +/* v2.0.0 +/* ----------------------------------------------- */ +function hexToRgb(e){var a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(a,function(e,a,t,i){return a+a+t+t+i+i});var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?{r:parseInt(t[1],16),g:parseInt(t[2],16),b:parseInt(t[3],16)}:null}function clamp(e,a,t){return Math.min(Math.max(e,a),t)}function isInArray(e,a){return a.indexOf(e)>-1}var pJS=function(e,a){var t=document.querySelector("#"+e+" > .particles-js-canvas-el");this.pJS={canvas:{el:t,w:t.offsetWidth,h:t.offsetHeight},particles:{number:{value:400,density:{enable:!0,value_area:800}},color:{value:"#fff"},shape:{type:"circle",stroke:{width:0,color:"#ff0000"},polygon:{nb_sides:5},image:{src:"",width:100,height:100}},opacity:{value:1,random:!1,anim:{enable:!1,speed:2,opacity_min:0,sync:!1}},size:{value:20,random:!1,anim:{enable:!1,speed:20,size_min:0,sync:!1}},line_linked:{enable:!0,distance:100,color:"#fff",opacity:1,width:1},move:{enable:!0,speed:2,direction:"none",random:!1,straight:!1,out_mode:"out",bounce:!1,attract:{enable:!1,rotateX:3e3,rotateY:3e3}},array:[]},interactivity:{detect_on:"canvas",events:{onhover:{enable:!0,mode:"grab"},onclick:{enable:!0,mode:"push"},resize:!0},modes:{grab:{distance:100,line_linked:{opacity:1}},bubble:{distance:200,size:80,duration:.4},repulse:{distance:200,duration:.4},push:{particles_nb:4},remove:{particles_nb:2}},mouse:{}},retina_detect:!1,fn:{interact:{},modes:{},vendors:{}},tmp:{}};var i=this.pJS;a&&Object.deepExtend(i,a),i.tmp.obj={size_value:i.particles.size.value,size_anim_speed:i.particles.size.anim.speed,move_speed:i.particles.move.speed,line_linked_distance:i.particles.line_linked.distance,line_linked_width:i.particles.line_linked.width,mode_grab_distance:i.interactivity.modes.grab.distance,mode_bubble_distance:i.interactivity.modes.bubble.distance,mode_bubble_size:i.interactivity.modes.bubble.size,mode_repulse_distance:i.interactivity.modes.repulse.distance},i.fn.retinaInit=function(){i.retina_detect&&window.devicePixelRatio>1?(i.canvas.pxratio=window.devicePixelRatio,i.tmp.retina=!0):(i.canvas.pxratio=1,i.tmp.retina=!1),i.canvas.w=i.canvas.el.offsetWidth*i.canvas.pxratio,i.canvas.h=i.canvas.el.offsetHeight*i.canvas.pxratio,i.particles.size.value=i.tmp.obj.size_value*i.canvas.pxratio,i.particles.size.anim.speed=i.tmp.obj.size_anim_speed*i.canvas.pxratio,i.particles.move.speed=i.tmp.obj.move_speed*i.canvas.pxratio,i.particles.line_linked.distance=i.tmp.obj.line_linked_distance*i.canvas.pxratio,i.interactivity.modes.grab.distance=i.tmp.obj.mode_grab_distance*i.canvas.pxratio,i.interactivity.modes.bubble.distance=i.tmp.obj.mode_bubble_distance*i.canvas.pxratio,i.particles.line_linked.width=i.tmp.obj.line_linked_width*i.canvas.pxratio,i.interactivity.modes.bubble.size=i.tmp.obj.mode_bubble_size*i.canvas.pxratio,i.interactivity.modes.repulse.distance=i.tmp.obj.mode_repulse_distance*i.canvas.pxratio},i.fn.canvasInit=function(){i.canvas.ctx=i.canvas.el.getContext("2d")},i.fn.canvasSize=function(){i.canvas.el.width=i.canvas.w,i.canvas.el.height=i.canvas.h,i&&i.interactivity.events.resize&&window.addEventListener("resize",function(){i.canvas.w=i.canvas.el.offsetWidth,i.canvas.h=i.canvas.el.offsetHeight,i.tmp.retina&&(i.canvas.w*=i.canvas.pxratio,i.canvas.h*=i.canvas.pxratio),i.canvas.el.width=i.canvas.w,i.canvas.el.height=i.canvas.h,i.particles.move.enable||(i.fn.particlesEmpty(),i.fn.particlesCreate(),i.fn.particlesDraw(),i.fn.vendors.densityAutoParticles()),i.fn.vendors.densityAutoParticles()})},i.fn.canvasPaint=function(){i.canvas.ctx.fillRect(0,0,i.canvas.w,i.canvas.h)},i.fn.canvasClear=function(){i.canvas.ctx.clearRect(0,0,i.canvas.w,i.canvas.h)},i.fn.particle=function(e,a,t){if(this.radius=(i.particles.size.random?Math.random():1)*i.particles.size.value,i.particles.size.anim.enable&&(this.size_status=!1,this.vs=i.particles.size.anim.speed/100,i.particles.size.anim.sync||(this.vs=this.vs*Math.random())),this.x=t?t.x:Math.random()*i.canvas.w,this.y=t?t.y:Math.random()*i.canvas.h,this.x>i.canvas.w-2*this.radius?this.x=this.x-this.radius:this.x<2*this.radius&&(this.x=this.x+this.radius),this.y>i.canvas.h-2*this.radius?this.y=this.y-this.radius:this.y<2*this.radius&&(this.y=this.y+this.radius),i.particles.move.bounce&&i.fn.vendors.checkOverlap(this,t),this.color={},"object"==typeof e.value)if(e.value instanceof Array){var s=e.value[Math.floor(Math.random()*i.particles.color.value.length)];this.color.rgb=hexToRgb(s)}else void 0!=e.value.r&&void 0!=e.value.g&&void 0!=e.value.b&&(this.color.rgb={r:e.value.r,g:e.value.g,b:e.value.b}),void 0!=e.value.h&&void 0!=e.value.s&&void 0!=e.value.l&&(this.color.hsl={h:e.value.h,s:e.value.s,l:e.value.l});else"random"==e.value?this.color.rgb={r:Math.floor(256*Math.random())+0,g:Math.floor(256*Math.random())+0,b:Math.floor(256*Math.random())+0}:"string"==typeof e.value&&(this.color=e,this.color.rgb=hexToRgb(this.color.value));this.opacity=(i.particles.opacity.random?Math.random():1)*i.particles.opacity.value,i.particles.opacity.anim.enable&&(this.opacity_status=!1,this.vo=i.particles.opacity.anim.speed/100,i.particles.opacity.anim.sync||(this.vo=this.vo*Math.random()));var n={};switch(i.particles.move.direction){case"top":n={x:0,y:-1};break;case"top-right":n={x:.5,y:-.5};break;case"right":n={x:1,y:-0};break;case"bottom-right":n={x:.5,y:.5};break;case"bottom":n={x:0,y:1};break;case"bottom-left":n={x:-.5,y:1};break;case"left":n={x:-1,y:0};break;case"top-left":n={x:-.5,y:-.5};break;default:n={x:0,y:0}}i.particles.move.straight?(this.vx=n.x,this.vy=n.y,i.particles.move.random&&(this.vx=this.vx*Math.random(),this.vy=this.vy*Math.random())):(this.vx=n.x+Math.random()-.5,this.vy=n.y+Math.random()-.5),this.vx_i=this.vx,this.vy_i=this.vy;var r=i.particles.shape.type;if("object"==typeof r){if(r instanceof Array){var c=r[Math.floor(Math.random()*r.length)];this.shape=c}}else this.shape=r;if("image"==this.shape){var o=i.particles.shape;this.img={src:o.image.src,ratio:o.image.width/o.image.height},this.img.ratio||(this.img.ratio=1),"svg"==i.tmp.img_type&&void 0!=i.tmp.source_svg&&(i.fn.vendors.createSvgImg(this),i.tmp.pushing&&(this.img.loaded=!1))}},i.fn.particle.prototype.draw=function(){function e(){i.canvas.ctx.drawImage(r,a.x-t,a.y-t,2*t,2*t/a.img.ratio)}var a=this;if(void 0!=a.radius_bubble)var t=a.radius_bubble;else var t=a.radius;if(void 0!=a.opacity_bubble)var s=a.opacity_bubble;else var s=a.opacity;if(a.color.rgb)var n="rgba("+a.color.rgb.r+","+a.color.rgb.g+","+a.color.rgb.b+","+s+")";else var n="hsla("+a.color.hsl.h+","+a.color.hsl.s+"%,"+a.color.hsl.l+"%,"+s+")";switch(i.canvas.ctx.fillStyle=n,i.canvas.ctx.beginPath(),a.shape){case"circle":i.canvas.ctx.arc(a.x,a.y,t,0,2*Math.PI,!1);break;case"edge":i.canvas.ctx.rect(a.x-t,a.y-t,2*t,2*t);break;case"triangle":i.fn.vendors.drawShape(i.canvas.ctx,a.x-t,a.y+t/1.66,2*t,3,2);break;case"polygon":i.fn.vendors.drawShape(i.canvas.ctx,a.x-t/(i.particles.shape.polygon.nb_sides/3.5),a.y-t/.76,2.66*t/(i.particles.shape.polygon.nb_sides/3),i.particles.shape.polygon.nb_sides,1);break;case"star":i.fn.vendors.drawShape(i.canvas.ctx,a.x-2*t/(i.particles.shape.polygon.nb_sides/4),a.y-t/1.52,2*t*2.66/(i.particles.shape.polygon.nb_sides/3),i.particles.shape.polygon.nb_sides,2);break;case"image":if("svg"==i.tmp.img_type)var r=a.img.obj;else var r=i.tmp.img_obj;r&&e()}i.canvas.ctx.closePath(),i.particles.shape.stroke.width>0&&(i.canvas.ctx.strokeStyle=i.particles.shape.stroke.color,i.canvas.ctx.lineWidth=i.particles.shape.stroke.width,i.canvas.ctx.stroke()),i.canvas.ctx.fill()},i.fn.particlesCreate=function(){for(var e=0;e=i.particles.opacity.value&&(a.opacity_status=!1),a.opacity+=a.vo):(a.opacity<=i.particles.opacity.anim.opacity_min&&(a.opacity_status=!0),a.opacity-=a.vo),a.opacity<0&&(a.opacity=0)),i.particles.size.anim.enable&&(1==a.size_status?(a.radius>=i.particles.size.value&&(a.size_status=!1),a.radius+=a.vs):(a.radius<=i.particles.size.anim.size_min&&(a.size_status=!0),a.radius-=a.vs),a.radius<0&&(a.radius=0)),"bounce"==i.particles.move.out_mode)var s={x_left:a.radius,x_right:i.canvas.w,y_top:a.radius,y_bottom:i.canvas.h};else var s={x_left:-a.radius,x_right:i.canvas.w+a.radius,y_top:-a.radius,y_bottom:i.canvas.h+a.radius};switch(a.x-a.radius>i.canvas.w?(a.x=s.x_left,a.y=Math.random()*i.canvas.h):a.x+a.radius<0&&(a.x=s.x_right,a.y=Math.random()*i.canvas.h),a.y-a.radius>i.canvas.h?(a.y=s.y_top,a.x=Math.random()*i.canvas.w):a.y+a.radius<0&&(a.y=s.y_bottom,a.x=Math.random()*i.canvas.w),i.particles.move.out_mode){case"bounce":a.x+a.radius>i.canvas.w?a.vx=-a.vx:a.x-a.radius<0&&(a.vx=-a.vx),a.y+a.radius>i.canvas.h?a.vy=-a.vy:a.y-a.radius<0&&(a.vy=-a.vy)}if(isInArray("grab",i.interactivity.events.onhover.mode)&&i.fn.modes.grabParticle(a),(isInArray("bubble",i.interactivity.events.onhover.mode)||isInArray("bubble",i.interactivity.events.onclick.mode))&&i.fn.modes.bubbleParticle(a),(isInArray("repulse",i.interactivity.events.onhover.mode)||isInArray("repulse",i.interactivity.events.onclick.mode))&&i.fn.modes.repulseParticle(a),i.particles.line_linked.enable||i.particles.move.attract.enable)for(var n=e+1;n0){var c=i.particles.line_linked.color_rgb_line;i.canvas.ctx.strokeStyle="rgba("+c.r+","+c.g+","+c.b+","+r+")",i.canvas.ctx.lineWidth=i.particles.line_linked.width,i.canvas.ctx.beginPath(),i.canvas.ctx.moveTo(e.x,e.y),i.canvas.ctx.lineTo(a.x,a.y),i.canvas.ctx.stroke(),i.canvas.ctx.closePath()}}},i.fn.interact.attractParticles=function(e,a){var t=e.x-a.x,s=e.y-a.y,n=Math.sqrt(t*t+s*s);if(n<=i.particles.line_linked.distance){var r=t/(1e3*i.particles.move.attract.rotateX),c=s/(1e3*i.particles.move.attract.rotateY);e.vx-=r,e.vy-=c,a.vx+=r,a.vy+=c}},i.fn.interact.bounceParticles=function(e,a){var t=e.x-a.x,i=e.y-a.y,s=Math.sqrt(t*t+i*i),n=e.radius+a.radius;n>=s&&(e.vx=-e.vx,e.vy=-e.vy,a.vx=-a.vx,a.vy=-a.vy)},i.fn.modes.pushParticles=function(e,a){i.tmp.pushing=!0;for(var t=0;e>t;t++)i.particles.array.push(new i.fn.particle(i.particles.color,i.particles.opacity.value,{x:a?a.pos_x:Math.random()*i.canvas.w,y:a?a.pos_y:Math.random()*i.canvas.h})),t==e-1&&(i.particles.move.enable||i.fn.particlesDraw(),i.tmp.pushing=!1)},i.fn.modes.removeParticles=function(e){i.particles.array.splice(0,e),i.particles.move.enable||i.fn.particlesDraw()},i.fn.modes.bubbleParticle=function(e){function a(){e.opacity_bubble=e.opacity,e.radius_bubble=e.radius}function t(a,t,s,n,c){if(a!=t)if(i.tmp.bubble_duration_end){if(void 0!=s){var o=n-p*(n-a)/i.interactivity.modes.bubble.duration,l=a-o;d=a+l,"size"==c&&(e.radius_bubble=d),"opacity"==c&&(e.opacity_bubble=d)}}else if(r<=i.interactivity.modes.bubble.distance){if(void 0!=s)var v=s;else var v=n;if(v!=a){var d=n-p*(n-a)/i.interactivity.modes.bubble.duration;"size"==c&&(e.radius_bubble=d),"opacity"==c&&(e.opacity_bubble=d)}}else"size"==c&&(e.radius_bubble=void 0),"opacity"==c&&(e.opacity_bubble=void 0)}if(i.interactivity.events.onhover.enable&&isInArray("bubble",i.interactivity.events.onhover.mode)){var s=e.x-i.interactivity.mouse.pos_x,n=e.y-i.interactivity.mouse.pos_y,r=Math.sqrt(s*s+n*n),c=1-r/i.interactivity.modes.bubble.distance;if(r<=i.interactivity.modes.bubble.distance){if(c>=0&&"mousemove"==i.interactivity.status){if(i.interactivity.modes.bubble.size!=i.particles.size.value)if(i.interactivity.modes.bubble.size>i.particles.size.value){var o=e.radius+i.interactivity.modes.bubble.size*c;o>=0&&(e.radius_bubble=o)}else{var l=e.radius-i.interactivity.modes.bubble.size,o=e.radius-l*c;o>0?e.radius_bubble=o:e.radius_bubble=0}if(i.interactivity.modes.bubble.opacity!=i.particles.opacity.value)if(i.interactivity.modes.bubble.opacity>i.particles.opacity.value){var v=i.interactivity.modes.bubble.opacity*c;v>e.opacity&&v<=i.interactivity.modes.bubble.opacity&&(e.opacity_bubble=v)}else{var v=e.opacity-(i.particles.opacity.value-i.interactivity.modes.bubble.opacity)*c;v=i.interactivity.modes.bubble.opacity&&(e.opacity_bubble=v)}}}else a();"mouseleave"==i.interactivity.status&&a()}else if(i.interactivity.events.onclick.enable&&isInArray("bubble",i.interactivity.events.onclick.mode)){if(i.tmp.bubble_clicking){var s=e.x-i.interactivity.mouse.click_pos_x,n=e.y-i.interactivity.mouse.click_pos_y,r=Math.sqrt(s*s+n*n),p=((new Date).getTime()-i.interactivity.mouse.click_time)/1e3;p>i.interactivity.modes.bubble.duration&&(i.tmp.bubble_duration_end=!0),p>2*i.interactivity.modes.bubble.duration&&(i.tmp.bubble_clicking=!1,i.tmp.bubble_duration_end=!1)}i.tmp.bubble_clicking&&(t(i.interactivity.modes.bubble.size,i.particles.size.value,e.radius_bubble,e.radius,"size"),t(i.interactivity.modes.bubble.opacity,i.particles.opacity.value,e.opacity_bubble,e.opacity,"opacity"))}},i.fn.modes.repulseParticle=function(e){function a(){var a=Math.atan2(d,p);if(e.vx=u*Math.cos(a),e.vy=u*Math.sin(a),"bounce"==i.particles.move.out_mode){var t={x:e.x+e.vx,y:e.y+e.vy};t.x+e.radius>i.canvas.w?e.vx=-e.vx:t.x-e.radius<0&&(e.vx=-e.vx),t.y+e.radius>i.canvas.h?e.vy=-e.vy:t.y-e.radius<0&&(e.vy=-e.vy)}}if(i.interactivity.events.onhover.enable&&isInArray("repulse",i.interactivity.events.onhover.mode)&&"mousemove"==i.interactivity.status){var t=e.x-i.interactivity.mouse.pos_x,s=e.y-i.interactivity.mouse.pos_y,n=Math.sqrt(t*t+s*s),r={x:t/n,y:s/n},c=i.interactivity.modes.repulse.distance,o=100,l=clamp(1/c*(-1*Math.pow(n/c,2)+1)*c*o,0,50),v={x:e.x+r.x*l,y:e.y+r.y*l};"bounce"==i.particles.move.out_mode?(v.x-e.radius>0&&v.x+e.radius0&&v.y+e.radius=m&&a()}else 0==i.tmp.repulse_clicking&&(e.vx=e.vx_i,e.vy=e.vy_i)},i.fn.modes.grabParticle=function(e){if(i.interactivity.events.onhover.enable&&"mousemove"==i.interactivity.status){var a=e.x-i.interactivity.mouse.pos_x,t=e.y-i.interactivity.mouse.pos_y,s=Math.sqrt(a*a+t*t);if(s<=i.interactivity.modes.grab.distance){var n=i.interactivity.modes.grab.line_linked.opacity-s/(1/i.interactivity.modes.grab.line_linked.opacity)/i.interactivity.modes.grab.distance;if(n>0){var r=i.particles.line_linked.color_rgb_line;i.canvas.ctx.strokeStyle="rgba("+r.r+","+r.g+","+r.b+","+n+")",i.canvas.ctx.lineWidth=i.particles.line_linked.width,i.canvas.ctx.beginPath(),i.canvas.ctx.moveTo(e.x,e.y),i.canvas.ctx.lineTo(i.interactivity.mouse.pos_x,i.interactivity.mouse.pos_y),i.canvas.ctx.stroke(),i.canvas.ctx.closePath()}}}},i.fn.vendors.eventsListeners=function(){"window"==i.interactivity.detect_on?i.interactivity.el=window:i.interactivity.el=i.canvas.el,(i.interactivity.events.onhover.enable||i.interactivity.events.onclick.enable)&&(i.interactivity.el.addEventListener("mousemove",function(e){if(i.interactivity.el==window)var a=e.clientX,t=e.clientY;else var a=e.offsetX||e.clientX,t=e.offsetY||e.clientY;i.interactivity.mouse.pos_x=a,i.interactivity.mouse.pos_y=t,i.tmp.retina&&(i.interactivity.mouse.pos_x*=i.canvas.pxratio,i.interactivity.mouse.pos_y*=i.canvas.pxratio),i.interactivity.status="mousemove"}),i.interactivity.el.addEventListener("mouseleave",function(e){i.interactivity.mouse.pos_x=null,i.interactivity.mouse.pos_y=null,i.interactivity.status="mouseleave"})),i.interactivity.events.onclick.enable&&i.interactivity.el.addEventListener("click",function(){if(i.interactivity.mouse.click_pos_x=i.interactivity.mouse.pos_x,i.interactivity.mouse.click_pos_y=i.interactivity.mouse.pos_y,i.interactivity.mouse.click_time=(new Date).getTime(),i.interactivity.events.onclick.enable)switch(i.interactivity.events.onclick.mode){case"push":i.particles.move.enable?i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb,i.interactivity.mouse):1==i.interactivity.modes.push.particles_nb?i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb,i.interactivity.mouse):i.interactivity.modes.push.particles_nb>1&&i.fn.modes.pushParticles(i.interactivity.modes.push.particles_nb);break;case"remove":i.fn.modes.removeParticles(i.interactivity.modes.remove.particles_nb);break;case"bubble":i.tmp.bubble_clicking=!0;break;case"repulse":i.tmp.repulse_clicking=!0,i.tmp.repulse_count=0,i.tmp.repulse_finish=!1,setTimeout(function(){i.tmp.repulse_clicking=!1},1e3*i.interactivity.modes.repulse.duration)}})},i.fn.vendors.densityAutoParticles=function(){if(i.particles.number.density.enable){var e=i.canvas.el.width*i.canvas.el.height/1e3;i.tmp.retina&&(e/=2*i.canvas.pxratio);var a=e*i.particles.number.value/i.particles.number.density.value_area,t=i.particles.array.length-a;0>t?i.fn.modes.pushParticles(Math.abs(t)):i.fn.modes.removeParticles(t)}},i.fn.vendors.checkOverlap=function(e,a){for(var t=0;tv;v++)e.lineTo(i,0),e.translate(i,0),e.rotate(l);e.fill(),e.restore()},i.fn.vendors.exportImg=function(){window.open(i.canvas.el.toDataURL("image/png"),"_blank")},i.fn.vendors.loadImg=function(e){if(i.tmp.img_error=void 0,""!=i.particles.shape.image.src)if("svg"==e){var a=new XMLHttpRequest;a.open("GET",i.particles.shape.image.src),a.onreadystatechange=function(e){4==a.readyState&&(200==a.status?(i.tmp.source_svg=e.currentTarget.response,i.fn.vendors.checkBeforeDraw()):(console.log("Error pJS - Image not found"),i.tmp.img_error=!0))},a.send()}else{var t=new Image;t.addEventListener("load",function(){i.tmp.img_obj=t,i.fn.vendors.checkBeforeDraw()}),t.src=i.particles.shape.image.src}else console.log("Error pJS - No image.src"),i.tmp.img_error=!0},i.fn.vendors.draw=function(){"image"==i.particles.shape.type?"svg"==i.tmp.img_type?i.tmp.count_svg>=i.particles.number.value?(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame)):i.tmp.img_error||(i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw)):void 0!=i.tmp.img_obj?(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame)):i.tmp.img_error||(i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw)):(i.fn.particlesDraw(),i.particles.move.enable?i.fn.drawAnimFrame=requestAnimFrame(i.fn.vendors.draw):cancelRequestAnimFrame(i.fn.drawAnimFrame))},i.fn.vendors.checkBeforeDraw=function(){"image"==i.particles.shape.type?"svg"==i.tmp.img_type&&void 0==i.tmp.source_svg?i.tmp.checkAnimFrame=requestAnimFrame(check):(cancelRequestAnimFrame(i.tmp.checkAnimFrame),i.tmp.img_error||(i.fn.vendors.init(),i.fn.vendors.draw())):(i.fn.vendors.init(),i.fn.vendors.draw())},i.fn.vendors.init=function(){i.fn.retinaInit(),i.fn.canvasInit(),i.fn.canvasSize(),i.fn.canvasPaint(),i.fn.particlesCreate(),i.fn.vendors.densityAutoParticles(),i.particles.line_linked.color_rgb_line=hexToRgb(i.particles.line_linked.color)},i.fn.vendors.start=function(){isInArray("image",i.particles.shape.type)?(i.tmp.img_type=i.particles.shape.image.src.substr(i.particles.shape.image.src.length-3),i.fn.vendors.loadImg(i.tmp.img_type)):i.fn.vendors.checkBeforeDraw()},i.fn.vendors.eventsListeners(),i.fn.vendors.start()};Object.deepExtend=function(e,a){for(var t in a)a[t]&&a[t].constructor&&a[t].constructor===Object?(e[t]=e[t]||{},arguments.callee(e[t],a[t])):e[t]=a[t];return e},window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}(),window.cancelRequestAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame||window.oCancelRequestAnimationFrame||window.msCancelRequestAnimationFrame||clearTimeout}(),window.pJSDom=[],window.particlesJS=function(e,a){"string"!=typeof e&&(a=e,e="particles-js"),e||(e="particles-js");var t=document.getElementById(e),i="particles-js-canvas-el",s=t.getElementsByClassName(i);if(s.length)for(;s.length>0;)t.removeChild(s[0]);var n=document.createElement("canvas");n.className=i,n.style.width="100%",n.style.height="100%";var r=document.getElementById(e).appendChild(n);null!=r&&pJSDom.push(new pJS(e,a))},window.particlesJS.load=function(e,a,t){var i=new XMLHttpRequest;i.open("GET",a),i.onreadystatechange=function(a){if(4==i.readyState)if(200==i.status){var s=JSON.parse(a.currentTarget.response);window.particlesJS(e,s),t&&t()}else console.log("Error pJS - XMLHttpRequest status: "+i.status),console.log("Error pJS - File config not found")},i.send()}; \ No newline at end of file diff --git a/readme.md b/readme.md index e74fe54..4703f1a 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,12 @@ -# ai `star` +# ai `star` - [particles.js](https://github.com/VincentGarreau/particles.js) +- [galaxy](https://github.com/the-halfbloodprince/GalaxyM1199) +- [solar-sys](https://github.com/solarcg/SolarSys) + +## example + +- [galaxy2](https://github.com/the-halfbloodprince/Galaxy-M2999) +- [100-stars](https://stars.chromeexperiments.com/) +- [nasa/solar-system](https://eyes.nasa.gov/apps/solar-system/) +- [nasa/3d-resources](https://github.com/nasa/NASA-3D-Resources) diff --git a/solar/css/solar.css b/solar/css/solar.css new file mode 100644 index 0000000..afad1d0 --- /dev/null +++ b/solar/css/solar.css @@ -0,0 +1,175 @@ +body { + color: #ffffff; + font-family: "Segoe UI", Myriad, Helvetica, Arial, "DejaVu Sans", "Noto Sans CJK SC", "Source Han Sans SC"; + font-size: 20px; + text-align: left; + background-color: #000000; + margin: 0px; + overflow: hidden; +} + +.small { + font-size: 12px; +} + +#container { + text-align: center; + width: 100%; + height: 100%; +} + +#info { + text-align: center; + position: absolute; + top: 0px; + width: 100%; + padding: 5px; +} + +h3, p { + margin-top: 5px; + margin-bottom: 5px; +} + +img { + margin-top: 10px; + max-width:100% !important; + height:30% !important; +} + + +a { + color: #ffffff; + outline: none; + text-decoration: none; +} + +a:hover, a:focus { + color: #ffffff; +} + +.progress { + display: inline-block; + font-size: 18px; + color: #ffffff !important; + text-decoration: none !important; + margin-top: 20px; + padding: 6px 70px; + line-height: 1; + overflow: hidden; + position: relative; + + border-style: solid; + border-width: 1px; + border-color: #ffffff; + border-radius: 15px; + + background-color: transparent; + + transition: box-shadow 0.5s; + -moz-transition: box-shadow 0.5s; + -o-transition: box-shadow 0.5s; + -webkit-transition: box-shadow 0.5s; +} + +.progress:hover, .progress:focus { + box-shadow: 0px 0px 30px #ffffffaa; + transition: box-shadow 0.5s; + -moz-transition: box-shadow 0.5s; + -o-transition: box-shadow 0.5s; + -webkit-transition: box-shadow 0.5s; +} + +.progress.in-progress, +.progress.finished { + color: transparent !important; +} + +.progress.in-progress:after, +.progress.finished:after { + position: absolute; + z-index: 2; + width: 100%; + height: 100%; + text-align: center; + top: 0; + padding-top: inherit; + color: #000000 !important; + left: 0; +} + +/* If the .in-progress class is set on the button, show the + contents of the data-loading attribute on the butotn */ + +.progress.in-progress:after { + content: attr(data-loading); +} + +/* The same goes for the .finished class */ + +.progress.finished:after { + content: attr(data-finished); +} + +/* The colorful bar that grows depending on the progress */ + +.progress .tz-bar { + background-color: #ffffff; + height: 3px; + bottom: 0; + left: 0; + width: 0; + position: absolute; + z-index: 1; + + border-radius: 0 0 2px 2px; + + -webkit-transition: width 0.5s, height 0.5s; + -moz-transition: width 0.5s, height 0.5s; + transition: width 0.5s, height 0.5s; +} + +/* The bar can be either horizontal, or vertical */ + +.progress .tz-bar.background-horizontal { + height: 100%; + border-radius: 2px; +} + +.progress .tz-bar.background-vertical { + height: 0; + top: 0; + width: 100%; + border-radius: 2px; +} + +/*---------------------------- + Color themes +-----------------------------*/ + +.progress.red { + background-color: #e6537d; + background-image: -webkit-linear-gradient(top, #e6537d, #df5179); + background-image: -moz-linear-gradient(top, #e6537d, #df5179); + background-image: linear-gradient(top, #e6537d, #df5179); +} + +.progress.red .tz-bar { + background-color: #6876b4; +} + +.progress.green { + background-color: #64c896; + background-image: -webkit-linear-gradient(top, #64c896, #5fbd8e); + background-image: -moz-linear-gradient(top, #64c896, #5fbd8e); + background-image: linear-gradient(top, #64c896, #5fbd8e); +} + +.progress.green .tz-bar { + background-color: #9e81d6; +} + +.key-h { + text-align: left; + padding:0 10px 10px 10px; +} diff --git a/solar/images/1.png b/solar/images/1.png new file mode 100644 index 0000000..af1fbed Binary files /dev/null and b/solar/images/1.png differ diff --git a/solar/images/2.png b/solar/images/2.png new file mode 100644 index 0000000..851b05a Binary files /dev/null and b/solar/images/2.png differ diff --git a/solar/images/3.png b/solar/images/3.png new file mode 100644 index 0000000..49e8205 Binary files /dev/null and b/solar/images/3.png differ diff --git a/solar/images/4.png b/solar/images/4.png new file mode 100644 index 0000000..4f930ba Binary files /dev/null and b/solar/images/4.png differ diff --git a/solar/images/5.png b/solar/images/5.png new file mode 100644 index 0000000..d1ed8c0 Binary files /dev/null and b/solar/images/5.png differ diff --git a/solar/images/6.png b/solar/images/6.png new file mode 100644 index 0000000..33d07de Binary files /dev/null and b/solar/images/6.png differ diff --git a/solar/index.html b/solar/index.html new file mode 100644 index 0000000..369be74 --- /dev/null +++ b/solar/index.html @@ -0,0 +1,70 @@ + + + + ai/solar + + + + + +
+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + diff --git a/solar/js/CelestialBody.js b/solar/js/CelestialBody.js new file mode 100644 index 0000000..8b2ed1a --- /dev/null +++ b/solar/js/CelestialBody.js @@ -0,0 +1,407 @@ +// Celestial body constructor +var CelestialBody = function (obj) { + // Meta + this.name = ""; + // If the planet is the sun + this.star = false; + // Object shape info + this.spherical = true; + this.oblateness = 0.; + this.radius = 1.; + this.isComet = false; + this.particleSystem = null; + // Parent/moon objects + this.parent = null; + this.children = []; + // TODO: Model info, to be implemented + // Orbit parameters + // 周期(恒星)、半长轴、离心率、倾角、升交点黄经、平近点角 (历时原点假设轨道是圆形时的黄经偏移) + + this.position = { + x: 0, y: 0, z: 0, + }; + + this.obj = { + path: null, objPath: null, mtlPath: null, + scale: 1., angle: 0., x: 0., y: 0., z: 0. + }; + + this.orbit = { + period: 1., semiMajorAxis: 1., eccentricity: 0., + inclination: 0., ascendingNode: 0., meanLongitude: 0. + }; + // Rotation parameters + // 周期(恒星)、倾角(黄赤夹角)、子午角(自转轴所在的与黄道垂直的平面,即子午面,与xOy平面的夹角)、历时原点角度偏移 + // 注:这里我们使用xOz平面作为黄道面 + this.rotation = { + period: 1., inclination: 1., + meridianAngle: 0., offset: 0. + }; + // 远景时显示光芒的参数设定 + // albedo 为反照率 + // 下面给出一个该把这个光点画多亮的粗略估计(只是用来看的,不是很严谨) + // x > R/k: (2 - /(|c|*|p|)) * R^2 * a * log(k*x0/R) / log(k*x/R) + // else: 0 + // 其中,a是反照率,记号<,>表示内积,|.|是二范数,c是摄像机坐标,p是天体坐标 + // R 是天体半径,x 是距天体的距离,即|c - p|,k 是一个系数 + this.albedo = 1.; + this.shineColor = 0xffffff; + // Material settings + this.material = { + // "phong", "lambert", "basic" + type: "phong", + diffuse: {map: null, color: 0xffffff}, + specular: {map: null, color: 0xffffff, shininess: 25}, + night: {map: null}, + bump: {map: null, height: 10} + }; + // Planet ring definitions + this.ring = { + map: null, + lower: 2000, higher: 6000, + color: 0xffffff, specularColor: 0xffffff, specularPower: 5 + }; + // halo effect + this.halo = { + color: null, + radius: 1. + }; + this.atmosphere = { + cloud: { + map: null, height: 1, speed: 20 + }, + // By wave length + scattering: false, + atmosphereColor: new THREE.Vector3(0.5, 0.7, 0.8), + sunsetColor: new THREE.Vector3(0.8, 0.7, 0.6), + atmosphereStrength: 1.0, + sunsetStrength: 1.0 + }; + + mergeRecursive(this, obj); +}; + +function mergeRecursive(obj1, obj2) { + for (var p in obj2) { + try { + //Property in destination object set; update its value. + if (obj2[p].constructor == Object) { + obj1[p] = mergeRecursive(obj1[p], obj2[p]); + } else { + obj1[p] = obj2[p]; + } + } catch (e) { + //Property in destination object not set; create it and set its value. + obj1[p] = obj2[p]; + } + } + return obj1; +} + +// lens flare texture +CelestialBody.prototype.flareTexture = textureLoader.load("res/effects/flare.jpg"); + +// IMPORTANT: This function of the prototype generate the object and put it on +// the scene. This is the most most important part in drawing the object. +CelestialBody.prototype.generateObjectsOnScene = function (argScene) { + var that = this; + // if(this.spherical) + if (!this.spherical) { + if (this.isComet) { + this.cometPivot = new THREE.Group(); + this.objectGroup = new THREE.Group(); + this.particleSystem = new THREE.GPUParticleSystem({ + maxParticles: 150000 + }); + this.objectGroup.add(this.particleSystem); + argScene.add(this.objectGroup); + } else { + this.objectGroup = new THREE.Group(); + var onProgress = function (xhr) { + if (xhr.lengthComputable) { + var percentComplete = xhr.loaded / xhr.total * 100; + } + }; + var onError = function (xhr) { + }; + if (that.obj.mtlPath != null) { + mtlLoader.setPath(that.obj.path); + mtlLoader.load(that.obj.mtlPath, function (materials) { + materials.preload(); + objLoader.setMaterials(materials); + objLoader.setPath(that.obj.path); + objLoader.load(that.obj.objPath, function (object) { + that.objectGroup.add(object); + var scale = that.obj.scale; + object.rotateY(that.obj.angle / 180.0 * Math.PI); + object.scale.set(scale, scale, scale); + object.translateX(that.obj.x); + object.translateY(that.obj.y); + object.translateZ(that.obj.z); + }, onProgress, onError); + }); + } else { + objLoader.setPath(that.obj.path); + objLoader.load(that.obj.objPath, function (object) { + object.traverse(function (child) { + var material = new THREE.MeshLambertMaterial(); + if (child instanceof THREE.Mesh) { + child.material = material; + } + }); + that.objectGroup.add(object); + object.rotateY(that.obj.angle / 180.0 * Math.PI); + var scale = that.obj.scale; + object.scale.set(scale, scale, scale); + object.translateX(that.obj.x); + object.translateY(that.obj.y); + object.translateZ(that.obj.z); + }, onProgress, onError); + } + argScene.add(this.objectGroup); + } + } else { + this.bodySphereGeometry = new THREE.SphereGeometry(this.radius, 64, 64); + // else if(!this.spherical) blablabla... + // The base body sphere material + var sphereMaterial = this.bodySphereMaterial = null; + switch (this.material.type) { + case "basic": + sphereMaterial = this.bodySphereMaterial + = new THREE.MeshBasicMaterial({ + color: new THREE.Color(this.material.diffuse.color) + }); + if (this.material.diffuse.map !== null) { + sphereMaterial.map = textureLoader.load(this.material.diffuse.map); + } + break; + case "lambert": + sphereMaterial = this.bodySphereMaterial + = new THREE.MeshPhongMaterial({ + color: new THREE.Color(this.material.diffuse.color), + specular: new THREE.Color(0x000000), + shininess: 0, + bumpScale: this.material.bump.height + }); + if (this.material.diffuse.map !== null) { + sphereMaterial.map = textureLoader.load(this.material.diffuse.map); + } + break; + case "phong": + default: + sphereMaterial = this.bodySphereMaterial + = new THREE.MeshPhongMaterial({ + color: new THREE.Color(this.material.diffuse.color), + specular: new THREE.Color(this.material.specular.color), + shininess: this.material.specular.shininess, + bumpScale: this.material.bump.height + }); + if (this.material.diffuse.map !== null) { + sphereMaterial.map = textureLoader.load(this.material.diffuse.map); + } + if (this.material.specular.map !== null) { + sphereMaterial.specularMap = textureLoader.load(this.material.specular.map); + } + if (this.material.bump.map !== null) { + sphereMaterial.bumpMap = textureLoader.load(this.material.bump.map); + } + break; + } + this.objectGroup = new THREE.Group(); + // Add the main body part + textureLoader.load(this.material.diffuse.map, function (texture) { + this.bodySphereMaterial = new THREE.MeshPhongMaterial({map: texture}); + }); + this.bodySphereMesh = new THREE.Mesh(this.bodySphereGeometry, this.bodySphereMaterial); + this.bodySphereMesh.scale.set(1, 1 - this.oblateness, 1); + + // Add lens flare + this.lensFlare = null; + if (this.star) { + this.lensFlare = + new THREE.LensFlare(this.flareTexture, 200, + 0, THREE.AdditiveBlending, new THREE.Color(this.shineColor)); + this.lensFlare.position.set(this.getX(), this.getY(), this.getZ()); + + var that = this; + this.lensFlare.customUpdateCallback = function () { + var cameraDistance = Math.sqrt( + (trackCamera[params.Camera].getX() - that.getX()) + * (trackCamera[params.Camera].getX() - that.getX()), + (trackCamera[params.Camera].getY() - that.getY()) + * (trackCamera[params.Camera].getY() - that.getY()), + (trackCamera[params.Camera].getZ() - that.getZ()) + * (trackCamera[params.Camera].getZ() - that.getZ())); + this.transparent = 0.3; + if (cameraDistance < 6000) { + that.bodySphereMaterial.depthTest = true; + that.haloMaterial.depthTest = true; + that.cloudMaterial.depthTest = true; + } + else { + that.bodySphereMaterial.depthTest = false; + that.haloMaterial.depthTest = false; + } + this.updateLensFlares(); + }; + } + + // Add night + this.nightMaterial = null; + this.nightSphereMesh = null; + if (this.material.night.map !== null) { + this.nightMaterial = new THREE.ShaderMaterial({ + uniforms: { + nightTexture: {value: textureLoader.load(this.material.night.map)} + }, + vertexShader: generalVS, + fragmentShader: nightFS, + transparent: true, + blending: THREE.CustomBlending, + blendEquation: THREE.AddEquation + }); + this.nightSphereMesh = new THREE.Mesh(this.bodySphereGeometry, this.nightMaterial); + this.objectGroup.add(this.nightSphereMesh); + } + + // Add clouds + this.cloudGeometry = null; + this.cloudMaterial = null; + this.cloudMesh = null; + if (this.atmosphere.cloud.map !== null) { + this.cloudGeometry = new THREE.SphereGeometry(this.radius + this.atmosphere.cloud.height, 64, 64); + if (!this.star) { + this.cloudMaterial = new THREE.MeshLambertMaterial({ + map: textureLoader.load(this.atmosphere.cloud.map), + transparent: true + }); + } else { + this.cloudMaterial = new THREE.MeshBasicMaterial({ + map: textureLoader.load(this.atmosphere.cloud.map), + transparent: true + }); + } + this.cloudMesh = new THREE.Mesh(this.cloudGeometry, this.cloudMaterial); + } + + // Add atmosphere + this.atmosphereGeometry = null; + this.atmosphereMaterial = null; + this.atmosphereMesh = null; + if (this.atmosphere.scattering) { + this.atmosphereGeometry = new THREE.SphereGeometry(this.radius * 1.015, 64, 64); + this.atmosphereMaterial = new THREE.ShaderMaterial({ + uniforms: { + atmosphereColor: {value: this.atmosphere.atmosphereColor}, + sunsetColor: {value: this.atmosphere.sunsetColor}, + atmosphereStrength: {value: this.atmosphere.atmosphereStrength}, + sunsetStrength: {value: this.atmosphere.sunsetStrength} + }, + vertexShader: atmosphereVS, + fragmentShader: atmosphereFS, + transparent: true, + blending: THREE.CustomBlending, + blendEquation: THREE.AddEquation + }); + this.atmosphereMesh = new THREE.Mesh(this.atmosphereGeometry, this.atmosphereMaterial); + this.objectGroup.add(this.atmosphereMesh); + } + + this.haloGeometry = null; + this.haloMaterial = null; + this.haloMesh = null; + if (this.halo.color != null) { + this.haloGeometry = new THREE.SphereGeometry(this.halo.radius, 64, 64); + this.haloMaterial = new THREE.ShaderMaterial({ + uniforms: { + color: {value: this.halo.color} + }, + vertexShader: haloVS, + fragmentShader: haloFS, + transparent: true, + blending: THREE.CustomBlending, + blendEquation: THREE.AddEquation + }); + this.haloMesh = new THREE.Mesh(this.haloGeometry, this.haloMaterial); + this.objectGroup.add(this.haloMesh); + } + + // Add rings + // Add clouds + this.ringGeometry = null; + this.ringMaterial = null; + this.ringMeshPositive = null; + this.ringMeshNegative = null; + this.ringTexture = null; + if (this.ring.map !== null) { + this.ringTexture = textureLoader.load(this.ring.map); + this.ringTexture.rotation = Math.PI / 2; + this.ringGeometry = new THREE.CylinderGeometry(this.radius + this.ring.lower, this.radius + this.ring.higher, 0, 100, 100, true); + this.ringMaterial = new THREE.MeshPhongMaterial({ + map: this.ringTexture, transparent: true, + emissive: new THREE.Color(0x222222) + }); + this.ringMeshPositive = new THREE.Mesh(this.ringGeometry, this.ringMaterial); + this.ringGeometry = new THREE.CylinderGeometry(this.radius + this.ring.higher, this.radius + this.ring.lower, 0, 100, 100, true); + this.ringMeshNegative = new THREE.Mesh(this.ringGeometry, this.ringMaterial); + // if(this.name === "Saturn") { + // this.ringMeshPositive.castShadow = true; + // this.ringMeshPositive.receiveShadow = true; + // this.ringMeshNegative.castShadow = true; + // this.ringMeshNegative.receiveShadow = true; + // this.bodySphereMesh.castShadow = true; + // this.bodySphereMesh.receiveShadow = true; + // } + } + + // Add meshes to the object group + if (this.lensFlare != null) this.objectGroup.add(this.lensFlare); + this.objectGroup.add(this.bodySphereMesh); + + if (this.ringMeshPositive !== null) { + this.objectGroup.add(this.ringMeshPositive); + this.objectGroup.add(this.ringMeshNegative); + } + if (this.cloudMesh !== null) { + this.objectGroup.add(this.cloudMesh); + } + // simple inclination + this.objectGroup.rotateZ(this.rotation.inclination / 180.0 * Math.PI); + argScene.add(this.objectGroup); + } +}; + + +CelestialBody.prototype.updateClouds = function (time) { + if (this.cloudGeometry !== null) { + this.cloudGeometry.rotateY(this.atmosphere.cloud.speed / 180.0 * Math.PI); + } +} + +CelestialBody.prototype.update = function (time) { + if (this.objectGroup !== undefined || this.isComet) { + this.updateOrbitAndRotation(time); + if (this.spherical && !this.isComet) + this.updateClouds(time); + } +}; + +CelestialBody.prototype.getX = function () { + if (this.objectGroup == null || this.objectGroup.position == null) return 0; + return this.objectGroup.position.getComponent(0); +}; + +CelestialBody.prototype.getY = function () { + if (this.objectGroup == null || this.objectGroup.position == null) return 0; + return this.objectGroup.position.getComponent(1); +}; + +CelestialBody.prototype.getZ = function () { + if (this.objectGroup == null || this.objectGroup.position == null) return 0; + return this.objectGroup.position.getComponent(2); +}; + +CelestialBody.prototype.getRadius = function () { + if (this.objectGroup == null || this.objectGroup.position == null) return 0; + return this.radius; +}; \ No newline at end of file diff --git a/solar/js/Detector.js b/solar/js/Detector.js new file mode 100644 index 0000000..17b7207 --- /dev/null +++ b/solar/js/Detector.js @@ -0,0 +1,79 @@ +/** + * @author alteredq / http://alteredqualia.com/ + * @author mr.doob / http://mrdoob.com/ + */ + +var Detector = { + + canvas: !!window.CanvasRenderingContext2D, + webgl: (function () { + + try { + + var canvas = document.createElement('canvas'); + return !!( window.WebGLRenderingContext && ( canvas.getContext('webgl') || canvas.getContext('experimental-webgl') ) ); + + } catch (e) { + + return false; + + } + + })(), + workers: !!window.Worker, + fileapi: window.File && window.FileReader && window.FileList && window.Blob, + + getWebGLErrorMessage: function () { + + var element = document.createElement('div'); + element.id = 'webgl-error-message'; + element.style.fontFamily = 'monospace'; + element.style.fontSize = '13px'; + element.style.fontWeight = 'normal'; + element.style.textAlign = 'center'; + element.style.background = '#fff'; + element.style.color = '#000'; + element.style.padding = '1.5em'; + element.style.width = '400px'; + element.style.margin = '5em auto 0'; + + if (!this.webgl) { + + element.innerHTML = window.WebGLRenderingContext ? [ + 'Your graphics card does not seem to support WebGL.
', + 'Find out how to get it here.' + ].join('\n') : [ + 'Your browser does not seem to support WebGL.
', + 'Find out how to get it here.' + ].join('\n'); + + } + + return element; + + }, + + addGetWebGLMessage: function (parameters) { + + var parent, id, element; + + parameters = parameters || {}; + + parent = parameters.parent !== undefined ? parameters.parent : document.body; + id = parameters.id !== undefined ? parameters.id : 'oldie'; + + element = Detector.getWebGLErrorMessage(); + element.id = id; + + parent.appendChild(element); + + } + +}; + +// browserify support +if (typeof module === 'object') { + + module.exports = Detector; + +} diff --git a/solar/js/animation.js b/solar/js/animation.js new file mode 100644 index 0000000..00c8189 --- /dev/null +++ b/solar/js/animation.js @@ -0,0 +1,36 @@ +function remain(objKey) { + if (celestialBodies[objKey].parent == null) + return true; + if ((calculateParams[celestialBodies[objKey].parent.name] && celestialBodies[objKey].parent.name != "Sun") || + calculateParams[objKey]) + return true; + return false; +} + +function render() { + for (var objKey in celestialBodies) { + if (firstflag || remain(objKey)) { + celestialBodies[objKey].update(globalTime.getRelative()); + if (orbitParams[objKey]) { + scene.add(orbitDraw[objKey]); + } else { + scene.remove(orbitDraw[objKey]); + } + } + } + if (firstflag) { + $(function () { + setTimeout(function () { + $("#prompt").fadeOut(500); + container.appendChild(stats.domElement); + container.appendChild(renderer.domElement); + gui.open(); + }, 2000); + }); + } + firstflag = false; + if (needSet) { + renderCamera.setCamera(); + } + renderer.render(scene, renderCamera.camera); +} \ No newline at end of file diff --git a/solar/js/cameraParameters.js b/solar/js/cameraParameters.js new file mode 100644 index 0000000..2a42612 --- /dev/null +++ b/solar/js/cameraParameters.js @@ -0,0 +1,46 @@ +var cameraParameters = function (distance, safeDistance, body) { + this.theta = 0.2; + this.phi = 0.3; + this.distance = distance; + this.safeDistance = safeDistance; + this.safeFar = 1e6; + this.body = body; + this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.4, 1e7); +}; + +cameraParameters.prototype.getDistance = function () { + return this.distance; +}; +cameraParameters.prototype.getCenterX = function () { + if (this.body == "Comet") + return celestialBodies["Comet"].cometPivot.position.getComponent(0); + else + return celestialBodies[this.body].getX(); +}; +cameraParameters.prototype.getCenterY = function () { + if (this.body == "Comet") + return celestialBodies["Comet"].cometPivot.position.getComponent(1); + else + return celestialBodies[this.body].getY(); +}; +cameraParameters.prototype.getCenterZ = function () { + if (this.body == "Comet") + return celestialBodies["Comet"].cometPivot.position.getComponent(2); + else + return celestialBodies[this.body].getZ(); +}; +cameraParameters.prototype.getX = function () { + return this.getCenterX() - (celestialBodies[this.body].getRadius() + this.distance) * Math.cos(this.theta) * Math.cos(this.phi); +}; +cameraParameters.prototype.getZ = function () { + return this.getCenterZ() - (celestialBodies[this.body].getRadius() + this.distance) * Math.sin(this.theta) * Math.cos(this.phi); +}; +cameraParameters.prototype.getY = function () { + return this.getCenterY() - (celestialBodies[this.body].getRadius() + this.distance) * Math.sin(this.phi); +}; +cameraParameters.prototype.setCamera = function () { + this.camera.position.x = this.getX(); + this.camera.position.y = this.getY(); + this.camera.position.z = this.getZ(); + this.camera.lookAt(this.getCenterX(), this.getCenterY(), this.getCenterZ()); +}; \ No newline at end of file diff --git a/solar/js/control.js b/solar/js/control.js new file mode 100644 index 0000000..45adfcd --- /dev/null +++ b/solar/js/control.js @@ -0,0 +1,181 @@ +var windowHalfX = window.innerWidth / 2; +var windowHalfY = window.innerHeight / 2; + +var mouseStatus = { + x: 0, y: 0, + leftDown: false, centerDown: false, rightDown: false +}; + +function onWindowMouseMove(event) { + // Keep the value in 0 -- 2 PI + var body = params.Camera; + if (mouseStatus.leftDown) { + trackCamera[body].theta = trackCamera[body].theta % (2 * Math.PI); + trackCamera[body].phi = trackCamera[body].phi % (0.5 * Math.PI); + + trackCamera[body].theta += (event.clientX - windowHalfX - mouseStatus.x) * 0.01; + + if (trackCamera[body].phi - (event.clientY - windowHalfY - mouseStatus.y) * 0.01 >= -0.5 * Math.PI && + trackCamera[body].phi - (event.clientY - windowHalfY - mouseStatus.y) * 0.01 <= 0.5 * Math.PI) + trackCamera[body].phi -= (event.clientY - windowHalfY - mouseStatus.y) * 0.01; + } + mouseStatus.x = event.clientX - windowHalfX; + mouseStatus.y = event.clientY - windowHalfY; +} + +function onWindowMouseDown(event) { + switch (event.which) { + case 1: + mouseStatus.leftDown = true; + break; + case 2: + mouseStatus.centerDown = true; + break; + case 3: + default: + mouseStatus.rightDown = true; + break; + } +} + +function onWindowMouseUp(event) { + switch (event.which) { + case 1: + mouseStatus.leftDown = false; + break; + case 2: + mouseStatus.centerDown = false; + break; + case 3: + default: + mouseStatus.rightDown = false; + break; + } +} + +function onMouseWheelChange(event) { + var body = params.Camera; + var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail))); + var newDistance = trackCamera[body].distance - 0.05 * trackCamera[body].distance * delta; + + if (newDistance <= trackCamera[body].safeDistance) { + newDistance = trackCamera[body].safeDistance; + } else if (newDistance >= trackCamera[body].safeFar) { + newDistance = trackCamera[body].safeFar; + } + trackCamera[body].distance = newDistance; +} + +var posSrc = { pos: 0.0 }; +var oX, oY, oZ, dX, dY, dZ, oTheta, dTheta, oPhi, dPhi, oDistance, dDistance, oSafeDis, dSafeDis; +var oCX, oCY, oCZ, dCX, dCY, dCZ; +tween = new TWEEN.Tween(posSrc) + .to({ pos: 1.0 }, 4000) + .easing(TWEEN.Easing.Quartic.InOut) + .onStart(function () { + globalTimeFlag = false; + }) + .onUpdate(function () { + var pos = posSrc.pos; + switchCamera.camera.position.set(oX + dX * pos, oY + dY * pos, oZ + dZ * pos); + switchCamera.theta = oTheta + dTheta * pos; + switchCamera.phi = oPhi + dPhi * pos; + switchCamera.distance = oDistance + dDistance * pos; + switchCamera.safeDistance = oSafeDis + dSafeDis * pos; + switchCamera.camera.lookAt(oCX + dCX * pos, oCY + dCY * pos, oCZ + dCZ * pos); + }) + .onComplete(function () { + // Need switching to roaming mode + if (goRoaming) { + calculateParams[curBody] = saveCur; + calculateParams["Earth"] = saveNext; + renderCamera = roamingCamera; + cameraControl = new THREE.FirstPersonControls(roamingCamera.camera); + cameraControl.lookSpeed = 0.1; + cameraControl.movementSpeed = 150; + cameraControl.noFly = true; + cameraControl.constrainVertical = true; + cameraControl.verticalMin = 1.0; + cameraControl.verticalMax = 2.0; + cameraControl.lon = -150; + cameraControl.lat = 120; + needSet = false; + roamingStatus = true; + goRoaming = false; + roamingCamera.camera.lookAt(0, 0, 0); + } else { + calculateParams[curBody] = saveCur; + calculateParams[nextBody] = saveNext; + switchCamera.body = nextBody; + curBody = nextBody; + needSet = true; + renderCamera = trackCamera[nextBody]; + } + globalTimeFlag = true; + }); + +function initTween() { + saveCur = calculateParams[curBody]; + saveNext = calculateParams[nextBody]; + calculateParams[curBody] = false; + calculateParams[nextBody] = false; + renderCamera = switchCamera; + posSrc.pos = 0.0; + needSet = false; +} + +function setTween(cur, next) { + if (cur == null) { + oX = arguments[2]; + oY = arguments[3]; + oZ = arguments[4]; + oTheta = 0.2; + oPhi = 0.3; + oDistance = 30; + oSafeDis = 30; + oCX = roamingCamera.camera.position.x; + oCY = roamingCamera.camera.position.y; + oCZ = roamingCamera.camera.position.z; + } else { + oX = trackCamera[cur].getX(); + oY = trackCamera[cur].getY(); + oZ = trackCamera[cur].getZ(); + oTheta = trackCamera[cur].theta; + oPhi = trackCamera[cur].phi; + oDistance = trackCamera[cur].distance; + oSafeDis = trackCamera[cur].safeDistance; + oCX = trackCamera[cur].getCenterX(); + oCY = trackCamera[cur].getCenterY(); + oCZ = trackCamera[cur].getCenterZ(); + } + if (next == null) { + dCX = dX = arguments[2] - oX; + dCY = dY = arguments[3] - oY; + dCZ = dZ = arguments[4] - oZ; + dTheta = 0.2 - oTheta; + dPhi = 0.3 - oPhi; + dDistance = 30 - oDistance; + dSafeDis = 30 - oSafeDis; + } else { + dX = trackCamera[next].getX() - oX; + dY = trackCamera[next].getY() - oY; + dZ = trackCamera[next].getZ() - oZ; + dCX = trackCamera[next].getCenterX() - oCX; + dCY = trackCamera[next].getCenterY() - oCY; + dCZ = trackCamera[next].getCenterZ() - oCZ; + dTheta = trackCamera[next].theta - oTheta; + dPhi = trackCamera[next].phi - oPhi; + dDistance = trackCamera[next].distance - oDistance; + dSafeDis = trackCamera[next].safeDistance - oSafeDis; + } +} + +function cameraCopy(cameraDst, cameraSrc) { + cameraDst.theta = cameraSrc.theta; + cameraDst.phi = cameraSrc.phi; + cameraDst.distance = cameraSrc.distance; + cameraDst.safeDistance = cameraSrc.safeDistance; + cameraDst.body = cameraSrc.body; + cameraDst.setCamera(); +} + diff --git a/solar/js/data.js b/solar/js/data.js new file mode 100644 index 0000000..b0a4bc9 --- /dev/null +++ b/solar/js/data.js @@ -0,0 +1,547 @@ +celestialBodies = { + Sun: new CelestialBody({ + name: "Sun", + star: true, + parent: "Sun", + radius: 200., + shineColor: 0xfff700, + orbit: { + semiMajorAxis: 0. + }, + rotation: { + period: 2500, + inclination: 0, + }, + material: { + type: "basic", + diffuse: {map: "res/sol/diffuse.png"} + }, + atmosphere: { + cloud: { + map: "res/sol/overlay.png", + height: 1, + speed: 1 + } + }, + halo: { + color: new THREE.Color(0xfff700), + radius: 500. + } + }), + Mercury: new CelestialBody({ + name: "Mercury", + radius: 3.8256, + parent: "Sun", + shineColor: 0x9999ff, + orbit: { + period: 1.204, + semiMajorAxis: 387.1, + eccentricity: 0.2056, + inclination: 7.0049 + }, + rotation: { + period: 1407.509405, + inclination: 28.55, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/mercury/diffuse.jpg"}, + bump: {map: "res/mercury/bump.jpg", height: 0.} + } + }), + Venus: new CelestialBody({ + name: "Venus", + radius: 9.488, + parent: "Sun", + shineColor: 0x9999ff, + orbit: { + period: 3.076, + semiMajorAxis: 723.3, + eccentricity: 0.0068, + inclination: 3.3947 + }, + rotation: { + period: 5832.443616, + inclination: 157.16, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/venus/diffuse.jpg"}, + bump: {map: "res/venus/bump.jpg", height: 0.} + }, + atmosphere: { + cloud: { + map: "res/venus/clouds.jpg", + height: 0.5, + speed: 0.02 + } + } + }), + Earth: new CelestialBody({ + name: "Earth", + radius: 10., + parent: "Sun", + shineColor: 0x6666ff, + orbit: { + period: 5., + semiMajorAxis: 1000., + eccentricity: 0.0167, + inclination: 0.0001 + }, + rotation: { + period: 23.93447117, + inclination: -23.4392911, + meridianAngle: 280.147, + offset: 0. + }, + material: { + type: "phong", + diffuse: {map: "res/earth/diffuse.jpg"}, + specular: {map: "res/earth/spec.jpg", color: 0x243232, shininess: 25}, + bump: {map: "res/earth/bump.jpg", height: 0.05}, + night: {map: "res/earth/night.png"} + }, + atmosphere: { + cloud: { + map: "res/earth/clouds.png", + height: 0.1, + speed: 0.02 + }, + scattering: true, + atmosphereColor: new THREE.Vector3(0.5, 0.7, 0.8), + sunsetColor: new THREE.Vector3(0.8, 0.7, 0.6), + atmosphereStrength: 1.5, + sunsetStrength: 1.0 + } + }), + Comet: new CelestialBody({ + name: "Comet", + parent: "Sun", + radius: 0, + spherical: false, + isComet: true, + orbit: { + period: 3.5, + semiMajorAxis: 3000., + eccentricity: 0.5, + inclination: 10., + }, + }), + Ship: new CelestialBody({ + name: "Ship", + parent: "Earth", + radius: 0.2, + spherical: false, + obj: { + path: "res/space/", + objPath: "tiangong.obj", + mtlPath: "tiangong.mtl", + angle: -30, + scale: 0.008, + }, + orbit: { + period: 1.0, + semiMajorAxis: 15., + inclination: 30, + }, + rotation: { + period: 100.0, + inclination: 0, + }, + }), + Astronaut: new CelestialBody({ + name: "Astronaut", + parent: "Earth", + radius: 0.05, + spherical: false, + obj: { + path: "res/space/", + objPath: "man.obj", + mtlPath: null, + scale: 0.008, + angle: 235, + x: 0.04, + y: 0.02, + z: 0.01, + }, + orbit: { + period: 1.0, + semiMajorAxis: 15., + inclination: 30, + }, + rotation: { + period: 100.0, + inclination: 0, + }, + }), + Moon: new CelestialBody({ + name: "Moon", + radius: 2.7243, + parent: "Earth", + shineColor: 0xff9988, + orbit: { + period: 2.0749, + semiMajorAxis: 25., + eccentricity: 0.0549, + inclination: 5.15 + }, + rotation: { + period: 655.2, + inclination: 23.4608, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/moon/diffuse.jpg"}, + bump: {map: "res/moon/bump.jpg", height: 0.1} + } + }), + Mars: new CelestialBody({ + name: "Mars", + radius: 5.3226, + parent: "Sun", + shineColor: 0xff9988, + orbit: { + period: 9.4095, + semiMajorAxis: 1523.7, + eccentricity: 0.0934, + inclination: 1.8506 + }, + rotation: { + period: 24.622962156, + inclination: 37.11350, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/mars/diffuse.jpg"}, + bump: {map: "res/mars/bump.jpg", height: 1.} + }, + atmosphere: { + scattering: true, + atmosphereColor: new THREE.Vector3(0.9, 0.8, 0.6), + sunsetColor: new THREE.Vector3(0.4, 0.5, 0.7), + atmosphereStrength: 1.0, + sunsetStrength: 0.9 + } + }), + Phobos: new CelestialBody({ + name: "Phobos", + radius: 1, + parent: "Mars", + shineColor: 0xff9988, + orbit: { + period: 1.5945, + semiMajorAxis: 20, + eccentricity: 0.0151, + inclination: 1.082 + }, + rotation: { + period: 100., + inclination: 37.10, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/phobos/diffuse.jpg"}, + bump: {map: "res/phobos/bump.jpg", height: 10.} + } + }), + Deimos: new CelestialBody({ + name: "Deimos", + radius: 0.5, + parent: "Mars", + shineColor: 0xff9988, + orbit: { + period: 6.3122, + semiMajorAxis: 30, + eccentricity: 0.00033, + inclination: 1.791 + }, + rotation: { + period: 150., + inclination: 36.48, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/deimos/diffuse.jpg"}, + bump: {map: "res/deimos/bump.jpg", height: 10.} + } + }), + Jupiter: new CelestialBody({ + name: "Jupiter", + radius: 112.09, + parent: "Sun", + shineColor: 0x9999ff, + orbit: { + period: 59.3, + semiMajorAxis: 2000., + eccentricity: 0.0484, + inclination: 1.3053 + }, + rotation: { + period: 238.23, + inclination: 2.22, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/jupiter/diffuse.jpg"}, + }, + atmosphere: { + cloud: { + map: "res/jupiter/clouds.png", + height: 0.3, + speed: 0.02 + }, + scattering: true, + atmosphereColor: new THREE.Vector3(1.0, 0.8, 0.7), + sunsetColor: new THREE.Vector3(0.7, 0.7, 0.8), + atmosphereStrength: 1.8, + sunsetStrength: 0.6 + }, + }), + Callisto: new CelestialBody({ + name: "Callisto", + radius: 4.0, + parent: "Jupiter", + shineColor: 0xff9988, + orbit: { + period: 2.49, + semiMajorAxis: 200., + eccentricity: 0.0045045, + inclination: 0.384285, + }, + rotation: { + period: 100., + inclination: 25.51, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/callisto/diffuse.jpg"}, + } + }), + Europa: new CelestialBody({ + name: "Europa", + radius: 3.0, + parent: "Jupiter", + shineColor: 0xff9988, + orbit: { + period: 17.76, + semiMajorAxis: 160., + eccentricity: 0.0101, + inclination: 0.470, + }, + rotation: { + period: 150., + inclination: 25.49, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/europa/diffuse.jpg"}, + } + }), + Io: new CelestialBody({ + name: "Io", + radius: 3.0, + parent: "Jupiter", + shineColor: 0xff9988, + orbit: { + period: 8.85, + semiMajorAxis: 100., + eccentricity: 0.0041, + inclination: 0.040, + }, + rotation: { + period: 100., + inclination: 25.50, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/io/diffuse.png"}, + } + }), + Saturn: new CelestialBody({ + name: "Saturn", + radius: 94.49, + parent: "Sun", + shineColor: 0x9999ff, + orbit: { + period: 40.0, + semiMajorAxis: 2500., + eccentricity: 0.0542, + inclination: 2.4845 + }, + rotation: { + period: 255.75, + inclination: 28.052, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/saturn/diffuse.png"}, + bump: {map: "res/saturn/bump.png"}, + }, + atmosphere: { + cloud: { + map: "res/saturn/clouds.png", + height: 0.5, + speed: 0.05 + }, + scattering: true, + atmosphereColor: new THREE.Vector3(0.8, 0.7, 0.5), + sunsetColor: new THREE.Vector3(0.7, 0.7, 0.8), + atmosphereStrength: 1.5, + sunsetStrength: 0.8 + }, + ring: { + map: "res/saturn/ring.png", + lower: 5, + higher: 80, + } + }), + Dione: new CelestialBody({ + name: "Dione", + radius: 5.0, + parent: "Saturn", + shineColor: 0xff9988, + orbit: { + period: 3.0, + semiMajorAxis: 200., + eccentricity: 0.05, + inclination: 0.0049, + }, + rotation: { + period: 130., + inclination: 22.9, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/dione/diffuse.jpg"}, + } + }), + Titan: new CelestialBody({ + name: "Titan", + radius: 6.0, + parent: "Saturn", + shineColor: 0xff9988, + orbit: { + period: 4.0, + semiMajorAxis: 150., + eccentricity: 0.05, + inclination: 0.0049, + }, + rotation: { + period: 120., + inclination: 1.53, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/titan/diffuse.jpg"}, + } + }), + Uranus: new CelestialBody({ + name: "Uranus", + radius: 40.07, + parent: "Sun", + shineColor: 0x9999ff, + orbit: { + period: 420.069, + semiMajorAxis: 3000., + eccentricity: 0.0472, + inclination: 0.7699 + }, + rotation: { + period: 413.76, + inclination: 97.722, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/uranus/diffuse.jpg"}, + }, + ring: { + map: "res/uranus/ring.png", + lower: 10, + higher: 20, + }, + atmosphere: { + scattering: true, + atmosphereColor: new THREE.Vector3(0.5, 0.9, 0.7), + sunsetColor: new THREE.Vector3(0.7, 0.9, 0.8), + atmosphereStrength: 0.2, + sunsetStrength: 0.7 + }, + }), + Neptune: new CelestialBody({ + name: "Neptune", + radius: 38.83, + parent: "Sun", + shineColor: 0x9999ff, + orbit: { + period: 823.965, + semiMajorAxis: 3500., + eccentricity: 0.0097, + inclination: 1.7692 + }, + rotation: { + period: 386.64, + inclination: 28.03, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/neptune/diffuse.jpg"}, + }, + ring: { + map: "res/neptune/ring.png", + lower: 10, + higher: 20, + } + }), + Pluto: new CelestialBody({ + name: "Pluto", + radius: 15., + parent: "Sun", + shineColor: 0x9999ff, + orbit: { + period: 32.0, + semiMajorAxis: 4000., + eccentricity: 0.2482, + inclination: 17.1449 + }, + rotation: { + period: 153.292944, + inclination: 115.60, + meridianAngle: 0., + offset: 0. + }, + material: { + type: "lambert", + diffuse: {map: "res/pluto/diffuse.jpg"}, + }, + }), +} diff --git a/solar/js/index.js b/solar/js/index.js new file mode 100644 index 0000000..622a4ba --- /dev/null +++ b/solar/js/index.js @@ -0,0 +1,258 @@ +(function ($) { + + // Creating a number of jQuery plugins that you can use to + // initialize and control the progress meters. + + $.fn.progressInitialize = function () { + + // This function creates the necessary markup for the progress meter + // and sets up a few event listeners. + + + // Loop through all the buttons: + + return this.each(function () { + + var button = $(this), + progress = 0; + + // Extract the data attributes into the options object. + // If they are missing, they will receive default values. + + var options = $.extend({ + type: 'background-horizontal', + loading: 'Loading', + finished: 'Done' + }, button.data()); + + // Add the data attributes if they are missing from the element. + // They are used by our CSS code to show the messages + button.attr({'data-loading': options.loading, 'data-finished': options.finished}); + + // Add the needed markup for the progress bar to the button + var bar = $('').appendTo(button); + + + // The progress event tells the button to update the progress bar + button.on('progress', function (e, val, absolute, finish) { + + if (!button.hasClass('in-progress')) { + + // This is the first progress event for the button (or the + // first after it has finished in a previous run). Re-initialize + // the progress and remove some classes that may be left. + + bar.show(); + progress = 0; + button.removeClass('finished').addClass('in-progress') + } + + // val, absolute and finish are event data passed by the progressIncrement + // and progressSet methods that you can see near the end of this file. + + if (absolute) { + progress = val; + } + else { + progress += val; + } + + if (progress >= 100) { + progress = 100; + } + + // if(finish){ + // + // button.removeClass('in-progress').addClass('finished'); + // + // bar.delay(500).fadeOut(function(){ + // + // // Trigger the custom progress-finish event + // button.trigger('progress-finish'); + // setProgress(0); + // }); + // + // } + + setProgress(progress); + }); + + function setProgress(percentage) { + bar.filter('.background-horizontal,.background-bar').width(percentage + '%'); + bar.filter('.background-vertical').height(percentage + '%'); + } + + }); + + }; + + // progressStart simulates activity on the progress meter. Call it first, + // if the progress is going to take a long time to finish. + + $.fn.progressStart = function () { + + var button = this.first(), + last_progress = new Date().getTime(); + + if (button.hasClass('in-progress')) { + // Don't start it a second time! + return this; + } + + button.on('progress', function () { + last_progress = new Date().getTime(); + }); + + // Every half a second check whether the progress + // has been incremented in the last two seconds + + var interval = window.setInterval(function () { + + if (new Date().getTime() > 2000 + last_progress) { + + // There has been no activity for two seconds. Increment the progress + // bar a little bit to show that something is happening + + button.progressIncrement(5); + } + + }, 500); + + button.on('progress-finish', function () { + window.clearInterval(interval); + }); + + return button.progressIncrement(10); + }; + + $.fn.progressFinish = function () { + return this.first().progressSet(100); + }; + + $.fn.progressIncrement = function (val) { + + val = val || 10; + + var button = this.first(); + + button.trigger('progress', [val]) + + return this; + }; + + $.fn.progressSet = function (val) { + val = val || 10; + + var finish = false; + if (val >= 100) { + finish = true; + } + + return this.first().trigger('progress', [val, true, finish]); + }; + + // This function creates a progress meter that + // finishes in a specified amount of time. + + $.fn.progressTimed = function (seconds, cb) { + + var button = this.first(), + bar = button.find('.tz-bar'); + + if (button.is('.in-progress')) { + return this; + } + + // Set a transition declaration for the duration of the meter. + // CSS will do the job of animating the progress bar for us. + + bar.css('transition', seconds + 's linear'); + button.progressSet(99); + + window.setTimeout(function () { + bar.css('transition', ''); + button.progressFinish(); + + if ($.isFunction(cb)) { + cb(); + } + + }, seconds * 1000); + }; + + function PreLoad(imgs, options) { + this.imgs = (typeof imgs === 'string') ? [imgs] : imgs; + this.opts = $.extend({}, PreLoad.DEFAULTS, options); + + if (this.opts.order === 'ordered') { + this._ordered(); + } else { + this._unordered(); + } + } + + PreLoad.DEFAULTS = { + order: 'unordered', //无序预加载 + each: null, //每张图片加载完毕后执行 + all: null // 所有图片加载完毕后执行 + }; + PreLoad.prototype._ordered = function () { + var imgs = this.imgs, + opts = this.opts, + count = 0, + len = imgs.length; + + function load() { + var imgObj = new Image(); + + $(imgObj).on('load error', function () { + opts.each && opts.each(count); + if (count >= len) { + //所有图片全部加载完成 + opts.all && opts.all(); + } else { + load(); + } + + count++; + }); + + imgObj.src = imgs[count]; + } + + load(); + }; + PreLoad.prototype._unordered = function () {//无序加载 + + var imgs = this.imgs, + opts = this.opts, + count = 0, + len = imgs.length; + + $.each(imgs, function (i, src) { + if (typeof src != 'string') return; + + var imgObj = new Image(); + + $(imgObj).on('load error', function () { + + opts.each && opts.each(count); + + if (count >= len - 1) { + opts.all && opts.all(); + } + count++; + }); + + imgObj.src = src; + }); + }; + + + $.extend({ + preLoad: function (imgs, opts) { + new PreLoad(imgs, opts); + } + }); + +})(jQuery); diff --git a/solar/js/libs/FirstPersonControls.js b/solar/js/libs/FirstPersonControls.js new file mode 100644 index 0000000..51e0c39 --- /dev/null +++ b/solar/js/libs/FirstPersonControls.js @@ -0,0 +1,300 @@ +/** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * @author paulirish / http://paulirish.com/ + */ + +THREE.FirstPersonControls = function ( object, domElement ) { + + this.object = object; + this.target = new THREE.Vector3( 0, 0, 0 ); + + this.domElement = ( domElement !== undefined ) ? domElement : document; + + this.enabled = true; + + this.movementSpeed = 1.0; + this.lookSpeed = 0.005; + + this.lookVertical = true; + this.autoForward = false; + + this.activeLook = true; + + this.heightSpeed = false; + this.heightCoef = 1.0; + this.heightMin = 0.0; + this.heightMax = 1.0; + + this.constrainVertical = false; + this.verticalMin = 0; + this.verticalMax = Math.PI; + + this.autoSpeedFactor = 0.0; + + this.mouseX = 0; + this.mouseY = 0; + + this.lat = 0; + this.lon = 0; + this.phi = 0; + this.theta = 0; + + this.moveForward = false; + this.moveBackward = false; + this.moveLeft = false; + this.moveRight = false; + + this.mouseDragOn = false; + + this.viewHalfX = 0; + this.viewHalfY = 0; + + if ( this.domElement !== document ) { + + this.domElement.setAttribute( 'tabindex', - 1 ); + + } + + // + + this.handleResize = function () { + + if ( this.domElement === document ) { + + this.viewHalfX = window.innerWidth / 2; + this.viewHalfY = window.innerHeight / 2; + + } else { + + this.viewHalfX = this.domElement.offsetWidth / 2; + this.viewHalfY = this.domElement.offsetHeight / 2; + + } + + }; + + this.onMouseDown = function ( event ) { + + if ( this.domElement !== document ) { + + this.domElement.focus(); + + } + + event.preventDefault(); + event.stopPropagation(); + + if ( this.activeLook ) { + + switch ( event.button ) { + + case 0: this.moveForward = true; break; + case 2: this.moveBackward = true; break; + + } + + } + + this.mouseDragOn = true; + + }; + + this.onMouseUp = function ( event ) { + + event.preventDefault(); + event.stopPropagation(); + + if ( this.activeLook ) { + + switch ( event.button ) { + + case 0: this.moveForward = false; break; + case 2: this.moveBackward = false; break; + + } + + } + + this.mouseDragOn = false; + + }; + + this.onMouseMove = function ( event ) { + + if ( this.domElement === document ) { + + this.mouseX = event.pageX - this.viewHalfX; + this.mouseY = event.pageY - this.viewHalfY; + + } else { + + this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX; + this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY; + + } + + }; + + this.onKeyDown = function ( event ) { + + //event.preventDefault(); + + switch ( event.keyCode ) { + + case 38: /*up*/ + case 87: /*W*/ this.moveForward = true; break; + + case 37: /*left*/ + case 65: /*A*/ this.moveLeft = true; break; + + case 40: /*down*/ + case 83: /*S*/ this.moveBackward = true; break; + + case 39: /*right*/ + case 68: /*D*/ this.moveRight = true; break; + + case 82: /*R*/ this.moveUp = true; break; + case 70: /*F*/ this.moveDown = true; break; + + } + + }; + + this.onKeyUp = function ( event ) { + + switch ( event.keyCode ) { + + case 38: /*up*/ + case 87: /*W*/ this.moveForward = false; break; + + case 37: /*left*/ + case 65: /*A*/ this.moveLeft = false; break; + + case 40: /*down*/ + case 83: /*S*/ this.moveBackward = false; break; + + case 39: /*right*/ + case 68: /*D*/ this.moveRight = false; break; + + case 82: /*R*/ this.moveUp = false; break; + case 70: /*F*/ this.moveDown = false; break; + + } + + }; + + this.update = function( delta ) { + + if ( this.enabled === false ) return; + + if ( this.heightSpeed ) { + + var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax ); + var heightDelta = y - this.heightMin; + + this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef ); + + } else { + + this.autoSpeedFactor = 0.0; + + } + + var actualMoveSpeed = delta * this.movementSpeed; + + if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) ); + if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed ); + + if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed ); + if ( this.moveRight ) this.object.translateX( actualMoveSpeed ); + + if ( this.moveUp ) this.object.translateY( actualMoveSpeed ); + if ( this.moveDown ) this.object.translateY( - actualMoveSpeed ); + + var actualLookSpeed = delta * this.lookSpeed; + + if ( ! this.activeLook ) { + + actualLookSpeed = 0; + + } + + var verticalLookRatio = 1; + + if ( this.constrainVertical ) { + + verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin ); + + } + + this.lon += this.mouseX * actualLookSpeed; + if ( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio; + + this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); + this.phi = THREE.Math.degToRad( 90 - this.lat ); + + this.theta = THREE.Math.degToRad( this.lon ); + + if ( this.constrainVertical ) { + + this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax ); + + } + + var targetPosition = this.target, + position = this.object.position; + + targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); + targetPosition.y = position.y + 100 * Math.cos( this.phi ); + targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); + + this.object.lookAt( targetPosition ); + + }; + + function contextmenu( event ) { + + event.preventDefault(); + + } + + this.dispose = function() { + + this.domElement.removeEventListener( 'contextmenu', contextmenu, false ); + this.domElement.removeEventListener( 'mousedown', _onMouseDown, false ); + this.domElement.removeEventListener( 'mousemove', _onMouseMove, false ); + this.domElement.removeEventListener( 'mouseup', _onMouseUp, false ); + + window.removeEventListener( 'keydown', _onKeyDown, false ); + window.removeEventListener( 'keyup', _onKeyUp, false ); + + }; + + var _onMouseMove = bind( this, this.onMouseMove ); + var _onMouseDown = bind( this, this.onMouseDown ); + var _onMouseUp = bind( this, this.onMouseUp ); + var _onKeyDown = bind( this, this.onKeyDown ); + var _onKeyUp = bind( this, this.onKeyUp ); + + this.domElement.addEventListener( 'contextmenu', contextmenu, false ); + this.domElement.addEventListener( 'mousemove', _onMouseMove, false ); + this.domElement.addEventListener( 'mousedown', _onMouseDown, false ); + this.domElement.addEventListener( 'mouseup', _onMouseUp, false ); + + window.addEventListener( 'keydown', _onKeyDown, false ); + window.addEventListener( 'keyup', _onKeyUp, false ); + + function bind( scope, fn ) { + + return function () { + + fn.apply( scope, arguments ); + + }; + + } + + this.handleResize(); + +}; diff --git a/solar/js/libs/GPUParticleSystem.js b/solar/js/libs/GPUParticleSystem.js new file mode 100644 index 0000000..8147596 --- /dev/null +++ b/solar/js/libs/GPUParticleSystem.js @@ -0,0 +1,501 @@ +/* + * GPU Particle System + * @author flimshaw - Charlie Hoey - http://charliehoey.com + * + * A simple to use, general purpose GPU system. Particles are spawn-and-forget with + * several options available, and do not require monitoring or cleanup after spawning. + * Because the paths of all particles are completely deterministic once spawned, the scale + * and direction of time is also variable. + * + * Currently uses a static wrapping perlin noise texture for turbulence, and a small png texture for + * particles, but adding support for a particle texture atlas or changing to a different type of turbulence + * would be a fairly light day's work. + * + * Shader and javascript packing code derrived from several Stack Overflow examples. + * + */ + +THREE.GPUParticleSystem = function( options ) { + + THREE.Object3D.apply( this, arguments ); + + options = options || {}; + + // parse options and use defaults + + this.PARTICLE_COUNT = options.maxParticles || 1000000; + this.PARTICLE_CONTAINERS = options.containerCount || 1; + + this.PARTICLE_NOISE_TEXTURE = options.particleNoiseTex || null; + this.PARTICLE_SPRITE_TEXTURE = options.particleSpriteTex || null; + + this.PARTICLES_PER_CONTAINER = Math.ceil( this.PARTICLE_COUNT / this.PARTICLE_CONTAINERS ); + this.PARTICLE_CURSOR = 0; + this.time = 0; + this.particleContainers = []; + this.rand = []; + + // custom vertex and fragement shader + + var GPUParticleShader = { + + vertexShader: [ + + 'uniform float uTime;', + 'uniform float uScale;', + 'uniform sampler2D tNoise;', + + 'attribute vec3 positionStart;', + 'attribute float startTime;', + 'attribute vec3 velocity;', + 'attribute float turbulence;', + 'attribute vec3 color;', + 'attribute float size;', + 'attribute float lifeTime;', + + 'varying vec4 vColor;', + 'varying float lifeLeft;', + + 'void main() {', + + // unpack things from our attributes' + + ' vColor = vec4( color, 1.0 );', + + // convert our velocity back into a value we can use' + + ' vec3 newPosition;', + ' vec3 v;', + + ' float timeElapsed = uTime - startTime;', + + ' lifeLeft = 1.0 - ( timeElapsed / lifeTime );', + + ' gl_PointSize = ( uScale * size ) * lifeLeft;', + + ' v.x = ( velocity.x - 0.5 ) * 3.0;', + ' v.y = ( velocity.y - 0.5 ) * 3.0;', + ' v.z = ( velocity.z - 0.5 ) * 3.0;', + + ' newPosition = positionStart + ( v * 10.0 ) * timeElapsed;', + + ' vec3 noise = texture2D( tNoise, vec2( newPosition.x * 0.015 + ( uTime * 0.05 ), newPosition.y * 0.02 + ( uTime * 0.015 ) ) ).rgb;', + ' vec3 noiseVel = ( noise.rgb - 0.5 ) * 30.0;', + + ' newPosition = mix( newPosition, newPosition + vec3( noiseVel * ( turbulence * 5.0 ) ), ( timeElapsed / lifeTime ) );', + + ' if( v.y > 0. && v.y < .05 ) {', + + ' lifeLeft = 0.0;', + + ' }', + + ' if( v.x < - 1.45 ) {', + + ' lifeLeft = 0.0;', + + ' }', + + ' if( timeElapsed > 0.0 ) {', + + ' gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );', + + ' } else {', + + ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + ' lifeLeft = 0.0;', + ' gl_PointSize = 0.;', + + ' }', + + '}' + + ].join( '\n' ), + + fragmentShader: [ + + 'float scaleLinear( float value, vec2 valueDomain ) {', + + ' return ( value - valueDomain.x ) / ( valueDomain.y - valueDomain.x );', + + '}', + + 'float scaleLinear( float value, vec2 valueDomain, vec2 valueRange ) {', + + ' return mix( valueRange.x, valueRange.y, scaleLinear( value, valueDomain ) );', + + '}', + + 'varying vec4 vColor;', + 'varying float lifeLeft;', + + 'uniform sampler2D tSprite;', + + 'void main() {', + + ' float alpha = 0.;', + + ' if( lifeLeft > 0.995 ) {', + + ' alpha = scaleLinear( lifeLeft, vec2( 1.0, 0.995 ), vec2( 0.0, 1.0 ) );', + + ' } else {', + + ' alpha = lifeLeft * 0.75;', + + ' }', + + ' vec4 tex = texture2D( tSprite, gl_PointCoord );', + ' gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );', + + '}' + + ].join( '\n' ) + + }; + + // preload a million random numbers + + var i; + + for ( i = 1e5; i > 0; i-- ) { + + this.rand.push( Math.random() - 0.5 ); + + } + + this.random = function() { + + return ++ i >= this.rand.length ? this.rand[ i = 1 ] : this.rand[ i ]; + + }; + + var textureLoader = new THREE.TextureLoader(); + + this.particleNoiseTex = this.PARTICLE_NOISE_TEXTURE || textureLoader.load( 'res/comet/perlin-512.png' ); + this.particleNoiseTex.wrapS = this.particleNoiseTex.wrapT = THREE.RepeatWrapping; + + this.particleSpriteTex = this.PARTICLE_SPRITE_TEXTURE || textureLoader.load( 'res/comet/particle2.png' ); + this.particleSpriteTex.wrapS = this.particleSpriteTex.wrapT = THREE.RepeatWrapping; + + this.particleShaderMat = new THREE.ShaderMaterial( { + transparent: true, + depthWrite: false, + uniforms: { + 'uTime': { + value: 0.0 + }, + 'uScale': { + value: 1.0 + }, + 'tNoise': { + value: this.particleNoiseTex + }, + 'tSprite': { + value: this.particleSpriteTex + } + }, + blending: THREE.AdditiveBlending, + vertexShader: GPUParticleShader.vertexShader, + fragmentShader: GPUParticleShader.fragmentShader + } ); + + // define defaults for all values + + this.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [ 0, 0, 0, 0 ]; + this.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [ 0, 0, 0, 0 ]; + + this.init = function() { + + for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) { + + var c = new THREE.GPUParticleContainer( this.PARTICLES_PER_CONTAINER, this ); + this.particleContainers.push( c ); + this.add( c ); + + } + + }; + + this.spawnParticle = function( options ) { + + this.PARTICLE_CURSOR ++; + + if ( this.PARTICLE_CURSOR >= this.PARTICLE_COUNT ) { + + this.PARTICLE_CURSOR = 1; + + } + + var currentContainer = this.particleContainers[ Math.floor( this.PARTICLE_CURSOR / this.PARTICLES_PER_CONTAINER ) ]; + + currentContainer.spawnParticle( options ); + + }; + + this.update = function( time ) { + + for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) { + + this.particleContainers[ i ].update( time ); + + } + + }; + + this.dispose = function() { + + this.particleShaderMat.dispose(); + this.particleNoiseTex.dispose(); + this.particleSpriteTex.dispose(); + + for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) { + + this.particleContainers[ i ].dispose(); + + } + + }; + + this.init(); + +}; + +THREE.GPUParticleSystem.prototype = Object.create( THREE.Object3D.prototype ); +THREE.GPUParticleSystem.prototype.constructor = THREE.GPUParticleSystem; + + +// Subclass for particle containers, allows for very large arrays to be spread out + +THREE.GPUParticleContainer = function( maxParticles, particleSystem ) { + + THREE.Object3D.apply( this, arguments ); + + this.PARTICLE_COUNT = maxParticles || 100000; + this.PARTICLE_CURSOR = 0; + this.time = 0; + this.offset = 0; + this.count = 0; + this.DPR = window.devicePixelRatio; + this.GPUParticleSystem = particleSystem; + this.particleUpdate = false; + + // geometry + + this.particleShaderGeo = new THREE.BufferGeometry(); + + this.particleShaderGeo.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); + this.particleShaderGeo.addAttribute( 'positionStart', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); + this.particleShaderGeo.addAttribute( 'startTime', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); + this.particleShaderGeo.addAttribute( 'velocity', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); + this.particleShaderGeo.addAttribute( 'turbulence', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); + this.particleShaderGeo.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) ); + this.particleShaderGeo.addAttribute( 'size', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); + this.particleShaderGeo.addAttribute( 'lifeTime', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) ); + + // material + + this.particleShaderMat = this.GPUParticleSystem.particleShaderMat; + + var position = new THREE.Vector3(); + var velocity = new THREE.Vector3(); + var color = new THREE.Color(); + + this.spawnParticle = function( options ) { + + var positionStartAttribute = this.particleShaderGeo.getAttribute( 'positionStart' ); + var startTimeAttribute = this.particleShaderGeo.getAttribute( 'startTime' ); + var velocityAttribute = this.particleShaderGeo.getAttribute( 'velocity' ); + var turbulenceAttribute = this.particleShaderGeo.getAttribute( 'turbulence' ); + var colorAttribute = this.particleShaderGeo.getAttribute( 'color' ); + var sizeAttribute = this.particleShaderGeo.getAttribute( 'size' ); + var lifeTimeAttribute = this.particleShaderGeo.getAttribute( 'lifeTime' ); + + options = options || {}; + + // setup reasonable default values for all arguments + + position = options.position !== undefined ? position.copy( options.position ) : position.set( 0, 0, 0 ); + velocity = options.velocity !== undefined ? velocity.copy( options.velocity ) : velocity.set( 0, 0, 0 ); + color = options.color !== undefined ? color.set( options.color ) : color.set( 0xffffff ); + + var positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0; + var velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0; + var colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1; + var turbulence = options.turbulence !== undefined ? options.turbulence : 1; + var lifetime = options.lifetime !== undefined ? options.lifetime : 5; + var size = options.size !== undefined ? options.size : 10; + var sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0; + var smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false; + + if ( this.DPR !== undefined ) size *= this.DPR; + + var i = this.PARTICLE_CURSOR; + + // position + + positionStartAttribute.array[ i * 3 + 0 ] = position.x + ( particleSystem.random() * positionRandomness ); + positionStartAttribute.array[ i * 3 + 1 ] = position.y + ( particleSystem.random() * positionRandomness ); + positionStartAttribute.array[ i * 3 + 2 ] = position.z + ( particleSystem.random() * positionRandomness ); + + if ( smoothPosition === true ) { + + positionStartAttribute.array[ i * 3 + 0 ] += - ( velocity.x * particleSystem.random() ); + positionStartAttribute.array[ i * 3 + 1 ] += - ( velocity.y * particleSystem.random() ); + positionStartAttribute.array[ i * 3 + 2 ] += - ( velocity.z * particleSystem.random() ); + + } + + // velocity + + var maxVel = 2; + + var velX = velocity.x + particleSystem.random() * velocityRandomness; + var velY = velocity.y + particleSystem.random() * velocityRandomness; + var velZ = velocity.z + particleSystem.random() * velocityRandomness; + + velX = THREE.Math.clamp( ( velX - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 ); + velY = THREE.Math.clamp( ( velY - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 ); + velZ = THREE.Math.clamp( ( velZ - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 ); + + velocityAttribute.array[ i * 3 + 0 ] = velX; + velocityAttribute.array[ i * 3 + 1 ] = velY; + velocityAttribute.array[ i * 3 + 2 ] = velZ; + + // color + + color.r = THREE.Math.clamp( color.r + particleSystem.random() * colorRandomness, 0, 1 ); + color.g = THREE.Math.clamp( color.g + particleSystem.random() * colorRandomness, 0, 1 ); + color.b = THREE.Math.clamp( color.b + particleSystem.random() * colorRandomness, 0, 1 ); + + colorAttribute.array[ i * 3 + 0 ] = color.r; + colorAttribute.array[ i * 3 + 1 ] = color.g; + colorAttribute.array[ i * 3 + 2 ] = color.b; + + // turbulence, size, lifetime and starttime + + turbulenceAttribute.array[ i ] = turbulence; + sizeAttribute.array[ i ] = size + particleSystem.random() * sizeRandomness; + lifeTimeAttribute.array[ i ] = lifetime; + startTimeAttribute.array[ i ] = this.time + particleSystem.random() * 2e-2; + + // offset + + if ( this.offset === 0 ) { + + this.offset = this.PARTICLE_CURSOR; + + } + + // counter and cursor + + this.count ++; + this.PARTICLE_CURSOR ++; + + if ( this.PARTICLE_CURSOR >= this.PARTICLE_COUNT ) { + + this.PARTICLE_CURSOR = 0; + + } + + this.particleUpdate = true; + + }; + + this.init = function() { + + this.particleSystem = new THREE.Points( this.particleShaderGeo, this.particleShaderMat ); + this.particleSystem.frustumCulled = false; + this.add( this.particleSystem ); + + }; + + this.update = function( time ) { + + this.time = time; + this.particleShaderMat.uniforms.uTime.value = time; + + this.geometryUpdate(); + + }; + + this.geometryUpdate = function() { + + if ( this.particleUpdate === true ) { + + this.particleUpdate = false; + + var positionStartAttribute = this.particleShaderGeo.getAttribute( 'positionStart' ); + var startTimeAttribute = this.particleShaderGeo.getAttribute( 'startTime' ); + var velocityAttribute = this.particleShaderGeo.getAttribute( 'velocity' ); + var turbulenceAttribute = this.particleShaderGeo.getAttribute( 'turbulence' ); + var colorAttribute = this.particleShaderGeo.getAttribute( 'color' ); + var sizeAttribute = this.particleShaderGeo.getAttribute( 'size' ); + var lifeTimeAttribute = this.particleShaderGeo.getAttribute( 'lifeTime' ); + + if ( this.offset + this.count < this.PARTICLE_COUNT ) { + + positionStartAttribute.updateRange.offset = this.offset * positionStartAttribute.itemSize; + startTimeAttribute.updateRange.offset = this.offset * startTimeAttribute.itemSize; + velocityAttribute.updateRange.offset = this.offset * velocityAttribute.itemSize; + turbulenceAttribute.updateRange.offset = this.offset * turbulenceAttribute.itemSize; + colorAttribute.updateRange.offset = this.offset * colorAttribute.itemSize; + sizeAttribute.updateRange.offset = this.offset * sizeAttribute.itemSize; + lifeTimeAttribute.updateRange.offset = this.offset * lifeTimeAttribute.itemSize; + + positionStartAttribute.updateRange.count = this.count * positionStartAttribute.itemSize; + startTimeAttribute.updateRange.count = this.count * startTimeAttribute.itemSize; + velocityAttribute.updateRange.count = this.count * velocityAttribute.itemSize; + turbulenceAttribute.updateRange.count = this.count * turbulenceAttribute.itemSize; + colorAttribute.updateRange.count = this.count * colorAttribute.itemSize; + sizeAttribute.updateRange.count = this.count * sizeAttribute.itemSize; + lifeTimeAttribute.updateRange.count = this.count * lifeTimeAttribute.itemSize; + + } else { + + positionStartAttribute.updateRange.offset = 0; + startTimeAttribute.updateRange.offset = 0; + velocityAttribute.updateRange.offset = 0; + turbulenceAttribute.updateRange.offset = 0; + colorAttribute.updateRange.offset = 0; + sizeAttribute.updateRange.offset = 0; + lifeTimeAttribute.updateRange.offset = 0; + + // Use -1 to update the entire buffer, see #11476 + positionStartAttribute.updateRange.count = -1; + startTimeAttribute.updateRange.count = -1; + velocityAttribute.updateRange.count = -1; + turbulenceAttribute.updateRange.count = -1; + colorAttribute.updateRange.count = -1; + sizeAttribute.updateRange.count = -1; + lifeTimeAttribute.updateRange.count = -1; + + } + + positionStartAttribute.needsUpdate = true; + startTimeAttribute.needsUpdate = true; + velocityAttribute.needsUpdate = true; + turbulenceAttribute.needsUpdate = true; + colorAttribute.needsUpdate = true; + sizeAttribute.needsUpdate = true; + lifeTimeAttribute.needsUpdate = true; + + this.offset = 0; + this.count = 0; + + } + + }; + + this.dispose = function() { + + this.particleShaderGeo.dispose(); + + }; + + this.init(); + +}; + +THREE.GPUParticleContainer.prototype = Object.create( THREE.Object3D.prototype ); +THREE.GPUParticleContainer.prototype.constructor = THREE.GPUParticleContainer; diff --git a/solar/js/libs/MTLLoader.js b/solar/js/libs/MTLLoader.js new file mode 100644 index 0000000..c2ae70a --- /dev/null +++ b/solar/js/libs/MTLLoader.js @@ -0,0 +1,551 @@ +/** + * Loads a Wavefront .mtl file specifying materials + * + * @author angelxuanchang + */ + +THREE.MTLLoader = function ( manager ) { + + this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + +}; + +THREE.MTLLoader.prototype = { + + constructor: THREE.MTLLoader, + + /** + * Loads and parses a MTL asset from a URL. + * + * @param {String} url - URL to the MTL file. + * @param {Function} [onLoad] - Callback invoked with the loaded object. + * @param {Function} [onProgress] - Callback for download progress. + * @param {Function} [onError] - Callback for download errors. + * + * @see setPath setTexturePath + * + * @note In order for relative texture references to resolve correctly + * you must call setPath and/or setTexturePath explicitly prior to load. + */ + load: function ( url, onLoad, onProgress, onError ) { + + var scope = this; + + var loader = new THREE.FileLoader( this.manager ); + loader.setPath( this.path ); + loader.load( url, function ( text ) { + + onLoad( scope.parse( text ) ); + + }, onProgress, onError ); + + }, + + /** + * Set base path for resolving references. + * If set this path will be prepended to each loaded and found reference. + * + * @see setTexturePath + * @param {String} path + * + * @example + * mtlLoader.setPath( 'assets/obj/' ); + * mtlLoader.load( 'my.mtl', ... ); + */ + setPath: function ( path ) { + + this.path = path; + + }, + + /** + * Set base path for resolving texture references. + * If set this path will be prepended found texture reference. + * If not set and setPath is, it will be used as texture base path. + * + * @see setPath + * @param {String} path + * + * @example + * mtlLoader.setPath( 'assets/obj/' ); + * mtlLoader.setTexturePath( 'assets/textures/' ); + * mtlLoader.load( 'my.mtl', ... ); + */ + setTexturePath: function ( path ) { + + this.texturePath = path; + + }, + + setBaseUrl: function ( path ) { + + console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' ); + + this.setTexturePath( path ); + + }, + + setCrossOrigin: function ( value ) { + + this.crossOrigin = value; + + }, + + setMaterialOptions: function ( value ) { + + this.materialOptions = value; + + }, + + /** + * Parses a MTL file. + * + * @param {String} text - Content of MTL file + * @return {THREE.MTLLoader.MaterialCreator} + * + * @see setPath setTexturePath + * + * @note In order for relative texture references to resolve correctly + * you must call setPath and/or setTexturePath explicitly prior to parse. + */ + parse: function ( text ) { + + var lines = text.split( '\n' ); + var info = {}; + var delimiter_pattern = /\s+/; + var materialsInfo = {}; + + for ( var i = 0; i < lines.length; i ++ ) { + + var line = lines[ i ]; + line = line.trim(); + + if ( line.length === 0 || line.charAt( 0 ) === '#' ) { + + // Blank line or comment ignore + continue; + + } + + var pos = line.indexOf( ' ' ); + + var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; + key = key.toLowerCase(); + + var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; + value = value.trim(); + + if ( key === 'newmtl' ) { + + // New material + + info = { name: value }; + materialsInfo[ value ] = info; + + } else if ( info ) { + + if ( key === 'ka' || key === 'kd' || key === 'ks' ) { + + var ss = value.split( delimiter_pattern, 3 ); + info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; + + } else { + + info[ key ] = value; + + } + + } + + } + + var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions ); + materialCreator.setCrossOrigin( this.crossOrigin ); + materialCreator.setManager( this.manager ); + materialCreator.setMaterials( materialsInfo ); + return materialCreator; + + } + +}; + +/** + * Create a new THREE-MTLLoader.MaterialCreator + * @param baseUrl - Url relative to which textures are loaded + * @param options - Set of options on how to construct the materials + * side: Which side to apply the material + * THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide + * wrap: What type of wrapping to apply for textures + * THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping + * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255 + * Default: false, assumed to be already normalized + * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's + * Default: false + * @constructor + */ + +THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) { + + this.baseUrl = baseUrl || ''; + this.options = options; + this.materialsInfo = {}; + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; + + this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide; + this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping; + +}; + +THREE.MTLLoader.MaterialCreator.prototype = { + + constructor: THREE.MTLLoader.MaterialCreator, + + crossOrigin: 'Anonymous', + + setCrossOrigin: function ( value ) { + + this.crossOrigin = value; + + }, + + setManager: function ( value ) { + + this.manager = value; + + }, + + setMaterials: function ( materialsInfo ) { + + this.materialsInfo = this.convert( materialsInfo ); + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; + + }, + + convert: function ( materialsInfo ) { + + if ( ! this.options ) return materialsInfo; + + var converted = {}; + + for ( var mn in materialsInfo ) { + + // Convert materials info into normalized form based on options + + var mat = materialsInfo[ mn ]; + + var covmat = {}; + + converted[ mn ] = covmat; + + for ( var prop in mat ) { + + var save = true; + var value = mat[ prop ]; + var lprop = prop.toLowerCase(); + + switch ( lprop ) { + + case 'kd': + case 'ka': + case 'ks': + + // Diffuse color (color under white light) using RGB values + + if ( this.options && this.options.normalizeRGB ) { + + value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ]; + + } + + if ( this.options && this.options.ignoreZeroRGBs ) { + + if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) { + + // ignore + + save = false; + + } + + } + + break; + + default: + + break; + + } + + if ( save ) { + + covmat[ lprop ] = value; + + } + + } + + } + + return converted; + + }, + + preload: function () { + + for ( var mn in this.materialsInfo ) { + + this.create( mn ); + + } + + }, + + getIndex: function ( materialName ) { + + return this.nameLookup[ materialName ]; + + }, + + getAsArray: function () { + + var index = 0; + + for ( var mn in this.materialsInfo ) { + + this.materialsArray[ index ] = this.create( mn ); + this.nameLookup[ mn ] = index; + index ++; + + } + + return this.materialsArray; + + }, + + create: function ( materialName ) { + + if ( this.materials[ materialName ] === undefined ) { + + this.createMaterial_( materialName ); + + } + + return this.materials[ materialName ]; + + }, + + createMaterial_: function ( materialName ) { + + // Create material + + var scope = this; + var mat = this.materialsInfo[ materialName ]; + var params = { + + name: materialName, + side: this.side + + }; + + function resolveURL( baseUrl, url ) { + + if ( typeof url !== 'string' || url === '' ) + return ''; + + // Absolute URL + if ( /^https?:\/\//i.test( url ) ) return url; + + return baseUrl + url; + + } + + function setMapForType( mapType, value ) { + + if ( params[ mapType ] ) return; // Keep the first encountered texture + + var texParams = scope.getTextureParams( value, params ); + var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); + + map.repeat.copy( texParams.scale ); + map.offset.copy( texParams.offset ); + + map.wrapS = scope.wrap; + map.wrapT = scope.wrap; + + params[ mapType ] = map; + + } + + for ( var prop in mat ) { + + var value = mat[ prop ]; + var n; + + if ( value === '' ) continue; + + switch ( prop.toLowerCase() ) { + + // Ns is material specular exponent + + case 'kd': + + // Diffuse color (color under white light) using RGB values + + params.color = new THREE.Color().fromArray( value ); + + break; + + case 'ks': + + // Specular color (color when light is reflected from shiny surface) using RGB values + params.specular = new THREE.Color().fromArray( value ); + + break; + + case 'map_kd': + + // Diffuse texture map + + setMapForType( "map", value ); + + break; + + case 'map_ks': + + // Specular map + + setMapForType( "specularMap", value ); + + break; + + case 'norm': + + setMapForType( "normalMap", value ); + + break; + + case 'map_bump': + case 'bump': + + // Bump texture map + + setMapForType( "bumpMap", value ); + + break; + + case 'ns': + + // The specular exponent (defines the focus of the specular highlight) + // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000. + + params.shininess = parseFloat( value ); + + break; + + case 'd': + n = parseFloat( value ); + + if ( n < 1 ) { + + params.opacity = n; + params.transparent = true; + + } + + break; + + case 'tr': + n = parseFloat( value ); + + if ( n > 0 ) { + + params.opacity = 1 - n; + params.transparent = true; + + } + + break; + + default: + break; + + } + + } + + this.materials[ materialName ] = new THREE.MeshPhongMaterial( params ); + return this.materials[ materialName ]; + + }, + + getTextureParams: function ( value, matParams ) { + + var texParams = { + + scale: new THREE.Vector2( 1, 1 ), + offset: new THREE.Vector2( 0, 0 ) + + }; + + var items = value.split( /\s+/ ); + var pos; + + pos = items.indexOf( '-bm' ); + + if ( pos >= 0 ) { + + matParams.bumpScale = parseFloat( items[ pos + 1 ] ); + items.splice( pos, 2 ); + + } + + pos = items.indexOf( '-s' ); + + if ( pos >= 0 ) { + + texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! + + } + + pos = items.indexOf( '-o' ); + + if ( pos >= 0 ) { + + texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) ); + items.splice( pos, 4 ); // we expect 3 parameters here! + + } + + texParams.url = items.join( ' ' ).trim(); + return texParams; + + }, + + loadTexture: function ( url, mapping, onLoad, onProgress, onError ) { + + var texture; + var loader = THREE.Loader.Handlers.get( url ); + var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager; + + if ( loader === null ) { + + loader = new THREE.TextureLoader( manager ); + + } + + if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); + texture = loader.load( url, onLoad, onProgress, onError ); + + if ( mapping !== undefined ) texture.mapping = mapping; + + return texture; + + } + +}; diff --git a/solar/js/libs/OBJLoader.js b/solar/js/libs/OBJLoader.js new file mode 100644 index 0000000..daf80ff --- /dev/null +++ b/solar/js/libs/OBJLoader.js @@ -0,0 +1,715 @@ +/** + * @author mrdoob / http://mrdoob.com/ + */ + +THREE.OBJLoader = ( function () { + + // o object_name | g group_name + var object_pattern = /^[og]\s*(.+)?/; + // mtllib file_reference + var material_library_pattern = /^mtllib /; + // usemtl material_name + var material_use_pattern = /^usemtl /; + + function ParserState() { + + var state = { + objects: [], + object: {}, + + vertices: [], + normals: [], + colors: [], + uvs: [], + + materialLibraries: [], + + startObject: function ( name, fromDeclaration ) { + + // If the current object (initial from reset) is not from a g/o declaration in the parsed + // file. We need to use it for the first parsed g/o to keep things in sync. + if ( this.object && this.object.fromDeclaration === false ) { + + this.object.name = name; + this.object.fromDeclaration = ( fromDeclaration !== false ); + return; + + } + + var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); + + if ( this.object && typeof this.object._finalize === 'function' ) { + + this.object._finalize( true ); + + } + + this.object = { + name: name || '', + fromDeclaration: ( fromDeclaration !== false ), + + geometry: { + vertices: [], + normals: [], + colors: [], + uvs: [] + }, + materials: [], + smooth: true, + + startMaterial: function ( name, libraries ) { + + var previous = this._finalize( false ); + + // New usemtl declaration overwrites an inherited material, except if faces were declared + // after the material, then it must be preserved for proper MultiMaterial continuation. + if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { + + this.materials.splice( previous.index, 1 ); + + } + + var material = { + index: this.materials.length, + name: name || '', + mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), + smooth: ( previous !== undefined ? previous.smooth : this.smooth ), + groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), + groupEnd: - 1, + groupCount: - 1, + inherited: false, + + clone: function ( index ) { + + var cloned = { + index: ( typeof index === 'number' ? index : this.index ), + name: this.name, + mtllib: this.mtllib, + smooth: this.smooth, + groupStart: 0, + groupEnd: - 1, + groupCount: - 1, + inherited: false + }; + cloned.clone = this.clone.bind( cloned ); + return cloned; + + } + }; + + this.materials.push( material ); + + return material; + + }, + + currentMaterial: function () { + + if ( this.materials.length > 0 ) { + + return this.materials[ this.materials.length - 1 ]; + + } + + return undefined; + + }, + + _finalize: function ( end ) { + + var lastMultiMaterial = this.currentMaterial(); + if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { + + lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; + lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; + lastMultiMaterial.inherited = false; + + } + + // Ignore objects tail materials if no face declarations followed them before a new o/g started. + if ( end && this.materials.length > 1 ) { + + for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { + + if ( this.materials[ mi ].groupCount <= 0 ) { + + this.materials.splice( mi, 1 ); + + } + + } + + } + + // Guarantee at least one empty material, this makes the creation later more straight forward. + if ( end && this.materials.length === 0 ) { + + this.materials.push( { + name: '', + smooth: this.smooth + } ); + + } + + return lastMultiMaterial; + + } + }; + + // Inherit previous objects material. + // Spec tells us that a declared material must be set to all objects until a new material is declared. + // If a usemtl declaration is encountered while this new object is being parsed, it will + // overwrite the inherited material. Exception being that there was already face declarations + // to the inherited material, then it will be preserved for proper MultiMaterial continuation. + + if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { + + var declared = previousMaterial.clone( 0 ); + declared.inherited = true; + this.object.materials.push( declared ); + + } + + this.objects.push( this.object ); + + }, + + finalize: function () { + + if ( this.object && typeof this.object._finalize === 'function' ) { + + this.object._finalize( true ); + + } + + }, + + parseVertexIndex: function ( value, len ) { + + var index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + + }, + + parseNormalIndex: function ( value, len ) { + + var index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + + }, + + parseUVIndex: function ( value, len ) { + + var index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; + + }, + + addVertex: function ( a, b, c ) { + + var src = this.vertices; + var dst = this.object.geometry.vertices; + + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + + }, + + addVertexLine: function ( a ) { + + var src = this.vertices; + var dst = this.object.geometry.vertices; + + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + + }, + + addNormal: function ( a, b, c ) { + + var src = this.normals; + var dst = this.object.geometry.normals; + + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + + }, + + addColor: function ( a, b, c ) { + + var src = this.colors; + var dst = this.object.geometry.colors; + + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + + }, + + addUV: function ( a, b, c ) { + + var src = this.uvs; + var dst = this.object.geometry.uvs; + + dst.push( src[ a + 0 ], src[ a + 1 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ] ); + + }, + + addUVLine: function ( a ) { + + var src = this.uvs; + var dst = this.object.geometry.uvs; + + dst.push( src[ a + 0 ], src[ a + 1 ] ); + + }, + + addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { + + var vLen = this.vertices.length; + + var ia = this.parseVertexIndex( a, vLen ); + var ib = this.parseVertexIndex( b, vLen ); + var ic = this.parseVertexIndex( c, vLen ); + + this.addVertex( ia, ib, ic ); + + if ( ua !== undefined ) { + + var uvLen = this.uvs.length; + + ia = this.parseUVIndex( ua, uvLen ); + ib = this.parseUVIndex( ub, uvLen ); + ic = this.parseUVIndex( uc, uvLen ); + + this.addUV( ia, ib, ic ); + + } + + if ( na !== undefined ) { + + // Normals are many times the same. If so, skip function call and parseInt. + var nLen = this.normals.length; + ia = this.parseNormalIndex( na, nLen ); + + ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); + ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); + + this.addNormal( ia, ib, ic ); + + } + + if ( this.colors.length > 0 ) { + + this.addColor( ia, ib, ic ); + + } + + }, + + addLineGeometry: function ( vertices, uvs ) { + + this.object.geometry.type = 'Line'; + + var vLen = this.vertices.length; + var uvLen = this.uvs.length; + + for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { + + this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); + + } + + for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { + + this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); + + } + + } + + }; + + state.startObject( '', false ); + + return state; + + } + + // + + function OBJLoader( manager ) { + + this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + + this.materials = null; + + } + + OBJLoader.prototype = { + + constructor: OBJLoader, + + load: function ( url, onLoad, onProgress, onError ) { + + var scope = this; + + var loader = new THREE.FileLoader( scope.manager ); + loader.setPath( this.path ); + loader.load( url, function ( text ) { + + onLoad( scope.parse( text ) ); + + }, onProgress, onError ); + + }, + + setPath: function ( value ) { + + this.path = value; + + }, + + setMaterials: function ( materials ) { + + this.materials = materials; + + return this; + + }, + + parse: function ( text ) { + + console.time( 'OBJLoader' ); + + var state = new ParserState(); + + if ( text.indexOf( '\r\n' ) !== - 1 ) { + + // This is faster than String.split with regex that splits on both + text = text.replace( /\r\n/g, '\n' ); + + } + + if ( text.indexOf( '\\\n' ) !== - 1 ) { + + // join lines separated by a line continuation character (\) + text = text.replace( /\\\n/g, '' ); + + } + + var lines = text.split( '\n' ); + var line = '', lineFirstChar = ''; + var lineLength = 0; + var result = []; + + // Faster to just trim left side of the line. Use if available. + var trimLeft = ( typeof ''.trimLeft === 'function' ); + + for ( var i = 0, l = lines.length; i < l; i ++ ) { + + line = lines[ i ]; + + line = trimLeft ? line.trimLeft() : line.trim(); + + lineLength = line.length; + + if ( lineLength === 0 ) continue; + + lineFirstChar = line.charAt( 0 ); + + // @todo invoke passed in handler if any + if ( lineFirstChar === '#' ) continue; + + if ( lineFirstChar === 'v' ) { + + var data = line.split( /\s+/ ); + + switch ( data[ 0 ] ) { + + case 'v': + state.vertices.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + if ( data.length === 8 ) { + + state.colors.push( + parseFloat( data[ 4 ] ), + parseFloat( data[ 5 ] ), + parseFloat( data[ 6 ] ) + + ); + + } + break; + case 'vn': + state.normals.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + break; + case 'vt': + state.uvs.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ) + ); + break; + + } + + } else if ( lineFirstChar === 'f' ) { + + var lineData = line.substr( 1 ).trim(); + var vertexData = lineData.split( /\s+/ ); + var faceVertices = []; + + // Parse the face vertex data into an easy to work with format + + for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { + + var vertex = vertexData[ j ]; + + if ( vertex.length > 0 ) { + + var vertexParts = vertex.split( '/' ); + faceVertices.push( vertexParts ); + + } + + } + + // Draw an edge between the first vertex and all subsequent vertices to form an n-gon + + var v1 = faceVertices[ 0 ]; + + for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { + + var v2 = faceVertices[ j ]; + var v3 = faceVertices[ j + 1 ]; + + state.addFace( + v1[ 0 ], v2[ 0 ], v3[ 0 ], + v1[ 1 ], v2[ 1 ], v3[ 1 ], + v1[ 2 ], v2[ 2 ], v3[ 2 ] + ); + + } + + } else if ( lineFirstChar === 'l' ) { + + var lineParts = line.substring( 1 ).trim().split( " " ); + var lineVertices = [], lineUVs = []; + + if ( line.indexOf( "/" ) === - 1 ) { + + lineVertices = lineParts; + + } else { + + for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { + + var parts = lineParts[ li ].split( "/" ); + + if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] ); + if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] ); + + } + + } + state.addLineGeometry( lineVertices, lineUVs ); + + } else if ( ( result = object_pattern.exec( line ) ) !== null ) { + + // o object_name + // or + // g group_name + + // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 + // var name = result[ 0 ].substr( 1 ).trim(); + var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); + + state.startObject( name ); + + } else if ( material_use_pattern.test( line ) ) { + + // material + + state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); + + } else if ( material_library_pattern.test( line ) ) { + + // mtl file + + state.materialLibraries.push( line.substring( 7 ).trim() ); + + } else if ( lineFirstChar === 's' ) { + + result = line.split( ' ' ); + + // smooth shading + + // @todo Handle files that have varying smooth values for a set of faces inside one geometry, + // but does not define a usemtl for each face set. + // This should be detected and a dummy material created (later MultiMaterial and geometry groups). + // This requires some care to not create extra material on each smooth value for "normal" obj files. + // where explicit usemtl defines geometry groups. + // Example asset: examples/models/obj/cerberus/Cerberus.obj + + /* + * http://paulbourke.net/dataformats/obj/ + * or + * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf + * + * From chapter "Grouping" Syntax explanation "s group_number": + * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. + * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form + * surfaces, smoothing groups are either turned on or off; there is no difference between values greater + * than 0." + */ + if ( result.length > 1 ) { + + var value = result[ 1 ].trim().toLowerCase(); + state.object.smooth = ( value !== '0' && value !== 'off' ); + + } else { + + // ZBrush can produce "s" lines #11707 + state.object.smooth = true; + + } + var material = state.object.currentMaterial(); + if ( material ) material.smooth = state.object.smooth; + + } else { + + // Handle null terminated files without exception + if ( line === '\0' ) continue; + + throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); + + } + + } + + state.finalize(); + + var container = new THREE.Group(); + container.materialLibraries = [].concat( state.materialLibraries ); + + for ( var i = 0, l = state.objects.length; i < l; i ++ ) { + + var object = state.objects[ i ]; + var geometry = object.geometry; + var materials = object.materials; + var isLine = ( geometry.type === 'Line' ); + + // Skip o/g line declarations that did not follow with any faces + if ( geometry.vertices.length === 0 ) continue; + + var buffergeometry = new THREE.BufferGeometry(); + + buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); + + if ( geometry.normals.length > 0 ) { + + buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); + + } else { + + buffergeometry.computeVertexNormals(); + + } + + if ( geometry.colors.length > 0 ) { + + buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); + + } + + if ( geometry.uvs.length > 0 ) { + + buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); + + } + + // Create materials + + var createdMaterials = []; + + for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + + var sourceMaterial = materials[ mi ]; + var material = undefined; + + if ( this.materials !== null ) { + + material = this.materials.create( sourceMaterial.name ); + + // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. + if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { + + var materialLine = new THREE.LineBasicMaterial(); + materialLine.copy( material ); + material = materialLine; + + } + + } + + if ( ! material ) { + + material = ( ! isLine ? new THREE.MeshPhongMaterial() : new THREE.LineBasicMaterial() ); + material.name = sourceMaterial.name; + + } + + material.flatShading = sourceMaterial.smooth ? false : true; + + createdMaterials.push( material ); + + } + + // Create mesh + + var mesh; + + if ( createdMaterials.length > 1 ) { + + for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + + var sourceMaterial = materials[ mi ]; + buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); + + } + + mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials ) : new THREE.LineSegments( buffergeometry, createdMaterials ) ); + + } else { + + mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ) : new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ) ); + + } + + mesh.name = object.name; + + container.add( mesh ); + + } + + console.timeEnd( 'OBJLoader' ); + + return container; + + } + + }; + + return OBJLoader; + +} )(); diff --git a/solar/js/libs/dat.gui.min.js b/solar/js/libs/dat.gui.min.js new file mode 100644 index 0000000..5b69be5 --- /dev/null +++ b/solar/js/libs/dat.gui.min.js @@ -0,0 +1,14 @@ +/** + * dat-gui JavaScript Controller Library + * https://github.com/dataarts/dat.gui + * + * Copyright 2016 Data Arts Team, Google Creative Lab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.dat=t():e.dat=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return e[o].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}var i=n(1),r=o(i);e.exports=r["default"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0;var i=n(2),r=o(i),a=n(6),l=o(a),s=n(3),u=o(s),d=n(7),c=o(d),f=n(8),_=o(f),p=n(10),h=o(p),m=n(11),b=o(m),g=n(12),v=o(g),y=n(13),w=o(y),x=n(14),E=o(x),C=n(15),A=o(C),S=n(16),k=o(S),O=n(9),T=o(O),R=n(17),L=o(R);t["default"]={color:{Color:r["default"],math:l["default"],interpret:u["default"]},controllers:{Controller:c["default"],BooleanController:_["default"],OptionController:h["default"],StringController:b["default"],NumberController:v["default"],NumberControllerBox:w["default"],NumberControllerSlider:E["default"],FunctionController:A["default"],ColorController:k["default"]},dom:{dom:T["default"]},gui:{GUI:L["default"]},GUI:L["default"]}},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t,n){Object.defineProperty(e,t,{get:function(){return"RGB"===this.__state.space?this.__state[t]:(h.recalculateRGB(this,t,n),this.__state[t])},set:function(e){"RGB"!==this.__state.space&&(h.recalculateRGB(this,t,n),this.__state.space="RGB"),this.__state[t]=e}})}function a(e,t){Object.defineProperty(e,t,{get:function(){return"HSV"===this.__state.space?this.__state[t]:(h.recalculateHSV(this),this.__state[t])},set:function(e){"HSV"!==this.__state.space&&(h.recalculateHSV(this),this.__state.space="HSV"),this.__state[t]=e}})}t.__esModule=!0;var l=n(3),s=o(l),u=n(6),d=o(u),c=n(4),f=o(c),_=n(5),p=o(_),h=function(){function e(){if(i(this,e),this.__state=s["default"].apply(this,arguments),this.__state===!1)throw new Error("Failed to interpret color arguments");this.__state.a=this.__state.a||1}return e.prototype.toString=function(){return(0,f["default"])(this)},e.prototype.toHexString=function(){return(0,f["default"])(this,!0)},e.prototype.toOriginal=function(){return this.__state.conversion.write(this)},e}();h.recalculateRGB=function(e,t,n){if("HEX"===e.__state.space)e.__state[t]=d["default"].component_from_hex(e.__state.hex,n);else{if("HSV"!==e.__state.space)throw new Error("Corrupted color state");p["default"].extend(e.__state,d["default"].hsv_to_rgb(e.__state.h,e.__state.s,e.__state.v))}},h.recalculateHSV=function(e){var t=d["default"].rgb_to_hsv(e.r,e.g,e.b);p["default"].extend(e.__state,{s:t.s,v:t.v}),p["default"].isNaN(t.h)?p["default"].isUndefined(e.__state.h)&&(e.__state.h=0):e.__state.h=t.h},h.COMPONENTS=["r","g","b","h","s","v","hex","a"],r(h.prototype,"r",2),r(h.prototype,"g",1),r(h.prototype,"b",0),a(h.prototype,"h"),a(h.prototype,"s"),a(h.prototype,"v"),Object.defineProperty(h.prototype,"a",{get:function(){return this.__state.a},set:function(e){this.__state.a=e}}),Object.defineProperty(h.prototype,"hex",{get:function(){return"HEX"!==!this.__state.space&&(this.__state.hex=d["default"].rgb_to_hex(this.r,this.g,this.b)),this.__state.hex},set:function(e){this.__state.space="HEX",this.__state.hex=e}}),t["default"]=h},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0;var i=n(4),r=o(i),a=n(5),l=o(a),s=[{litmus:l["default"].isString,conversions:{THREE_CHAR_HEX:{read:function(e){var t=e.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return null!==t&&{space:"HEX",hex:parseInt("0x"+t[1].toString()+t[1].toString()+t[2].toString()+t[2].toString()+t[3].toString()+t[3].toString(),0)}},write:r["default"]},SIX_CHAR_HEX:{read:function(e){var t=e.match(/^#([A-F0-9]{6})$/i);return null!==t&&{space:"HEX",hex:parseInt("0x"+t[1].toString(),0)}},write:r["default"]},CSS_RGB:{read:function(e){var t=e.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);return null!==t&&{space:"RGB",r:parseFloat(t[1]),g:parseFloat(t[2]),b:parseFloat(t[3])}},write:r["default"]},CSS_RGBA:{read:function(e){var t=e.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);return null!==t&&{space:"RGB",r:parseFloat(t[1]),g:parseFloat(t[2]),b:parseFloat(t[3]),a:parseFloat(t[4])}},write:r["default"]}}},{litmus:l["default"].isNumber,conversions:{HEX:{read:function(e){return{space:"HEX",hex:e,conversionName:"HEX"}},write:function(e){return e.hex}}}},{litmus:l["default"].isArray,conversions:{RGB_ARRAY:{read:function(e){return 3===e.length&&{space:"RGB",r:e[0],g:e[1],b:e[2]}},write:function(e){return[e.r,e.g,e.b]}},RGBA_ARRAY:{read:function(e){return 4===e.length&&{space:"RGB",r:e[0],g:e[1],b:e[2],a:e[3]}},write:function(e){return[e.r,e.g,e.b,e.a]}}}},{litmus:l["default"].isObject,conversions:{RGBA_OBJ:{read:function(e){return!!(l["default"].isNumber(e.r)&&l["default"].isNumber(e.g)&&l["default"].isNumber(e.b)&&l["default"].isNumber(e.a))&&{space:"RGB",r:e.r,g:e.g,b:e.b,a:e.a}},write:function(e){return{r:e.r,g:e.g,b:e.b,a:e.a}}},RGB_OBJ:{read:function(e){return!!(l["default"].isNumber(e.r)&&l["default"].isNumber(e.g)&&l["default"].isNumber(e.b))&&{space:"RGB",r:e.r,g:e.g,b:e.b}},write:function(e){return{r:e.r,g:e.g,b:e.b}}},HSVA_OBJ:{read:function(e){return!!(l["default"].isNumber(e.h)&&l["default"].isNumber(e.s)&&l["default"].isNumber(e.v)&&l["default"].isNumber(e.a))&&{space:"HSV",h:e.h,s:e.s,v:e.v,a:e.a}},write:function(e){return{h:e.h,s:e.s,v:e.v,a:e.a}}},HSV_OBJ:{read:function(e){return!!(l["default"].isNumber(e.h)&&l["default"].isNumber(e.s)&&l["default"].isNumber(e.v))&&{space:"HSV",h:e.h,s:e.s,v:e.v}},write:function(e){return{h:e.h,s:e.s,v:e.v}}}}}],u=void 0,d=void 0,c=function(){d=!1;var e=arguments.length>1?l["default"].toArray(arguments):arguments[0];return l["default"].each(s,function(t){if(t.litmus(e))return l["default"].each(t.conversions,function(t,n){if(u=t.read(e),d===!1&&u!==!1)return d=u,u.conversionName=n,u.conversion=t,l["default"].BREAK}),l["default"].BREAK}),d};t["default"]=c},function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e,t){var n=e.__state.conversionName.toString(),o=Math.round(e.r),i=Math.round(e.g),r=Math.round(e.b),a=e.a,l=Math.round(e.h),s=e.s.toFixed(1),u=e.v.toFixed(1);if(t||"THREE_CHAR_HEX"===n||"SIX_CHAR_HEX"===n){for(var d=e.hex.toString(16);d.length<6;)d="0"+d;return"#"+d}return"CSS_RGB"===n?"rgb("+o+","+i+","+r+")":"CSS_RGBA"===n?"rgba("+o+","+i+","+r+","+a+")":"HEX"===n?"0x"+e.hex.toString(16):"RGB_ARRAY"===n?"["+o+","+i+","+r+"]":"RGBA_ARRAY"===n?"["+o+","+i+","+r+","+a+"]":"RGB_OBJ"===n?"{r:"+o+",g:"+i+",b:"+r+"}":"RGBA_OBJ"===n?"{r:"+o+",g:"+i+",b:"+r+",a:"+a+"}":"HSV_OBJ"===n?"{h:"+l+",s:"+s+",v:"+u+"}":"HSVA_OBJ"===n?"{h:"+l+",s:"+s+",v:"+u+",a:"+a+"}":"unknown format"}},function(e,t){"use strict";t.__esModule=!0;var n=Array.prototype.forEach,o=Array.prototype.slice,i={BREAK:{},extend:function(e){return this.each(o.call(arguments,1),function(t){var n=this.isObject(t)?Object.keys(t):[];n.forEach(function(n){this.isUndefined(t[n])||(e[n]=t[n])}.bind(this))},this),e},defaults:function(e){return this.each(o.call(arguments,1),function(t){var n=this.isObject(t)?Object.keys(t):[];n.forEach(function(n){this.isUndefined(e[n])&&(e[n]=t[n])}.bind(this))},this),e},compose:function(){var e=o.call(arguments);return function(){for(var t=o.call(arguments),n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},each:function(e,t,o){if(e)if(n&&e.forEach&&e.forEach===n)e.forEach(t,o);else if(e.length===e.length+0){var i=void 0,r=void 0;for(i=0,r=e.length;i>8*t&255},hex_with_component:function(e,t,o){return o<<(n=8*t)|e&~(255<-1?t.length-t.indexOf(".")-1:0}t.__esModule=!0;var s=n(7),u=o(s),d=n(5),c=o(d),f=function(e){function t(n,o,a){i(this,t);var s=r(this,e.call(this,n,o)),u=a||{};return s.__min=u.min,s.__max=u.max,s.__step=u.step,c["default"].isUndefined(s.__step)?0===s.initialValue?s.__impliedStep=1:s.__impliedStep=Math.pow(10,Math.floor(Math.log(Math.abs(s.initialValue))/Math.LN10))/10:s.__impliedStep=s.__step,s.__precision=l(s.__impliedStep),s}return a(t,e),t.prototype.setValue=function(t){var n=t;return void 0!==this.__min&&nthis.__max&&(n=this.__max),void 0!==this.__step&&n%this.__step!==0&&(n=Math.round(n/this.__step)*this.__step),e.prototype.setValue.call(this,n)},t.prototype.min=function(e){return this.__min=e,this},t.prototype.max=function(e){return this.__max=e,this},t.prototype.step=function(e){return this.__step=e,this.__impliedStep=e,this.__precision=l(e),this},t}(u["default"]);t["default"]=f},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){var n=Math.pow(10,t);return Math.round(e*n)/n}t.__esModule=!0;var s=n(12),u=o(s),d=n(9),c=o(d),f=n(5),_=o(f),p=function(e){function t(n,o,a){function l(){var e=parseFloat(m.__input.value);_["default"].isNaN(e)||m.setValue(e)}function s(){m.__onFinishChange&&m.__onFinishChange.call(m,m.getValue())}function u(){s()}function d(e){var t=b-e.clientY;m.setValue(m.getValue()+t*m.__impliedStep),b=e.clientY}function f(){c["default"].unbind(window,"mousemove",d),c["default"].unbind(window,"mouseup",f),s()}function p(e){c["default"].bind(window,"mousemove",d),c["default"].bind(window,"mouseup",f),b=e.clientY}i(this,t);var h=r(this,e.call(this,n,o,a));h.__truncationSuspended=!1;var m=h,b=void 0;return h.__input=document.createElement("input"),h.__input.setAttribute("type","text"),c["default"].bind(h.__input,"change",l),c["default"].bind(h.__input,"blur",u),c["default"].bind(h.__input,"mousedown",p),c["default"].bind(h.__input,"keydown",function(e){13===e.keyCode&&(m.__truncationSuspended=!0,this.blur(),m.__truncationSuspended=!1,s())}),h.updateDisplay(),h.domElement.appendChild(h.__input),h}return a(t,e),t.prototype.updateDisplay=function(){return this.__input.value=this.__truncationSuspended?this.getValue():l(this.getValue(),this.__precision),e.prototype.updateDisplay.call(this)},t}(u["default"]);t["default"]=p},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t,n,o,i){return o+(i-o)*((e-t)/(n-t))}t.__esModule=!0;var s=n(12),u=o(s),d=n(9),c=o(d),f=function(e){function t(n,o,a,s,u){function d(e){document.activeElement.blur(),c["default"].bind(window,"mousemove",f),c["default"].bind(window,"mouseup",_),f(e)}function f(e){e.preventDefault();var t=h.__background.getBoundingClientRect();return h.setValue(l(e.clientX,t.left,t.right,h.__min,h.__max)),!1}function _(){c["default"].unbind(window,"mousemove",f),c["default"].unbind(window,"mouseup",_),h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())}i(this,t);var p=r(this,e.call(this,n,o,{min:a,max:s,step:u})),h=p;return p.__background=document.createElement("div"),p.__foreground=document.createElement("div"),c["default"].bind(p.__background,"mousedown",d),c["default"].addClass(p.__background,"slider"),c["default"].addClass(p.__foreground,"slider-fg"),p.updateDisplay(),p.__background.appendChild(p.__foreground),p.domElement.appendChild(p.__background),p}return a(t,e),t.prototype.updateDisplay=function(){var t=(this.getValue()-this.__min)/(this.__max-this.__min);return this.__foreground.style.width=100*t+"%",e.prototype.updateDisplay.call(this)},t}(u["default"]);t["default"]=f},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}t.__esModule=!0;var l=n(7),s=o(l),u=n(9),d=o(u),c=function(e){function t(n,o,a){i(this,t);var l=r(this,e.call(this,n,o)),s=l;return l.__button=document.createElement("div"),l.__button.innerHTML=void 0===a?"Fire":a,d["default"].bind(l.__button,"click",function(e){return e.preventDefault(),s.fire(),!1}),d["default"].addClass(l.__button,"button"),l.domElement.appendChild(l.__button),l}return a(t,e),t.prototype.fire=function(){this.__onChange&&this.__onChange.call(this),this.getValue().call(this.object),this.__onFinishChange&&this.__onFinishChange.call(this,this.getValue())},t}(s["default"]);t["default"]=c},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t,n,o){e.style.background="",g["default"].each(y,function(i){e.style.cssText+="background: "+i+"linear-gradient("+t+", "+n+" 0%, "+o+" 100%); "})}function s(e){e.style.background="",e.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);",e.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);",e.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);",e.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);",e.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}t.__esModule=!0;var u=n(7),d=o(u),c=n(9),f=o(c),_=n(2),p=o(_),h=n(3),m=o(h),b=n(5),g=o(b),v=function(e){function t(n,o){function a(e){h(e),f["default"].bind(window,"mousemove",h),f["default"].bind(window,"mouseup",u)}function u(){f["default"].unbind(window,"mousemove",h),f["default"].unbind(window,"mouseup",u),_()}function d(){var e=(0,m["default"])(this.value);e!==!1?(y.__color.__state=e,y.setValue(y.__color.toOriginal())):this.value=y.__color.toString()}function c(){f["default"].unbind(window,"mousemove",b),f["default"].unbind(window,"mouseup",c),_()}function _(){y.__onFinishChange&&y.__onFinishChange.call(y,y.__color.toOriginal())}function h(e){e.preventDefault();var t=y.__saturation_field.getBoundingClientRect(),n=(e.clientX-t.left)/(t.right-t.left),o=1-(e.clientY-t.top)/(t.bottom-t.top);return o>1?o=1:o<0&&(o=0),n>1?n=1:n<0&&(n=0),y.__color.v=o,y.__color.s=n,y.setValue(y.__color.toOriginal()),!1}function b(e){e.preventDefault();var t=y.__hue_field.getBoundingClientRect(),n=1-(e.clientY-t.top)/(t.bottom-t.top);return n>1?n=1:n<0&&(n=0),y.__color.h=360*n,y.setValue(y.__color.toOriginal()),!1}i(this,t);var v=r(this,e.call(this,n,o));v.__color=new p["default"](v.getValue()),v.__temp=new p["default"](0);var y=v;v.domElement=document.createElement("div"),f["default"].makeSelectable(v.domElement,!1),v.__selector=document.createElement("div"),v.__selector.className="selector",v.__saturation_field=document.createElement("div"),v.__saturation_field.className="saturation-field",v.__field_knob=document.createElement("div"),v.__field_knob.className="field-knob",v.__field_knob_border="2px solid ",v.__hue_knob=document.createElement("div"),v.__hue_knob.className="hue-knob",v.__hue_field=document.createElement("div"),v.__hue_field.className="hue-field",v.__input=document.createElement("input"),v.__input.type="text",v.__input_textShadow="0 1px 1px ",f["default"].bind(v.__input,"keydown",function(e){13===e.keyCode&&d.call(this)}),f["default"].bind(v.__input,"blur",d),f["default"].bind(v.__selector,"mousedown",function(){f["default"].addClass(this,"drag").bind(window,"mouseup",function(){f["default"].removeClass(y.__selector,"drag")})});var w=document.createElement("div");return g["default"].extend(v.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"}),g["default"].extend(v.__field_knob.style,{position:"absolute",width:"12px",height:"12px",border:v.__field_knob_border+(v.__color.v<.5?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1}),g["default"].extend(v.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1}),g["default"].extend(v.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"}),g["default"].extend(w.style,{width:"100%",height:"100%",background:"none"}),l(w,"top","rgba(0,0,0,0)","#000"),g["default"].extend(v.__hue_field.style,{width:"15px",height:"100px",border:"1px solid #555",cursor:"ns-resize",position:"absolute",top:"3px",right:"3px"}),s(v.__hue_field),g["default"].extend(v.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:v.__input_textShadow+"rgba(0,0,0,0.7)"}),f["default"].bind(v.__saturation_field,"mousedown",a),f["default"].bind(v.__field_knob,"mousedown",a),f["default"].bind(v.__hue_field,"mousedown",function(e){b(e),f["default"].bind(window,"mousemove",b),f["default"].bind(window,"mouseup",c)}),v.__saturation_field.appendChild(w),v.__selector.appendChild(v.__field_knob),v.__selector.appendChild(v.__saturation_field),v.__selector.appendChild(v.__hue_field),v.__hue_field.appendChild(v.__hue_knob),v.domElement.appendChild(v.__input),v.domElement.appendChild(v.__selector),v.updateDisplay(),v}return a(t,e),t.prototype.updateDisplay=function(){var e=(0,m["default"])(this.getValue());if(e!==!1){var t=!1;g["default"].each(p["default"].COMPONENTS,function(n){if(!g["default"].isUndefined(e[n])&&!g["default"].isUndefined(this.__color.__state[n])&&e[n]!==this.__color.__state[n])return t=!0,{}},this),t&&g["default"].extend(this.__color.__state,e)}g["default"].extend(this.__temp.__state,this.__color.__state),this.__temp.a=1;var n=this.__color.v<.5||this.__color.s>.5?255:0,o=255-n;g["default"].extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+"px",marginTop:100*(1-this.__color.v)-7+"px",backgroundColor:this.__temp.toHexString(),border:this.__field_knob_border+"rgb("+n+","+n+","+n+")"}),this.__hue_knob.style.marginTop=100*(1-this.__color.h/360)+"px",this.__temp.s=1,this.__temp.v=1,l(this.__saturation_field,"left","#fff",this.__temp.toHexString()),this.__input.value=this.__color.toString(),g["default"].extend(this.__input.style,{backgroundColor:this.__color.toHexString(),color:"rgb("+n+","+n+","+n+")",textShadow:this.__input_textShadow+"rgba("+o+","+o+","+o+",.7)"})},t}(d["default"]),y=["-moz-","-o-","-webkit-","-ms-",""];t["default"]=v},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t,n){var o=document.createElement("li");return t&&o.appendChild(t),n?e.__ul.insertBefore(o,n):e.__ul.appendChild(o),e.onResize(),o}function r(e,t){var n=e.__preset_select[e.__preset_select.selectedIndex];t?n.innerHTML=n.value+"*":n.innerHTML=n.value}function a(e,t,n){if(n.__li=t,n.__gui=e,U["default"].extend(n,{options:function(t){if(arguments.length>1){var o=n.__li.nextElementSibling;return n.remove(),s(e,n.object,n.property,{before:o,factoryArgs:[U["default"].toArray(arguments)]})}if(U["default"].isArray(t)||U["default"].isObject(t)){var i=n.__li.nextElementSibling;return n.remove(),s(e,n.object,n.property,{before:i,factoryArgs:[t]})}},name:function(e){return n.__li.firstElementChild.firstElementChild.innerHTML=e,n},listen:function(){return n.__gui.listen(n),n},remove:function(){ +return n.__gui.remove(n),n}}),n instanceof B["default"])!function(){var e=new N["default"](n.object,n.property,{min:n.__min,max:n.__max,step:n.__step});U["default"].each(["updateDisplay","onChange","onFinishChange","step"],function(t){var o=n[t],i=e[t];n[t]=e[t]=function(){var t=Array.prototype.slice.call(arguments);return i.apply(e,t),o.apply(n,t)}}),z["default"].addClass(t,"has-slider"),n.domElement.insertBefore(e.domElement,n.domElement.firstElementChild)}();else if(n instanceof N["default"]){var o=function(t){if(U["default"].isNumber(n.__min)&&U["default"].isNumber(n.__max)){var o=n.__li.firstElementChild.firstElementChild.innerHTML,i=n.__gui.__listening.indexOf(n)>-1;n.remove();var r=s(e,n.object,n.property,{before:n.__li.nextElementSibling,factoryArgs:[n.__min,n.__max,n.__step]});return r.name(o),i&&r.listen(),r}return t};n.min=U["default"].compose(o,n.min),n.max=U["default"].compose(o,n.max)}else n instanceof O["default"]?(z["default"].bind(t,"click",function(){z["default"].fakeEvent(n.__checkbox,"click")}),z["default"].bind(n.__checkbox,"click",function(e){e.stopPropagation()})):n instanceof R["default"]?(z["default"].bind(t,"click",function(){z["default"].fakeEvent(n.__button,"click")}),z["default"].bind(t,"mouseover",function(){z["default"].addClass(n.__button,"hover")}),z["default"].bind(t,"mouseout",function(){z["default"].removeClass(n.__button,"hover")})):n instanceof j["default"]&&(z["default"].addClass(t,"color"),n.updateDisplay=U["default"].compose(function(e){return t.style.borderLeftColor=n.__color.toString(),e},n.updateDisplay),n.updateDisplay());n.setValue=U["default"].compose(function(t){return e.getRoot().__preset_select&&n.isModified()&&r(e.getRoot(),!0),t},n.setValue)}function l(e,t){var n=e.getRoot(),o=n.__rememberedObjects.indexOf(t.object);if(o!==-1){var i=n.__rememberedObjectIndecesToControllers[o];if(void 0===i&&(i={},n.__rememberedObjectIndecesToControllers[o]=i),i[t.property]=t,n.load&&n.load.remembered){var r=n.load.remembered,a=void 0;if(r[e.preset])a=r[e.preset];else{if(!r[Q])return;a=r[Q]}if(a[o]&&void 0!==a[o][t.property]){var l=a[o][t.property];t.initialValue=l,t.setValue(l)}}}}function s(e,t,n,o){if(void 0===t[n])throw new Error('Object "'+t+'" has no property "'+n+'"');var r=void 0;if(o.color)r=new j["default"](t,n);else{var s=[t,n].concat(o.factoryArgs);r=C["default"].apply(e,s)}o.before instanceof S["default"]&&(o.before=o.before.__li),l(e,r),z["default"].addClass(r.domElement,"c");var u=document.createElement("span");z["default"].addClass(u,"property-name"),u.innerHTML=r.property;var d=document.createElement("div");d.appendChild(u),d.appendChild(r.domElement);var c=i(e,d,o.before);return z["default"].addClass(c,oe.CLASS_CONTROLLER_ROW),r instanceof j["default"]?z["default"].addClass(c,"color"):z["default"].addClass(c,g(r.getValue())),a(e,c,r),e.__controllers.push(r),r}function u(e,t){return document.location.href+"."+t}function d(e,t,n){var o=document.createElement("option");o.innerHTML=t,o.value=t,e.__preset_select.appendChild(o),n&&(e.__preset_select.selectedIndex=e.__preset_select.length-1)}function c(e,t){t.style.display=e.useLocalStorage?"block":"none"}function f(e){var t=e.__save_row=document.createElement("li");z["default"].addClass(e.domElement,"has-save"),e.__ul.insertBefore(t,e.__ul.firstChild),z["default"].addClass(t,"save-row");var n=document.createElement("span");n.innerHTML=" ",z["default"].addClass(n,"button gears");var o=document.createElement("span");o.innerHTML="Save",z["default"].addClass(o,"button"),z["default"].addClass(o,"save");var i=document.createElement("span");i.innerHTML="New",z["default"].addClass(i,"button"),z["default"].addClass(i,"save-as");var r=document.createElement("span");r.innerHTML="Revert",z["default"].addClass(r,"button"),z["default"].addClass(r,"revert");var a=e.__preset_select=document.createElement("select");e.load&&e.load.remembered?U["default"].each(e.load.remembered,function(t,n){d(e,n,n===e.preset)}):d(e,Q,!1),z["default"].bind(a,"change",function(){for(var t=0;t0&&(e.preset=this.preset,e.remembered||(e.remembered={}),e.remembered[this.preset]=h(this)),e.folders={},U["default"].each(this.__folders,function(t,n){e.folders[n]=t.getSaveObject()}),e},save:function(){this.load.remembered||(this.load.remembered={}),this.load.remembered[this.preset]=h(this),r(this,!1),this.saveToLocalStorageIfPossible()},saveAs:function(e){this.load.remembered||(this.load.remembered={},this.load.remembered[Q]=h(this,!0)),this.load.remembered[e]=h(this),this.preset=e,d(this,e,!0),this.saveToLocalStorageIfPossible()},revert:function(e){U["default"].each(this.__controllers,function(t){this.getRoot().load.remembered?l(e||this.getRoot(),t):t.setValue(t.initialValue),t.__onFinishChange&&t.__onFinishChange.call(t,t.getValue())},this),U["default"].each(this.__folders,function(e){e.revert(e)}),e||r(this.getRoot(),!1)},listen:function(e){var t=0===this.__listening.length;this.__listening.push(e),t&&b(this.__listening)},updateDisplay:function(){U["default"].each(this.__controllers,function(e){e.updateDisplay()}),U["default"].each(this.__folders,function(e){e.updateDisplay()})}}),e.exports=oe},function(e,t){"use strict";e.exports={load:function(e,t){var n=t||document,o=n.createElement("link");o.type="text/css",o.rel="stylesheet",o.href=e,n.getElementsByTagName("head")[0].appendChild(o)},inject:function(e,t){var n=t||document,o=document.createElement("style");o.type="text/css",o.innerHTML=e;var i=n.getElementsByTagName("head")[0];try{i.appendChild(o)}catch(r){}}}},function(e,t){e.exports="
Here's the new load parameter for your GUI's constructor:
Automatically save values to localStorage on exit.
The values saved to localStorage will override those passed to dat.GUI's constructor. This makes it easier to work incrementally, but localStorage is fragile, and your friends may not see the same values you do.
"},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0;var i=n(10),r=o(i),a=n(13),l=o(a),s=n(14),u=o(s),d=n(11),c=o(d),f=n(15),_=o(f),p=n(8),h=o(p),m=n(5),b=o(m),g=function(e,t){var n=e[t];return b["default"].isArray(arguments[2])||b["default"].isObject(arguments[2])?new r["default"](e,t,arguments[2]):b["default"].isNumber(n)?b["default"].isNumber(arguments[2])&&b["default"].isNumber(arguments[3])?b["default"].isNumber(arguments[4])?new u["default"](e,t,arguments[2],arguments[3],arguments[4]):new u["default"](e,t,arguments[2],arguments[3]):b["default"].isNumber(arguments[4])?new l["default"](e,t,{min:arguments[2],max:arguments[3],step:arguments[4]}):new l["default"](e,t,{min:arguments[2],max:arguments[3]}):b["default"].isString(n)?new c["default"](e,t):b["default"].isFunction(n)?new _["default"](e,t,""):b["default"].isBoolean(n)?new h["default"](e,t):null};t["default"]=g},function(e,t){"use strict";function n(e){setTimeout(e,1e3/60)}t.__esModule=!0,t["default"]=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||n},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}t.__esModule=!0;var r=n(9),a=o(r),l=n(5),s=o(l),u=function(){function e(){i(this,e),this.backgroundElement=document.createElement("div"),s["default"].extend(this.backgroundElement.style,{backgroundColor:"rgba(0,0,0,0.8)",top:0,left:0,display:"none",zIndex:"1000",opacity:0,WebkitTransition:"opacity 0.2s linear",transition:"opacity 0.2s linear"}),a["default"].makeFullscreen(this.backgroundElement),this.backgroundElement.style.position="fixed",this.domElement=document.createElement("div"),s["default"].extend(this.domElement.style,{position:"fixed",display:"none",zIndex:"1001",opacity:0,WebkitTransition:"-webkit-transform 0.2s ease-out, opacity 0.2s linear",transition:"transform 0.2s ease-out, opacity 0.2s linear"}),document.body.appendChild(this.backgroundElement),document.body.appendChild(this.domElement);var t=this;a["default"].bind(this.backgroundElement,"click",function(){t.hide()})}return e.prototype.show=function(){var e=this;this.backgroundElement.style.display="block",this.domElement.style.display="block",this.domElement.style.opacity=0,this.domElement.style.webkitTransform="scale(1.1)",this.layout(),s["default"].defer(function(){e.backgroundElement.style.opacity=1,e.domElement.style.opacity=1,e.domElement.style.webkitTransform="scale(1)"})},e.prototype.hide=function t(){var e=this,t=function n(){e.domElement.style.display="none",e.backgroundElement.style.display="none",a["default"].unbind(e.domElement,"webkitTransitionEnd",n),a["default"].unbind(e.domElement,"transitionend",n),a["default"].unbind(e.domElement,"oTransitionEnd",n)};a["default"].bind(this.domElement,"webkitTransitionEnd",t),a["default"].bind(this.domElement,"transitionend",t),a["default"].bind(this.domElement,"oTransitionEnd",t),this.backgroundElement.style.opacity=0,this.domElement.style.opacity=0,this.domElement.style.webkitTransform="scale(1.1)"},e.prototype.layout=function(){this.domElement.style.left=window.innerWidth/2-a["default"].getWidth(this.domElement)/2+"px",this.domElement.style.top=window.innerHeight/2-a["default"].getHeight(this.domElement)/2+"px"},e}();t["default"]=u},function(e,t,n){t=e.exports=n(24)(),t.push([e.id,".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity .1s linear;transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1!important}.dg.main .close-button.drag,.dg.main:hover .close-button{opacity:1}.dg.main .close-button{-webkit-transition:opacity .1s linear;transition:opacity .1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save>ul{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height .1s ease-out;transition:height .1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid transparent}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.boolean,.dg .cr.boolean *,.dg .cr.function,.dg .cr.function *,.dg .cr.function .property-name{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco,monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px Lucida Grande,sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid hsla(0,0%,100%,.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.boolean:hover,.dg .cr.function:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}",""])},function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S), +a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function _a(a,b,c,d,e){return new _a.prototype.init(a,b,c,d,e)}r.Tween=_a,_a.prototype={constructor:_a,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=_a.propHooks[this.prop];return a&&a.get?a.get(this):_a.propHooks._default.get(this)},run:function(a){var b,c=_a.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):_a.propHooks._default.set(this),this}},_a.prototype.init.prototype=_a.prototype,_a.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},_a.propHooks.scrollTop=_a.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=_a.prototype.init,r.fx.step={};var ab,bb,cb=/^(?:toggle|show|hide)$/,db=/queueHooks$/;function eb(){bb&&(d.hidden===!1&&a.requestAnimationFrame?a.requestAnimationFrame(eb):a.setTimeout(eb,r.fx.interval),r.fx.tick())}function fb(){return a.setTimeout(function(){ab=void 0}),ab=r.now()}function gb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ca[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function hb(a,b,c){for(var d,e=(kb.tweeners[b]||[]).concat(kb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?lb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b), +null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),lb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=mb[b]||r.find.attr;mb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=mb[g],mb[g]=e,e=null!=c(a,b,d)?g:null,mb[g]=f),e}});var nb=/^(?:input|select|textarea|button)$/i,ob=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):nb.test(a.nodeName)||ob.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function pb(a){var b=a.match(L)||[];return b.join(" ")}function qb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,qb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,qb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,qb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=qb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+pb(qb(c))+" ").indexOf(b)>-1)return!0;return!1}});var rb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:pb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!sb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,sb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var tb=a.location,ub=r.now(),vb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}});var Bb=/%20/g,Cb=/#.*$/,Db=/([?&])_=[^&]*/,Eb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Fb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Gb=/^(?:GET|HEAD)$/,Hb=/^\/\//,Ib={},Jb={},Kb="*/".concat("*"),Lb=d.createElement("a");Lb.href=tb.href;function Mb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(L)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nb(a,b,c,d){var e={},f=a===Jb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ob(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Pb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Qb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:tb.href,type:"GET",isLocal:Fb.test(tb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ob(Ob(a,r.ajaxSettings),b):Ob(r.ajaxSettings,a)},ajaxPrefilter:Mb(Ib),ajaxTransport:Mb(Jb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Eb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||tb.href)+"").replace(Hb,tb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(L)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Lb.protocol+"//"+Lb.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Nb(Ib,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Gb.test(o.type),f=o.url.replace(Cb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(Bb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(vb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Db,"$1"),n=(vb.test(f)?"&":"?")+"_="+ub++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Kb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Nb(Jb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Pb(o,y,d)),v=Qb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Rb={0:200,1223:204},Sb=r.ajaxSettings.xhr();o.cors=!!Sb&&"withCredentials"in Sb,o.ajax=Sb=!!Sb,r.ajaxTransport(function(b){var c,d;if(o.cors||Sb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Rb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("