749 lines
32 KiB
JavaScript
749 lines
32 KiB
JavaScript
//
|
|
// Created by Triplelexx on 16/05/26
|
|
// Copyright 2016 High Fidelity, Inc.
|
|
//
|
|
// An entity that can be sat apon
|
|
//
|
|
// Sitting animations adapted by Triplelexx from version obtained from Mixamo
|
|
// Links provided to copies of original animations created by High Fidelity, Inc
|
|
// This is due to issues requiring use of overrideRoleAnimation to chain animations and not knowing a better way
|
|
// to reference them cross-platform.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
|
|
(function() {
|
|
var _this;
|
|
const SIT_MAPPING_NAME = "chair.sit.override";
|
|
const HAND_MAPPING_NAME = "chair.hand.override";
|
|
const IK_TYPES = {
|
|
RotationAndPosition: 0,
|
|
RotationOnly: 1,
|
|
HmdHead: 2,
|
|
HipsRelativeRotationAndPosition: 3,
|
|
Off: 4
|
|
}; //http://hifi-content.s3.amazonaws.com/Examples%20Content/production/sitsystem/idle.fbx
|
|
const STAND_IMAGE_URL = "http://hifi-content.s3.amazonaws.com/Examples%20Content/production/sitsystem/stand.png";
|
|
const IDLE_ANIM = {
|
|
url: "http://hifi-content.s3.amazonaws.com/Examples%20Content/production/sitsystem/idle.fbx",
|
|
playbackRate: 30.0,
|
|
loopFlag: true,
|
|
startFrame: 1.0,
|
|
endFrame: 300.0
|
|
};
|
|
const IDLE_TALK_ANIM = {
|
|
url: "http://hifi-content.s3.amazonaws.com/Examples%20Content/production/sitsystem/talk.fbx",
|
|
playbackRate: 30.0,
|
|
loopFlag: true,
|
|
startFrame: 1.0,
|
|
endFrame: 800.0
|
|
};
|
|
const SIT_DOWN_ANIM = {
|
|
url: "http://hifi-content.s3.amazonaws.com/Examples%20Content/production/sitsystem/sit_down.fbx",
|
|
playbackRate: 30.0,
|
|
loopFlag: false,
|
|
startFrame: 1.0,
|
|
endFrame: 120.0
|
|
};
|
|
const SIT_IDLE_ANIM = {
|
|
url: "http://hifi-content.s3.amazonaws.com/Examples%20Content/production/sitsystem/sit_idle_inplace.fbx",
|
|
playbackRate: 30.0,
|
|
loopFlag: true,
|
|
startFrame: 1.0,
|
|
endFrame: 80.0
|
|
};
|
|
const SIT_IDLE_TALK_ANIM = {
|
|
url: "http://hifi-content.s3.amazonaws.com/Examples%20Content/production/sitsystem/sit_idle_talk_inplace.fbx",
|
|
playbackRate: 30.0,
|
|
loopFlag: true,
|
|
startFrame: 1.0,
|
|
endFrame: 80.0
|
|
};
|
|
const HALF = 0.5;
|
|
const HALF_CIRCLE = 180.0;
|
|
const SMALL_DIST = 0.1;
|
|
const VERY_SMALL_DIST = 0.01;
|
|
const SIT_INTERVAL = 5000; // in milliseconds
|
|
const INTERACTION_CHECK_INTERVAL = 1000; // in milliseconds
|
|
const SCALING_COMPLETE_INTERVAL = 1000; // in milliseconds
|
|
const NULL_UUID = "{00000000-0000-0000-0000-000000000000}";
|
|
const MIN_USERANGLE = 0.9;
|
|
const MAX_USERDIST = 2.5;
|
|
const SCALE_SPEED_FACTOR = 0.001;
|
|
const STANDBUTTON_SIZE = 96;
|
|
const SPHERE_TOUCH_DIST = 0.5;
|
|
const SPHERE_OFFSET_UP = 0.75;
|
|
const SPHERE_OFFSET_RIGHT = 0.75;
|
|
const SPHERE_ALPHA = 0.75;
|
|
const SPHERE_SIZE = 0.25;
|
|
const SPHERE_COLOR = {
|
|
red: 0,
|
|
green: 200,
|
|
blue: 50
|
|
};
|
|
|
|
ChairEntity = function() {
|
|
_this = this;
|
|
|
|
this.chairProperties = null;
|
|
this.sphereOverlay = null;
|
|
this.standButton = null;
|
|
this.hasButton = false;
|
|
this.wantsToSit = false;
|
|
this.isChangingScale = false;
|
|
this.isAngleCorrectForSitting = false;
|
|
this.sitAnimationHandlerId = null;
|
|
this.orientationMix = 0.0;
|
|
this.allowScaling = true;
|
|
this.allowSwivelling = false;
|
|
this.seatPositionFront = Vec3.ZERO;
|
|
this.seatPositionCenter = Vec3.ZERO;
|
|
this.sphereOverlayPosition = Vec3.ZERO;
|
|
this.originalDimensions = Vec3.ZERO;
|
|
this.manualSitTarget = Vec3.ZERO;
|
|
this.currentUser = NULL_UUID;
|
|
this.sitDownAnimation = AnimationCache.prefetch(SIT_DOWN_ANIM.url);
|
|
this.sitIdleAnimation = AnimationCache.prefetch(SIT_IDLE_ANIM.url);
|
|
this.sitIdleTalkAnimation = AnimationCache.prefetch(SIT_IDLE_TALK_ANIM.url);
|
|
this.idleAnimation = AnimationCache.prefetch(IDLE_ANIM.url);
|
|
this.talkAnimation = AnimationCache.prefetch(IDLE_TALK_ANIM.url);
|
|
this.sitEventMapping = null;
|
|
this.handEventMapping = null;
|
|
};
|
|
|
|
ChairEntity.prototype = {
|
|
|
|
getUserData: function() {
|
|
this.chairProperties = Entities.getEntityProperties(this.entityId, ["position", "rotation",
|
|
"dimensions", "userData"]);
|
|
try {
|
|
var userData = JSON.parse(this.chairProperties.userData);
|
|
if(userData.allowScaling == true || userData.allowScaling == false) {
|
|
this.allowScaling = userData.allowScaling;
|
|
}
|
|
if(userData.allowSwivelling == true || userData.allowSwivelling == false) {
|
|
this.allowSwivelling = userData.allowSwivelling;
|
|
}
|
|
if(userData.manualSitTarget.x != 0.0 || userData.manualSitTarget.y != 0.0 || userData.manualSitTarget.z != 0.0) {
|
|
this.manualSitTarget = userData.manualSitTarget;
|
|
}
|
|
} catch(errorState) {
|
|
print("userData error: " + errorState);
|
|
}
|
|
},
|
|
|
|
getChairSurface: function() {
|
|
if(this.manualSitTarget.x != 0.0 && this.manualSitTarget.y != 0.0 && this.manualSitTarget.z != 0.0) {
|
|
this.seatPositionCenter = this.manualSitTarget;
|
|
return;
|
|
}
|
|
const DIST_INFRONT = 1.5;
|
|
const DIST_ABOVE = 4.0;
|
|
var chairPosition = this.chairProperties.position;
|
|
|
|
// raycast down from above the chair
|
|
chairPosition.y += DIST_ABOVE;
|
|
var intersectionDown = Entities.findRayIntersection({direction: Vec3.UNIT_NEG_Y,
|
|
origin: chairPosition}, true);
|
|
|
|
if(intersectionDown.intersects) {
|
|
if(intersectionDown.entityID === this.entityId) {
|
|
// we found the highest point in middle
|
|
this.seatPositionCenter = chairPosition;
|
|
// set y slightly lower so next ray to find the front will hit
|
|
chairPosition.y = intersectionDown.intersection.y - VERY_SMALL_DIST;
|
|
// we cast a ray in front of the chair going backward to find the front of the geometry
|
|
var chairFront = Quat.multiply(this.chairProperties.rotation,
|
|
Quat.fromPitchYawRollDegrees(0.0, HALF_CIRCLE, 0.0));
|
|
|
|
chairPosition = Vec3.sum(chairPosition, Vec3.multiply(Quat.getFront(chairFront), DIST_INFRONT));
|
|
var intersectionFront = Entities.findRayIntersection({direction: Quat.getFront(this.chairProperties.rotation),
|
|
origin: chairPosition}, true);
|
|
|
|
if(intersectionFront.intersects) {
|
|
if(intersectionFront.entityID === this.entityId) {
|
|
this.seatPositionFront = Vec3.sum(intersectionFront.intersection, Vec3.multiply(Quat.getFront(chairFront), SMALL_DIST));
|
|
}
|
|
} else {
|
|
this.seatPositionFront = this.chairProperties.position;
|
|
}
|
|
}
|
|
} else {
|
|
this.seatPositionFront = this.chairProperties.position;
|
|
}
|
|
},
|
|
|
|
scaleChair: function() {
|
|
if(!this.allowScaling) {
|
|
return;
|
|
}
|
|
|
|
var currentDimensions = this.chairProperties.dimensions;
|
|
this.originalDimensions = this.chairProperties.dimensions;
|
|
var difference = Vec3.ZERO;
|
|
if(MyAvatar.scale > 1.0) {
|
|
difference.x = (currentDimensions.x * MyAvatar.scale) - currentDimensions.x;
|
|
difference.y = (currentDimensions.y * MyAvatar.scale) - currentDimensions.y;
|
|
difference.z = (currentDimensions.z * MyAvatar.scale) - currentDimensions.z;
|
|
|
|
if(HMD.active){
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x + difference.x,
|
|
y: currentDimensions.y + difference.y,
|
|
z: currentDimensions.z + difference.z
|
|
}
|
|
});
|
|
} else {
|
|
for(var i = 0.0; i < 1.0; i += SCALE_SPEED_FACTOR) {
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x + (difference.x * i),
|
|
y: currentDimensions.y + (difference.y * i),
|
|
z: currentDimensions.z + (difference.z * i)
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
difference.x = currentDimensions.x - (currentDimensions.x * MyAvatar.scale);
|
|
difference.y = currentDimensions.y - (currentDimensions.y * MyAvatar.scale);
|
|
difference.z = currentDimensions.z - (currentDimensions.z * MyAvatar.scale);
|
|
if(HMD.active){
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x - difference.x,
|
|
y: currentDimensions.y - difference.y,
|
|
z: currentDimensions.z - difference.z
|
|
}
|
|
});
|
|
} else {
|
|
for(var i = 0.0; i < 1.0; i += SCALE_SPEED_FACTOR) {
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x - (difference.x * i),
|
|
y: currentDimensions.y - (difference.y * i),
|
|
z: currentDimensions.z - (difference.z * i)
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
resetChairScale: function() {
|
|
if(!this.allowScaling) {
|
|
return;
|
|
}
|
|
// check again for valid data
|
|
this.getUserData();
|
|
var currentDimensions = this.chairProperties.dimensions;
|
|
var difference = Vec3.ZERO;
|
|
if(currentDimensions.y > this.originalDimensions.y) {
|
|
difference.x = currentDimensions.x - this.originalDimensions.x;
|
|
difference.y = currentDimensions.y - this.originalDimensions.y;
|
|
difference.z = currentDimensions.z - this.originalDimensions.z;
|
|
if(HMD.active) {
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x - difference.x,
|
|
y: currentDimensions.y - difference.y,
|
|
z: currentDimensions.z - difference.z
|
|
}
|
|
});
|
|
} else {
|
|
for(var i = 0.0; i < 1.0; i += SCALE_SPEED_FACTOR) {
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x - (difference.x * i),
|
|
y: currentDimensions.y - (difference.y * i),
|
|
z: currentDimensions.z - (difference.z * i)
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
difference.x = this.originalDimensions.x - currentDimensions.x;
|
|
difference.y = this.originalDimensions.y - currentDimensions.y;
|
|
difference.z = this.originalDimensions.z - currentDimensions.z;
|
|
if(HMD.active) {
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x + difference.x,
|
|
y: currentDimensions.y + difference.y,
|
|
z: currentDimensions.z + difference.z
|
|
}
|
|
});
|
|
} else {
|
|
for(var i = 0.0; i < 1.0; i += SCALE_SPEED_FACTOR) {
|
|
Entities.editEntity(this.entityId, {
|
|
dimensions: {
|
|
x: currentDimensions.x + (difference.x * i),
|
|
y: currentDimensions.y + (difference.y * i),
|
|
z: currentDimensions.z + (difference.z * i)
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
moveAvatarToChairCenter: function() {
|
|
//disable collisions
|
|
MyAvatar.characterControllerEnabled = false;
|
|
const SEAT_OFFSET = 0.2;
|
|
if(this.allowScaling) {
|
|
this.seatPositionCenter.y += SEAT_OFFSET * MyAvatar.scale;
|
|
} else {
|
|
this.seatPositionCenter.y += SEAT_OFFSET;
|
|
}
|
|
var frontVec = Quat.getFront(this.chairProperties.rotation);
|
|
this.seatPositionCenter = Vec3.sum(this.seatPositionCenter, Vec3.multiply(-SMALL_DIST, frontVec));
|
|
MyAvatar.position = this.seatPositionCenter;
|
|
},
|
|
|
|
moveAvatarToChairFront: function() {
|
|
//enable collisions
|
|
MyAvatar.characterControllerEnabled = true;
|
|
MyAvatar.position = this.seatPositionFront;
|
|
},
|
|
|
|
maybeSit: function() {
|
|
const MAX_ROT = 5.0;
|
|
// block unacceptable attempts including the chair being tipped
|
|
if(this.wantsToSit || this.isChangingScale || this.currentUser !== NULL_UUID ||
|
|
this.chairProperties.rotation.x > MAX_ROT || this.chairProperties.rotation.x < -MAX_ROT ||
|
|
this.chairProperties.rotation.z > MAX_ROT || this.chairProperties.rotation.z < -MAX_ROT) {
|
|
return;
|
|
}
|
|
|
|
this.scaleChair();
|
|
this.isChangingScale = true;
|
|
|
|
// sit instantly with HMD
|
|
if(HMD.active) {
|
|
//get the post-scaled chair surface
|
|
this.getChairSurface();
|
|
this.wantsToSit = true;
|
|
this.isAngleCorrectForSitting = false;
|
|
this.orientationMix = 0.0;
|
|
this.isChangingScale = false;
|
|
} else {
|
|
// allow time for scaling then proceed
|
|
Script.setTimeout(function() {
|
|
//get the post-scaled chair surface
|
|
_this.getChairSurface();
|
|
_this.wantsToSit = true;
|
|
_this.isAngleCorrectForSitting = false;
|
|
_this.orientationMix = 0.0;
|
|
_this.isChangingScale = false;
|
|
}, SCALING_COMPLETE_INTERVAL);
|
|
}
|
|
Entities.clickReleaseOnEntity.disconnect(this.clickReleaseOnEntity);
|
|
},
|
|
|
|
sitDown: function() {
|
|
MyAvatar.overrideRoleAnimation("idleStand", SIT_DOWN_ANIM.url, SIT_DOWN_ANIM.playbackRate,
|
|
SIT_DOWN_ANIM.loopFlag, SIT_DOWN_ANIM.startFrame, SIT_DOWN_ANIM.endFrame);
|
|
|
|
function animateSit() {
|
|
return {
|
|
leftFootType: IK_TYPES.Off,
|
|
rightFootType: IK_TYPES.Off,
|
|
rightHandType: IK_TYPES.Off,
|
|
leftHandType: IK_TYPES.Off,
|
|
neckType: IK_TYPES.Off,
|
|
headType: IK_TYPES.Off,
|
|
isTalking: false,
|
|
isFlying: false,
|
|
isNotMoving: true,
|
|
ikOverlayAlpha: 0.0,
|
|
isMovingForward: false,
|
|
isMovingBackward: false,
|
|
isMovingLeft: false,
|
|
isMovingRight: false,
|
|
isNotTurning: true,
|
|
isTurningLeft: false,
|
|
isTurningRight: false,
|
|
inAirAlpha: 0.0
|
|
};
|
|
}
|
|
sitAnimationHandlerId = MyAvatar.addAnimationStateHandler(animateSit,
|
|
[
|
|
"leftFootType",
|
|
"rightFootType",
|
|
"rightHandType",
|
|
"leftHandType",
|
|
"neckType",
|
|
"headType",
|
|
"isTalking",
|
|
"isFlying",
|
|
"isNotMoving",
|
|
"ikOverlayAlpha",
|
|
"isMovingForward",
|
|
"isMovingBackward",
|
|
"isMovingLeft",
|
|
"isMovingRight",
|
|
"isNotTurning",
|
|
"isTurningLeft",
|
|
"isTurningRight",
|
|
"inAirAlpha"
|
|
]
|
|
);
|
|
|
|
this.setSitControllerMapping();
|
|
MyAvatar.setParentID(this.entityId);
|
|
|
|
Script.setTimeout(function() {
|
|
_this.sitFinished();
|
|
}, SIT_INTERVAL);
|
|
},
|
|
|
|
sitFinished: function() {
|
|
if(HMD.active) {
|
|
this.moveSphereOverlay();
|
|
MyAvatar.hmdLeanRecenterEnabled = false;
|
|
} else {
|
|
this.createStandButton();
|
|
MyAvatar.removeAnimationStateHandler(sitAnimationHandlerId);
|
|
}
|
|
function animateSit() {
|
|
return {
|
|
leftFootType: IK_TYPES.Off,
|
|
rightFootType: IK_TYPES.Off,
|
|
rightHandType: IK_TYPES.HipsRelativeRotationAndPosition,
|
|
leftHandType: IK_TYPES.HipsRelativeRotationAndPosition,
|
|
neckType: IK_TYPES.HipsRelativeRotationAndPosition,
|
|
headType: IK_TYPES.HipsRelativeRotationAndPosition,
|
|
isFlying: false,
|
|
isNotMoving: true,
|
|
ikOverlayAlpha: 1.0,
|
|
isMovingForward: false,
|
|
isMovingBackward: false,
|
|
isMovingLeft: false,
|
|
isMovingRight: false,
|
|
isNotTurning: true,
|
|
isTurningLeft: false,
|
|
isTurningRight: false,
|
|
inAirAlpha: 0.0
|
|
};
|
|
}
|
|
sitAnimationHandlerId = MyAvatar.addAnimationStateHandler(animateSit,
|
|
[
|
|
"leftFootType",
|
|
"rightFootType",
|
|
"rightHandType",
|
|
"leftHandType",
|
|
"neckType",
|
|
"headType",
|
|
"isFlying",
|
|
"isNotMoving",
|
|
"ikOverlayAlpha",
|
|
"isMovingForward",
|
|
"isMovingBackward",
|
|
"isMovingLeft",
|
|
"isMovingRight",
|
|
"isNotTurning",
|
|
"isTurningLeft",
|
|
"isTurningRight",
|
|
"inAirAlpha"
|
|
]
|
|
);
|
|
|
|
MyAvatar.overrideRoleAnimation("idleStand", SIT_IDLE_ANIM.url, SIT_IDLE_ANIM.playbackRate,
|
|
SIT_IDLE_ANIM.loopFlag, SIT_IDLE_ANIM.startFrame, SIT_IDLE_ANIM.endFrame);
|
|
|
|
MyAvatar.overrideRoleAnimation("idleTalk", SIT_IDLE_TALK_ANIM.url, SIT_IDLE_TALK_ANIM.playbackRate,
|
|
SIT_IDLE_TALK_ANIM.loopFlag, SIT_IDLE_TALK_ANIM.startFrame,
|
|
SIT_IDLE_TALK_ANIM.endFrame);
|
|
|
|
this.currentUser = MyAvatar.sessionUUID;
|
|
// we move the avatar itself rather than using motion from the animation
|
|
this.moveAvatarToChairCenter();
|
|
},
|
|
|
|
standUp: function() {
|
|
print("STANDING");
|
|
MyAvatar.removeAnimationStateHandler(sitAnimationHandlerId);
|
|
MyAvatar.overrideRoleAnimation("idleStand", IDLE_ANIM.url, IDLE_ANIM.playbackRate, IDLE_ANIM.loopFlag,
|
|
IDLE_ANIM.startFrame, IDLE_ANIM.endFrame);
|
|
|
|
MyAvatar.overrideRoleAnimation("idleTalk", IDLE_TALK_ANIM.url, IDLE_TALK_ANIM.playbackRate,
|
|
IDLE_TALK_ANIM.loopFlag, IDLE_TALK_ANIM.startFrame, IDLE_TALK_ANIM.endFrame);
|
|
|
|
if(HMD.active) {
|
|
MyAvatar.hmdLeanRecenterEnabled = true;
|
|
this.moveSphereOverlayBack();
|
|
} else {
|
|
this.removeStandButton();
|
|
}
|
|
MyAvatar.setParentID(NULL_UUID);
|
|
this.currentUser = NULL_UUID;
|
|
this.moveAvatarToChairFront();
|
|
this.resetChairScale();
|
|
this.removeSitControllerMapping();
|
|
Entities.clickReleaseOnEntity.connect(this.clickReleaseOnEntity);
|
|
},
|
|
|
|
createSphereOverlay: function() {
|
|
// check again for valid data
|
|
this.getUserData();
|
|
this.setHandControllerMapping();
|
|
this.sphereOverlayPosition = this.chairProperties.position;
|
|
this.sphereOverlayPosition.y += SPHERE_OFFSET_UP;
|
|
|
|
this.sphereOverlay = Overlays.addOverlay("sphere", {
|
|
size: SPHERE_SIZE,
|
|
color: SPHERE_COLOR,
|
|
position: this.sphereOverlayPosition,
|
|
alpha: SPHERE_ALPHA,
|
|
visible: true,
|
|
solid: true,
|
|
drawInFront: false
|
|
});
|
|
},
|
|
|
|
moveSphereOverlay: function() {
|
|
var rightVec = Quat.getRight(this.chairProperties.rotation);
|
|
this.sphereOverlayPosition = Vec3.sum(this.sphereOverlayPosition, Vec3.multiply(-SPHERE_OFFSET_RIGHT, rightVec));
|
|
Overlays.editOverlay(this.sphereOverlay, {
|
|
position: this.sphereOverlayPosition
|
|
});
|
|
},
|
|
|
|
moveSphereOverlayBack: function() {
|
|
var rightVec = Quat.getRight(this.chairProperties.rotation);
|
|
this.sphereOverlayPosition = Vec3.sum(this.sphereOverlayPosition, Vec3.multiply(SPHERE_OFFSET_RIGHT, rightVec));
|
|
Overlays.editOverlay(this.sphereOverlay, {
|
|
position: this.sphereOverlayPosition
|
|
});
|
|
},
|
|
|
|
removeSphereOverlay: function() {
|
|
Overlays.deleteOverlay(this.sphereOverlay);
|
|
this.removeHandControllerMapping();
|
|
this.sphereOverlay = null;
|
|
},
|
|
|
|
createStandButton: function() {
|
|
if (!this.hasButton) {
|
|
var windowDimensions = Controller.getViewportDimensions();
|
|
var buttonWidth = STANDBUTTON_SIZE;
|
|
var buttonHeight = STANDBUTTON_SIZE;
|
|
var buttonPadding = STANDBUTTON_SIZE * HALF;
|
|
var buttonPositionX = (buttonWidth + buttonPadding) + (windowDimensions.x * HALF) -
|
|
(buttonWidth + buttonPadding);
|
|
|
|
var buttonPositionY = (buttonHeight * HALF) + buttonPadding;
|
|
this.standButton = Overlays.addOverlay("image", {
|
|
x: buttonPositionX,
|
|
y: buttonPositionY,
|
|
width: buttonWidth,
|
|
height: buttonHeight,
|
|
imageURL: STAND_IMAGE_URL,
|
|
visible: true,
|
|
alpha: 1.0
|
|
});
|
|
Controller.mousePressEvent.connect(this.mousePressEvent);
|
|
this.hasButton = true;
|
|
}
|
|
},
|
|
|
|
removeStandButton: function() {
|
|
Overlays.deleteOverlay(this.standButton);
|
|
Controller.mousePressEvent.disconnect(this.mousePressEvent);
|
|
this.hasButton = false;
|
|
},
|
|
|
|
setSitControllerMapping: function () {
|
|
this.sitEventMapping = Controller.newMapping(SIT_MAPPING_NAME);
|
|
|
|
// I am trying to disable inputs to keep the avatar in the chair, is there a neater way to do this?
|
|
// keyboard seems to map directly to actions
|
|
if(!this.allowSwivelling) {
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.MouseMoveLeft).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.MouseMoveRight).to(function () {
|
|
});
|
|
}
|
|
this.sitEventMapping.from(Controller.Standard.LX).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Standard.LY).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Standard.RX).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.W).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.S).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.A).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.D).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.Left).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.Right).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.Up).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.Down).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.E).to(function () {
|
|
});
|
|
this.sitEventMapping.from(Controller.Hardware.Keyboard.C).to(function () {
|
|
});
|
|
|
|
Controller.enableMapping(SIT_MAPPING_NAME, true);
|
|
},
|
|
|
|
removeSitControllerMapping: function () {
|
|
Controller.disableMapping(SIT_MAPPING_NAME);
|
|
},
|
|
|
|
setHandControllerMapping: function () {
|
|
this.handEventMapping = Controller.newMapping(HAND_MAPPING_NAME);
|
|
|
|
this.handEventMapping.from(Controller.Standard.RT).peek().to(function () {
|
|
if(_this.currentUser === MyAvatar.sessionUUID && _this.isTouchingSphereOverlay()) {
|
|
_this.standUp();
|
|
} else if(_this.currentUser === NULL_UUID && _this.isTouchingSphereOverlay()) {
|
|
_this.maybeSit();
|
|
}
|
|
});
|
|
this.handEventMapping.from(Controller.Standard.LT).peek().to(function () {
|
|
if(_this.currentUser === MyAvatar.sessionUUID && _this.isTouchingSphereOverlay()) {
|
|
_this.standUp();
|
|
} else if(_this.currentUser === NULL_UUID && _this.isTouchingSphereOverlay()) {
|
|
_this.maybeSit();
|
|
}
|
|
});
|
|
|
|
Controller.enableMapping(HAND_MAPPING_NAME, true);
|
|
},
|
|
|
|
removeHandControllerMapping: function () {
|
|
Controller.disableMapping(HAND_MAPPING_NAME);
|
|
},
|
|
|
|
isTouchingSphereOverlay: function () {
|
|
var leftHandPosition = MyAvatar.getLeftPalmPosition();
|
|
var rightHandPosition = MyAvatar.getRightPalmPosition();
|
|
|
|
var sphereDistL = Vec3.distance(leftHandPosition, this.sphereOverlayPosition);
|
|
var sphereDistR = Vec3.distance(rightHandPosition, this.sphereOverlayPosition);
|
|
return (sphereDistL < SPHERE_TOUCH_DIST || sphereDistR < SPHERE_TOUCH_DIST);
|
|
},
|
|
|
|
isCloseToChair: function() {
|
|
// check again for valid data
|
|
this.getUserData();
|
|
var distanceFromChair = Vec3.distance(MyAvatar.position, this.chairProperties.position);
|
|
|
|
return (distanceFromChair < MAX_USERDIST) ? true : false;
|
|
},
|
|
|
|
isFacingChair: function() {
|
|
// check again for valid data
|
|
this.getUserData();
|
|
var userAngle = Quat.dot(Quat.getFront(MyAvatar.orientation),
|
|
Quat.getFront(this.chairProperties.rotation));
|
|
|
|
return (userAngle > MIN_USERANGLE) ? true : false;
|
|
},
|
|
|
|
maybeToggleHMDButton: function() {
|
|
if(!HMD.active) {
|
|
if(this.sphereOverlay !== null) {
|
|
this.removeSphereOverlay();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(this.isCloseToChair() && this.sphereOverlay === null) {
|
|
this.createSphereOverlay();
|
|
} else if (!this.isCloseToChair() && this.sphereOverlay !== null) {
|
|
this.removeSphereOverlay();
|
|
}
|
|
|
|
Script.setTimeout(function() {
|
|
_this.maybeToggleHMDButton();
|
|
}, INTERACTION_CHECK_INTERVAL);
|
|
},
|
|
|
|
mousePressEvent: function(event) {
|
|
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
|
if(clickedOverlay === _this.standButton) {
|
|
if(_this.currentUser === MyAvatar.sessionUUID) {
|
|
_this.standUp();
|
|
}
|
|
}
|
|
},
|
|
|
|
clickReleaseOnEntity: function(entityId, clickEvent) {
|
|
if(entityId === this.entityId) {
|
|
if(this.isFacingChair() && this.isCloseToChair()) {
|
|
this.maybeSit();
|
|
}
|
|
}
|
|
},
|
|
|
|
onUpdate: function(deltaTime) {
|
|
if(_this.wantsToSit) {
|
|
// the angle we want to face is rotated 180 deg in y
|
|
var chairFront = Quat.multiply(_this.chairProperties.rotation,
|
|
Quat.fromPitchYawRollDegrees(0.0, HALF_CIRCLE, 0.0));
|
|
|
|
if(!HMD.active) {
|
|
if(!_this.isAngleCorrectForSitting) {
|
|
// rotate smoothly using deltaTime of the loop then sit
|
|
_this.orientationMix += deltaTime;
|
|
var increment = _this.orientationMix * SMALL_DIST;
|
|
if(_this.orientationMix < 1.0) {
|
|
MyAvatar.orientation = Quat.mix(MyAvatar.orientation, chairFront, increment);
|
|
} else {
|
|
MyAvatar.orientation = Quat.mix(MyAvatar.orientation, chairFront, 1.0);
|
|
MyAvatar.position = _this.seatPositionFront;
|
|
_this.isAngleCorrectForSitting = true;
|
|
_this.sitDown();
|
|
_this.wantsToSit = false;
|
|
}
|
|
}
|
|
} else {
|
|
MyAvatar.orientation = Quat.mix(MyAvatar.orientation, chairFront, 1.0);
|
|
MyAvatar.position = _this.seatPositionFront;
|
|
_this.isAngleCorrectForSitting = true;
|
|
// go straight to idle loop
|
|
_this.sitFinished();
|
|
_this.wantsToSit = false;
|
|
}
|
|
}
|
|
},
|
|
|
|
preload: function(entityId) {
|
|
this.entityId = entityId;
|
|
this.getUserData();
|
|
this.getChairSurface();
|
|
this.maybeToggleHMDButton();
|
|
Entities.clickReleaseOnEntity.connect(this.clickReleaseOnEntity);
|
|
Script.update.connect(this.onUpdate);
|
|
},
|
|
|
|
unload: function() {
|
|
print("UNLOADING");
|
|
if(this.currentUser !== NULL_UUID) {
|
|
print("USER IS NOT NULL");
|
|
this.standUp();
|
|
}
|
|
if(this.sphereOverlay !== null) {
|
|
this.removeSphereOverlay();
|
|
}
|
|
if(this.handEventMapping !== null) {
|
|
this.removeHandControllerMapping();
|
|
}
|
|
Script.update.disconnect(this.onUpdate);
|
|
Entities.clickReleaseOnEntity.disconnect(this.clickReleaseOnEntity);
|
|
}
|
|
};
|
|
|
|
return new ChairEntity();
|
|
});
|