mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 14:29:13 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into rotationRingSize
This commit is contained in:
commit
cc953ab691
14 changed files with 163 additions and 76 deletions
|
@ -1247,7 +1247,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
|
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
|
||||||
|
|
||||||
// use our MyAvatar position and quat for address manager path
|
// use our MyAvatar position and quat for address manager path
|
||||||
addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldPosition(); });
|
addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldFeetPosition(); });
|
||||||
addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); });
|
addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); });
|
||||||
|
|
||||||
connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
|
connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
|
||||||
|
|
|
@ -154,7 +154,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
||||||
|
|
||||||
// connect to AddressManager signal for location jumps
|
// connect to AddressManager signal for location jumps
|
||||||
connect(DependencyManager::get<AddressManager>().data(), &AddressManager::locationChangeRequired,
|
connect(DependencyManager::get<AddressManager>().data(), &AddressManager::locationChangeRequired,
|
||||||
this, static_cast<SlotType>(&MyAvatar::goToLocation));
|
this, static_cast<SlotType>(&MyAvatar::goToFeetLocation));
|
||||||
|
|
||||||
// handle scale constraints imposed on us by the domain-server
|
// handle scale constraints imposed on us by the domain-server
|
||||||
auto& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
auto& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||||
|
@ -2623,6 +2623,49 @@ void MyAvatar::goToLocation(const QVariant& propertiesVar) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::goToFeetLocation(const glm::vec3& newPosition,
|
||||||
|
bool hasOrientation, const glm::quat& newOrientation,
|
||||||
|
bool shouldFaceLocation) {
|
||||||
|
|
||||||
|
qCDebug(interfaceapp).nospace() << "MyAvatar goToFeetLocation - moving to " << newPosition.x << ", "
|
||||||
|
<< newPosition.y << ", " << newPosition.z;
|
||||||
|
|
||||||
|
ShapeInfo shapeInfo;
|
||||||
|
computeShapeInfo(shapeInfo);
|
||||||
|
glm::vec3 halfExtents = shapeInfo.getHalfExtents();
|
||||||
|
glm::vec3 localFeetPos = shapeInfo.getOffset() - glm::vec3(0.0f, halfExtents.y + halfExtents.x, 0.0f);
|
||||||
|
glm::mat4 localFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, localFeetPos);
|
||||||
|
|
||||||
|
glm::mat4 worldFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, newPosition);
|
||||||
|
|
||||||
|
glm::mat4 avatarMat = worldFeet * glm::inverse(localFeet);
|
||||||
|
|
||||||
|
glm::vec3 adjustedPosition = extractTranslation(avatarMat);
|
||||||
|
|
||||||
|
_goToPending = true;
|
||||||
|
_goToPosition = adjustedPosition;
|
||||||
|
_goToOrientation = getWorldOrientation();
|
||||||
|
if (hasOrientation) {
|
||||||
|
qCDebug(interfaceapp).nospace() << "MyAvatar goToFeetLocation - new orientation is "
|
||||||
|
<< newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z << ", " << newOrientation.w;
|
||||||
|
|
||||||
|
// orient the user to face the target
|
||||||
|
glm::quat quatOrientation = cancelOutRollAndPitch(newOrientation);
|
||||||
|
|
||||||
|
if (shouldFaceLocation) {
|
||||||
|
quatOrientation = newOrientation * glm::angleAxis(PI, Vectors::UP);
|
||||||
|
|
||||||
|
// move the user a couple units away
|
||||||
|
const float DISTANCE_TO_USER = 2.0f;
|
||||||
|
_goToPosition = adjustedPosition - quatOrientation * IDENTITY_FORWARD * DISTANCE_TO_USER;
|
||||||
|
}
|
||||||
|
|
||||||
|
_goToOrientation = quatOrientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit transformChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::goToLocation(const glm::vec3& newPosition,
|
void MyAvatar::goToLocation(const glm::vec3& newPosition,
|
||||||
bool hasOrientation, const glm::quat& newOrientation,
|
bool hasOrientation, const glm::quat& newOrientation,
|
||||||
bool shouldFaceLocation) {
|
bool shouldFaceLocation) {
|
||||||
|
|
|
@ -1133,6 +1133,20 @@ public slots:
|
||||||
*/
|
*/
|
||||||
float getGravity();
|
float getGravity();
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Move the avatar to a new position and/or orientation in the domain, while taking into account Avatar leg-length.
|
||||||
|
* @function MyAvatar.goToFeetLocation
|
||||||
|
* @param {Vec3} position - The new position for the avatar, in world coordinates.
|
||||||
|
* @param {boolean} [hasOrientation=false] - Set to <code>true</code> to set the orientation of the avatar.
|
||||||
|
* @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar.
|
||||||
|
* @param {boolean} [shouldFaceLocation=false] - Set to <code>true</code> to position the avatar a short distance away from
|
||||||
|
* the new position and orientate the avatar to face the position.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void goToFeetLocation(const glm::vec3& newPosition,
|
||||||
|
bool hasOrientation, const glm::quat& newOrientation,
|
||||||
|
bool shouldFaceLocation);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Move the avatar to a new position and/or orientation in the domain.
|
* Move the avatar to a new position and/or orientation in the domain.
|
||||||
* @function MyAvatar.goToLocation
|
* @function MyAvatar.goToLocation
|
||||||
|
|
|
@ -115,8 +115,6 @@ ParabolaPointer::RenderState::RenderState(const OverlayID& startID, const Overla
|
||||||
_pathWidth = pathWidth;
|
_pathWidth = pathWidth;
|
||||||
if (render::Item::isValidID(_pathID)) {
|
if (render::Item::isValidID(_pathID)) {
|
||||||
auto renderItem = std::make_shared<ParabolaRenderItem>(pathColor, pathAlpha, pathWidth, isVisibleInSecondaryCamera, pathEnabled);
|
auto renderItem = std::make_shared<ParabolaRenderItem>(pathColor, pathAlpha, pathWidth, isVisibleInSecondaryCamera, pathEnabled);
|
||||||
// TODO: update bounds properly
|
|
||||||
renderItem->editBound().setBox(glm::vec3(-16000.0f), 32000.0f);
|
|
||||||
transaction.resetItem(_pathID, std::make_shared<ParabolaRenderItem::Payload>(renderItem));
|
transaction.resetItem(_pathID, std::make_shared<ParabolaRenderItem::Payload>(renderItem));
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
@ -180,6 +178,7 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve
|
||||||
item.setAcceleration(acceleration);
|
item.setAcceleration(acceleration);
|
||||||
item.setParabolicDistance(parabolicDistance);
|
item.setParabolicDistance(parabolicDistance);
|
||||||
item.setWidth(width);
|
item.setWidth(width);
|
||||||
|
item.updateBounds();
|
||||||
});
|
});
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
@ -302,10 +301,10 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::setVisible(bool visible)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParabolaPointer::RenderState::ParabolaRenderItem::updateKey() {
|
void ParabolaPointer::RenderState::ParabolaRenderItem::updateKey() {
|
||||||
// FIXME: There's no way to designate a render item as non-shadow-reciever, and since a parabola's bounding box covers the entire domain,
|
auto builder = _parabolaData.color.a < 1.0f ? render::ItemKey::Builder::transparentShape() : render::ItemKey::Builder::opaqueShape();
|
||||||
// it seems to block all shadows. I think this is a bug with shadows.
|
|
||||||
//auto builder = _parabolaData.color.a < 1.0f ? render::ItemKey::Builder::transparentShape() : render::ItemKey::Builder::opaqueShape();
|
// TODO: parabolas should cast shadows, but they're so thin that the cascaded shadow maps make them look pretty bad
|
||||||
auto builder = render::ItemKey::Builder::transparentShape();
|
//builder.withShadowCaster();
|
||||||
|
|
||||||
if (_enabled && _visible) {
|
if (_enabled && _visible) {
|
||||||
builder.withVisible();
|
builder.withVisible();
|
||||||
|
@ -322,6 +321,33 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::updateKey() {
|
||||||
_key = builder.build();
|
_key = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParabolaPointer::RenderState::ParabolaRenderItem::updateBounds() {
|
||||||
|
glm::vec3 max = _origin;
|
||||||
|
glm::vec3 min = _origin;
|
||||||
|
|
||||||
|
glm::vec3 end = _origin + _parabolaData.velocity * _parabolaData.parabolicDistance +
|
||||||
|
0.5f * _parabolaData.acceleration * _parabolaData.parabolicDistance * _parabolaData.parabolicDistance;
|
||||||
|
max = glm::max(max, end);
|
||||||
|
min = glm::min(min, end);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (fabsf(_parabolaData.velocity[i]) > EPSILON && fabsf(_parabolaData.acceleration[i]) > EPSILON) {
|
||||||
|
float maxT = -_parabolaData.velocity[i] / _parabolaData.acceleration[i];
|
||||||
|
if (maxT > 0.0f && maxT < _parabolaData.parabolicDistance) {
|
||||||
|
glm::vec3 maxPoint = _origin + _parabolaData.velocity * maxT + 0.5f * _parabolaData.acceleration * maxT * maxT;
|
||||||
|
max = glm::max(max, maxPoint);
|
||||||
|
min = glm::min(min, maxPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 halfWidth = glm::vec3(0.5f * _parabolaData.width);
|
||||||
|
max += halfWidth;
|
||||||
|
min -= halfWidth;
|
||||||
|
|
||||||
|
_bound = AABox(min, max - min);
|
||||||
|
}
|
||||||
|
|
||||||
const gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline() {
|
const gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline() {
|
||||||
if (!_parabolaPipeline || !_transparentParabolaPipeline) {
|
if (!_parabolaPipeline || !_transparentParabolaPipeline) {
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::parabola);
|
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::parabola);
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
void setVisible(bool visible);
|
void setVisible(bool visible);
|
||||||
void updateKey();
|
void updateKey();
|
||||||
void updateUniformBuffer() { _uniformBuffer->setSubData(0, _parabolaData); }
|
void updateUniformBuffer() { _uniformBuffer->setSubData(0, _parabolaData); }
|
||||||
|
void updateBounds();
|
||||||
|
|
||||||
void setColor(const glm::vec3& color) { _parabolaData.color = glm::vec4(color, _parabolaData.color.a); }
|
void setColor(const glm::vec3& color) { _parabolaData.color = glm::vec4(color, _parabolaData.color.a); }
|
||||||
void setAlpha(const float& alpha) { _parabolaData.color.a = alpha; }
|
void setAlpha(const float& alpha) { _parabolaData.color.a = alpha; }
|
||||||
|
|
|
@ -138,7 +138,7 @@ public:
|
||||||
* @property {Vec3} intersection The intersection point in world-space.
|
* @property {Vec3} intersection The intersection point in world-space.
|
||||||
* @property {Vec3} surfaceNormal The surface normal at the intersected point. All NANs if type == INTERSECTED_HUD.
|
* @property {Vec3} surfaceNormal The surface normal at the intersected point. All NANs if type == INTERSECTED_HUD.
|
||||||
* @property {Variant} extraInfo Additional intersection details when available for Model objects.
|
* @property {Variant} extraInfo Additional intersection details when available for Model objects.
|
||||||
* @property {StylusTip} parabola The PickParabola that was used. Valid even if there was no intersection.
|
* @property {PickParabola} parabola The PickParabola that was used. Valid even if there was no intersection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
|
|
@ -92,7 +92,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
|
||||||
* @typedef {object} Pointers.LaserPointerProperties
|
* @typedef {object} Pointers.LaserPointerProperties
|
||||||
* @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar.
|
* @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar.
|
||||||
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
|
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
|
||||||
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the laser is pointing.
|
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing.
|
||||||
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
|
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
|
||||||
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
|
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
|
||||||
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
|
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
|
||||||
|
@ -207,9 +207,10 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
||||||
* The rendering properties of the parabolic path
|
* The rendering properties of the parabolic path
|
||||||
*
|
*
|
||||||
* @typedef {object} Pointers.ParabolaProperties
|
* @typedef {object} Pointers.ParabolaProperties
|
||||||
* @property {Color} color The color of the parabola.
|
* @property {Color} color=255,255,255 The color of the parabola.
|
||||||
* @property {number} alpha The alpha of the parabola.
|
* @property {number} alpha=1.0 The alpha of the parabola.
|
||||||
* @property {number} width The width of the parabola, in meters.
|
* @property {number} width=0.01 The width of the parabola, in meters.
|
||||||
|
* @property {boolean} isVisibleInSecondaryCamera=false The width of the parabola, in meters.
|
||||||
*/
|
*/
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* A set of properties used to define the visual aspect of a Parabola Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.ParabolaPointerRenderState},
|
* A set of properties used to define the visual aspect of a Parabola Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.ParabolaPointerRenderState},
|
||||||
|
@ -232,10 +233,10 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
||||||
*/
|
*/
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick.
|
* A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick.
|
||||||
* @typedef {object} Pointers.LaserPointerProperties
|
* @typedef {object} Pointers.ParabolaPointerProperties
|
||||||
* @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar.
|
* @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar.
|
||||||
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
|
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
|
||||||
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the laser is pointing.
|
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing.
|
||||||
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
|
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
|
||||||
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
|
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
|
||||||
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
|
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
|
||||||
|
|
|
@ -1577,6 +1577,14 @@ void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) {
|
||||||
radius = halfExtents.x;
|
radius = halfExtents.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 Avatar::getWorldFeetPosition() {
|
||||||
|
ShapeInfo shapeInfo;
|
||||||
|
computeShapeInfo(shapeInfo);
|
||||||
|
glm::vec3 halfExtents = shapeInfo.getHalfExtents(); // x = radius, y = halfHeight
|
||||||
|
glm::vec3 localFeet(0.0f, shapeInfo.getOffset().y - halfExtents.y - halfExtents.x, 0.0f);
|
||||||
|
return getWorldOrientation() * localFeet + getWorldPosition();
|
||||||
|
}
|
||||||
|
|
||||||
float Avatar::computeMass() {
|
float Avatar::computeMass() {
|
||||||
float radius;
|
float radius;
|
||||||
glm::vec3 start, end;
|
glm::vec3 start, end;
|
||||||
|
|
|
@ -249,6 +249,12 @@ public:
|
||||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
|
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
|
||||||
void getCapsule(glm::vec3& start, glm::vec3& end, float& radius);
|
void getCapsule(glm::vec3& start, glm::vec3& end, float& radius);
|
||||||
float computeMass();
|
float computeMass();
|
||||||
|
/**jsdoc
|
||||||
|
* Get the position of the current avatar's feet (or rather, bottom of its collision capsule) in world coordinates.
|
||||||
|
* @function MyAvatar.getWorldFeetPosition
|
||||||
|
* @returns {Vec3} The position of the avatar's feet in world coordinates.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE glm::vec3 getWorldFeetPosition();
|
||||||
|
|
||||||
void setPositionViaScript(const glm::vec3& position) override;
|
void setPositionViaScript(const glm::vec3& position) override;
|
||||||
void setOrientationViaScript(const glm::quat& orientation) override;
|
void setOrientationViaScript(const glm::quat& orientation) override;
|
||||||
|
|
|
@ -3743,6 +3743,8 @@ bool EntityItemProperties::verifyStaticCertificateProperties() {
|
||||||
void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityIDToClone) {
|
void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityIDToClone) {
|
||||||
setName(getName() + "-clone-" + entityIDToClone.toString());
|
setName(getName() + "-clone-" + entityIDToClone.toString());
|
||||||
setLocked(false);
|
setLocked(false);
|
||||||
|
setParentID(QUuid());
|
||||||
|
setParentJointIndex(-1);
|
||||||
setLifetime(getCloneLifetime());
|
setLifetime(getCloneLifetime());
|
||||||
setDynamic(getCloneDynamic());
|
setDynamic(getCloneDynamic());
|
||||||
setClientOnly(getCloneAvatarEntity());
|
setClientOnly(getCloneAvatarEntity());
|
||||||
|
|
|
@ -145,6 +145,7 @@ public:
|
||||||
*
|
*
|
||||||
* @property {number} Ray Ray Picks intersect a ray with the nearest object in front of them, along a given direction.
|
* @property {number} Ray Ray Picks intersect a ray with the nearest object in front of them, along a given direction.
|
||||||
* @property {number} Stylus Stylus Picks provide "tapping" functionality on/into flat surfaces.
|
* @property {number} Stylus Stylus Picks provide "tapping" functionality on/into flat surfaces.
|
||||||
|
* @property {number} Parabola Parabola Picks intersect a parabola with the nearest object in front of them, with a given initial velocity and acceleration.
|
||||||
*/
|
*/
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* <table>
|
* <table>
|
||||||
|
@ -154,6 +155,7 @@ public:
|
||||||
* <tbody>
|
* <tbody>
|
||||||
* <tr><td><code>{@link PickType(0)|PickType.Ray}</code></td><td></td></tr>
|
* <tr><td><code>{@link PickType(0)|PickType.Ray}</code></td><td></td></tr>
|
||||||
* <tr><td><code>{@link PickType(0)|PickType.Stylus}</code></td><td></td></tr>
|
* <tr><td><code>{@link PickType(0)|PickType.Stylus}</code></td><td></td></tr>
|
||||||
|
* <tr><td><code>{@link PickType(0)|PickType.Parabola}</code></td><td></td></tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
* @typedef {number} PickType
|
* @typedef {number} PickType
|
||||||
|
|
|
@ -174,10 +174,12 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
this.hapticTargetID = props.id;
|
this.hapticTargetID = props.id;
|
||||||
}
|
}
|
||||||
// if we've attempted to grab a child, roll up to the root of the tree
|
if (!entityIsCloneable(props)) {
|
||||||
var groupRootProps = findGroupParent(controllerData, props);
|
// if we've attempted to grab a non-cloneable child, roll up to the root of the tree
|
||||||
if (entityIsGrabbable(groupRootProps)) {
|
var groupRootProps = findGroupParent(controllerData, props);
|
||||||
return groupRootProps;
|
if (entityIsGrabbable(groupRootProps)) {
|
||||||
|
return groupRootProps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
this.startNearParentingGrabEntity = function (controllerData, targetProps) {
|
this.startNearParentingGrabEntity = function (controllerData, targetProps) {
|
||||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
unhighlightTargetEntity(this.targetEntityID);
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
|
this.highlightedEntity = null;
|
||||||
var message = {
|
var message = {
|
||||||
hand: this.hand,
|
hand: this.hand,
|
||||||
entityID: this.targetEntityID
|
entityID: this.targetEntityID
|
||||||
|
@ -177,6 +178,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||||
}));
|
}));
|
||||||
unhighlightTargetEntity(this.targetEntityID);
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
|
this.highlightedEntity = null;
|
||||||
this.grabbing = false;
|
this.grabbing = false;
|
||||||
this.targetEntityID = null;
|
this.targetEntityID = null;
|
||||||
this.robbed = false;
|
this.robbed = false;
|
||||||
|
@ -268,10 +270,12 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
this.hapticTargetID = props.id;
|
this.hapticTargetID = props.id;
|
||||||
}
|
}
|
||||||
// if we've attempted to grab a child, roll up to the root of the tree
|
if (!entityIsCloneable(props)) {
|
||||||
var groupRootProps = findGroupParent(controllerData, props);
|
// if we've attempted to grab a non-cloneable child, roll up to the root of the tree
|
||||||
if (entityIsGrabbable(groupRootProps)) {
|
var groupRootProps = findGroupParent(controllerData, props);
|
||||||
return groupRootProps;
|
if (entityIsGrabbable(groupRootProps)) {
|
||||||
|
return groupRootProps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
@ -304,6 +308,10 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
return makeRunningValues(true, [this.targetEntityID], []);
|
return makeRunningValues(true, [this.targetEntityID], []);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (this.highlightedEntity) {
|
||||||
|
unhighlightTargetEntity(this.highlightedEntity);
|
||||||
|
this.highlightedEntity = null;
|
||||||
|
}
|
||||||
this.hapticTargetID = null;
|
this.hapticTargetID = null;
|
||||||
this.robbed = false;
|
this.robbed = false;
|
||||||
return makeRunningValues(false, [], []);
|
return makeRunningValues(false, [], []);
|
||||||
|
@ -322,6 +330,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
if (!props) {
|
if (!props) {
|
||||||
// entity was deleted
|
// entity was deleted
|
||||||
unhighlightTargetEntity(this.targetEntityID);
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
|
this.highlightedEntity = null;
|
||||||
this.grabbing = false;
|
this.grabbing = false;
|
||||||
this.targetEntityID = null;
|
this.targetEntityID = null;
|
||||||
this.hapticTargetID = null;
|
this.hapticTargetID = null;
|
||||||
|
@ -344,6 +353,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
if (!readiness.active) {
|
if (!readiness.active) {
|
||||||
this.robbed = false;
|
this.robbed = false;
|
||||||
unhighlightTargetEntity(this.highlightedEntity);
|
unhighlightTargetEntity(this.highlightedEntity);
|
||||||
|
this.highlightedEntity = null;
|
||||||
return readiness;
|
return readiness;
|
||||||
}
|
}
|
||||||
if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
||||||
|
|
|
@ -22,7 +22,6 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
(function() { // BEGIN LOCAL_SCOPE
|
(function() { // BEGIN LOCAL_SCOPE
|
||||||
|
|
||||||
var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleport-destination.fbx");
|
var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleport-destination.fbx");
|
||||||
var TOO_CLOSE_MODEL_URL = Script.resolvePath("../../assets/models/teleport-cancel.fbx");
|
|
||||||
var SEAT_MODEL_URL = Script.resolvePath("../../assets/models/teleport-seat.fbx");
|
var SEAT_MODEL_URL = Script.resolvePath("../../assets/models/teleport-seat.fbx");
|
||||||
|
|
||||||
var TARGET_MODEL_DIMENSIONS = {
|
var TARGET_MODEL_DIMENSIONS = {
|
||||||
|
@ -49,8 +48,6 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
blue: 73
|
blue: 73
|
||||||
};
|
};
|
||||||
|
|
||||||
var COOL_IN_DURATION = 300;
|
|
||||||
|
|
||||||
var handInfo = {
|
var handInfo = {
|
||||||
right: {
|
right: {
|
||||||
controllerInput: Controller.Standard.RightHand
|
controllerInput: Controller.Standard.RightHand
|
||||||
|
@ -61,37 +58,19 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
};
|
};
|
||||||
|
|
||||||
var cancelPath = {
|
var cancelPath = {
|
||||||
type: "line3d",
|
|
||||||
color: COLORS_TELEPORT_CANCEL,
|
color: COLORS_TELEPORT_CANCEL,
|
||||||
ignorePickIntersection: true,
|
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
solid: true,
|
width: 0.025
|
||||||
drawInFront: true,
|
|
||||||
glow: 1.0
|
|
||||||
};
|
};
|
||||||
var teleportPath = {
|
var teleportPath = {
|
||||||
type: "line3d",
|
|
||||||
color: COLORS_TELEPORT_CAN_TELEPORT,
|
color: COLORS_TELEPORT_CAN_TELEPORT,
|
||||||
ignorePickIntersection: true,
|
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
solid: true,
|
width: 0.025
|
||||||
drawInFront: true,
|
|
||||||
glow: 1.0
|
|
||||||
};
|
};
|
||||||
var seatPath = {
|
var seatPath = {
|
||||||
type: "line3d",
|
|
||||||
color: COLORS_TELEPORT_SEAT,
|
color: COLORS_TELEPORT_SEAT,
|
||||||
ignorePickIntersection: true,
|
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
solid: true,
|
width: 0.025
|
||||||
drawInFront: true,
|
|
||||||
glow: 1.0
|
|
||||||
};
|
|
||||||
var cancelEnd = {
|
|
||||||
type: "model",
|
|
||||||
url: TOO_CLOSE_MODEL_URL,
|
|
||||||
dimensions: TARGET_MODEL_DIMENSIONS,
|
|
||||||
ignorePickIntersection: true
|
|
||||||
};
|
};
|
||||||
var teleportEnd = {
|
var teleportEnd = {
|
||||||
type: "model",
|
type: "model",
|
||||||
|
@ -107,20 +86,18 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd},
|
var teleportRenderStates = [{name: "cancel", path: cancelPath},
|
||||||
{name: "teleport", path: teleportPath, end: teleportEnd},
|
{name: "teleport", path: teleportPath, end: teleportEnd},
|
||||||
{name: "seat", path: seatPath, end: seatEnd}];
|
{name: "seat", path: seatPath, end: seatEnd}];
|
||||||
|
|
||||||
var DEFAULT_DISTANCE = 50;
|
var DEFAULT_DISTANCE = 8.0;
|
||||||
var teleportDefaultRenderStates = [{name: "cancel", distance: DEFAULT_DISTANCE, path: cancelPath}];
|
var teleportDefaultRenderStates = [{name: "cancel", distance: DEFAULT_DISTANCE, path: cancelPath}];
|
||||||
|
|
||||||
var coolInTimeout = null;
|
|
||||||
var ignoredEntities = [];
|
var ignoredEntities = [];
|
||||||
|
|
||||||
|
|
||||||
var TELEPORTER_STATES = {
|
var TELEPORTER_STATES = {
|
||||||
IDLE: 'idle',
|
IDLE: 'idle',
|
||||||
COOL_IN: 'cool_in',
|
|
||||||
TARGETTING: 'targetting',
|
TARGETTING: 'targetting',
|
||||||
TARGETTING_INVALID: 'targetting_invalid'
|
TARGETTING_INVALID: 'targetting_invalid'
|
||||||
};
|
};
|
||||||
|
@ -133,7 +110,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
SEAT: 'seat' // The current target is a seat
|
SEAT: 'seat' // The current target is a seat
|
||||||
};
|
};
|
||||||
|
|
||||||
var speed = 7.0;
|
var speed = 12.0;
|
||||||
var accelerationAxis = {x: 0.0, y: -5.0, z: 0.0};
|
var accelerationAxis = {x: 0.0, y: -5.0, z: 0.0};
|
||||||
|
|
||||||
function Teleporter(hand) {
|
function Teleporter(hand) {
|
||||||
|
@ -151,8 +128,10 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
return otherModule;
|
return otherModule;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.teleportParabolaHandVisible = Pointers.createPointer(PickType.Ray, {
|
this.teleportParabolaHandVisible = Pointers.createPointer(PickType.Parabola, {
|
||||||
joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||||
|
dirOffset: { x: 0, y: 1, z: 0.1 },
|
||||||
|
posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 },
|
||||||
filter: Picks.PICK_ENTITIES,
|
filter: Picks.PICK_ENTITIES,
|
||||||
faceAvatar: true,
|
faceAvatar: true,
|
||||||
scaleWithAvatar: true,
|
scaleWithAvatar: true,
|
||||||
|
@ -161,10 +140,13 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
accelerationAxis: accelerationAxis,
|
accelerationAxis: accelerationAxis,
|
||||||
rotateAccelerationWithAvatar: true,
|
rotateAccelerationWithAvatar: true,
|
||||||
renderStates: teleportRenderStates,
|
renderStates: teleportRenderStates,
|
||||||
defaultRenderStates: teleportDefaultRenderStates
|
defaultRenderStates: teleportDefaultRenderStates,
|
||||||
|
maxDistance: 8.0
|
||||||
});
|
});
|
||||||
this.teleportParabolaHandInvisible = Pointers.createPointer(PickType.Ray, {
|
this.teleportParabolaHandInvisible = Pointers.createPointer(PickType.Parabola, {
|
||||||
joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||||
|
dirOffset: { x: 0, y: 1, z: 0.1 },
|
||||||
|
posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 },
|
||||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||||
faceAvatar: true,
|
faceAvatar: true,
|
||||||
scaleWithAvatar: true,
|
scaleWithAvatar: true,
|
||||||
|
@ -172,9 +154,10 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
speed: speed,
|
speed: speed,
|
||||||
accelerationAxis: accelerationAxis,
|
accelerationAxis: accelerationAxis,
|
||||||
rotateAccelerationWithAvatar: true,
|
rotateAccelerationWithAvatar: true,
|
||||||
renderStates: teleportRenderStates
|
renderStates: teleportRenderStates,
|
||||||
|
maxDistance: 8.0
|
||||||
});
|
});
|
||||||
this.teleportParabolaHeadVisible = Pointers.createPointer(PickType.Ray, {
|
this.teleportParabolaHeadVisible = Pointers.createPointer(PickType.Parabola, {
|
||||||
joint: "Avatar",
|
joint: "Avatar",
|
||||||
filter: Picks.PICK_ENTITIES,
|
filter: Picks.PICK_ENTITIES,
|
||||||
faceAvatar: true,
|
faceAvatar: true,
|
||||||
|
@ -184,9 +167,10 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
accelerationAxis: accelerationAxis,
|
accelerationAxis: accelerationAxis,
|
||||||
rotateAccelerationWithAvatar: true,
|
rotateAccelerationWithAvatar: true,
|
||||||
renderStates: teleportRenderStates,
|
renderStates: teleportRenderStates,
|
||||||
defaultRenderStates: teleportDefaultRenderStates
|
defaultRenderStates: teleportDefaultRenderStates,
|
||||||
|
maxDistance: 8.0
|
||||||
});
|
});
|
||||||
this.teleportParabolaHeadInvisible = Pointers.createPointer(PickType.Ray, {
|
this.teleportParabolaHeadInvisible = Pointers.createPointer(PickType.Parabola, {
|
||||||
joint: "Avatar",
|
joint: "Avatar",
|
||||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||||
faceAvatar: true,
|
faceAvatar: true,
|
||||||
|
@ -195,7 +179,8 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
speed: speed,
|
speed: speed,
|
||||||
accelerationAxis: accelerationAxis,
|
accelerationAxis: accelerationAxis,
|
||||||
rotateAccelerationWithAvatar: true,
|
rotateAccelerationWithAvatar: true,
|
||||||
renderStates: teleportRenderStates
|
renderStates: teleportRenderStates,
|
||||||
|
maxDistance: 8.0
|
||||||
});
|
});
|
||||||
|
|
||||||
this.cleanup = function() {
|
this.cleanup = function() {
|
||||||
|
@ -216,16 +201,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
100);
|
100);
|
||||||
|
|
||||||
this.enterTeleport = function() {
|
this.enterTeleport = function() {
|
||||||
if (coolInTimeout !== null) {
|
this.state = TELEPORTER_STATES.TARGETTING;
|
||||||
Script.clearTimeout(coolInTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state = TELEPORTER_STATES.COOL_IN;
|
|
||||||
coolInTimeout = Script.setTimeout(function() {
|
|
||||||
if (_this.state === TELEPORTER_STATES.COOL_IN) {
|
|
||||||
_this.state = TELEPORTER_STATES.TARGETTING;
|
|
||||||
}
|
|
||||||
}, COOL_IN_DURATION);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isReady = function(controllerData, deltaTime) {
|
this.isReady = function(controllerData, deltaTime) {
|
||||||
|
@ -287,11 +263,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
} else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) {
|
} else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) {
|
||||||
this.setTeleportState(mode, "", "cancel");
|
this.setTeleportState(mode, "", "cancel");
|
||||||
} else if (teleportLocationType === TARGET.SURFACE) {
|
} else if (teleportLocationType === TARGET.SURFACE) {
|
||||||
if (this.state === TELEPORTER_STATES.COOL_IN) {
|
this.setTeleportState(mode, "teleport", "");
|
||||||
this.setTeleportState(mode, "cancel", "");
|
|
||||||
} else {
|
|
||||||
this.setTeleportState(mode, "teleport", "");
|
|
||||||
}
|
|
||||||
} else if (teleportLocationType === TARGET.SEAT) {
|
} else if (teleportLocationType === TARGET.SEAT) {
|
||||||
this.setTeleportState(mode, "", "seat");
|
this.setTeleportState(mode, "", "seat");
|
||||||
}
|
}
|
||||||
|
@ -304,7 +276,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
return makeRunningValues(true, [], []);
|
return makeRunningValues(true, [], []);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target === TARGET.NONE || target === TARGET.INVALID || this.state === TELEPORTER_STATES.COOL_IN) {
|
if (target === TARGET.NONE || target === TARGET.INVALID) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} else if (target === TARGET.SEAT) {
|
} else if (target === TARGET.SEAT) {
|
||||||
Entities.callEntityMethod(result.objectID, 'sit');
|
Entities.callEntityMethod(result.objectID, 'sit');
|
||||||
|
|
Loading…
Reference in a new issue