History

Merge pull request #10175 from PhilipRosedale/springHold

New Tutorial and entity scripts

Brad Hefta-Gaub committed 9 years ago

Commit f1bd3712 parents ac6d496 8826dbe7 files · +448 −419Browse files

Showing the changes to scripts/tutorials/entity_scripts (2 of 7 files). Show all

Unified · Split

2 files
  1. scripts/tutorials/entity_scripts/springHold.js +116 −0
  2. scripts/tutorials/entity_scripts/touch.js +206 −0
scripts/tutorials/entity_scripts/springHold.js+116−0
@@ -0,0 +1,116 @@
1//
2// springHold.js
3//
4// Created by Philip Rosedale on March 18, 2017
5// Copyright 2017 High Fidelity, Inc.
6//
7// Attach this entity script to a model or basic shape and grab it. The object will
8// follow your hand like a spring, allowing you, for example, to swordfight with others.
9//
10// Distributed under the Apache License, Version 2.0.
11// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
12//
13
14(function() {
15
16 var TIMESCALE = 0.03;
17 var ACTION_TTL = 10;
18 var _this;
19
20 function SpringHold() {
21 _this = this;
22 }
23
24 function updateSpringAction(timescale) {
25
26 var targetProps = Entities.getEntityProperties(_this.entityID);
27 var props = {
28 targetPosition: targetProps.position,
29 targetRotation: targetProps.rotation,
30 linearTimeScale: timescale,
31 angularTimeScale: timescale,
32 ttl: ACTION_TTL
33 };
34 Entities.updateAction(_this.copy, _this.actionID, props);
35 }
36
37 function createSpringAction(timescale) {
38
39 var targetProps = Entities.getEntityProperties(_this.entityID);
40 var props = {
41 targetPosition: targetProps.position,
42 targetRotation: targetProps.rotation,
43 linearTimeScale: timescale,
44 angularTimeScale: timescale,
45 ttl: ACTION_TTL
46 };
47 _this.actionID = Entities.addAction("spring", _this.copy, props);
48 }
49
50 function createCopy() {
51 var originalProps = Entities.getEntityProperties(_this.entityID);
52 var props = {
53 type: originalProps.type,
54 color: originalProps.color,
55 modelURL: originalProps.modelURL,
56 dimensions: originalProps.dimensions,
57 dynamic: true,
58 damping: 0.0,
59 angularDamping: 0.0,
60 collidesWith: 'dynamic,static,kinematic',
61 rotation: originalProps.rotation,
62 position: originalProps.position,
63 shapeType: originalProps.shapeType,
64 visible: true,
65 userData:JSON.stringify({
66 grabbableKey:{
67 grabbable:false
68 }
69 })
70 };
71 _this.copy = Entities.addEntity(props);
72 }
73
74 function deleteCopy() {
75 Entities.deleteEntity(_this.copy);
76 }
77
78 function makeOriginalInvisible() {
79 Entities.editEntity(_this.entityID, {
80 visible: false,
81 collisionless: true
82 });
83 }
84
85 function makeOriginalVisible() {
86 Entities.editEntity(_this.entityID, {
87 visible: true,
88 collisionless: false
89 });
90 }
91
92 function deleteSpringAction() {
93 Entities.deleteAction(_this.copy, _this.actionID);
94 }
95
96 SpringHold.prototype = {
97 preload: function(entityID) {
98 _this.entityID = entityID;
99 },
100 startNearGrab: function(entityID, data) {
101 createCopy();
102 createSpringAction(TIMESCALE);
103 makeOriginalInvisible();
104 },
105 continueNearGrab: function() {
106 updateSpringAction(TIMESCALE);
107 },
108 releaseGrab: function() {
109 deleteSpringAction();
110 deleteCopy();
111 makeOriginalVisible();
112 }
113 };
114
115 return new SpringHold();
116});
scripts/tutorials/entity_scripts/touch.js+206−0
@@ -0,0 +1,206 @@
1(function() {
2
3 // touch.js
4 //
5 // Sample file using spring action, haptic vibration, and color change to demonstrate two spheres
6 // That can give a sense of touch to the holders.
7 // Create two standard spheres, make them grabbable, and attach this entity script. Grab them and touch them together.
8 //
9 // Created by Philip Rosedale on March 18, 2017
10 // Copyright 2017 High Fidelity, Inc.
11 //
12 // Distributed under the Apache License, Version 2.0.
13 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
14 //
15
16 var TIMESCALE = 0.03;
17 var ACTION_TTL = 10;
18 var _this;
19
20 var RIGHT_HAND = 1;
21 var LEFT_HAND = 0;
22 var HAPTIC_PULSE_FIRST_STRENGTH = 0.5;
23 var HAPTIC_PULSE_MIN_STRENGTH = 0.20;
24 var HAPTIC_PULSE_MAX_STRENGTH = 0.5;
25 var HAPTIC_PULSE_FIRST_DURATION = 1.0;
26 var HAPTIC_PULSE_DURATION = 16.0;
27 var HAPTIC_PULSE_DISTANCE = 0.0;
28 var MAX_PENETRATION = 0.02;
29 var HAPTIC_MIN_VELOCITY = 0.002;
30 var HAPTIC_MAX_VELOCITY = 0.5;
31 var PENETRATION_PULLBACK_FACTOR = 0.65;
32 var FRAME_TIME = 0.016;
33
34 var isColliding = false;
35
36 var hand = LEFT_HAND;
37 var lastHapticPulseLocation = { x:0, y:0, z:0 };
38
39
40 var GRAY = { red: 128, green: 128, blue: 128 };
41 var RED = { red: 255, green: 0, blue: 0 };
42
43 var targetColor = { x: GRAY.red, y: GRAY.green, z: GRAY.blue };
44
45 var lastPosition = { x: 0, y: 0, z: 0 };
46 var velocity = { x: 0, y: 0, z: 0 };
47
48 var lastOtherPosition = { x: 0, y: 0, z: 0 };
49 var otherVelocity = { x: 0, y: 0, z: 0 };
50
51
52 function TouchExample() {
53 _this = this;
54 }
55
56 function updateSpringAction(timescale) {
57 var targetProps = Entities.getEntityProperties(_this.entityID);
58 //
59 // Look for nearby entities to touch
60 //
61 var copyProps = Entities.getEntityProperties(_this.copy);
62 var nearbyEntities = Entities.findEntities(copyProps.position, copyProps.dimensions.x * 2);
63 var wasColliding = isColliding;
64 var targetAdjust = { x: 0, y: 0, z: 0 };
65
66 isColliding = false;
67 for (var i = 0; i < nearbyEntities.length; i++) {
68 if (_this.copy != nearbyEntities[i] && _this.entityID != nearbyEntities[i]) {
69 var otherProps = Entities.getEntityProperties(nearbyEntities[i]);
70 var penetration = Vec3.distance(copyProps.position, otherProps.position) - (copyProps.dimensions.x / 2 + otherProps.dimensions.x / 2);
71 if (otherProps.type === 'Sphere' && penetration < 0 && penetration > -copyProps.dimensions.x * 3) {
72 isColliding = true;
73 targetAdjust = Vec3.sum(targetAdjust, Vec3.multiply(Vec3.normalize(Vec3.subtract(targetProps.position, otherProps.position)), -penetration * PENETRATION_PULLBACK_FACTOR));
74 if (!wasColliding && false) {
75 targetColor = { x: RED.red, y: RED.green, z: RED.blue };
76 } else {
77 targetColor = { x: 200 + Math.min(-penetration / MAX_PENETRATION, 1.0) * 55, y: GRAY.green, z: GRAY.blue };
78 }
79 if (Vec3.distance(targetProps.position, lastHapticPulseLocation) > HAPTIC_PULSE_DISTANCE || !wasColliding) {
80 if (!wasColliding) {
81 velocity = { x: 0, y: 0, z: 0};
82 otherVelocity = { x: 0, y: 0, z: 0 };
83 Controller.triggerHapticPulse(HAPTIC_PULSE_FIRST_STRENGTH, HAPTIC_PULSE_FIRST_DURATION, hand);
84 } else {
85 velocity = Vec3.distance(targetProps.position, lastPosition) / FRAME_TIME;
86 otherVelocity = Vec3.distance(otherProps.position, lastOtherPosition) / FRAME_TIME;
87 var velocityStrength = Math.min(velocity + otherVelocity / HAPTIC_MAX_VELOCITY, 1.0);
88 var strength = HAPTIC_PULSE_MIN_STRENGTH + Math.min(-penetration / MAX_PENETRATION, 1.0) * (HAPTIC_PULSE_MAX_STRENGTH - HAPTIC_PULSE_MIN_STRENGTH);
89 Controller.triggerHapticPulse(velocityStrength * strength, HAPTIC_PULSE_DURATION, hand);
90 }
91 lastPosition = targetProps.position;
92 lastOtherPosition = otherProps.position;
93 lastHapticPulseLocation = targetProps.position;
94 }
95 }
96 }
97 }
98 if ((wasColliding != isColliding) && !isColliding) {
99 targetColor = { x: GRAY.red, y: GRAY.green, z: GRAY.blue };
100 }
101 // Interpolate color toward target color
102 var currentColor = { x: copyProps.color.red, y: copyProps.color.green, z: copyProps.color.blue };
103 var newColor = Vec3.sum(currentColor, Vec3.multiply(Vec3.subtract(targetColor, currentColor), 0.1));
104 Entities.editEntity(_this.copy, { color: { red: newColor.x, green: newColor.y, blue: newColor.z } });
105
106 var props = {
107 targetPosition: Vec3.sum(targetProps.position, targetAdjust),
108 targetRotation: targetProps.rotation,
109 linearTimeScale: timescale,
110 angularTimeScale: timescale,
111 ttl: ACTION_TTL
112 };
113 var success = Entities.updateAction(_this.copy, _this.actionID, props);
114 }
115
116 function createSpringAction(timescale) {
117
118 var targetProps = Entities.getEntityProperties(_this.entityID);
119 var props = {
120 targetPosition: targetProps.position,
121 targetRotation: targetProps.rotation,
122 linearTimeScale: timescale,
123 angularTimeScale: timescale,
124 ttl: ACTION_TTL
125 };
126 _this.actionID = Entities.addAction("spring", _this.copy, props);
127 return;
128 }
129
130 function createCopy() {
131 var originalProps = Entities.getEntityProperties(_this.entityID);
132 var props = {
133 type: originalProps.type,
134 modelURL: originalProps.modelURL,
135 dimensions: originalProps.dimensions,
136 color: GRAY,
137 dynamic: true,
138 damping: 0.0,
139 angularDamping: 0.0,
140 collidesWith: 'static',
141 rotation: originalProps.rotation,
142 position: originalProps.position,
143 shapeType: originalProps.shapeType,
144 visible: true,
145 userData:JSON.stringify({
146 grabbableKey:{
147 grabbable:false
148 }
149 })
150 };
151 _this.copy = Entities.addEntity(props);
152 }
153
154 function deleteCopy() {
155 print("Delete copy");
156 Entities.deleteEntity(_this.copy);
157 }
158
159 function makeOriginalInvisible() {
160 Entities.editEntity(_this.entityID, {
161 visible: false,
162 collisionless: true
163 });
164 }
165
166 function makeOriginalVisible() {
167 Entities.editEntity(_this.entityID, {
168 visible: true,
169 collisionless: false
170 });
171 }
172
173 function deleteSpringAction() {
174 Entities.deleteAction(_this.copy, _this.actionID);
175 }
176
177 function setHand(position) {
178 if (Vec3.distance(MyAvatar.getLeftPalmPosition(), position) < Vec3.distance(MyAvatar.getRightPalmPosition(), position)) {
179 hand = LEFT_HAND;
180 } else {
181 hand = RIGHT_HAND;
182 }
183 }
184
185 TouchExample.prototype = {
186 preload: function(entityID) {
187 _this.entityID = entityID;
188 },
189 startNearGrab: function(entityID, data) {
190 createCopy();
191 createSpringAction(TIMESCALE);
192 makeOriginalInvisible();
193 setHand(Entities.getEntityProperties(_this.entityID).position);
194 },
195 continueNearGrab: function() {
196 updateSpringAction(TIMESCALE);
197 },
198 releaseGrab: function() {
199 deleteSpringAction();
200 deleteCopy();
201 makeOriginalVisible();
202 }
203 };
204
205 return new TouchExample();
206});