Merge branch 'musicbox' into homereset

This commit is contained in:
James B. Pollack 2016-03-28 15:45:03 -07:00
commit a1004919a5
3 changed files with 457 additions and 29 deletions

View file

@ -44,8 +44,8 @@ var PICK_WITH_HAND_RAY = true;
var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified
var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified
var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified
var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified
var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did
var MOVE_WITH_HEAD = true; // experimental head-control of distantly held objects
var FAR_TO_NEAR_GRAB_PADDING_FACTOR = 1.2;
@ -126,6 +126,7 @@ var GRABBABLE_PROPERTIES = [
var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js
var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js
var GRAB_CONSTRAINTS_USER_DATA_KEY = "grabConstraintsKey"
var DEFAULT_GRABBABLE_DATA = {
disableReleaseVelocity: false
@ -345,7 +346,7 @@ function MyController(hand) {
this.grabSphereOff();
if (WANT_DEBUG || WANT_DEBUG_STATE) {
print("STATE (" + this.hand + "): " + stateToName(this.state) + " --> " +
stateToName(newState) + ", hand: " + this.hand);
stateToName(newState) + ", hand: " + this.hand);
}
this.state = newState;
};
@ -424,11 +425,15 @@ function MyController(hand) {
}
this.grabSphereOn = function() {
var color = {red: 0, green: 255, blue: 0};
var color = {
red: 0,
green: 255,
blue: 0
};
if (this.grabSphere === null) {
var sphereProperties = {
position: this.getHandPosition(),
size: GRAB_RADIUS*2,
size: GRAB_RADIUS * 2,
color: color,
alpha: 0.1,
solid: true,
@ -438,7 +443,7 @@ function MyController(hand) {
} else {
Overlays.editOverlay(this.grabSphere, {
position: this.getHandPosition(),
size: GRAB_RADIUS*2,
size: GRAB_RADIUS * 2,
color: color,
alpha: 0.1,
solid: true,
@ -491,12 +496,10 @@ function MyController(hand) {
}
var searchSphereLocation = Vec3.sum(distantPickRay.origin,
Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
this.searchSphereOn(searchSphereLocation, SEARCH_SPHERE_SIZE * this.searchSphereDistance,
(this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
this.searchSphereOn(searchSphereLocation, SEARCH_SPHERE_SIZE * this.searchSphereDistance, (this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
if ((USE_OVERLAY_LINES_FOR_SEARCHING === true) && PICK_WITH_HAND_RAY) {
this.overlayLineOn(handPosition, searchSphereLocation,
(this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
this.overlayLineOn(handPosition, searchSphereLocation, (this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
}
}
@ -823,8 +826,8 @@ function MyController(hand) {
var distantPickRay = {
origin: PICK_WITH_HAND_RAY ? handPosition : Camera.position,
direction: PICK_WITH_HAND_RAY ? Quat.getUp(this.getHandRotation()) : Vec3.mix(Quat.getUp(this.getHandRotation()),
Quat.getFront(Camera.orientation),
HAND_HEAD_MIX_RATIO),
Quat.getFront(Camera.orientation),
HAND_HEAD_MIX_RATIO),
length: PICK_MAX_DISTANCE
};
@ -999,6 +1002,8 @@ function MyController(hand) {
intersectionPointToCenterDistance *
FAR_TO_NEAR_GRAB_PADDING_FACTOR);
}
this.setState(this.state == STATE_SEARCHING ? STATE_DISTANCE_HOLDING : STATE_EQUIP);
this.searchSphereOff();
return;
@ -1145,9 +1150,9 @@ function MyController(hand) {
// double delta controller rotation
var handChange = Quat.multiply(Quat.slerp(this.previousControllerRotation,
controllerRotation,
DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR),
Quat.inverse(this.previousControllerRotation));
controllerRotation,
DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR),
Quat.inverse(this.previousControllerRotation));
// update the currentObject position and rotation.
this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, handMoved);
@ -1275,7 +1280,9 @@ function MyController(hand) {
};
this.hasPresetOffsets = function() {
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}});
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {
joints: {}
});
if ("joints" in wearableData) {
var allowedJoints = wearableData.joints;
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
@ -1287,7 +1294,9 @@ function MyController(hand) {
}
this.getPresetPosition = function() {
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}});
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {
joints: {}
});
var allowedJoints = wearableData.joints;
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
if (handJointName in allowedJoints) {
@ -1296,7 +1305,9 @@ function MyController(hand) {
}
this.getPresetRotation = function() {
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}});
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {
joints: {}
});
var allowedJoints = wearableData.joints;
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
if (handJointName in allowedJoints) {
@ -1304,7 +1315,23 @@ function MyController(hand) {
}
}
this.getGrabConstraints = function() {
var defaultConstraints = {
positionLocked: false,
rotationLocked: false,
positionMod: false,
rotationMod: {
pitch: false,
yaw: false,
roll: false
}
}
var constraints = getEntityCustomData(GRAB_CONSTRAINTS_USER_DATA_KEY, this.grabbedEntity, defaultConstraints);
return constraints;
}
this.nearGrabbing = function() {
print('NEAR GRAB')
var now = Date.now();
if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
@ -1370,6 +1397,7 @@ function MyController(hand) {
reparentProps["localRotation"] = this.offsetRotation;
}
Entities.editEntity(this.grabbedEntity, reparentProps);
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
action: 'equip',
grabbedEntity: this.grabbedEntity
@ -1392,6 +1420,7 @@ function MyController(hand) {
};
this.continueNearGrabbing = function() {
print('CONTINUE NEAR GRAB')
if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed("releaseGrab");
@ -1427,7 +1456,7 @@ function MyController(hand) {
Vec3.length(props.localPosition) > NEAR_PICK_MAX_DISTANCE * 2.0) {
// for whatever reason, the held/equipped entity has been pulled away. ungrab or unequip.
print("handControllerGrab -- autoreleasing held or equipped item because it is far from hand." +
props.parentID + " " + vec3toStr(props.position));
props.parentID + " " + vec3toStr(props.position));
this.setState(STATE_RELEASE);
this.callEntityMethodOnGrabbed(this.state == STATE_NEAR_GRABBING ? "releaseGrab" : "releaseEquip");
return;
@ -1457,7 +1486,19 @@ function MyController(hand) {
this.callEntityMethodOnGrabbed("continueNearGrab");
}
var constraints = this.getGrabConstraints();
if (constraints.positionLocked === true) {
print('IT HAS ITS POSITION LOCKED!!')
}
if (constraints.rotationMod !== false) {
print('IT HAS A ROTATION MOD!!!')
}
// so it never seems to hit this currently
if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) {
// if less than a 5 seconds left, refresh the actions ttl
var success = Entities.updateAction(this.grabbedEntity, this.actionID, {
hand: this.hand === RIGHT_HAND ? "right" : "left",
@ -1493,6 +1534,9 @@ function MyController(hand) {
}
this.callEntityMethodOnGrabbed("startNearTrigger");
this.setState(STATE_CONTINUE_NEAR_TRIGGER);
print('START NEAR TRIGGER')
};
this.farTrigger = function() {
@ -1511,6 +1555,71 @@ function MyController(hand) {
this.callEntityMethodOnGrabbed("stopNearTrigger");
return;
}
var constraints = this.getGrabConstraints();
if (constraints.rotationMod !== false) {
//implement the rotation modifier
var grabbedProps = Entities.getEntityProperties(this.grabbedEntity);
var handPosition = this.getHandPosition();
var modTypes = [];
if (constraints.rotationMod.pitch !== false) {
modTypes.push('pitch')
}
if (constraints.rotationMod.yaw !== false) {
modTypes.push('yaw')
}
if (constraints.rotationMod.roll !== false) {
modTypes.push('roll')
}
finalRotation = {
x: 0,
y: 0,
z: 0
}
modTypes.forEach(function(modType) {
var value = handPosition[constraints.rotationMod[modType].startingAxis];
var min1 = constraints.rotationMod[modType].startingPoint;
var finalAngle = scale(value, min1, constraints.rotationMod[modType].distanceToMax, constraints.rotationMod[modType].min, constraints.rotationMod[modType].max)
// print('VARS: ')
// print('CONSTRAINTS:: ' + JSON.stringify(constraints))
// print('value: ' + value)
// print('min1:' + min1)
// print('max1:' + constraints.rotationMod[modType].distanceToMax)
// print('min2: ' + constraints.rotationMod[modType].min)
// print('max2: ' + constraints.rotationMod[modType].max)
// print('FINAL ANGLE::' + finalAngle)
if (finalAngle < constraints.rotationMod[modType].min) {
finalAngle = constraints.rotationMod[modType].min;
}
if (finalAngle > constraints.rotationMod[modType].max) {
finalAngle = constraints.rotationMod[modType].max;
}
if (modType === 'pitch') {
finalRotation.x = finalAngle
}
if (modType === 'yaw') {
finalRotation.y = finalAngle
}
if (modType === 'roll') {
finalRotation.z = finalAngle
}
});
Entities.callEntityMethod(this.grabbedEntity, constraints.callback, [JSON.stringify(finalRotation)]);
}
this.callEntityMethodOnGrabbed("continueNearTrigger");
};
@ -1624,6 +1733,7 @@ function MyController(hand) {
// sometimes we want things to stay right where they are when we let go.
var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, {});
var releaseVelocityData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
print('RELEASE DATA::' + JSON.stringify(releaseVelocityData))
if (releaseVelocityData.disableReleaseVelocity === true ||
// this next line allowed both:
// (1) far-grab, pull to self, near grab, then throw
@ -1638,6 +1748,7 @@ function MyController(hand) {
this.actionID = null;
this.setState(STATE_OFF);
print('HAS VELOCITY AT RELEASE?? ' + noVelocity)
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
action: 'release',
grabbedEntity: this.grabbedEntity,
@ -1705,6 +1816,7 @@ function MyController(hand) {
// when using string values
"collidesWith": COLLIDES_WITH_WHILE_GRABBED
};
print('ACTIVATING ENTITY')
Entities.editEntity(entityID, whileHeldProperties);
} else if (data["refCount"] > 1) {
if (data["heartBeat"] === undefined ||
@ -1722,9 +1834,12 @@ function MyController(hand) {
// people are holding something and one of them will be able (if the other releases at the right time) to
// bootstrap themselves with the held object. This happens because the meaning of "otherAvatar" in
// the collision mask hinges on who the physics simulation owner is.
Entities.editEntity(entityID, {"collidesWith": COLLIDES_WITH_WHILE_MULTI_GRABBED});
Entities.editEntity(entityID, {
"collidesWith": COLLIDES_WITH_WHILE_MULTI_GRABBED
});
}
}
print('ACTIVATED ENTITY!!!')
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
return data;
};
@ -1736,7 +1851,9 @@ function MyController(hand) {
var children = Entities.getChildrenIDsOfJoint(MyAvatar.sessionUUID, handJointIndex);
children.forEach(function(childID) {
print("disconnecting stray child of hand: (" + _this.hand + ") " + childID);
Entities.editEntity(childID, {parentID: NULL_UUID});
Entities.editEntity(childID, {
parentID: NULL_UUID
});
});
}
@ -1764,11 +1881,23 @@ function MyController(hand) {
data["dynamic"] &&
data["parentID"] == NULL_UUID &&
!data["collisionless"]) {
deactiveProps["velocity"] = {x: 0.0, y: 0.1, z: 0.0};
deactiveProps["velocity"] = {
x: 0.0,
y: 0.1,
z: 0.0
};
}
if (noVelocity) {
deactiveProps["velocity"] = {x: 0.0, y: 0.0, z: 0.0};
deactiveProps["angularVelocity"] = {x: 0.0, y: 0.0, z: 0.0};
deactiveProps["velocity"] = {
x: 0.0,
y: 0.0,
z: 0.0
};
deactiveProps["angularVelocity"] = {
x: 0.0,
y: 0.0,
z: 0.0
};
}
Entities.editEntity(entityID, deactiveProps);
@ -1778,13 +1907,31 @@ function MyController(hand) {
var deactiveProps = {
parentID: this.previousParentID,
parentJointIndex: this.previousParentJointIndex,
velocity: {x: 0.0, y: 0.0, z: 0.0},
angularVelocity: {x: 0.0, y: 0.0, z: 0.0}
velocity: {
x: 0.0,
y: 0.0,
z: 0.0
},
angularVelocity: {
x: 0.0,
y: 0.0,
z: 0.0
}
};
Entities.editEntity(entityID, deactiveProps);
} else if (noVelocity) {
Entities.editEntity(entityID, {velocity: {x: 0.0, y: 0.0, z: 0.0},
angularVelocity: {x: 0.0, y: 0.0, z: 0.0}});
Entities.editEntity(entityID, {
velocity: {
x: 0.0,
y: 0.0,
z: 0.0
},
angularVelocity: {
x: 0.0,
y: 0.0,
z: 0.0
}
});
}
} else {
data = null;
@ -1916,3 +2063,8 @@ function cleanup() {
}
Script.scriptEnding.connect(cleanup);
Script.update.connect(update);
function scale(value, min1, max1, min2, max2) {
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
}

View file

@ -0,0 +1,144 @@
var SHOULD_CLEANUP = true;
var WHITE = {
red: 255,
green: 255,
blue: 255
};
var RED = {
red: 255,
green: 0,
blue: 0
};
var GREEN = {
red: 0,
green: 255,
blue: 0
};
var BLUE = {
red: 0,
green: 0,
blue: 255
};
var center = Vec3.sum(Vec3.sum(MyAvatar.position, {
x: 0,
y: 0.5,
z: 0
}), Vec3.multiply(1, Quat.getFront(Camera.getOrientation())));
var BASE_DIMENSIONS = {
x: 0.5,
y: 0.5,
z: 0.5
};
var BASE_POSITION = center;
var LID_DIMENSIONS = {
x: BASE_DIMENSIONS.x,
y: BASE_DIMENSIONS.y / 8,
z: BASE_DIMENSIONS.z
};
var LID_OFFSET = {
x: 0,
y: BASE_DIMENSIONS.y / 2 + (LID_DIMENSIONS.y / 2),
z: 0.25
};
var LID_REGISTRATION_POINT = {
x: 0.5,
y: 0.5,
z: 1
}
var LID_SCRIPT_URL = Script.resolvePath('lid.js?'+Math.random());
var base, lid;
function createBase() {
var baseProperties = {
name: 'hifi-home-music-box-base',
type: 'Box',
color: WHITE,
position: BASE_POSITION,
dimensions: BASE_DIMENSIONS
}
base = Entities.addEntity(baseProperties);
};
function createLid() {
var lidPosition = Vec3.sum(BASE_POSITION, LID_OFFSET);
print('LID DIMENSIONS:' + JSON.stringify(lidPosition))
var lidProperties = {
name: 'hifi-home-music-box-lid',
type: 'Box',
color: BLUE,
dimensions: LID_DIMENSIONS,
position: lidPosition,
registrationPoint: LID_REGISTRATION_POINT,
dynamic: false,
script:LID_SCRIPT_URL,
collidesWith: 'myAvatar,otherAvatar',
userData: JSON.stringify({
grabConstraintsKey: {
callback:'rotateLid',
positionLocked: true,
rotationLocked: false,
positionMod: false,
rotationMod: {
pitch: {
min: 0,
max: 75,
startingAxis:'y',
startingPoint:lidPosition.y,
distanceToMax:lidPosition.y+0.35,
},
yaw: false,
roll: false
}
},
grabbableKey: {
wantsTrigger: true,
disableReleaseVelocity: true,
disableMoveWithHead: true,
disableFarGrab:true,
disableEquip:true
}
})
}
lid = Entities.addEntity(lidProperties);
};
var theta = 0;
var min = 0;
var max = 60;
var direction = "up";
function animateLid() {
theata += 1
}
if (SHOULD_CLEANUP === true) {
Script.scriptEnding.connect(cleanup);
}
function cleanup() {
Entities.deleteEntity(base);
Entities.deleteEntity(lid);
}
createBase();
createLid();

View file

@ -0,0 +1,132 @@
(function() {
var _this;
function Lid() {
_this = this;
return this;
}
var MUSIC_URL = 'https://hifi-content.s3.amazonaws.com/DomainContent/Home/Sounds/aquarium_small.L.wav';
var SHUT_SOUND_URL = 'http://hifi-content.s3.amazonaws.com/DomainContent/Home/Sounds/book_fall.L.wav';
var OPEN_SOUND_URL = 'http://public.highfidelity.io/sounds/Switches%20and%20sliders/lamp_switch_2.wav'
Lid.prototype = {
preload: function(entityID) {
print('PRELOAD LID')
_this.entityID = entityID;
_this.music = SoundCache.getSound(MUSIC_URL);
_this.shutSound = SoundCache.getSound(SHUT_SOUND_URL);
_this.openSound = SoundCache.getSound(OPEN_SOUND_URL);
_this.musicIsPlaying = false;
_this.shut = true;
_this.shutSoundInjector = {
isPlaying: false
};
_this.musicInjector = null;
_this.openSoundInjector = {
isPlaying: false
}
},
continueNearTrigger: function() {
var properties = Entities.getEntityProperties(this.entityID);
},
playMusic: function() {
if (this.musicIsPlaying !== true) {
var properties = Entities.getEntityProperties(this.entityID);
var audioOptions = {
position: properties.position,
volume: 0.75,
loop: true
}
this.musicInjector = Audio.playSound(this.music, audioOptions);
this.musicIsPlaying = true;
}
},
stopMusic: function() {
this.musicInjector.stop();
this.musicIsPlaying = false;
},
playOpenSound: function() {
if (this.openSoundInjector.isPlaying !== true) {
var properties = Entities.getEntityProperties(this.entityID);
var audioOptions = {
position: properties.position,
volume: 1,
loop: false
}
this.openSoundInjector = Audio.playSound(this.openSound, audioOptions);
}
},
playShutSound: function() {
if (this.shutSoundInjector.isPlaying !== true) {
var properties = Entities.getEntityProperties(this.entityID);
var audioOptions = {
position: properties.position,
volume: 1,
loop: false
}
this.shutSoundInjector = Audio.playSound(this.shutSound, audioOptions);
}
},
rotateLid: function(myID, paramsArray) {
var finalRotation;
paramsArray.forEach(function(param) {
var p;
// print('param is:' + param)
try {
p = JSON.parse(param);
finalRotation = p;
} catch (err) {
// print('not a json param')
return;
p = param;
}
});
if (finalRotation.x > 20 && this.musicIsPlaying === false) {
this.playMusic();
print('play music!!')
}
if (finalRotation.x <= 20 && this.musicIsPlaying === true) {
print('stop music!!')
this.stopMusic();
}
if (finalRotation.x > 0 && this.shut === true) {
print('play open sound!!')
this.shut = false;
this.playOpenSound();
} else if (finalRotation.x <= 0 && this.shut === false) {
print('play shut sound!!')
this.shut = true;
this.playShutSound();
}
Entities.editEntity(this.entityID, {
rotation: Quat.fromPitchYawRollDegrees(finalRotation.x, finalRotation.y, finalRotation.z)
})
},
unload: function() {
this.musicInjector.stop();
},
}
return new Lid();
})