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+});