Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updates flocking demos and ColorPalette(), BorderPalette()

Adds function to get objects to flock around mouse when users
click and hold on flocking demos. Adds id property to ColorPalette()
and BorderPalette(). Updates ElementList.getAllByAttribute() to accept
a 0 value.

Increments build version to 0.0.7
  • Loading branch information...
commit 841c65d40193af407280e43888bb6362b9b6dd31 1 parent c7cfa2a
Vince Allen vinceallen authored
6 README.markdown
View
@@ -532,3 +532,9 @@ The following examples implement advanced functions of FloraJS.
* fixed avoidEdges()
* added default value for Element.viewArgs
+0.0.7
+* updated ElementList.getAllByAttribute() to accept 0 as a value
+* added id property to ColorPalette();
+* added id property to BorderPalette();
+* updated flocking demos
+
2  build.properties
View
@@ -1,6 +1,6 @@
projectName = FloraJS
buildName = flora
-version = 0.0.6
+version = 0.0.7
src.dir = ./src
build.dir = ./build
examples.dir = ./examples
2  build.xml
View
@@ -460,6 +460,8 @@
<copy file="${dev.dir}/flap.html" tofile="${public.dir}/flap.html" overwrite="true"/>
<copy file="${dev.dir}/js/spin.js" tofile="${public.dir}/js/spin.js" overwrite="true"/>
<copy file="${dev.dir}/spin.html" tofile="${public.dir}/spin.html" overwrite="true"/>
+ <copy file="${dev.dir}/js/roll.js" tofile="${public.dir}/js/roll.js" overwrite="true"/>
+ <copy file="${dev.dir}/roll.html" tofile="${public.dir}/roll.html" overwrite="true"/>
<copy file="${dev.dir}/js/particles1_CURIOUS.js" tofile="${public.dir}/js/particles1_CURIOUS.js" overwrite="true"/>
<copy file="${dev.dir}/particles1_CURIOUS.html" tofile="${public.dir}/particles1_CURIOUS.html" overwrite="true"/>
5,315 build/backup/flora.0.0.7.js
View
5,315 additions, 0 deletions not shown
146 build/backup/flora.min.0.0.7.js
View
@@ -0,0 +1,146 @@
+/*
+FloraJS
+Copyright (c) 2012 Vince Allen
+Brooklyn, NY 11215, USA
+email: vince@vinceallen.com
+web: http://www.vinceallen.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/* Version: 0.0.7 */
+/* Simplex noise by Sean McCullough banksean@gmail.com */
+/* Build time: December 2, 2012 05:44:02 */
+var Flora={},exports=Flora;
+(function(c){function p(){this._records=[]}function w(){}function j(a,b){this.x=a||0;this.y=b||0}function s(a){this._gradients=[];this._colors=[];this.id=a||s._idCount;s._idCount+=1}function A(){}function v(a){this._borders=[];this.id=a||v._idCount;v._idCount+=1}function l(a){var b=this,a=a||{};this.isPlaying=a.isPlaying||!0;this.zSorted=!!a.zSorted;this.showStats=!!a.showStats;this.isDeviceMotion=!!a.isDeviceMotion;this._records=[];this._statsDisplay=null;c.Utils.addEvent(document.body,"mousemove",
+function(a){c.mouse.locLast=c.mouse.loc.clone();a.pageX&&a.pageY?c.mouse.loc=new c.Vector(a.pageX,a.pageY):a.clientX&&a.clientY&&(c.mouse.loc=new c.Vector(a.clientX,a.clientY))});c.Utils.addEvent(document,"keyup",function(a){a.keyCode===c.config.keyMap.pause?b.pauseSystem():a.keyCode===c.config.keyMap.reset?b.resetSystem():a.keyCode===c.config.keyMap.stats&&b.toggleStats()});c.Utils.addEvent(document,"touchstart",function(a){a=a.touches;2===a.length?b.toggleStats():3===a.length?b.pauseSystem():4===
+a.length&&b.resetSystem()});c.Utils.addEvent(document.body,"keydown",function(a){var b,f=c.elementList.all(),h,g,i,k;switch(a.keyCode){case c.config.keyMap.thrustLeft:a=0;for(b=f.length;a<b;a++)f[a].keyControl&&(h=f[a],i=h.world.width/2,k=c.Utils.degreesToRadians(h.angle-h.turningRadius),g=i*Math.cos(k),i*=Math.sin(k),g=c.Vector.VectorAdd(new c.Vector(g,i),h.location),g=c.Vector.VectorSub(g,h.location),g.normalize(),g.mult(2*h.velocity.mag()),g=c.Vector.VectorSub(g,h.velocity),h.applyForce(g));break;
+case c.config.keyMap.thrustUp:a=0;for(b=f.length;a<b;a++)f[a].keyControl&&(h=f[a],i=h.world.width/2,k=c.Utils.degreesToRadians(h.angle),g=i*Math.cos(k),i*=Math.sin(k),g=new c.Vector(g,i),g.normalize(),g.mult(h.thrust),g.limit(h.maxSpeed),f[a].applyForce(g));break;case c.config.keyMap.thrustRight:a=0;for(b=f.length;a<b;a++)f[a].keyControl&&(h=f[a],i=h.world.width/2,k=c.Utils.degreesToRadians(h.angle+h.turningRadius),g=i*Math.cos(k),i*=Math.sin(k),g=c.Vector.VectorAdd(new c.Vector(g,i),h.location),
+g=c.Vector.VectorSub(g,h.location),g.normalize(),g.mult(2*h.velocity.mag()),g=c.Vector.VectorSub(g,h.velocity),f[a].applyForce(g));break;case c.config.keyMap.thrustDown:a=0;for(b=f.length;a<b;a++)f[a].keyControl&&f[a].velocity.mult(0.5)}});c.System.supportedFeatures.touch&&this.isDeviceMotion&&this.addDeviceMotionEventListener();this.showStats&&this.createStats()}function t(a){var b=this,a=a||{},e=c.Utils.getWindowSize();this.isStatic=a.isStatic||!0;this.clock=a.clock||0;this.c=a.c||0.01;this.gravity=
+a.gravity||new c.Vector(0,1);this.wind=a.wind||new c.Vector;this.location=a.location||new c.Vector;this.scale=a.scale||1;this.angle=a.angle||0;this.opacity=a.opacity||1;this.colorMode=a.colorMode||"rgb";this.color=a.color||[0,0,0];this.borderWidth=a.borderWidth||0;this.borderStyle=a.borderStyle||"none";this.borderColor=a.borderColor||null;this.borderRadius=a.borderRadius||0;this.boxShadow=a.boxShadow||0;this.zIndex=0;this.beforeStep=a.beforeStep||void 0;this.afterStep=a.afterStep||void 0;a.el?(this.el=
+a.el,this.id=this.el.id,this.width=this.el.offsetWidth,this.height=this.el.offsetHeight):(this.el=document.body,this.width=e.width,this.height=e.height,this.id=t.name+"-"+t._idCount);this.el.className="world floraElement";this.el.style.width=this.width+"px";this.el.style.height=this.height+"px";t._idCount+=1;c.Utils.addEvent(window,"resize",function(){b.resize.call(b)})}function V(a){a=a||{};this.location=a.location||new c.Vector(0,0);this.controlObj=a.controlObj||null}function m(a){var b,e,d,f;b=
+0;for(e=arguments.length;b<e;b+=1)for(d in f=arguments[b],f)f.hasOwnProperty(d)&&(this[d]=f[d]);b=a||{};e=c.elementList.all()||[];d=c.liquids||[];f=c.repellers||[];var h=c.attractors||[],g=c.heats||[],i=c.colds||[],k=c.predators||[],j=c.lights||[],r=c.oxygen||[],q=c.food||[],o,l=this.name||"anon";o=b.viewArgs||[];this.id=b.id||l.toLowerCase()+"-"+m._idCount;this.el=b.view&&"function"===c.Interface.getDataType(b.view)?b.view.apply(this,o):"object"===c.Interface.getDataType(b.view)?b.view:document.createElement("div");
+o=this.world=b.world||c.universe.first();this.location=b.location||new c.Vector(o.width/2,o.height/2);this.acceleration=b.acceleration||new c.Vector;this.velocity=b.velocity||new c.Vector;this.width=0===b.width?0:b.width||20;this.height=0===b.height?0:b.height||20;this.scale=0===b.scale?0:b.scale||1;this.angle=b.angle||0;this.opacity=0===b.opacity?0:b.opacity||0.85;this.colorMode=b.colorMode||"rgb";this.color=b.color||null;this.zIndex=0===b.zIndex?0:b.zIndex||1;this.borderWidth=b.borderWidth||null;
+this.borderStyle=b.borderStyle||null;this.borderColor=b.borderColor||null;this.borderRadius=b.borderRadius||null;this.boxShadow=b.boxShadow||null;this.zeroForceVector=new c.Vector;this.applyForceVector=new c.Vector;this.followDesiredVelocity=new c.Vector;this.followTargetVector=new c.Vector;this.separateSumForceVector=new c.Vector;this.alignSumForceVector=new c.Vector;this.cohesionSumForceVector=new c.Vector;this.checkCameraEdgesVector=new c.Vector;this.getLocationVector=new c.Vector;this.getVelocityVector=
+new c.Vector;this.cameraDiffVector=new c.Vector;this.sensors=b.sensors||[];this.className=b.className||l.toLowerCase();this.className+=" floraElement";e.push(this);this.el.id=this.id;this.el.className=0<this.sensors.length?this.className+" hasSensor":this.className;this.el.style.display="none";o.el&&o.el.appendChild(this.el);m._idCount+=1;-1!==this.className.search("liquid")?d.push(this):-1!==this.className.search("repeller")?f.push(this):-1!==this.className.search("attractor")?h.push(this):-1!==
+this.className.search("heat")?g.push(this):-1!==this.className.search("cold")?i.push(this):-1!==this.className.search("predator")?k.push(this):-1!==this.className.search("light")?j.push(this):-1!==this.className.search("oxygen")?r.push(this):-1!==this.className.search("food")&&q.push(this);if(this.controlCamera=!!b.controlCamera)c.camera.controlObj=this,o.location.x=-o.width/2+c.Utils.getWindowSize().width/2+(o.width/2-this.location.x),o.location.y=-o.height/2+c.Utils.getWindowSize().height/2+(o.height/
+2-this.location.y)}function n(a){a=a||{};c.Element.call(this,a);this.mass=a.mass||10;this.maxSpeed=0===a.maxSpeed?0:a.maxSpeed||10;this.minSpeed=a.minSpeed||0;this.motorSpeed=a.motorSpeed||0;this.lifespan=0===a.lifespan?0:a.lifespan||-1;this.offsetDistance=0===a.offsetDistance?0:a.offsetDistance||30;this.offsetAngle=a.offsetAngle||0;this.pointToDirection=!1===a.pointToDirection?!1:a.pointToDirection||!0;this.followMouse=!!a.followMouse;this.seekTarget=a.seekTarget||null;this.followTarget=a.followTarget||
+null;this.isStatic=!!a.isStatic;this.draggable=!!a.draggable;this.checkEdges=!1===a.checkEdges?!1:a.checkEdges||!0;this.wrapEdges=!!a.wrapEdges;this.avoidEdges=!!a.avoidEdges;this.avoidEdgesStrength=0===a.avoidEdgesStrength?0:a.avoidEdgesStrength||200;this.bounciness=0===a.bounciness?0:a.bounciness||0.75;this.maxSteeringForce=0===a.maxSteeringForce?0:a.maxSteeringForce||100;this.turningRadius=0===a.turningRadius?0:a.turningRadius||90;this.thrust=0===a.thrust?0:a.thrust||5;this.flocking=!!a.flocking;
+this.desiredSeparation=0===a.desiredSeparation?0:a.desiredSeparation||2*this.width;this.separateStrength=0===a.separateStrength?0:a.separateStrength||0.3;this.alignStrength=0===a.alignStrength?0:a.alignStrength||0.2;this.cohesionStrength=0===a.cohesionStrength?0:a.cohesionStrength||0.1;this.flowField=a.flowField||null;this.beforeStep=a.beforeStep||void 0;this.afterStep=a.afterStep||void 0;var b=this,a=function(a){c.Element.mouseover(a,b)},e,d=this;e=function(a){c.Element.mousedown(a,d)};var f,h=this;
+f=function(a){c.Element.mousemove(a,h)};var g,i=this;g=function(a){c.Element.mouseup(a,i)};var k,j=this;k=function(a){c.Element.mouseout(a,j)};this.draggable&&(c.Utils.addEvent(this.el,"mouseover",a),c.Utils.addEvent(this.el,"mousedown",e),c.Utils.addEvent(this.el,"mousemove",f),c.Utils.addEvent(this.el,"mouseup",g),c.Utils.addEvent(this.el,"mouseout",k))}function B(a){a=a||{};c.Agent.call(this,a);this.isPerlin=!1===a.isPerlin?!1:a.isPerlin||!0;this.remainsOnScreen=!!a.remainsOnScreen;this.perlinSpeed=
+a.perlinSpeed||0.0050;this.perlinTime=a.perlinTime||0;this.perlinAccelLow=a.perlinAccelLow||-0.075;this.perlinAccelHigh=a.perlinAccelHigh||0.075;this.offsetX=a.offsetX||1E4*Math.random();this.offsetY=a.offsetY||1E4*Math.random();this.isRandom=!!a.isRandom;this.randomRadius=a.randomRadius||100;this.width=0===a.width?0:a.width||10;this.height=0===a.height?0:a.height||10;this.maxSpeed=0===a.maxSpeed?0:a.maxSpeed||30;this.wrapEdges=!!a.wrapEdges;this.isStatic=!!a.isStatic}function C(a){a=a||{};c.Agent.call(this,
+a);this.initialLocation=a.initialLocation||new c.Vector(this.world.width/2,this.world.height/2);this.lastLocation=new c.Vector(0,0);this.width=0===a.width?0:a.width||10;this.height=0===a.height?0:a.height||10;this.amplitude=a.amplitude||new c.Vector(this.world.width/2-this.width,this.world.height/2-this.height);this.acceleration=a.acceleration||new c.Vector(0.01,0);this.aVelocity=new c.Vector(0,0);this.isStatic=!!a.isStatic;this.isPerlin=!!a.isPerlin;this.perlinSpeed=a.perlinSpeed||0.0050;this.perlinTime=
+a.perlinTime||0;this.perlinAccelLow=a.perlinAccelLow||-2;this.perlinAccelHigh=a.perlinAccelHigh||2;this.perlinOffsetX=a.perlinOffsetX||1E4*Math.random();this.perlinOffsetY=a.perlinOffsetY||1E4*Math.random()}function D(a){a=a||{};c.Agent.call(this,a);this.lifespan=a.lifespan||40;this.borderRadius=a.borderRadius||"100%"}function G(a){var a=a||{},b=c.defaultColors.getColor("heat"),e=c.defaultColors.getColor("food"),d=new c.ColorPalette;c.Agent.call(this,a);d.addColor({min:12,max:24,startColor:b.startColor,
+endColor:b.endColor}).addColor({min:12,max:24,startColor:e.startColor,endColor:e.endColor});this.beforeStep=function(){var a;if(0===this.world.clock%this.burstRate)for(a=0;a<this.burst;a+=1)new c.Particle(this.particle());0<this.lifespan?this.lifespan-=1:0===this.lifespan&&c.elementList.destroyElement(this.id)};this.lifespan=a.lifespan||-1;this.width=0===a.width?0:a.width||0;this.height=0===a.height?0:a.height||0;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.burst=0===a.burst?0:a.burst||1;
+this.burstRate=0===a.burstRate?0:a.burstRate||3;this.particle=a.particle||function(){var a=c.config.borderStyles,a=a[c.Utils.getRandomNumber(0,a.length-1)];return{color:d.getColor(),borderWidth:c.Utils.getRandomNumber(2,12),borderStyle:a,borderColor:d.getColor(),boxShadow:"0 0 0 "+c.Utils.getRandomNumber(2,6)+"px rgb("+d.getColor().toString()+")",zIndex:c.Utils.getRandomNumber(1,100),location:this.getLocation(),acceleration:new c.Vector(c.Utils.getRandomNumber(-4,4),c.Utils.getRandomNumber(-4,4))}}}
+function H(a){a=a||{};c.Agent.call(this,a);this.c=0===a.c?0:a.c||1;this.mass=0===a.mass?0:a.mass||50;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||100;this.height=0===a.height?0:a.height||100;this.opacity=0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||10}function I(a){a=a||{};c.Agent.call(this,a);this.G=0===a.G?0:a.G||10;this.mass=0===a.mass?0:a.mass||100;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||100;
+this.height=0===a.height?0:a.height||100;this.opacity=0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||10}function J(a){a=a||{};c.Agent.call(this,a);this.G=0===a.G?0:a.G||-10;this.mass=0===a.mass?0:a.mass||100;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||100;this.height=0===a.height?0:a.height||100;this.opacity=0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||10}function K(a){a=a||{};c.Agent.call(this,a);this.mass=0===a.mass?
+0:a.mass||50;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||50;this.height=0===a.height?0:a.height||50;this.opacity=0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||10}function L(a){a=a||{};c.Agent.call(this,a);this.mass=0===a.mass?0:a.mass||50;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||50;this.height=0===a.height?0:a.height||50;this.opacity=0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||
+10}function M(a){a=a||{};c.Agent.call(this,a);this.mass=0===a.mass?0:a.mass||50;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||50;this.height=0===a.height?0:a.height||50;this.opacity=0===a.opacity?0:a.opacity||0.85;this.zIndex=0===a.zIndex?0:a.zIndex||10}function N(a){a=a||{};c.Agent.call(this,a);this.mass=0===a.mass?0:a.mass||50;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||50;this.height=0===a.height?0:a.height||50;this.opacity=
+0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||10}function O(a){a=a||{};c.Agent.call(this,a);this.mass=0===a.mass?0:a.mass||50;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?0:a.width||50;this.height=0===a.height?0:a.height||50;this.opacity=0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||10}function P(a){a=a||{};c.Agent.call(this,a);this.mass=0===a.mass?0:a.mass||50;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.width=0===a.width?
+0:a.width||75;this.height=0===a.height?0:a.height||75;this.opacity=0===a.opacity?0:a.opacity||0.75;this.zIndex=0===a.zIndex?0:a.zIndex||10}function x(a){a=a||{};c.Agent.call(this,a);this.type=a.type||"";this.behavior=a.behavior||"LOVE";this.sensitivity=0===a.sensitivity?0:a.sensitivity||2;this.width=0===a.width?0:a.width||7;this.height=0===a.height?0:a.height||7;this.offsetDistance=0===a.offsetDistance?0:a.offsetDistance||30;this.offsetAngle=a.offsetAngle||0;this.opacity=0===a.opacity?0:a.opacity||
+0.75;this.target=a.target||null;this.activated=!!a.activated;this.activatedColor=a.activatedColor||[200,200,200]}function W(a){var b,e;if(c.Interface.checkRequiredParams(a,{location:"object",scale:"number",angle:"number",opacity:"number",width:"number",height:"number",colorMode:"string",color:"array"}))return b=document.createElement("div"),e=document.createElement("div"),b.className="flowFieldMarker floraElement",e.className="nose",b.appendChild(e),b.style.cssText=c.Utils.getCSSText({x:a.location.x-
+a.width/2,y:a.location.y-a.height/2,s:a.scale,a:a.angle,o:a.opacity,w:a.width,h:a.height,cm:a.colorMode,color:a.color,z:a.zIndex,borderWidth:a.borderWidth,borderStyle:a.borderStyle,borderColor:a.borderColor,borderRadius:a.borderRadius,boxShadow:a.boxShadow}),b}function Q(a){a=a||{};this.resolution=a.resolution||50;this.perlinSpeed=a.perlinSpeed||0.01;this.perlinTime=a.perlinTime||100;this.field=a.field||null;this.createMarkers=a.createMarkers||!1;this.world=a.world||c.universe.first()}function E(a,
+b,e){e=e||{};c.Agent.call(this,e);if(!a||!b)throw Error("Connector: both parentA and parentB are required.");this.parentA=a;this.parentB=b;this.height=this.width=0;this.color="transparent";this.opacity=0===e.opacity?0:e.opacity||1;this.zIndex=e.zIndex||0}function R(a){a=a||{};c.Agent.call(this,a);this.width=0===a.width?0:a.width||10;this.height=0===a.height?0:a.height||10;this.opacity=0===a.opacity?0:a.opacity||0.5;this.isStatic=!1===a.isStatic?!1:a.isStatic||!0;this.zIndex=0===a.zIndex?0:a.zIndex||
+0;this.offsetAngle=a.offsetAngle||0;this.length=0===a.length?0:a.length||30}function S(a){a=a||{};this.world=a.world||c.universe.first();this.position=a.position||"top left";this.text=a.text||"";this.opacity=0===a.opacity?0:a.opacity||0.75;this.color=a.color||[255,255,255];this.borderWidth=a.borderWidth||"1px";this.borderStyle=a.borderStyle||"solid";this.borderColor=a.borderColor||[204,204,204];this.colorMode=a.colorMode||"rgb";this._el=document.createElement("div");this._el.id="caption";this._el.className=
+"caption "+this.position;this._el.style.opacity=this.opacity;this._el.style.color=this.colorMode+"("+this.color[0]+", "+this.color[1]+", "+this.color[2]+")";this._el.style.borderWidth=this.borderWidth;this._el.style.borderStyle=this.borderStyle;this._el.style.borderColor="string"===typeof this.borderColor?this.borderColor:this.colorMode+"("+this.borderColor[0]+", "+this.borderColor[1]+", "+this.borderColor[2]+")";this._el.appendChild(document.createTextNode(this.text));document.getElementById("caption")&&
+document.getElementById("caption").parentNode.removeChild(document.getElementById("caption"));this.world.el.appendChild(this._el)}function T(a){var b=this,a=a||{};this.world=a.world||c.universe.first();this.position=a.position||"top left";this.opacity=0===a.opacity?0:a.opacity||0.75;this.color=a.color||[255,255,255];this.borderWidth=a.borderWidth||"1px";this.borderStyle=a.borderStyle||"solid";this.borderColor=a.borderColor||[204,204,204];this.colorMode=a.colorMode||"rgb";this.text=c.System.supportedFeatures.touch?
+c.config.touchMap.stats+"-finger tap = stats | "+c.config.touchMap.pause+"-finger tap = pause | "+c.config.touchMap.reset+"-finger tap = reset":"'"+String.fromCharCode(c.config.keyMap.pause).toLowerCase()+"' = pause | '"+String.fromCharCode(c.config.keyMap.reset).toLowerCase()+"' = reset | '"+String.fromCharCode(c.config.keyMap.stats).toLowerCase()+"' = stats";this._el=document.createElement("div");this._el.id="inputMenu";this._el.className="inputMenu "+this.position;this._el.style.opacity=this.opacity;
+this._el.style.color=this.colorMode+"("+this.color[0]+", "+this.color[1]+", "+this.color[2]+")";this._el.style.borderWidth=this.borderWidth;this._el.style.borderStyle=this.borderStyle;this._el.style.borderColor="string"===typeof this.borderColor?this.borderColor:this.colorMode+"("+this.borderColor[0]+", "+this.borderColor[1]+", "+this.borderColor[2]+")";this._el.appendChild(document.createTextNode(this.text));document.getElementById("inputMenu")&&document.getElementById("inputMenu").parentNode.removeChild(document.getElementById("inputMenu"));
+c.System.supportedFeatures.touch?c.Utils.addEvent(this._el,"touchstart",function(){b.destroy()}):c.Utils.addEvent(this._el,"mouseup",function(){b.destroy()});this.world.el.appendChild(this._el)}function F(){var a,b;this._fps=0;this._timeLastSecond=this._timeLastFrame=this._time=Date.now?Date.now():0;this._frameCount=0;this._el=document.createElement("div");this._el.id="statsDisplay";this._el.className="statsDisplay";this._el.style.color="white";this._fpsValue=this._totalElementsValue=null;a=document.createElement("span");
+a.className="statsDisplayLabel";b=document.createTextNode("trans3d: ");a.appendChild(b);this._el.appendChild(a);this._3dTransformsValue=document.createTextNode(c.System.supportedFeatures.csstransforms3d);this._el.appendChild(this._3dTransformsValue);a=document.createElement("span");a.className="statsDisplayLabel";b=document.createTextNode("total elements: ");a.appendChild(b);this._el.appendChild(a);this._totalElementsValue=document.createTextNode("0");this._el.appendChild(this._totalElementsValue);
+a=document.createElement("span");a.className="statsDisplayLabel";b=document.createTextNode("fps: ");a.appendChild(b);this._el.appendChild(a);this._fpsValue=document.createTextNode("0");this._el.appendChild(this._fpsValue);document.body.appendChild(this._el);this._update(this)}function y(){}window.requestAnimFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,
+1E3/60)};c.config={borderStyles:"none solid dotted dashed double inset outset groove ridge".split(" "),defaultColorList:[{name:"heat",startColor:[255,132,86],endColor:[175,47,0]},{name:"cold",startColor:[88,129,135],endColor:[171,244,255]},{name:"food",startColor:[186,255,130],endColor:[84,187,0]},{name:"oxygen",startColor:[109,215,255],endColor:[0,140,192]},{name:"light",startColor:[255,227,127],endColor:[189,148,0]}],keyMap:{pause:80,reset:82,stats:83,thrustLeft:37,thrustUp:38,thrustRight:39,thrustDown:40},
+touchMap:{stats:2,pause:3,reset:4}};p.prototype.name="ElementList";p.prototype.add=function(a){this._records.push(a);return this._records};p.prototype.all=function(){return this._records};p.prototype.count=function(){return this._records.length};p.prototype.getAllByName=function(a){var b,c,d=[];b=0;for(c=this._records.length;b<c;b++)this._records[b].name===a&&(d[d.length]=this._records[b]);return d};p.prototype.getAllByAttribute=function(a,b){var c,d,f=[],h=void 0!==b?b:null;c=0;for(d=this._records.length;c<
+d;c++)void 0!==this._records[c][a]&&!(null!==h&&this._records[c][a]!==h)&&(f[f.length]=this._records[c]);return f};p.prototype.updatePropsByName=function(a,b){var c,d,f,h=this.getAllByName(a);c=0;for(d=h.length;c<d;c++)for(f in b)b.hasOwnProperty(f)&&(h[c][f]=b[f]);return h};p.prototype.getElement=function(a){var b,c,d=this._records;b=0;for(c=d.length;b<c;b+=1)if(d[b].id===a)return d[b]};p.prototype.destroyElement=function(a){var b,c,d=this._records;b=0;for(c=d.length;b<c;b+=1)if(d[b].id===a){d[b].world.el.removeChild(d[b].el);
+d.splice(b,1);break}};p.prototype.destroyAll=function(){var a,b=this._records;for(a=b.length-1;0<=a;a-=1)b[a].world&&b[a].world.el.removeChild(b[a].el);this._records=[]};p.prototype.destroyByWorld=function(a){var b,c=this._records;for(b=c.length-1;0<=b;b-=1)c[b].world&&c[b].world===a&&(c[b].world.el.removeChild(c[b].el),c.splice(b,1))};c.ElementList=p;w.name="System";w.setup=null;w.start=function(a,b,e){var d=c.config.defaultColorList;this.universeOptions=b||null;this.worlds=e||null;this._featureDetector=
+new c.FeatureDetector;this.supportedFeatures={};this.supportedFeatures.csstransforms=this._featureDetector.detect("csstransforms");this.supportedFeatures.csstransforms3d=this._featureDetector.detect("csstransforms3d");this.supportedFeatures.touch=this._featureDetector.detect("touch");c.liquids=[];c.repellers=[];c.attractors=[];c.heats=[];c.colds=[];c.lights=[];c.oxygen=[];c.food=[];c.predators=[];c.mouse={loc:new c.Vector,locLast:new c.Vector};c.elementList=new c.ElementList;c.universe=new c.Universe(this.universeOptions);
+if("array"===c.Interface.getDataType(this.worlds)){b=0;for(e=this.worlds.length;b<e;b+=1)c.universe.addWorld({el:this.worlds[b]})}else c.universe.addWorld();c.camera=new c.Camera;c.defaultColors=new c.ColorTable;b=0;for(e=d.length;b<e;b++)c.defaultColors.addColor({name:d[b].name,startColor:d[b].startColor,endColor:d[b].endColor});c.animLoop=function(){var a;a=c.universe;var b=c.elementList.all();if(a.isPlaying){window.requestAnimFrame(c.animLoop);a.zSorted&&(b=b.sort(function(a,b){return b.zIndex-
+a.zIndex}));for(a=b.length-1;0<=a;a-=1)b[a].step();for(a=b.length-1;0<=a;a-=1)b[a]&&b[a].draw();c.universe.updateClocks()}};a="function"===c.Interface.getDataType(a)?a:function(){};w.setup=a;a();c.animLoop()};w.destroy=function(){c.elementList.destroyAll()};c.System=w;c.Utils={extend:function(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a},map:function(a,b,c,d,f){return(a-b)/(c-b)*(f-d)+d},getRandomNumber:function(a,b,c){return c?Math.random()*(b-(a-1))+a:Math.floor(Math.random()*
+(b-(a-1)))+a},degreesToRadians:function(a){if("undefined"!==typeof a)return 2*Math.PI*(a/360);"undefined"!==typeof console&&console.log("Error: Utils.degreesToRadians is missing degrees param.");return!1},radiansToDegrees:function(a){if("undefined"!==typeof a)return a*(180/Math.PI);"undefined"!==typeof console&&console.log("Error: Utils.radiansToDegrees is missing radians param.");return!1},constrain:function(a,b,c){return a>c?c:a<b?b:a},clone:function(a){function b(){}b.prototype=a;return new b},
+addEvent:function(a,b,c){a.addEventListener?this.addEventHandler=function(a,b,c){a.addEventListener(b,c,!1)}:a.attachEvent&&(this.addEventHandler=function(a,b,c){a.attachEvent("on"+b,c)});this.addEventHandler(a,b,c)},log:function(a){"undefined"!==typeof console&&"undefined"!==typeof console.log?(this.log=function(a){console.log(a)},this.log.call(this,a)):this.log=function(){}},getWindowSize:function(){var a={width:!1,height:!1};"undefined"!==typeof window.innerWidth?a.width=window.innerWidth:"undefined"!==
+typeof document.documentElement&&"undefined"!==typeof document.documentElement.clientWidth?a.width=document.documentElement.clientWidth:"undefined"!==typeof document.body&&(a.width=document.body.clientWidth);"undefined"!==typeof window.innerHeight?a.height=window.innerHeight:"undefined"!==typeof document.documentElement&&"undefined"!==typeof document.documentElement.clientHeight?a.height=document.documentElement.clientHeight:"undefined"!==typeof document.body&&(a.height=document.body.clientHeight);
+return a},getCSSText:function(a){var b="",e="number"===typeof a.w?a.w+"px":a.w,d="number"===typeof a.h?a.h+"px":a.h;a.color?a.background=a.cm+"("+a.color[0]+", "+a.color[1]+", "+a.color[2]+")":(a.color=[],a.background=null);a.borderColor?a.borderColorStr=a.cm+"("+a.borderColor[0]+", "+a.borderColor[1]+", "+a.borderColor[2]+")":(a.borderColor=[],a.borderColorStr="");b=c.System.supportedFeatures.csstransforms3d?["-webkit-transform: translate3d("+a.x+"px, "+a.y+"px, 0) rotate("+a.a+"deg) scaleX("+a.s+
+") scaleY("+a.s+")","-moz-transform: translate3d("+a.x+"px, "+a.y+"px, 0) rotate("+a.a+"deg) scaleX("+a.s+") scaleY("+a.s+")","-o-transform: translate3d("+a.x+"px, "+a.y+"px, 0) rotate("+a.a+"deg) scaleX("+a.s+") scaleY("+a.s+")","-ms-transform: translate3d("+a.x+"px, "+a.y+"px, 0) rotate("+a.a+"deg) scaleX("+a.s+") scaleY("+a.s+")"].join(";"):c.System.supportedFeatures.csstransforms?["-webkit-transform: translateX("+a.x+"px) translateY("+a.y+"px) rotate("+a.a+"deg) scaleX("+a.s+") scaleY("+a.s+")",
+"-moz-transform: translateX("+a.x+"px) translateY("+a.y+"px) rotate("+a.a+"deg) scaleX("+a.s+") scaleY("+a.s+")","-o-transform: translateX("+a.x+"px) translateY("+a.y+"px) rotate("+a.a+"deg) scaleX("+a.s+") scaleY("+a.s+")","-ms-transform: translateX("+a.x+"px) translateY("+a.y+"px) rotate("+a.a+"deg) scaleX("+a.s+") scaleY("+a.s+")"].join(";"):["position: absolute","left: "+a.x+"px","top: "+a.y+"px"].join(";");return[b,"opacity: "+a.o,"width: "+e,"height: "+d,"background: "+a.background,"z-index: "+
+a.z,"border-width: "+a.borderWidth+"px","border-style: "+a.borderStyle,"border-color: "+a.borderColorStr,"border-radius: "+a.borderRadius,"box-shadow: "+a.boxShadow].join(";")}};j.VectorSub=function(a,b){return new j(a.x-b.x,a.y-b.y)};j.VectorAdd=function(a,b){return new j(a.x+b.x,a.y+b.y)};j.VectorMult=function(a,b){return new j(a.x*b,a.y*b)};j.VectorDiv=function(a,b){return new j(a.x/b,a.y/b)};j.VectorDistance=function(a,b){return Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2))};j.VectorMidPoint=
+function(a,b){return j.VectorAdd(a,b).div(2)};j.VectorAngleBetween=function(a,b){var c=a.dot(b);return Math.acos(c/(a.mag()*b.mag()))};j.prototype.name="Vector";j.prototype.clone=function(){function a(){}a.prototype=this;return new a};j.prototype.add=function(a){this.x+=a.x;this.y+=a.y;return this};j.prototype.sub=function(a){this.x-=a.x;this.y-=a.y;return this};j.prototype.mult=function(a){this.x*=a;this.y*=a;return this};j.prototype.div=function(a){this.x/=a;this.y/=a;return this};j.prototype.mag=
+function(){return Math.sqrt(this.x*this.x+this.y*this.y)};j.prototype.limit=function(a){this.mag()>a&&(this.normalize(),this.mult(a));return this};j.prototype.limitLow=function(a){this.mag()<a&&(this.normalize(),this.mult(a));return this};j.prototype.normalize=function(){var a=this.mag();if(0!==a)return this.div(a)};j.prototype.distance=function(a){return Math.sqrt(Math.pow(a.x-this.x,2)+Math.pow(a.y-this.y,2))};j.prototype.rotate=function(a){var b=Math.cos(a),a=Math.sin(a),c=this.x,d=this.y;this.x=
+c*b-d*a;this.y=c*a+d*b;return this};j.prototype.midpoint=function(a){return j.VectorAdd(this,a).div(2)};j.prototype.dot=function(a){return this.z&&a.z?this.x*a.x+this.y*a.y+this.z*a.z:this.x*a.x+this.y*a.y};c.Vector=j;s._idCount=0;s.prototype.name="ColorPalette";s.prototype.addColor=function(a){var b,e;if(c.Interface.checkRequiredParams(a,{min:"number",max:"number",startColor:"array",endColor:"array"})){b=c.Utils.getRandomNumber(a.min,a.max);e=s._createColorRange(a.startColor,a.endColor,255);for(a=
+0;a<b;a++)this._colors.push(e[c.Utils.getRandomNumber(0,e.length-1)])}return this};s.prototype.createGradient=function(a){if(c.Interface.checkRequiredParams(a,{startColor:"array",endColor:"array"}))if(this.startColor=a.startColor,this.endColor=a.endColor,this.totalColors=a.totalColors||255,0<this.totalColors)this._gradients.push(s._createColorRange(this.startColor,this.endColor,this.totalColors));else throw Error("ColorPalette: total colors must be greater than zero.");};s.prototype.getColor=function(){if(0<
+this._colors.length)return this._colors[c.Utils.getRandomNumber(0,this._colors.length-1)];throw Error("ColorPalette.getColor: You must add colors via addColor() before using getColor().");};s.prototype.createSampleStrip=function(a){var b,c,d;b=0;for(c=this._colors.length;b<c;b++)d=document.createElement("div"),d.className="color-sample-strip",d.style.background="rgb("+this._colors[b].toString()+")",a.appendChild(d)};s._createColorRange=function(a,b,c){var d,f=[],h=a[0],g=a[1],a=a[2],i=b[1];d=b[2];
+var k,j,r,q,b=b[0]-h,i=i-g;k=d-a;for(d=0;d<c;d++)j=parseInt(b*d/c,10)+h,r=parseInt(i*d/c,10)+g,q=parseInt(k*d/c,10)+a,f.push([j,r,q]);return f};c.ColorPalette=s;A.prototype.addColor=function(a){c.Interface.checkRequiredParams(a,{name:"string",startColor:"array",endColor:"array"})&&(this[a.name]={startColor:a.startColor,endColor:a.endColor});return this};A.prototype.name="ColorTable";A.prototype.getColor=function(a,b,e){var d,f;if("string"===c.Interface.getDataType(a))if(this[a]){a=this[a];b&&(d=a.startColor);
+e&&(f=a.endColor);if(d&&f||!d&&!f)return{startColor:a.startColor,endColor:a.endColor};if(d)return d;if(f)return f}else throw Error("ColorTable: "+a+" does not exist. Add colors to the ColorTable via addColor().");else throw Error("ColorTable: You must pass a name (string) for the color entry in the table.");};c.ColorTable=A;v._idCount=0;v.prototype.name="BorderPalette";v.prototype.addBorder=function(a){var b,e;if(c.Interface.checkRequiredParams(a,{min:"number",max:"number",style:"string"})){e=c.Utils.getRandomNumber(a.min,
+a.max);for(b=0;b<e;b++)this._borders.push(a.style)}return this};v.prototype.getBorder=function(){if(0<this._borders.length)return this._borders[c.Utils.getRandomNumber(0,this._borders.length-1)];throw Error("BorderPalette.getBorder: You must add borders via addBorder() before using getBorder().");};c.BorderPalette=v;var z={random:function(){return 0.1}};void 0===z&&(z=Math);var u,U=[];for(u=0;256>u;u+=1)U[u]=Math.floor(256*z.random());z=[];for(u=0;512>u;u+=1)z[u]=U[u&255];c.SimplexNoise={grad3:[[1,
+1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],p:U,perm:z,simplex:[[0,1,2,3],[0,1,3,2],[0,0,0,0],[0,2,3,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,3,0],[0,2,1,3],[0,0,0,0],[0,3,1,2],[0,3,2,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,3,2,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,0,3],[0,0,0,0],[1,3,0,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,3,0,1],[2,3,1,0],[1,0,2,3],[1,0,3,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,
+3,1],[0,0,0,0],[2,1,3,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,1,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,0,1,2],[3,0,2,1],[0,0,0,0],[3,1,2,0],[2,1,0,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,1,0,2],[0,0,0,0],[3,2,0,1],[3,2,1,0]],dot:function(a,b,c){return a[0]*b+a[1]*c},noise:function(a,b){var c,d,f;f=0.5*(Math.sqrt(3)-1);f*=a+b;var h=Math.floor(a+f),g=Math.floor(b+f),i=(3-Math.sqrt(3))/6;f=(h+g)*i;c=a-(h-f);var k=b-(g-f),j,r;c>k?(j=1,r=0):(j=0,r=1);d=c-j+i;var q=
+k-r+i;f=c-1+2*i;var i=k-1+2*i,o=h&255,g=g&255,h=this.perm[o+this.perm[g]]%12;j=this.perm[o+j+this.perm[g+r]]%12;r=this.perm[o+1+this.perm[g+1]]%12;g=0.5-c*c-k*k;0>g?c=0:(g*=g,c=g*g*this.dot(this.grad3[h],c,k));k=0.5-d*d-q*q;0>k?d=0:(k*=k,d=k*k*this.dot(this.grad3[j],d,q));q=0.5-f*f-i*i;0>q?f=0:(q*=q,f=q*q*this.dot(this.grad3[r],f,i));return 70*(c+d+f)},noise3d:function(a,b,c){var d,f,h,g=(a+b+c)*(1/3),i=Math.floor(a+g),k=Math.floor(b+g),j=Math.floor(c+g),g=1/6;h=(i+k+j)*g;d=a-(i-h);f=b-(k-h);var r=
+c-(j-h),q,o,l,n,m,s;d>=f?f>=r?(q=1,l=o=0,m=n=1,s=0):(d>=r?(q=1,l=o=0):(o=q=0,l=1),n=1,m=0,s=1):f<r?(o=q=0,l=1,n=0,s=m=1):d<r?(q=0,o=1,n=l=0,s=m=1):(q=0,o=1,l=0,m=n=1,s=0);var p=d-q+g,t=f-o+g,u=r-l+g;h=d-n+2*g;var a=f-m+2*g,v=r-s+2*g,c=d-1+3*g,b=f-1+3*g,g=r-1+3*g,i=i&255,w=k&255,x=j&255,k=this.perm[i+this.perm[w+this.perm[x]]]%12,j=this.perm[i+q+this.perm[w+o+this.perm[x+l]]]%12;n=this.perm[i+n+this.perm[w+m+this.perm[x+s]]]%12;i=this.perm[i+1+this.perm[w+1+this.perm[x+1]]]%12;m=0.6-d*d-f*f-r*r;0>
+m?d=0:(m*=m,d=m*m*this.dot(this.grad3[k],d,f,r));f=0.6-p*p-t*t-u*u;0>f?f=0:(f*=f,f=f*f*this.dot(this.grad3[j],p,t,u));p=0.6-h*h-a*a-v*v;0>p?h=0:(p*=p,h=p*p*this.dot(this.grad3[n],h,a,v));a=0.6-c*c-b*b-g*g;0>a?c=0:(a*=a,c=a*a*this.dot(this.grad3[i],c,b,g));return 32*(d+f+h+c)}};c.Interface={checkRequiredParams:function(a,b,c){var d,f,h=!0;for(d in b)if(b.hasOwnProperty(d))try{if("undefined"===typeof a)throw Error("checkRequiredOptions: No options were passed.");if(!this.checkDataType(this.getDataType(a[d]),
+b[d].split("|"))||""===a[d])throw h=!1,f=""===a[d]?'checkRequiredOptions: required option "'+d+'" is empty.':"undefined"===typeof a[d]?'checkRequiredOptions: required option "'+d+'" is missing from passed options.':'checkRequiredOptions: passed option "'+d+'" must be type '+b[d]+". Passed as "+this.getDataType(a[d])+".",Error(f);}catch(g){"undefined"!==typeof console&&console.log("ERROR: "+g.message+(c?" from: "+c:""))}return h},checkDataType:function(a,b){var c,d;c=0;for(d=b.length;c<d;c++)if(a===
+b[c])return!0;return!1},getDataType:function(a){return"[object Array]"===Object.prototype.toString.call(a)?"array":"[object NodeList]"===Object.prototype.toString.call(a)?"nodeList":typeof a}};l.prototype.name="Universe";l.prototype.addWorld=function(a){this._records.push(new c.World(a||{}));c.elementList.add(this._records[this._records.length-1]);return this._records};l.prototype.first=function(){return this._records[0]?this._records[0]:null};l.prototype.last=function(){return this._records[this._records.length-
+1]?this._records[this._records.length-1]:null};l.prototype.update=function(a,b){var e,d="object"===c.Interface.getDataType(a)?a:{},f;if(b)if("string"===c.Interface.getDataType(b))f=this.getWorldById(b);else if("object"===c.Interface.getDataType(b))f=b;else{c.Utils.log("Universe: update: world param must be null, a string (an id) or reference to a world.");return}else f=this.first();for(e in d)d.hasOwnProperty(e)&&(f[e]=d[e]);d.el&&(f.width=parseInt(f.el.style.width.replace("px",""),10),f.height=parseInt(f.el.style.height.replace("px",
+""),10));c.System.supportedFeatures.touch&&d.isDeviceMotion&&this.addDeviceMotionEventListener()};l.prototype.all=function(){return this._records};l.prototype.count=function(){return this._records.length};l.prototype.getWorldById=function(a){var b,c,d=this._records;b=0;for(c=d.length;b<c;b+=1)if(d[b].id===a)return d[b];return null};l.prototype.destroyWorld=function(a){var b,e,d=this._records;b=0;for(e=d.length;b<e;b+=1)if(d[b].id===a){a=d[b].el.parentNode;d[b].el===document.body?c.elementList.destroyAll():
+(c.elementList.destroyByWorld(d[b]),a.removeChild(d[b].el));d.splice(b,1);break}};l.prototype.clearWorld=function(a){var b,e,d=this._records;b=0;for(e=d.length;b<e;b+=1)if(d[b].id===a)return c.elementList.destroyByWorld(d[b]),!0};l.prototype.destroyAll=function(){c.elementList.destroyAll();for(var a=this._records.length-1;0<=a;a-=1)this.destroyWorld(this._records[a].id)};l.prototype.updateClocks=function(){for(var a=0,b=this._records.length;a<b;a+=1)this._records[a].clock+=1};l.prototype.pauseSystem=
+function(){(this.isPlaying=!this.isPlaying)&&window.requestAnimFrame(c.animLoop);return this.isPlaying};l.prototype.resetSystem=function(){var a,b,e;e=this.all();a=0;for(b=e.length;a<b;a+=1)c.elementList.destroyByWorld(e[a]);c.System.setup();this.isPlaying||(this.isPlaying=!0,window.requestAnimFrame(c.animLoop))};l.prototype.toggleStats=function(){this._statsDisplay?this.destroyStats():this.createStats();return this._statsDisplay};l.prototype.createStats=function(){this._statsDisplay=new c.StatsDisplay};
+l.prototype.destroyStats=function(){var a=document.getElementById("statsDisplay");this._statsDisplay=null;a&&a.parentNode.removeChild(a)};l.prototype.addDeviceMotionEventListener=function(){var a=this;c.Utils.addEvent(window,"devicemotion",function(b){a.devicemotion.call(a,b)})};l.prototype.devicemotion=function(a){0===window.orientation?this.update({gravity:new c.Vector(a.accelerationIncludingGravity.x,-1*a.accelerationIncludingGravity.y)}):-90===window.orientation?this.update({gravity:new c.Vector(a.accelerationIncludingGravity.y,
+a.accelerationIncludingGravity.x)}):this.update({gravity:new c.Vector(-1*a.accelerationIncludingGravity.y,-1*a.accelerationIncludingGravity.x)})};c.Universe=l;t.prototype.name="World";t._idCount=0;t.prototype.configure=function(a){this.el=a||null||document.body;this.el.style.width=this.width+"px";this.el.style.height=this.height+"px"};t.prototype.update=function(a){var b,e,d="",a="object"===c.Interface.getDataType(a)?a:{};for(e in a)a.hasOwnProperty(e)&&(this[e]=a[e]);a.el&&(this.width=parseInt(this.el.style.width.replace("px",
+""),10),this.height=parseInt(this.el.style.height.replace("px",""),10));if(this.el.style.setAttribute){if(a.style)for(b in a.style)a.style.hasOwnProperty(b)&&(d=d+b+": "+a.style[b]+";");this.el.style.setAttribute("cssText",d,0)}else if(a.style)for(b in a.style)a.style.hasOwnProperty(b)&&(this.el.style[b]=a.style[b],d=d+b+": "+a.style[b]+";")};t.prototype.resize=function(){var a,b,e;a=c.Utils.getWindowSize();var d=a.width,f=a.height,h=c.elementList.all();a=0;for(b=h.length;a<b;a+=1)if(h[a].controlCamera){e=
+!0;break}if(!e){a=0;for(b=h.length;a<b;a+=1)e=h[a].location,e.x=d*(e.x/this.width),e.y=f*(e.y/this.height);this.el===document.body&&(this.width=d,this.height=f,this.el.style.width=this.width+"px",this.el.style.height=this.height+"px")}};t.prototype.step=function(){this.beforeStep&&this.beforeStep.apply(this);this.afterStep&&this.afterStep.apply(this)};t.prototype.draw=function(){if(c.camera.controlObj||!(this.isStatic&&0<this.clock))this.el.style.cssText=c.Utils.getCSSText({x:this.location.x,y:this.location.y,
+s:this.scale,a:this.angle,o:this.opacity,w:this.width,h:this.height,cm:this.colorMode,color:this.color,z:this.zIndex,borderWidth:this.borderWidth,borderStyle:this.borderStyle,borderColor:this.borderColor,borderRadius:this.borderRadius,boxShadow:this.boxShadow})};c.World=t;V.prototype.name="Camera";c.Camera=V;m._idCount=0;m.events=["mouseenter","mousedown","mousemove","mouseup","mouseleave"];m.prototype.name="Element";m.mouseover=function(a,b){b.isMouseOut=!1;clearInterval(b.mouseOutInterval)};m.mousedown=
+function(a,b){var c=a.target;b.isPressed=!0;b.isMouseOut=!1;b.offsetX=a.pageX-c.offsetLeft;b.offsetY=a.pageY-c.offsetTop};m.mousemove=function(a,b){var e,d;b.isPressed&&(b.isMouseOut=!1,e=a.pageX-b.world.el.offsetLeft,d=a.pageY-b.world.el.offsetTop,m.mouseIsInsideWorld(b.world)?b.location=new c.Vector(e,d):b.isPressed=!1)};m.mouseup=function(a,b){b.isPressed=!1};m.mouseout=function(a,b){var e,d;b.isPressed&&(b.isMouseOut=!0,b.mouseOutInterval=setInterval(function(){b.isPressed&&b.isMouseOut&&(e=c.mouse.loc.x-
+b.world.el.offsetLeft,d=c.mouse.loc.y-b.world.el.offsetTop,b.location=new c.Vector(e,d))},16))};m.mouseIsInsideWorld=function(a){var b=c.mouse.loc.x,e=c.mouse.loc.y;return a&&b>a.location.x&&b<a.location.x+a.width&&e>a.location.y&&e<a.location.y+a.height?!0:!1};m.prototype.step=function(){};m.prototype.draw=function(){this.el.style.cssText=c.Utils.getCSSText({x:this.location.x-("number"===typeof this.width?this.width:this.el.offsetWidth)/2,y:this.location.y-("number"===typeof this.height?this.height:
+this.el.offsetHeight)/2,s:this.scale,a:this.angle,o:this.opacity,w:this.width,h:this.height,cm:this.colorMode,color:this.color,z:this.zIndex,borderWidth:this.borderWidth,borderStyle:this.borderStyle,borderColor:this.borderColor,borderRadius:this.borderRadius,boxShadow:this.boxShadow})};c.Element=m;c.Utils.extend(n,c.Element);n.prototype.name="Agent";n.prototype.step=function(){var a,b,e,d,f,h,g,i=this.world,j=c.elementList.all();this.beforeStep&&this.beforeStep.apply(this);if(!this.isStatic&&!this.isPressed){if(0<
+c.liquids.length){a=0;for(b=c.liquids.length;a<b;a+=1)this.id!==c.liquids[a].id&&this.isInside(c.liquids[a])&&(e=this.drag(c.liquids[a]),this.applyForce(e),e=c.liquids[a].className+" activated",c.liquids[a].el.className=e)}if(0<c.repellers.length){a=0;for(b=c.repellers.length;a<b;a+=1)this.id!==c.repellers[a].id&&(e=this.attract(c.repellers[a]),this.applyForce(e))}if(0<c.attractors.length){a=0;for(b=c.attractors.length;a<b;a+=1)this.id!==c.attractors[a].id&&(e=this.attract(c.attractors[a]),this.applyForce(e))}if(0<
+this.sensors.length){a=0;for(b=this.sensors.length;a<b;a+=1)h=this.sensors[a],d=h.offsetDistance,f=c.Utils.degreesToRadians(this.angle+h.offsetAngle),e=d*Math.cos(f),d*=Math.sin(f),h.location.x=this.location.x,h.location.y=this.location.y,h.location.add(new c.Vector(e,d)),h.activated&&(this.applyForce(h.getActivationForce({agent:this})),g=!0)}!g&&this.motorSpeed&&(a=c.Utils.clone(this.velocity),a.normalize(),this.velocity.mag()>this.motorSpeed?a.mult(-this.motorSpeed):a.mult(this.motorSpeed),this.applyForce(a));
+i.c&&(a=c.Utils.clone(this.velocity),a.mult(-1),a.normalize(),a.mult(i.c),this.applyForce(a));this.applyForce(i.wind);this.applyForce(i.gravity);this.followMouse&&(a={location:new c.Vector(c.mouse.loc.x,c.mouse.loc.y)},this.applyForce(this.seek(a)));this.seekTarget&&this.applyForce(this.seek(this.seekTarget));this.flowField&&(b=this.flowField.resolution,a=Math.floor(this.location.x/b),b=Math.floor(this.location.y/b),this.flowField.field[a]&&((a=this.flowField.field[a][b])?(this.followTargetVector.x=
+a.x,this.followTargetVector.y=a.y):(this.followTargetVector.x=this.location.x,this.followTargetVector.y=this.location.y),a={location:this.followTargetVector},this.applyForce(this.follow(a))));this.flocking&&this.flock(j);this.avoidEdges&&this.checkAvoidEdges();this.velocity.add(this.acceleration);this.maxSpeed&&this.velocity.limit(this.maxSpeed);this.minSpeed&&this.velocity.limitLow(this.minSpeed);this.location.add(this.velocity);this.pointToDirection&&0.1<this.velocity.mag()&&(this.angle=c.Utils.radiansToDegrees(Math.atan2(this.velocity.y,
+this.velocity.x)));this.controlCamera&&this.checkCameraEdges();(this.checkEdges||this.wrapEdges)&&this.checkWorldEdges(i);this.parent&&(this.offsetDistance?(d=this.offsetDistance,f=c.Utils.degreesToRadians(this.parent.angle+this.offsetAngle),e=d*Math.cos(f),d*=Math.sin(f),this.location.x=this.parent.location.x,this.location.y=this.parent.location.y,this.location.add(new c.Vector(e,d))):this.location=this.parent.location);this.afterStep&&this.afterStep.apply(this);this.acceleration.mult(0);0<this.lifespan&&
+(this.lifespan-=1)}};n.prototype.applyForce=function(a){this.applyForceVector.x=a.x;this.applyForceVector.y=a.y;this.applyForceVector.div(this.mass);this.acceleration.add(this.applyForceVector)};n.prototype.seek=function(a){var b=this.world,a=c.Vector.VectorSub(a.location,this.location),e=a.mag();a.normalize();e<b.width/2?(b=c.Utils.map(e,0,b.width/2,0,this.maxSpeed),a.mult(b)):a.mult(this.maxSpeed);a.sub(this.velocity);a.limit(this.maxSteeringForce);return a};n.prototype.follow=function(a){this.followDesiredVelocity.x=
+a.location.x;this.followDesiredVelocity.y=a.location.y;this.followDesiredVelocity.mult(this.maxSpeed);this.followDesiredVelocity.sub(this.velocity);this.followDesiredVelocity.limit(this.maxSteeringForce);return this.followDesiredVelocity};n.prototype.flock=function(a){this.applyForce(this.separate(a).mult(this.separateStrength));this.applyForce(this.align(a).mult(this.alignStrength));this.applyForce(this.cohesion(a).mult(this.cohesionStrength))};n.prototype.separate=function(a){var b,e,d,f,h,g=0;
+this.separateSumForceVector.x=0;this.separateSumForceVector.y=0;h=this.separateSumForceVector;b=0;for(e=a.length;b<e;b+=1)d=a[b],this.className===d.className&&this.id!==d.id&&(f=this.location.distance(d.location),0<f&&f<this.desiredSeparation&&(d=c.Vector.VectorSub(this.location,d.location),d.normalize(),d.div(f),h.add(d),g+=1));return 0<g?(h.div(g),h.normalize(),h.mult(this.maxSpeed),h.sub(this.velocity),h.limit(this.maxSteeringForce),h):this.zeroForceVector};n.prototype.align=function(a){var b,
+c,d,f,h=2*this.width,g,i=0;this.alignSumForceVector.x=0;this.alignSumForceVector.y=0;g=this.alignSumForceVector;b=0;for(c=a.length;b<c;b+=1)d=a[b],f=this.location.distance(d.location),0<f&&f<h&&(this.className===d.className&&this.id!==d.id)&&(g.add(d.velocity),i+=1);return 0<i?(g.div(i),g.normalize(),g.mult(this.maxSpeed),g.sub(this.velocity),g.limit(this.maxSteeringForce),g):this.zeroForceVector};n.prototype.cohesion=function(a){var b,c,d,f,h,g=0;this.cohesionSumForceVector.y=0;this.cohesionSumForceVector.y=
+0;h=this.cohesionSumForceVector;b=0;for(c=a.length;b<c;b+=1)d=a[b],f=this.location.distance(d.location),0<f&&10>f&&(this.className===d.className&&this.id!==d.id)&&(h.add(d.location),g+=1);return 0<g?(h.div(g),h.sub(this.location),h.normalize(),h.mult(this.maxSpeed),h.sub(this.velocity),h.limit(this.maxSteeringForce),h):this.zeroForceVector};n.prototype.flee=function(a){a=c.Vector.VectorSub(a.location,this.location);a.normalize();a.mult(-this.maxSpeed);return a};n.prototype.drag=function(a){var b=
+this.velocity.mag(),a=-1*a.c*b*b,b=c.Utils.clone(this.velocity);b.normalize();b.mult(a);return b};n.prototype.attract=function(a){var b=c.Vector.VectorSub(a.location,this.location),e;e=b.mag();e=c.Utils.constrain(e,this.width*this.height/8,a.width*a.height);b.normalize();b.mult(a.G*a.mass*this.mass/(e*e));return b};n.prototype.isInside=function(a){return a&&this.location.x+this.width/2>a.location.x-a.width/2&&this.location.x-this.width/2<a.location.x+a.width/2&&this.location.y+this.height/2>a.location.y-
+a.height/2&&this.location.y-this.height/2<a.location.y+a.height/2?!0:!1};n.prototype.checkAvoidEdges=function(){var a,b;this.location.x<this.avoidEdgesStrength?a=this.maxSpeed:this.location.x>this.world.width-this.avoidEdgesStrength&&(a=-this.maxSpeed);a&&(b=new c.Vector(a,this.velocity.y),b.sub(this.velocity),b.limit(this.maxSteeringForce),this.applyForce(b));this.location.y<this.avoidEdgesStrength?a=this.maxSpeed:this.location.y>this.world.height-this.avoidEdgesStrength&&(a=-this.maxSpeed);a&&(b=
+new c.Vector(this.velocity.x,a),b.sub(this.velocity),b.limit(this.maxSteeringForce),this.applyForce(b))};n.prototype.checkWorldEdges=function(a){var b=this.location.x,c=this.location.y,d=this.velocity,f=!1;this.wrapEdges?this.location.x>a.width?(this.location.x=0,f=!0,this.controlCamera&&(this.cameraDiffVector.x=b-this.location.x,this.cameraDiffVector.y=0)):0>this.location.x&&(this.location.x=a.width,f=!0,this.controlCamera&&(this.cameraDiffVector.x=b-this.location.x,this.cameraDiffVector.y=0)):this.location.x+
+this.width/2>a.width?(this.location.x=a.width-this.width/2,d.x*=-1*this.bounciness,f=!0,this.controlCamera&&(this.cameraDiffVector.x=b-this.location.x,this.cameraDiffVector.y=0)):this.location.x<this.width/2&&(this.location.x=this.width/2,d.x*=-1*this.bounciness,f=!0,this.controlCamera&&(this.cameraDiffVector.x=b-this.location.x,this.cameraDiffVector.y=0));this.wrapEdges?this.location.y>a.height?(this.location.y=0,f=!0,this.controlCamera&&(this.cameraDiffVector.x=0,this.cameraDiffVector.y=c-this.location.y)):
+0>this.location.y&&(this.location.y=a.height,f=!0,this.controlCamera&&(this.cameraDiffVector.x=0,this.cameraDiffVector.y=c-this.location.y)):this.location.y+this.height/2>a.height?(this.location.y=a.height-this.height/2,this.velocity.y*=-1*this.bounciness,f=!0,this.controlCamera&&(this.cameraDiffVector.x=0,this.cameraDiffVector.y=c-this.location.y)):this.location.y<this.height/2&&(this.location.y=this.height/2,this.velocity.y*=-1*this.bounciness,f=!0,this.controlCamera&&(this.cameraDiffVector.x=0,
+this.cameraDiffVector.y=c-this.location.y));f&&this.controlCamera&&a.location.add(this.cameraDiffVector);return f};n.prototype.checkCameraEdges=function(){this.checkCameraEdgesVector.x=this.velocity.x;this.checkCameraEdgesVector.y=this.velocity.y;this.world.location.add(this.checkCameraEdgesVector.mult(-1))};n.prototype.getLocation=function(a){if(a){if("x"===a)return this.location.x;if("y"===a)return this.location.y}else return this.getLocationVector.x=this.location.x,this.getLocationVector.y=this.location.y,
+this.getLocationVector};n.prototype.getVelocity=function(a){if(a){if("x"===a)return this.velocity.x;if("y"===a)return this.velocity.y}else return this.getVelocityVector.x=this.location.x,this.getVelocityVector.y=this.location.y,this.getVelocityVector};c.Agent=n;c.Utils.extend(B,c.Agent);B.prototype.name="Walker";B.prototype.step=function(){var a=this.world,b;this.beforeStep&&this.beforeStep.apply(this);!this.isStatic&&!this.isPressed&&(this.isPerlin?(this.perlinTime+=this.perlinSpeed,this.remainsOnScreen?
+(this.acceleration=new c.Vector,this.velocity=new c.Vector.create,this.location.x=c.Utils.map(c.SimplexNoise.noise(this.perlinTime+this.offsetX,0,0.1),-1,1,0,c.world.width),this.location.y=c.Utils.map(c.SimplexNoise.noise(0,this.perlinTime+this.offsetY,0.1),-1,1,0,c.world.height)):(this.acceleration.x=c.Utils.map(c.SimplexNoise.noise(this.perlinTime+this.offsetX,0,0.1),-1,1,this.perlinAccelLow,this.perlinAccelHigh),this.acceleration.y=c.Utils.map(c.SimplexNoise.noise(0,this.perlinTime+this.offsetY,
+0.1),-1,1,this.perlinAccelLow,this.perlinAccelHigh))):(a.c&&(b=c.Utils.clone(this.velocity),b.mult(-1),b.normalize(),b.mult(a.c),this.applyForce(b)),this.applyForce(a.wind),this.applyForce(a.gravity)),this.isRandom&&(this.seekTarget={location:c.Vector.VectorAdd(this.location,new c.Vector(c.Utils.getRandomNumber(-this.randomRadius,this.randomRadius),c.Utils.getRandomNumber(-this.randomRadius,this.randomRadius)))}),this.seekTarget&&this.applyForce(this.seek(this.seekTarget)),this.avoidEdges&&this.checkAvoidEdges(),
+this.velocity.add(this.acceleration),this.maxSpeed&&this.velocity.limit(this.maxSpeed),this.location.add(this.velocity),this.pointToDirection&&0.1<this.velocity.mag()&&(this.angle=c.Utils.radiansToDegrees(Math.atan2(this.velocity.y,this.velocity.x))),this.controlCamera&&this.checkCameraEdges(),(this.checkEdges||this.wrapEdges)&&this.checkWorldEdges(a),0<this.lifespan&&(this.lifespan-=1),this.afterStep&&this.afterStep.apply(this),this.acceleration.mult(0))};c.Walker=B;c.Utils.extend(C,c.Agent);C.prototype.name=
+"Oscillator";C.prototype.step=function(){var a=this.world,b;this.beforeStep&&this.beforeStep.apply(this);if(!this.isStatic&&!this.isPressed&&(this.isPerlin?(this.perlinTime+=this.perlinSpeed,this.aVelocity.x=c.Utils.map(c.SimplexNoise.noise(this.perlinTime+this.perlinOffsetX,0,0.1),-1,1,this.perlinAccelLow,this.perlinAccelHigh),this.aVelocity.y=c.Utils.map(c.SimplexNoise.noise(0,this.perlinTime+this.perlinOffsetY,0.1),-1,1,this.perlinAccelLow,this.perlinAccelHigh)):this.aVelocity.add(this.acceleration),
+this.location.x=this.initialLocation.x+Math.sin(this.aVelocity.x)*this.amplitude.x,this.location.y=this.initialLocation.y+Math.sin(this.aVelocity.y)*this.amplitude.y,this.pointToDirection&&(b=c.Vector.VectorSub(this.location,this.lastLocation),this.angle=c.Utils.radiansToDegrees(Math.atan2(b.y,b.x))),this.controlCamera&&this.checkCameraEdges(),(this.checkEdges||this.wrapEdges)&&this.checkWorldEdges(a),0<this.lifespan&&(this.lifespan-=1),this.afterStep&&this.afterStep.apply(this),this.pointToDirection))this.lastLocation.x=
+this.location.x,this.lastLocation.y=this.location.y};c.Oscillator=C;c.Utils.extend(D,c.Agent);D.prototype.name="Particle";D.prototype.step=function(){var a=this.world,b;this.beforeStep&&this.beforeStep.apply(this);!this.isStatic&&!this.isPressed&&(a.c&&(b=c.Utils.clone(this.velocity),b.mult(-1),b.normalize(),b.mult(a.c),this.applyForce(b)),this.applyForce(a.wind),this.applyForce(a.gravity),(this.checkEdges||this.wrapEdges)&&this.checkWorldEdges(a),this.velocity.add(this.acceleration),this.maxSpeed&&
+this.velocity.limit(this.maxSpeed),this.location.add(this.velocity),this.opacity=c.Utils.map(this.lifespan,0,this.maxSpeed,0,1),this.afterStep&&this.afterStep.apply(this),0<this.lifespan?this.lifespan-=1:0===this.lifespan&&c.elementList.destroyElement(this.id),this.acceleration.mult(0))};c.Particle=D;c.Utils.extend(G,c.Agent);G.prototype.name="ParticleSystem";c.ParticleSystem=G;c.Utils.extend(H,c.Agent);H.prototype.name="Liquid";c.Liquid=H;c.Utils.extend(I,c.Agent);I.prototype.name="Attractor";c.Attractor=
+I;c.Utils.extend(J,c.Agent);J.prototype.name="Repeller";c.Repeller=J;c.Utils.extend(K,c.Agent);K.prototype.name="Heat";c.Heat=K;c.Utils.extend(L,c.Agent);L.prototype.name="Cold";c.Cold=L;c.Utils.extend(M,c.Agent);M.prototype.name="Light";c.Light=M;c.Utils.extend(N,c.Agent);N.prototype.name="Oxygen";c.Oxygen=N;c.Utils.extend(O,c.Agent);O.prototype.name="Food";c.Food=O;c.Utils.extend(P,c.Agent);P.prototype.name="Predator";c.Predator=P;c.Utils.extend(x,c.Agent);x.prototype.name="Sensor";x.prototype.step=
+function(){var a=!1,b,e;if("heat"===this.type&&0<c.heats.length){b=0;for(e=c.heats.length;b<e;b+=1)this.isInside(this,c.heats[b],this.sensitivity)&&(this.target=c.heats[b],a=this.activated=!0)}else if("cold"===this.type&&0<c.colds.length){b=0;for(e=c.colds.length;b<e;b+=1)this.isInside(this,c.colds[b],this.sensitivity)&&(this.target=c.colds[b],a=this.activated=!0)}else if("predator"===this.type&&0<c.predators.length){b=0;for(e=c.predators.length;b<e;b+=1)this.isInside(this,c.predators[b],this.sensitivity)&&
+(this.target=c.predators[b],a=this.activated=!0)}else if("light"===this.type&&0<c.lights.length){b=0;for(e=c.lights.length;b<e;b+=1)this.isInside(this,c.lights[b],this.sensitivity)&&(this.target=c.lights[b],a=this.activated=!0)}else if("oxygen"===this.type&&0<c.oxygen.length){b=0;for(e=c.oxygen.length;b<e;b+=1)this.isInside(this,c.oxygen[b],this.sensitivity)&&(this.target=c.oxygen[b],a=this.activated=!0)}else if("food"===this.type&&0<c.food.length){b=0;for(e=c.food.length;b<e;b+=1)this.isInside(this,
+c.food[b],this.sensitivity)&&(this.target=c.food[b],a=this.activated=!0)}a?this.color=this.activatedColor:(this.target=null,this.activated=!1,this.color="transparent");this.afterStep&&this.afterStep.apply(this)};x.prototype.getActivationForce=function(a){var b;switch(this.behavior){case "AGGRESSIVE":return this.seek(this.target);case "COWARD":return this.seek(this.target).mult(-1);case "LIKES":var e=c.Vector.VectorSub(this.target.location,this.location);b=e.mag();e.normalize();b/=a.agent.maxSpeed;
+e.mult(b);b=c.Vector.VectorSub(e,a.agent.velocity);b.limit(0.01*a.agent.maxSteeringForce);return b;case "LOVES":e=c.Vector.VectorSub(this.target.location,this.location);b=e.mag();e.normalize();if(b>this.width)return b/=a.agent.maxSpeed,e.mult(b),b=c.Vector.VectorSub(e,a.agent.velocity),b.limit(a.agent.maxSteeringForce),b;a.agent.velocity=new c.Vector;a.agent.acceleration=new c.Vector;return new c.Vector;case "EXPLORER":return e=c.Vector.VectorSub(this.target.location,this.location),b=e.mag(),e.normalize(),
+b/=a.agent.maxSpeed,e.mult(-b),b=c.Vector.VectorSub(e,a.agent.velocity),b.limit(0.01*a.agent.maxSteeringForce),b;case "RUN":return this.flee(this.target);case "ACCELERATE":return b=a.agent.velocity.clone(),b.normalize(),b.mult(a.agent.minSpeed);case "DECELERATE":return b=a.agent.velocity.clone(),b.normalize(),b.mult(-a.agent.minSpeed);default:return new c.Vector}};x.prototype.isInside=function(a,b,c){return a.location.x+a.width/2>b.location.x-b.width/2-c*b.width&&a.location.x-a.width/2<b.location.x+
+b.width/2+c*b.width&&a.location.y+a.height/2>b.location.y-b.height/2-c*b.height&&a.location.y-a.height/2<b.location.y+b.height/2+c*b.height?!0:!1};c.Sensor=x;W.prototype.name="FlowFieldMarker";c.FlowFieldMarker=W;Q.prototype.name="FlowField";Q.prototype.build=function(){var a,b,e,d,f,h,g,i,j={},l=this.world,m=Math.ceil(l.width/parseFloat(this.resolution)),n=Math.ceil(l.height/parseFloat(this.resolution)),o=this.perlinTime,p;for(a=0;a<m;a+=1){p=this.perlinTime;j[a]={};b=0;for(e=n;b<e;b+=1)d=a*this.resolution+
+this.resolution/2,f=b*this.resolution+this.resolution/2,h=c.Utils.map(c.SimplexNoise.noise(o,p,0.1),0,1,0,2*Math.PI),g=Math.cos(h),i=Math.sin(h),h=new c.Vector(g,i),j[a][b]=h,g=c.Utils.radiansToDegrees(Math.atan2(i,g)),this.createMarkers&&(d=new c.FlowFieldMarker({location:new c.Vector(d,f),scale:1,opacity:c.Utils.map(g,-360,360,0.1,1),width:this.resolution,height:this.resolution/2,field:h,angle:g,colorMode:"rgb",color:[200,100,50]}),l.el.appendChild(d)),p+=parseFloat(this.perlinSpeed);o+=parseFloat(this.perlinSpeed)}this.field=
+j};c.FlowField=Q;c.Utils.extend(E,c.Agent);E.prototype.name="Connector";E.prototype.step=function(){var a=this.parentA.location,b=this.parentB.location;this.width=Math.floor(c.Vector.VectorSub(this.parentA.location,this.parentB.location).mag());this.location=c.Vector.VectorAdd(this.parentA.location,this.parentB.location).div(2);this.angle=c.Utils.radiansToDegrees(Math.atan2(b.y-a.y,b.x-a.x))};c.Connector=E;c.Utils.extend(R,c.Agent);R.prototype.name="Point";c.Point=R;S.prototype.name="Caption";S.prototype.destroy=
+function(){this._el.parentNode.removeChild(this._el)};c.Caption=S;T.prototype.name="InputMenu";T.prototype.destroy=function(){this._el.parentNode.removeChild(this._el)};c.InputMenu=T;F.prototype.getFPS=function(){return this._fps};F.prototype._update=function(a){var b=c.elementList.count();a._time=Date.now?Date.now():0;a._frameCount++;a._time>a._timeLastSecond+1E3&&(a._fps=a._frameCount,a._timeLastSecond=a._time,a._frameCount=0,a._fpsValue.nodeValue=a._fps,a._totalElementsValue.nodeValue=b,a._3dTransformsValue.nodeValue=
+c.System.supportedFeatures.csstransforms3d);var e=this;window.requestAnimFrame(function(){e._update(e)})};F.prototype.name="StatsDisplay";c.StatsDisplay=F;y.prototype.name="FeatureDetector";y.prototype.detect=function(a){return!this[a]?!1:this[a].call(this)};y.prototype.csstransforms=function(){var a=document.createDocumentFragment(),b=document.createElement("div");a.appendChild(b);b.style.cssText="-webkit-transform: translateX(1px) translateY(1px);-moz-transform: translateX(1px) translateY(1px);-o-transform: translateX(1px) translateY(1px);-ms-transform: translateX(1px) translateY(1px)";
+for(var a=[b.style.transform,b.style.webkitTransform,b.style.MozTransform,b.style.OTransform,b.style.msTransform],b=!1,c=0;c<a.length;c+=1)if(a[c]){b=!0;break}return b};y.prototype.csstransforms3d=function(){var a=document.createDocumentFragment(),b=document.createElement("div");a.appendChild(b);b.style.cssText="-webkit-transform: translate3d(1px, 1px, 0);-moz-transform: translate3d(1px, 1px, 0);-o-transform: translate3d(1px, 1px, 0);-ms-transform: translate3d(1px, 1px, 0)";for(var a=[b.style.transform,
+b.style.webkitTransform,b.style.MozTransform,b.style.OTransform,b.style.msTransform],b=!1,c=0;c<a.length;c+=1)if(a[c]){b=!0;break}return b};y.prototype.touch=function(){var a=document.createElement("div");a.setAttribute("ongesturestart","return;");return"function"===typeof a.ongesturestart?!0:!1};c.FeatureDetector=y})(exports);
+
3,283 build/backup/floraDOM.0.0.7.js
View
@@ -0,0 +1,3283 @@
+/*
+FloraJS | DOM Renderer
+Copyright (c) 2012 Vince Allen
+Brooklyn, NY 11215, USA
+email: vince@vinceallen.com
+web: http://www.vinceallen.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/* Version: 0.0.7 */
+/* Build time: December 2, 2012 05:44:02 */
+/** @namespace */
+var Flora = {}, exports = Flora;
+
+(function(exports) {
+/*global window */
+/**
+ * RequestAnimationFrame shim layer with setTimeout fallback
+ * @param {function} callback The function to call.
+ * @returns {function|Object} An animation frame or a timeout object.
+ */
+window.requestAnimFrame = (function(callback){
+
+ 'use strict';
+
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback) {
+ window.setTimeout(callback, 1000 / 60);
+ };
+})();
+/*global exports */
+var config = {
+ borderStyles: [
+ 'none',
+ 'solid',
+ 'dotted',
+ 'dashed',
+ 'double',
+ 'inset',
+ 'outset',
+ 'groove',
+ 'ridge'
+ ],
+ defaultColorList: [
+ {
+ name: 'heat',
+ startColor: [255, 132, 86],
+ endColor: [175, 47, 0]
+ },
+ {
+ name: 'cold',
+ startColor: [88, 129, 135],
+ endColor: [171, 244, 255]
+ },
+ {
+ name: 'food',
+ startColor: [186, 255, 130],
+ endColor: [84, 187, 0]
+ },
+ {
+ name: 'oxygen',
+ startColor: [109, 215, 255],
+ endColor: [0, 140, 192]
+ },
+ {
+ name: 'light',
+ startColor: [255, 227, 127],
+ endColor: [189, 148, 0]
+ }
+ ],
+ keyMap: {
+ pause: 80,
+ reset: 82,
+ stats: 83,
+ thrustLeft: 37,
+ thrustUp: 38,
+ thrustRight: 39,
+ thrustDown: 40
+ },
+ touchMap: {
+ stats: 2,
+ pause: 3,
+ reset: 4
+ }
+};
+exports.config = config;
+/*global exports */
+/**
+ * Creates a new ElementList.
+ *
+ * @constructor
+ */
+function ElementList() {
+
+ 'use strict';
+
+ /**
+ * Holds a list of elements.
+ * @private
+ */
+ this._records = [];
+}
+
+ElementList.prototype.name = 'ElementList';
+
+/**
+ * Returns the entire 'records' array.
+ *
+ * @returns {Array} An array of elements.
+ */
+ElementList.prototype.add = function(obj) {
+
+ 'use strict';
+
+ this._records.push(obj);
+
+ return this._records;
+};
+
+/**
+ * Returns the entire 'records' array.
+ *
+ * @returns {Array} An array of elements.
+ */
+ElementList.prototype.all = function() {
+ 'use strict';
+ return this._records;
+};
+
+/**
+ * Returns the total number of elements.
+ *
+ * @returns {number} Total number of elements.
+ */
+ElementList.prototype.count = function() {
+ 'use strict';
+ return this._records.length;
+};
+
+/**
+ * Returns an array of elements created from the same constructor.
+ *
+ * @param {string} name The 'name' property.
+ * @returns {Array} An array of elements.
+ */
+ElementList.prototype.getAllByName = function(name) {
+
+ 'use strict';
+
+ var i, max, arr = [];
+
+ for (i = 0, max = this._records.length; i < max; i++) {
+ if (this._records[i].name === name) {
+ arr[arr.length] = this._records[i];
+ }
+ }
+ return arr;
+};
+
+/**
+ * Returns an array of elements with an attribute that matches the
+ * passed 'attr'. If 'opt_val' is passed, 'attr' must equal 'val'.
+ *
+ * @param {string} attr The property to match.
+ * @param {*} [opt_val=] The 'attr' property must equal 'val'.
+ * @returns {Array} An array of elements.
+ */
+ElementList.prototype.getAllByAttribute = function(attr, opt_val) {
+
+ 'use strict';
+
+ var i, max, arr = [], val = opt_val !== undefined ? opt_val : null;
+
+ for (i = 0, max = this._records.length; i < max; i++) {
+ if (this._records[i][attr] !== undefined) {
+ if (val !== null && this._records[i][attr] !== val) {
+ continue;
+ }
+ arr[arr.length] = this._records[i];
+ }
+ }
+ return arr;
+};
+
+/**
+ * Updates the properties of elements created from the same constructor.
+ *
+ * @param {string} name The constructor name.
+ * @param {Object} props A map of properties to update.
+ * @returns {Array} An array of elements.
+ * @example
+ * exports.elementList.updatePropsByName('point', {
+ * color: [0, 0, 0],
+ * scale: 2
+ * }); // all point will turn black and double in size
+ */
+ElementList.prototype.updatePropsByName = function(name, props) {
+
+ 'use strict';
+
+ var i, max, p, arr = this.getAllByName(name);
+
+ for (i = 0, max = arr.length; i < max; i++) {
+ for (p in props) {
+ if (props.hasOwnProperty(p)) {
+ arr[i][p] = props[p];
+ }
+ }
+ }
+ return arr;
+};
+
+/**
+ * Finds an element by its 'id' and returns it.
+ *
+ * @param {string|number} id The element's id.
+ * @returns {Object} The element.
+ */
+ElementList.prototype.getElement = function (id) {
+
+ 'use strict';
+
+ var i, max, records = this._records;
+
+ for (i = 0, max = records.length; i < max; i += 1) {
+ if (records[i].id === id) {
+ return records[i];
+ }
+ }
+};
+
+/**
+ * Finds an element by its 'id' and removes it from its
+ * world as well as the records array.
+ *
+ * @param {string|number} id The element's id.
+ */
+ElementList.prototype.destroyElement = function (id) {
+
+ 'use strict';
+
+ var i, max, records = this._records;
+
+ for (i = 0, max = records.length; i < max; i += 1) {
+ if (records[i].id === id) {
+ records[i].world.el.removeChild(records[i].el);
+ records.splice(i, 1);
+ break;
+ }
+ }
+};
+
+/**
+ * Removes all elements from their world and resets
+ * the 'records' array.
+ *
+ * @param {string|number} id The element's id.
+ */
+ElementList.prototype.destroyAll = function () {
+
+ 'use strict';
+
+ var i, records = this._records;
+
+ for (i = records.length - 1; i >= 0; i -= 1) {
+ if (records[i].world) {
+ records[i].world.el.removeChild(records[i].el);
+ }
+ }
+ this._records = [];
+};
+
+/**
+ * Removes all elements from their world and resets
+ * the 'records' array.
+ *
+ * @param {World} world The world.
+ */
+ElementList.prototype.destroyByWorld = function (world) {
+
+ 'use strict';
+
+ var i, records = this._records;
+
+ for (i = records.length - 1; i >= 0; i -= 1) {
+ if (records[i].world && records[i].world === world) {
+ records[i].world.el.removeChild(records[i].el);
+ records.splice(i, 1);
+ }
+ }
+};
+exports.ElementList = ElementList;
+/*global exports, window */
+/**
+ * Creates a new System.
+ *
+ * @constructor
+ */
+function System() {
+
+ 'use strict';
+}
+
+System.name = 'System';
+
+/**
+ * A list of instructions to execute before the system starts.
+ */
+System.setup = null;
+
+/**
+ * Starts the System.
+ * @param {function} func A list of instructions to execute before the system starts.
+ * @param {Object} opt_universe A map of options for the System's Universe.
+ * @param {Array} opt_worlds An array of DOM elements to use as Worlds.
+ */
+System.start = function (func, opt_universe, opt_worlds) {
+
+ 'use strict';
+
+ var i, max,
+ defaultColorList = exports.config.defaultColorList;
+
+ this.universeOptions = opt_universe || null;
+ this.worlds = opt_worlds || null;
+
+ this._featureDetector = new exports.FeatureDetector();
+
+ this.supportedFeatures = {};
+ this.supportedFeatures.csstransforms = this._featureDetector.detect('csstransforms');
+ this.supportedFeatures.csstransforms3d = this._featureDetector.detect('csstransforms3d');
+ this.supportedFeatures.touch = this._featureDetector.detect('touch');
+
+ exports.liquids = [];
+ exports.repellers = [];
+ exports.attractors = [];
+ exports.heats = [];
+ exports.colds = [];
+ exports.lights = [];
+ exports.oxygen = [];
+ exports.food = [];
+ exports.predators = [];
+
+ exports.mouse = {
+ loc: new exports.Vector(),
+ locLast: new exports.Vector()
+ };
+
+ // create elementList before universe
+ exports.elementList = new exports.ElementList();
+
+ exports.universe = new exports.Universe(this.universeOptions);
+ if (exports.Interface.getDataType(this.worlds) === 'array') {
+ for (i = 0, max = this.worlds.length; i < max; i += 1) {
+ exports.universe.addWorld({
+ el: this.worlds[i]
+ });
+ }
+ } else {
+ exports.universe.addWorld();
+ }
+
+ exports.camera = new exports.Camera();
+
+ // add default colors
+ exports.defaultColors = new exports.ColorTable();
+ for (i = 0, max = defaultColorList.length; i < max; i++) {
+ exports.defaultColors.addColor({
+ name: defaultColorList[i].name,
+ startColor: defaultColorList[i].startColor,
+ endColor: defaultColorList[i].endColor
+ });
+ }
+
+ exports.animLoop = function () {
+
+ var i, universe = exports.universe,
+ elements = exports.elementList.all();
+
+ if (universe.isPlaying) {
+ window.requestAnimFrame(exports.animLoop);
+
+ if (universe.zSorted) {
+ elements = elements.sort(function(a,b){return (b.zIndex - a.zIndex);});
+ }
+
+ /*
+ * Using two loops here because it's faster and frame rate
+ * is more consistent if all properties are updated in one loop,
+ * and all DOM updates are done in a separate loop.
+ */
+
+ // update elements' properties
+ for (i = elements.length - 1; i >= 0; i -= 1) {
+ elements[i].step();
+ }
+
+ // updated elements' DOM element
+ for (i = elements.length - 1; i >= 0; i -= 1) {
+ if (elements[i]) {
+ elements[i].draw();
+ }
+ }
+
+ exports.universe.updateClocks();
+ }
+ };
+
+
+ func = exports.Interface.getDataType(func) === "function" ? func : function () {};
+ System.setup = func;
+
+ func();
+ exports.animLoop();
+};
+
+/**
+ * Destroys a System.
+ */
+System.destroy = function () {
+ 'use strict';
+ exports.elementList.destroyAll();
+};
+
+exports.System = System;
+/*global exports, document, window, console */
+/*jshint supernew:true */
+
+/**
+ * @namespace
+ */
+var Utils = {};
+
+/**
+ * Use to extend the properties and methods of a superClass
+ * onto a subClass.
+ */
+Utils.extend = function(subClass, superClass) {
+
+ 'use strict';
+
+ function F() {}
+ F.prototype = superClass.prototype;
+ subClass.prototype = new F;
+ subClass.prototype.constructor = subClass;
+};
+
+/**
+ * Re-maps a number from one range to another.
+ *
+ * @param {number} value The value to be converted.
+ * @param {number} min1 Lower bound of the value's current range.
+ * @param {number} max1 Upper bound of the value's current range.
+ * @param {number} min2 Lower bound of the value's target range.
+ * @param {number} max2 Upper bound of the value's target range.
+ * @returns {number} A number.
+ */
+Utils.map = function(value, min1, max1, min2, max2) { // returns a new value relative to a new range
+
+ 'use strict';
+
+ var unitratio = (value - min1) / (max1 - min1);
+ return (unitratio * (max2 - min2)) + min2;
+};
+
+/**
+ * Generates a psuedo-random number within a range.
+ *
+ * @param {number} low The low end of the range.
+ * @param {number} high The high end of the range.
+ * @param {boolean} [flt] Set to true to return a float.
+ * @returns {number} A number.
+ */
+Utils.getRandomNumber = function(low, high, flt) {
+
+ 'use strict';
+
+ if (flt) {
+ return Math.random()*(high-(low-1)) + low;
+ }
+ return Math.floor(Math.random()*(high-(low-1))) + low;
+};
+
+/**
+ * Converts degrees to radians.
+ *
+ * @param {number} degrees The degrees value to be converted.
+ * @returns {number} A number in radians.
+ */
+Utils.degreesToRadians = function(degrees) {
+
+ 'use strict';
+
+ if (typeof degrees !== 'undefined') {
+ return 2 * Math.PI * (degrees/360);
+ } else {
+ if (typeof console !== 'undefined') {
+ console.log('Error: Utils.degreesToRadians is missing degrees param.');
+ }
+ return false;
+ }
+};
+
+/**
+ * Converts radians to degrees.
+ *
+ * @param {number} radians The radians value to be converted.
+ * @returns {number} A number in degrees.
+ */
+Utils.radiansToDegrees = function(radians) {
+
+ 'use strict';
+
+ if (typeof radians !== 'undefined') {
+ return radians * (180/Math.PI);
+ } else {
+ if (typeof console !== 'undefined') {
+ console.log('Error: Utils.radiansToDegrees is missing radians param.');
+ }
+ return false;
+ }
+};
+
+/**
+ * Constrain a value within a range.
+ *
+ * @param {number} val The value to constrain.
+ * @param {number} low The lower bound of the range.
+ * @param {number} high The upper bound of the range.
+ * @returns {number} A number.
+ */
+Utils.constrain = function(val, low, high) {
+
+ 'use strict';
+
+ if (val > high) {
+ return high;
+ } else if (val < low) {
+ return low;
+ }
+ return val;
+};
+
+ /**
+ * Returns a new object with all properties and methods of the
+ * old object copied to the new object's prototype.
+ *
+ * @param {Object} object The object to clone.
+ * @returns {Object} An object.
+ */
+Utils.clone = function(object) {
+
+ 'use strict';
+
+ function F() {}
+ F.prototype = object;
+ return new F;
+};
+
+/**
+ * Add an event listener to a DOM element.
+ *
+ * @param {Object} target The element to receive the event listener.
+ * @param {string} eventType The event type.
+ * @param {function} The function to run when the event is triggered.
+ */
+Utils.addEvent = function(target, eventType, handler) {
+
+ 'use strict';
+
+ if (target.addEventListener) { // W3C
+ this.addEventHandler = function(target, eventType, handler) {
+ target.addEventListener(eventType, handler, false);
+ };
+ } else if (target.attachEvent) { // IE
+ this.addEventHandler = function(target, eventType, handler) {
+ target.attachEvent("on" + eventType, handler);
+ };
+ }
+ this.addEventHandler(target, eventType, handler);
+};
+
+/**
+ * Logs a message to the browser console.
+ *
+ * @param {string} msg The message to log.
+ */
+Utils.log = function(msg) {
+
+ 'use strict';
+
+ if (typeof console !== 'undefined' && typeof console.log !== 'undefined') {
+ this.log = function(msg) {
+ console.log(msg); // output error to console
+ };
+ this.log.call(this, msg);
+ } else {
+ this.log = function () {}; // noop
+ }
+};
+
+/**
+ * @returns {Object} The current window width and height.
+ * @example getWindowDim() returns {width: 1024, height: 768}
+ */
+Utils.getWindowSize = function() {
+
+ 'use strict';
+
+ var d = {
+ 'width' : false,
+ 'height' : false
+ };
+ if (typeof(window.innerWidth) !== "undefined") {
+ d.width = window.innerWidth;
+ } else if (typeof(document.documentElement) !== "undefined" &&
+ typeof(document.documentElement.clientWidth) !== "undefined") {
+ d.width = document.documentElement.clientWidth;
+ } else if (typeof(document.body) !== "undefined") {
+ d.width = document.body.clientWidth;
+ }
+ if (typeof(window.innerHeight) !== "undefined") {
+ d.height = window.innerHeight;
+ } else if (typeof(document.documentElement) !== "undefined" &&
+ typeof(document.documentElement.clientHeight) !== "undefined") {
+ d.height = document.documentElement.clientHeight;
+ } else if (typeof(document.body) !== "undefined") {
+ d.height = document.body.clientHeight;
+ }
+ return d;
+};
+
+/**
+ * Concatenates several properties into a single list
+ * representing the style properties of an object.
+ *
+ * @param [Object] props A map of properties.
+ * @returns {string} A list of style properties.
+ */
+Utils.getCSSText = function(props) {
+
+ 'use strict';
+
+ var positionStr = '',
+ width = typeof props.w === 'number' ? props.w + 'px' : props.w,
+ height = typeof props.h === 'number' ? props.h + 'px' : props.h;
+
+ if (!props.color) {
+ props.color = [];
+ props.background = null;
+ } else {
+ props.background = props.cm + '(' + props.color[0] + ', ' + props.color[1] + ', ' + props.color[2] + ')';
+ }
+
+ if (!props.borderColor) {
+ props.borderColor = [];
+ props.borderColorStr = '';
+ } else {
+ props.borderColorStr = props.cm + '(' + props.borderColor[0] + ', ' + props.borderColor[1] + ', ' + props.borderColor[2] + ')';
+ }
+
+ if (exports.System.supportedFeatures.csstransforms3d) {
+ positionStr = [
+ '-webkit-transform: translate3d(' + props.x + 'px, ' + props.y + 'px, 0) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')',
+ '-moz-transform: translate3d(' + props.x + 'px, ' + props.y + 'px, 0) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')',
+ '-o-transform: translate3d(' + props.x + 'px, ' + props.y + 'px, 0) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')',
+ '-ms-transform: translate3d(' + props.x + 'px, ' + props.y + 'px, 0) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')'
+ ].join(';');
+ } else if (exports.System.supportedFeatures.csstransforms) {
+ positionStr = [
+ '-webkit-transform: translateX(' + props.x + 'px) translateY(' + props.y + 'px) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')',
+ '-moz-transform: translateX(' + props.x + 'px) translateY(' + props.y + 'px) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')',
+ '-o-transform: translateX(' + props.x + 'px) translateY(' + props.y + 'px) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')',
+ '-ms-transform: translateX(' + props.x + 'px) translateY(' + props.y + 'px) rotate(' + props.a + 'deg) scaleX(' + props.s + ') scaleY(' + props.s + ')'
+ ].join(';');
+ } else {
+ positionStr = [
+ 'position: absolute',
+ 'left: ' + props.x + 'px',
+ 'top: ' + props.y + 'px'
+ ].join(';');
+ }
+
+ return [
+ positionStr,
+ 'opacity: ' + props.o,
+ 'width: ' + width,
+ 'height: ' + height,
+ 'background: ' + props.background,
+ 'z-index: ' + props.z,
+ 'border-width: ' + props.borderWidth + 'px',
+ 'border-style: ' + props.borderStyle,
+ 'border-color: ' + props.borderColorStr,
+ 'border-radius: ' + props.borderRadius,
+ 'box-shadow: ' + props.boxShadow
+ ].join(';');
+};
+
+exports.Utils = Utils;
+/*global exports */
+/*jshint supernew:true */
+/**
+ * Creates a new Vector.
+ *
+ * @param {number} [opt_x = 0] The x location.
+ * @param {number} [opt_y = 0] The y location.
+ * @constructor
+ */
+function Vector(opt_x, opt_y) {
+ 'use strict';
+ this.x = opt_x || 0;
+ this.y = opt_y || 0;
+}
+
+/**
+ * Subtract two vectors.
+ *
+ * @param {number} v1 The first vector.
+ * @param {number} v2 The second vector.
+ * @returns {Object} A new Vector.
+ */
+Vector.VectorSub = function(v1, v2) {
+ 'use strict';
+ return new Vector(v1.x - v2.x, v1.y - v2.y);
+};
+
+/**
+ * Add two vectors.
+ *
+ * @param {number} v1 The first vector.
+ * @param {number} v2 The second vector.
+ * @returns {Object} A new Vector.
+ */
+Vector.VectorAdd = function(v1, v2) {
+ 'use strict';
+ return new Vector(v1.x + v2.x, v1.y + v2.y);
+};
+
+/**
+ * Multiply a vector by a scalar value.
+ *
+ * @param {number} v A vector.
+ * @param {number} n Vector will be multiplied by this number.
+ * @returns {Object} A new Vector.
+ */
+Vector.VectorMult = function(v, n) {
+ 'use strict';
+ return new Vector(v.x * n, v.y * n);
+};
+
+/**
+ * Divide two vectors.
+ *
+ * @param {number} v A vector.
+ * @param {number} n Vector will be divided by this number.
+ * @returns {Object} A new Vector.
+ */
+Vector.VectorDiv = function(v, n) {
+ 'use strict';
+ return new Vector(v.x / n, v.y / n);
+};
+
+/**
+ * Calculates the distance between two vectors.
+ *
+ * @param {number} v1 The first vector.
+ * @param {number} v2 The second vector.
+ * @returns {number} The distance between the two vectors.
+ */
+Vector.VectorDistance = function(v1, v2) {
+ 'use strict';
+ return Math.sqrt(Math.pow(v2.x - v1.x, 2) + Math.pow(v2.y - v1.y, 2));
+};
+
+/**
+ * Get the midpoint between two vectors.
+ *
+ * @param {number} v1 The first vector.
+ * @param {number} v2 The second vector.
+ * @returns {Object} A new Vector.
+ */
+Vector.VectorMidPoint = function(v1, v2) {
+ 'use strict';
+ return Vector.VectorAdd(v1, v2).div(2); // midpoint = (v1 + v2)/2
+};
+
+/**
+ * Get the angle between two vectors.
+ *
+ * @param {number} v1 The first vector.
+ * @param {number} v2 The second vector.
+ * @returns {number} An angle.
+ */
+Vector.VectorAngleBetween = function(v1, v2) {
+ 'use strict';
+ var dot = v1.dot(v2),
+ theta = Math.acos(dot / (v1.mag() * v2.mag()));
+ return theta;
+};
+
+Vector.prototype.name = 'Vector';
+
+/**
+* Returns an new vector with all properties and methods of the
+* old vector copied to the new vector's prototype.
+*
+* @returns {Object} A vector.
+*/
+Vector.prototype.clone = function() {
+ 'use strict';
+ function F() {}
+ F.prototype = this;
+ return new F;
+};
+
+/**
+ * Adds a vector to this vector.
+ *
+ * @param {Object} vector The vector to add.
+ * @returns {Object} This vector.
+ */
+Vector.prototype.add = function(vector) {
+ 'use strict';
+ this.x += vector.x;
+ this.y += vector.y;
+ return this;
+};
+
+/**
+ * Subtracts a vector from this vector.
+ *
+ * @param {Object} vector The vector to subtract.
+ * @returns {Object} This vector.
+ */
+Vector.prototype.sub = function(vector) {
+ 'use strict';
+ this.x -= vector.x;
+ this.y -= vector.y;
+ return this;
+};
+
+/**
+ * Multiplies this vector by a passed value.
+ *
+ * @param {number} n Vector will be multiplied by this number.
+ * @returns {Object} This vector.
+ */
+Vector.prototype.mult = function(n) {
+ 'use strict';
+ this.x *= n;
+ this.y *= n;
+ return this;
+};
+
+/**
+ * Divides this vector by a passed value.
+ *
+ * @param {number} n Vector will be divided by this number.
+ * @returns {Object} This vector.
+ */
+Vector.prototype.div = function(n) {
+ 'use strict';
+ this.x /= n;
+ this.y /= n;
+ return this;
+};
+
+/**
+ * Calculates the magnitude of this vector.
+ *
+ * @returns {number} The vector's magnitude.
+ */
+Vector.prototype.mag = function() {
+ 'use strict';
+ return Math.sqrt((this.x * this.x) + (this.y * this.y));
+};
+
+/**
+ * Limits the vector's magnitude.
+ *
+ * @param {number} high The upper bound of the vector's magnitude.
+ * @returns {Object} This vector.
+ */
+Vector.prototype.limit = function(high) {
+ 'use strict';
+ if (this.mag() > high) {
+ this.normalize();
+ this.mult(high);
+ }
+ return this;
+};
+
+Vector.prototype.limitLow = function(low) {
+ 'use strict';
+ if (this.mag() < low) {
+ this.normalize();
+ this.mult(low);
+ }
+ return this;
+};
+
+/**
+ * Divides a vector by its magnitude to reduce its magnitude to 1.
+ * Typically used to retrieve the direction of the vector for later manipulation.
+ *
+ * @returns {Object} This vector.
+ */
+Vector.prototype.normalize = function() {
+ 'use strict';
+ var m = this.mag();
+ if (m !== 0) {
+ return this.div(m);
+ }
+};
+
+/**
+ * Calculates the distance between this vector and a passed vector.
+ *
+ * @param {Object} vector The target vector.
+ * @returns {Object} The distance between the two vectors.
+ */
+Vector.prototype.distance = function(vector) {
+ 'use strict';
+ return Math.sqrt(Math.pow(vector.x - this.x, 2) + Math.pow(vector.y - this.y, 2));
+};
+
+/**
+ * Rotates a vector using a passed angle in radians.
+ *
+ * @param {number} radians The angle to rotate in radians.
+ * @returns {Object} This vector.
+ */
+Vector.prototype.rotate = function(radians) {
+ 'use strict';
+ var cos = Math.cos(radians),
+ sin = Math.sin(radians),
+ x = this.x,
+ y = this.y;
+
+ this.x = x * cos - y * sin;
+ this.y = x * sin + y * cos;
+ return this;
+};
+
+/**
+ * Calculates the midpoint between this vector and a passed vector.
+ *
+ * @param {Object} v1 The first vector.
+ * @param {Object} v1 The second vector.
+ * @returns {Object} A vector representing the midpoint between the passed vectors.
+ */
+Vector.prototype.midpoint = function(vector) {
+ 'use strict';
+ return Vector.VectorAdd(this, vector).div(2);
+};
+
+/**
+ * Calulates the dot product.
+ *
+ * @param {Object} vector The target vector.
+ * @returns {Object} A vector.
+ */
+Vector.prototype.dot = function(vector) {
+ 'use strict';
+ if (this.z && vector.z) {
+ return this.x * vector.x + this.y * vector.y + this.z * vector.z;
+ }
+ return this.x * vector.x + this.y * vector.y;
+};
+exports.Vector = Vector;
+/*global exports, document */
+/**
+ * Creates a new ColorPalette object.
+ *
+ * Use this class to create a palette of colors randomly selected
+ * from a range created with initial start and end colors. You
+ * can also generate gradients that smoothly interpolate from
+ * start and end colors.
+ *
+ * @param {string|number} opt_id An optional id. If an id is not passed, a default id is created.
+ * @constructor
+ */
+function ColorPalette(opt_id) {
+
+ 'use strict';
+
+ /**
+ * Holds a list of arrays representing 3-digit color values
+ * smoothly interpolated between start and end colors.
+ * @private
+ */
+ this._gradients = [];
+
+ /**
+ * Holds a list of arrays representing 3-digit color values
+ * randomly selected from start and end colors.
+ * @private
+ */
+ this._colors = [];
+
+ this.id = opt_id || ColorPalette._idCount;
+ ColorPalette._idCount += 1; // increment id
+}
+
+/**
+ * Increments as each ColorPalette is created.
+ * @type number
+ * @default 0
+ * @private
+ */
+ColorPalette._idCount = 0;
+
+ColorPalette.prototype.name = 'ColorPalette';
+
+/**
+ * Creates a color range of 255 colors from the passed start and end colors.
+ * Adds a random selection of these colors to the color property of
+ * the color palette.
+ *
+ * @param {Object} options A set of required options
+ * that includes:
+ * options.min {number} The minimum number of colors to add.
+ * options.max {number} The maximum number of color to add.
+ * options.startColor {Array} The beginning color of the color range.
+ * options.endColor {Array} The end color of the color range.
+ */
+ColorPalette.prototype.addColor = function(options) {
+
+ 'use strict';
+
+ var requiredOptions = {
+ min: 'number',
+ max: 'number',
+ startColor: 'array',
+ endColor: 'array'
+ }, i, ln, colors;
+
+ if (exports.Interface.checkRequiredParams(options, requiredOptions)) {
+
+ ln = exports.Utils.getRandomNumber(options.min, options.max);
+ colors = ColorPalette._createColorRange(options.startColor, options.endColor, 255);
+
+ for (i = 0; i < ln; i++) {
+ this._colors.push(colors[exports.Utils.getRandomNumber(0, colors.length - 1)]);
+ }
+ }
+ return this;
+};
+
+/**
+ * Adds color arrays representing a color range to the gradients property.
+ *
+ * @param {Object} options A set of required options
+ * that includes:
+ * options.startColor {Array} The beginning color of the color range.
+ * options.endColor {Array} The end color of the color range.
+ * options.totalColors {number} The total number of colors in the gradient.
+ * @private
+ */
+ColorPalette.prototype.createGradient = function(options) {
+
+ 'use strict';
+
+ var requiredOptions = {
+ startColor: 'array',
+ endColor: 'array'
+ };
+
+ if (exports.Interface.checkRequiredParams(options, requiredOptions)) {
+
+ this.startColor = options.startColor;
+ this.endColor = options.endColor;
+ this.totalColors = options.totalColors || 255;
+ if (this.totalColors > 0) {
+ this._gradients.push(ColorPalette._createColorRange(this.startColor, this.endColor, this.totalColors));
+ } else {
+ throw new Error('ColorPalette: total colors must be greater than zero.');
+ }
+ }
+};
+
+/**
+ * @returns An array representing a randomly selected color
+ * from the colors property.
+ * @throws {Error} If the colors property is empty.
+ */
+ColorPalette.prototype.getColor = function() {
+
+ 'use strict';
+
+ if (this._colors.length > 0) {
+ return this._colors[exports.Utils.getRandomNumber(0, this._colors.length - 1)];
+ } else {
+ throw new Error('ColorPalette.getColor: You must add colors via addColor() before using getColor().');
+ }
+};
+
+/**
+ * Renders a strip of colors representing the color range
+ * in the colors property.
+ *
+ * @param {Object} parent A DOM object to contain the color strip.
+ */
+ColorPalette.prototype.createSampleStrip = function(parent) {
+
+ 'use strict';
+
+ var i, max, div;
+
+ for (i = 0, max = this._colors.length; i < max; i++) {
+ div = document.createElement('div');
+ div.className = 'color-sample-strip';
+ div.style.background = 'rgb(' + this._colors[i].toString() + ')';
+ parent.appendChild(div);
+ }
+};
+
+/**
+ * Creates an array of RGB color values interpolated between
+ * a passed startColor and endColor.
+ *
+ * @param {Array} startColor The beginning of the color array.
+ * @param {Array} startColor The end of the color array.
+ * @param {number} totalColors The total numnber of colors to create.
+ * @returns {Array} An array of color values.
+ */
+ColorPalette._createColorRange = function(startColor, endColor, totalColors) {
+
+ 'use strict';
+
+ var i, colors = [],
+ startRed = startColor[0],
+ startGreen = startColor[1],
+ startBlue = startColor[2],
+ endRed = endColor[0],
+ endGreen = endColor[1],
+ endBlue = endColor[2],
+ diffRed, diffGreen, diffBlue,
+ newRed, newGreen, newBlue;
+
+ diffRed = endRed - startRed;
+ diffGreen = endGreen - startGreen;
+ diffBlue = endBlue - startBlue;
+
+ for (i = 0; i < totalColors; i++) {
+ newRed = parseInt(diffRed * i/totalColors, 10) + startRed;
+ newGreen = parseInt(diffGreen * i/totalColors, 10) + startGreen;
+ newBlue = parseInt(diffBlue * i/totalColors, 10) + startBlue;
+ colors.push([newRed, newGreen, newBlue]);
+ }
+ return colors;
+};
+
+exports.ColorPalette = ColorPalette;
+/*global exports */
+/**
+ * Creates a new ColorTable.
+ *
+ * Use a color table to create a map of keywords to color ranges.
+ * Instead of manually passing start and end colors when creating
+ * color palettes, you can use getColor() and pass a keyword to
+ * receive the start and end colors.
+ *
+ * @example
+ * var heat = defaultColors.getColor('heat');
+ * console.log(heat.startColor); // -> [255, 132, 86]
+ * console.log(heat.endColor); // -> [175, 47, 0]
+ *
+ * @constructor
+ */
+function ColorTable() {
+ 'use strict';
+}
+
+/**
+ * Adds a key to the color table with start and end color values.
+ *
+ * @param {Object} options A set of required options
+ * that includes:
+ * options.name {number} The name of the entry in the color table.
+ * options.startColor {Array} The beginning color of the color range.
+ * options.endColor {Array} The end color of the color range.
+ *
+ * @returns {Object} The color table.
+ */
+ColorTable.prototype.addColor = function(options) {
+
+ 'use strict';
+
+ var requiredOptions = {
+ name: 'string',
+ startColor: 'array',
+ endColor: 'array'
+ };
+
+ if (exports.Interface.checkRequiredParams(options, requiredOptions)) {
+ this[options.name] = {
+ startColor: options.startColor,
+ endColor: options.endColor
+ };
+ }
+ return this;
+};
+
+ColorTable.prototype.name = 'ColorTable';
+
+/**
+ * Returns start and end colors from a key in the color table.
+ *
+ * @param {Object} options A set of options.
+ * Required:
+ * options.name {number} The name of the entry in the color table.
+ * Optional:
+ * options.startColor {boolean} Pass true to only return the start color.
+ * options.endColor {boolean} Pass true to only return the end color.
+ * @param {Array} startColor An array representing the start color. ex: [255, 100, 50].
+ * @param {Array} endColor An array representing the end color. ex: [155, 50, 10].
+ * @returns {Object|Array} Either an object with startColor and endColor
+ * properties or an array representing a start or end color.
+ *
+ * @example
+ * var heat = myColorTable.getColor('heat');
+ * console.log(heat.startColor); // -> [255, 132, 86]
+ * console.log(heat.endColor); // -> [175, 47, 0]
+ *
+ * var heat = myColorTable.getColor('heat', true);
+ * console.log(heat); // -> [255, 132, 86]
+ *
+ * var heat = myColorTable.getColor('heat', false, true);
+ * console.log(heat); // -> [175, 47, 0]
+ */
+ColorTable.prototype.getColor = function(name, startColor, endColor) {
+
+ 'use strict';
+
+ var color, startCol, endCol;
+
+ if (exports.Interface.getDataType(name) === 'string') {
+
+ if (this[name]) {
+
+ color = this[name];
+
+ if (startColor) {
+ startCol = color.startColor;
+ }
+ if (endColor) {
+ endCol = color.endColor;
+ }
+ if (startCol && endCol || !startCol && !endCol) {
+ return {
+ startColor: color.startColor,
+ endColor: color.endColor
+ };
+ } else if (startCol) {
+ return startCol;
+ } else if (endCol) {
+ return endCol;
+ }
+ } else {
+ throw new Error('ColorTable: ' + name + ' does not exist. Add colors to the ColorTable via addColor().');
+ }
+ } else {
+ throw new Error('ColorTable: You must pass a name (string) for the color entry in the table.');
+ }
+};
+
+exports.ColorTable = ColorTable;
+/*global exports */
+/**
+ * Creates a new BorderPalette object.
+ *
+ * Use this class to create a palette of border styles.
+ *
+ * @constructor
+ */
+function BorderPalette(opt_id) {
+
+ 'use strict';
+
+ /**
+ * Holds a list of border styles.
+ * @private
+ */
+ this._borders = [];
+
+ this.id = opt_id || BorderPalette._idCount;
+ BorderPalette._idCount += 1; // increment id
+}
+
+/**
+ * Increments as each BorderPalette is created.
+ * @type number
+ * @default 0
+ * @private
+ */
+BorderPalette._idCount = 0;
+
+BorderPalette.prototype.name = 'BorderPalette';
+
+/**
+ * Adds a random number of the passed border style to the 'borders' array.
+ *
+ * @param {Object} options A set of required options
+ * that includes:
+ * options.min {number} The minimum number of styles to add.
+ * options.max {number} The maximum number of styles to add.
+ * options.style {string} The border style.
+ */
+BorderPalette.prototype.addBorder = function(options) {
+
+ 'use strict';
+
+ var requiredOptions = {
+ min: 'number',
+ max: 'number',
+ style: 'string'
+ }, i, ln;
+
+ if (exports.Interface.checkRequiredParams(options, requiredOptions)) {
+
+ ln = exports.Utils.getRandomNumber(options.min, options.max);
+
+ for (i = 0; i < ln; i++) {
+ this._borders.push(options.style);
+ }
+ }
+ return this;
+};
+
+/**
+ * @returns A style randomly selected from the 'borders' property.
+ * @throws {Error} If the 'borders' property is empty.
+ */
+BorderPalette.prototype.getBorder = function() {
+
+ 'use strict';
+
+ if (this._borders.length > 0) {
+ return this._borders[exports.Utils.getRandomNumber(0, this._borders.length - 1)];
+ } else {
+ throw new Error('BorderPalette.getBorder: You must add borders via addBorder() before using getBorder().');
+ }
+};
+exports.BorderPalette = BorderPalette;
+/*global exports */
+/*jshint bitwise:false */
+/**
+* https://gist.github.com/304522
+* Ported from Stefan Gustavson's java implementation
+* http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
+* Read Stefan's excellent paper for details on how this code works.
+*
+* @author Sean McCullough banksean@gmail.com
+*
+* You can pass in a random number generator object if you like.
+* It is assumed to have a random() method.
+*/
+
+/**
+ * @namespace
+ */
+var SimplexNoise = (function (r) {
+
+ 'use strict';
+
+ if (r === undefined) {
+ r = Math;
+ }
+ var i;
+ var grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]];
+ var p = [];
+ for (i = 0; i < 256; i += 1) {
+ p[i] = Math.floor(r.random()*256);
+ }
+ // To remove the need for index wrapping, double the permutation table length
+ var perm = [];
+ for(i = 0; i < 512; i += 1) {
+ perm[i] = p[i & 255];
+ }
+
+ // A lookup table to traverse the simplex around a given point in 4D.
+ // Details can be found where this table is used, in the 4D noise method.
+ var simplex = [
+ [0,1,2,3],[0,1,3,2],[0,0,0,0],[0,2,3,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,3,0],
+ [0,2,1,3],[0,0,0,0],[0,3,1,2],[0,3,2,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,3,2,0],
+ [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],
+ [1,2,0,3],[0,0,0,0],[1,3,0,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,3,0,1],[2,3,1,0],
+ [1,0,2,3],[1,0,3,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,3,1],[0,0,0,0],[2,1,3,0],
+ [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],
+ [2,0,1,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,0,1,2],[3,0,2,1],[0,0,0,0],[3,1,2,0],
+ [2,1,0,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,1,0,2],[0,0,0,0],[3,2,0,1],[3,2,1,0]];
+
+return {
+ grad3: grad3,
+ p: p,
+ perm: perm,
+ simplex: simplex,
+ dot: function(g, x, y) {
+ return g[0] * x + g[1] * y;
+ },
+ noise: function(xin, yin) {
+ var n0, n1, n2; // Noise contributions from the three corners
+ // Skew the input space to determine which simplex cell we're in
+ var F2 = 0.5*(Math.sqrt(3.0)-1.0);
+ var s = (xin+yin)*F2; // Hairy factor for 2D
+ var i = Math.floor(xin+s);
+ var j = Math.floor(yin+s);
+ var G2 = (3.0-Math.sqrt(3.0))/6.0;
+ var t = (i+j)*G2;
+ var X0 = i-t; // Unskew the cell origin back to (x,y) space
+ var Y0 = j-t;
+ var x0 = xin-X0; // The x,y distances from the cell origin
+ var y0 = yin-Y0;
+ // For the 2D case, the simplex shape is an equilateral triangle.
+ // Determine which simplex we are in.
+ var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
+ if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
+ else {i1=0; j1=1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
+ // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
+ // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
+ // c = (3-sqrt(3))/6
+ var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
+ var y1 = y0 - j1 + G2;
+ var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
+ var y2 = y0 - 1.0 + 2.0 * G2;
+ // Work out the hashed gradient indices of the three simplex corners
+ var ii = i & 255;
+ var jj = j & 255;
+ var gi0 = this.perm[ii+this.perm[jj]] % 12;
+ var gi1 = this.perm[ii+i1+this.perm[jj+j1]] % 12;
+ var gi2 = this.perm[ii+1+this.perm[jj+1]] % 12;
+ // Calculate the contribution from the three corners
+ var t0 = 0.5 - x0*x0-y0*y0;
+ if (t0 < 0) {
+ n0 = 0.0;
+ } else {
+ t0 *= t0;
+ n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient
+ }
+ var t1 = 0.5 - x1*x1-y1*y1;
+ if (t1 < 0) {
+ n1 = 0.0;
+ } else {
+ t1 *= t1;
+ n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1);
+ }
+ var t2 = 0.5 - x2*x2-y2*y2;
+ if (t2 < 0) {
+ n2 = 0.0;
+ } else {
+ t2 *= t2;
+ n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2);
+ }
+ // Add contributions from each corner to get the final noise value.
+ // The result is scaled to return values in the interval [-1,1].
+ return 70.0 * (n0 + n1 + n2);
+ },
+ noise3d: function(xin, yin, zin) {
+ var n0, n1, n2, n3; // Noise contributions from the four corners
+ // Skew the input space to determine which simplex cell we're in
+ var F3 = 1.0/3.0;
+ var s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D
+ var i = Math.floor(xin+s);
+ var j = Math.floor(yin+s);
+ var k = Math.floor(zin+s);
+ var G3 = 1.0/6.0; // Very nice and simple unskew factor, too
+ var t = (i+j+k)*G3;
+ var X0 = i-t; // Unskew the cell origin back to (x,y,z) space
+ var Y0 = j-t;
+ var Z0 = k-t;
+ var x0 = xin-X0; // The x,y,z distances from the cell origin
+ var y0 = yin-Y0;
+ var z0 = zin-Z0;
+ // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
+ // Determine which simplex we are in.
+ var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
+ var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
+ if(x0>=y0) {
+ if(y0>=z0)
+ { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order
+ else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order
+ else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order
+ }
+ else { // x0<y0
+ if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order
+ else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order
+ else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order
+ }
+ // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
+ // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
+ // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
+ // c = 1/6.
+ var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
+ var y1 = y0 - j1 + G3;
+ var z1 = z0 - k1 + G3;
+ var x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords
+ var y2 = y0 - j2 + 2.0*G3;
+ var z2 = z0 - k2 + 2.0*G3;
+ var x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords
+ var y3 = y0 - 1.0 + 3.0*G3;
+ var z3 = z0 - 1.0 + 3.0*G3;
+ // Work out the hashed gradient indices of the four simplex corners
+ var ii = i & 255;
+ var jj = j & 255;
+ var kk = k & 255;
+ var gi0 = this.perm[ii+this.perm[jj+this.perm[kk]]] % 12;
+ var gi1 = this.perm[ii+i1+this.perm[jj+j1+this.perm[kk+k1]]] % 12;
+ var gi2 = this.perm[ii+i2+this.perm[jj+j2+this.perm[kk+k2]]] % 12;
+ var gi3 = this.perm[ii+1+this.perm[jj+1+this.perm[kk+1]]] % 12;
+ // Calculate the contribution from the four corners
+ var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
+ if (t0 < 0) {
+ n0 = 0.0;
+ } else {
+ t0 *= t0;
+ n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0, z0);
+ }
+ var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
+ if (t1 < 0) {
+ n1 = 0.0;
+ } else {
+ t1 *= t1;
+ n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1, z1);
+ }
+ var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
+ if(t2 < 0) {
+ n2 = 0.0;
+ } else {
+ t2 *= t2;
+ n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2, z2);
+ }
+ var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
+ if(t3 <0 ) {
+ n3 = 0.0;
+ } else {
+ t3 *= t3;
+ n3 = t3 * t3 * this.dot(this.grad3[gi3], x3, y3, z3);
+ }
+ // Add contributions from each corner to get the final noise value.
+ // The result is scaled to stay just inside [-1,1]
+ return 32.0*(n0 + n1 + n2 + n3);
+ }
+};
+
+}({
+random: function () {
+
+ 'use strict';
+
+ return 0.1;
+}
+}));
+exports.SimplexNoise = SimplexNoise;
+/*global exports, console */
+/** @namespace */
+var Interface = {};
+
+/**
+ * @description Compares passed options to a set of required options.
+ * @param {Object} optionsPassed An object containing options passed to a function.
+ * @param {Object} optionsRequired An object containing a function's required options.