Showing the changes to scripts/tutorials (3 of 3 files). Show all
Unified · Split
| @@ -1,181 +0,0 @@ | |||
| 1 | // gravity.js | ||
| 2 | // | ||
| 3 | // Created by Philip Rosedale on March 29, 2016 | ||
| 4 | // Copyright 2016 High Fidelity, Inc. | ||
| 5 | // | ||
| 6 | // Distributed under the Apache License, Version 2.0. | ||
| 7 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html | ||
| 8 | // | ||
| 9 | // This entity script causes the object to move with gravitational force and be attracted to other spheres nearby. | ||
| 10 | // The force is scaled by GRAVITY_STRENGTH, and only entities of type "Sphere" within GRAVITY_RANGE will affect it. | ||
| 11 | // The person who has most recently grabbed this object will simulate it. | ||
| 12 | // | ||
| 13 | |||
| 14 | function Timer() { | ||
| 15 | var time; | ||
| 16 | var count = 0; | ||
| 17 | var totalTime = 0; | ||
| 18 | this.reset = function() { | ||
| 19 | count = 0; | ||
| 20 | totalTime = 0; | ||
| 21 | } | ||
| 22 | this.start = function() { | ||
| 23 | time = new Date().getTime(); | ||
| 24 | } | ||
| 25 | this.record = function() { | ||
| 26 | var elapsed = new Date().getTime() - time; | ||
| 27 | totalTime += elapsed; | ||
| 28 | count++; | ||
| 29 | return elapsed; | ||
| 30 | } | ||
| 31 | this.count = function() { | ||
| 32 | return count; | ||
| 33 | } | ||
| 34 | this.average = function() { | ||
| 35 | return (count == 0) ? 0 : totalTime / count; | ||
| 36 | } | ||
| 37 | this.elapsed = function() { | ||
| 38 | return new Date().getTime() - time; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | (function () { | ||
| 43 | var entityID, | ||
| 44 | wantDebug = true, | ||
| 45 | CHECK_INTERVAL = 10.00, | ||
| 46 | SEARCH_INTERVAL = 1000, | ||
| 47 | GRAVITY_RANGE = 20.0, | ||
| 48 | GRAVITY_STRENGTH = 1.0, | ||
| 49 | MIN_VELOCITY = 0.01, | ||
| 50 | timeoutID = null, | ||
| 51 | timeSinceLastSearch = 0, | ||
| 52 | timer = new Timer(), | ||
| 53 | simulate = false, | ||
| 54 | spheres = []; | ||
| 55 | |||
| 56 | var printDebug = function(message) { | ||
| 57 | if (wantDebug) { | ||
| 58 | print(message); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | var greatestDimension = function(dimensions) { | ||
| 63 | return Math.max(Math.max(dimensions.x, dimensions.y), dimensions.z); | ||
| 64 | } | ||
| 65 | |||
| 66 | var mass2 = function(dimensions) { | ||
| 67 | return dimensions.x * dimensions.y * dimensions.z; | ||
| 68 | } | ||
| 69 | |||
| 70 | var findSpheres = function(position) { | ||
| 71 | var entities = Entities.findEntities(position, GRAVITY_RANGE); | ||
| 72 | spheres = []; | ||
| 73 | for (var i = 0; i < entities.length; i++) { | ||
| 74 | if (entityID == spheres[i]) { | ||
| 75 | // this entity doesn't experience its own gravity. | ||
| 76 | continue; | ||
| 77 | } | ||
| 78 | var props = Entities.getEntityProperties(entities[i]); | ||
| 79 | if (props && (props.shapeType == "sphere" || props.type == "Sphere")) { | ||
| 80 | spheres.push(entities[i]); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | // print("FOUND " + spheres.length + " SPHERES"); | ||
| 84 | } | ||
| 85 | |||
| 86 | var applyGravity = function() { | ||
| 87 | if (!simulate) { | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | |||
| 91 | var properties = Entities.getEntityProperties(entityID); | ||
| 92 | if (!properties || !properties.position) { | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | // update the list of nearby spheres | ||
| 97 | var deltaTime = timer.elapsed() / 1000.0; | ||
| 98 | if (deltaTime == 0.0) { | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | timeSinceLastSearch += CHECK_INTERVAL; | ||
| 102 | if (timeSinceLastSearch >= SEARCH_INTERVAL) { | ||
| 103 | findSpheres(properties.position); | ||
| 104 | timeSinceLastSearch = 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | var deltaVelocity = { x: 0, y: 0, z: 0 }; | ||
| 108 | var otherCount = 0; | ||
| 109 | var mass = mass2(properties.dimensions); | ||
| 110 | |||
| 111 | for (var i = 0; i < spheres.length; i++) { | ||
| 112 | otherProperties = Entities.getEntityProperties(spheres[i]); | ||
| 113 | if (!otherProperties || !otherProperties.position) { | ||
| 114 | continue; // sphere was deleted | ||
| 115 | } | ||
| 116 | otherCount++; | ||
| 117 | var radius = Vec3.distance(properties.position, otherProperties.position); | ||
| 118 | var otherMass = mass2(otherProperties.dimensions); | ||
| 119 | var r = (greatestDimension(properties.dimensions) + greatestDimension(otherProperties.dimensions)) / 2; | ||
| 120 | if (radius > r) { | ||
| 121 | var n0 = Vec3.normalize(Vec3.subtract(otherProperties.position, properties.position)); | ||
| 122 | var n1 = Vec3.multiply(deltaTime * GRAVITY_STRENGTH * otherMass / (radius * radius), n0); | ||
| 123 | deltaVelocity = Vec3.sum(deltaVelocity, n1); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | Entities.editEntity(entityID, { velocity: Vec3.sum(properties.velocity, deltaVelocity) }); | ||
| 127 | if (Vec3.length(properties.velocity) < MIN_VELOCITY) { | ||
| 128 | print("Gravity simulation stopped due to velocity"); | ||
| 129 | simulate = false; | ||
| 130 | } else { | ||
| 131 | timer.start(); | ||
| 132 | timeoutID = Script.setTimeout(applyGravity, CHECK_INTERVAL); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | this.applyGravity = applyGravity; | ||
| 136 | |||
| 137 | var releaseGrab = function() { | ||
| 138 | printDebug("Gravity simulation started."); | ||
| 139 | var properties = Entities.getEntityProperties(entityID); | ||
| 140 | findSpheres(properties.position); | ||
| 141 | timer.start(); | ||
| 142 | timeoutID = Script.setTimeout(applyGravity, CHECK_INTERVAL); | ||
| 143 | simulate = true; | ||
| 144 | } | ||
| 145 | this.releaseGrab = releaseGrab; | ||
| 146 | |||
| 147 | var preload = function (givenEntityID) { | ||
| 148 | printDebug("load gravity..."); | ||
| 149 | entityID = givenEntityID; | ||
| 150 | }; | ||
| 151 | this.preload = preload; | ||
| 152 | |||
| 153 | var unload = function () { | ||
| 154 | printDebug("Unload gravity..."); | ||
| 155 | if (timeoutID !== undefined) { | ||
| 156 | Script.clearTimeout(timeoutID); | ||
| 157 | } | ||
| 158 | if (simulate) { | ||
| 159 | Entities.editEntity(entityID, { velocity: { x: 0, y: 0, z: 0 } }); | ||
| 160 | } | ||
| 161 | }; | ||
| 162 | this.unload = unload; | ||
| 163 | |||
| 164 | var handleMessages = function(channel, message, sender) { | ||
| 165 | if (channel === 'Hifi-Object-Manipulation') { | ||
| 166 | try { | ||
| 167 | var parsedMessage = JSON.parse(message); | ||
| 168 | if (parsedMessage.action === 'grab' && parsedMessage.grabbedEntity == entityID) { | ||
| 169 | print("Gravity simulation stopped due to grab"); | ||
| 170 | simulate = false; | ||
| 171 | } | ||
| 172 | } catch (e) { | ||
| 173 | print('error parsing Hifi-Object-Manipulation message: ' + message); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } | ||
| 177 | this.handleMessages = handleMessages; | ||
| 178 | |||
| 179 | Messages.messageReceived.connect(this.handleMessages); | ||
| 180 | Messages.subscribe('Hifi-Object-Manipulation'); | ||
| 181 | }); | ||
| @@ -1,72 +0,0 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||
| 3 | |||
| 4 | <svg | ||
| 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" | ||
| 6 | xmlns:cc="http://creativecommons.org/ns#" | ||
| 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
| 8 | xmlns:svg="http://www.w3.org/2000/svg" | ||
| 9 | xmlns="http://www.w3.org/2000/svg" | ||
| 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
| 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
| 12 | width="64" | ||
| 13 | height="64" | ||
| 14 | viewBox="0 0 64.000001 64.000001" | ||
| 15 | id="svg2" | ||
| 16 | version="1.1" | ||
| 17 | inkscape:version="0.91 r13725" | ||
| 18 | sodipodi:docname="gravity.svg"> | ||
| 19 | <defs | ||
| 20 | id="defs4" /> | ||
| 21 | <sodipodi:namedview | ||
| 22 | id="base" | ||
| 23 | pagecolor="#ffffff" | ||
| 24 | bordercolor="#666666" | ||
| 25 | borderopacity="1.0" | ||
| 26 | inkscape:pageopacity="0.0" | ||
| 27 | inkscape:pageshadow="2" | ||
| 28 | inkscape:zoom="1.4" | ||
| 29 | inkscape:cx="192.07838" | ||
| 30 | inkscape:cy="33.619203" | ||
| 31 | inkscape:document-units="px" | ||
| 32 | inkscape:current-layer="layer1" | ||
| 33 | showgrid="false" | ||
| 34 | units="px" | ||
| 35 | inkscape:window-width="2782" | ||
| 36 | inkscape:window-height="1764" | ||
| 37 | inkscape:window-x="98" | ||
| 38 | inkscape:window-y="36" | ||
| 39 | inkscape:window-maximized="1" /> | ||
| 40 | <metadata | ||
| 41 | id="metadata7"> | ||
| 42 | <rdf:RDF> | ||
| 43 | <cc:Work | ||
| 44 | rdf:about=""> | ||
| 45 | <dc:format>image/svg+xml</dc:format> | ||
| 46 | <dc:type | ||
| 47 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||
| 48 | <dc:title></dc:title> | ||
| 49 | </cc:Work> | ||
| 50 | </rdf:RDF> | ||
| 51 | </metadata> | ||
| 52 | <g | ||
| 53 | inkscape:label="Layer 1" | ||
| 54 | inkscape:groupmode="layer" | ||
| 55 | id="layer1" | ||
| 56 | transform="translate(0,-988.36216)"> | ||
| 57 | <ellipse | ||
| 58 | style="fill:#a09898;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none" | ||
| 59 | id="path4690" | ||
| 60 | cx="12.142858" | ||
| 61 | cy="1039.1478" | ||
| 62 | rx="8.5714283" | ||
| 63 | ry="8.2142859" /> | ||
| 64 | <ellipse | ||
| 65 | style="fill:#3131d9;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" | ||
| 66 | id="path4692" | ||
| 67 | cx="39.285717" | ||
| 68 | cy="1014.1478" | ||
| 69 | rx="21.358366" | ||
| 70 | ry="21.001223" /> | ||
| 71 | </g> | ||
| 72 | </svg> | ||
| @@ -1,166 +0,0 @@ | |||
| 1 | // makePlanets.js | ||
| 2 | // | ||
| 3 | // Created by Philip Rosedale on March 29, 2016 | ||
| 4 | // Copyright 2016 High Fidelity, Inc. | ||
| 5 | // | ||
| 6 | // Distributed under the Apache License, Version 2.0. | ||
| 7 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html | ||
| 8 | // | ||
| 9 | // Make an earth and moon, where you can grab and throw moon into orbit. Entity | ||
| 10 | // script attached to moon gives it gravitation behavior and will also make it attracted to | ||
| 11 | // other spheres placed nearby. | ||
| 12 | // | ||
| 13 | |||
| 14 | var SCALE = 3.0; | ||
| 15 | var EARTH_SIZE = 3.959 / SCALE; | ||
| 16 | var MOON_SIZE = 1.079 / SCALE; | ||
| 17 | |||
| 18 | var BUTTON_SIZE = 32; | ||
| 19 | var PADDING = 3; | ||
| 20 | |||
| 21 | var earth = null; | ||
| 22 | var moon = null; | ||
| 23 | |||
| 24 | var SCRIPT_URL = Script.resolvePath("gravity.js"); | ||
| 25 | |||
| 26 | HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; | ||
| 27 | Script.include(["/~/system/libraries/toolBars.js"]); | ||
| 28 | var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.makePlanets.js"); | ||
| 29 | |||
| 30 | var makePlanetsIconURL = Script.resolvePath("gravity.svg"); | ||
| 31 | var button = toolBar.addOverlay("image", { | ||
| 32 | width: BUTTON_SIZE, | ||
| 33 | height: BUTTON_SIZE, | ||
| 34 | imageURL: makePlanetsIconURL, | ||
| 35 | color: { | ||
| 36 | red: 255, | ||
| 37 | green: 255, | ||
| 38 | blue: 255 | ||
| 39 | }, | ||
| 40 | alpha: 1 | ||
| 41 | }); | ||
| 42 | |||
| 43 | var deleteButton = toolBar.addOverlay("image", { | ||
| 44 | width: BUTTON_SIZE, | ||
| 45 | height: BUTTON_SIZE, | ||
| 46 | imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png", | ||
| 47 | color: { | ||
| 48 | red: 255, | ||
| 49 | green: 255, | ||
| 50 | blue: 255 | ||
| 51 | }, | ||
| 52 | alpha: 1 | ||
| 53 | }); | ||
| 54 | |||
| 55 | function inFrontOfMe(distance) { | ||
| 56 | return Vec3.sum(Camera.getPosition(), Vec3.multiply(distance, Quat.getForward(Camera.getOrientation()))); | ||
| 57 | } | ||
| 58 | |||
| 59 | function onButtonClick() { | ||
| 60 | earth = Entities.addEntity({ | ||
| 61 | type: "Model", | ||
| 62 | name: "Earth", | ||
| 63 | modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/earth.fbx", | ||
| 64 | position: inFrontOfMe(2 * EARTH_SIZE), | ||
| 65 | dimensions: { x: EARTH_SIZE, y: EARTH_SIZE, z: EARTH_SIZE }, | ||
| 66 | shapeType: "sphere", | ||
| 67 | lifetime: 86400, // 1 day | ||
| 68 | angularDamping: 0, | ||
| 69 | angularVelocity: { x: 0, y: 0.1, z: 0 }, | ||
| 70 | }); | ||
| 71 | moon = Entities.addEntity({ | ||
| 72 | type: "Model", | ||
| 73 | name: "Moon", | ||
| 74 | modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/moon.fbx", | ||
| 75 | position: inFrontOfMe(EARTH_SIZE - MOON_SIZE), | ||
| 76 | dimensions: { x: MOON_SIZE, y: MOON_SIZE, z: MOON_SIZE }, | ||
| 77 | dynamic: true, | ||
| 78 | damping: 0, // 0.01, | ||
| 79 | angularDamping: 0, // 0.01, | ||
| 80 | script: SCRIPT_URL, | ||
| 81 | shapeType: "sphere" | ||
| 82 | }); | ||
| 83 | Entities.addEntity({ | ||
| 84 | "accelerationSpread": { | ||
| 85 | "x": 0, | ||
| 86 | "y": 0, | ||
| 87 | "z": 0 | ||
| 88 | }, | ||
| 89 | "alpha": 1, | ||
| 90 | "alphaFinish": 0, | ||
| 91 | "alphaStart": 1, | ||
| 92 | "azimuthFinish": 0, | ||
| 93 | "azimuthStart": 0, | ||
| 94 | "color": { | ||
| 95 | "blue": 255, | ||
| 96 | "green": 255, | ||
| 97 | "red": 255 | ||
| 98 | }, | ||
| 99 | "colorFinish": { | ||
| 100 | "blue": 255, | ||
| 101 | "green": 255, | ||
| 102 | "red": 255 | ||
| 103 | }, | ||
| 104 | "colorStart": { | ||
| 105 | "blue": 255, | ||
| 106 | "green": 255, | ||
| 107 | "red": 255 | ||
| 108 | }, | ||
| 109 | "dimensions": { | ||
| 110 | "x": 0.10890001058578491, | ||
| 111 | "y": 0.10890001058578491, | ||
| 112 | "z": 0.10890001058578491 | ||
| 113 | }, | ||
| 114 | "emitAcceleration": { | ||
| 115 | "x": 0, | ||
| 116 | "y": 0, | ||
| 117 | "z": 0 | ||
| 118 | }, | ||
| 119 | "emitOrientation": { | ||
| 120 | "w": 0.99999994039535522, | ||
| 121 | "x": 0, | ||
| 122 | "y": 0, | ||
| 123 | "z": 0 | ||
| 124 | }, | ||
| 125 | "emitRate": 300, | ||
| 126 | "emitSpeed": 0, | ||
| 127 | "emitterShouldTrail": 1, | ||
| 128 | "maxParticles": 10000, | ||
| 129 | "name": "moon trail", | ||
| 130 | "parentID": moon, | ||
| 131 | "particleRadius": 0.005, | ||
| 132 | "radiusFinish": 0.005, | ||
| 133 | "radiusSpread": 0.005, | ||
| 134 | "radiusStart": 0.005, | ||
| 135 | "speedSpread": 0, | ||
| 136 | "lifespan": 20, | ||
| 137 | "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", | ||
| 138 | "type": "ParticleEffect", | ||
| 139 | "userData": "{\"grabbableKey\":{\"grabbable\":false}}" | ||
| 140 | }); | ||
| 141 | } | ||
| 142 | |||
| 143 | function onDeleteButton() { | ||
| 144 | Entities.deleteEntity(earth); | ||
| 145 | Entities.deleteEntity(moon); | ||
| 146 | } | ||
| 147 | |||
| 148 | function mousePressEvent(event) { | ||
| 149 | var clickedText = false; | ||
| 150 | var clickedOverlay = Overlays.getOverlayAtPoint({ | ||
| 151 | x: event.x, | ||
| 152 | y: event.y | ||
| 153 | }); | ||
| 154 | if (clickedOverlay == button) { | ||
| 155 | onButtonClick(); | ||
| 156 | } else if (clickedOverlay == deleteButton) { | ||
| 157 | onDeleteButton(); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | function scriptEnding() { | ||
| 162 | toolBar.cleanup(); | ||
| 163 | } | ||
| 164 | |||
| 165 | Controller.mousePressEvent.connect(mousePressEvent); | ||
| 166 | Script.scriptEnding.connect(scriptEnding); | ||