Commit 2ddeadd2 authored by Roque's avatar Roque

erp5_drone_simulator: drone simulator gadget

 simulator engine assets, styles and code
parent 28048ede
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>business_template_skin_layer_priority</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>float</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>business_template_skin_layer_priority</string> </key>
<value> <float>10.0</float> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_drone_simulator</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>assets</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UI</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>doc.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>58</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>58</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>full_screen.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>58</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>59</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>pause.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>58</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>59</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>play.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>58</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>59</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>restart.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>58</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>59</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>save.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>58</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>58</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>stop.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>58</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>59</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>drone</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>drone.babylon</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/x-unknown-content-type</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>drone_bleu.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>32</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>32</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>drone_bleu_old.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>256</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>256</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>drone_rouge.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>32</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>32</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>drone_rouge_old.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>256</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>256</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>map</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
{"producer":{"name":"3dsmax","version":"2017","exporter_version":"0.4.5","file":"terrain.babylon"},"autoClear":true,"clearColor":[0.0,0.0,0.0],"ambientColor":[0.0,0.0,0.0],"fogMode":0,"fogColor":null,"fogStart":0.0,"fogEnd":0.0,"fogDensity":0.0,"gravity":[0.0,0.0,0.0],"physicsEngine":null,"physicsEnabled":false,"physicsGravity":null,"cameras":[{"isStereoscopicSideBySide":false,"name":"Default camera","id":"576afc29-5e57-4444-9694-4794999723ec","parentId":null,"lockedTargetId":null,"type":"FreeCamera","position":["-Infinity","-Infinity","-Infinity"],"rotation":[0.0,0.0,0.0],"target":["-Infinity","-Infinity","-Infinity"],"fov":0.8,"minZ":1.0,"maxZ":"Infinity","speed":"Infinity","inertia":0.9,"interaxialDistance":0.0637,"checkCollisions":false,"applyGravity":false,"ellipsoid":null,"autoAnimate":false,"autoAnimateFrom":0,"autoAnimateTo":0,"autoAnimateLoop":false,"animations":null,"mode":0,"orthoLeft":null,"orthoRight":null,"orthoBottom":null,"orthoTop":null,"metadata":null,"tags":null}],"activeCameraID":"576afc29-5e57-4444-9694-4794999723ec","lights":[{"name":"Default light","id":"068479ea-6c6c-4d19-a268-d7d05e4d7989","parentId":null,"position":null,"direction":[0.0,1.0,0.0],"type":3,"diffuse":[1.0,1.0,1.0],"specular":[1.0,1.0,1.0],"intensity":1.0,"range":3.40282347E+38,"exponent":0.0,"angle":0.0,"groundColor":[0.0,0.0,0.0],"excludedMeshesIds":null,"includedOnlyMeshesIds":null,"autoAnimate":false,"autoAnimateFrom":0,"autoAnimateTo":0,"autoAnimateLoop":false,"animations":null,"metadata":null,"tags":null}],"meshes":[{"materialId":"50d53c00-2900-4fec-9062-cf5f9094ceb6","isEnabled":true,"isVisible":true,"pickable":false,"pivotMatrix":null,"positions":[-25000.0,0.0,-25000.0,25000.0,0.0,-25000.0,25000.0,0.0,25000.0,25000.0,0.0,25000.0,-25000.0,0.0,25000.0,-25000.0,0.0,-25000.0],"normals":[0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0],"uvs":[0.0005,1.2849,0.7061,1.2849,0.7061,1.9905,0.7061,1.9905,0.0005,1.9905,0.0005,1.2849],"uvs2":null,"colors":null,"hasVertexAlpha":false,"matricesIndices":null,"matricesWeights":null,"matricesIndicesExtra":null,"matricesWeightsExtra":null,"indices":[0,1,2,3,4,5],"checkCollisions":false,"receiveShadows":true,"infiniteDistance":false,"billboardMode":0,"visibility":1.0,"subMeshes":[{"materialIndex":0,"verticesStart":0,"verticesCount":6,"indexStart":0,"indexCount":6}],"instances":[],"skeletonId":-1,"numBoneInfluencers":4,"showBoundingBox":false,"showSubMeshesBoundingBox":false,"applyFog":true,"alphaIndex":1000,"physicsImpostor":0,"physicsMass":0.0,"physicsFriction":0.0,"physicsRestitution":0.0,"metadata":null,"tags":null,"id":"32d610cd-55dd-4f3e-96ea-7511d26fa986","name":"terrain001","position":[0.0,0.0,0.0],"rotation":[0.0,0.0,0.0],"scaling":[1.0,1.0,1.0],"rotationQuaternion":null,"actions":null,"animations":[],"autoAnimate":true,"autoAnimateFrom":0,"autoAnimateTo":100,"autoAnimateLoop":true,"parentId":null}],"sounds":[],"materials":[{"ambient":[0.5882,0.5882,0.5882],"diffuse":[1.0,1.0,1.0],"specular":[0.0,0.0,0.0],"emissive":[0.0,0.0,0.0],"specularPower":25.6,"diffuseTexture":{"name":"terrain.jpg","level":1.0,"hasAlpha":false,"getAlphaFromRGB":false,"coordinatesMode":0,"isCube":false,"uOffset":0.0,"vOffset":0.0,"uScale":1.0,"vScale":1.0,"uAng":0.0,"vAng":0.0,"wAng":0.0,"wrapU":1,"wrapV":1,"coordinatesIndex":0,"isRenderTarget":false,"renderTargetSize":0,"mirrorPlane":null,"renderList":null,"animations":[],"extensions":null,"samplingMode":3},"diffuseFresnelParameters":null,"ambientTexture":null,"opacityTexture":null,"opacityFresnelParameters":null,"reflectionTexture":null,"reflectionFresnelParameters":null,"emissiveTexture":null,"lightmapTexture":null,"useLightmapAsShadowmap":false,"emissiveFresnelParameters":null,"specularTexture":null,"bumpTexture":null,"useSpecularOverAlpha":true,"disableLighting":false,"useEmissiveAsIllumination":false,"linkEmissiveWithDiffuse":false,"name":"terrain","id":"50d53c00-2900-4fec-9062-cf5f9094ceb6","backFaceCulling":true,"wireframe":false,"alpha":1.0,"alphaMode":2}],"multiMaterials":[],"particleSystems":null,"lensFlareSystems":null,"shadowGenerators":[],"skeletons":[],"actions":null,"metadata":null,"workerCollisions":false}
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>map.babylon</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/x-unknown-content-type</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>terrain.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>586</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>840</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>obstacle</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
{"autoClear":true,"clearColor":[0.2,0.2,0.3,1],"ambientColor":[0,0,0],"gravity":[0,-9.807,0],"collisionsEnabled":true,"morphTargetManagers":[],"lights":[{"tags":null,"groundColor":[0,0,0],"direction":[0,1,0],"diffuse":[1,1,1],"specular":[1,1,1],"falloffType":0,"intensity":1,"range":1.7976931348623157e+308,"intensityMode":0,"radius":0.00001,"_renderPriority":0,"shadowEnabled":true,"excludeWithLayerMask":0,"includeOnlyWithLayerMask":0,"lightmapMode":0,"name":"light","id":"light","uniqueId":83,"state":"","type":3,"animations":[],"ranges":[]}],"cameras":[{"tags":null,"alpha":-1.5707963267948966,"beta":1.2566370614359172,"radius":3,"target":[0,0,0],"inertialAlphaOffset":0,"inertialBetaOffset":0,"inertialRadiusOffset":0,"lowerBetaLimit":0.01,"upperBetaLimit":3.1315926535897933,"inertialPanningX":0,"inertialPanningY":0,"pinchToPanMaxDistance":20,"panningOriginTarget":[0,0,0],"panningInertia":0.9,"zoomOnFactor":1,"targetScreenOffset":{"x":0,"y":0},"allowUpsideDown":true,"useInputToRestoreState":true,"rotation":[0,0,0],"speed":2,"position":[1.7470624777336384e-16,0.9270509831248424,-2.8531695488854605],"upVector":[0,1,0],"fov":0.8,"minZ":1,"maxZ":10000,"inertia":0.9,"mode":0,"layerMask":268435455,"fovMode":0,"cameraRigMode":0,"name":"camera","id":"camera","uniqueId":82,"state":"","type":"ArcRotateCamera","inputsmgr":{"ArcRotateCameraKeyboardMoveInput":{"tags":null,"keysUp":[38],"keysDown":[40],"keysLeft":[37],"keysRight":[39],"keysReset":[220],"panningSensibility":50,"zoomingSensibility":25,"useAltToZoom":true,"angularSpeed":0.01},"ArcRotateCameraMouseWheelInput":{"tags":null,"wheelPrecision":3,"wheelDeltaPercentage":0},"ArcRotateCameraPointersInput":{"tags":null,"buttons":[0,1,2],"angularSensibilityX":1000,"angularSensibilityY":1000,"pinchPrecision":12,"pinchDeltaPercentage":0,"useNaturalPinchZoom":false,"panningSensibility":1000,"multiTouchPanning":true,"multiTouchPanAndZoom":true}},"animations":[],"ranges":[]}],"activeCameraID":"camera","animations":[],"materials":[{"tags":null,"diffuseTexture":{"tags":null,"url":"boat.png","uOffset":0,"vOffset":0,"uScale":1,"vScale":1,"uAng":0,"vAng":0,"wAng":0,"uRotationCenter":0.5,"vRotationCenter":0.5,"wRotationCenter":0.5,"isBlocking":true,"uniqueId":72,"name":"boat.png","hasAlpha":false,"getAlphaFromRGB":false,"level":1,"coordinatesIndex":0,"coordinatesMode":0,"wrapU":1,"wrapV":1,"wrapR":1,"anisotropicFilteringLevel":4,"isCube":false,"is3D":false,"is2DArray":false,"gammaSpace":true,"invertZ":false,"lodLevelInAlpha":false,"lodGenerationOffset":0,"lodGenerationScale":0,"linearSpecularLOD":false,"isRenderTarget":false,"animations":[],"invertY":true,"samplingMode":3},"ambient":[0,0,0],"diffuse":[1,1,1],"specular":[1,1,1],"emissive":[0,0,0],"specularPower":64,"useAlphaFromDiffuseTexture":false,"useEmissiveAsIllumination":false,"linkEmissiveWithDiffuse":false,"useSpecularOverAlpha":false,"useReflectionOverAlpha":false,"disableLighting":false,"useObjectSpaceNormalMap":false,"useParallax":false,"useParallaxOcclusion":false,"parallaxScaleBias":0.05,"roughness":0,"indexOfRefraction":0.98,"invertRefractionY":true,"alphaCutOff":0.4,"useLightmapAsShadowmap":false,"useReflectionFresnelFromSpecular":false,"useGlossinessFromSpecularMapAlpha":false,"maxSimultaneousLights":4,"invertNormalMapX":false,"invertNormalMapY":false,"twoSidedLighting":false,"id":"carMat","uniqueId":71,"name":"carMat","checkReadyOnEveryCall":false,"checkReadyOnlyOnce":false,"state":"","alpha":1,"backFaceCulling":true,"sideOrientation":1,"alphaMode":2,"_needDepthPrePass":false,"disableDepthWrite":false,"disableColorWrite":false,"forceDepthWrite":false,"depthFunction":0,"separateCullingPass":false,"fogEnabled":true,"pointSize":1,"zOffset":0,"pointsCloud":false,"fillMode":0},{"tags":null,"diffuseTexture":{"tags":null,"url":"boat.png","uOffset":0,"vOffset":0,"uScale":1,"vScale":1,"uAng":0,"vAng":0,"wAng":0,"uRotationCenter":0.5,"vRotationCenter":0.5,"wRotationCenter":0.5,"isBlocking":true,"uniqueId":76,"name":"boat.png","hasAlpha":false,"getAlphaFromRGB":false,"level":1,"coordinatesIndex":0,"coordinatesMode":0,"wrapU":1,"wrapV":1,"wrapR":1,"anisotropicFilteringLevel":4,"isCube":false,"is3D":false,"is2DArray":false,"gammaSpace":true,"invertZ":false,"lodLevelInAlpha":false,"lodGenerationOffset":0,"lodGenerationScale":0,"linearSpecularLOD":false,"isRenderTarget":false,"animations":[],"invertY":true,"samplingMode":3},"ambient":[0,0,0],"diffuse":[1,1,1],"specular":[1,1,1],"emissive":[0,0,0],"specularPower":64,"useAlphaFromDiffuseTexture":false,"useEmissiveAsIllumination":false,"linkEmissiveWithDiffuse":false,"useSpecularOverAlpha":false,"useReflectionOverAlpha":false,"disableLighting":false,"useObjectSpaceNormalMap":false,"useParallax":false,"useParallaxOcclusion":false,"parallaxScaleBias":0.05,"roughness":0,"indexOfRefraction":0.98,"invertRefractionY":true,"alphaCutOff":0.4,"useLightmapAsShadowmap":false,"useReflectionFresnelFromSpecular":false,"useGlossinessFromSpecularMapAlpha":false,"maxSimultaneousLights":4,"invertNormalMapX":false,"invertNormalMapY":false,"twoSidedLighting":false,"id":"wheelMat","uniqueId":75,"name":"wheelMat","checkReadyOnEveryCall":false,"checkReadyOnlyOnce":false,"state":"","alpha":1,"backFaceCulling":true,"sideOrientation":1,"alphaMode":2,"_needDepthPrePass":false,"disableDepthWrite":false,"disableColorWrite":false,"forceDepthWrite":false,"depthFunction":0,"separateCullingPass":false,"fogEnabled":true,"pointSize":1,"zOffset":0,"pointsCloud":false,"fillMode":0}],"multiMaterials":[],"environmentIntensity":1,"skeletons":[],"transformNodes":[],"geometries":{"boxes":[],"spheres":[],"cylinders":[],"toruses":[],"grounds":[],"planes":[],"torusKnots":[],"vertexData":[{"id":"c49f95a5-b519-4086-ac83-b118e56e3799","updatable":false,"positions":[-0.3,0,-0.1,0.2,0,-0.1,0.2,0,-0.1,0.1993834667466256,0,-0.08430818085443101,0.19753766811902757,0,-0.06871310699195382,0.1944739840795353,0,-0.05331092722881892,0.1902113032590307,0,-0.038196601125010526,0.18477590650225736,0,-0.02346331352698204,0.1782013048376736,0,-0.00920190005209065,0.17052803287081847,0,0.004499712943189765,0.1618033988749895,0,0.017557050458494622,0.1520811931200062,0,0.029889609666036737,0.14142135623730953,0,0.041421356237309526,0.12988960966603677,0,0.05208119312000617,0.11755705045849463,0,0.06180339887498951,0.10449971294318978,0,0.07052803287081844,0.09079809994790937,0,0.07820130483767357,0.07653668647301798,0,0.08477590650225736,0.06180339887498949,0,0.0902113032590307,0.046689072771181096,0,0.0944739840795353,0.031286893008046185,0,0.09753766811902756,0.015691819145569,0,0.0993834667466256,0,0,0.1,-0.3,0,0.1,-0.3,-0.2,-0.1,0.2,-0.2,-0.1,0.2,-0.2,-0.1,0.1993834667466256,-0.2,-0.08430818085443101,0.19753766811902757,-0.2,-0.06871310699195382,0.1944739840795353,-0.2,-0.05331092722881892,0.1902113032590307,-0.2,-0.038196601125010526,0.18477590650225736,-0.2,-0.02346331352698204,0.1782013048376736,-0.2,-0.00920190005209065,0.17052803287081847,-0.2,0.004499712943189765,0.1618033988749895,-0.2,0.017557050458494622,0.1520811931200062,-0.2,0.029889609666036737,0.14142135623730953,-0.2,0.041421356237309526,0.12988960966603677,-0.2,0.05208119312000617,0.11755705045849463,-0.2,0.06180339887498951,0.10449971294318978,-0.2,0.07052803287081844,0.09079809994790937,-0.2,0.07820130483767357,0.07653668647301798,-0.2,0.08477590650225736,0.06180339887498949,-0.2,0.0902113032590307,0.046689072771181096,-0.2,0.0944739840795353,0.031286893008046185,-0.2,0.09753766811902756,0.015691819145569,-0.2,0.0993834667466256,0,-0.2,0.1,-0.3,-0.2,0.1,-0.3,0,-0.1,-0.3,-0.2,-0.1,0.2,0,-0.1,0.2,-0.2,-0.1,0.2,0,-0.1,0.2,-0.2,-0.1,0.2,0,-0.1,0.2,-0.2,-0.1,0.2,0,-0.1,0.2,-0.2,-0.1,0.1993834667466256,0,-0.08430818085443101,0.1993834667466256,-0.2,-0.08430818085443101,0.1993834667466256,0,-0.08430818085443101,0.1993834667466256,-0.2,-0.08430818085443101,0.19753766811902757,0,-0.06871310699195382,0.19753766811902757,-0.2,-0.06871310699195382,0.19753766811902757,0,-0.06871310699195382,0.19753766811902757,-0.2,-0.06871310699195382,0.1944739840795353,0,-0.05331092722881892,0.1944739840795353,-0.2,-0.05331092722881892,0.1944739840795353,0,-0.05331092722881892,0.1944739840795353,-0.2,-0.05331092722881892,0.1902113032590307,0,-0.038196601125010526,0.1902113032590307,-0.2,-0.038196601125010526,0.1902113032590307,0,-0.038196601125010526,0.1902113032590307,-0.2,-0.038196601125010526,0.18477590650225736,0,-0.02346331352698204,0.18477590650225736,-0.2,-0.02346331352698204,0.18477590650225736,0,-0.02346331352698204,0.18477590650225736,-0.2,-0.02346331352698204,0.1782013048376736,0,-0.00920190005209065,0.1782013048376736,-0.2,-0.00920190005209065,0.1782013048376736,0,-0.00920190005209065,0.1782013048376736,-0.2,-0.00920190005209065,0.17052803287081847,0,0.004499712943189765,0.17052803287081847,-0.2,0.004499712943189765,0.17052803287081847,0,0.004499712943189765,0.17052803287081847,-0.2,0.004499712943189765,0.1618033988749895,0,0.017557050458494622,0.1618033988749895,-0.2,0.017557050458494622,0.1618033988749895,0,0.017557050458494622,0.1618033988749895,-0.2,0.017557050458494622,0.1520811931200062,0,0.029889609666036737,0.1520811931200062,-0.2,0.029889609666036737,0.1520811931200062,0,0.029889609666036737,0.1520811931200062,-0.2,0.029889609666036737,0.14142135623730953,0,0.041421356237309526,0.14142135623730953,-0.2,0.041421356237309526,0.14142135623730953,0,0.041421356237309526,0.14142135623730953,-0.2,0.041421356237309526,0.12988960966603677,0,0.05208119312000617,0.12988960966603677,-0.2,0.05208119312000617,0.12988960966603677,0,0.05208119312000617,0.12988960966603677,-0.2,0.05208119312000617,0.11755705045849463,0,0.06180339887498951,0.11755705045849463,-0.2,0.06180339887498951,0.11755705045849463,0,0.06180339887498951,0.11755705045849463,-0.2,0.06180339887498951,0.10449971294318978,0,0.07052803287081844,0.10449971294318978,-0.2,0.07052803287081844,0.10449971294318978,0,0.07052803287081844,0.10449971294318978,-0.2,0.07052803287081844,0.09079809994790937,0,0.07820130483767357,0.09079809994790937,-0.2,0.07820130483767357,0.09079809994790937,0,0.07820130483767357,0.09079809994790937,-0.2,0.07820130483767357,0.07653668647301798,0,0.08477590650225736,0.07653668647301798,-0.2,0.08477590650225736,0.07653668647301798,0,0.08477590650225736,0.07653668647301798,-0.2,0.08477590650225736,0.06180339887498949,0,0.0902113032590307,0.06180339887498949,-0.2,0.0902113032590307,0.06180339887498949,0,0.0902113032590307,0.06180339887498949,-0.2,0.0902113032590307,0.046689072771181096,0,0.0944739840795353,0.046689072771181096,-0.2,0.0944739840795353,0.046689072771181096,0,0.0944739840795353,0.046689072771181096,-0.2,0.0944739840795353,0.031286893008046185,0,0.09753766811902756,0.031286893008046185,-0.2,0.09753766811902756,0.031286893008046185,0,0.09753766811902756,0.031286893008046185,-0.2,0.09753766811902756,0.015691819145569,0,0.0993834667466256,0.015691819145569,-0.2,0.0993834667466256,0.015691819145569,0,0.0993834667466256,0.015691819145569,-0.2,0.0993834667466256,0,0,0.1,0,-0.2,0.1,0,0,0.1,0,-0.2,0.1,-0.3,0,0.1,-0.3,-0.2,0.1,-0.3,0,0.1,-0.3,-0.2,0.1,-0.3,0,-0.1,-0.3,-0.2,-0.1],"normals":[0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0.9992290362407228,0,0.03925981575906874,0.9992290362407228,0,0.03925981575906874,0.9992290362407228,0,0.03925981575906874,0.9992290362407228,0,0.03925981575906874,0.9930684569549263,0,0.11753739745783691,0.9930684569549263,0,0.11753739745783691,0.9930684569549263,0,0.11753739745783691,0.9930684569549263,0,0.11753739745783691,0.98078528040323,0,0.19509032201613016,0.98078528040323,0,0.19509032201613016,0.98078528040323,0,0.19509032201613016,0.98078528040323,0,0.19509032201613016,0.9624552364536474,0,0.271440449865074,0.9624552364536474,0,0.271440449865074,0.9624552364536474,0,0.271440449865074,0.9624552364536474,0,0.271440449865074,0.9381913359224846,0,0.34611705707749174,0.9381913359224846,0,0.34611705707749174,0.9381913359224846,0,0.34611705707749174,0.9381913359224846,0,0.34611705707749174,0.9081431738250815,0,0.4186597375374275,0.9081431738250815,0,0.4186597375374275,0.9081431738250815,0,0.4186597375374275,0.9081431738250815,0,0.4186597375374275,0.8724960070727971,0,0.4886212414969552,0.8724960070727971,0,0.4886212414969552,0.8724960070727971,0,0.4886212414969552,0.8724960070727971,0,0.4886212414969552,0.8314696123025453,0,0.555570233019602,0.8314696123025453,0,0.555570233019602,0.8314696123025453,0,0.555570233019602,0.8314696123025453,0,0.555570233019602,0.7853169308807447,0,0.6190939493098341,0.7853169308807447,0,0.6190939493098341,0.7853169308807447,0,0.6190939493098341,0.7853169308807447,0,0.6190939493098341,0.7343225094356863,0,0.6788007455329409,0.7343225094356863,0,0.6788007455329409,0.7343225094356863,0,0.6788007455329409,0.7343225094356863,0,0.6788007455329409,0.6788007455329408,0,0.7343225094356863,0.6788007455329408,0,0.7343225094356863,0.6788007455329408,0,0.7343225094356863,0.6788007455329408,0,0.7343225094356863,0.6190939493098344,0,0.7853169308807446,0.6190939493098344,0,0.7853169308807446,0.6190939493098344,0,0.7853169308807446,0.6190939493098344,0,0.7853169308807446,0.5555702330196012,0,0.8314696123025459,0.5555702330196012,0,0.8314696123025459,0.5555702330196012,0,0.8314696123025459,0.5555702330196012,0,0.8314696123025459,0.4886212414969552,0,0.8724960070727971,0.4886212414969552,0,0.8724960070727971,0.4886212414969552,0,0.8724960070727971,0.4886212414969552,0,0.8724960070727971,0.418659737537429,0,0.9081431738250809,0.418659737537429,0,0.9081431738250809,0.418659737537429,0,0.9081431738250809,0.418659737537429,0,0.9081431738250809,0.34611705707749174,0,0.9381913359224846,0.34611705707749174,0,0.9381913359224846,0.34611705707749174,0,0.9381913359224846,0.34611705707749174,0,0.9381913359224846,0.271440449865074,0,0.9624552364536474,0.271440449865074,0,0.9624552364536474,0.271440449865074,0,0.9624552364536474,0.271440449865074,0,0.9624552364536474,0.19509032201613,0,0.98078528040323,0.19509032201613,0,0.98078528040323,0.19509032201613,0,0.98078528040323,0.19509032201613,0,0.98078528040323,0.11753739745783694,0,0.9930684569549263,0.11753739745783694,0,0.9930684569549263,0.11753739745783694,0,0.9930684569549263,0.11753739745783694,0,0.9930684569549263,0.039259815759068735,0,0.9992290362407228,0.039259815759068735,0,0.9992290362407228,0.039259815759068735,0,0.9992290362407228,0.039259815759068735,0,0.9992290362407228,0,0,1,0,0,1,0,0,1,0,0,1,-1,0,0,-1,0,0,-1,0,0,-1,0,0],"uvs":[0,0.5,0.38,0.5,0.38,0.5,0.37953143472743545,0.5392295478639224,0.37812862777046097,0.5782172325201155,0.3758002279004468,0.6167226819279527,0.37256059047686335,0.6545084971874737,0.36842968894171557,0.6913417161825448,0.36343299167663196,0.7269952498697734,0.357601304981822,0.7612492823579744,0.350970583144992,0.7938926261462366,0.3435817067712047,0.8247240241650918,0.3354802307403552,0.8535533905932737,0.32671610334618795,0.8802029828000154,0.3173433583484559,0.9045084971874737,0.3074197818368242,0.9263200821770461,0.29700655596041114,0.9455032620941839,0.28616788171949364,0.9619397662556434,0.274970583144992,0.9755282581475768,0.26348369530609766,0.9861849601988383,0.2517780386861151,0.9938441702975689,0.23992578255063243,0.998458666866564,0.22799999999999998,1,0,1,0,0.5,0.38,0.5,0.38,0.5,0.37953143472743545,0.5392295478639225,0.37812862777046097,0.5782172325201155,0.3758002279004468,0.6167226819279528,0.37256059047686335,0.6545084971874737,0.36842968894171557,0.6913417161825449,0.36343299167663196,0.7269952498697734,0.357601304981822,0.7612492823579744,0.350970583144992,0.7938926261462366,0.3435817067712047,0.8247240241650918,0.3354802307403552,0.8535533905932737,0.32671610334618795,0.8802029828000154,0.3173433583484559,0.9045084971874737,0.3074197818368242,0.9263200821770461,0.29700655596041114,0.9455032620941839,0.28616788171949364,0.9619397662556434,0.274970583144992,0.9755282581475768,0.26348369530609766,0.9861849601988383,0.2517780386861151,0.9938441702975689,0.23992578255063243,0.998458666866564,0.22799999999999998,1,0,1,0,0.5,0,0,0.3804947650231942,0.5,0.3804947650231942,0,0.3804947650231942,0.5,0.3804947650231942,0,0.3804947650231942,0.5,0.3804947650231942,0,0.3804947650231942,0.5,0.3804947650231942,0,0.39244528852087474,0.5,0.39244528852087474,0,0.39244528852087474,0.5,0.39244528852087474,0,0.40439581201855535,0.5,0.40439581201855535,0,0.40439581201855535,0.5,0.40439581201855535,0,0.41634633551623595,0.5,0.41634633551623595,0,0.41634633551623595,0.5,0.41634633551623595,0,0.42829685901391656,0.5,0.42829685901391656,0,0.42829685901391656,0.5,0.42829685901391656,0,0.4402473825115972,0.5,0.4402473825115972,0,0.4402473825115972,0.5,0.4402473825115972,0,0.4521979060092777,0.5,0.4521979060092777,0,0.4521979060092777,0.5,0.4521979060092777,0,0.4641484295069583,0.5,0.4641484295069583,0,0.4641484295069583,0.5,0.4641484295069583,0,0.4760989530046389,0.5,0.4760989530046389,0,0.4760989530046389,0.5,0.4760989530046389,0,0.4880494765023195,0.5,0.4880494765023195,0,0.4880494765023195,0.5,0.4880494765023195,0,0.5000000000000001,0.5,0.5000000000000001,0,0.5000000000000001,0.5,0.5000000000000001,0,0.5119505234976806,0.5,0.5119505234976806,0,0.5119505234976806,0.5,0.5119505234976806,0,0.5239010469953612,0.5,0.5239010469953612,0,0.5239010469953612,0.5,0.5239010469953612,0,0.5358515704930417,0.5,0.5358515704930417,0,0.5358515704930417,0.5,0.5358515704930417,0,0.5478020939907223,0.5,0.5478020939907223,0,0.5478020939907223,0.5,0.5478020939907223,0,0.5597526174884029,0.5,0.5597526174884029,0,0.5597526174884029,0.5,0.5597526174884029,0,0.5717031409860835,0.5,0.5717031409860835,0,0.5717031409860835,0.5,0.5717031409860835,0,0.5836536644837641,0.5,0.5836536644837641,0,0.5836536644837641,0.5,0.5836536644837641,0,0.5956041879814448,0.5,0.5956041879814448,0,0.5956041879814448,0.5,0.5956041879814448,0,0.6075547114791253,0.5,0.6075547114791253,0,0.6075547114791253,0.5,0.6075547114791253,0,0.6195052349768059,0.5,0.6195052349768059,0,0.6195052349768059,0.5,0.6195052349768059,0,0.8478020939907224,0.5,0.8478020939907224,0,0.8478020939907224,0.5,0.8478020939907224,0,1,0.5,1,0],"indices":[22,23,0,3,4,5,5,6,7,7,8,9,9,10,11,11,12,13,13,14,15,15,16,17,17,18,19,19,20,21,21,22,0,3,5,7,7,9,11,11,13,15,15,17,19,19,21,0,3,7,11,11,15,19,3,11,19,3,19,0,3,0,2,24,47,46,29,28,27,31,30,29,33,32,31,35,34,33,37,36,35,39,38,37,41,40,39,43,42,41,45,44,43,24,46,45,31,29,27,35,33,31,39,37,35,43,41,39,24,45,43,35,31,27,43,39,35,43,35,27,24,43,27,26,24,27,48,49,50,49,51,50,52,53,54,53,55,54,56,57,58,57,59,58,60,61,62,61,63,62,64,65,66,65,67,66,68,69,70,69,71,70,72,73,74,73,75,74,76,77,78,77,79,78,80,81,82,81,83,82,84,85,86,85,87,86,88,89,90,89,91,90,92,93,94,93,95,94,96,97,98,97,99,98,100,101,102,101,103,102,104,105,106,105,107,106,108,109,110,109,111,110,112,113,114,113,115,114,116,117,118,117,119,118,120,121,122,121,123,122,124,125,126,125,127,126,128,129,130,129,131,130,132,133,134,133,135,134,136,137,138,137,139,138,140,141,142,141,143,142]},{"id":"2d726b47-ba60-44ea-9b59-414ebb9c4692","updatable":false,"positions":[0.0625,-0.025,0,0.06037036414306677,-0.025,-0.016176190318907546,0.05412658773652742,-0.025,-0.031249999999999997,0.04419417382415922,-0.025,-0.04419417382415922,0.03125000000000001,-0.025,-0.05412658773652741,0.01617619031890756,-0.025,-0.06037036414306676,3.827021247335479e-18,-0.025,-0.0625,-0.01617619031890754,-0.025,-0.06037036414306677,-0.031249999999999986,-0.025,-0.05412658773652742,-0.044194173824159216,-0.025,-0.04419417382415922,-0.054126587736527405,-0.025,-0.03125000000000002,-0.06037036414306676,-0.025,-0.016176190318907564,-0.0625,-0.025,-7.654042494670958e-18,-0.060370364143066776,-0.025,0.016176190318907522,-0.054126587736527426,-0.025,0.031249999999999983,-0.044194173824159244,-0.025,0.044194173824159196,-0.03125000000000003,-0.025,0.054126587736527405,-0.016176190318907595,-0.025,0.060370364143066756,-1.1481063742006436e-17,-0.025,0.0625,0.01617619031890752,-0.025,0.060370364143066776,0.03124999999999996,-0.025,0.05412658773652744,0.04419417382415921,-0.025,0.04419417382415923,0.0541265877365274,-0.025,0.03125000000000003,0.060370364143066756,-0.025,0.016176190318907598,0.0625,-0.025,1.5308084989341915e-17,0.0625,0.025,0,0.06037036414306677,0.025,-0.016176190318907546,0.05412658773652742,0.025,-0.031249999999999997,0.04419417382415922,0.025,-0.04419417382415922,0.03125000000000001,0.025,-0.05412658773652741,0.01617619031890756,0.025,-0.06037036414306676,3.827021247335479e-18,0.025,-0.0625,-0.01617619031890754,0.025,-0.06037036414306677,-0.031249999999999986,0.025,-0.05412658773652742,-0.044194173824159216,0.025,-0.04419417382415922,-0.054126587736527405,0.025,-0.03125000000000002,-0.06037036414306676,0.025,-0.016176190318907564,-0.0625,0.025,-7.654042494670958e-18,-0.060370364143066776,0.025,0.016176190318907522,-0.054126587736527426,0.025,0.031249999999999983,-0.044194173824159244,0.025,0.044194173824159196,-0.03125000000000003,0.025,0.054126587736527405,-0.016176190318907595,0.025,0.060370364143066756,-1.1481063742006436e-17,0.025,0.0625,0.01617619031890752,0.025,0.060370364143066776,0.03124999999999996,0.025,0.05412658773652744,0.04419417382415921,0.025,0.04419417382415923,0.0541265877365274,0.025,0.03125000000000003,0.060370364143066756,0.025,0.016176190318907598,0.0625,0.025,1.5308084989341915e-17,0,-0.025,0,0.0625,-0.025,0,0.06037036414306677,-0.025,-0.016176190318907546,0.05412658773652742,-0.025,-0.031249999999999997,0.04419417382415922,-0.025,-0.04419417382415922,0.03125000000000001,-0.025,-0.05412658773652741,0.016176190318907546,-0.025,-0.06037036414306677,3.827021247335479e-18,-0.025,-0.0625,-0.01617619031890754,-0.025,-0.06037036414306677,-0.031249999999999986,-0.025,-0.05412658773652742,-0.044194173824159216,-0.025,-0.04419417382415922,-0.05412658773652742,-0.025,-0.031249999999999997,-0.06037036414306676,-0.025,-0.016176190318907564,-0.0625,-0.025,-7.654042494670958e-18,-0.06037036414306677,-0.025,0.01617619031890755,-0.054126587736527426,-0.025,0.031249999999999983,-0.044194173824159244,-0.025,0.044194173824159196,-0.03125000000000003,-0.025,0.054126587736527405,-0.01617619031890754,-0.025,0.06037036414306677,-1.1481063742006436e-17,-0.025,0.0625,0.01617619031890752,-0.025,0.060370364143066776,0.03125000000000001,-0.025,0.05412658773652741,0.04419417382415921,-0.025,0.04419417382415923,0.0541265877365274,-0.025,0.03125000000000003,0.060370364143066756,-0.025,0.016176190318907598,0.0625,-0.025,1.5308084989341915e-17,0,0.025,0,0.0625,0.025,0,0.06037036414306677,0.025,-0.016176190318907546,0.05412658773652742,0.025,-0.031249999999999997,0.04419417382415922,0.025,-0.04419417382415922,0.03125000000000001,0.025,-0.05412658773652741,0.016176190318907546,0.025,-0.06037036414306677,3.827021247335479e-18,0.025,-0.0625,-0.01617619031890754,0.025,-0.06037036414306677,-0.031249999999999986,0.025,-0.05412658773652742,-0.044194173824159216,0.025,-0.04419417382415922,-0.05412658773652742,0.025,-0.031249999999999997,-0.06037036414306676,0.025,-0.016176190318907564,-0.0625,0.025,-7.654042494670958e-18,-0.06037036414306677,0.025,0.01617619031890755,-0.054126587736527426,0.025,0.031249999999999983,-0.044194173824159244,0.025,0.044194173824159196,-0.03125000000000003,0.025,0.054126587736527405,-0.01617619031890754,0.025,0.06037036414306677,-1.1481063742006436e-17,0.025,0.0625,0.01617619031890752,0.025,0.060370364143066776,0.03125000000000001,0.025,0.05412658773652741,0.04419417382415921,0.025,0.04419417382415923,0.0541265877365274,0.025,0.03125000000000003,0.060370364143066756,0.025,0.016176190318907598,0.0625,0.025,1.5308084989341915e-17],"normals":[1,0,0,0.9659258262890683,0,-0.25881904510252074,0.8660254037844387,0,-0.49999999999999994,0.7071067811865476,0,-0.7071067811865476,0.5000000000000001,0,-0.8660254037844386,0.25881904510252096,0,-0.9659258262890682,6.123233995736766e-17,0,-1,-0.25881904510252063,0,-0.9659258262890683,-0.4999999999999999,0,-0.8660254037844389,-0.7071067811865475,0,-0.7071067811865476,-0.8660254037844385,0,-0.5000000000000003,-0.9659258262890682,0,-0.258819045102521,-1,0,-1.2246467991473532e-16,-0.9659258262890684,0,0.25881904510252035,-0.8660254037844388,0,0.4999999999999997,-0.7071067811865479,0,0.7071067811865471,-0.5000000000000004,0,0.8660254037844385,-0.2588190451025215,0,0.9659258262890681,-1.8369701987210297e-16,0,1,0.2588190451025203,0,0.9659258262890684,0.49999999999999933,0,0.866025403784439,0.7071067811865474,0,0.7071067811865477,0.8660254037844384,0,0.5000000000000004,0.9659258262890681,0,0.25881904510252157,1,0,2.4492935982947064e-16,1,0,0,0.9659258262890683,0,-0.25881904510252074,0.8660254037844387,0,-0.49999999999999994,0.7071067811865476,0,-0.7071067811865476,0.5000000000000001,0,-0.8660254037844386,0.25881904510252096,0,-0.9659258262890682,6.123233995736766e-17,0,-1,-0.25881904510252063,0,-0.9659258262890683,-0.4999999999999999,0,-0.8660254037844389,-0.7071067811865475,0,-0.7071067811865476,-0.8660254037844385,0,-0.5000000000000003,-0.9659258262890682,0,-0.258819045102521,-1,0,-1.2246467991473532e-16,-0.9659258262890684,0,0.25881904510252035,-0.8660254037844388,0,0.4999999999999997,-0.7071067811865479,0,0.7071067811865471,-0.5000000000000004,0,0.8660254037844385,-0.2588190451025215,0,0.9659258262890681,-1.8369701987210297e-16,0,1,0.2588190451025203,0,0.9659258262890684,0.49999999999999933,0,0.866025403784439,0.7071067811865474,0,0.7071067811865477,0.8660254037844384,0,0.5000000000000004,0.9659258262890681,0,0.25881904510252157,1,0,2.4492935982947064e-16,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0],"uvs":[0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0,0.5,0.5,0.5,1,0.5,0.9829629131445341,0.37059047744873963,0.9330127018922194,0.25,0.8535533905932737,0.1464466094067262,0.75,0.0669872981077807,0.6294095225512604,0.017037086855465844,0.5,0,0.3705904774487397,0.017037086855465844,0.2500000000000001,0.06698729810778065,0.14644660940672627,0.1464466094067262,0.06698729810778065,0.25,0.0170370868554659,0.3705904774487395,0,0.49999999999999994,0.017037086855465844,0.6294095225512604,0.06698729810778059,0.7499999999999999,0.14644660940672605,0.8535533905932735,0.24999999999999978,0.9330127018922192,0.3705904774487397,0.9829629131445341,0.4999999999999999,1,0.6294095225512601,0.9829629131445342,0.75,0.9330127018922193,0.8535533905932737,0.8535533905932738,0.9330127018922192,0.7500000000000002,0.9829629131445341,0.6294095225512608,1,0.5000000000000001,0.5,0.5,1,0.5,0.9829629131445341,0.37059047744873963,0.9330127018922194,0.25,0.8535533905932737,0.1464466094067262,0.75,0.0669872981077807,0.6294095225512604,0.017037086855465844,0.5,0,0.3705904774487397,0.017037086855465844,0.2500000000000001,0.06698729810778065,0.14644660940672627,0.1464466094067262,0.06698729810778065,0.25,0.0170370868554659,0.3705904774487395,0,0.49999999999999994,0.017037086855465844,0.6294095225512604,0.06698729810778059,0.7499999999999999,0.14644660940672605,0.8535533905932735,0.24999999999999978,0.9330127018922192,0.3705904774487397,0.9829629131445341,0.4999999999999999,1,0.6294095225512601,0.9829629131445342,0.75,0.9330127018922193,0.8535533905932737,0.8535533905932738,0.9330127018922192,0.7500000000000002,0.9829629131445341,0.6294095225512608,1,0.5000000000000001],"indices":[0,25,1,26,1,25,1,26,2,27,2,26,2,27,3,28,3,27,3,28,4,29,4,28,4,29,5,30,5,29,5,30,6,31,6,30,6,31,7,32,7,31,7,32,8,33,8,32,8,33,9,34,9,33,9,34,10,35,10,34,10,35,11,36,11,35,11,36,12,37,12,36,12,37,13,38,13,37,13,38,14,39,14,38,14,39,15,40,15,39,15,40,16,41,16,40,16,41,17,42,17,41,17,42,18,43,18,42,18,43,19,44,19,43,19,44,20,45,20,44,20,45,21,46,21,45,21,46,22,47,22,46,22,47,23,48,23,47,23,48,24,49,24,48,50,51,52,50,52,53,50,53,54,50,54,55,50,55,56,50,56,57,50,57,58,50,58,59,50,59,60,50,60,61,50,61,62,50,62,63,50,63,64,50,64,65,50,65,66,50,66,67,50,67,68,50,68,69,50,69,70,50,70,71,50,71,72,50,72,73,50,73,74,50,74,75,76,78,77,76,79,78,76,80,79,76,81,80,76,82,81,76,83,82,76,84,83,76,85,84,76,86,85,76,87,86,76,88,87,76,89,88,76,90,89,76,91,90,76,92,91,76,93,92,76,94,93,76,95,94,76,96,95,76,97,96,76,98,97,76,99,98,76,100,99,76,101,100]}]},"meshes":[{"name":"car","id":"car","uniqueId":73,"type":"Mesh","position":[0,0,0],"rotation":[-1.5707963267948966,0,0],"scaling":[1,1,1],"localMatrix":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"isEnabled":true,"isVisible":true,"infiniteDistance":false,"pickable":true,"receiveShadows":false,"billboardMode":0,"visibility":1,"checkCollisions":false,"isBlocker":false,"overrideMaterialSideOrientation":null,"isUnIndexed":false,"geometryId":"c49f95a5-b519-4086-ac83-b118e56e3799","subMeshes":[{"materialIndex":0,"verticesStart":0,"verticesCount":144,"indexStart":0,"indexCount":270}],"materialId":"carMat","instances":[],"animations":[],"ranges":[],"layerMask":268435455,"alphaIndex":1.7976931348623157e+308,"hasVertexAlpha":false,"overlayAlpha":0.5,"overlayColor":[1,0,0],"applyFog":true},{"name":"wheelRB","id":"wheelRB","uniqueId":77,"type":"Mesh","position":[-0.2,0.035,-0.1],"rotation":[0,5.535486255625217,0],"scaling":[1,1,1],"localMatrix":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"isEnabled":true,"isVisible":true,"infiniteDistance":false,"pickable":true,"receiveShadows":false,"billboardMode":0,"visibility":1,"checkCollisions":false,"isBlocker":false,"overrideMaterialSideOrientation":null,"parentId":"car","isUnIndexed":false,"geometryId":"2d726b47-ba60-44ea-9b59-414ebb9c4692","subMeshes":[{"materialIndex":0,"verticesStart":0,"verticesCount":102,"indexStart":0,"indexCount":288}],"materialId":"wheelMat","instances":[],"animations":[{"name":"wheelAnimation","property":"rotation.y","framePerSecond":30,"dataType":0,"loopBehavior":1,"blendingSpeed":0.01,"keys":[{"frame":0,"values":[0]},{"frame":30,"values":[6.283185307179586]}],"ranges":[]}],"ranges":[],"layerMask":268435455,"alphaIndex":1.7976931348623157e+308,"hasVertexAlpha":false,"overlayAlpha":0.5,"overlayColor":[1,0,0],"applyFog":true},{"name":"wheelRF","id":"wheelRF.wheelRB","uniqueId":79,"type":"Mesh","position":[0.1,0.035,-0.1],"rotation":[0,5.535486255625217,0],"scaling":[1,1,1],"pivotMatrix":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"isEnabled":true,"isVisible":true,"infiniteDistance":false,"pickable":true,"receiveShadows":false,"billboardMode":0,"visibility":1,"checkCollisions":false,"isBlocker":false,"overrideMaterialSideOrientation":null,"parentId":"car","isUnIndexed":false,"geometryId":"2d726b47-ba60-44ea-9b59-414ebb9c4692","subMeshes":[{"materialIndex":0,"verticesStart":0,"verticesCount":102,"indexStart":0,"indexCount":288}],"materialId":"wheelMat","instances":[],"animations":[{"name":"wheelAnimation","property":"rotation.y","framePerSecond":30,"dataType":0,"loopBehavior":1,"blendingSpeed":0.01,"keys":[{"frame":0,"values":[0]},{"frame":30,"values":[6.283185307179586]}],"ranges":[]}],"ranges":[],"layerMask":268435455,"alphaIndex":1.7976931348623157e+308,"hasVertexAlpha":false,"overlayAlpha":0.5,"overlayColor":[1,0,0],"applyFog":true},{"name":"wheelLB","id":"wheelLB.wheelRB","uniqueId":80,"type":"Mesh","position":[-0.2,-0.23500000000000001,-0.1],"rotation":[0,5.535486255625217,0],"scaling":[1,1,1],"pivotMatrix":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"isEnabled":true,"isVisible":true,"infiniteDistance":false,"pickable":true,"receiveShadows":false,"billboardMode":0,"visibility":1,"checkCollisions":false,"isBlocker":false,"overrideMaterialSideOrientation":null,"parentId":"car","isUnIndexed":false,"geometryId":"2d726b47-ba60-44ea-9b59-414ebb9c4692","subMeshes":[{"materialIndex":0,"verticesStart":0,"verticesCount":102,"indexStart":0,"indexCount":288}],"materialId":"wheelMat","instances":[],"animations":[{"name":"wheelAnimation","property":"rotation.y","framePerSecond":30,"dataType":0,"loopBehavior":1,"blendingSpeed":0.01,"keys":[{"frame":0,"values":[0]},{"frame":30,"values":[6.283185307179586]}],"ranges":[]}],"ranges":[],"layerMask":268435455,"alphaIndex":1.7976931348623157e+308,"hasVertexAlpha":false,"overlayAlpha":0.5,"overlayColor":[1,0,0],"applyFog":true},{"name":"wheelLF","id":"wheelLF.wheelRF.wheelRB","uniqueId":81,"type":"Mesh","position":[0.1,-0.23500000000000001,-0.1],"rotation":[0,5.535486255625217,0],"scaling":[1,1,1],"pivotMatrix":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":0,"12":0,"13":0,"14":0,"15":1},"isEnabled":true,"isVisible":true,"infiniteDistance":false,"pickable":true,"receiveShadows":false,"billboardMode":0,"visibility":1,"checkCollisions":false,"isBlocker":false,"overrideMaterialSideOrientation":null,"parentId":"car","isUnIndexed":false,"geometryId":"2d726b47-ba60-44ea-9b59-414ebb9c4692","subMeshes":[{"materialIndex":0,"verticesStart":0,"verticesCount":102,"indexStart":0,"indexCount":288}],"materialId":"wheelMat","instances":[],"animations":[{"name":"wheelAnimation","property":"rotation.y","framePerSecond":30,"dataType":0,"loopBehavior":1,"blendingSpeed":0.01,"keys":[{"frame":0,"values":[0]},{"frame":30,"values":[6.283185307179586]}],"ranges":[]}],"ranges":[],"layerMask":268435455,"alphaIndex":1.7976931348623157e+308,"hasVertexAlpha":false,"overlayAlpha":0.5,"overlayColor":[1,0,0],"applyFog":true}],"particleSystems":[],"postProcesses":[]}
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>boat.babylon</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/x-unknown-content-type</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>boat.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>302</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>993</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>schema.png</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/png</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>388</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>680</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>skybox</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>sky_nx.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>512</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>512</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>sky_ny.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>512</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>512</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>sky_nz.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>512</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>512</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>sky_px.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>512</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>512</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>sky_py.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>512</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>512</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Image" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>sky_pz.jpg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/jpeg</string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>512</int> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>512</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>css</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden; }
body {
display: flex;
font-family: Georgia 20; }
.gutter {
background-color: #333;
border-left: 1px solid #eee; }
.gutter:hover {
cursor: col-resize; }
/** Canvas and action bar */
.leftZone {
box-sizing: border-box;
height: 100%;
display: flex;
flex-flow: column;
/** The game canvas */
/** Action bar */ }
.leftZone #simCanvas {
width: 100%;
height: 85%;
background-color: black; }
.leftZone .result {
display: block;
position: fixed;}
.leftZone .actionBar {
box-sizing: border-box;
width: 100%;
background-color: white;
height: 15%;
margin: 5px 0 0 10px; }
.leftZone .actionBar img {
width: 50px;
height: 50px;
cursor: pointer;
display: inline-block; }
.leftZone .actionBar #simPause {
display: none; }
.leftZone .actionBar #simStop, .leftZone .actionBar #simFullscreen/*, .leftZone .actionBar #simRestart*/ {
visibility: hidden; }
.leftZone .actionBar .messages {
display: inline-block;
vertical-align: top;
width: calc(100% - 320px);
height: calc(100% - 5px);
margin-left: 30px;
text-align: center; }
.leftZone .actionBar #timingDisplay {
float: right;
margin: 10px 30px 0 0;
color: black;
font-size: 28px; }
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>main.css</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/css</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!DOCTYPE html>
<html>
<head>
<title>Drone simulator engine</title>
<!--Libraries-->
<script src="rsvp.js" type="text/javascript"></script>
<script src="jiodev.js" type="text/javascript"></script>
<script src ="renderjs.js"></script>
<script type="text/javascript" src="./js/libraries/split.min.js"></script>
<script type="text/javascript" src="./js/libraries/babylon.min.js"></script>
<script type="text/javascript" src="./js/libraries/babylon.gui.js"></script>
<script type="text/javascript" src="./js/libraries/require.js"></script>
<script src="./js/DroneAPI.js"></script>
<script src="./js/DroneManager.js"></script>
<script src="./js/GameManager.js"></script>
<script src="./js/MapManager.js"></script>
<script src="./js/ObstacleManager.js"></script>
<script src="drone_simulator_engine.js"></script>
<link rel="stylesheet" type="text/css" href="./css/main.css">
</head>
<body>
<div class="leftZone">
<canvas id="simCanvas"></canvas>
<div class='actionBar'>
<img id="simPlay" src="assets/UI/play.png">
<img id="simPause" src="assets/UI/pause.png">
<div id="messages" class="messages">Loading simulator...</div>
<div id="timingDisplay">00:00</div>
</div>
</div>
</body>
</html>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>drone_simulator_engine.html</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*global window, rJS, RSVP, GameManager, loopEventListener, console, document, Blob*/
/*jslint nomen: true, maxlen:80, indent:2*/
(function (window, rJS, RSVP, GameManager, console, document, Blob) {
"use strict";
var deferred = RSVP.defer();
rJS(window)
.declareMethod('render', function (options) {
return this.changeState({
content: options.value,
key: options.key
});
})
.declareMethod('getContent', function (options) {
return deferred.promise;
})
.declareJob('runGame', function runGame() {
var value = this.state.content ? JSON.parse(this.state.content) : null,
gadget = this;
if (value.autorun) {
return (new GameManager(value.script, value.map,
value.simulation_speed)).run()
.push(function (result) {
if (GameManager.getLog() !== '') {
var blob = new Blob([GameManager.getLog()], {type: 'text/plain'}),
a = document.createElement('a');
a.download = 'drone_log.txt';
a.href = window.URL.createObjectURL(blob);
a.dataset.downloadurl = ['text/plain', a.download,
a.href].join(':');
a.textContent = 'LOG';
document.querySelector('.actionBar').appendChild(a);
}
deferred.resolve(result);
});
}
})
.onStateChange(function (modification_dict) {
if (modification_dict.hasOwnProperty('content')) {
return this.runGame();
}
});
}(window, rJS, RSVP, GameManager, console, document, Blob));
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>drone_simulator_engine.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Drone simulator gadget</title>
<link rel="http://www.renderjs.org/rel/interface" href="interface_editor.html">
<link rel="http://www.renderjs.org/rel/interface" href="interface_erp5_form_content_provider.html">
<link rel="stylesheet" href="gadget_editor.css">
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="gadget_drone_simulator.js"></script>
</head>
<body>
</body>
</html>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>gadget_drone_simulator.html</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*jslint nomen: true, indent: 2 */
/*global window, rJS, RSVP, document*/
(function (window, rJS, RSVP, document) {
"use strict";
rJS(window)
.declareAcquiredMethod('triggerMaximize', 'triggerMaximize')
.allowPublicAcquisition('triggerMaximize', function (param_list) {
var gadget = this;
if (!this.element.classList.contains('editor-maximize')) {
this.element.classList.toggle('editor-maximize');
}
return this.triggerMaximize.apply(this, param_list)
.push(undefined, function () {
if (gadget.element.classList.contains('editor-maximize')) {
gadget.element.classList.remove('editor-maximize');
}
});
})
.declareMethod('render', function (options) {
return this.renderAsynchronously(options);
})
.declareJob('renderAsynchronously', function (options) {
var state_dict = {
value: options.value || "",
maximize: options.maximize,
key: options.key,
// Force calling subfield render
// as user may have modified the input value
render_timestamp: new Date().getTime()
};
return this.changeState(state_dict);
})
.onStateChange(function (modification_dict) {
var element = this.element,
gadget = this,
div = document.createElement('div'),
div_max = document.createElement('div'),
code,
queue = new RSVP.Queue();
while (element.firstChild) {
element.removeChild(element.firstChild);
}
element.appendChild(div_max);
queue
.push(function () {
return gadget.triggerMaximize(false);
})
.push(function () {
return gadget.declareGadget("gadget_button_maximize.html", {
scope: 'maximize',
element: div_max,
sandbox: 'public'
});
}, function (error) {
// Check Acquisition, old erp5 ui don't have triggerMaximize
if (error.name !== "AcquisitionError") {
throw error;
}
});
element.appendChild(div);
queue
.push(function () {
return gadget.declareGadget(
"drone_simulator_engine.html",
{
scope: 'simulator',
sandbox: 'iframe',
element: div
}
);
});
queue
.push(function () {
return gadget.getDeclaredGadget('simulator');
})
.push(function (simulator_gadget) {
return simulator_gadget.render(gadget.state);
});
if (modification_dict.maximize === "auto") {
queue
.push(function () {
return gadget.getDeclaredGadget("maximize");
})
.push(function (gadget_maximize) {
return gadget_maximize.callMaximize(true);
});
}
return queue;
})
.declareMethod('getContent', function () {
var gadget = this;
return gadget.getDeclaredGadget('simulator')
.push(function (simulator_gadget) {
return simulator_gadget.getContent();
});
}, {mutex: 'changestate'})
.declareMethod('checkValidity', function () {
// XXX How to implement this for editors?
return true;
});
}(window, rJS, RSVP, document));
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>gadget_drone_simulator.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>js</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/// <reference path="./GameManager.ts" />
var DroneAPI = /** @class */ (function () {
//*************************************************** CONSTRUCTOR **************************************************
function DroneAPI(gameManager, team) {
this._gameManager = gameManager;
this._team = team;
}
Object.defineProperty(DroneAPI.prototype, "team", {
//*************************************************** ACCESSOR *****************************************************
get: function () {
if (this._team == "L")
return this._gameManager.teamLeft;
else if (this._team == "R")
return this._gameManager.teamRight;
},
enumerable: true,
configurable: true
});
//*************************************************** FUNCTIONS ****************************************************
//#region ------------------ Internal
DroneAPI.prototype.internal_sendMsg = function (msg, to) {
var _this = this;
_this._gameManager.delay(function () {
if (to < 0) {
// Send to all drones
_this.team.forEach(function (drone) {
if (drone.infosMesh) {
try {
drone.onGetMsg(msg);
}
catch (error) {
console.warn('Drone crashed on sendMsg due to error:', error);
drone._internal_crash();
}
}
});
}
else {
// Send to specific drone
if (drone.infosMesh) {
try {
_this.team[to].onGetMsg(msg);
}
catch (error) {
console.warn('Drone crashed on sendMsg due to error:', error);
_this.team[to]._internal_crash();
}
}
}
}, GAMEPARAMETERS.latency.communication);
};
//#endregion
//#region ------------------ Accessible from AI
DroneAPI.prototype.log = function (msg) {
console.log("API say : " + msg);
};
DroneAPI.prototype.getGameParameter = function (name) {
if (["gameTime", "mapSize", "teamSize", "derive", "meteo", "initialHumanAreaPosition"].includes(name))
return this._gameManager.gameParameter[name];
};
DroneAPI.prototype.getMapInfos = function () {
return {
width: GAMEPARAMETERS.mapSize.width,
depth: GAMEPARAMETERS.mapSize.depth,
height: GAMEPARAMETERS.mapSize.height
};
};
DroneAPI.prototype._isWithinDroneView = function (drone_position, element_position) {
// Check if element is under the drone cone-view
var angle = GAMEPARAMETERS.drone.viewAngle ? GAMEPARAMETERS.drone.viewAngle : 60,
radius = drone_position.z * Math.tan(angle/2 * Math.PI/180),
distance = (drone_position.x - element_position.x) * (drone_position.x - element_position.x) +
(drone_position.y - element_position.y) * (drone_position.y - element_position.y);
if (distance < (radius*radius))
return true;
return false;
};
DroneAPI.prototype._getProbabilityOfDetection = function (drone_position) {
var h = drone_position.z,
km = GAMEPARAMETERS.meteo;
prob = 20 * (1 + (110-h)/25) * km;
return prob;
};
DroneAPI.prototype.isHumanPositionSpottedCalculation = function (drone) {
var context = this,
result = false,
drone_position = drone.infosMesh.position;
//swap axes back
drone_position = {
x: drone_position.x,
y: drone_position.z,
z: drone_position.y
};
context._gameManager.teamRight.forEach(function (human) {
if (human.infosMesh && context._isWithinDroneView(drone_position, human.position)) {
var prob = context._getProbabilityOfDetection(drone_position),
random = Math.floor(Math.random()*101);
if (random < prob)
result = true;
}
});
return result;
};
DroneAPI.prototype.isHumanPositionSpotted = function (drone) {
var context = this,
human_detected;
if (drone.__is_calculating_human_position !== true) {
drone.__is_calculating_human_position = true;
//human detection is done with the info captured by the drone
//at the moment this method is called
human_detected = context.isHumanPositionSpottedCalculation(drone);
context._gameManager.delay(function () {
drone.__is_calculating_human_position = false;
try {
drone.onCapture(human_detected);
} catch (error) {
console.warn('Drone crashed on capture due to error:', error);
drone._internal_crash();
}
}, 2000);
}
};
return DroneAPI;
}());
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>DroneAPI.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/// <reference path="./typings/babylon.3.1.d.ts" />
/// <reference path="./DroneAPI.ts" />
var DroneManager = /** @class */ (function () {
//*************************************************** CONSTRUCTOR **************************************************
function DroneManager(scene, id, team, API) {
var _this = this;
// Mesh
this._mesh = null;
this._controlMesh = null;
this._colliderBackMesh = null;
this._canPlay = false;
this._canCommunicate = false;
this._maxAcceleration = 0;
this._maxSpeed = 0;
this._speed = 0;
this._acceleration = 0;
this._direction = BABYLON.Vector3.Zero();
this._rotationSpeed = 0.4;
this._maxOrientation = Math.PI / 4;
this._scene = scene;
this._canUpdate = true;
this._id = id;
this._team = team;
this._API = API; // var API created on AI evel
// Create the control mesh
this._controlMesh = BABYLON.Mesh.CreateBox("droneControl_" + id, 0.01, this._scene);
this._controlMesh.isVisible = false;
if (this._team == "R")
this._controlMesh.rotation = new BABYLON.Vector3(0, Math.PI, 0);
this._controlMesh.computeWorldMatrix(true);
// Create the mesh from the drone prefab
this._mesh = DroneManager.Prefab.clone("drone_" + id, this._controlMesh);
this._mesh.position = BABYLON.Vector3.Zero();
this._mesh.isVisible = false;
this._mesh.computeWorldMatrix(true);
// Get the back collider
this._mesh.getChildMeshes().forEach(function (mesh) {
if (mesh.name.substring(mesh.name.length - 13) == "Dummy_arriere") {
_this._colliderBackMesh = mesh;
_this._colliderBackMesh.isVisible = false;
}
else {
if (_this._team !== "R") {
mesh.isVisible = true;
} else {
mesh.isVisible = false;
_this._colliderBackMesh = mesh;
_this._colliderBackMesh.isVisible = false;
}
}
});
// Team color
if (!DroneManager.PrefabBlueMat || !DroneManager.PrefabRedMat) {
DroneManager.PrefabBlueMat = new BABYLON.StandardMaterial("blueTeamMat", scene);
DroneManager.PrefabBlueMat.diffuseTexture = new BABYLON.Texture("assets/drone/drone_bleu.jpg", scene);
DroneManager.PrefabRedMat = new BABYLON.StandardMaterial("redTeamMat", scene);
DroneManager.PrefabRedMat.diffuseTexture = new BABYLON.Texture("assets/drone/drone_rouge.jpg", scene);
}
this._propellerAnimMeshes = [];
this._mesh.getChildren().forEach(function (mesh) {
// Propeller animation
if (mesh.name.substring(mesh.name.length - 7, mesh.name.length - 1) == "helice") {
var anim = new BABYLON.Animation("propellerTurning_" + mesh.name, "rotation.y", 20, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
var keys = [
{ frame: 0, value: 0 },
{ frame: 2, value: Math.PI },
{ frame: 4, value: Math.PI * 2 }
];
anim.setKeys(keys);
mesh.animations.push(anim);
_this._scene.beginAnimation(mesh, 0, 4, true);
_this._propellerAnimMeshes.push(mesh);
}
else {
if (_this._team == "L") {
mesh.material = DroneManager.PrefabBlueMat;
}
else if (_this._team == "R") {
mesh.material = DroneManager.PrefabRedMat;
}
}
});
// jIO auto save
// TO DO : Faire ça avec un vrai timer, puisque le setInterval est cassé si on met en pause
this._internal_jIO_save();
}
DroneManager.prototype._swapAxe = function (vector) {
return new BABYLON.Vector3(vector.x, vector.z, vector.y);
};
Object.defineProperty(DroneManager.prototype, "id", {
//*************************************************** ACCESSOR *****************************************************
get: function () { return this._id; },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "team", {
get: function () { return this._team; },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "colliderMesh", {
get: function () { return this._mesh; },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "colliderBackMesh", {
get: function () { return this._colliderBackMesh; },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "infosMesh", {
get: function () { return this._controlMesh; },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "position", {
get: function () {
if (this._controlMesh !== null) {
return this._swapAxe(this._controlMesh.position);
}
return null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "rotation", {
get: function () { return this._swapAxe(this._controlMesh.rotation); },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "speed", {
get: function () { return this._speed; },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "direction", {
get: function () { return this._swapAxe(this._direction); },
enumerable: true,
configurable: true
});
Object.defineProperty(DroneManager.prototype, "worldDirection", {
get: function () {
var t = this.team === "L" ? 1 : -1;
return new BABYLON.Vector3(t * this._direction.x, this._direction.y, t * this._direction.z);
},
enumerable: true,
configurable: true
});
//*************************************************** FUNCTIONS ****************************************************
//#region ------------------ Internal
// Function called by the GameManager
// Set internal variables then call API function
DroneManager.prototype.internal_start = function () {
this._maxAcceleration = GAMEPARAMETERS.drone.maxAcceleration;
if (this._team == "R") {
if (GAMEPARAMETERS.derive) {
this._maxSpeed = GAMEPARAMETERS.derive.speed;
} else {
this._maxSpeed = 0;
}
} else {
this._maxSpeed = GAMEPARAMETERS.drone.maxSpeed;
}
this._canPlay = true;
this._canCommunicate = true;
try {
return this.onStart();
} catch (error) {
console.warn('Drone crashed on start due to error:', error);
this._internal_crash();
}
};
DroneManager.prototype.internal_update = function (delta_time) {
var context = this;
if (this._controlMesh) {
if (context._rotationTarget) {
var rotStep = BABYLON.Vector3.Zero();
var diff = context._rotationTarget.subtract(context._controlMesh.rotation);
if (diff.x >= 1)
rotStep.x = 1;
else
rotStep.x = diff.x;
if (diff.y >= 1)
rotStep.y = 1;
else
rotStep.y = diff.y;
if (diff.z >= 1)
rotStep.z = 1;
else
rotStep.z = diff.z;
if (rotStep == BABYLON.Vector3.Zero()) {
context._rotationTarget = null;
return;
}
var newrot = new BABYLON.Vector3(context._controlMesh.rotation.x + (rotStep.x * context._rotationSpeed), context._controlMesh.rotation.y + (rotStep.y * context._rotationSpeed), context._controlMesh.rotation.z + (rotStep.z * context._rotationSpeed));
context._controlMesh.rotation = newrot;
}
context._speed += context._acceleration * delta_time / 1000;
if (context._speed > context._maxSpeed)
context._speed = context._maxSpeed;
if (context._speed < -context._maxSpeed)
context._speed = -context._maxSpeed;
var updateSpeed = context._speed * delta_time / 1000;
if (context._direction.x != 0
|| context._direction.y != 0
|| context._direction.z != 0) {
context._controlMesh.position.addInPlace(new BABYLON.Vector3(context._direction.x * updateSpeed, context._direction.y * updateSpeed, context._direction.z * updateSpeed));
}
var orientationValue = context._maxOrientation * (context._speed / context._maxSpeed);
context._mesh.rotation = new BABYLON.Vector3(orientationValue * context._direction.z, 0, -orientationValue * context._direction.x);
context._controlMesh.computeWorldMatrix(true);
context._mesh.computeWorldMatrix(true);
if (context._canUpdate) {
context._canUpdate = false;
return new RSVP.Queue()
.push(function () {
return context.onUpdate();
})
.push(function () {
context._canUpdate = true;
}, function (err) {
console.warn('Drone crashed on update due to error:', err);
context._internal_crash();
});
}
return;
}
return;
};
DroneManager.prototype.internal_touch = function () {
var _this = this;
this.setRotationBy(0, 0, 0);
this.setDirection(0, 0, -1);
this.setAcceleration(this._maxAcceleration);
this._canPlay = false;
if (this._propellerAnimMeshes != null) {
try {
this._propellerAnimMeshes.forEach(function (mesh) {
_this._scene.stopAnimation(mesh);
});
}
catch (ex) { }
this._propellerAnimMeshes = null;
}
this._canCommunicate = false;
this._controlMesh = null;
this._mesh = null;
this.onTouched();
};
DroneManager.prototype._internal_crash = function () {
var _this = this;
if (this._propellerAnimMeshes !== null) {
try {
this._propellerAnimMeshes.forEach(function (mesh) {
_this._scene.stopAnimation(mesh);
});
}
catch (ex) { }
this._propellerAnimMeshes = null;
}
this._canCommunicate = false;
this._controlMesh = null;
this._mesh = null;
this._canPlay = false;
this.onTouched();
this._API._gameManager._onDroneInternalCrash(this);
};
DroneManager.prototype._internal_dispose = function () {
if (this._mesh) {
this._mesh.dispose();
this._mesh = null;
this._controlMesh.dispose();
this._controlMesh = null;
}
};
DroneManager.prototype.internal_finish = function () {
this._canPlay = false;
this._canCommunicate = false;
this._controlMesh = null;
};
DroneManager.prototype.can_play = function () {
return this._canPlay;
};
DroneManager.prototype._internal_jIO_save = function () {
if (this._controlMesh) {
var timestamp = Date.now();
return DroneManager.jIOstorage.put(this._id + "_" + this._team + "_" + timestamp, {
type: "state",
id: this._id,
team: this._team,
timestamp: timestamp,
direction: {
x: this._direction.x,
y: this._direction.z,
z: this._direction.y
},
position: {
x: this._controlMesh.position.x,
y: this._controlMesh.position.z,
z: this._controlMesh.position.y
},
rotation: {
x: this._controlMesh.rotation.x,
y: this._controlMesh.rotation.z,
z: this._controlMesh.rotation.y
},
speed: this._speed
});
}
};
//#endregion
//#region ------------------ Accessible from AI
// Function callable by "me.functionName()" in AI code
// -- Starting info
/**
* Set the starting position of the drone
* Take x,y,z coordinates as parameters
*/
DroneManager.prototype.setStartingPosition = function (x, y, z) {
if(isNaN(x) || isNaN(y) || isNaN(z)){
throw new Error('Position coordinates must be numbers');
}
if (!this._canPlay) {
if (z <= 0.05)
z = 0.05;
this._controlMesh.position = new BABYLON.Vector3(x, z, y);
}
this._controlMesh.computeWorldMatrix(true);
this._mesh.computeWorldMatrix(true);
};
//#region -- Movements
/**
* Set the drone acceleration
* It is in meter / second
*/
DroneManager.prototype.setAcceleration = function (factor) {
if (!this._canPlay)
return;
if (isNaN(factor)){
throw new Error('Acceleration must be a number');
}
if (factor > this._maxAcceleration)
factor = this._maxAcceleration;
this._acceleration = factor;
};
//#region -- Movements
/**
* Set the human derive acceleration
* It is in meter / second
* It has no cap to allow constant speed
*/
DroneManager.prototype.setHumanAcceleration = function (factor) {
if (!this._canPlay)
return;
if (isNaN(factor)){
throw new Error('Acceleration must be a number');
}
this._acceleration = factor;
};
/**
* Set the drone direction
*/
DroneManager.prototype.setDirection = function (x, y, z) {
if (!this._canPlay)
return;
if(isNaN(x) || isNaN(y) || isNaN(z)){
throw new Error('Direction coordinates must be numbers');
}
this._direction = new BABYLON.Vector3(x, z, y).normalize();
};
/**
* Set the drone rotation
*/
DroneManager.prototype.setRotation = function (x, y, z) {
if (!this._canPlay)
return;
if (this._team == "R")
y += Math.PI;
this._rotationTarget = new BABYLON.Vector3(x, z, y);
};
/**
* Add this rotation to the actual drone rotation
*/
DroneManager.prototype.setRotationBy = function (x, y, z) {
if (!this._canPlay)
return;
this._rotationTarget = new BABYLON.Vector3(this.rotation.x + x, this.rotation.y + z, this.rotation.z + y);
};
/**
* Set a target point to move
*/
DroneManager.prototype.setTargetCoordinates = function (x, y, z) {
if (!this._canPlay)
return;
if(isNaN(x) || isNaN(y) || isNaN(z)){
throw new Error('Target coordinates must be numbers');
}
x -= this._controlMesh.position.x;
y -= this._controlMesh.position.z;
z -= this._controlMesh.position.y;
if (this.team == "R")
y = -y;
this.setDirection(x, y, z);
this.setAcceleration(this._maxAcceleration);
};
//#endregion
//#region -- Messaging
/**
* Send a message to team drones
* @param msg The message to send
* @param id The targeted drone. -1 or nothing to broadcast
*/
DroneManager.prototype.sendMsg = function (msg, id) {
var _this = this;
if (!this._canCommunicate)
return;
if (id >= 0) { }
else
id = -1;
if (_this.infosMesh) {
return _this._API.internal_sendMsg(JSON.parse(JSON.stringify(msg)), id);
}
};
/**
* Perform a console.log with drone id + the message
*/
DroneManager.prototype.log = function (msg) { };
//#endregion
//#region -- Game informations
/**
* Get other drone infos
* @param id If no id, return all drones infos
*/
DroneManager.prototype.getDroneInfos = function (id) {
if (!this._canCommunicate)
return;
return this._API.getDroneInfos(this.infosMesh.position, id, this._id);
};
/**
* Get a game parameter by name
* @param name Name of the parameter to retrieve
*/
DroneManager.prototype.getGameParameter = function (name) {
if (!this._canCommunicate)
return;
return this._API.getGameParameter(name);
};
/**
* Get the map
*/
DroneManager.prototype.getMapInfos = function () {
if (!this._canCommunicate)
return;
return this._API.getMapInfos();
};
/**
* get if drone detects the human position
*/
DroneManager.prototype.isHumanPositionSpotted = function () {
if (!this._canCommunicate)
return;
return this._API.isHumanPositionSpotted(this);
};
/**
* get current drone position
*/
DroneManager.prototype.getCurrentPosition = function () {
if (this._controlMesh)
return {
x:this._controlMesh.position.x,
y:this._controlMesh.position.z,
z:this._controlMesh.position.y
};
return null;
};
/**
* Set the reported human position
* @param position information to be set
*/
DroneManager.prototype.reportHumanPosition = function (position) {
this._API._gameManager.reportHumanPosition(position);
};
//#endregion
//#endregion
//#region ------------------ To be defined in AI code
// Function called on evt.
// These functions must be defined in the AI code
/**
* Function called on game start
*/
DroneManager.prototype.onStart = function () { };
;
/**
* Function called on game update
*/
DroneManager.prototype.onUpdate = function () { };
;
/**
* Function called when drone die (crash or collision)
*/
DroneManager.prototype.onTouched = function () { };
;
/**
* Function called when a message is received
* @param msg The message
*/
DroneManager.prototype.onGetMsg = function (msg) { };
;
/**
* Function called when drone finishes the detection process
* @param human_detected true or false
*/
DroneManager.prototype.onCapture = function (human_detected) { };
;
return DroneManager;
}());
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>DroneManager.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/// <reference path="./typings/babylon.3.1.d.ts" />
/// <reference path="./typings/require.d.ts" />
/// <reference path="./DroneManager.ts" />
/// <reference path="./MapManager.ts" />
/// <reference path="./typings/babylon.gui.d.ts" />
var GAMEPARAMETERS = {};
var GameManager = /** @class */ (function (console) {
var browser_console = console,
console_output = '';
console = {
warn: browser_console.warn.bind(browser_console),
log: function () {
var i,
len = arguments.length,
output_list = [];
for (i = 0; i < len; i += 1) {
output_list.push(JSON.stringify(arguments[i]));
}
console_output += output_list.join(' ') + '\n';
browser_console.log.apply(browser_console, arguments);
}
};
//*************************************************** CONSTRUCTOR **************************************************
function GameManager(script, map, simulation_speed) {
var _this = this;
//*************************************************** MEMBERS ******************************************************
// Base Babylon members
this._scene = null;
this._engine = null;
// Teams
this._teamLeft = [];
this._teamRight = [];
// Update registering
this._canUpdate = false;
this._gameFinished = false;
// this._pauseTime = 0;
this._isFullscreen = false;
this._final_score = 0;
Object.assign(GAMEPARAMETERS, map);
this._map = map;
this._map_swapped = false;
this._script = script;
this._updated = false;
this._reported_human_position = false;
this._time_human_position_reported = false;
this._ground_truth_target = false;
this.finish_deferred = null;
if (!simulation_speed) { simulation_speed = 5; }
this._max_step_animation_frame = simulation_speed;
// ----------------------------------- CODE ZONES AND PARAMS
// JIO : AI
// XXX
DroneManager.jIOstorage = jIO.createJIO({
"type": "query",
"sub_storage": {
"type": "indexeddb",
"database": "Drones_infos_storage"
}
});
// Timing display
this._timeDisplay = document.getElementById("timingDisplay");
document.getElementById("simPlay").style.display = "none";
document.getElementById("simPause").style.display = "none";
};
GameManager.prototype.run = function() {
var gadget = this;
return DroneManager.jIOstorage.allDocs()
.push(function (result) {
var promise_list = [], i;
for (i = 0; i < result.data.total_rows; i += 1) {
promise_list.push(DroneManager.jIOstorage.remove(result.data.rows[i].id));
}
return RSVP.all(promise_list);
})
.push(function () {
return gadget._init();
})
.push(function () {
return gadget._final_score;
});
};
GameManager.getLog = function getLog() {
return console_output;
};
Object.defineProperty(GameManager.prototype, "teamLeft", {
//*************************************************** ACCESSOR *****************************************************
get: function () { return this._teamLeft; },
enumerable: true,
configurable: true
});
Object.defineProperty(GameManager.prototype, "teamRight", {
get: function () { return this._teamRight; },
enumerable: true,
configurable: true
});
Object.defineProperty(GameManager.prototype, "gameParameter", {
get: function () {
return this._gameParameter;
},
enumerable: true,
configurable: true
});
//*************************************************** FUNCTIONS ****************************************************
/**
* Display a message in the bottom zone
* @param msg
*/
GameManager.prototype._displayMsg = function (msg) {
document.getElementById("messages").innerText = msg;
};
/**
* Display a message in the bottom zone
* @param msg
*/
GameManager.prototype._formatTimeToMinutesAndSeconds = function (time) {
var seconds = Math.floor(time / 1000),
minutes = Math.floor(seconds / 60),
sminutes = "00",
sseconds = "00";
sminutes = (minutes < 10) ? "0" + minutes.toString() : minutes.toString();
seconds -= (minutes * 60);
sseconds = (seconds < 10) ? "0" + seconds.toString() : sseconds = seconds.toString();
return sminutes + ":" + sseconds;
};
/**
* Store the human position reported by a drone and the detection time
* @param position
*/
GameManager.prototype.reportHumanPosition = function (position) {
this._reported_human_position = position;
this._time_human_position_reported = this._game_duration;
this._finish();
};
/**
* Verify if drone has found the human by checking the position coordinates
* @param reported_human_position
*/
GameManager.prototype.checkHumanDistance = function (reported_human_position) {
if (!reported_human_position)
return -1;
var a = reported_human_position.x - this._ground_truth_target.x,
b = reported_human_position.y - this._ground_truth_target.y,
distance = Math.sqrt( a*a + b*b );
return distance;
};
GameManager.prototype._calculateScore = function (human_found) {
var detection_time = this._time_human_position_reported / 1000;
if (!human_found) {
this._time_human_position_reported = this._totalTime * 1000;
detection_time = this._totalTime;
}
this._final_score = Math.floor(detection_time);
};
GameManager.prototype._displayResult = function () {
var table = document.createElement('table'), tr, th, td, team, div,
main = document.getElementsByClassName("leftZone")[0];
table.setAttribute("id", "result_table");
tr = document.createElement('tr');
td = document.createElement('td');
td.textContent = "Total detection time:";
tr.appendChild(td);
td = document.createElement('td');
td.textContent = this._formatTimeToMinutesAndSeconds(this._time_human_position_reported);
tr.appendChild(td);
table.appendChild(tr);
tr = document.createElement('tr');
td = document.createElement('td');
td.textContent = "Reported human position:";
tr.appendChild(td);
td = document.createElement('td');
if (this._reported_human_position) {
td.textContent = "(" +
Math.round(this._reported_human_position.x * 100) / 100 +
"," + Math.round(this._reported_human_position.y * 100) / 100 + ")";
} else {
td.textContent = "-";
}
tr.appendChild(td);
table.appendChild(tr);
tr = document.createElement('tr');
td = document.createElement('td');
td.textContent = "Real human position:";
tr.appendChild(td);
td = document.createElement('td');
var ground_truth_target_s = "(" +
Math.round(this._ground_truth_target.x * 100) / 100 +
"," + Math.round(this._ground_truth_target.y * 100) / 100 + ")";
td.textContent = ground_truth_target_s;
tr.appendChild(td);
table.appendChild(tr);
tr = document.createElement('tr');
th = document.createElement('th');
th.textContent = "Score";
tr.appendChild(th);
th = document.createElement('th');
th.textContent = Math.round(this._final_score * 100) / 100;
tr.appendChild(th);
table.appendChild(tr);
table.className = "result";
main.appendChild(table);
};
//**************************** INTERNAL FUNCTIONS
/**
* Function called to load all the 3D models
* @param callback Function called when models loaded
*/
GameManager.prototype._load3DModel = function (callback) {
var _this = this;
var assetManager = new BABYLON.AssetsManager(this._scene);
assetManager.useDefaultLoadingScreen = true;
// OBSTACLE
var obstacleTask = assetManager.addMeshTask("loadingObstacle", "", "assets/obstacle/", "boat.babylon");
obstacleTask.onSuccess = function (task) {
task.loadedMeshes.forEach(function (mesh) {
mesh.isPickable = false;
mesh.isVisible = false;
});
ObstacleManager.Prefab = _this._scene.getMeshByName("car");
};
obstacleTask.onError = function () {
console.log("Error loading 3D model for Obstacle");
};
// DRONE
var droneTask = assetManager.addMeshTask("loadingDrone", "", "assets/drone/", "drone.babylon");
droneTask.onSuccess = function (task) {
task.loadedMeshes.forEach(function (mesh) {
mesh.isPickable = false;
mesh.isVisible = false;
});
DroneManager.Prefab = _this._scene.getMeshByName("Dummy_Drone");
DroneManager.Prefab.scaling = new BABYLON.Vector3(0.006, 0.006, 0.006);
DroneManager.Prefab.position = new BABYLON.Vector3(0, -5, 0);
};
droneTask.onError = function () {
console.log("Error loading 3D model for Drone");
};
// MAP
var mapTask = assetManager.addMeshTask("loadingMap", "", "assets/map/", "map.babylon");
mapTask.onSuccess = function (task) {
task.loadedMeshes.forEach(function (mesh) {
mesh.isPickable = false;
mesh.isVisible = false;
});
};
mapTask.onError = function () {
console.log("Error loading 3D model for Map");
};
assetManager.onFinish = function () {
return callback();
};
assetManager.load();
};
/**
* Update the displayed timing
*/
GameManager.prototype._updateTiming = function (delta_time, update_dom) {
// Timing display
this._game_duration += delta_time;
var seconds = Math.floor(this._game_duration / 1000);
if (this._totalTime - seconds <= 0) {
this._time_human_position_reported = this._game_duration;
this._finish(time_out=true);
}
if (update_dom) {
this._timeDisplay.textContent = this._formatTimeToMinutesAndSeconds(this._game_duration);
}
};
/**
* Function used to check collision between 2 drones
* @param drone1
* @param drone2
*/
GameManager.prototype._checkCollision = function (drone, other) {
if (drone.colliderMesh && other.colliderMesh
&& drone.colliderMesh.intersectsMesh(other.colliderMesh, false)) {
var angle = Math.acos(BABYLON.Vector3.Dot(drone.worldDirection, other.worldDirection) / (drone.worldDirection.length() * other.worldDirection.length()));
var dteam = "blue";
var msg = void 0;
if (drone.team == "R")
dteam = "red";
var oteam = "blue";
if (other.team == "R")
oteam = "red";
if (angle < GAMEPARAMETERS.drone.collisionSector) {
if (drone.speed > other.speed) {
this._gameResult[other.team].crash += 1;
other.internal_touch();
msg = "Drone " + drone.id + " bump drone " + other.id + "!";
}
else {
this._gameResult[drone.team].crash += 1;
drone.internal_touch();
msg = "Drone " + other.id + " bump drone " + drone.id + "!";
}
}
else {
msg = "Drone " + drone.id + " touched drone " + other.id + "!";
this._gameResult[other.team].crash += 1;
this._gameResult[drone.team].crash += 1;
drone.internal_touch();
other.internal_touch();
}
this._displayMsg(msg);
}
};
/**
* Function used to check collision between 1 drone and an special obstacle
* @param drone
* @param obstacle
*/
GameManager.prototype._checkCollisionWithSpecialObstacle = function (drone, obstacle) {
if (drone.colliderMesh && obstacle.colliderMesh
&& drone.colliderMesh.intersectsMesh(obstacle.colliderMesh, false)) {
this._gameResult[drone.team].crash += 1;
drone.internal_touch();
this._displayMsg("Drone " + drone.id + " touched an obstacle");
}
};
/**
* Function used to check collision between 1 drone and an obstacle
* @param drone
* @param obstacle
*/
GameManager.prototype._checkCollisionWithObstacle = function (drone, obstacle) {
if (obstacle.obsType === "boat") {
return this._checkCollisionWithSpecialObstacle(drone, obstacle);
}
if (drone.colliderMesh
&& drone.colliderMesh.intersectsMesh(obstacle, true)) {
/**
* Closest facet check is needed for sphere and cylinder, but just seemed bugged with the box
* So only need to check intersectMesh for the box
*/
var closest = void 0;
if (obstacle["obsType"] == "box") {
closest = true;
}
else {
obstacle.updateFacetData();
var projected = BABYLON.Vector3.Zero();
closest = obstacle.getClosestFacetAtCoordinates(drone.infosMesh.position.x, drone.infosMesh.position.y, drone.infosMesh.position.z, projected);
}
if (closest != null) {
drone.internal_touch();
var dteam = "blue";
if (drone.team == "R")
dteam = "red";
this._gameResult[drone.team].obstacle += 1;
this._displayMsg("Drone n" + drone.id + " touched an obstacle!");
}
}
};
/**
* Function to check collision with floor
* @param drone
*/
GameManager.prototype._checkCollisionWithFloor = function (drone) {
if (drone.infosMesh) {
if (drone.position.z < 9) {
return true;
}
}
return false;
};
/**
* Function to check drone out of the map
* @param drone
*/
GameManager.prototype._checkDroneOut = function (drone) {
if (drone.position !== null) {
if (drone.position.z > 100) {
return true;
}
return BABYLON.Vector3.Distance(drone.position, BABYLON.Vector3.Zero()) > GAMEPARAMETERS.distances.control;
}
};
/**
* Function to check game finish
*/
GameManager.prototype._allDroneAreOut = function () {
return this._gameResult.L.out + this._gameResult.L.crash === GAMEPARAMETERS.teamSize;
};
GameManager.prototype._getGameParameter = function () {
var parameter = {}, i, swap = function (pos) {
return {
x: pos.x,
y: pos.z,
z: pos.y
};
};
Object.assign(parameter, this._map);
this._gameParameter = {};
Object.assign(this._gameParameter, this._map);
for (i = 0; i < parameter.obstacles.length; i += 1) {
parameter.obstacles[i].position = swap(parameter.obstacles[i].position);
if (parameter.obstacles[i].scale) {
parameter.obstacles[i].scale = swap(parameter.obstacles[i].scale);
}
if (parameter.obstacles[i].rotation) {
parameter.obstacles[i].rotation = swap(parameter.obstacles[i].rotation);
}
}
parameter.goalPositionLeftTeam = swap(parameter.goalPositionLeftTeam);
parameter.goalPositionRightTeam = swap(parameter.goalPositionRightTeam);
return parameter;
};
GameManager.prototype._setSpawnDrone = function (x, y, z, index, api, code, team) {
var ctx = this, base, code_eval = "let drone = new DroneManager(ctx._scene, "
+ index + ', "' + team + '", api);'
+ "let droneMe = function(NativeDate, me, Math, window, DroneManager, GameManager, DroneAPI, BABYLON, GAMEPARAMETERS) {"
+ "var start_time = (new Date(2070, 0, 0, 0, 0, 0, 0)).getTime();"
+ "Date.now = function () {return start_time + drone._tick * 1000/60;}; "
+ "function Date() {if (!(this instanceof Date)) {throw new Error('Missing new operator');} "
+ "if (arguments.length === 0) {return new NativeDate(Date.now());} else {return new NativeDate(...arguments);}}";
// Simple desactivation of direct access of all globals
// It is still accessible in reality, but it will me more visible
// if people really access them
if (x !== null && y !== null && z !== null) {
code_eval += "me.setStartingPosition("
+ x + ", " + y + ", " + z + ");";
}
base = code_eval;
code_eval += code + "}; droneMe(Date, drone, Math, {});";
//code_eval += code + "}; droneMe(drone, Math, {});";
if (team == "R") {
base += "};ctx._teamRight.push(drone)";
code_eval += "ctx._teamRight.push(drone)";
}
else {
base += "};ctx._teamLeft.push(drone)";
code_eval += "ctx._teamLeft.push(drone)";
}
try {
eval(code_eval);
}
catch (error) {
eval(base);
}
};
GameManager.prototype._setRandomSpawnPosition = function (randomSpawn, team_size, api, code, team) {
var position, i, position_list = [], center = randomSpawn.position, max_collision = randomSpawn.maxCollision || 10 * team_size, collision_nb = 0;
function randomSpherePoint(x0, y0, z0, rx0, ry0, rz0) {
var u = Math.random(),
v = Math.random(),
rx = Math.random() * rx0,
ry = Math.random() * ry0,
rz = Math.random() * rz0,
theta = 2 * Math.PI * u,
phi = Math.acos(2 * v - 1),
x = x0 + (rx * Math.sin(phi) * Math.cos(theta)),
y = y0 + (ry * Math.sin(phi) * Math.sin(theta)),
z = z0 + (rz * Math.cos(phi));
return new BABYLON.Vector3(x, y, z);
}
function checkCollision(position, list) {
var i;
for (i = 0; i < list.length; i += 1) {
if (position.equalsWithEpsilon(list[i], 0.5)) {
return true;
}
}
return false;
}
for (i = 0; i < team_size; i += 1) {
//set only one element for right team (the human)
if (team === "L" || i === 0) {
if (GAMEPARAMETERS.randomSpawn.rightTeam.dispersed) {
position = randomSpherePoint(center.x + i, center.y + i, center.z + i, 0, 0, 0);
} else {
position = randomSpherePoint(center.x, center.y, center.z, randomSpawn.dispertion.x, randomSpawn.dispertion.y, randomSpawn.dispertion.z);
}
if (team === "R") {
this._setSpawnDrone(this._ground_truth_target.x, this._ground_truth_target.y, this._ground_truth_target.z, i, api, code, team);
} else {
if (checkCollision(position, position_list) || position.z < 0.05) {
collision_nb += 1;
if (collision_nb < max_collision) {
i -= 1;
}
}
else {
position_list.push(position);
this._setSpawnDrone(position.x, position.y, position.z, i, api, code, team);
}
}
}
}
};
GameManager.prototype.delay = function (callback, millisecond) {
this._delayed_defer_list.push([callback, millisecond]);
}
//**************************** GAME STATES
/**
* Function called to init the engine and scene, prepare all the things, then start the game.
*/
GameManager.prototype._init = function () {
this._displayMsg("Simulation loading ...");
function randomSpherePoint(x0, y0, z0, rx0, ry0, rz0) {
var u = Math.random(), v = Math.random(), rx = Math.random() * rx0, ry = Math.random() * ry0, rz = Math.random() * rz0, theta = 2 * Math.PI * u, phi = Math.acos(2 * v - 1), x = x0 + (rx * Math.sin(phi) * Math.cos(theta)), y = y0 + (ry * Math.sin(phi) * Math.sin(theta)), z = z0 + (rz * Math.cos(phi));
return new BABYLON.Vector3(x, y, z);
}
var _this = this,
center = GAMEPARAMETERS.randomSpawn.rightTeam.position,
dispertion = GAMEPARAMETERS.randomSpawn.rightTeam.dispertion;
if (GAMEPARAMETERS.randomSpawn.rightTeam.dispersed)
dispertion = {x: 0, y: 0, z: 0};
this._ground_truth_target = randomSpherePoint(center.x, center.y, center.z, dispertion.x, dispertion.y, dispertion.z);
this._delayed_defer_list = [];
// TODO cleanup _gameResult (drop some parts like obstacle)
this._gameResult = {
"L": { "goal": 0, "crash": 0, "out": 0, "obstacle": 0 },
"R": { "goal": 0, "crash": 0, "out": 0, "obstacle": 0 }
};
this._dispose();
document.getElementById("simPlay").style.display = "none";
// ----------------------------------- SIMULATION - 3Dscene
// Get the canvas
var canvas = document.getElementById("simCanvas");
// Create the Babylon engine
this._engine = new BABYLON.Engine(canvas, true);
this._engine.enableOfflineSupport = false;
// Create the base scene
this._scene = new BABYLON.Scene(this._engine);
this._scene.clearColor = new BABYLON.Color4(88/255,171/255,217/255,255/255);
// this._scene.debugLayer.show();
// Collisions
this._scene.collisionsEnabled = true;
// Lights
var hemi_north = new BABYLON.HemisphericLight("hemiN", new BABYLON.Vector3(1, -1, 1), this._scene);
hemi_north.intensity = .75;
var hemi_south = new BABYLON.HemisphericLight("hemiS", new BABYLON.Vector3(-1, 1, -1), this._scene);
hemi_south.intensity = .75;
var radius = (GAMEPARAMETERS.mapSize.width/3 < 75) ? 75 : GAMEPARAMETERS.mapSize.width/3,
vector_x = (this._ground_truth_target.x > -50 && this._ground_truth_target.x < 50) ? 0 : this._ground_truth_target.x,
vector_y = (this._ground_truth_target.y > -50 && this._ground_truth_target.y < 50) ? 0 : this._ground_truth_target.y,
camera, x_rotation;
if (this._ground_truth_target.x > 0 && this._ground_truth_target.y > 0) {
x_rotation = 1;
} else if (this._ground_truth_target.x > 0 && this._ground_truth_target.y < 0) {
x_rotation = 200;
} else if (this._ground_truth_target.x < 0 && this._ground_truth_target.y < 0) {
x_rotation = 400;
} else {
x_rotation = 750;
}
//cap camera distance to 1km
if (radius > 800) radius = 800;
camera = new BABYLON.ArcRotateCamera("camera", x_rotation, 1.25, radius, new BABYLON.Vector3(vector_x, 0, vector_y), this._scene);
camera.wheelPrecision = 10;
camera.attachControl(this._scene.getEngine().getRenderingCanvas());
camera.maxz = 40000
// Render loop
this._engine.runRenderLoop(function () {
_this._scene.render();
});
// Resize canvas on window resize
window.addEventListener('resize', function () {
_this._engine.resize();
});
// ----------------------------------- SIMULATION - Prepare API, Map and Teams
var on3DmodelsReady = function (ctx) {
// Get the game parameters
if (!ctx._map_swapped) {
GAMEPARAMETERS = ctx._getGameParameter();
ctx._map_swapped = true;
}
// Create the API
var lAPI = new DroneAPI(ctx, "L");
var rAPI = new DroneAPI(ctx, "R");
// Set the AI code into drones
var AIcodeEval, AIcodeRight, AIcodeLeft;
AIcodeLeft = ctx._script;
//set AI for the target (derive or do nothing)
if (GAMEPARAMETERS.derive) {
AIcodeRight = `me.onStart = function() { me.setHumanAcceleration(99999); me.setDirection(${GAMEPARAMETERS.derive.direction.x},${GAMEPARAMETERS.derive.direction.y},0); }`;
} else {
AIcodeRight = "me.onStart = function() { me.setAcceleration(0); me.setDirection(0,0,0); }";
}
// Init the map
_this._mapManager = new MapManager(ctx._scene);
// If positions are defined in GameParameter
if (GAMEPARAMETERS.spawnPositions && GAMEPARAMETERS.spawnPositions.length > 0) {
GAMEPARAMETERS.teamSize = GAMEPARAMETERS.spawnPositions.length;
var pos = void 0;
// Load the left team code into left team drones
for (var index = 0; index < GAMEPARAMETERS.spawnPositions.length; index++) {
pos = GAMEPARAMETERS.spawnPositions[index];
ctx._setSpawnDrone(-pos.x, -pos.y, pos.z, index, lAPI, AIcodeLeft, "L");
}
// Load the right team code into right team drones
for (var index = 0; index < GAMEPARAMETERS.spawnPositions.length; index++) {
//set only one drone for right team (the target)
if (index === 0) {
pos = GAMEPARAMETERS.spawnPositions[index];
ctx._setSpawnDrone(pos.x, pos.y, pos.z, index, rAPI, AIcodeRight, "R");
}
}
}
else if (GAMEPARAMETERS.randomSpawn) {
ctx._setRandomSpawnPosition(GAMEPARAMETERS.randomSpawn.leftTeam, GAMEPARAMETERS.teamSize, lAPI, AIcodeLeft, "L");
ctx._setRandomSpawnPosition(GAMEPARAMETERS.randomSpawn.rightTeam, GAMEPARAMETERS.teamSize, rAPI, AIcodeRight, "R");
}
else {
// Load the left team code into left team drones
for (var count = 0; count < GAMEPARAMETERS.teamSize; count++) {
ctx._setSpawnDrone(null, null, null, count, lAPI, AIcodeLeft, "L");
}
// Load the right team code into right team drones
for (var count = 0; count < GAMEPARAMETERS.teamSize; count++) {
//set only one drone for right team (the target)
if (count === 0) {
ctx._setSpawnDrone(null, null, null, count, rAPI, AIcodeRight, "R");
}
}
}
// Hide the drone prefab
DroneManager.Prefab.isVisible = false;
// Save Game params and AI codes
// this._saveParamsAndAiCodes();
//GUI for drones ID display
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
for (var count = 0; count < GAMEPARAMETERS.teamSize; count++) {
var controlMeshBlue = ctx._teamLeft[count].infosMesh;
//set only one drone for right team (the target)
if (count === 0) {
var controlMeshRed = ctx._teamRight[count].infosMesh;
var ellipse = new BABYLON.GUI.Ellipse();
ellipse.height = "10px";
ellipse.width = "15px";
ellipse.thickness = 4;
ellipse.color = "red";
ellipse.linkOffsetY = 0;
advancedTexture.addControl(ellipse);
ellipse.linkWithMesh(controlMeshRed);
}
var rectBlue = new BABYLON.GUI.Rectangle();
if (count < 100)
rectBlue.width = "10px";
else
rectBlue.width = "14px";
rectBlue.height = "10px";
rectBlue.cornerRadius = 20;
rectBlue.color = "white";
rectBlue.thickness = 0.5;
rectBlue.background = "blue";
advancedTexture.addControl(rectBlue);
var labelBlue = new BABYLON.GUI.TextBlock();
labelBlue.text = count.toString();
labelBlue.fontSize = 7;
rectBlue.addControl(labelBlue);
rectBlue.linkWithMesh(controlMeshBlue);
rectBlue.linkOffsetY = 0;
}
return ctx;
};
// ----------------------------------- SIMULATION - Load 3D models
return new RSVP.Queue()
.push(function () {
return new RSVP.Promise(function (resolve) {
return _this._load3DModel(resolve);
});
})
.push(function () {
on3DmodelsReady(_this);
// 3,2,1,GO before start. To animate.
var result = new RSVP.Queue(),
i;
function countdown (count) {
return function () {
_this._displayMsg(count + " ...");
return RSVP.delay(200);
};
}
for (i = 5; 0 <= i; i -= 1) {
result.push(countdown(i));
}
return result.push(_this._start.bind(_this));
});
};
/**
* Function called on game start
*/
GameManager.prototype._start = function () {
var _this = this,
waiting_update_count,
ongoing_update_promise = null;
_this.finish_deferred = RSVP.defer();
this._displayMsg("Simulation started.");
// Timing
this._game_duration = 0;
this._totalTime = GAMEPARAMETERS.gameTime;
this._canUpdate = true;
return new RSVP.Queue()
.push(function () {
promise_list = []
_this._teamLeft.forEach(function (drone) {
drone._tick = 0;
promise_list.push(drone.internal_start());
});
_this._teamRight.forEach(function (drone) {
drone._tick = 0;
promise_list.push(drone.internal_start());
});
return RSVP.all(promise_list);
})
.push(function () {
_this._scene.registerBeforeRender(function () {
// To increase the game speed, increase this value
//_this._max_step_animation_frame = 10,
// time delta means that drone are updated every virtual second
// This is fixed and must not be modified
// otherwise, it will lead to different scenario results
// (as drone calculations may be triggered less often)
//TIME_DELTA = 1000 / 30,
var TIME_DELTA = 1000 / 60,
i;
// init the value on the first step
waiting_update_count = _this._max_step_animation_frame;
function triggerUpdateIfPossible() {
if ((_this._canUpdate) && (ongoing_update_promise === null) && (0 < waiting_update_count)) {
//TODO FIX
//by duplicating time_delta (to 1000/30) the game runs two times faster (ok)
//by adding a delay of a time_delta, it should run 'normal' again
//but it runs slower: 1 real minute is around 40 seconds in simulation (but not exactly 40, some miliseconds more)
//I don't understand it, there's some kind of (large) overhead here
//ongoing_update_promise = new RSVP.Queue(RSVP.all([_this._update(TIME_DELTA), RSVP.delay(TIME_DELTA)]))
ongoing_update_promise = _this._update(TIME_DELTA, (waiting_update_count === 1))
.push(function () {
waiting_update_count -= 1;
ongoing_update_promise = null;
triggerUpdateIfPossible();
})
.push(undefined, _this.finish_deferred.reject.bind(_this.finish_deferred));
}
}
triggerUpdateIfPossible();
});
return _this.finish_deferred.promise;
});
};
/**
* Function called after refresh for restart
*/
GameManager.prototype._restartAfterRefresh = function () {
if (localStorage.getItem('restart') == 'true') {
this._init();
localStorage.setItem('restart', 'false');
}
};
/**
* Function called after a drone internal crash
*/
GameManager.prototype._onDroneInternalCrash = function (drone) {
this._gameResult[drone.team].crash += 1;
this._displayMsg("Drone " + drone.id + " crashed!");
};
/**
* Function called on game update
*/
GameManager.prototype._update = function (delta_time, update_dom) {
var _this = this,
queue = new RSVP.Queue(),
i;
this._updateTiming(delta_time, update_dom);
// trigger all deferred calls if it is time
for (i = _this._delayed_defer_list.length - 1; 0 <= i; i -= 1) {
_this._delayed_defer_list[i][1] = _this._delayed_defer_list[i][1] - delta_time;
if (_this._delayed_defer_list[i][1] <= 0) {
queue.push(_this._delayed_defer_list[i][0]);
_this._delayed_defer_list.splice(i, 1);
}
}
function updateDrone(drone) {
var msg = '';
drone._tick += 1;
if (drone.can_play()) {
if (_this._checkCollisionWithFloor(drone)) {
_this._gameResult.L.crash += 1;
msg = "Drone " + drone.id + " touched the sea!";
drone.internal_touch();
}
else if (_this._checkDroneOut(drone)) {
_this._gameResult.L.out += 1;
msg = "Drone " + drone.id + " touched out of limits!";
drone.internal_touch();
}
else {
_this._teamLeft.forEach(function (other) {
if (other.can_play() && drone.id != other.id) {
_this._checkCollision(drone, other);
}
});
_this._teamRight.forEach(function (other) {
if (other.can_play()) {
_this._checkCollision(drone, other);
}
});
_this._mapManager.obstacles.forEach(function (obstacle) {
_this._checkCollisionWithObstacle(drone, obstacle);
});
}
}
if (msg)
_this._displayMsg(msg);
return drone.internal_update(delta_time);
}
function updateHuman(human) {
var result = human.internal_update(delta_time);
_this._ground_truth_target = {
x: human.position.x,
y: human.position.y,
z: human.position.z
};
return result;
}
// Check collisions -- Drone swarm
this._teamLeft.forEach(function (drone) {
queue.push(function () {
return updateDrone(drone);
});
});
// Update position -- Human
this._teamRight.forEach(function (human) {
queue.push(function () {
return updateHuman(human);
});
});
return queue
.push(function () {
if (_this._allDroneAreOut()) {
return _this._finish();
}
});
};
/**
* Function called when game end
*/
GameManager.prototype._finish = function (time_out) {
this._canUpdate = false;
if (this._reported_human_position) {
//mark the reported position with a green point in the map
var api = new DroneAPI(this, "R"),
code = `me.start = function() { me.setAcceleration(${GAMEPARAMETERS.derive.acceleration}); me.setDirection(${GAMEPARAMETERS.derive.direction.x},${GAMEPARAMETERS.derive.direction.y},0); }`;
this._setSpawnDrone(this._reported_human_position.x,
this._reported_human_position.y,
0.1, 0, api, code, "R");
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI"),
controlMeshGreen = this._teamRight[1].infosMesh,
rectGreen = new BABYLON.GUI.Rectangle();
rectGreen.width = "10px";
rectGreen.height = "10px";
rectGreen.cornerRadius = 20;
rectGreen.color = "white";
rectGreen.thickness = 0.5;
rectGreen.background = "green";
advancedTexture.addControl(rectGreen);
var labelGreen = new BABYLON.GUI.TextBlock();
labelGreen.text = "X";
labelGreen.fontSize = 7;
rectGreen.addControl(labelGreen);
rectGreen.linkWithMesh(controlMeshGreen);
rectGreen.linkOffsetY = 0;
}
var msg, human_found = false,
distance = this.checkHumanDistance(this._reported_human_position);
if (time_out) {
msg = "FAIL: timeout. The human position was not reported.";
} else if (!this._reported_human_position) {
msg = "FAIL: all drones are down, human position was not reported.";
} else if (distance > 40) {
distance = Math.round(distance * 100) / 100;
msg = "FAIL: human is " + distance + " meters away from the reported position.";
} else {
msg = "HUMAN FOUND!";
human_found = true;
}
this._displayMsg(msg);
this._calculateScore(human_found);
this._displayResult();
this._teamLeft.forEach(function (drone) {
drone.internal_finish();
});
this._teamRight.forEach(function (drone) {
drone.internal_finish();
});
return this.finish_deferred.resolve();
};
/**
* Function called on game stop
*/
GameManager.prototype._dispose = function () {
// Dispose the engine
if (this._scene) {
this._scene.dispose();
}
};
//**************************** UTILS
GameManager.prototype.YupToZup = function (axes) {
var tempy = axes.y;
axes.y = axes.z;
axes.z = tempy;
};
GameManager.prototype.ZupToYup = function (axes) {
var tempz = axes.z;
axes.z = axes.y;
axes.y = tempz;
};
return GameManager;
}(console));
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>GameManager.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/// <reference path="./typings/babylon.3.1.d.ts" />
var MapManager = /** @class */ (function () {
//*************************************************** CONSTRUCTOR **************************************************
function MapManager(scene) {
var _this = this;
var max = GAMEPARAMETERS.mapSize.width;
if (GAMEPARAMETERS.mapSize.depth > max)
max = GAMEPARAMETERS.mapSize.depth;
if (GAMEPARAMETERS.mapSize.height > max)
max = GAMEPARAMETERS.mapSize.height;
max = max < GAMEPARAMETERS.mapSize.depth ? GAMEPARAMETERS.mapSize.depth : max;
// Skybox
var max_sky = (max * 10 < 20000) ? max * 10 : 20000,
skybox = BABYLON.Mesh.CreateBox("skyBox", max_sky, scene);
skybox.infiniteDistance = true;
skybox.renderingGroupId = 0;
var skyboxMat = new BABYLON.StandardMaterial("skybox", scene);
skyboxMat.backFaceCulling = false;
skyboxMat.disableLighting = true;
skyboxMat.reflectionTexture = new BABYLON.CubeTexture("./assets/skybox/sky", scene);
skyboxMat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skyboxMat.infiniteDistance = true;
skybox.material = skyboxMat;
// Plane from bottom
var largeGroundMat = new BABYLON.StandardMaterial("largeGroundMat", scene);
largeGroundMat.specularColor = BABYLON.Color3.Black();
largeGroundMat.alpha = 0.4;
var largeGroundBottom = BABYLON.Mesh.CreatePlane("largeGroundBottom", max * 11, scene);
largeGroundBottom.position.y = -0.01;
largeGroundBottom.rotation.x = -Math.PI / 2;
largeGroundBottom.rotation.y = Math.PI;
largeGroundBottom.material = largeGroundMat;
// Camera
scene.activeCamera.upperRadiusLimit = max * 4;
// Terrain
var width = GAMEPARAMETERS.mapSize.width,
depth = GAMEPARAMETERS.mapSize.depth,
height = GAMEPARAMETERS.mapSize.height,
terrain = scene.getMeshByName("terrain001");
terrain.isVisible = true;
terrain.position = BABYLON.Vector3.Zero();
terrain.scaling = new BABYLON.Vector3(depth / 50000, depth / 50000, width / 50000);
// Goals
this._rGoal = BABYLON.Mesh.CreateSphere("rightGoal", 32, GAMEPARAMETERS.goalDiameter, scene);
var rGoalMat = new BABYLON.StandardMaterial("rGoalMat", scene);
rGoalMat.alpha = 0.0;
rGoalMat.diffuseColor = BABYLON.Color3.Red();
this._rGoal.material = rGoalMat;
this._rGoal.position = new BABYLON.Vector3(GAMEPARAMETERS.goalPositionRightTeam.x, GAMEPARAMETERS.goalPositionRightTeam.y, GAMEPARAMETERS.goalPositionRightTeam.z);
this._rGoal.computeWorldMatrix(true);
this._lGoal = BABYLON.Mesh.CreateSphere("leftGoal", 32, GAMEPARAMETERS.goalDiameter, scene);
goal_x = GAMEPARAMETERS.goalPositionLeftTeam.x;
goal_y = GAMEPARAMETERS.goalPositionLeftTeam.y;
goal_z = GAMEPARAMETERS.goalPositionLeftTeam.z;
this._lGoal.position = new BABYLON.Vector3(goal_x, goal_y, goal_z);
var lGoalMat = new BABYLON.StandardMaterial("lGoalMat", scene);
lGoalMat.alpha = 0.0;
lGoalMat.diffuseColor = BABYLON.Color3.Blue();
this._lGoal.material = lGoalMat;
this._lGoal.computeWorldMatrix(true);
//base is now a boat (special object)
ObstacleManager.Prefab.rotation = new BABYLON.Vector3(20.4, 0, 0);
ObstacleManager.Prefab.scaling = new BABYLON.Vector3(15, 15, 15);
goalPart1 = new ObstacleManager("goal_1", scene);
goalPart1.setStartingPosition(goal_x, goal_y, goal_z);
goalPart2 = BABYLON.MeshBuilder.CreateBox("goal_2", { 'size': 1 }, scene);
goalPart2.position = new BABYLON.Vector3(goal_x - 0.5, goal_y + 1.5, goal_z + 1.5);
goalPart2.rotation = new BABYLON.Vector3(0, 0, 0);
goalPart2.scaling = new BABYLON.Vector3(2, 2, 1.5);
goalPart3 = BABYLON.MeshBuilder.CreateCylinder("goal_3", {
'diameterBottom': 1.5,
'diameterTop': 1.5,
'height': 1
}, scene);
goalPart3.position = new BABYLON.Vector3(goal_x + 2.5, goal_y + 1.5, goal_z + 1.5);
goalPart3.rotation = new BABYLON.Vector3(0, 0, 0);
goalPart3.scaling = new BABYLON.Vector3(1.5, 3.5, 1.5);
// Obstacles
var count = 0;
this._obstacles = [];
GAMEPARAMETERS.obstacles.forEach(function (obs) {
var newObj;
switch (obs.type) {
case "box":
newObj = BABYLON.MeshBuilder.CreateBox("obs_" + count, { 'size': 1 }, scene);
break;
case "cylinder":
newObj = BABYLON.MeshBuilder.CreateCylinder("obs_" + count, {
'diameterBottom': obs.diameterBottom,
'diameterTop': obs.diameterTop,
'height': 1
}, scene);
break;
case "sphere":
newObj = BABYLON.MeshBuilder.CreateSphere("obs_" + count, {
'diameterX': obs.scale.x,
'diameterY': obs.scale.y,
'diameterZ': obs.scale.z
}, scene);
break;
case "boat":
ObstacleManager.Prefab.rotation = new BABYLON.Vector3(obs.rotation.x, obs.rotation.y, obs.rotation.z);
ObstacleManager.Prefab.scaling = new BABYLON.Vector3(obs.scale.x * 2, obs.scale.y * 2, obs.scale.z * 2);
newObj = new ObstacleManager("obs_" + count, scene);
newObj.setStartingPosition(obs.position.x, obs.position.y, obs.position.z);
break;
default:
return;
}
newObj["obsType"] = obs.type;
var convertion = Math.PI / 180;
if ("position" in obs)
newObj.position = new BABYLON.Vector3(obs.position.x, obs.position.y, obs.position.z);
if ("rotation" in obs)
newObj.rotation = new BABYLON.Vector3(obs.rotation.x * convertion, obs.rotation.y * convertion, obs.rotation.z * convertion);
if ("scale" in obs)
newObj.scaling = new BABYLON.Vector3(obs.scale.x, obs.scale.y, obs.scale.z);
_this._obstacles.push(newObj);
});
}
Object.defineProperty(MapManager.prototype, "lGoal", {
get: function () { return this._lGoal; },
enumerable: true,
configurable: true
});
Object.defineProperty(MapManager.prototype, "rGoal", {
get: function () { return this._rGoal; },
enumerable: true,
configurable: true
});
Object.defineProperty(MapManager.prototype, "obstacles", {
get: function () { return this._obstacles; },
enumerable: true,
configurable: true
});
return MapManager;
}());
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>MapManager.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/// <reference path="./typings/babylon.3.1.d.ts" />
var ObstacleManager = /** @class */ (function () {
//*************************************************** CONSTRUCTOR **************************************************
function ObstacleManager(id, scene) {
// Mesh
this._mesh = null;
this._controlMesh = null;
this._colliderBackMesh = null;
this._maxOrientation = Math.PI / 4;
this._scene = scene;
this._id = id;
// Create the control mesh
this._controlMesh = BABYLON.Mesh.CreateBox("obstacleControl_" + id, 0.01, this._scene);
this._controlMesh.isVisible = false;
this._controlMesh.rotation = new BABYLON.Vector3(0, Math.PI, 0);
this._controlMesh.computeWorldMatrix(true);
// Create the mesh from the obstacle prefab
this._mesh = ObstacleManager.Prefab.clone("obstacle_" + id, this._controlMesh);
this._mesh.position = BABYLON.Vector3.Zero();
this._mesh.isVisible = true;
this._mesh.computeWorldMatrix(true);
this._propellerAnimMeshes = [];
}
// API
ObstacleManager.prototype._swapAxe = function (vector) {
return new BABYLON.Vector3(vector.x, vector.z, vector.y);
};
Object.defineProperty(ObstacleManager.prototype, "colliderMesh", {
//*************************************************** ACCESSOR *****************************************************
get: function () { return this._mesh; },
enumerable: true,
configurable: true
});
Object.defineProperty(ObstacleManager.prototype, "colliderBackMesh", {
get: function () { return this._colliderBackMesh; },
enumerable: true,
configurable: true
});
Object.defineProperty(ObstacleManager.prototype, "infosMesh", {
get: function () { return this._controlMesh; },
enumerable: true,
configurable: true
});
Object.defineProperty(ObstacleManager.prototype, "position", {
get: function () {
if (this._controlMesh !== null) {
return this._swapAxe(this._controlMesh.position);
}
return null;
},
enumerable: true,
configurable: true
});
//*************************************************** FUNCTIONS ****************************************************
// -- Starting info
/**
* Set the starting position of the obstacle
* Take x,y,z coordinates as parameters
*/
ObstacleManager.prototype.setStartingPosition = function (x, y, z) {
this._controlMesh.position = new BABYLON.Vector3(x, y, z);
this._controlMesh.computeWorldMatrix(true);
this._mesh.computeWorldMatrix(true);
};
return ObstacleManager;
}());
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>ObstacleManager.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>libraries</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>babylon.gui.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>babylon.min.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 2.3.5 Copyright jQuery Foundation and other contributors.
* Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE
*/
//Not using strict: uneven strict support in browsers, #392, and causes
//problems with requirejs.exec()/transpiler plugins that may not be strict.
/*jslint regexp: true, nomen: true, sloppy: true */
/*global window, navigator, document, importScripts, setTimeout, opera */
var requirejs, require, define;
(function (global, setTimeout) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
version = '2.3.5',
commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
currDirRegExp = /^\.\//,
op = Object.prototype,
ostring = op.toString,
hasOwn = op.hasOwnProperty,
isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document),
isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
//PS3 indicates loaded and complete, but need to wait for complete
//specifically. Sequence is 'loading', 'loaded', execution,
// then 'complete'. The UA check is unfortunate, but not sure how
//to feature test w/o causing perf issues.
readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
/^complete$/ : /^(complete|loaded)$/,
defContextName = '_',
//Oh the tragedy, detecting opera. See the usage of isOpera for reason.
isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
contexts = {},
cfg = {},
globalDefQueue = [],
useInteractive = false;
//Could match something like ')//comment', do not lose the prefix to comment.
function commentReplace(match, singlePrefix) {
return singlePrefix || '';
}
function isFunction(it) {
return ostring.call(it) === '[object Function]';
}
function isArray(it) {
return ostring.call(it) === '[object Array]';
}
/**
* Helper function for iterating over an array. If the func returns
* a true value, it will break out of the loop.
*/
function each(ary, func) {
if (ary) {
var i;
for (i = 0; i < ary.length; i += 1) {
if (ary[i] && func(ary[i], i, ary)) {
break;
}
}
}
}
/**
* Helper function for iterating over an array backwards. If the func
* returns a true value, it will break out of the loop.
*/
function eachReverse(ary, func) {
if (ary) {
var i;
for (i = ary.length - 1; i > -1; i -= 1) {
if (ary[i] && func(ary[i], i, ary)) {
break;
}
}
}
}
function hasProp(obj, prop) {
return hasOwn.call(obj, prop);
}
function getOwn(obj, prop) {
return hasProp(obj, prop) && obj[prop];
}
/**
* Cycles over properties in an object and calls a function for each
* property value. If the function returns a truthy value, then the
* iteration is stopped.
*/
function eachProp(obj, func) {
var prop;
for (prop in obj) {
if (hasProp(obj, prop)) {
if (func(obj[prop], prop)) {
break;
}
}
}
}
/**
* Simple function to mix in properties from source into target,
* but only if target does not already have a property of the same name.
*/
function mixin(target, source, force, deepStringMixin) {
if (source) {
eachProp(source, function (value, prop) {
if (force || !hasProp(target, prop)) {
if (deepStringMixin && typeof value === 'object' && value &&
!isArray(value) && !isFunction(value) &&
!(value instanceof RegExp)) {
if (!target[prop]) {
target[prop] = {};
}
mixin(target[prop], value, force, deepStringMixin);
} else {
target[prop] = value;
}
}
});
}
return target;
}
//Similar to Function.prototype.bind, but the 'this' object is specified
//first, since it is easier to read/figure out what 'this' will be.
function bind(obj, fn) {
return function () {
return fn.apply(obj, arguments);
};
}
function scripts() {
return document.getElementsByTagName('script');
}
function defaultOnError(err) {
throw err;
}
//Allow getting a global that is expressed in
//dot notation, like 'a.b.c'.
function getGlobal(value) {
if (!value) {
return value;
}
var g = global;
each(value.split('.'), function (part) {
g = g[part];
});
return g;
}
/**
* Constructs an error with a pointer to an URL with more information.
* @param {String} id the error ID that maps to an ID on a web page.
* @param {String} message human readable error.
* @param {Error} [err] the original error, if there is one.
*
* @returns {Error}
*/
function makeError(id, msg, err, requireModules) {
var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
e.requireType = id;
e.requireModules = requireModules;
if (err) {
e.originalError = err;
}
return e;
}
if (typeof define !== 'undefined') {
//If a define is already in play via another AMD loader,
//do not overwrite.
return;
}
if (typeof requirejs !== 'undefined') {
if (isFunction(requirejs)) {
//Do not overwrite an existing requirejs instance.
return;
}
cfg = requirejs;
requirejs = undefined;
}
//Allow for a require config object
if (typeof require !== 'undefined' && !isFunction(require)) {
//assume it is a config object.
cfg = require;
require = undefined;
}
function newContext(contextName) {
var inCheckLoaded, Module, context, handlers,
checkLoadedTimeoutId,
config = {
//Defaults. Do not set a default for map
//config to speed up normalize(), which
//will run faster if there is no default.
waitSeconds: 7,
baseUrl: './',
paths: {},
bundles: {},
pkgs: {},
shim: {},
config: {}
},
registry = {},
//registry of just enabled modules, to speed
//cycle breaking code when lots of modules
//are registered, but not activated.
enabledRegistry = {},
undefEvents = {},
defQueue = [],
defined = {},
urlFetched = {},
bundlesMap = {},
requireCounter = 1,
unnormalizedCounter = 1;
/**
* Trims the . and .. from an array of path segments.
* It will keep a leading path segment if a .. will become
* the first path segment, to help with module name lookups,
* which act like paths, but can be remapped. But the end result,
* all paths that use this function should look normalized.
* NOTE: this method MODIFIES the input array.
* @param {Array} ary the array of path segments.
*/
function trimDots(ary) {
var i, part;
for (i = 0; i < ary.length; i++) {
part = ary[i];
if (part === '.') {
ary.splice(i, 1);
i -= 1;
} else if (part === '..') {
// If at the start, or previous value is still ..,
// keep them so that when converted to a path it may
// still work when converted to a path, even though
// as an ID it is less than ideal. In larger point
// releases, may be better to just kick out an error.
if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') {
continue;
} else if (i > 0) {
ary.splice(i - 1, 2);
i -= 2;
}
}
}
}
/**
* Given a relative module name, like ./something, normalize it to
* a real name that can be mapped to a path.
* @param {String} name the relative name
* @param {String} baseName a real name that the name arg is relative
* to.
* @param {Boolean} applyMap apply the map config to the value. Should
* only be done if this normalization is for a dependency ID.
* @returns {String} normalized name
*/
function normalize(name, baseName, applyMap) {
var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex,
foundMap, foundI, foundStarMap, starI, normalizedBaseParts,
baseParts = (baseName && baseName.split('/')),
map = config.map,
starMap = map && map['*'];
//Adjust any relative paths.
if (name) {
name = name.split('/');
lastIndex = name.length - 1;
// If wanting node ID compatibility, strip .js from end
// of IDs. Have to do this here, and not in nameToUrl
// because node allows either .js or non .js to map
// to same file.
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
}
// Starts with a '.' so need the baseName
if (name[0].charAt(0) === '.' && baseParts) {
//Convert baseName to array, and lop off the last part,
//so that . matches that 'directory' and not name of the baseName's
//module. For instance, baseName of 'one/two/three', maps to
//'one/two/three.js', but we want the directory, 'one/two' for
//this normalization.
normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
name = normalizedBaseParts.concat(name);
}
trimDots(name);
name = name.join('/');
}
//Apply map config if available.
if (applyMap && map && (baseParts || starMap)) {
nameParts = name.split('/');
outerLoop: for (i = nameParts.length; i > 0; i -= 1) {
nameSegment = nameParts.slice(0, i).join('/');
if (baseParts) {
//Find the longest baseName segment match in the config.
//So, do joins on the biggest to smallest lengths of baseParts.
for (j = baseParts.length; j > 0; j -= 1) {
mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
//baseName segment has config, find if it has one for
//this name.
if (mapValue) {
mapValue = getOwn(mapValue, nameSegment);
if (mapValue) {
//Match, update name to the new value.
foundMap = mapValue;
foundI = i;
break outerLoop;
}
}
}
}
//Check for a star map match, but just hold on to it,
//if there is a shorter segment match later in a matching
//config, then favor over this star map.
if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
foundStarMap = getOwn(starMap, nameSegment);
starI = i;
}
}
if (!foundMap && foundStarMap) {
foundMap = foundStarMap;
foundI = starI;
}
if (foundMap) {
nameParts.splice(0, foundI, foundMap);
name = nameParts.join('/');
}
}
// If the name points to a package's name, use
// the package main instead.
pkgMain = getOwn(config.pkgs, name);
return pkgMain ? pkgMain : name;
}
function removeScript(name) {
if (isBrowser) {
each(scripts(), function (scriptNode) {
if (scriptNode.getAttribute('data-requiremodule') === name &&
scriptNode.getAttribute('data-requirecontext') === context.contextName) {
scriptNode.parentNode.removeChild(scriptNode);
return true;
}
});
}
}
function hasPathFallback(id) {
var pathConfig = getOwn(config.paths, id);
if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
//Pop off the first array value, since it failed, and
//retry
pathConfig.shift();
context.require.undef(id);
//Custom require that does not do map translation, since
//ID is "absolute", already mapped/resolved.
context.makeRequire(null, {
skipMap: true
})([id]);
return true;
}
}
//Turns a plugin!resource to [plugin, resource]
//with the plugin being undefined if the name
//did not have a plugin prefix.
function splitPrefix(name) {
var prefix,
index = name ? name.indexOf('!') : -1;
if (index > -1) {
prefix = name.substring(0, index);
name = name.substring(index + 1, name.length);
}
return [prefix, name];
}
/**
* Creates a module mapping that includes plugin prefix, module
* name, and path. If parentModuleMap is provided it will
* also normalize the name via require.normalize()
*
* @param {String} name the module name
* @param {String} [parentModuleMap] parent module map
* for the module name, used to resolve relative names.
* @param {Boolean} isNormalized: is the ID already normalized.
* This is true if this call is done for a define() module ID.
* @param {Boolean} applyMap: apply the map config to the ID.
* Should only be true if this map is for a dependency.
*
* @returns {Object}
*/
function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
var url, pluginModule, suffix, nameParts,
prefix = null,
parentName = parentModuleMap ? parentModuleMap.name : null,
originalName = name,
isDefine = true,
normalizedName = '';
//If no name, then it means it is a require call, generate an
//internal name.
if (!name) {
isDefine = false;
name = '_@r' + (requireCounter += 1);
}
nameParts = splitPrefix(name);
prefix = nameParts[0];
name = nameParts[1];
if (prefix) {
prefix = normalize(prefix, parentName, applyMap);
pluginModule = getOwn(defined, prefix);
}
//Account for relative paths if there is a base name.
if (name) {
if (prefix) {
if (isNormalized) {
normalizedName = name;
} else if (pluginModule && pluginModule.normalize) {
//Plugin is loaded, use its normalize method.
normalizedName = pluginModule.normalize(name, function (name) {
return normalize(name, parentName, applyMap);
});
} else {
// If nested plugin references, then do not try to
// normalize, as it will not normalize correctly. This
// places a restriction on resourceIds, and the longer
// term solution is not to normalize until plugins are
// loaded and all normalizations to allow for async
// loading of a loader plugin. But for now, fixes the
// common uses. Details in #1131
normalizedName = name.indexOf('!') === -1 ?
normalize(name, parentName, applyMap) :
name;
}
} else {
//A regular module.
normalizedName = normalize(name, parentName, applyMap);
//Normalized name may be a plugin ID due to map config
//application in normalize. The map config values must
//already be normalized, so do not need to redo that part.
nameParts = splitPrefix(normalizedName);
prefix = nameParts[0];
normalizedName = nameParts[1];
isNormalized = true;
url = context.nameToUrl(normalizedName);
}
}
//If the id is a plugin id that cannot be determined if it needs
//normalization, stamp it with a unique ID so two matching relative
//ids that may conflict can be separate.
suffix = prefix && !pluginModule && !isNormalized ?
'_unnormalized' + (unnormalizedCounter += 1) :
'';
return {
prefix: prefix,
name: normalizedName,
parentMap: parentModuleMap,
unnormalized: !!suffix,
url: url,
originalName: originalName,
isDefine: isDefine,
id: (prefix ?
prefix + '!' + normalizedName :
normalizedName) + suffix
};
}
function getModule(depMap) {
var id = depMap.id,
mod = getOwn(registry, id);
if (!mod) {
mod = registry[id] = new context.Module(depMap);
}
return mod;
}
function on(depMap, name, fn) {
var id = depMap.id,
mod = getOwn(registry, id);
if (hasProp(defined, id) &&
(!mod || mod.defineEmitComplete)) {
if (name === 'defined') {
fn(defined[id]);
}
} else {
mod = getModule(depMap);
if (mod.error && name === 'error') {
fn(mod.error);
} else {
mod.on(name, fn);
}
}
}
function onError(err, errback) {
var ids = err.requireModules,
notified = false;
if (errback) {
errback(err);
} else {
each(ids, function (id) {
var mod = getOwn(registry, id);
if (mod) {
//Set error on module, so it skips timeout checks.
mod.error = err;
if (mod.events.error) {
notified = true;
mod.emit('error', err);
}
}
});
if (!notified) {
req.onError(err);
}
}
}
/**
* Internal method to transfer globalQueue items to this context's
* defQueue.
*/
function takeGlobalQueue() {
//Push all the globalDefQueue items into the context's defQueue
if (globalDefQueue.length) {
each(globalDefQueue, function(queueItem) {
var id = queueItem[0];
if (typeof id === 'string') {
context.defQueueMap[id] = true;
}
defQueue.push(queueItem);
});
globalDefQueue = [];
}
}
handlers = {
'require': function (mod) {
if (mod.require) {
return mod.require;
} else {
return (mod.require = context.makeRequire(mod.map));
}
},
'exports': function (mod) {
mod.usingExports = true;
if (mod.map.isDefine) {
if (mod.exports) {
return (defined[mod.map.id] = mod.exports);
} else {
return (mod.exports = defined[mod.map.id] = {});
}
}
},
'module': function (mod) {
if (mod.module) {
return mod.module;
} else {
return (mod.module = {
id: mod.map.id,
uri: mod.map.url,
config: function () {
return getOwn(config.config, mod.map.id) || {};
},
exports: mod.exports || (mod.exports = {})
});
}
}
};
function cleanRegistry(id) {
//Clean up machinery used for waiting modules.
delete registry[id];
delete enabledRegistry[id];
}
function breakCycle(mod, traced, processed) {
var id = mod.map.id;
if (mod.error) {
mod.emit('error', mod.error);
} else {
traced[id] = true;
each(mod.depMaps, function (depMap, i) {
var depId = depMap.id,
dep = getOwn(registry, depId);
//Only force things that have not completed
//being defined, so still in the registry,
//and only if it has not been matched up
//in the module already.
if (dep && !mod.depMatched[i] && !processed[depId]) {
if (getOwn(traced, depId)) {
mod.defineDep(i, defined[depId]);
mod.check(); //pass false?
} else {
breakCycle(dep, traced, processed);
}
}
});
processed[id] = true;
}
}
function checkLoaded() {
var err, usingPathFallback,
waitInterval = config.waitSeconds * 1000,
//It is possible to disable the wait interval by using waitSeconds of 0.
expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
noLoads = [],
reqCalls = [],
stillLoading = false,
needCycleCheck = true;
//Do not bother if this call was a result of a cycle break.
if (inCheckLoaded) {
return;
}
inCheckLoaded = true;
//Figure out the state of all the modules.
eachProp(enabledRegistry, function (mod) {
var map = mod.map,
modId = map.id;
//Skip things that are not enabled or in error state.
if (!mod.enabled) {
return;
}
if (!map.isDefine) {
reqCalls.push(mod);
}
if (!mod.error) {
//If the module should be executed, and it has not
//been inited and time is up, remember it.
if (!mod.inited && expired) {
if (hasPathFallback(modId)) {
usingPathFallback = true;
stillLoading = true;
} else {
noLoads.push(modId);
removeScript(modId);
}
} else if (!mod.inited && mod.fetched && map.isDefine) {
stillLoading = true;
if (!map.prefix) {
//No reason to keep looking for unfinished
//loading. If the only stillLoading is a
//plugin resource though, keep going,
//because it may be that a plugin resource
//is waiting on a non-plugin cycle.
return (needCycleCheck = false);
}
}
}
});
if (expired && noLoads.length) {
//If wait time expired, throw error of unloaded modules.
err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
err.contextName = context.contextName;
return onError(err);
}
//Not expired, check for a cycle.
if (needCycleCheck) {
each(reqCalls, function (mod) {
breakCycle(mod, {}, {});
});
}
//If still waiting on loads, and the waiting load is something
//other than a plugin resource, or there are still outstanding
//scripts, then just try back later.
if ((!expired || usingPathFallback) && stillLoading) {
//Something is still waiting to load. Wait for it, but only
//if a timeout is not already in effect.
if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
checkLoadedTimeoutId = setTimeout(function () {
checkLoadedTimeoutId = 0;
checkLoaded();
}, 50);
}
}
inCheckLoaded = false;
}
Module = function (map) {
this.events = getOwn(undefEvents, map.id) || {};
this.map = map;
this.shim = getOwn(config.shim, map.id);
this.depExports = [];
this.depMaps = [];
this.depMatched = [];
this.pluginMaps = {};
this.depCount = 0;
/* this.exports this.factory
this.depMaps = [],
this.enabled, this.fetched
*/
};
Module.prototype = {
init: function (depMaps, factory, errback, options) {
options = options || {};
//Do not do more inits if already done. Can happen if there
//are multiple define calls for the same module. That is not
//a normal, common case, but it is also not unexpected.
if (this.inited) {
return;
}
this.factory = factory;
if (errback) {
//Register for errors on this module.
this.on('error', errback);
} else if (this.events.error) {
//If no errback already, but there are error listeners
//on this module, set up an errback to pass to the deps.
errback = bind(this, function (err) {
this.emit('error', err);
});
}
//Do a copy of the dependency array, so that
//source inputs are not modified. For example
//"shim" deps are passed in here directly, and
//doing a direct modification of the depMaps array
//would affect that config.
this.depMaps = depMaps && depMaps.slice(0);
this.errback = errback;
//Indicate this module has be initialized
this.inited = true;
this.ignore = options.ignore;
//Could have option to init this module in enabled mode,
//or could have been previously marked as enabled. However,
//the dependencies are not known until init is called. So
//if enabled previously, now trigger dependencies as enabled.
if (options.enabled || this.enabled) {
//Enable this module and dependencies.
//Will call this.check()
this.enable();
} else {
this.check();
}
},
defineDep: function (i, depExports) {
//Because of cycles, defined callback for a given
//export can be called more than once.
if (!this.depMatched[i]) {
this.depMatched[i] = true;
this.depCount -= 1;
this.depExports[i] = depExports;
}
},
fetch: function () {
if (this.fetched) {
return;
}
this.fetched = true;
context.startTime = (new Date()).getTime();
var map = this.map;
//If the manager is for a plugin managed resource,
//ask the plugin to load it now.
if (this.shim) {
context.makeRequire(this.map, {
enableBuildCallback: true
})(this.shim.deps || [], bind(this, function () {
return map.prefix ? this.callPlugin() : this.load();
}));
} else {
//Regular dependency.
return map.prefix ? this.callPlugin() : this.load();
}
},
load: function () {
var url = this.map.url;
//Regular dependency.
if (!urlFetched[url]) {
urlFetched[url] = true;
context.load(this.map.id, url);
}
},
/**
* Checks if the module is ready to define itself, and if so,
* define it.
*/
check: function () {
if (!this.enabled || this.enabling) {
return;
}
var err, cjsModule,
id = this.map.id,
depExports = this.depExports,
exports = this.exports,
factory = this.factory;
if (!this.inited) {
// Only fetch if not already in the defQueue.
if (!hasProp(context.defQueueMap, id)) {
this.fetch();
}
} else if (this.error) {
this.emit('error', this.error);
} else if (!this.defining) {
//The factory could trigger another require call
//that would result in checking this module to
//define itself again. If already in the process
//of doing that, skip this work.
this.defining = true;
if (this.depCount < 1 && !this.defined) {
if (isFunction(factory)) {
//If there is an error listener, favor passing
//to that instead of throwing an error. However,
//only do it for define()'d modules. require
//errbacks should not be called for failures in
//their callbacks (#699). However if a global
//onError is set, use that.
if ((this.events.error && this.map.isDefine) ||
req.onError !== defaultOnError) {
try {
exports = context.execCb(id, factory, depExports, exports);
} catch (e) {
err = e;
}
} else {
exports = context.execCb(id, factory, depExports, exports);
}
// Favor return value over exports. If node/cjs in play,
// then will not have a return value anyway. Favor
// module.exports assignment over exports object.
if (this.map.isDefine && exports === undefined) {
cjsModule = this.module;
if (cjsModule) {
exports = cjsModule.exports;
} else if (this.usingExports) {
//exports already set the defined value.
exports = this.exports;
}
}
if (err) {
err.requireMap = this.map;
err.requireModules = this.map.isDefine ? [this.map.id] : null;
err.requireType = this.map.isDefine ? 'define' : 'require';
return onError((this.error = err));
}
} else {
//Just a literal value
exports = factory;
}
this.exports = exports;
if (this.map.isDefine && !this.ignore) {
defined[id] = exports;
if (req.onResourceLoad) {
var resLoadMaps = [];
each(this.depMaps, function (depMap) {
resLoadMaps.push(depMap.normalizedMap || depMap);
});
req.onResourceLoad(context, this.map, resLoadMaps);
}
}
//Clean up
cleanRegistry(id);
this.defined = true;
}
//Finished the define stage. Allow calling check again
//to allow define notifications below in the case of a
//cycle.
this.defining = false;
if (this.defined && !this.defineEmitted) {
this.defineEmitted = true;
this.emit('defined', this.exports);
this.defineEmitComplete = true;
}
}
},
callPlugin: function () {
var map = this.map,
id = map.id,
//Map already normalized the prefix.
pluginMap = makeModuleMap(map.prefix);
//Mark this as a dependency for this plugin, so it
//can be traced for cycles.
this.depMaps.push(pluginMap);
on(pluginMap, 'defined', bind(this, function (plugin) {
var load, normalizedMap, normalizedMod,
bundleId = getOwn(bundlesMap, this.map.id),
name = this.map.name,
parentName = this.map.parentMap ? this.map.parentMap.name : null,
localRequire = context.makeRequire(map.parentMap, {
enableBuildCallback: true
});
//If current map is not normalized, wait for that
//normalized name to load instead of continuing.
if (this.map.unnormalized) {
//Normalize the ID if the plugin allows it.
if (plugin.normalize) {
name = plugin.normalize(name, function (name) {
return normalize(name, parentName, true);
}) || '';
}
//prefix and name should already be normalized, no need
//for applying map config again either.
normalizedMap = makeModuleMap(map.prefix + '!' + name,
this.map.parentMap,
true);
on(normalizedMap,
'defined', bind(this, function (value) {
this.map.normalizedMap = normalizedMap;
this.init([], function () { return value; }, null, {
enabled: true,
ignore: true
});
}));
normalizedMod = getOwn(registry, normalizedMap.id);
if (normalizedMod) {
//Mark this as a dependency for this plugin, so it
//can be traced for cycles.
this.depMaps.push(normalizedMap);
if (this.events.error) {
normalizedMod.on('error', bind(this, function (err) {
this.emit('error', err);
}));
}
normalizedMod.enable();
}
return;
}
//If a paths config, then just load that file instead to
//resolve the plugin, as it is built into that paths layer.
if (bundleId) {
this.map.url = context.nameToUrl(bundleId);
this.load();
return;
}
load = bind(this, function (value) {
this.init([], function () { return value; }, null, {
enabled: true
});
});
load.error = bind(this, function (err) {
this.inited = true;
this.error = err;
err.requireModules = [id];
//Remove temp unnormalized modules for this module,
//since they will never be resolved otherwise now.
eachProp(registry, function (mod) {
if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
cleanRegistry(mod.map.id);
}
});
onError(err);
});
//Allow plugins to load other code without having to know the
//context or how to 'complete' the load.
load.fromText = bind(this, function (text, textAlt) {
/*jslint evil: true */
var moduleName = map.name,
moduleMap = makeModuleMap(moduleName),
hasInteractive = useInteractive;
//As of 2.1.0, support just passing the text, to reinforce
//fromText only being called once per resource. Still
//support old style of passing moduleName but discard
//that moduleName in favor of the internal ref.
if (textAlt) {
text = textAlt;
}
//Turn off interactive script matching for IE for any define
//calls in the text, then turn it back on at the end.
if (hasInteractive) {
useInteractive = false;
}
//Prime the system by creating a module instance for
//it.
getModule(moduleMap);
//Transfer any config to this other module.
if (hasProp(config.config, id)) {
config.config[moduleName] = config.config[id];
}
try {
req.exec(text);
} catch (e) {
return onError(makeError('fromtexteval',
'fromText eval for ' + id +
' failed: ' + e,
e,
[id]));
}
if (hasInteractive) {
useInteractive = true;
}
//Mark this as a dependency for the plugin
//resource
this.depMaps.push(moduleMap);
//Support anonymous modules.
context.completeLoad(moduleName);
//Bind the value of that module to the value for this
//resource ID.
localRequire([moduleName], load);
});
//Use parentName here since the plugin's name is not reliable,
//could be some weird string with no path that actually wants to
//reference the parentName's path.
plugin.load(map.name, localRequire, load, config);
}));
context.enable(pluginMap, this);
this.pluginMaps[pluginMap.id] = pluginMap;
},
enable: function () {
enabledRegistry[this.map.id] = this;
this.enabled = true;
//Set flag mentioning that the module is enabling,
//so that immediate calls to the defined callbacks
//for dependencies do not trigger inadvertent load
//with the depCount still being zero.
this.enabling = true;
//Enable each dependency
each(this.depMaps, bind(this, function (depMap, i) {
var id, mod, handler;
if (typeof depMap === 'string') {
//Dependency needs to be converted to a depMap
//and wired up to this module.
depMap = makeModuleMap(depMap,
(this.map.isDefine ? this.map : this.map.parentMap),
false,
!this.skipMap);
this.depMaps[i] = depMap;
handler = getOwn(handlers, depMap.id);
if (handler) {
this.depExports[i] = handler(this);
return;
}
this.depCount += 1;
on(depMap, 'defined', bind(this, function (depExports) {
if (this.undefed) {
return;
}
this.defineDep(i, depExports);
this.check();
}));
if (this.errback) {
on(depMap, 'error', bind(this, this.errback));
} else if (this.events.error) {
// No direct errback on this module, but something
// else is listening for errors, so be sure to
// propagate the error correctly.
on(depMap, 'error', bind(this, function(err) {
this.emit('error', err);
}));
}
}
id = depMap.id;
mod = registry[id];
//Skip special modules like 'require', 'exports', 'module'
//Also, don't call enable if it is already enabled,
//important in circular dependency cases.
if (!hasProp(handlers, id) && mod && !mod.enabled) {
context.enable(depMap, this);
}
}));
//Enable each plugin that is used in
//a dependency
eachProp(this.pluginMaps, bind(this, function (pluginMap) {
var mod = getOwn(registry, pluginMap.id);
if (mod && !mod.enabled) {
context.enable(pluginMap, this);
}
}));
this.enabling = false;
this.check();
},
on: function (name, cb) {
var cbs = this.events[name];
if (!cbs) {
cbs = this.events[name] = [];
}
cbs.push(cb);
},
emit: function (name, evt) {
each(this.events[name], function (cb) {
cb(evt);
});
if (name === 'error') {
//Now that the error handler was triggered, remove
//the listeners, since this broken Module instance
//can stay around for a while in the registry.
delete this.events[name];
}
}
};
function callGetModule(args) {
//Skip modules already defined.
if (!hasProp(defined, args[0])) {
getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
}
}
function removeListener(node, func, name, ieName) {
//Favor detachEvent because of IE9
//issue, see attachEvent/addEventListener comment elsewhere
//in this file.
if (node.detachEvent && !isOpera) {
//Probably IE. If not it will throw an error, which will be
//useful to know.
if (ieName) {
node.detachEvent(ieName, func);
}
} else {
node.removeEventListener(name, func, false);
}
}
/**
* Given an event from a script node, get the requirejs info from it,
* and then removes the event listeners on the node.
* @param {Event} evt
* @returns {Object}
*/
function getScriptData(evt) {
//Using currentTarget instead of target for Firefox 2.0's sake. Not
//all old browsers will be supported, but this one was easy enough
//to support and still makes sense.
var node = evt.currentTarget || evt.srcElement;
//Remove the listeners once here.
removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
removeListener(node, context.onScriptError, 'error');
return {
node: node,
id: node && node.getAttribute('data-requiremodule')
};
}
function intakeDefines() {
var args;
//Any defined modules in the global queue, intake them now.
takeGlobalQueue();
//Make sure any remaining defQueue items get properly processed.
while (defQueue.length) {
args = defQueue.shift();
if (args[0] === null) {
return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' +
args[args.length - 1]));
} else {
//args are id, deps, factory. Should be normalized by the
//define() function.
callGetModule(args);
}
}
context.defQueueMap = {};
}
context = {
config: config,
contextName: contextName,
registry: registry,
defined: defined,
urlFetched: urlFetched,
defQueue: defQueue,
defQueueMap: {},
Module: Module,
makeModuleMap: makeModuleMap,
nextTick: req.nextTick,
onError: onError,
/**
* Set a configuration for the context.
* @param {Object} cfg config object to integrate.
*/
configure: function (cfg) {
//Make sure the baseUrl ends in a slash.
if (cfg.baseUrl) {
if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
cfg.baseUrl += '/';
}
}
// Convert old style urlArgs string to a function.
if (typeof cfg.urlArgs === 'string') {
var urlArgs = cfg.urlArgs;
cfg.urlArgs = function(id, url) {
return (url.indexOf('?') === -1 ? '?' : '&') + urlArgs;
};
}
//Save off the paths since they require special processing,
//they are additive.
var shim = config.shim,
objs = {
paths: true,
bundles: true,
config: true,
map: true
};
eachProp(cfg, function (value, prop) {
if (objs[prop]) {
if (!config[prop]) {
config[prop] = {};
}
mixin(config[prop], value, true, true);
} else {
config[prop] = value;
}
});
//Reverse map the bundles
if (cfg.bundles) {
eachProp(cfg.bundles, function (value, prop) {
each(value, function (v) {
if (v !== prop) {
bundlesMap[v] = prop;
}
});
});
}
//Merge shim
if (cfg.shim) {
eachProp(cfg.shim, function (value, id) {
//Normalize the structure
if (isArray(value)) {
value = {
deps: value
};
}
if ((value.exports || value.init) && !value.exportsFn) {
value.exportsFn = context.makeShimExports(value);
}
shim[id] = value;
});
config.shim = shim;
}
//Adjust packages if necessary.
if (cfg.packages) {
each(cfg.packages, function (pkgObj) {
var location, name;
pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj;
name = pkgObj.name;
location = pkgObj.location;
if (location) {
config.paths[name] = pkgObj.location;
}
//Save pointer to main module ID for pkg name.
//Remove leading dot in main, so main paths are normalized,
//and remove any trailing .js, since different package
//envs have different conventions: some use a module name,
//some use a file name.
config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main')
.replace(currDirRegExp, '')
.replace(jsSuffixRegExp, '');
});
}
//If there are any "waiting to execute" modules in the registry,
//update the maps for them, since their info, like URLs to load,
//may have changed.
eachProp(registry, function (mod, id) {
//If module already has init called, since it is too
//late to modify them, and ignore unnormalized ones
//since they are transient.
if (!mod.inited && !mod.map.unnormalized) {
mod.map = makeModuleMap(id, null, true);
}
});
//If a deps array or a config callback is specified, then call
//require with those args. This is useful when require is defined as a
//config object before require.js is loaded.
if (cfg.deps || cfg.callback) {
context.require(cfg.deps || [], cfg.callback);
}
},
makeShimExports: function (value) {
function fn() {
var ret;
if (value.init) {
ret = value.init.apply(global, arguments);
}
return ret || (value.exports && getGlobal(value.exports));
}
return fn;
},
makeRequire: function (relMap, options) {
options = options || {};
function localRequire(deps, callback, errback) {
var id, map, requireMod;
if (options.enableBuildCallback && callback && isFunction(callback)) {
callback.__requireJsBuild = true;
}
if (typeof deps === 'string') {
if (isFunction(callback)) {
//Invalid call
return onError(makeError('requireargs', 'Invalid require call'), errback);
}
//If require|exports|module are requested, get the
//value for them from the special handlers. Caveat:
//this only works while module is being defined.
if (relMap && hasProp(handlers, deps)) {
return handlers[deps](registry[relMap.id]);
}
//Synchronous access to one module. If require.get is
//available (as in the Node adapter), prefer that.
if (req.get) {
return req.get(context, deps, relMap, localRequire);
}
//Normalize module name, if it contains . or ..
map = makeModuleMap(deps, relMap, false, true);
id = map.id;
if (!hasProp(defined, id)) {
return onError(makeError('notloaded', 'Module name "' +
id +
'" has not been loaded yet for context: ' +
contextName +
(relMap ? '' : '. Use require([])')));
}
return defined[id];
}
//Grab defines waiting in the global queue.
intakeDefines();
//Mark all the dependencies as needing to be loaded.
context.nextTick(function () {
//Some defines could have been added since the
//require call, collect them.
intakeDefines();
requireMod = getModule(makeModuleMap(null, relMap));
//Store if map config should be applied to this require
//call for dependencies.
requireMod.skipMap = options.skipMap;
requireMod.init(deps, callback, errback, {
enabled: true
});
checkLoaded();
});
return localRequire;
}
mixin(localRequire, {
isBrowser: isBrowser,
/**
* Converts a module name + .extension into an URL path.
* *Requires* the use of a module name. It does not support using
* plain URLs like nameToUrl.
*/
toUrl: function (moduleNamePlusExt) {
var ext,
index = moduleNamePlusExt.lastIndexOf('.'),
segment = moduleNamePlusExt.split('/')[0],
isRelative = segment === '.' || segment === '..';
//Have a file extension alias, and it is not the
//dots from a relative path.
if (index !== -1 && (!isRelative || index > 1)) {
ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
}
return context.nameToUrl(normalize(moduleNamePlusExt,
relMap && relMap.id, true), ext, true);
},
defined: function (id) {
return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
},
specified: function (id) {
id = makeModuleMap(id, relMap, false, true).id;
return hasProp(defined, id) || hasProp(registry, id);
}
});
//Only allow undef on top level require calls
if (!relMap) {
localRequire.undef = function (id) {
//Bind any waiting define() calls to this context,
//fix for #408
takeGlobalQueue();
var map = makeModuleMap(id, relMap, true),
mod = getOwn(registry, id);
mod.undefed = true;
removeScript(id);
delete defined[id];
delete urlFetched[map.url];
delete undefEvents[id];
//Clean queued defines too. Go backwards
//in array so that the splices do not
//mess up the iteration.
eachReverse(defQueue, function(args, i) {
if (args[0] === id) {
defQueue.splice(i, 1);
}
});
delete context.defQueueMap[id];
if (mod) {
//Hold on to listeners in case the
//module will be attempted to be reloaded
//using a different config.
if (mod.events.defined) {
undefEvents[id] = mod.events;
}
cleanRegistry(id);
}
};
}
return localRequire;
},
/**
* Called to enable a module if it is still in the registry
* awaiting enablement. A second arg, parent, the parent module,
* is passed in for context, when this method is overridden by
* the optimizer. Not shown here to keep code compact.
*/
enable: function (depMap) {
var mod = getOwn(registry, depMap.id);
if (mod) {
getModule(depMap).enable();
}
},
/**
* Internal method used by environment adapters to complete a load event.
* A load event could be a script load or just a load pass from a synchronous
* load call.
* @param {String} moduleName the name of the module to potentially complete.
*/
completeLoad: function (moduleName) {
var found, args, mod,
shim = getOwn(config.shim, moduleName) || {},
shExports = shim.exports;
takeGlobalQueue();
while (defQueue.length) {
args = defQueue.shift();
if (args[0] === null) {
args[0] = moduleName;
//If already found an anonymous module and bound it
//to this name, then this is some other anon module
//waiting for its completeLoad to fire.
if (found) {
break;
}
found = true;
} else if (args[0] === moduleName) {
//Found matching define call for this script!
found = true;
}
callGetModule(args);
}
context.defQueueMap = {};
//Do this after the cycle of callGetModule in case the result
//of those calls/init calls changes the registry.
mod = getOwn(registry, moduleName);
if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
if (hasPathFallback(moduleName)) {
return;
} else {
return onError(makeError('nodefine',
'No define call for ' + moduleName,
null,
[moduleName]));
}
} else {
//A script that does not call define(), so just simulate
//the call for it.
callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
}
}
checkLoaded();
},
/**
* Converts a module name to a file path. Supports cases where
* moduleName may actually be just an URL.
* Note that it **does not** call normalize on the moduleName,
* it is assumed to have already been normalized. This is an
* internal API, not a public one. Use toUrl for the public API.
*/
nameToUrl: function (moduleName, ext, skipExt) {
var paths, syms, i, parentModule, url,
parentPath, bundleId,
pkgMain = getOwn(config.pkgs, moduleName);
if (pkgMain) {
moduleName = pkgMain;
}
bundleId = getOwn(bundlesMap, moduleName);
if (bundleId) {
return context.nameToUrl(bundleId, ext, skipExt);
}
//If a colon is in the URL, it indicates a protocol is used and it is just
//an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
//or ends with .js, then assume the user meant to use an url and not a module id.
//The slash is important for protocol-less URLs as well as full paths.
if (req.jsExtRegExp.test(moduleName)) {
//Just a plain path, not module name lookup, so just return it.
//Add extension if it is included. This is a bit wonky, only non-.js things pass
//an extension, this method probably needs to be reworked.
url = moduleName + (ext || '');
} else {
//A module that needs to be converted to a path.
paths = config.paths;
syms = moduleName.split('/');
//For each module name segment, see if there is a path
//registered for it. Start with most specific name
//and work up from it.
for (i = syms.length; i > 0; i -= 1) {
parentModule = syms.slice(0, i).join('/');
parentPath = getOwn(paths, parentModule);
if (parentPath) {
//If an array, it means there are a few choices,
//Choose the one that is desired
if (isArray(parentPath)) {
parentPath = parentPath[0];
}
syms.splice(0, i, parentPath);
break;
}
}
//Join the path parts together, then figure out if baseUrl is needed.
url = syms.join('/');
url += (ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? '' : '.js'));
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
}
return config.urlArgs && !/^blob\:/.test(url) ?
url + config.urlArgs(moduleName, url) : url;
},
//Delegates to req.load. Broken out as a separate function to
//allow overriding in the optimizer.
load: function (id, url) {
req.load(context, id, url);
},
/**
* Executes a module callback function. Broken out as a separate function
* solely to allow the build system to sequence the files in the built
* layer in the right sequence.
*
* @private
*/
execCb: function (name, callback, args, exports) {
return callback.apply(exports, args);
},
/**
* callback for script loads, used to check status of loading.
*
* @param {Event} evt the event from the browser for the script
* that was loaded.
*/
onScriptLoad: function (evt) {
//Using currentTarget instead of target for Firefox 2.0's sake. Not
//all old browsers will be supported, but this one was easy enough
//to support and still makes sense.
if (evt.type === 'load' ||
(readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
//Reset interactive script so a script node is not held onto for
//to long.
interactiveScript = null;
//Pull out the name of the module and the context.
var data = getScriptData(evt);
context.completeLoad(data.id);
}
},
/**
* Callback for script errors.
*/
onScriptError: function (evt) {
var data = getScriptData(evt);
if (!hasPathFallback(data.id)) {
var parents = [];
eachProp(registry, function(value, key) {
if (key.indexOf('_@r') !== 0) {
each(value.depMaps, function(depMap) {
if (depMap.id === data.id) {
parents.push(key);
return true;
}
});
}
});
return onError(makeError('scripterror', 'Script error for "' + data.id +
(parents.length ?
'", needed by: ' + parents.join(', ') :
'"'), evt, [data.id]));
}
}
};
context.require = context.makeRequire();
return context;
}
/**
* Main entry point.
*
* If the only argument to require is a string, then the module that
* is represented by that string is fetched for the appropriate context.
*
* If the first argument is an array, then it will be treated as an array
* of dependency string names to fetch. An optional function callback can
* be specified to execute when all of those dependencies are available.
*
* Make a local req variable to help Caja compliance (it assumes things
* on a require that are not standardized), and to give a short
* name for minification/local scope use.
*/
req = requirejs = function (deps, callback, errback, optional) {
//Find the right context, use default
var context, config,
contextName = defContextName;
// Determine if have config object in the call.
if (!isArray(deps) && typeof deps !== 'string') {
// deps is a config object
config = deps;
if (isArray(callback)) {
// Adjust args if there are dependencies
deps = callback;
callback = errback;
errback = optional;
} else {
deps = [];
}
}
if (config && config.context) {
contextName = config.context;
}
context = getOwn(contexts, contextName);
if (!context) {
context = contexts[contextName] = req.s.newContext(contextName);
}
if (config) {
context.configure(config);
}
return context.require(deps, callback, errback);
};
/**
* Support require.config() to make it easier to cooperate with other
* AMD loaders on globally agreed names.
*/
req.config = function (config) {
return req(config);
};
/**
* Execute something after the current tick
* of the event loop. Override for other envs
* that have a better solution than setTimeout.
* @param {Function} fn function to execute later.
*/
req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
setTimeout(fn, 4);
} : function (fn) { fn(); };
/**
* Export require as a global, but only if it does not already exist.
*/
if (!require) {
require = req;
}
req.version = version;
//Used to filter out dependencies that are already paths.
req.jsExtRegExp = /^\/|:|\?|\.js$/;
req.isBrowser = isBrowser;
s = req.s = {
contexts: contexts,
newContext: newContext
};
//Create default context.
req({});
//Exports some context-sensitive methods on global require.
each([
'toUrl',
'undef',
'defined',
'specified'
], function (prop) {
//Reference from contexts instead of early binding to default context,
//so that during builds, the latest instance of the default context
//with its config gets used.
req[prop] = function () {
var ctx = contexts[defContextName];
return ctx.require[prop].apply(ctx, arguments);
};
});
if (isBrowser) {
head = s.head = document.getElementsByTagName('head')[0];
//If BASE tag is in play, using appendChild is a problem for IE6.
//When that browser dies, this can be removed. Details in this jQuery bug:
//http://dev.jquery.com/ticket/2709
baseElement = document.getElementsByTagName('base')[0];
if (baseElement) {
head = s.head = baseElement.parentNode;
}
}
/**
* Any errors that require explicitly generates will be passed to this
* function. Intercept/override it if you want custom error handling.
* @param {Error} err the error object.
*/
req.onError = defaultOnError;
/**
* Creates the node for the load command. Only used in browser envs.
*/
req.createNode = function (config, moduleName, url) {
var node = config.xhtml ?
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
return node;
};
/**
* Does the request to load a module for the browser case.
* Make this a separate function to allow other environments
* to override it.
*
* @param {Object} context the require context to find state.
* @param {String} moduleName the name of the module.
* @param {Object} url the URL to the module.
*/
req.load = function (context, moduleName, url) {
var config = (context && context.config) || {},
node;
if (isBrowser) {
//In the browser so use a script tag
node = req.createNode(config, moduleName, url);
node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);
//Set up load listener. Test attachEvent first because IE9 has
//a subtle issue in its addEventListener and script onload firings
//that do not match the behavior of all other browsers with
//addEventListener support, which fire the onload event for a
//script right after the script execution. See:
//https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
//UNFORTUNATELY Opera implements attachEvent but does not follow the script
//script execution mode.
if (node.attachEvent &&
//Check if node.attachEvent is artificially added by custom script or
//natively supported by browser
//read https://github.com/requirejs/requirejs/issues/187
//if we can NOT find [native code] then it must NOT natively supported.
//in IE8, node.attachEvent does not have toString()
//Note the test for "[native code" with no closing brace, see:
//https://github.com/requirejs/requirejs/issues/273
!(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
!isOpera) {
//Probably IE. IE (at least 6-8) do not fire
//script onload right after executing the script, so
//we cannot tie the anonymous define call to a name.
//However, IE reports the script as being in 'interactive'
//readyState at the time of the define call.
useInteractive = true;
node.attachEvent('onreadystatechange', context.onScriptLoad);
//It would be great to add an error handler here to catch
//404s in IE9+. However, onreadystatechange will fire before
//the error handler, so that does not help. If addEventListener
//is used, then IE will fire error before load, but we cannot
//use that pathway given the connect.microsoft.com issue
//mentioned above about not doing the 'script execute,
//then fire the script load event listener before execute
//next script' that other browsers do.
//Best hope: IE10 fixes the issues,
//and then destroys all installs of IE 6-9.
//node.attachEvent('onerror', context.onScriptError);
} else {
node.addEventListener('load', context.onScriptLoad, false);
node.addEventListener('error', context.onScriptError, false);
}
node.src = url;
//Calling onNodeCreated after all properties on the node have been
//set, but before it is placed in the DOM.
if (config.onNodeCreated) {
config.onNodeCreated(node, config, moduleName, url);
}
//For some cache cases in IE 6-8, the script executes before the end
//of the appendChild execution, so to tie an anonymous define
//call to the module name (which is stored on the node), hold on
//to a reference to this node, but clear after the DOM insertion.
currentlyAddingScript = node;
if (baseElement) {
head.insertBefore(node, baseElement);
} else {
head.appendChild(node);
}
currentlyAddingScript = null;
return node;
} else if (isWebWorker) {
try {
//In a web worker, use importScripts. This is not a very
//efficient use of importScripts, importScripts will block until
//its script is downloaded and evaluated. However, if web workers
//are in play, the expectation is that a build has been done so
//that only one script needs to be loaded anyway. This may need
//to be reevaluated if other use cases become common.
// Post a task to the event loop to work around a bug in WebKit
// where the worker gets garbage-collected after calling
// importScripts(): https://webkit.org/b/153317
setTimeout(function() {}, 0);
importScripts(url);
//Account for anonymous modules
context.completeLoad(moduleName);
} catch (e) {
context.onError(makeError('importscripts',
'importScripts failed for ' +
moduleName + ' at ' + url,
e,
[moduleName]));
}
}
};
function getInteractiveScript() {
if (interactiveScript && interactiveScript.readyState === 'interactive') {
return interactiveScript;
}
eachReverse(scripts(), function (script) {
if (script.readyState === 'interactive') {
return (interactiveScript = script);
}
});
return interactiveScript;
}
//Look for a data-main script attribute, which could also adjust the baseUrl.
if (isBrowser && !cfg.skipDataMain) {
//Figure out baseUrl. Get it from the script tag with require.js in it.
eachReverse(scripts(), function (script) {
//Set the 'head' where we can append children by
//using the script's parent.
if (!head) {
head = script.parentNode;
}
//Look for a data-main attribute to set main script for the page
//to load. If it is there, the path to data main becomes the
//baseUrl, if it is not already set.
dataMain = script.getAttribute('data-main');
if (dataMain) {
//Preserve dataMain in case it is a path (i.e. contains '?')
mainScript = dataMain;
//Set final baseUrl if there is not already an explicit one,
//but only do so if the data-main value is not a loader plugin
//module ID.
if (!cfg.baseUrl && mainScript.indexOf('!') === -1) {
//Pull off the directory of data-main for use as the
//baseUrl.
src = mainScript.split('/');
mainScript = src.pop();
subPath = src.length ? src.join('/') + '/' : './';
cfg.baseUrl = subPath;
}
//Strip off any trailing .js since mainScript is now
//like a module name.
mainScript = mainScript.replace(jsSuffixRegExp, '');
//If mainScript is still a path, fall back to dataMain
if (req.jsExtRegExp.test(mainScript)) {
mainScript = dataMain;
}
//Put the data-main script in the files to load.
cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
return true;
}
});
}
/**
* The function that handles definitions of modules. Differs from
* require() in that a string for the module should be the first argument,
* and the function to execute after dependencies are loaded should
* return a value to define the module corresponding to the first argument's
* name.
*/
define = function (name, deps, callback) {
var node, context;
//Allow for anonymous modules
if (typeof name !== 'string') {
//Adjust args appropriately
callback = deps;
deps = name;
name = null;
}
//This module may not have dependencies
if (!isArray(deps)) {
callback = deps;
deps = null;
}
//If no name, and callback is a function, then figure out if it a
//CommonJS thing with dependencies.
if (!deps && isFunction(callback)) {
deps = [];
//Remove comments from the callback string,
//look for require calls, and pull them into the dependencies,
//but only if there are function args.
if (callback.length) {
callback
.toString()
.replace(commentRegExp, commentReplace)
.replace(cjsRequireRegExp, function (match, dep) {
deps.push(dep);
});
//May be a CommonJS thing even without require calls, but still
//could use exports, and module. Avoid doing exports and module
//work though if it just needs require.
//REQUIRES the function to expect the CommonJS variables in the
//order listed below.
deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
}
}
//If in IE 6-8 and hit an anonymous define() call, do the interactive
//work.
if (useInteractive) {
node = currentlyAddingScript || getInteractiveScript();
if (node) {
if (!name) {
name = node.getAttribute('data-requiremodule');
}
context = contexts[node.getAttribute('data-requirecontext')];
}
}
//Always save off evaluating the def call until the script onload handler.
//This allows multiple modules to be in a file without prematurely
//tracing dependencies, and allows for anonymous module support,
//where the module name is not known until the script onload event
//occurs. If no context, use the global queue, and get it processed
//in the onscript load callback.
if (context) {
context.defQueue.push([name, deps, callback]);
context.defQueueMap[name] = true;
} else {
globalDefQueue.push([name, deps, callback]);
}
};
define.amd = {
jQuery: true
};
/**
* Executes the text. Normally just uses eval, but can be modified
* to use a better, environment-specific call. Only used for transpiling
* loader plugins, not for plain JS modules.
* @param {String} text the text to execute/evaluate.
*/
req.exec = function (text) {
/*jslint evil: true */
return eval(text);
};
//Set up with config info.
req(cfg);
}(this, (typeof setTimeout === 'undefined' ? undefined : setTimeout)));
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>require.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
!function(f,a,c){var s,l=256,p="random",d=c.pow(l,6),g=c.pow(2,52),y=2*g,h=l-1;function n(n,t,r){function e(){for(var n=u.g(6),t=d,r=0;n<g;)n=(n+r)*l,t*=l,r=u.g(1);for(;y<=n;)n/=2,t/=2,r>>>=1;return(n+r)/t}var o=[],i=j(function n(t,r){var e,o=[],i=typeof t;if(r&&"object"==i)for(e in t)try{o.push(n(t[e],r-1))}catch(n){}return o.length?o:"string"==i?t:t+"\0"}((t=1==t?{entropy:!0}:t||{}).entropy?[n,S(a)]:null==n?function(){try{var n;return s&&(n=s.randomBytes)?n=n(l):(n=new Uint8Array(l),(f.crypto||f.msCrypto).getRandomValues(n)),S(n)}catch(n){var t=f.navigator,r=t&&t.plugins;return[+new Date,f,r,f.screen,S(a)]}}():n,3),o),u=new m(o);return e.int32=function(){return 0|u.g(4)},e.quick=function(){return u.g(4)/4294967296},e.double=e,j(S(u.S),a),(t.pass||r||function(n,t,r,e){return e&&(e.S&&v(e,u),n.state=function(){return v(u,{})}),r?(c[p]=n,t):n})(e,i,"global"in t?t.global:this==c,t.state)}function m(n){var t,r=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(r||(n=[r++]);e<l;)i[e]=e++;for(e=0;e<l;e++)i[e]=i[o=h&o+n[e%r]+(t=i[e])],i[o]=t;(u.g=function(n){for(var t,r=0,e=u.i,o=u.j,i=u.S;n--;)t=i[e=h&e+1],r=r*l+i[h&(i[e]=i[o=h&o+t])+(i[o]=t)];return u.i=e,u.j=o,r})(l)}function v(n,t){return t.i=n.i,t.j=n.j,t.S=n.S.slice(),t}function j(n,t){for(var r,e=n+"",o=0;o<e.length;)t[h&o]=h&(r^=19*t[h&o])+e.charCodeAt(o++);return S(t)}function S(n){return String.fromCharCode.apply(0,n)}if(j(c.random(),a),"object"==typeof module&&module.exports){module.exports=n;try{s=require("crypto")}catch(n){}}else"function"==typeof define&&define.amd?define(function(){return n}):c["seed"+p]=n}("undefined"!=typeof self?self:this,[],Math);
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>seedrandom.min.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*! Split.js - v1.3.5 */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var e=window,t=e.document,n="addEventListener",i="removeEventListener",r="getBoundingClientRect",s=function(){return!1},o=e.attachEvent&&!e[n],a=["","-webkit-","-moz-","-o-"].filter(function(e){var n=t.createElement("div");return n.style.cssText="width:"+e+"calc(9px)",!!n.style.length}).shift()+"calc",l=function(e){return"string"==typeof e||e instanceof String?t.querySelector(e):e};return function(u,c){function z(e,t,n){var i=A(y,t,n);Object.keys(i).forEach(function(t){return e.style[t]=i[t]})}function h(e,t){var n=B(y,t);Object.keys(n).forEach(function(t){return e.style[t]=n[t]})}function f(e){var t=E[this.a],n=E[this.b],i=t.size+n.size;t.size=e/this.size*i,n.size=i-e/this.size*i,z(t.element,t.size,this.aGutterSize),z(n.element,n.size,this.bGutterSize)}function m(e){var t;this.dragging&&((t="touches"in e?e.touches[0][b]-this.start:e[b]-this.start)<=E[this.a].minSize+M+this.aGutterSize?t=E[this.a].minSize+this.aGutterSize:t>=this.size-(E[this.b].minSize+M+this.bGutterSize)&&(t=this.size-(E[this.b].minSize+this.bGutterSize)),f.call(this,t),c.onDrag&&c.onDrag())}function g(){var e=E[this.a].element,t=E[this.b].element;this.size=e[r]()[y]+t[r]()[y]+this.aGutterSize+this.bGutterSize,this.start=e[r]()[G]}function d(){var t=this,n=E[t.a].element,r=E[t.b].element;t.dragging&&c.onDragEnd&&c.onDragEnd(),t.dragging=!1,e[i]("mouseup",t.stop),e[i]("touchend",t.stop),e[i]("touchcancel",t.stop),t.parent[i]("mousemove",t.move),t.parent[i]("touchmove",t.move),delete t.stop,delete t.move,n[i]("selectstart",s),n[i]("dragstart",s),r[i]("selectstart",s),r[i]("dragstart",s),n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",r.style.userSelect="",r.style.webkitUserSelect="",r.style.MozUserSelect="",r.style.pointerEvents="",t.gutter.style.cursor="",t.parent.style.cursor=""}function S(t){var i=this,r=E[i.a].element,o=E[i.b].element;!i.dragging&&c.onDragStart&&c.onDragStart(),t.preventDefault(),i.dragging=!0,i.move=m.bind(i),i.stop=d.bind(i),e[n]("mouseup",i.stop),e[n]("touchend",i.stop),e[n]("touchcancel",i.stop),i.parent[n]("mousemove",i.move),i.parent[n]("touchmove",i.move),r[n]("selectstart",s),r[n]("dragstart",s),o[n]("selectstart",s),o[n]("dragstart",s),r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",o.style.userSelect="none",o.style.webkitUserSelect="none",o.style.MozUserSelect="none",o.style.pointerEvents="none",i.gutter.style.cursor=j,i.parent.style.cursor=j,g.call(i)}function v(e){e.forEach(function(t,n){if(n>0){var i=F[n-1],r=E[i.a],s=E[i.b];r.size=e[n-1],s.size=t,z(r.element,r.size,i.aGutterSize),z(s.element,s.size,i.bGutterSize)}})}function p(){F.forEach(function(e){e.parent.removeChild(e.gutter),E[e.a].element.style[y]="",E[e.b].element.style[y]=""})}void 0===c&&(c={});var y,b,G,E,w=l(u[0]).parentNode,D=e.getComputedStyle(w).flexDirection,U=c.sizes||u.map(function(){return 100/u.length}),k=void 0!==c.minSize?c.minSize:100,x=Array.isArray(k)?k:u.map(function(){return k}),L=void 0!==c.gutterSize?c.gutterSize:10,M=void 0!==c.snapOffset?c.snapOffset:30,O=c.direction||"horizontal",j=c.cursor||("horizontal"===O?"ew-resize":"ns-resize"),C=c.gutter||function(e,n){var i=t.createElement("div");return i.className="gutter gutter-"+n,i},A=c.elementStyle||function(e,t,n){var i={};return"string"==typeof t||t instanceof String?i[e]=t:i[e]=o?t+"%":a+"("+t+"% - "+n+"px)",i},B=c.gutterStyle||function(e,t){return n={},n[e]=t+"px",n;var n};"horizontal"===O?(y="width","clientWidth",b="clientX",G="left","paddingLeft"):"vertical"===O&&(y="height","clientHeight",b="clientY",G="top","paddingTop");var F=[];return E=u.map(function(e,t){var i,s={element:l(e),size:U[t],minSize:x[t]};if(t>0&&(i={a:t-1,b:t,dragging:!1,isFirst:1===t,isLast:t===u.length-1,direction:O,parent:w},i.aGutterSize=L,i.bGutterSize=L,i.isFirst&&(i.aGutterSize=L/2),i.isLast&&(i.bGutterSize=L/2),"row-reverse"===D||"column-reverse"===D)){var a=i.a;i.a=i.b,i.b=a}if(!o&&t>0){var c=C(t,O);h(c,L),c[n]("mousedown",S.bind(i)),c[n]("touchstart",S.bind(i)),w.insertBefore(c,s.element),i.gutter=c}0===t||t===u.length-1?z(s.element,s.size,L/2):z(s.element,s.size,L);var f=s.element[r]()[y];return f<s.minSize&&(s.minSize=f),t>0&&F.push(i),s}),o?{setSizes:v,destroy:p}:{setSizes:v,getSizes:function(){return E.map(function(e){return e.size})},collapse:function(e){if(e===F.length){var t=F[e-1];g.call(t),o||f.call(t,t.size-t.bGutterSize)}else{var n=F[e];g.call(n),o||f.call(n,n.aGutterSize)}},destroy:p}}});
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>split.min.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
Standard gadget with babylonjs drone simulator.
\ No newline at end of file
erp5_drone_simulator
\ No newline at end of file
erp5_drone_simulator
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment