Needs a lot of cleanup. Data has been de-duplicated, and where identical copies existed, one of them has been replaced with a symlink. Some files have been excluded, such as binaries, installers and debug dumps. Some of that may still be present.
349 lines
No EOL
9.5 KiB
JavaScript
349 lines
No EOL
9.5 KiB
JavaScript
//
|
|
// seatManager.js
|
|
// examples/entityScripts
|
|
//
|
|
// Created by Eric Levin on April 9, 2015
|
|
// Copyright 2015 High Fidelity, Inc.
|
|
//
|
|
// This is an example of an entity script which handles positioning and seating avatars correctly on a moving vehicle.
|
|
//
|
|
// 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 self = this;
|
|
this.preload = function(entityId) {
|
|
this.entityId = entityId;
|
|
this.buttonImageURL = "https://s3.amazonaws.com/hifi-public/images/tools/sit.svg";
|
|
this.addStandButton();
|
|
this.totalAnimationTime = 0.7;
|
|
this.targetAvatarToChairDistance = 0.5;
|
|
this.properties = Entities.getEntityProperties(this.entityId);
|
|
this.isSittingSettingHandle = "AvatarSittingState";
|
|
Settings.setValue(this.isSittingSettingHandle, false);
|
|
this.startPoseAndTransition = [];
|
|
this.forward = {
|
|
x: 0,
|
|
y: 0,
|
|
z: -1
|
|
};
|
|
this.mySeatIndex = null;
|
|
|
|
this.seatRadius = this.properties.dimensions.x * 0.4;
|
|
this.sittingAreaAngle = Math.PI;
|
|
this.numSeats = 5;
|
|
this.seatHeight = 2.0;
|
|
|
|
this.seatedPose = [{
|
|
joint: "LeftArm",
|
|
rotation: {
|
|
x: 70.0,
|
|
y: 0.0,
|
|
z: 60.0
|
|
}
|
|
}, {
|
|
joint: "LeftForeArm",
|
|
rotation: {
|
|
x: -40.0,
|
|
y: 15.0,
|
|
z: 20.0
|
|
}
|
|
}, {
|
|
joint: "RightArm",
|
|
rotation: {
|
|
x: 70.0,
|
|
y: 0.0,
|
|
z: -60.0
|
|
}
|
|
}, {
|
|
joint: "RightForeArm",
|
|
rotation: {
|
|
x: -40.0,
|
|
y: -15.0,
|
|
z: -20.0
|
|
}
|
|
}, {
|
|
joint: "RightUpLeg",
|
|
rotation: {
|
|
x: 100.0,
|
|
y: 15.0,
|
|
z: 0.0
|
|
}
|
|
}, {
|
|
joint: "RightLeg",
|
|
rotation: {
|
|
x: -120.0,
|
|
y: 80.0,
|
|
z: 0.0
|
|
}
|
|
}, {
|
|
joint: "RightFoot",
|
|
rotation: {
|
|
x: 20,
|
|
y: 5.0,
|
|
z: 0.0
|
|
}
|
|
}, {
|
|
joint: "LeftUpLeg",
|
|
rotation: {
|
|
x: 100.0,
|
|
y: -15.0,
|
|
z: 0.0
|
|
}
|
|
}, {
|
|
joint: "LeftLeg",
|
|
rotation: {
|
|
x: -150.0,
|
|
y: -70.0,
|
|
z: 0.0
|
|
}
|
|
}, {
|
|
joint: "LeftFoot",
|
|
rotation: {
|
|
x: 30,
|
|
y: 15.0,
|
|
z: 0.0
|
|
}
|
|
}];
|
|
|
|
this.storeStartPoseAndTransition();
|
|
this.getUserData();
|
|
}
|
|
|
|
this.initSeats = function() {
|
|
this.userData.seats = [];
|
|
for (var i = 0; i < this.numSeats; i++) {
|
|
this.userData.seats[i] = 0;
|
|
}
|
|
this.updateUserData();
|
|
}
|
|
|
|
//returns the index of first empty seat found in vehicle
|
|
this.assignSeat = function() {
|
|
this.getUserData();
|
|
for (var i = 0; i < this.userData.seats.length; i++) {
|
|
if (this.userData.seats[i] === 0) {
|
|
this.mySeatIndex = i;
|
|
this.userData.seats[this.mySeatIndex] = 1;
|
|
this.updateUserData();
|
|
//Now return so we don't fill up any other seat!
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.getUserData = function() {
|
|
if (this.properties.userData) {
|
|
this.userData = JSON.parse(this.properties.userData);
|
|
} else {
|
|
this.userData = {};
|
|
}
|
|
if (!this.userData.seats) {
|
|
this.initSeats();
|
|
}
|
|
}
|
|
|
|
this.updateUserData = function() {
|
|
Entities.editEntity(this.entityId, {
|
|
userData: JSON.stringify(this.userData)
|
|
});
|
|
}
|
|
|
|
|
|
this.addStandButton = function() {
|
|
this.windowDimensions = Controller.getViewportDimensions();
|
|
this.buttonWidth = 37;
|
|
this.buttonHeight = 46;
|
|
this.buttonPadding = 10;
|
|
|
|
this.buttonPositionX = (this.windowDimensions.x - this.buttonPadding) / 2 - this.buttonWidth;
|
|
this.buttonPositionY = (this.windowDimensions.y - this.buttonHeight) - (this.buttonHeight + this.buttonPadding);
|
|
this.standUpButton = Overlays.addOverlay("image", {
|
|
x: this.buttonPositionX,
|
|
y: this.buttonPositionY,
|
|
width: this.buttonWidth,
|
|
height: this.buttonHeight,
|
|
subImage: {
|
|
x: this.buttonWidth,
|
|
y: this.buttonHeight,
|
|
width: this.buttonWidth,
|
|
height: this.buttonHeight
|
|
},
|
|
imageURL: this.buttonImageURL,
|
|
visible: false,
|
|
alpha: 1.0
|
|
});
|
|
}
|
|
|
|
this.storeStartPoseAndTransition = function() {
|
|
for (var i = 0; i < this.seatedPose.length; i++) {
|
|
var startRotation = Quat.safeEulerAngles(MyAvatar.getJointRotation(this.seatedPose[i].joint));
|
|
var transitionVector = Vec3.subtract(this.seatedPose[i].rotation, startRotation);
|
|
this.startPoseAndTransition.push({
|
|
joint: this.seatedPose[i].joint,
|
|
start: startRotation,
|
|
transition: transitionVector
|
|
});
|
|
}
|
|
}
|
|
|
|
this.clickReleaseOnEntity = function(entityId, mouseEvent) {
|
|
var isStanding = false;
|
|
if(Settings.getValue(this.isSittingSettingHandle, false) === false){
|
|
isStanding = true;
|
|
}
|
|
if (mouseEvent.isLeftButton && isStanding) {
|
|
this.initMoveToSeat();
|
|
}
|
|
}
|
|
|
|
this.initMoveToSeat = function() {
|
|
|
|
this.assignSeat();
|
|
if (this.mySeatIndex !== null) {
|
|
this.seatTheta = -this.mySeatIndex / this.numSeats * this.sittingAreaAngle;
|
|
//first we need to move avatar towards seat
|
|
this.activeUpdate = this.moveToSeat;
|
|
} else {
|
|
print("NO SEAT AVAILABLE AT THIS TIME *************************");
|
|
}
|
|
|
|
}
|
|
|
|
this.update = function(deltaTime) {
|
|
if (self.entityId) {
|
|
self.properties = Entities.getEntityProperties(self.entityId);
|
|
//need to always update seat so when user clicks on it it is in proper world space
|
|
var xPos = self.properties.position.x + (Math.cos(self.seatTheta) * self.seatRadius);
|
|
var zPos = self.properties.position.z + (Math.sin(self.seatTheta) * self.seatRadius);
|
|
self.seatPosition = {
|
|
x: xPos,
|
|
y: self.properties.position.y + self.seatHeight,
|
|
z: zPos
|
|
};
|
|
}
|
|
if (!self.activeUpdate) {
|
|
return;
|
|
}
|
|
self.activeUpdate(deltaTime);
|
|
|
|
}
|
|
|
|
this.moveToSeat = function(deltaTime) {
|
|
self.distance = Vec3.distance(MyAvatar.position, self.seatPosition);
|
|
if (self.distance > self.targetAvatarToChairDistance) {
|
|
self.sanitizedRotation = Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(self.properties.rotation).y, 0);
|
|
MyAvatar.orientation = Quat.mix(MyAvatar.orientation, self.sanitizedRotation, 0.02);
|
|
MyAvatar.position = Vec3.mix(MyAvatar.position, self.seatPosition, 0.05);
|
|
} else {
|
|
//otherwise we made it to chair, now sit down should be out active update function
|
|
this.elapsedTime = 0
|
|
self.activeUpdate = self.sitDown;
|
|
}
|
|
|
|
}
|
|
|
|
this.sitDown = function(deltaTime) {
|
|
self.elapsedTime += deltaTime;
|
|
self.factor = self.elapsedTime / self.totalAnimationTime;
|
|
if (self.elapsedTime < self.totalAnimationTime) {
|
|
self.updateJoints();
|
|
} else {
|
|
//We've sat, now we don't need to update any longer;
|
|
self.activeUpdate = null;
|
|
Settings.setValue(self.isSittingSettingHandle, true);
|
|
Overlays.editOverlay(self.standUpButton, {
|
|
visible: true
|
|
});
|
|
MyAvatar.setModelReferential(self.properties.id);
|
|
}
|
|
}
|
|
|
|
this.standUp = function(deltaTime) {
|
|
|
|
self.elapsedTime += deltaTime;
|
|
self.factor = 1 - self.elapsedTime / self.totalAnimationTime;
|
|
if (self.elapsedTime < self.totalAnimationTime) {
|
|
self.updateJoints();
|
|
} else {
|
|
//We're done with standing animation
|
|
self.activeUpdate = null;
|
|
Settings.setValue(this.isSittingSettingHandle, false);
|
|
//We just finished a standup after deleting the entity the avatar was sitting on
|
|
if (self.disconnectAfterStanding) {
|
|
Overlays.deleteOverlay(this.standUpButton);
|
|
Script.update.disconnect(self.update);
|
|
}
|
|
//make sure we set avatar head yaw back to 0.
|
|
MyAvatar.headYaw = 0
|
|
this.userData.seats[this.mySeatIndex] = 0;
|
|
this.mySeatIndex = null;
|
|
this.updateUserData();
|
|
//make sure we free up this seat
|
|
this.clearAvatarAnimation();
|
|
|
|
}
|
|
}
|
|
|
|
self.updateJoints = function() {
|
|
for (var i = 0; i < self.startPoseAndTransition.length; i++) {
|
|
self.scaledTransition = Vec3.multiply(self.startPoseAndTransition[i].transition, self.factor);
|
|
self.jointRotation = Vec3.sum(self.startPoseAndTransition[i].start, self.scaledTransition);
|
|
MyAvatar.setJointData(self.startPoseAndTransition[i].joint, Quat.fromVec3Degrees(self.jointRotation));
|
|
}
|
|
}
|
|
|
|
this.clearAvatarAnimation = function() {
|
|
MyAvatar.clearReferential();
|
|
for (var i = 0; i < self.seatedPose.length; i++) {
|
|
print('YAAAAAA')
|
|
MyAvatar.clearJointData(this.seatedPose[i].joint);
|
|
}
|
|
Overlays.editOverlay(this.standUpButton, {
|
|
visible: false
|
|
};);
|
|
|
|
}
|
|
|
|
this.unload = function() {
|
|
var isSitting = Settings.getValue(this.isSittingSettingHandle)
|
|
this.entityId = null;
|
|
if (isSitting === "true") {
|
|
// We need to let avatar stand before disconnecting, and then end
|
|
this.initStandUp();
|
|
this.disconnectAfterStanding = true;
|
|
this.activeUpdate = this.standUp
|
|
} else {
|
|
this.clearAvatarAnimation();
|
|
Script.update.disconnect(this.update);
|
|
}
|
|
}
|
|
|
|
this.onClick = function(event) {
|
|
var clickedOverlay = Overlays.getOverlayAtPoint({
|
|
x: event.x,
|
|
y: event.y
|
|
});
|
|
if (clickedOverlay === self.standUpButton) {
|
|
self.initStandUp();
|
|
}
|
|
}
|
|
|
|
this.initStandUp = function() {
|
|
this.elapsedTime = 0;
|
|
this.activeUpdate = this.standUp;
|
|
MyAvatar.clearReferential();
|
|
Overlays.editOverlay(self.standUpButton, {
|
|
visible: false
|
|
};);
|
|
}
|
|
|
|
function map(value, min1, max1, min2, max2) {
|
|
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
|
|
}
|
|
|
|
Controller.mousePressEvent.connect(this.onClick);
|
|
Script.update.connect(this.update);
|
|
|
|
}); |