mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 19:10:49 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into expose-anim-vars
This commit is contained in:
commit
6e4d0043c9
20 changed files with 535 additions and 74 deletions
|
@ -74,8 +74,8 @@ var MSEC_PER_SEC = 1000.0;
|
||||||
|
|
||||||
// these control how long an abandoned pointer line will hang around
|
// these control how long an abandoned pointer line will hang around
|
||||||
var LIFETIME = 10;
|
var LIFETIME = 10;
|
||||||
var ACTION_LIFETIME = 15; // seconds
|
var ACTION_TTL = 15; // seconds
|
||||||
var ACTION_LIFETIME_REFRESH = 5;
|
var ACTION_TTL_REFRESH = 5;
|
||||||
var PICKS_PER_SECOND_PER_HAND = 5;
|
var PICKS_PER_SECOND_PER_HAND = 5;
|
||||||
var MSECS_PER_SEC = 1000.0;
|
var MSECS_PER_SEC = 1000.0;
|
||||||
|
|
||||||
|
@ -422,12 +422,12 @@ function MyController(hand, triggerAction) {
|
||||||
targetRotation: this.currentObjectRotation,
|
targetRotation: this.currentObjectRotation,
|
||||||
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||||
tag: getTag(),
|
tag: getTag(),
|
||||||
lifetime: ACTION_LIFETIME
|
ttl: ACTION_TTL
|
||||||
});
|
});
|
||||||
if (this.actionID === NULL_ACTION_ID) {
|
if (this.actionID === NULL_ACTION_ID) {
|
||||||
this.actionID = null;
|
this.actionID = null;
|
||||||
}
|
}
|
||||||
this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC);
|
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||||
|
|
||||||
if (this.actionID !== null) {
|
if (this.actionID !== null) {
|
||||||
this.setState(STATE_CONTINUE_DISTANCE_HOLDING);
|
this.setState(STATE_CONTINUE_DISTANCE_HOLDING);
|
||||||
|
@ -524,9 +524,9 @@ function MyController(hand, triggerAction) {
|
||||||
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||||
targetRotation: this.currentObjectRotation,
|
targetRotation: this.currentObjectRotation,
|
||||||
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||||
lifetime: ACTION_LIFETIME
|
ttl: ACTION_TTL
|
||||||
});
|
});
|
||||||
this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC);
|
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.nearGrabbing = function() {
|
this.nearGrabbing = function() {
|
||||||
|
@ -579,12 +579,12 @@ function MyController(hand, triggerAction) {
|
||||||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||||
relativePosition: this.offsetPosition,
|
relativePosition: this.offsetPosition,
|
||||||
relativeRotation: this.offsetRotation,
|
relativeRotation: this.offsetRotation,
|
||||||
lifetime: ACTION_LIFETIME
|
ttl: ACTION_TTL
|
||||||
});
|
});
|
||||||
if (this.actionID === NULL_ACTION_ID) {
|
if (this.actionID === NULL_ACTION_ID) {
|
||||||
this.actionID = null;
|
this.actionID = null;
|
||||||
} else {
|
} else {
|
||||||
this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC);
|
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||||
this.setState(STATE_CONTINUE_NEAR_GRABBING);
|
this.setState(STATE_CONTINUE_NEAR_GRABBING);
|
||||||
if (this.hand === RIGHT_HAND) {
|
if (this.hand === RIGHT_HAND) {
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
||||||
|
@ -624,16 +624,16 @@ function MyController(hand, triggerAction) {
|
||||||
this.currentObjectTime = now;
|
this.currentObjectTime = now;
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab");
|
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab");
|
||||||
|
|
||||||
if (this.actionTimeout - now < ACTION_LIFETIME_REFRESH * MSEC_PER_SEC) {
|
if (this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) {
|
||||||
// if less than a 5 seconds left, refresh the actions lifetime
|
// if less than a 5 seconds left, refresh the actions ttl
|
||||||
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||||
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
||||||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||||
relativePosition: this.offsetPosition,
|
relativePosition: this.offsetPosition,
|
||||||
relativeRotation: this.offsetRotation,
|
relativeRotation: this.offsetRotation,
|
||||||
lifetime: ACTION_LIFETIME
|
ttl: ACTION_TTL
|
||||||
});
|
});
|
||||||
this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC);
|
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ var IDENTITY_QUAT = {
|
||||||
z: 0,
|
z: 0,
|
||||||
w: 0
|
w: 0
|
||||||
};
|
};
|
||||||
var ACTION_LIFETIME = 10; // seconds
|
var ACTION_TTL = 10; // seconds
|
||||||
|
|
||||||
function getTag() {
|
function getTag() {
|
||||||
return "grab-" + MyAvatar.sessionUUID;
|
return "grab-" + MyAvatar.sessionUUID;
|
||||||
|
@ -403,7 +403,7 @@ Grabber.prototype.moveEvent = function(event) {
|
||||||
|
|
||||||
var actionArgs = {
|
var actionArgs = {
|
||||||
tag: getTag(),
|
tag: getTag(),
|
||||||
lifetime: ACTION_LIFETIME
|
ttl: ACTION_TTL
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.mode === "rotate") {
|
if (this.mode === "rotate") {
|
||||||
|
@ -424,7 +424,7 @@ Grabber.prototype.moveEvent = function(event) {
|
||||||
targetRotation: this.lastRotation,
|
targetRotation: this.lastRotation,
|
||||||
angularTimeScale: 0.1,
|
angularTimeScale: 0.1,
|
||||||
tag: getTag(),
|
tag: getTag(),
|
||||||
lifetime: ACTION_LIFETIME
|
ttl: ACTION_TTL
|
||||||
};
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -459,7 +459,7 @@ Grabber.prototype.moveEvent = function(event) {
|
||||||
targetPosition: this.targetPosition,
|
targetPosition: this.targetPosition,
|
||||||
linearTimeScale: 0.1,
|
linearTimeScale: 0.1,
|
||||||
tag: getTag(),
|
tag: getTag(),
|
||||||
lifetime: ACTION_LIFETIME
|
ttl: ACTION_TTL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ var soundMap = [{
|
||||||
y: 495.60,
|
y: 495.60,
|
||||||
z: 502.08
|
z: 502.08
|
||||||
},
|
},
|
||||||
volume: 0.25,
|
volume: 0.03,
|
||||||
loop: true
|
loop: true
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
@ -73,14 +73,27 @@ var soundMap = [{
|
||||||
url: "http://hifi-public.s3.amazonaws.com/ryan/dogs_barking_1.L.wav",
|
url: "http://hifi-public.s3.amazonaws.com/ryan/dogs_barking_1.L.wav",
|
||||||
audioOptions: {
|
audioOptions: {
|
||||||
position: {
|
position: {
|
||||||
x: 551.61,
|
x: 523,
|
||||||
y: 494.88,
|
y: 494.88,
|
||||||
z: 502.00
|
z: 469
|
||||||
},
|
},
|
||||||
volume: 0.15,
|
volume: 0.05,
|
||||||
loop: false
|
loop: false
|
||||||
},
|
},
|
||||||
playAtInterval: 60 * 1000
|
playAtInterval: 60 * 1000
|
||||||
|
}, {
|
||||||
|
name: 'arcade game',
|
||||||
|
url: "http://hifi-public.s3.amazonaws.com/ryan/ARCADE_GAMES_VID.L.L.wav",
|
||||||
|
audioOptions: {
|
||||||
|
position: {
|
||||||
|
x: 543.77,
|
||||||
|
y: 495.07,
|
||||||
|
z: 502.25
|
||||||
|
},
|
||||||
|
volume: 0.01,
|
||||||
|
loop: false,
|
||||||
|
},
|
||||||
|
playAtInterval: 90 * 1000
|
||||||
}];
|
}];
|
||||||
|
|
||||||
function loadSounds() {
|
function loadSounds() {
|
||||||
|
|
|
@ -66,7 +66,8 @@ EntityActionPointer InterfaceActionFactory::factoryBA(EntityItemPointer ownerEnt
|
||||||
if (action) {
|
if (action) {
|
||||||
action->deserialize(data);
|
action->deserialize(data);
|
||||||
if (action->lifetimeIsOver()) {
|
if (action->lifetimeIsOver()) {
|
||||||
qDebug() << "InterfaceActionFactory::factoryBA lifetimeIsOver during action creation";
|
qDebug() << "InterfaceActionFactory::factoryBA lifetimeIsOver during action creation --"
|
||||||
|
<< action->getExpires() << "<" << usecTimestampNow();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -454,7 +454,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
||||||
if (renderBounding && shouldRenderHead(renderArgs)) {
|
if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) {
|
||||||
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f);
|
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ QByteArray AvatarActionHold::serialize() const {
|
||||||
dataStream << _linearTimeScale;
|
dataStream << _linearTimeScale;
|
||||||
dataStream << _hand;
|
dataStream << _hand;
|
||||||
|
|
||||||
dataStream << _expires + getEntityServerClockSkew();
|
dataStream << localTimeToServerTime(_expires);
|
||||||
dataStream << _tag;
|
dataStream << _tag;
|
||||||
dataStream << _kinematic;
|
dataStream << _kinematic;
|
||||||
dataStream << _kinematicSetVelocity;
|
dataStream << _kinematicSetVelocity;
|
||||||
|
@ -277,8 +277,10 @@ void AvatarActionHold::deserialize(QByteArray serializedArguments) {
|
||||||
_angularTimeScale = _linearTimeScale;
|
_angularTimeScale = _linearTimeScale;
|
||||||
dataStream >> _hand;
|
dataStream >> _hand;
|
||||||
|
|
||||||
dataStream >> _expires;
|
quint64 serverExpires;
|
||||||
_expires -= getEntityServerClockSkew();
|
dataStream >> serverExpires;
|
||||||
|
_expires = serverTimeToLocalTime(serverExpires);
|
||||||
|
|
||||||
dataStream >> _tag;
|
dataStream >> _tag;
|
||||||
dataStream >> _kinematic;
|
dataStream >> _kinematic;
|
||||||
dataStream >> _kinematicSetVelocity;
|
dataStream >> _kinematicSetVelocity;
|
||||||
|
|
|
@ -77,7 +77,10 @@ AvatarManager::AvatarManager(QObject* parent) :
|
||||||
|
|
||||||
void AvatarManager::init() {
|
void AvatarManager::init() {
|
||||||
_myAvatar->init();
|
_myAvatar->init();
|
||||||
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
{
|
||||||
|
QWriteLocker locker(&_hashLock);
|
||||||
|
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
||||||
|
}
|
||||||
|
|
||||||
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged, this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
|
connect(DependencyManager::get<SceneScriptingInterface>().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged, this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
@ -127,6 +130,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
} else if (avatar->shouldDie()) {
|
} else if (avatar->shouldDie()) {
|
||||||
removeAvatarMotionState(avatar);
|
removeAvatarMotionState(avatar);
|
||||||
_avatarFades.push_back(avatarIterator.value());
|
_avatarFades.push_back(avatarIterator.value());
|
||||||
|
QWriteLocker locker(&_hashLock);
|
||||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||||
} else {
|
} else {
|
||||||
avatar->startUpdate();
|
avatar->startUpdate();
|
||||||
|
@ -202,6 +206,7 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
||||||
if (avatar != _myAvatar && avatar->isInitialized()) {
|
if (avatar != _myAvatar && avatar->isInitialized()) {
|
||||||
removeAvatarMotionState(avatar);
|
removeAvatarMotionState(avatar);
|
||||||
_avatarFades.push_back(avatarIterator.value());
|
_avatarFades.push_back(avatarIterator.value());
|
||||||
|
QWriteLocker locker(&_hashLock);
|
||||||
_avatarHash.erase(avatarIterator);
|
_avatarHash.erase(avatarIterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,6 +223,7 @@ void AvatarManager::clearOtherAvatars() {
|
||||||
} else {
|
} else {
|
||||||
removeAvatarMotionState(avatar);
|
removeAvatarMotionState(avatar);
|
||||||
_avatarFades.push_back(avatarIterator.value());
|
_avatarFades.push_back(avatarIterator.value());
|
||||||
|
QWriteLocker locker(&_hashLock);
|
||||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,5 +355,6 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID)
|
||||||
if (sessionID == _myAvatar->getSessionUUID()) {
|
if (sessionID == _myAvatar->getSessionUUID()) {
|
||||||
return std::static_pointer_cast<Avatar>(_myAvatar);
|
return std::static_pointer_cast<Avatar>(_myAvatar);
|
||||||
}
|
}
|
||||||
return getAvatarHash()[sessionID];
|
QReadLocker locker(&_hashLock);
|
||||||
|
return _avatarHash[sessionID];
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,6 +208,11 @@ void MyAvatar::update(float deltaTime) {
|
||||||
setPosition(_goToPosition);
|
setPosition(_goToPosition);
|
||||||
setOrientation(_goToOrientation);
|
setOrientation(_goToOrientation);
|
||||||
_goToPending = false;
|
_goToPending = false;
|
||||||
|
// updateFromHMDSensorMatrix (called from paintGL) expects that the sensorToWorldMatrix is updated for any position changes
|
||||||
|
// that happen between render and Application::update (which calls updateSensorToWorldMatrix to do so).
|
||||||
|
// However, render/MyAvatar::update/Application::update don't always match (e.g., when using the separate avatar update thread),
|
||||||
|
// so we update now. It's ok if it updates again in the normal way.
|
||||||
|
updateSensorToWorldMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_referential) {
|
if (_referential) {
|
||||||
|
@ -1020,7 +1025,11 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
||||||
const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f;
|
const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f;
|
||||||
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f;
|
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f;
|
||||||
|
|
||||||
foreach (const AvatarSharedPointer& avatarPointer, DependencyManager::get<AvatarManager>()->getAvatarHash()) {
|
AvatarHash hash;
|
||||||
|
DependencyManager::get<AvatarManager>()->withAvatarHash([&] (const AvatarHash& locked) {
|
||||||
|
hash = locked; // make a shallow copy and operate on that, to minimize lock time
|
||||||
|
});
|
||||||
|
foreach (const AvatarSharedPointer& avatarPointer, hash) {
|
||||||
auto avatar = static_pointer_cast<Avatar>(avatarPointer);
|
auto avatar = static_pointer_cast<Avatar>(avatarPointer);
|
||||||
bool isCurrentTarget = avatar->getIsLookAtTarget();
|
bool isCurrentTarget = avatar->getIsLookAtTarget();
|
||||||
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
||||||
|
@ -1052,7 +1061,6 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
||||||
glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal);
|
glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal);
|
||||||
glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal);
|
glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal);
|
||||||
|
|
||||||
|
|
||||||
// First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point.
|
// First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point.
|
||||||
// (We will be adding that offset to the camera position, after making some other adjustments.)
|
// (We will be adding that offset to the camera position, after making some other adjustments.)
|
||||||
glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition();
|
glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition();
|
||||||
|
@ -1064,14 +1072,14 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
||||||
|
|
||||||
// If the camera is also not oriented with the head, adjust by getting the offset in head-space...
|
// If the camera is also not oriented with the head, adjust by getting the offset in head-space...
|
||||||
/* Not needed (i.e., code is a no-op), but I'm leaving the example code here in case something like this is needed someday.
|
/* Not needed (i.e., code is a no-op), but I'm leaving the example code here in case something like this is needed someday.
|
||||||
glm::quat avatarHeadOrientation = getHead()->getOrientation();
|
glm::quat avatarHeadOrientation = getHead()->getOrientation();
|
||||||
glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset;
|
glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset;
|
||||||
// ... and treat that as though it were in camera space, bringing it back to world space.
|
// ... and treat that as though it were in camera space, bringing it back to world space.
|
||||||
// But camera is fudged to make the picture feel like the avatar's orientation.
|
// But camera is fudged to make the picture feel like the avatar's orientation.
|
||||||
glm::quat humanOrientation = humanSystem->getOrientation(); // or just avatar getOrienation() ?
|
glm::quat humanOrientation = humanSystem->getOrientation(); // or just avatar getOrienation() ?
|
||||||
gazeOffset = humanOrientation * gazeOffsetLocalToHead;
|
gazeOffset = humanOrientation * gazeOffsetLocalToHead;
|
||||||
glm::vec3 corrected = humanSystem->getPosition() + gazeOffset;
|
glm::vec3 corrected = humanSystem->getPosition() + gazeOffset;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// And now we can finally add that offset to the camera.
|
// And now we can finally add that offset to the camera.
|
||||||
glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset;
|
glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset;
|
||||||
|
|
|
@ -22,7 +22,12 @@ AvatarHashMap::AvatarHashMap() {
|
||||||
connect(DependencyManager::get<NodeList>().data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
|
connect(DependencyManager::get<NodeList>().data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarHashMap::withAvatarHash(std::function<void(const AvatarHash& hash)> callback) {
|
||||||
|
QReadLocker locker(&_hashLock);
|
||||||
|
callback(_avatarHash);
|
||||||
|
}
|
||||||
bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) {
|
bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) {
|
||||||
|
QReadLocker locker(&_hashLock);
|
||||||
foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) {
|
foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) {
|
||||||
glm::vec3 avatarPosition = sharedAvatar->getPosition();
|
glm::vec3 avatarPosition = sharedAvatar->getPosition();
|
||||||
float distance = glm::distance(avatarPosition, position);
|
float distance = glm::distance(avatarPosition, position);
|
||||||
|
@ -43,6 +48,7 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe
|
||||||
AvatarSharedPointer avatar = newSharedAvatar();
|
AvatarSharedPointer avatar = newSharedAvatar();
|
||||||
avatar->setSessionUUID(sessionUUID);
|
avatar->setSessionUUID(sessionUUID);
|
||||||
avatar->setOwningAvatarMixer(mixerWeakPointer);
|
avatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||||
|
QWriteLocker locker(&_hashLock);
|
||||||
_avatarHash.insert(sessionUUID, avatar);
|
_avatarHash.insert(sessionUUID, avatar);
|
||||||
|
|
||||||
return avatar;
|
return avatar;
|
||||||
|
@ -134,6 +140,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer<NLPacket> packet, SharedNod
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) {
|
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) {
|
||||||
|
QWriteLocker locker(&_hashLock);
|
||||||
_avatarHash.remove(sessionUUID);
|
_avatarHash.remove(sessionUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <QtCore/QSharedPointer>
|
#include <QtCore/QSharedPointer>
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
@ -30,7 +31,7 @@ class AvatarHashMap : public QObject, public Dependency {
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const AvatarHash& getAvatarHash() { return _avatarHash; }
|
void withAvatarHash(std::function<void(const AvatarHash& hash)>);
|
||||||
int size() { return _avatarHash.size(); }
|
int size() { return _avatarHash.size(); }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -52,6 +53,9 @@ protected:
|
||||||
virtual void removeAvatar(const QUuid& sessionUUID);
|
virtual void removeAvatar(const QUuid& sessionUUID);
|
||||||
|
|
||||||
AvatarHash _avatarHash;
|
AvatarHash _avatarHash;
|
||||||
|
// "Case-based safety": Most access to the _avatarHash is on the same thread. Write access is protected by a write-lock.
|
||||||
|
// If you read from a different thread, you must read-lock the _hashLock. (Scripted write access is not supported).
|
||||||
|
QReadWriteLock _hashLock;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUuid _lastOwnerSessionUUID;
|
QUuid _lastOwnerSessionUUID;
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
static QString actionTypeToString(EntityActionType actionType);
|
static QString actionTypeToString(EntityActionType actionType);
|
||||||
|
|
||||||
virtual bool lifetimeIsOver() { return false; }
|
virtual bool lifetimeIsOver() { return false; }
|
||||||
|
virtual quint64 getExpires() { return 0; }
|
||||||
|
|
||||||
bool locallyAddedButNotYetReceived = false;
|
bool locallyAddedButNotYetReceived = false;
|
||||||
|
|
||||||
|
|
|
@ -85,11 +85,11 @@ bool ObjectAction::updateArguments(QVariantMap arguments) {
|
||||||
quint64 previousExpires = _expires;
|
quint64 previousExpires = _expires;
|
||||||
QString previousTag = _tag;
|
QString previousTag = _tag;
|
||||||
|
|
||||||
bool lifetimeSet = true;
|
bool ttlSet = true;
|
||||||
float lifetime = EntityActionInterface::extractFloatArgument("action", arguments, "lifetime", lifetimeSet, false);
|
float ttl = EntityActionInterface::extractFloatArgument("action", arguments, "ttl", ttlSet, false);
|
||||||
if (lifetimeSet) {
|
if (ttlSet) {
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
_expires = now + (quint64)(lifetime * USECS_PER_SECOND);
|
_expires = now + (quint64)(ttl * USECS_PER_SECOND);
|
||||||
} else {
|
} else {
|
||||||
_expires = 0;
|
_expires = 0;
|
||||||
}
|
}
|
||||||
|
@ -114,10 +114,10 @@ QVariantMap ObjectAction::getArguments() {
|
||||||
QVariantMap arguments;
|
QVariantMap arguments;
|
||||||
withReadLock([&]{
|
withReadLock([&]{
|
||||||
if (_expires == 0) {
|
if (_expires == 0) {
|
||||||
arguments["lifetime"] = 0.0f;
|
arguments["ttl"] = 0.0f;
|
||||||
} else {
|
} else {
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
arguments["lifetime"] = (float)(_expires - now) / (float)USECS_PER_SECOND;
|
arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND;
|
||||||
}
|
}
|
||||||
arguments["tag"] = _tag;
|
arguments["tag"] = _tag;
|
||||||
});
|
});
|
||||||
|
@ -245,3 +245,31 @@ bool ObjectAction::lifetimeIsOver() {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) const {
|
||||||
|
// 0 indicates no expiration
|
||||||
|
if (timeValue == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serverClockSkew = getEntityServerClockSkew();
|
||||||
|
if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) {
|
||||||
|
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeValue + serverClockSkew;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) const {
|
||||||
|
// 0 indicates no expiration
|
||||||
|
if (timeValue == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serverClockSkew = getEntityServerClockSkew();
|
||||||
|
if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) {
|
||||||
|
return 1; // non-zero but long-expired value to avoid negative roll-over
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeValue - serverClockSkew;
|
||||||
|
}
|
||||||
|
|
|
@ -47,11 +47,10 @@ public:
|
||||||
virtual void deserialize(QByteArray serializedArguments) = 0;
|
virtual void deserialize(QByteArray serializedArguments) = 0;
|
||||||
|
|
||||||
virtual bool lifetimeIsOver();
|
virtual bool lifetimeIsOver();
|
||||||
|
virtual quint64 getExpires() { return _expires; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
int getEntityServerClockSkew() const;
|
|
||||||
|
|
||||||
virtual btRigidBody* getRigidBody();
|
virtual btRigidBody* getRigidBody();
|
||||||
virtual glm::vec3 getPosition();
|
virtual glm::vec3 getPosition();
|
||||||
virtual void setPosition(glm::vec3 position);
|
virtual void setPosition(glm::vec3 position);
|
||||||
|
@ -68,6 +67,12 @@ protected:
|
||||||
|
|
||||||
quint64 _expires; // in seconds since epoch
|
quint64 _expires; // in seconds since epoch
|
||||||
QString _tag;
|
QString _tag;
|
||||||
|
|
||||||
|
quint64 localTimeToServerTime(quint64 timeValue) const;
|
||||||
|
quint64 serverTimeToLocalTime(quint64 timeValue) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int getEntityServerClockSkew() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ObjectAction_h
|
#endif // hifi_ObjectAction_h
|
||||||
|
|
|
@ -160,7 +160,7 @@ QByteArray ObjectActionOffset::serialize() const {
|
||||||
dataStream << _linearDistance;
|
dataStream << _linearDistance;
|
||||||
dataStream << _linearTimeScale;
|
dataStream << _linearTimeScale;
|
||||||
dataStream << _positionalTargetSet;
|
dataStream << _positionalTargetSet;
|
||||||
dataStream << _expires + getEntityServerClockSkew();
|
dataStream << localTimeToServerTime(_expires);
|
||||||
dataStream << _tag;
|
dataStream << _tag;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -189,8 +189,11 @@ void ObjectActionOffset::deserialize(QByteArray serializedArguments) {
|
||||||
dataStream >> _linearDistance;
|
dataStream >> _linearDistance;
|
||||||
dataStream >> _linearTimeScale;
|
dataStream >> _linearTimeScale;
|
||||||
dataStream >> _positionalTargetSet;
|
dataStream >> _positionalTargetSet;
|
||||||
dataStream >> _expires;
|
|
||||||
_expires -= getEntityServerClockSkew();
|
quint64 serverExpires;
|
||||||
|
dataStream >> serverExpires;
|
||||||
|
_expires = serverTimeToLocalTime(serverExpires);
|
||||||
|
|
||||||
dataStream >> _tag;
|
dataStream >> _tag;
|
||||||
_active = true;
|
_active = true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -198,7 +198,7 @@ QByteArray ObjectActionSpring::serialize() const {
|
||||||
dataStream << _rotationalTarget;
|
dataStream << _rotationalTarget;
|
||||||
dataStream << _angularTimeScale;
|
dataStream << _angularTimeScale;
|
||||||
dataStream << _rotationalTargetSet;
|
dataStream << _rotationalTargetSet;
|
||||||
dataStream << _expires + getEntityServerClockSkew();
|
dataStream << localTimeToServerTime(_expires);
|
||||||
dataStream << _tag;
|
dataStream << _tag;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -232,8 +232,10 @@ void ObjectActionSpring::deserialize(QByteArray serializedArguments) {
|
||||||
dataStream >> _angularTimeScale;
|
dataStream >> _angularTimeScale;
|
||||||
dataStream >> _rotationalTargetSet;
|
dataStream >> _rotationalTargetSet;
|
||||||
|
|
||||||
dataStream >> _expires;
|
quint64 serverExpires;
|
||||||
_expires -= getEntityServerClockSkew();
|
dataStream >> serverExpires;
|
||||||
|
_expires = serverTimeToLocalTime(serverExpires);
|
||||||
|
|
||||||
dataStream >> _tag;
|
dataStream >> _tag;
|
||||||
|
|
||||||
_active = true;
|
_active = true;
|
||||||
|
|
111
unpublishedScripts/basketballsResetter.js
Normal file
111
unpublishedScripts/basketballsResetter.js
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by James B. Pollack @imgntn on 10/26/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var _this;
|
||||||
|
Resetter = function() {
|
||||||
|
_this = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Resetter.prototype = {
|
||||||
|
|
||||||
|
startNearGrabNonColliding: function() {
|
||||||
|
this.resetObjects();
|
||||||
|
},
|
||||||
|
|
||||||
|
clickReleaseOnEntity: function() {
|
||||||
|
this.resetObjects();
|
||||||
|
},
|
||||||
|
|
||||||
|
resetObjects: function() {
|
||||||
|
var ids = Entities.findEntities(this.initialProperties.position, 75);
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < ids.length; i++) {
|
||||||
|
var id = ids[i];
|
||||||
|
var properties = Entities.getEntityProperties(id, "name");
|
||||||
|
if (properties.name === "Hifi-Basketball") {
|
||||||
|
Entities.deleteEntity(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.createBasketballs();
|
||||||
|
},
|
||||||
|
|
||||||
|
createBasketballs: function() {
|
||||||
|
var NUMBER_OF_BALLS = 4;
|
||||||
|
var DIAMETER = 0.30;
|
||||||
|
var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx";
|
||||||
|
var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav";
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: 542.86,
|
||||||
|
y: 494.84,
|
||||||
|
z: 475.06
|
||||||
|
};
|
||||||
|
var collidingBalls = [];
|
||||||
|
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < NUMBER_OF_BALLS; i++) {
|
||||||
|
var ballPosition = {
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + DIAMETER * 2,
|
||||||
|
z: position.z + (DIAMETER) - (DIAMETER * i)
|
||||||
|
};
|
||||||
|
var newPosition = {
|
||||||
|
x: position.x + (DIAMETER * 2) - (DIAMETER * i),
|
||||||
|
y: position.y + DIAMETER * 2,
|
||||||
|
z: position.z
|
||||||
|
};
|
||||||
|
var collidingBall = Entities.addEntity({
|
||||||
|
type: "Model",
|
||||||
|
name: 'Hifi-Basketball',
|
||||||
|
shapeType: 'Sphere',
|
||||||
|
position: newPosition,
|
||||||
|
dimensions: {
|
||||||
|
x: DIAMETER,
|
||||||
|
y: DIAMETER,
|
||||||
|
z: DIAMETER
|
||||||
|
},
|
||||||
|
restitution: 1.0,
|
||||||
|
linearDamping: 0.00001,
|
||||||
|
gravity: {
|
||||||
|
x: 0,
|
||||||
|
y: -9.8,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
collisionsWillMove: true,
|
||||||
|
collisionsSoundURL: basketballCollisionSoundURL,
|
||||||
|
ignoreForCollisions: false,
|
||||||
|
modelURL: basketballURL,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
resetMe: {
|
||||||
|
resetMe: true
|
||||||
|
},
|
||||||
|
grabbableKey: {
|
||||||
|
invertSolidWhileHeld: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
collidingBalls.push(collidingBall);
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.initialProperties = Entities.getEntityProperties(entityID);
|
||||||
|
this.entityID = entityID;
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Resetter();
|
||||||
|
});
|
|
@ -22,7 +22,8 @@
|
||||||
var dollScriptURL = Script.resolvePath("../examples/toybox/doll/doll.js");
|
var dollScriptURL = Script.resolvePath("../examples/toybox/doll/doll.js");
|
||||||
var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js");
|
var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js");
|
||||||
var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js');
|
var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js');
|
||||||
|
var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js');
|
||||||
|
var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js');
|
||||||
|
|
||||||
ResetSwitch = function() {
|
ResetSwitch = function() {
|
||||||
_this = this;
|
_this = this;
|
||||||
|
@ -110,9 +111,12 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
createPingPongBallGun();
|
createPingPongBallGun();
|
||||||
|
createTargets();
|
||||||
|
createTargetResetter();
|
||||||
|
|
||||||
createBasketballHoop();
|
createBasketballHoop();
|
||||||
createBasketballRack();
|
createBasketballRack();
|
||||||
|
createBasketballResetter();
|
||||||
|
|
||||||
createGates();
|
createGates();
|
||||||
|
|
||||||
|
@ -120,8 +124,6 @@
|
||||||
// Handles toggling of all sconce lights
|
// Handles toggling of all sconce lights
|
||||||
createLights();
|
createLights();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
createCat({
|
createCat({
|
||||||
x: 551.09,
|
x: 551.09,
|
||||||
y: 494.98,
|
y: 494.98,
|
||||||
|
@ -135,7 +137,6 @@
|
||||||
z: 503.91
|
z: 503.91
|
||||||
});
|
});
|
||||||
|
|
||||||
createTargets();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,10 +276,11 @@
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
var collidingBalls = [];
|
|
||||||
|
|
||||||
function createCollidingBalls() {
|
function createCollidingBalls() {
|
||||||
var position = rackStartPosition;
|
var position = rackStartPosition;
|
||||||
|
var collidingBalls = [];
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < NUMBER_OF_BALLS; i++) {
|
for (i = 0; i < NUMBER_OF_BALLS; i++) {
|
||||||
|
@ -334,6 +336,74 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createBasketballResetter() {
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: 543.58,
|
||||||
|
y: 495.47,
|
||||||
|
z: 469.59
|
||||||
|
};
|
||||||
|
|
||||||
|
var dimensions = {
|
||||||
|
x: 1.65,
|
||||||
|
y: 1.71,
|
||||||
|
z: 1.75
|
||||||
|
};
|
||||||
|
|
||||||
|
var resetter = Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
position: position,
|
||||||
|
name: "Basketball Resetter",
|
||||||
|
script: basketballResetterScriptURL,
|
||||||
|
dimensions: dimensions,
|
||||||
|
visible: false,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
resetMe: {
|
||||||
|
resetMe: true
|
||||||
|
},
|
||||||
|
grabbableKey: {
|
||||||
|
wantsTrigger: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTargetResetter() {
|
||||||
|
var dimensions = {
|
||||||
|
x: 0.21,
|
||||||
|
y: 0.61,
|
||||||
|
z: 0.21
|
||||||
|
};
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: 548.42,
|
||||||
|
y: 496.40,
|
||||||
|
z: 509.61
|
||||||
|
};
|
||||||
|
|
||||||
|
var resetter = Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
position: position,
|
||||||
|
name: "Target Resetter",
|
||||||
|
script: targetsResetterScriptURL,
|
||||||
|
dimensions: dimensions,
|
||||||
|
visible: false,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
resetMe: {
|
||||||
|
resetMe: true
|
||||||
|
},
|
||||||
|
grabbableKey: {
|
||||||
|
wantsTrigger: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function createTargets() {
|
function createTargets() {
|
||||||
|
|
||||||
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx';
|
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx';
|
||||||
|
|
|
@ -8,15 +8,11 @@
|
||||||
|
|
||||||
/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */
|
/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */
|
||||||
|
|
||||||
|
|
||||||
var masterResetScript = Script.resolvePath("masterReset.js");
|
var masterResetScript = Script.resolvePath("masterReset.js");
|
||||||
var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js");
|
var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js");
|
||||||
|
|
||||||
|
|
||||||
Script.include(masterResetScript);
|
Script.include(masterResetScript);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function createHiddenMasterSwitch() {
|
function createHiddenMasterSwitch() {
|
||||||
|
|
||||||
var resetKey = "resetMe";
|
var resetKey = "resetMe";
|
||||||
|
@ -31,7 +27,6 @@ function createHiddenMasterSwitch() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var entities = Entities.findEntities(MyAvatar.position, 100);
|
var entities = Entities.findEntities(MyAvatar.position, 100);
|
||||||
|
|
||||||
entities.forEach(function(entity) {
|
entities.forEach(function(entity) {
|
||||||
|
@ -41,5 +36,7 @@ entities.forEach(function(entity) {
|
||||||
Entities.deleteEntity(entity);
|
Entities.deleteEntity(entity);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
createHiddenMasterSwitch();
|
createHiddenMasterSwitch();
|
||||||
|
|
||||||
MasterReset();
|
MasterReset();
|
|
@ -14,16 +14,16 @@
|
||||||
var utilitiesScript = Script.resolvePath("../examples/libraries/utils.js");
|
var utilitiesScript = Script.resolvePath("../examples/libraries/utils.js");
|
||||||
Script.include(utilitiesScript);
|
Script.include(utilitiesScript);
|
||||||
|
|
||||||
var sprayPaintScriptURL = Script.resolvePath("../examples/toybox/spray_paint/sprayPaintCan.js");
|
var sprayPaintScriptURL = Script.resolvePath("../examples/toybox/spray_paint/sprayPaintCan.js");
|
||||||
var catScriptURL = Script.resolvePath("../examples/toybox/cat/cat.js");
|
var catScriptURL = Script.resolvePath("../examples/toybox/cat/cat.js");
|
||||||
var flashlightScriptURL = Script.resolvePath('../examples/toybox/flashlight/flashlight.js');
|
var flashlightScriptURL = Script.resolvePath('../examples/toybox/flashlight/flashlight.js');
|
||||||
var pingPongScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/pingPongGun.js');
|
var pingPongScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/pingPongGun.js');
|
||||||
var wandScriptURL = Script.resolvePath("../examples/toybox/bubblewand/wand.js");
|
var wandScriptURL = Script.resolvePath("../examples/toybox/bubblewand/wand.js");
|
||||||
var dollScriptURL = Script.resolvePath("../examples/toybox/doll/doll.js");
|
var dollScriptURL = Script.resolvePath("../examples/toybox/doll/doll.js");
|
||||||
var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js");
|
var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js");
|
||||||
var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js');
|
var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js');
|
||||||
|
var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js');
|
||||||
|
var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js');
|
||||||
|
|
||||||
MasterReset = function() {
|
MasterReset = function() {
|
||||||
var resetKey = "resetMe";
|
var resetKey = "resetMe";
|
||||||
|
@ -84,9 +84,12 @@ MasterReset = function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
createPingPongBallGun();
|
createPingPongBallGun();
|
||||||
|
createTargets();
|
||||||
|
createTargetResetter();
|
||||||
|
|
||||||
createBasketballHoop();
|
createBasketballHoop();
|
||||||
createBasketballRack();
|
createBasketballRack();
|
||||||
|
createBasketballResetter();
|
||||||
|
|
||||||
createGates();
|
createGates();
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ MasterReset = function() {
|
||||||
z: 503.91
|
z: 503.91
|
||||||
});
|
});
|
||||||
|
|
||||||
createTargets();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +204,7 @@ MasterReset = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function createBasketballRack() {
|
function createBasketballRack() {
|
||||||
var NUMBER_OF_BALLS = 4;
|
var NUMBER_OF_BALLS = 4;
|
||||||
var DIAMETER = 0.30;
|
var DIAMETER = 0.30;
|
||||||
|
@ -249,10 +253,11 @@ MasterReset = function() {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
var collidingBalls = [];
|
|
||||||
|
|
||||||
function createCollidingBalls() {
|
function createCollidingBalls() {
|
||||||
var position = rackStartPosition;
|
var position = rackStartPosition;
|
||||||
|
var collidingBalls = [];
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < NUMBER_OF_BALLS; i++) {
|
for (i = 0; i < NUMBER_OF_BALLS; i++) {
|
||||||
|
@ -308,6 +313,75 @@ MasterReset = function() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function createBasketballResetter() {
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: 543.58,
|
||||||
|
y: 495.47,
|
||||||
|
z: 469.59
|
||||||
|
};
|
||||||
|
|
||||||
|
var dimensions = {
|
||||||
|
x: 1.65,
|
||||||
|
y: 1.71,
|
||||||
|
z: 1.75
|
||||||
|
};
|
||||||
|
|
||||||
|
var resetter = Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
position: position,
|
||||||
|
name: "Basketball Resetter",
|
||||||
|
script: basketballResetterScriptURL,
|
||||||
|
dimensions: dimensions,
|
||||||
|
visible:false,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
resetMe: {
|
||||||
|
resetMe: true
|
||||||
|
},
|
||||||
|
grabbableKey: {
|
||||||
|
wantsTrigger: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTargetResetter() {
|
||||||
|
var dimensions = {
|
||||||
|
x: 0.21,
|
||||||
|
y: 0.61,
|
||||||
|
z: 0.21
|
||||||
|
};
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: 548.42,
|
||||||
|
y: 496.40,
|
||||||
|
z: 509.61
|
||||||
|
};
|
||||||
|
|
||||||
|
var resetter = Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
position: position,
|
||||||
|
name: "Target Resetter",
|
||||||
|
script: targetsResetterScriptURL,
|
||||||
|
dimensions: dimensions,
|
||||||
|
visible:false,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
resetMe: {
|
||||||
|
resetMe: true
|
||||||
|
},
|
||||||
|
grabbableKey: {
|
||||||
|
wantsTrigger: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function createTargets() {
|
function createTargets() {
|
||||||
|
|
||||||
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx';
|
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx';
|
||||||
|
|
128
unpublishedScripts/targetsResetter.js
Normal file
128
unpublishedScripts/targetsResetter.js
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by James B. Pollack @imgntn on 10/26/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 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 targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js');
|
||||||
|
|
||||||
|
var _this;
|
||||||
|
Resetter = function() {
|
||||||
|
_this = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Resetter.prototype = {
|
||||||
|
|
||||||
|
startNearGrabNonColliding: function() {
|
||||||
|
this.resetObjects();
|
||||||
|
},
|
||||||
|
|
||||||
|
clickReleaseOnEntity: function() {
|
||||||
|
this.resetObjects();
|
||||||
|
},
|
||||||
|
|
||||||
|
resetObjects: function() {
|
||||||
|
var ids = Entities.findEntities(this.initialProperties.position, 50);
|
||||||
|
for (var i = 0; i < ids.length; i++) {
|
||||||
|
var id = ids[i];
|
||||||
|
var properties = Entities.getEntityProperties(id, "name");
|
||||||
|
if (properties.name === "Hifi-Target") {
|
||||||
|
Entities.deleteEntity(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.createTargets();
|
||||||
|
},
|
||||||
|
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.initialProperties = Entities.getEntityProperties(entityID);
|
||||||
|
this.entityID = entityID;
|
||||||
|
},
|
||||||
|
|
||||||
|
createTargets: function() {
|
||||||
|
|
||||||
|
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx';
|
||||||
|
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target_collision_hull.obj';
|
||||||
|
|
||||||
|
var MINIMUM_MOVE_LENGTH = 0.05;
|
||||||
|
var RESET_DISTANCE = 0.5;
|
||||||
|
var TARGET_USER_DATA_KEY = 'hifi-ping_pong_target';
|
||||||
|
var NUMBER_OF_TARGETS = 6;
|
||||||
|
var TARGETS_PER_ROW = 3;
|
||||||
|
|
||||||
|
var TARGET_DIMENSIONS = {
|
||||||
|
x: 0.06,
|
||||||
|
y: 0.42,
|
||||||
|
z: 0.42
|
||||||
|
};
|
||||||
|
|
||||||
|
var VERTICAL_SPACING = TARGET_DIMENSIONS.y + 0.5;
|
||||||
|
var HORIZONTAL_SPACING = TARGET_DIMENSIONS.z + 0.5;
|
||||||
|
|
||||||
|
|
||||||
|
var startPosition = {
|
||||||
|
x: 548.68,
|
||||||
|
y: 497.30,
|
||||||
|
z: 509.74
|
||||||
|
};
|
||||||
|
|
||||||
|
var rotation = Quat.fromPitchYawRollDegrees(0, -55.25, 0);
|
||||||
|
|
||||||
|
var targets = [];
|
||||||
|
|
||||||
|
function addTargets() {
|
||||||
|
var i;
|
||||||
|
var row = -1;
|
||||||
|
for (i = 0; i < NUMBER_OF_TARGETS; i++) {
|
||||||
|
|
||||||
|
if (i % TARGETS_PER_ROW === 0) {
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var vHat = Quat.getFront(rotation);
|
||||||
|
var spacer = HORIZONTAL_SPACING * (i % TARGETS_PER_ROW) + (row * HORIZONTAL_SPACING / 2);
|
||||||
|
var multiplier = Vec3.multiply(spacer, vHat);
|
||||||
|
var position = Vec3.sum(startPosition, multiplier);
|
||||||
|
position.y = startPosition.y - (row * VERTICAL_SPACING);
|
||||||
|
|
||||||
|
var targetProperties = {
|
||||||
|
name: 'Hifi-Target',
|
||||||
|
type: 'Model',
|
||||||
|
modelURL: MODEL_URL,
|
||||||
|
shapeType: 'compound',
|
||||||
|
collisionsWillMove: true,
|
||||||
|
dimensions: TARGET_DIMENSIONS,
|
||||||
|
compoundShapeURL: COLLISION_HULL_URL,
|
||||||
|
position: position,
|
||||||
|
rotation: rotation,
|
||||||
|
script: targetsScriptURL,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
originalPositionKey: {
|
||||||
|
originalPosition: position
|
||||||
|
},
|
||||||
|
resetMe: {
|
||||||
|
resetMe: true
|
||||||
|
},
|
||||||
|
grabbableKey: {
|
||||||
|
grabbable: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var target = Entities.addEntity(targetProperties);
|
||||||
|
targets.push(target);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addTargets();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Resetter();
|
||||||
|
});
|
Loading…
Reference in a new issue