mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' of https://github.com/highfidelity/hifi into skin
This commit is contained in:
commit
9281b28d43
31 changed files with 423 additions and 327 deletions
|
@ -52,13 +52,14 @@ module.exports = {
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"brace-style": ["error", "1tbs", { "allowSingleLine": false }],
|
"brace-style": ["error", "1tbs", { "allowSingleLine": false }],
|
||||||
"comma-dangle": ["error", "only-multiline"],
|
"comma-dangle": ["error", "never"],
|
||||||
"camelcase": ["error"],
|
"camelcase": ["error"],
|
||||||
"curly": ["error", "all"],
|
"curly": ["error", "all"],
|
||||||
"indent": ["error", 4, { "SwitchCase": 1 }],
|
"indent": ["error", 4, { "SwitchCase": 1 }],
|
||||||
"keyword-spacing": ["error", { "before": true, "after": true }],
|
"keyword-spacing": ["error", { "before": true, "after": true }],
|
||||||
"max-len": ["error", 128, 4],
|
"max-len": ["error", 128, 4],
|
||||||
"new-cap": ["error"],
|
"new-cap": ["error"],
|
||||||
|
"no-floating-decimal": ["error"],
|
||||||
//"no-magic-numbers": ["error", { "ignore": [0, 1], "ignoreArrayIndexes": true }],
|
//"no-magic-numbers": ["error", { "ignore": [0, 1], "ignoreArrayIndexes": true }],
|
||||||
"no-multiple-empty-lines": ["error"],
|
"no-multiple-empty-lines": ["error"],
|
||||||
"no-multi-spaces": ["error"],
|
"no-multi-spaces": ["error"],
|
||||||
|
@ -67,6 +68,6 @@ module.exports = {
|
||||||
"spaced-comment": ["error", "always", {
|
"spaced-comment": ["error", "always", {
|
||||||
"line": { "markers": ["/"] }
|
"line": { "markers": ["/"] }
|
||||||
}],
|
}],
|
||||||
"space-before-function-paren": ["error", "never"]
|
"space-before-function-paren": ["error", {"anonymous": "always", "named": "never"}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -137,12 +137,14 @@ ScrollingWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateVisiblity() {
|
function updateVisiblity() {
|
||||||
for (var i = 0; i < tabView.count; ++i) {
|
if (visible) {
|
||||||
if (tabView.getTab(i).enabled) {
|
for (var i = 0; i < tabView.count; ++i) {
|
||||||
return;
|
if (tabView.getTab(i).enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
shown = false;
|
||||||
}
|
}
|
||||||
shown = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function findIndexForUrl(source) {
|
function findIndexForUrl(source) {
|
||||||
|
|
|
@ -603,7 +603,7 @@ ModalWindow {
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: currentSelection
|
id: currentSelection
|
||||||
label: "Path:"
|
label: selectDirectory ? "Directory:" : "File name:"
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
right: selectionType.visible ? selectionType.left: parent.right
|
right: selectionType.visible ? selectionType.left: parent.right
|
||||||
|
|
|
@ -7,7 +7,7 @@ import "../../windows"
|
||||||
import "../../js/Utils.js" as Utils
|
import "../../js/Utils.js" as Utils
|
||||||
import "../models"
|
import "../models"
|
||||||
|
|
||||||
ScrollingWindow {
|
Window {
|
||||||
id: root
|
id: root
|
||||||
resizable: true
|
resizable: true
|
||||||
width: 516
|
width: 516
|
||||||
|
|
|
@ -4998,7 +4998,6 @@ void Application::takeSnapshot() {
|
||||||
|
|
||||||
DependencyManager::get<OffscreenUi>()->load("hifi/dialogs/SnapshotShareDialog.qml", [=](QQmlContext*, QObject* dialog) {
|
DependencyManager::get<OffscreenUi>()->load("hifi/dialogs/SnapshotShareDialog.qml", [=](QQmlContext*, QObject* dialog) {
|
||||||
dialog->setProperty("source", QUrl::fromLocalFile(fileName));
|
dialog->setProperty("source", QUrl::fromLocalFile(fileName));
|
||||||
connect(dialog, SIGNAL(uploadSnapshot(const QString& snapshot)), this, SLOT(uploadSnapshot(const QString& snapshot)));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
||||||
_lastColor = colorX;
|
_lastColor = colorX;
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
|
||||||
Q_ASSERT(args->_batch);
|
Q_ASSERT(args->_batch);
|
||||||
auto& batch = *args->_batch;
|
auto& batch = *args->_batch;
|
||||||
|
|
||||||
|
@ -283,6 +283,9 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
|
if (!getIsSolid()) {
|
||||||
|
builder.withUnlit().withDepthBias();
|
||||||
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,10 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
||||||
Transform transform;
|
Transform transform;
|
||||||
transform.setTranslation(position);
|
transform.setTranslation(position);
|
||||||
transform.setRotation(rotation);
|
transform.setRotation(rotation);
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
auto pipeline = args->_pipeline;
|
auto pipeline = args->_pipeline;
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
pipeline = geometryCache->getShapePipeline();
|
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isSolid) {
|
if (_isSolid) {
|
||||||
|
@ -56,7 +55,7 @@ void Cube3DOverlay::render(RenderArgs* args) {
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline);
|
geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline);
|
||||||
} else {
|
} else {
|
||||||
|
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
|
||||||
if (getIsDashedLine()) {
|
if (getIsDashedLine()) {
|
||||||
transform.setScale(1.0f);
|
transform.setScale(1.0f);
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
|
@ -101,6 +100,9 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
|
if (!getIsSolid()) {
|
||||||
|
builder.withUnlit().withDepthBias();
|
||||||
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,6 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
||||||
transform.setScale(glm::vec3(getDimensions(), 1.0f));
|
transform.setScale(glm::vec3(getDimensions(), 1.0f));
|
||||||
transform.setTranslation(position);
|
transform.setTranslation(position);
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
|
|
||||||
const float MINOR_GRID_EDGE = 0.0025f;
|
const float MINOR_GRID_EDGE = 0.0025f;
|
||||||
const float MAJOR_GRID_EDGE = 0.005f;
|
const float MAJOR_GRID_EDGE = 0.005f;
|
||||||
DependencyManager::get<GeometryCache>()->renderGrid(*batch, minCorner, maxCorner,
|
DependencyManager::get<GeometryCache>()->renderGrid(*batch, minCorner, maxCorner,
|
||||||
|
@ -86,7 +85,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const render::ShapeKey Grid3DOverlay::getShapeKey() {
|
const render::ShapeKey Grid3DOverlay::getShapeKey() {
|
||||||
return render::ShapeKey::Builder().withOwnPipeline();
|
return render::ShapeKey::Builder().withOwnPipeline().withUnlit().withDepthBias();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grid3DOverlay::setProperties(const QVariantMap& properties) {
|
void Grid3DOverlay::setProperties(const QVariantMap& properties) {
|
||||||
|
|
|
@ -92,7 +92,7 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(
|
DependencyManager::get<GeometryCache>()->renderQuad(
|
||||||
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||||
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)
|
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)
|
||||||
|
|
|
@ -54,17 +54,20 @@ void Line3DOverlay::render(RenderArgs* args) {
|
||||||
if (batch) {
|
if (batch) {
|
||||||
batch->setModelTransform(_transform);
|
batch->setModelTransform(_transform);
|
||||||
|
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
|
||||||
if (getIsDashedLine()) {
|
if (getIsDashedLine()) {
|
||||||
// TODO: add support for color to renderDashedLine()
|
// TODO: add support for color to renderDashedLine()
|
||||||
DependencyManager::get<GeometryCache>()->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
geometryCache->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<GeometryCache>()->renderLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
|
||||||
|
geometryCache->renderLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder().withoutCullFace();
|
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,13 +53,15 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
|
||||||
transform.setRotation(rotation);
|
transform.setRotation(rotation);
|
||||||
|
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
|
||||||
if (getIsSolid()) {
|
if (getIsSolid()) {
|
||||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, 0.0f);
|
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, 0.0f);
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(*batch, topLeft, bottomRight, rectangleColor);
|
geometryCache->bindSimpleProgram(*batch);
|
||||||
|
geometryCache->renderQuad(*batch, topLeft, bottomRight, rectangleColor);
|
||||||
} else {
|
} else {
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
geometryCache->bindSimpleProgram(*batch, false, false, true, true);
|
||||||
if (getIsDashedLine()) {
|
if (getIsDashedLine()) {
|
||||||
glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||||
glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f);
|
glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||||
|
@ -89,7 +91,7 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder();
|
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
auto pipeline = args->_pipeline;
|
auto pipeline = args->_pipeline;
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
pipeline = geometryCache->getShapePipeline();
|
pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isSolid) {
|
if (_isSolid) {
|
||||||
|
@ -58,10 +58,13 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder();
|
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
|
if (!getIsSolid()) {
|
||||||
|
builder.withUnlit().withDepthBias();
|
||||||
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,9 @@ void Web3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color);
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
geometryCache->bindSimpleProgram(batch, true, false, true, false);
|
||||||
|
geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color);
|
||||||
batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me
|
batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -425,7 +425,7 @@ glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const
|
||||||
d = glm::normalize(overlaySurfacePoint);
|
d = glm::normalize(overlaySurfacePoint);
|
||||||
}
|
}
|
||||||
reticlePosition = headPosition + (d * getReticleDepth());
|
reticlePosition = headPosition + (d * getReticleDepth());
|
||||||
quat reticleOrientation = glm::quat_cast(_currentDisplayPlugin->getHeadPose());
|
quat reticleOrientation = cancelOutRoll(glm::quat_cast(_currentDisplayPlugin->getHeadPose()));
|
||||||
vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize * getReticleDepth());
|
vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize * getReticleDepth());
|
||||||
return glm::inverse(eyePose) * createMatFromScaleQuatAndPos(reticleScale, reticleOrientation, reticlePosition);
|
return glm::inverse(eyePose) * createMatFromScaleQuatAndPos(reticleScale, reticleOrientation, reticlePosition);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -696,6 +696,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||||
QVector<glm::mat4> localTransforms;
|
QVector<glm::mat4> localTransforms;
|
||||||
const FBXGeometry& geometry = _model->getFBXGeometry();
|
const FBXGeometry& geometry = _model->getFBXGeometry();
|
||||||
int numberOfMeshes = geometry.meshes.size();
|
int numberOfMeshes = geometry.meshes.size();
|
||||||
|
int totalNumVertices = 0;
|
||||||
for (int i = 0; i < numberOfMeshes; i++) {
|
for (int i = 0; i < numberOfMeshes; i++) {
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
if (mesh.clusters.size() > 0) {
|
if (mesh.clusters.size() > 0) {
|
||||||
|
@ -706,6 +707,13 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||||
glm::mat4 identity;
|
glm::mat4 identity;
|
||||||
localTransforms.push_back(identity);
|
localTransforms.push_back(identity);
|
||||||
}
|
}
|
||||||
|
totalNumVertices += mesh.vertices.size();
|
||||||
|
}
|
||||||
|
const int MAX_VERTICES_PER_STATIC_MESH = 1e6;
|
||||||
|
if (totalNumVertices > MAX_VERTICES_PER_STATIC_MESH) {
|
||||||
|
qWarning() << "model" << getModelURL() << "has too many vertices" << totalNumVertices << "and will collide as a box.";
|
||||||
|
info.setParams(SHAPE_TYPE_BOX, 0.5f * dimensions);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateModelBounds();
|
updateModelBounds();
|
||||||
|
|
|
@ -117,7 +117,6 @@ void DomainHandler::hardReset() {
|
||||||
_hostname = QString();
|
_hostname = QString();
|
||||||
_sockAddr.clear();
|
_sockAddr.clear();
|
||||||
|
|
||||||
_hasSignalledProtocolMismatch = false;
|
|
||||||
_domainConnectionRefusals.clear();
|
_domainConnectionRefusals.clear();
|
||||||
|
|
||||||
_hasCheckedForAccessToken = false;
|
_hasCheckedForAccessToken = false;
|
||||||
|
@ -407,25 +406,9 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer<Rec
|
||||||
// and check and signal for an access token so that we can make sure they are logged in
|
// and check and signal for an access token so that we can make sure they are logged in
|
||||||
qCWarning(networking) << "The domain-server denied a connection request: " << reasonMessage;
|
qCWarning(networking) << "The domain-server denied a connection request: " << reasonMessage;
|
||||||
|
|
||||||
if (!_domainConnectionRefusals.contains(reasonCode)) {
|
if (!_domainConnectionRefusals.contains(reasonMessage)) {
|
||||||
|
_domainConnectionRefusals.insert(reasonMessage);
|
||||||
_domainConnectionRefusals.append(reasonCode);
|
emit domainConnectionRefused(reasonMessage, (int)reasonCode);
|
||||||
|
|
||||||
bool shouldSignal = true;
|
|
||||||
|
|
||||||
// only signal once for a protocol mismatch, even between soft resets that will reset the _domainConnectionRefusals
|
|
||||||
if (reasonCode == ConnectionRefusedReason::ProtocolMismatch) {
|
|
||||||
if (_hasSignalledProtocolMismatch) {
|
|
||||||
shouldSignal = false;
|
|
||||||
} else {
|
|
||||||
_hasSignalledProtocolMismatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldSignal) {
|
|
||||||
emit domainConnectionRefused(reasonMessage, (int)reasonCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
|
|
|
@ -144,8 +144,7 @@ private:
|
||||||
QString _pendingPath;
|
QString _pendingPath;
|
||||||
QTimer _settingsTimer;
|
QTimer _settingsTimer;
|
||||||
|
|
||||||
QList<ConnectionRefusedReason> _domainConnectionRefusals;
|
QSet<QString> _domainConnectionRefusals;
|
||||||
bool _hasSignalledProtocolMismatch { false };
|
|
||||||
bool _hasCheckedForAccessToken { false };
|
bool _hasCheckedForAccessToken { false };
|
||||||
int _connectionDenialsSinceKeypairRegen { 0 };
|
int _connectionDenialsSinceKeypairRegen { 0 };
|
||||||
|
|
||||||
|
|
|
@ -218,10 +218,12 @@ void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& re
|
||||||
ShapeInfo shapeInfo;
|
ShapeInfo shapeInfo;
|
||||||
entity->computeShapeInfo(shapeInfo);
|
entity->computeShapeInfo(shapeInfo);
|
||||||
int numPoints = shapeInfo.getLargestSubshapePointCount();
|
int numPoints = shapeInfo.getLargestSubshapePointCount();
|
||||||
if (numPoints > MAX_HULL_POINTS) {
|
if (shapeInfo.getType() == SHAPE_TYPE_COMPOUND) {
|
||||||
qWarning() << "convex hull with" << numPoints
|
if (numPoints > MAX_HULL_POINTS) {
|
||||||
<< "points for entity" << entity->getName()
|
qWarning() << "convex hull with" << numPoints
|
||||||
<< "at" << entity->getPosition() << " will be reduced";
|
<< "points for entity" << entity->getName()
|
||||||
|
<< "at" << entity->getPosition() << " will be reduced";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
||||||
if (shape) {
|
if (shape) {
|
||||||
|
|
|
@ -309,6 +309,7 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
render::ShapePipelinePointer GeometryCache::_simplePipeline;
|
render::ShapePipelinePointer GeometryCache::_simplePipeline;
|
||||||
|
render::ShapePipelinePointer GeometryCache::_simpleWirePipeline;
|
||||||
|
|
||||||
GeometryCache::GeometryCache() :
|
GeometryCache::GeometryCache() :
|
||||||
_nextID(0)
|
_nextID(0)
|
||||||
|
@ -324,6 +325,10 @@ GeometryCache::GeometryCache() :
|
||||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
GeometryCache::_simpleWirePipeline =
|
||||||
|
std::make_shared<render::ShapePipeline>(getSimplePipeline(false, false, true, true), nullptr,
|
||||||
|
[](const render::ShapePipeline&, gpu::Batch& batch) { }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GeometryCache::~GeometryCache() {
|
GeometryCache::~GeometryCache() {
|
||||||
|
|
|
@ -157,7 +157,8 @@ public:
|
||||||
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true,
|
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true,
|
||||||
bool unlit = false, bool depthBias = false);
|
bool unlit = false, bool depthBias = false);
|
||||||
render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; }
|
render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; }
|
||||||
|
render::ShapePipelinePointer getWireShapePipeline() { return GeometryCache::_simpleWirePipeline; }
|
||||||
|
|
||||||
// Static (instanced) geometry
|
// Static (instanced) geometry
|
||||||
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||||
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||||
|
@ -179,7 +180,7 @@ public:
|
||||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
|
||||||
renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ public:
|
||||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) {
|
||||||
renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,6 +402,7 @@ private:
|
||||||
gpu::ShaderPointer _simpleShader;
|
gpu::ShaderPointer _simpleShader;
|
||||||
gpu::ShaderPointer _unlitShader;
|
gpu::ShaderPointer _unlitShader;
|
||||||
static render::ShapePipelinePointer _simplePipeline;
|
static render::ShapePipelinePointer _simplePipeline;
|
||||||
|
static render::ShapePipelinePointer _simpleWirePipeline;
|
||||||
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -466,6 +466,12 @@ glm::mat4 createMatFromScaleQuatAndPos(const glm::vec3& scale, const glm::quat&
|
||||||
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
|
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cancel out roll
|
||||||
|
glm::quat cancelOutRoll(const glm::quat& q) {
|
||||||
|
glm::vec3 forward = q * Vectors::FRONT;
|
||||||
|
return glm::quat_cast(glm::inverse(glm::lookAt(Vectors::ZERO, forward, Vectors::UP)));
|
||||||
|
}
|
||||||
|
|
||||||
// cancel out roll and pitch
|
// cancel out roll and pitch
|
||||||
glm::quat cancelOutRollAndPitch(const glm::quat& q) {
|
glm::quat cancelOutRollAndPitch(const glm::quat& q) {
|
||||||
glm::vec3 zAxis = q * glm::vec3(0.0f, 0.0f, 1.0f);
|
glm::vec3 zAxis = q * glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
|
|
@ -221,6 +221,7 @@ glm::detail::tvec4<T, P> lerp(const glm::detail::tvec4<T, P>& x, const glm::deta
|
||||||
|
|
||||||
glm::mat4 createMatFromQuatAndPos(const glm::quat& q, const glm::vec3& p);
|
glm::mat4 createMatFromQuatAndPos(const glm::quat& q, const glm::vec3& p);
|
||||||
glm::mat4 createMatFromScaleQuatAndPos(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans);
|
glm::mat4 createMatFromScaleQuatAndPos(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans);
|
||||||
|
glm::quat cancelOutRoll(const glm::quat& q);
|
||||||
glm::quat cancelOutRollAndPitch(const glm::quat& q);
|
glm::quat cancelOutRollAndPitch(const glm::quat& q);
|
||||||
glm::mat4 cancelOutRollAndPitch(const glm::mat4& m);
|
glm::mat4 cancelOutRollAndPitch(const glm::mat4& m);
|
||||||
glm::vec3 transformPoint(const glm::mat4& m, const glm::vec3& p);
|
glm::vec3 transformPoint(const glm::mat4& m, const glm::vec3& p);
|
||||||
|
|
|
@ -123,6 +123,7 @@ void QmlWindowClass::initQml(QVariantMap properties) {
|
||||||
|
|
||||||
// Forward messages received from QML on to the script
|
// Forward messages received from QML on to the script
|
||||||
connect(_qmlWindow, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection);
|
connect(_qmlWindow, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection);
|
||||||
|
connect(_qmlWindow, SIGNAL(visibleChanged()), this, SIGNAL(visibleChanged()), Qt::QueuedConnection);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Q_ASSERT(_qmlWindow);
|
Q_ASSERT(_qmlWindow);
|
||||||
|
|
|
@ -24,7 +24,7 @@ class QmlWindowClass : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition NOTIFY positionChanged)
|
Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition NOTIFY positionChanged)
|
||||||
Q_PROPERTY(glm::vec2 size READ getSize WRITE setSize NOTIFY sizeChanged)
|
Q_PROPERTY(glm::vec2 size READ getSize WRITE setSize NOTIFY sizeChanged)
|
||||||
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged)
|
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
|
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
|
||||||
|
@ -52,7 +52,7 @@ public slots:
|
||||||
void sendToQml(const QVariant& message);
|
void sendToQml(const QVariant& message);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void visibilityChanged(bool visible); // Tool window
|
void visibleChanged();
|
||||||
void positionChanged();
|
void positionChanged();
|
||||||
void sizeChanged();
|
void sizeChanged();
|
||||||
void moved(glm::vec2 position);
|
void moved(glm::vec2 position);
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
/*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, Reticle, Messages, setEntityCustomData, getEntityCustomData, vec3toStr */
|
/* global setEntityCustomData, getEntityCustomData, vec3toStr, flatten, Xform */
|
||||||
|
|
||||||
Script.include("/~/system/libraries/utils.js");
|
Script.include("/~/system/libraries/utils.js");
|
||||||
|
Script.include("../libraries/Xform.js");
|
||||||
|
|
||||||
//
|
//
|
||||||
// add lines where the hand ray picking is happening
|
// add lines where the hand ray picking is happening
|
||||||
|
@ -138,7 +139,7 @@ var DEFAULT_GRABBABLE_DATA = {
|
||||||
var USE_BLACKLIST = true;
|
var USE_BLACKLIST = true;
|
||||||
var blacklist = [];
|
var blacklist = [];
|
||||||
|
|
||||||
//we've created various ways of visualizing looking for and moving distant objects
|
// we've created various ways of visualizing looking for and moving distant objects
|
||||||
var USE_ENTITY_LINES_FOR_SEARCHING = false;
|
var USE_ENTITY_LINES_FOR_SEARCHING = false;
|
||||||
var USE_OVERLAY_LINES_FOR_SEARCHING = true;
|
var USE_OVERLAY_LINES_FOR_SEARCHING = true;
|
||||||
|
|
||||||
|
@ -254,7 +255,8 @@ function isIn2DMode() {
|
||||||
// In this version, we make our own determination of whether we're aimed a HUD element,
|
// In this version, we make our own determination of whether we're aimed a HUD element,
|
||||||
// because other scripts (such as handControllerPointer) might be using some other visualization
|
// because other scripts (such as handControllerPointer) might be using some other visualization
|
||||||
// instead of setting Reticle.visible.
|
// instead of setting Reticle.visible.
|
||||||
return EXTERNALLY_MANAGED_2D_MINOR_MODE && (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position));
|
return (EXTERNALLY_MANAGED_2D_MINOR_MODE &&
|
||||||
|
(Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)));
|
||||||
}
|
}
|
||||||
function restore2DMode() {
|
function restore2DMode() {
|
||||||
if (!EXTERNALLY_MANAGED_2D_MINOR_MODE) {
|
if (!EXTERNALLY_MANAGED_2D_MINOR_MODE) {
|
||||||
|
@ -273,7 +275,7 @@ EntityPropertiesCache.prototype.clear = function() {
|
||||||
EntityPropertiesCache.prototype.findEntities = function(position, radius) {
|
EntityPropertiesCache.prototype.findEntities = function(position, radius) {
|
||||||
var entities = Entities.findEntities(position, radius);
|
var entities = Entities.findEntities(position, radius);
|
||||||
var _this = this;
|
var _this = this;
|
||||||
entities.forEach(function (x) {
|
entities.forEach(function(x) {
|
||||||
_this.updateEntity(x);
|
_this.updateEntity(x);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -285,7 +287,7 @@ EntityPropertiesCache.prototype.updateEntity = function(entityID) {
|
||||||
if (props.userData) {
|
if (props.userData) {
|
||||||
try {
|
try {
|
||||||
userData = JSON.parse(props.userData);
|
userData = JSON.parse(props.userData);
|
||||||
} catch(err) {
|
} catch (err) {
|
||||||
print("WARNING: malformed userData on " + entityID + ", name = " + props.name + ", error = " + err);
|
print("WARNING: malformed userData on " + entityID + ", name = " + props.name + ", error = " + err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,9 +297,9 @@ EntityPropertiesCache.prototype.updateEntity = function(entityID) {
|
||||||
};
|
};
|
||||||
EntityPropertiesCache.prototype.getEntities = function() {
|
EntityPropertiesCache.prototype.getEntities = function() {
|
||||||
return Object.keys(this.cache);
|
return Object.keys(this.cache);
|
||||||
}
|
};
|
||||||
EntityPropertiesCache.prototype.getProps = function(entityID) {
|
EntityPropertiesCache.prototype.getProps = function(entityID) {
|
||||||
var obj = this.cache[entityID]
|
var obj = this.cache[entityID];
|
||||||
return obj ? obj : undefined;
|
return obj ? obj : undefined;
|
||||||
};
|
};
|
||||||
EntityPropertiesCache.prototype.getGrabbableProps = function(entityID) {
|
EntityPropertiesCache.prototype.getGrabbableProps = function(entityID) {
|
||||||
|
@ -324,6 +326,14 @@ EntityPropertiesCache.prototype.getWearableProps = function(entityID) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
EntityPropertiesCache.prototype.getEquipHotspotsProps = function(entityID) {
|
||||||
|
var props = this.cache[entityID];
|
||||||
|
if (props) {
|
||||||
|
return props.userData.equipHotspots ? props.userData.equipHotspots : {};
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function MyController(hand) {
|
function MyController(hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
|
@ -337,7 +347,7 @@ function MyController(hand) {
|
||||||
this.getHandRotation = function() {
|
this.getHandRotation = function() {
|
||||||
var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||||
return Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation);
|
return Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation);
|
||||||
}
|
};
|
||||||
|
|
||||||
this.actionID = null; // action this script created...
|
this.actionID = null; // action this script created...
|
||||||
this.grabbedEntity = null; // on this entity.
|
this.grabbedEntity = null; // on this entity.
|
||||||
|
@ -350,11 +360,11 @@ function MyController(hand) {
|
||||||
this.rawSecondaryValue = 0;
|
this.rawSecondaryValue = 0;
|
||||||
this.rawThumbValue = 0;
|
this.rawThumbValue = 0;
|
||||||
|
|
||||||
//for visualizations
|
// for visualizations
|
||||||
this.overlayLine = null;
|
this.overlayLine = null;
|
||||||
this.particleBeamObject = null;
|
this.particleBeamObject = null;
|
||||||
|
|
||||||
//for lights
|
// for lights
|
||||||
this.spotlight = null;
|
this.spotlight = null;
|
||||||
this.pointlight = null;
|
this.pointlight = null;
|
||||||
this.overlayLine = null;
|
this.overlayLine = null;
|
||||||
|
@ -379,7 +389,7 @@ function MyController(hand) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
var suppressedIn2D = [STATE_OFF, STATE_SEARCHING];
|
var suppressedIn2D = [STATE_OFF, STATE_SEARCHING];
|
||||||
this.ignoreInput = function () {
|
this.ignoreInput = function() {
|
||||||
// We've made the decision to use 'this' for new code, even though it is fragile,
|
// We've made the decision to use 'this' for new code, even though it is fragile,
|
||||||
// in order to keep/ the code uniform without making any no-op line changes.
|
// in order to keep/ the code uniform without making any no-op line changes.
|
||||||
return (-1 !== suppressedIn2D.indexOf(this.state)) && isIn2DMode();
|
return (-1 !== suppressedIn2D.indexOf(this.state)) && isIn2DMode();
|
||||||
|
@ -410,7 +420,7 @@ function MyController(hand) {
|
||||||
this.callEntityMethodOnGrabbed = function(entityMethodName) {
|
this.callEntityMethodOnGrabbed = function(entityMethodName) {
|
||||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
Entities.callEntityMethod(this.grabbedEntity, entityMethodName, args);
|
Entities.callEntityMethod(this.grabbedEntity, entityMethodName, args);
|
||||||
}
|
};
|
||||||
|
|
||||||
this.setState = function(newState, reason) {
|
this.setState = function(newState, reason) {
|
||||||
|
|
||||||
|
@ -508,7 +518,7 @@ function MyController(hand) {
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: true, // Even when burried inside of something, show it.
|
drawInFront: true, // Even when burried inside of something, show it.
|
||||||
visible: true
|
visible: true
|
||||||
}
|
};
|
||||||
this.searchSphere = Overlays.addOverlay("sphere", sphereProperties);
|
this.searchSphere = Overlays.addOverlay("sphere", sphereProperties);
|
||||||
} else {
|
} else {
|
||||||
Overlays.editOverlay(this.searchSphere, {
|
Overlays.editOverlay(this.searchSphere, {
|
||||||
|
@ -518,7 +528,7 @@ function MyController(hand) {
|
||||||
visible: true
|
visible: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
this.overlayLineOn = function(closePoint, farPoint, color) {
|
this.overlayLineOn = function(closePoint, farPoint, color) {
|
||||||
if (this.overlayLine === null) {
|
if (this.overlayLine === null) {
|
||||||
|
@ -567,7 +577,7 @@ function MyController(hand) {
|
||||||
this.overlayLineOn(handPosition, searchSphereLocation,
|
this.overlayLineOn(handPosition, searchSphereLocation,
|
||||||
(this.triggerSmoothedGrab() || this.secondarySqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
|
(this.triggerSmoothedGrab() || this.secondarySqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
this.handleDistantParticleBeam = function(handPosition, objectPosition, color) {
|
this.handleDistantParticleBeam = function(handPosition, objectPosition, color) {
|
||||||
|
|
||||||
|
@ -634,7 +644,7 @@ function MyController(hand) {
|
||||||
"alphaFinish": 1,
|
"alphaFinish": 1,
|
||||||
"additiveBlending": 0,
|
"additiveBlending": 0,
|
||||||
"textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png"
|
"textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png"
|
||||||
}
|
};
|
||||||
|
|
||||||
this.particleBeamObject = Entities.addEntity(particleBeamPropertiesObject);
|
this.particleBeamObject = Entities.addEntity(particleBeamPropertiesObject);
|
||||||
};
|
};
|
||||||
|
@ -648,7 +658,7 @@ function MyController(hand) {
|
||||||
emitSpeed: speed,
|
emitSpeed: speed,
|
||||||
speedSpread: spread,
|
speedSpread: spread,
|
||||||
lifespan: lifespan
|
lifespan: lifespan
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.evalLightWorldTransform = function(modelPos, modelRot) {
|
this.evalLightWorldTransform = function(modelPos, modelRot) {
|
||||||
|
@ -702,9 +712,9 @@ function MyController(hand) {
|
||||||
this.spotlight = Entities.addEntity(lightProperties);
|
this.spotlight = Entities.addEntity(lightProperties);
|
||||||
} else {
|
} else {
|
||||||
Entities.editEntity(this.spotlight, {
|
Entities.editEntity(this.spotlight, {
|
||||||
//without this, this light would maintain rotation with its parent
|
// without this, this light would maintain rotation with its parent
|
||||||
rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0)
|
rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0)
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -768,7 +778,7 @@ function MyController(hand) {
|
||||||
Entities.deleteEntity(this.particleBeamObject);
|
Entities.deleteEntity(this.particleBeamObject);
|
||||||
this.particleBeamObject = null;
|
this.particleBeamObject = null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
this.turnLightsOff = function() {
|
this.turnLightsOff = function() {
|
||||||
if (this.spotlight !== null) {
|
if (this.spotlight !== null) {
|
||||||
|
@ -844,7 +854,7 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.thumbPress = function(value) {
|
this.thumbPress = function(value) {
|
||||||
_this.rawThumbValue = value;
|
_this.rawThumbValue = value;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.thumbPressed = function() {
|
this.thumbPressed = function() {
|
||||||
return _this.rawThumbValue > THUMB_ON_VALUE;
|
return _this.rawThumbValue > THUMB_ON_VALUE;
|
||||||
|
@ -869,8 +879,8 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.createHotspots = function () {
|
this.createHotspots = function() {
|
||||||
var props, overlay;
|
var _this = this;
|
||||||
|
|
||||||
var HAND_EQUIP_SPHERE_COLOR = { red: 90, green: 255, blue: 90 };
|
var HAND_EQUIP_SPHERE_COLOR = { red: 90, green: 255, blue: 90 };
|
||||||
var HAND_EQUIP_SPHERE_ALPHA = 0.7;
|
var HAND_EQUIP_SPHERE_ALPHA = 0.7;
|
||||||
|
@ -888,6 +898,7 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.hotspotOverlays = [];
|
this.hotspotOverlays = [];
|
||||||
|
|
||||||
|
var overlay;
|
||||||
if (DRAW_HAND_SPHERES) {
|
if (DRAW_HAND_SPHERES) {
|
||||||
// add tiny green sphere around the palm.
|
// add tiny green sphere around the palm.
|
||||||
var handPosition = this.getHandPosition();
|
var handPosition = this.getHandPosition();
|
||||||
|
@ -901,7 +912,6 @@ function MyController(hand) {
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: false
|
drawInFront: false
|
||||||
});
|
});
|
||||||
|
|
||||||
this.hotspotOverlays.push({
|
this.hotspotOverlays.push({
|
||||||
entityID: undefined,
|
entityID: undefined,
|
||||||
overlay: overlay,
|
overlay: overlay,
|
||||||
|
@ -919,11 +929,11 @@ function MyController(hand) {
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: false
|
drawInFront: false
|
||||||
});
|
});
|
||||||
|
|
||||||
this.hotspotOverlays.push({
|
this.hotspotOverlays.push({
|
||||||
entityID: undefined,
|
entityID: undefined,
|
||||||
overlay: overlay,
|
overlay: overlay,
|
||||||
type: "hand"
|
type: "hand",
|
||||||
|
localPosition: {x: 0, y: 0, z: 0}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,64 +941,71 @@ function MyController(hand) {
|
||||||
this.entityPropertyCache.clear();
|
this.entityPropertyCache.clear();
|
||||||
this.entityPropertyCache.findEntities(MyAvatar.position, HOTSPOT_DRAW_DISTANCE);
|
this.entityPropertyCache.findEntities(MyAvatar.position, HOTSPOT_DRAW_DISTANCE);
|
||||||
|
|
||||||
var _this = this;
|
if (DRAW_GRAB_BOXES) {
|
||||||
this.entityPropertyCache.getEntities().forEach(function (entityID) {
|
// add blue box overlays for grabbable entities.
|
||||||
if (_this.entityIsEquippableWithoutDistanceCheck(entityID)) {
|
this.entityPropertyCache.getEntities().forEach(function(entityID) {
|
||||||
props = _this.entityPropertyCache.getProps(entityID);
|
var props = _this.entityPropertyCache.getProps(entityID);
|
||||||
|
if (_this.entityIsGrabbable(entityID)) {
|
||||||
|
var overlay = Overlays.addOverlay("cube", {
|
||||||
|
rotation: props.rotation,
|
||||||
|
position: props.position,
|
||||||
|
size: props.dimensions,
|
||||||
|
color: GRAB_BOX_COLOR,
|
||||||
|
alpha: GRAB_BOX_ALPHA,
|
||||||
|
solid: true,
|
||||||
|
visible: true,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
drawInFront: false
|
||||||
|
});
|
||||||
|
_this.hotspotOverlays.push({
|
||||||
|
entityID: entityID,
|
||||||
|
overlay: overlay,
|
||||||
|
type: "near",
|
||||||
|
localPosition: {x: 0, y: 0, z: 0}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
overlay = Overlays.addOverlay("sphere", {
|
// add green spheres for each equippable hotspot.
|
||||||
rotation: props.rotation,
|
flatten(this.entityPropertyCache.getEntities().map(function(entityID) {
|
||||||
position: props.position,
|
return _this.collectEquipHotspots(entityID);
|
||||||
size: EQUIP_RADIUS * 2,
|
})).filter(function(hotspot) {
|
||||||
color: EQUIP_SPHERE_COLOR,
|
return _this.hotspotIsEquippable(hotspot);
|
||||||
alpha: EQUIP_SPHERE_ALPHA,
|
}).forEach(function(hotspot) {
|
||||||
solid: true,
|
var overlay = Overlays.addOverlay("sphere", {
|
||||||
visible: true,
|
position: hotspot.worldPosition,
|
||||||
ignoreRayIntersection: true,
|
size: hotspot.radius * 2,
|
||||||
drawInFront: false
|
color: EQUIP_SPHERE_COLOR,
|
||||||
});
|
alpha: EQUIP_SPHERE_ALPHA,
|
||||||
|
solid: true,
|
||||||
_this.hotspotOverlays.push({
|
visible: true,
|
||||||
entityID: entityID,
|
ignoreRayIntersection: true,
|
||||||
overlay: overlay,
|
drawInFront: false
|
||||||
type: "equip"
|
});
|
||||||
});
|
_this.hotspotOverlays.push({
|
||||||
}
|
entityID: hotspot.entityID,
|
||||||
|
overlay: overlay,
|
||||||
if (DRAW_GRAB_BOXES && _this.entityIsGrabbable(entityID)) {
|
type: "equip",
|
||||||
props = _this.entityPropertyCache.getProps(entityID);
|
localPosition: hotspot.localPosition
|
||||||
|
});
|
||||||
overlay = Overlays.addOverlay("cube", {
|
|
||||||
rotation: props.rotation,
|
|
||||||
position: props.position,
|
|
||||||
size: props.dimensions, //{x: props.dimensions.x, y: props.dimensions.y, z: props.dimensions.z},
|
|
||||||
color: GRAB_BOX_COLOR,
|
|
||||||
alpha: GRAB_BOX_ALPHA,
|
|
||||||
solid: true,
|
|
||||||
visible: true,
|
|
||||||
ignoreRayIntersection: true,
|
|
||||||
drawInFront: false
|
|
||||||
});
|
|
||||||
|
|
||||||
_this.hotspotOverlays.push({
|
|
||||||
entityID: entityID,
|
|
||||||
overlay: overlay,
|
|
||||||
type: "near"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateHotspots = function() {
|
this.updateHotspots = function() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var props;
|
var props;
|
||||||
this.hotspotOverlays.forEach(function (overlayInfo) {
|
this.hotspotOverlays.forEach(function(overlayInfo) {
|
||||||
if (overlayInfo.type === "hand") {
|
if (overlayInfo.type === "hand") {
|
||||||
Overlays.editOverlay(overlayInfo.overlay, { position: _this.getHandPosition() });
|
Overlays.editOverlay(overlayInfo.overlay, { position: _this.getHandPosition() });
|
||||||
} else if (overlayInfo.type === "equip") {
|
} else if (overlayInfo.type === "equip") {
|
||||||
_this.entityPropertyCache.updateEntity(overlayInfo.entityID);
|
_this.entityPropertyCache.updateEntity(overlayInfo.entityID);
|
||||||
props = _this.entityPropertyCache.getProps(overlayInfo.entityID);
|
props = _this.entityPropertyCache.getProps(overlayInfo.entityID);
|
||||||
Overlays.editOverlay(overlayInfo.overlay, { position: props.position, rotation: props.rotation });
|
var entityXform = new Xform(props.rotation, props.position);
|
||||||
|
Overlays.editOverlay(overlayInfo.overlay, {
|
||||||
|
position: entityXform.xformPoint(overlayInfo.localPosition),
|
||||||
|
rotation: props.rotation
|
||||||
|
});
|
||||||
} else if (overlayInfo.type === "near") {
|
} else if (overlayInfo.type === "near") {
|
||||||
_this.entityPropertyCache.updateEntity(overlayInfo.entityID);
|
_this.entityPropertyCache.updateEntity(overlayInfo.entityID);
|
||||||
props = _this.entityPropertyCache.getProps(overlayInfo.entityID);
|
props = _this.entityPropertyCache.getProps(overlayInfo.entityID);
|
||||||
|
@ -998,7 +1015,7 @@ function MyController(hand) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.destroyHotspots = function() {
|
this.destroyHotspots = function() {
|
||||||
this.hotspotOverlays.forEach(function (overlayInfo) {
|
this.hotspotOverlays.forEach(function(overlayInfo) {
|
||||||
Overlays.deleteOverlay(overlayInfo.overlay);
|
Overlays.deleteOverlay(overlayInfo.overlay);
|
||||||
});
|
});
|
||||||
this.hotspotOverlays = [];
|
this.hotspotOverlays = [];
|
||||||
|
@ -1012,14 +1029,14 @@ function MyController(hand) {
|
||||||
this.destroyHotspots();
|
this.destroyHotspots();
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
|
||||||
// Performs ray pick test from the hand controller into the world
|
// Performs ray pick test from the hand controller into the world
|
||||||
// @param {number} which hand to use, RIGHT_HAND or LEFT_HAND
|
// @param {number} which hand to use, RIGHT_HAND or LEFT_HAND
|
||||||
// @returns {object} returns object with two keys entityID and distance
|
// @returns {object} returns object with two keys entityID and distance
|
||||||
//
|
//
|
||||||
this.calcRayPickInfo = function(hand) {
|
this.calcRayPickInfo = function(hand) {
|
||||||
|
|
||||||
var pose = Controller.getPoseValue((hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand);
|
var standardControllerValue = (hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||||
|
var pose = Controller.getPoseValue(standardControllerValue);
|
||||||
var worldHandPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position);
|
var worldHandPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position);
|
||||||
var worldHandRotation = Quat.multiply(MyAvatar.orientation, pose.rotation);
|
var worldHandRotation = Quat.multiply(MyAvatar.orientation, pose.rotation);
|
||||||
|
|
||||||
|
@ -1058,63 +1075,82 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var overlayIntersection = Overlays.findRayIntersection(pickRayBacked);
|
var overlayIntersection = Overlays.findRayIntersection(pickRayBacked);
|
||||||
if (!intersection.intersects || (overlayIntersection.intersects && (intersection.distance > overlayIntersection.distance))) {
|
if (!intersection.intersects ||
|
||||||
|
(overlayIntersection.intersects && (intersection.distance > overlayIntersection.distance))) {
|
||||||
intersection = overlayIntersection;
|
intersection = overlayIntersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intersection.intersects) {
|
if (intersection.intersects) {
|
||||||
return { entityID: intersection.entityID,
|
return {
|
||||||
searchRay: pickRay,
|
entityID: intersection.entityID,
|
||||||
distance: Vec3.distance(pickRay.origin, intersection.intersection) }
|
searchRay: pickRay,
|
||||||
|
distance: Vec3.distance(pickRay.origin, intersection.intersection)
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.entityWantsTrigger = function (entityID) {
|
this.entityWantsTrigger = function(entityID) {
|
||||||
var grabbableProps = this.entityPropertyCache.getGrabbableProps(entityID);
|
var grabbableProps = this.entityPropertyCache.getGrabbableProps(entityID);
|
||||||
return grabbableProps && grabbableProps.wantsTrigger;
|
return grabbableProps && grabbableProps.wantsTrigger;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.entityIsEquippableWithoutDistanceCheck = function (entityID) {
|
// returns a list of all equip-hotspots assosiated with this entity.
|
||||||
|
// @param {UUID} entityID
|
||||||
|
// @returns {Object[]} array of objects with the following fields.
|
||||||
|
// * entityID {UUID}
|
||||||
|
// * localPosition {Vec3} position of the hotspot in object space.
|
||||||
|
// * worldPosition {vec3} position of the hotspot in world space.
|
||||||
|
// * radius {number} radius of equip hotspot
|
||||||
|
// * joints {Object} keys are joint names values are arrays of two elements:
|
||||||
|
// offset position {Vec3} and offset rotation {Quat}, both are in the coordinate system of the joint.
|
||||||
|
this.collectEquipHotspots = function(entityID) {
|
||||||
|
var result = [];
|
||||||
var props = this.entityPropertyCache.getProps(entityID);
|
var props = this.entityPropertyCache.getProps(entityID);
|
||||||
var handPosition = props.position;
|
var entityXform = new Xform(props.rotation, props.position);
|
||||||
return this.entityIsEquippableWithDistanceCheck(entityID, handPosition);
|
var equipHotspotsProps = this.entityPropertyCache.getEquipHotspotsProps(entityID);
|
||||||
|
if (equipHotspotsProps && equipHotspotsProps.length > 0) {
|
||||||
|
var i, length = equipHotspotsProps.length;
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
var hotspot = equipHotspotsProps[i];
|
||||||
|
if (hotspot.position && hotspot.radius && hotspot.joints) {
|
||||||
|
result.push({
|
||||||
|
entityID: entityID,
|
||||||
|
localPosition: hotspot.position,
|
||||||
|
worldPosition: entityXform.xformPoint(hotspot.position),
|
||||||
|
radius: hotspot.radius,
|
||||||
|
joints: hotspot.joints
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var wearableProps = this.entityPropertyCache.getWearableProps(entityID);
|
||||||
|
if (wearableProps && wearableProps.joints) {
|
||||||
|
result.push({
|
||||||
|
entityID: entityID,
|
||||||
|
localPosition: {x: 0, y: 0, z: 0},
|
||||||
|
worldPosition: entityXform.pos,
|
||||||
|
radius: EQUIP_RADIUS,
|
||||||
|
joints: wearableProps.joints
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.entityIsEquippableWithDistanceCheck = function (entityID, handPosition) {
|
this.hotspotIsEquippable = function(hotspot) {
|
||||||
var props = this.entityPropertyCache.getProps(entityID);
|
var props = this.entityPropertyCache.getProps(hotspot.entityID);
|
||||||
var distance = Vec3.distance(props.position, handPosition);
|
var grabProps = this.entityPropertyCache.getGrabProps(hotspot.entityID);
|
||||||
var grabProps = this.entityPropertyCache.getGrabProps(entityID);
|
|
||||||
var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME);
|
var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME);
|
||||||
|
|
||||||
var refCount = ("refCount" in grabProps) ? grabProps.refCount : 0;
|
var refCount = ("refCount" in grabProps) ? grabProps.refCount : 0;
|
||||||
if (refCount > 0) {
|
var okToEquipFromOtherHand = ((this.getOtherHandController().state == STATE_NEAR_GRABBING ||
|
||||||
|
this.getOtherHandController().state == STATE_DISTANCE_HOLDING) &&
|
||||||
|
this.getOtherHandController().grabbedEntity == hotspot.entityID);
|
||||||
|
if (refCount > 0 && !okToEquipFromOtherHand) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
print("equip is skipping '" + props.name + "': it is already grabbed");
|
print("equip is skipping '" + props.name + "': grabbed by someone else");
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distance > EQUIP_RADIUS) {
|
|
||||||
if (debug) {
|
|
||||||
print("equip is skipping '" + props.name + "': too far away, " + distance + " meters");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var wearableProps = this.entityPropertyCache.getWearableProps(entityID);
|
|
||||||
if (!wearableProps || !wearableProps.joints) {
|
|
||||||
if (debug) {
|
|
||||||
print("equip is skipping '" + props.name + "': no wearable attach-point");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
|
|
||||||
if (!wearableProps.joints[handJointName]) {
|
|
||||||
if (debug) {
|
|
||||||
print("equip is skipping '" + props.name + "': no wearable joint for " + handJointName);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1122,7 +1158,7 @@ function MyController(hand) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.entityIsGrabbable = function (entityID) {
|
this.entityIsGrabbable = function(entityID) {
|
||||||
var grabbableProps = this.entityPropertyCache.getGrabbableProps(entityID);
|
var grabbableProps = this.entityPropertyCache.getGrabbableProps(entityID);
|
||||||
var grabProps = this.entityPropertyCache.getGrabProps(entityID);
|
var grabProps = this.entityPropertyCache.getGrabProps(entityID);
|
||||||
var props = this.entityPropertyCache.getProps(entityID);
|
var props = this.entityPropertyCache.getProps(entityID);
|
||||||
|
@ -1255,29 +1291,31 @@ function MyController(hand) {
|
||||||
this.entityPropertyCache.findEntities(handPosition, NEAR_GRAB_RADIUS);
|
this.entityPropertyCache.findEntities(handPosition, NEAR_GRAB_RADIUS);
|
||||||
var candidateEntities = this.entityPropertyCache.getEntities();
|
var candidateEntities = this.entityPropertyCache.getEntities();
|
||||||
|
|
||||||
var equippableEntities = candidateEntities.filter(function (entity) {
|
var equippableHotspots = flatten(candidateEntities.map(function(entityID) {
|
||||||
return _this.entityIsEquippableWithDistanceCheck(entity, handPosition);
|
return _this.collectEquipHotspots(entityID);
|
||||||
|
})).filter(function(hotspot) {
|
||||||
|
return _this.hotspotIsEquippable(hotspot) && Vec3.distance(hotspot.worldPosition, handPosition) < hotspot.radius;
|
||||||
});
|
});
|
||||||
|
|
||||||
var entity;
|
var entity;
|
||||||
if (equippableEntities.length > 0) {
|
if (equippableHotspots.length > 0) {
|
||||||
// sort by distance
|
// sort by distance
|
||||||
equippableEntities.sort(function (a, b) {
|
equippableHotspots.sort(function(a, b) {
|
||||||
var aDistance = Vec3.distance(_this.entityPropertyCache.getProps(a).position, handPosition);
|
var aDistance = Vec3.distance(a.worldPosition, handPosition);
|
||||||
var bDistance = Vec3.distance(_this.entityPropertyCache.getProps(b).position, handPosition);
|
var bDistance = Vec3.distance(b.worldPosition, handPosition);
|
||||||
return aDistance - bDistance;
|
return aDistance - bDistance;
|
||||||
});
|
});
|
||||||
entity = equippableEntities[0];
|
|
||||||
if (this.triggerSmoothedGrab()) {
|
if (this.triggerSmoothedGrab()) {
|
||||||
this.grabbedEntity = entity;
|
this.grabbedHotspot = equippableHotspots[0];
|
||||||
this.setState(STATE_HOLD, "eqipping '" + this.entityPropertyCache.getProps(entity).name + "'");
|
this.grabbedEntity = equippableHotspots[0].entityID;
|
||||||
|
this.setState(STATE_HOLD, "eqipping '" + this.entityPropertyCache.getProps(this.grabbedEntity).name + "'");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// TODO: highlight the equippable object?
|
// TODO: highlight the equippable object?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var grabbableEntities = candidateEntities.filter(function (entity) {
|
var grabbableEntities = candidateEntities.filter(function(entity) {
|
||||||
return _this.entityIsNearGrabbable(entity, handPosition, NEAR_GRAB_MAX_DISTANCE);
|
return _this.entityIsNearGrabbable(entity, handPosition, NEAR_GRAB_MAX_DISTANCE);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1294,7 +1332,7 @@ function MyController(hand) {
|
||||||
|
|
||||||
if (grabbableEntities.length > 0) {
|
if (grabbableEntities.length > 0) {
|
||||||
// sort by distance
|
// sort by distance
|
||||||
grabbableEntities.sort(function (a, b) {
|
grabbableEntities.sort(function(a, b) {
|
||||||
var aDistance = Vec3.distance(_this.entityPropertyCache.getProps(a).position, handPosition);
|
var aDistance = Vec3.distance(_this.entityPropertyCache.getProps(a).position, handPosition);
|
||||||
var bDistance = Vec3.distance(_this.entityPropertyCache.getProps(b).position, handPosition);
|
var bDistance = Vec3.distance(_this.entityPropertyCache.getProps(b).position, handPosition);
|
||||||
return aDistance - bDistance;
|
return aDistance - bDistance;
|
||||||
|
@ -1354,9 +1392,11 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//search line visualizations
|
// search line visualizations
|
||||||
if (USE_ENTITY_LINES_FOR_SEARCHING === true) {
|
if (USE_ENTITY_LINES_FOR_SEARCHING === true) {
|
||||||
this.lineOn(rayPickInfo.searchRay.origin, Vec3.multiply(rayPickInfo.searchRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
this.lineOn(rayPickInfo.searchRay.origin,
|
||||||
|
Vec3.multiply(rayPickInfo.searchRay.direction, LINE_LENGTH),
|
||||||
|
NO_INTERSECT_COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.searchIndicatorOn(rayPickInfo.searchRay);
|
this.searchIndicatorOn(rayPickInfo.searchRay);
|
||||||
|
@ -1371,11 +1411,11 @@ function MyController(hand) {
|
||||||
timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME;
|
timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME;
|
||||||
}
|
}
|
||||||
return timeScale;
|
return timeScale;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.getMass = function(dimensions, density) {
|
this.getMass = function(dimensions, density) {
|
||||||
return (dimensions.x * dimensions.y * dimensions.z) * density;
|
return (dimensions.x * dimensions.y * dimensions.z) * density;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.distanceHoldingEnter = function() {
|
this.distanceHoldingEnter = function() {
|
||||||
|
|
||||||
|
@ -1502,7 +1542,8 @@ function MyController(hand) {
|
||||||
|
|
||||||
var RADIAL_GRAB_AMPLIFIER = 10.0;
|
var RADIAL_GRAB_AMPLIFIER = 10.0;
|
||||||
if (Math.abs(this.grabRadialVelocity) > 0.0) {
|
if (Math.abs(this.grabRadialVelocity) > 0.0) {
|
||||||
this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime * this.grabRadius * RADIAL_GRAB_AMPLIFIER);
|
this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime *
|
||||||
|
this.grabRadius * RADIAL_GRAB_AMPLIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
var newTargetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(controllerRotation));
|
var newTargetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(controllerRotation));
|
||||||
|
@ -1530,30 +1571,9 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// var defaultConstraintData = {
|
|
||||||
// axisStart: false,
|
|
||||||
// axisEnd: false
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var constraintData = getEntityCustomData('lightModifierKey', this.grabbedEntity, defaultConstraintData);
|
|
||||||
// var clampedVector;
|
|
||||||
// var targetPosition;
|
|
||||||
// if (constraintData.axisStart !== false) {
|
|
||||||
// clampedVector = this.projectVectorAlongAxis(this.currentObjectPosition,
|
|
||||||
// constraintData.axisStart,
|
|
||||||
// constraintData.axisEnd);
|
|
||||||
// targetPosition = clampedVector;
|
|
||||||
// } else {
|
|
||||||
// targetPosition = {
|
|
||||||
// x: this.currentObjectPosition.x,
|
|
||||||
// y: this.currentObjectPosition.y,
|
|
||||||
// z: this.currentObjectPosition.z
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
var handPosition = this.getHandPosition();
|
var handPosition = this.getHandPosition();
|
||||||
|
|
||||||
//visualizations
|
// visualizations
|
||||||
if (USE_ENTITY_LINES_FOR_MOVING === true) {
|
if (USE_ENTITY_LINES_FOR_MOVING === true) {
|
||||||
this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR);
|
this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR);
|
||||||
}
|
}
|
||||||
|
@ -1561,7 +1581,7 @@ function MyController(hand) {
|
||||||
this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR);
|
this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR);
|
||||||
}
|
}
|
||||||
if (USE_PARTICLE_BEAM_FOR_MOVING === true) {
|
if (USE_PARTICLE_BEAM_FOR_MOVING === true) {
|
||||||
this.handleDistantParticleBeam(handPosition, grabbedProperties.position, INTERSECT_COLOR)
|
this.handleDistantParticleBeam(handPosition, grabbedProperties.position, INTERSECT_COLOR);
|
||||||
}
|
}
|
||||||
if (USE_POINTLIGHT === true) {
|
if (USE_POINTLIGHT === true) {
|
||||||
this.handlePointLight(this.grabbedEntity);
|
this.handlePointLight(this.grabbedEntity);
|
||||||
|
@ -1621,46 +1641,17 @@ function MyController(hand) {
|
||||||
scalar = 1;
|
scalar = 1;
|
||||||
}
|
}
|
||||||
var projection = Vec3.sum(axisStart, Vec3.multiply(scalar, Vec3.normalize(bPrime)));
|
var projection = Vec3.sum(axisStart, Vec3.multiply(scalar, Vec3.normalize(bPrime)));
|
||||||
return projection
|
return projection;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.hasPresetOffsets = function() {
|
|
||||||
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}});
|
|
||||||
if ("joints" in wearableData) {
|
|
||||||
var allowedJoints = wearableData.joints;
|
|
||||||
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
|
|
||||||
if (handJointName in allowedJoints) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getPresetPosition = function() {
|
|
||||||
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}});
|
|
||||||
var allowedJoints = wearableData.joints;
|
|
||||||
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
|
|
||||||
if (handJointName in allowedJoints) {
|
|
||||||
return allowedJoints[handJointName][0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getPresetRotation = function() {
|
|
||||||
var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}});
|
|
||||||
var allowedJoints = wearableData.joints;
|
|
||||||
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
|
|
||||||
if (handJointName in allowedJoints) {
|
|
||||||
return allowedJoints[handJointName][1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dropGestureReset = function() {
|
this.dropGestureReset = function() {
|
||||||
this.fastHandMoveDetected = false;
|
this.fastHandMoveDetected = false;
|
||||||
this.fastHandMoveTimer = 0;
|
this.fastHandMoveTimer = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dropGestureProcess = function(deltaTime) {
|
this.dropGestureProcess = function(deltaTime) {
|
||||||
var pose = Controller.getPoseValue((this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand);
|
var standardControllerValue = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||||
|
var pose = Controller.getPoseValue(standardControllerValue);
|
||||||
var worldHandVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, pose.velocity);
|
var worldHandVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, pose.velocity);
|
||||||
var worldHandRotation = Quat.multiply(MyAvatar.orientation, pose.rotation);
|
var worldHandRotation = Quat.multiply(MyAvatar.orientation, pose.rotation);
|
||||||
|
|
||||||
|
@ -1710,6 +1701,12 @@ function MyController(hand) {
|
||||||
this.grabbedEntity = saveGrabbedID;
|
this.grabbedEntity = saveGrabbedID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var otherHandController = this.getOtherHandController();
|
||||||
|
if (otherHandController.grabbedEntity == this.grabbedEntity &&
|
||||||
|
(otherHandController.state == STATE_NEAR_GRABBING || otherHandController.state == STATE_DISTANCE_HOLDING)) {
|
||||||
|
otherHandController.setState(STATE_OFF, "other hand grabbed this entity");
|
||||||
|
}
|
||||||
|
|
||||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
||||||
this.activateEntity(this.grabbedEntity, grabbedProperties, false);
|
this.activateEntity(this.grabbedEntity, grabbedProperties, false);
|
||||||
|
|
||||||
|
@ -1718,13 +1715,17 @@ function MyController(hand) {
|
||||||
var handPosition = this.getHandPosition();
|
var handPosition = this.getHandPosition();
|
||||||
|
|
||||||
var hasPresetPosition = false;
|
var hasPresetPosition = false;
|
||||||
if (this.state == STATE_HOLD && this.hasPresetOffsets()) {
|
if (this.state == STATE_HOLD && this.grabbedHotspot) {
|
||||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
||||||
// if an object is "equipped" and has a predefined offset, use it.
|
// if an object is "equipped" and has a predefined offset, use it.
|
||||||
this.ignoreIK = grabbableData.ignoreIK ? grabbableData.ignoreIK : false;
|
this.ignoreIK = grabbableData.ignoreIK ? grabbableData.ignoreIK : false;
|
||||||
this.offsetPosition = this.getPresetPosition();
|
|
||||||
this.offsetRotation = this.getPresetRotation();
|
var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand";
|
||||||
hasPresetPosition = true;
|
if (this.grabbedHotspot.joints[handJointName]) {
|
||||||
|
this.offsetPosition = this.grabbedHotspot.joints[handJointName][0];
|
||||||
|
this.offsetRotation = this.grabbedHotspot.joints[handJointName][1];
|
||||||
|
hasPresetPosition = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.ignoreIK = false;
|
this.ignoreIK = false;
|
||||||
|
|
||||||
|
@ -1757,7 +1758,7 @@ function MyController(hand) {
|
||||||
var reparentProps = {
|
var reparentProps = {
|
||||||
parentID: MyAvatar.sessionUUID,
|
parentID: MyAvatar.sessionUUID,
|
||||||
parentJointIndex: handJointIndex
|
parentJointIndex: handJointIndex
|
||||||
}
|
};
|
||||||
if (hasPresetPosition) {
|
if (hasPresetPosition) {
|
||||||
reparentProps["localPosition"] = this.offsetPosition;
|
reparentProps["localPosition"] = this.offsetPosition;
|
||||||
reparentProps["localRotation"] = this.offsetRotation;
|
reparentProps["localRotation"] = this.offsetRotation;
|
||||||
|
@ -1826,7 +1827,6 @@ function MyController(hand) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
if (now - this.lastUnequipCheckTime > MSECS_PER_SEC * CHECK_TOO_FAR_UNEQUIP_TIME) {
|
if (now - this.lastUnequipCheckTime > MSECS_PER_SEC * CHECK_TOO_FAR_UNEQUIP_TIME) {
|
||||||
this.lastUnequipCheckTime = now;
|
this.lastUnequipCheckTime = now;
|
||||||
|
@ -1995,6 +1995,7 @@ function MyController(hand) {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.grabbedEntity = null;
|
this.grabbedEntity = null;
|
||||||
|
this.grabbedHotspot = null;
|
||||||
|
|
||||||
if (this.triggerSmoothedGrab()) {
|
if (this.triggerSmoothedGrab()) {
|
||||||
this.waitForTriggerRelease = true;
|
this.waitForTriggerRelease = true;
|
||||||
|
@ -2097,7 +2098,7 @@ function MyController(hand) {
|
||||||
print("disconnecting stray child of hand: (" + _this.hand + ") " + childID);
|
print("disconnecting stray child of hand: (" + _this.hand + ") " + childID);
|
||||||
Entities.editEntity(childID, {parentID: NULL_UUID});
|
Entities.editEntity(childID, {parentID: NULL_UUID});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
this.deactivateEntity = function(entityID, noVelocity) {
|
this.deactivateEntity = function(entityID, noVelocity) {
|
||||||
var deactiveProps;
|
var deactiveProps;
|
||||||
|
@ -2122,7 +2123,7 @@ function MyController(hand) {
|
||||||
|
|
||||||
// things that are held by parenting and dropped with no velocity will end up as "static" in bullet. If
|
// things that are held by parenting and dropped with no velocity will end up as "static" in bullet. If
|
||||||
// it looks like the dropped thing should fall, give it a little velocity.
|
// it looks like the dropped thing should fall, give it a little velocity.
|
||||||
var props = Entities.getEntityProperties(entityID, ["parentID", "velocity", "dynamic", "shapeType"])
|
var props = Entities.getEntityProperties(entityID, ["parentID", "velocity", "dynamic", "shapeType"]);
|
||||||
var parentID = props.parentID;
|
var parentID = props.parentID;
|
||||||
|
|
||||||
var doSetVelocity = false;
|
var doSetVelocity = false;
|
||||||
|
@ -2183,6 +2184,10 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
|
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getOtherHandController = function() {
|
||||||
|
return (this.hand === RIGHT_HAND) ? leftController : rightController;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var rightController = new MyController(RIGHT_HAND);
|
var rightController = new MyController(RIGHT_HAND);
|
||||||
|
@ -2204,7 +2209,8 @@ mapping.from([Controller.Standard.RightPrimaryThumb]).peek().to(rightController.
|
||||||
|
|
||||||
Controller.enableMapping(MAPPING_NAME);
|
Controller.enableMapping(MAPPING_NAME);
|
||||||
|
|
||||||
//the section below allows the grab script to listen for messages that disable either one or both hands. useful for two handed items
|
// the section below allows the grab script to listen for messages
|
||||||
|
// that disable either one or both hands. useful for two handed items
|
||||||
var handToDisable = 'none';
|
var handToDisable = 'none';
|
||||||
|
|
||||||
function update(deltaTime) {
|
function update(deltaTime) {
|
||||||
|
@ -2267,7 +2273,7 @@ var handleHandMessages = function(channel, message, sender) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Messages.messageReceived.connect(handleHandMessages);
|
Messages.messageReceived.connect(handleHandMessages);
|
||||||
|
|
||||||
|
|
|
@ -125,8 +125,17 @@ function ignoreMouseActivity() {
|
||||||
weMovedReticle = false;
|
weMovedReticle = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
var MARGIN = 25;
|
||||||
|
var reticleMinX = MARGIN, reticleMaxX, reticleMinY = MARGIN, reticleMaxY;
|
||||||
|
function updateRecommendedArea() {
|
||||||
|
var dims = Controller.getViewportDimensions();
|
||||||
|
reticleMaxX = dims.x - MARGIN;
|
||||||
|
reticleMaxY = dims.y - MARGIN;
|
||||||
|
}
|
||||||
var setReticlePosition = function (point2d) {
|
var setReticlePosition = function (point2d) {
|
||||||
weMovedReticle = true;
|
weMovedReticle = true;
|
||||||
|
point2d.x = Math.max(reticleMinX, Math.min(point2d.x, reticleMaxX));
|
||||||
|
point2d.y = Math.max(reticleMinY, Math.min(point2d.y, reticleMaxY));
|
||||||
Reticle.setPosition(point2d);
|
Reticle.setPosition(point2d);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,6 +196,32 @@ function overlayFromWorldPoint(point) {
|
||||||
return { x: horizontalPixels, y: verticalPixels };
|
return { x: horizontalPixels, y: verticalPixels };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey.
|
||||||
|
var controllerPose = Controller.getPoseValue(activeHand);
|
||||||
|
// Valid if any plugged-in hand controller is "on". (uncradled Hydra, green-lighted Vive...)
|
||||||
|
if (!controllerPose.valid) {
|
||||||
|
return; // Controller is cradled.
|
||||||
|
}
|
||||||
|
var controllerPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, controllerPose.translation),
|
||||||
|
MyAvatar.position);
|
||||||
|
// This gets point direction right, but if you want general quaternion it would be more complicated:
|
||||||
|
var controllerDirection = Quat.getUp(Quat.multiply(MyAvatar.orientation, controllerPose.rotation));
|
||||||
|
|
||||||
|
var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection);
|
||||||
|
if (!hudPoint3d) {
|
||||||
|
if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here
|
||||||
|
print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong.
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var hudPoint2d = overlayFromWorldPoint(hudPoint3d);
|
||||||
|
|
||||||
|
// We don't know yet if we'll want to make the cursor or laser visble, but we need to move it to see if
|
||||||
|
// it's pointing at a QML tool (aka system overlay).
|
||||||
|
setReticlePosition(hudPoint2d);
|
||||||
|
return hudPoint2d;
|
||||||
|
}
|
||||||
|
|
||||||
// MOUSE ACTIVITY --------
|
// MOUSE ACTIVITY --------
|
||||||
//
|
//
|
||||||
var isSeeking = false;
|
var isSeeking = false;
|
||||||
|
@ -351,8 +386,23 @@ function isPointingAtOverlayStartedNonFullTrigger(trigger) {
|
||||||
}
|
}
|
||||||
clickMapping.from(rightTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(rightTrigger)).to(Controller.Actions.ReticleClick);
|
clickMapping.from(rightTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(rightTrigger)).to(Controller.Actions.ReticleClick);
|
||||||
clickMapping.from(leftTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(leftTrigger)).to(Controller.Actions.ReticleClick);
|
clickMapping.from(leftTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(leftTrigger)).to(Controller.Actions.ReticleClick);
|
||||||
clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(Controller.Actions.ContextMenu);
|
// The following is essentially like Left and Right versions of
|
||||||
clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(Controller.Actions.ContextMenu);
|
// clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(Controller.Actions.ContextMenu);
|
||||||
|
// except that we first update the reticle position from the appropriate hand position, before invoking the ContextMenu.
|
||||||
|
var wantsMenu = 0;
|
||||||
|
clickMapping.from(function () { return wantsMenu; }).to(Controller.Actions.ContextMenu);
|
||||||
|
clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(function (clicked) {
|
||||||
|
if (clicked) {
|
||||||
|
activeHudPoint2d(Controller.Standard.RightHand);
|
||||||
|
}
|
||||||
|
wantsMenu = clicked;
|
||||||
|
});
|
||||||
|
clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (clicked) {
|
||||||
|
if (clicked) {
|
||||||
|
activeHudPoint2d(Controller.Standard.LeftHand);
|
||||||
|
}
|
||||||
|
wantsMenu = clicked;
|
||||||
|
});
|
||||||
clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () {
|
clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () {
|
||||||
// Allow the reticle depth to be set correctly:
|
// Allow the reticle depth to be set correctly:
|
||||||
// Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move
|
// Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move
|
||||||
|
@ -398,7 +448,7 @@ function update() {
|
||||||
}
|
}
|
||||||
updateSeeking(true);
|
updateSeeking(true);
|
||||||
if (!handControllerLockOut.expired(now)) {
|
if (!handControllerLockOut.expired(now)) {
|
||||||
return off(); // Let them use mouse it in peace.
|
return off(); // Let them use mouse in peace.
|
||||||
}
|
}
|
||||||
if (!Menu.isOptionChecked("First Person")) {
|
if (!Menu.isOptionChecked("First Person")) {
|
||||||
return off(); // What to do? menus can be behind hand!
|
return off(); // What to do? menus can be behind hand!
|
||||||
|
@ -408,28 +458,13 @@ function update() {
|
||||||
}
|
}
|
||||||
leftTrigger.update();
|
leftTrigger.update();
|
||||||
rightTrigger.update();
|
rightTrigger.update();
|
||||||
var controllerPose = Controller.getPoseValue(activeHand);
|
if (!activeTrigger.state) {
|
||||||
// Valid if any plugged-in hand controller is "on". (uncradled Hydra, green-lighted Vive...)
|
return off(); // No trigger
|
||||||
if (!controllerPose.valid) {
|
|
||||||
return off(); // Controller is cradled.
|
|
||||||
}
|
}
|
||||||
var controllerPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, controllerPose.translation),
|
var hudPoint2d = activeHudPoint2d(activeHand);
|
||||||
MyAvatar.position);
|
if (!hudPoint2d) {
|
||||||
// This gets point direction right, but if you want general quaternion it would be more complicated:
|
|
||||||
var controllerDirection = Quat.getUp(Quat.multiply(MyAvatar.orientation, controllerPose.rotation));
|
|
||||||
|
|
||||||
var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection);
|
|
||||||
if (!hudPoint3d) {
|
|
||||||
if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here
|
|
||||||
print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong.
|
|
||||||
}
|
|
||||||
return off();
|
return off();
|
||||||
}
|
}
|
||||||
var hudPoint2d = overlayFromWorldPoint(hudPoint3d);
|
|
||||||
|
|
||||||
// We don't know yet if we'll want to make the cursor visble, but we need to move it to see if
|
|
||||||
// it's pointing at a QML tool (aka system overlay).
|
|
||||||
setReticlePosition(hudPoint2d);
|
|
||||||
// If there's a HUD element at the (newly moved) reticle, just make it visible and bail.
|
// If there's a HUD element at the (newly moved) reticle, just make it visible and bail.
|
||||||
if (isPointingAtOverlay(hudPoint2d)) {
|
if (isPointingAtOverlay(hudPoint2d)) {
|
||||||
if (HMD.active) {
|
if (HMD.active) {
|
||||||
|
@ -446,23 +481,16 @@ function update() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We are not pointing at a HUD element (but it could be a 3d overlay).
|
// We are not pointing at a HUD element (but it could be a 3d overlay).
|
||||||
if (!activeTrigger.state) {
|
|
||||||
return off(); // No trigger
|
|
||||||
}
|
|
||||||
clearSystemLaser();
|
clearSystemLaser();
|
||||||
Reticle.visible = false;
|
Reticle.visible = false;
|
||||||
}
|
}
|
||||||
|
setupHandler(Script.update, update);
|
||||||
var UPDATE_INTERVAL = 50; // milliseconds. Script.update is too frequent.
|
|
||||||
var updater = Script.setInterval(update, UPDATE_INTERVAL);
|
|
||||||
Script.scriptEnding.connect(function () {
|
|
||||||
Script.clearInterval(updater);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check periodically for changes to setup.
|
// Check periodically for changes to setup.
|
||||||
var SETTINGS_CHANGE_RECHECK_INTERVAL = 10 * 1000; // milliseconds
|
var SETTINGS_CHANGE_RECHECK_INTERVAL = 10 * 1000; // milliseconds
|
||||||
function checkSettings() {
|
function checkSettings() {
|
||||||
updateFieldOfView();
|
updateFieldOfView();
|
||||||
|
updateRecommendedArea();
|
||||||
}
|
}
|
||||||
checkSettings();
|
checkSettings();
|
||||||
var settingsChecker = Script.setInterval(checkSettings, SETTINGS_CHANGE_RECHECK_INTERVAL);
|
var settingsChecker = Script.setInterval(checkSettings, SETTINGS_CHANGE_RECHECK_INTERVAL);
|
||||||
|
|
|
@ -33,6 +33,14 @@ Xform.prototype.mirrorX = function() {
|
||||||
{x: -this.pos.x, y: this.pos.y, z: this.pos.z});
|
{x: -this.pos.x, y: this.pos.y, z: this.pos.z});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Xform.prototype.xformVector = function (vector) {
|
||||||
|
return Vec3.multiplyQbyV(this.rot, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
Xform.prototype.xformPoint = function (point) {
|
||||||
|
return Vec3.sum(Vec3.multiplyQbyV(this.rot, point), this.pos);
|
||||||
|
}
|
||||||
|
|
||||||
Xform.prototype.toString = function() {
|
Xform.prototype.toString = function() {
|
||||||
var rot = this.rot;
|
var rot = this.rot;
|
||||||
var pos = this.pos;
|
var pos = this.pos;
|
||||||
|
|
|
@ -111,8 +111,8 @@ EntityListTool = function(opts) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
webView.visibilityChanged.connect(function (visible) {
|
webView.visibleChanged.connect(function () {
|
||||||
if (visible) {
|
if (webView.visible) {
|
||||||
that.sendUpdate();
|
that.sendUpdate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -309,5 +309,11 @@ calculateHandSizeRatio = function() {
|
||||||
|
|
||||||
clamp = function(val, min, max){
|
clamp = function(val, min, max){
|
||||||
return Math.max(min, Math.min(max, val))
|
return Math.max(min, Math.min(max, val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flattens an array of arrays into a single array
|
||||||
|
// example: flatten([[1], [3, 4], []) => [1, 3, 4]
|
||||||
|
// NOTE: only does one level of flattening, it is not recursive.
|
||||||
|
flatten = function(array) {
|
||||||
|
return [].concat.apply([], array);
|
||||||
|
}
|
||||||
|
|
|
@ -125,18 +125,32 @@
|
||||||
Entities.deleteEntity(this.arrow);
|
Entities.deleteEntity(this.arrow);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
startNearGrab: function(entityID, args) {
|
||||||
|
_this.startEquip(entityID, args);
|
||||||
|
},
|
||||||
|
|
||||||
|
continueNearGrab: function(entityID, args) {
|
||||||
|
_this.continueEquip(entityID, args);
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseGrab: function(entityID, args) {
|
||||||
|
_this.releaseEquip(entityID, args);
|
||||||
|
},
|
||||||
|
|
||||||
startEquip: function(entityID, args) {
|
startEquip: function(entityID, args) {
|
||||||
this.hand = args[0];
|
this.hand = args[0];
|
||||||
avatarID = args[1];
|
avatarID = args[1];
|
||||||
|
|
||||||
//disable the opposite hand in handControllerGrab.js by message
|
//disable the opposite hand in handControllerGrab.js by message
|
||||||
var handToDisable = this.hand === 'right' ? 'left' : 'right';
|
var handToDisable = this.hand === 'right' ? 'left' : 'right';
|
||||||
print("disabling hand: " + handToDisable);
|
|
||||||
Messages.sendMessage('Hifi-Hand-Disabler', handToDisable);
|
Messages.sendMessage('Hifi-Hand-Disabler', handToDisable);
|
||||||
|
|
||||||
var data = getEntityCustomData('grabbableKey', this.entityID, {});
|
var data = getEntityCustomData('grabbableKey', this.entityID, {});
|
||||||
data.grabbable = false;
|
data.grabbable = false;
|
||||||
setEntityCustomData('grabbableKey', this.entityID, data);
|
setEntityCustomData('grabbableKey', this.entityID, data);
|
||||||
|
Entities.editEntity(_this.entityID, {
|
||||||
|
collidesWith: ""
|
||||||
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
continueEquip: function(entityID, args) {
|
continueEquip: function(entityID, args) {
|
||||||
|
@ -169,7 +183,6 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
releaseEquip: function(entityID, args) {
|
releaseEquip: function(entityID, args) {
|
||||||
// print('RELEASE GRAB EVENT')
|
|
||||||
Messages.sendMessage('Hifi-Hand-Disabler', "none")
|
Messages.sendMessage('Hifi-Hand-Disabler', "none")
|
||||||
|
|
||||||
this.stringDrawn = false;
|
this.stringDrawn = false;
|
||||||
|
@ -181,10 +194,12 @@
|
||||||
Entities.deleteEntity(this.arrow);
|
Entities.deleteEntity(this.arrow);
|
||||||
this.aiming = false;
|
this.aiming = false;
|
||||||
this.hasArrowNotched = false;
|
this.hasArrowNotched = false;
|
||||||
|
Entities.editEntity(_this.entityID, {
|
||||||
|
collidesWith: "static,dynamic,kinematic,otherAvatar,myAvatar"
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
createArrow: function() {
|
createArrow: function() {
|
||||||
print('create arrow')
|
|
||||||
this.playArrowNotchSound();
|
this.playArrowNotchSound();
|
||||||
|
|
||||||
var arrow = Entities.addEntity({
|
var arrow = Entities.addEntity({
|
||||||
|
@ -209,25 +224,24 @@
|
||||||
|
|
||||||
var makeArrowStick = function(entityA, entityB, collision) {
|
var makeArrowStick = function(entityA, entityB, collision) {
|
||||||
Entities.editEntity(entityA, {
|
Entities.editEntity(entityA, {
|
||||||
angularVelocity: {
|
angularVelocity: {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: 0
|
z: 0
|
||||||
},
|
},
|
||||||
velocity: {
|
velocity: {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: 0
|
z: 0
|
||||||
},
|
},
|
||||||
gravity: {
|
gravity: {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: 0
|
z: 0
|
||||||
},
|
},
|
||||||
position: collision.contactPoint,
|
position: collision.contactPoint,
|
||||||
dynamic: false
|
dynamic: false
|
||||||
})
|
})
|
||||||
// print('ARROW COLLIDED WITH::' + entityB);
|
|
||||||
Script.removeEventHandler(arrow, "collisionWithEntity", makeArrowStick)
|
Script.removeEventHandler(arrow, "collisionWithEntity", makeArrowStick)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +297,6 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
updateStringPositions: function() {
|
updateStringPositions: function() {
|
||||||
// print('update string positions!!!')
|
|
||||||
var upVector = Quat.getUp(this.bowProperties.rotation);
|
var upVector = Quat.getUp(this.bowProperties.rotation);
|
||||||
var upOffset = Vec3.multiply(upVector, TOP_NOTCH_OFFSET);
|
var upOffset = Vec3.multiply(upVector, TOP_NOTCH_OFFSET);
|
||||||
var downVector = Vec3.multiply(-1, Quat.getUp(this.bowProperties.rotation));
|
var downVector = Vec3.multiply(-1, Quat.getUp(this.bowProperties.rotation));
|
||||||
|
@ -354,7 +367,6 @@
|
||||||
|
|
||||||
if (this.triggerValue < DRAW_STRING_THRESHOLD && this.stringDrawn === true) {
|
if (this.triggerValue < DRAW_STRING_THRESHOLD && this.stringDrawn === true) {
|
||||||
// firing the arrow
|
// firing the arrow
|
||||||
// print('HIT RELEASE LOOP IN CHECK');
|
|
||||||
|
|
||||||
this.drawStrings();
|
this.drawStrings();
|
||||||
this.hasArrowNotched = false;
|
this.hasArrowNotched = false;
|
||||||
|
@ -364,7 +376,6 @@
|
||||||
|
|
||||||
|
|
||||||
} else if (this.triggerValue > DRAW_STRING_THRESHOLD && this.stringDrawn === true) {
|
} else if (this.triggerValue > DRAW_STRING_THRESHOLD && this.stringDrawn === true) {
|
||||||
// print('HIT CONTINUE LOOP IN CHECK')
|
|
||||||
//continuing to aim the arrow
|
//continuing to aim the arrow
|
||||||
|
|
||||||
this.aiming = true;
|
this.aiming = true;
|
||||||
|
@ -372,7 +383,6 @@
|
||||||
this.updateArrowPositionInNotch();
|
this.updateArrowPositionInNotch();
|
||||||
|
|
||||||
} else if (this.triggerValue > DRAW_STRING_THRESHOLD && this.stringDrawn === false) {
|
} else if (this.triggerValue > DRAW_STRING_THRESHOLD && this.stringDrawn === false) {
|
||||||
// print('HIT START LOOP IN CHECK');
|
|
||||||
this.arrow = this.createArrow();
|
this.arrow = this.createArrow();
|
||||||
this.playStringPullSound();
|
this.playStringPullSound();
|
||||||
|
|
||||||
|
@ -461,10 +471,14 @@
|
||||||
// rotation: arrowProps.rotation
|
// rotation: arrowProps.rotation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//actually shoot the arrow and play its sound
|
//actually shoot the arrow and play its sound
|
||||||
Entities.editEntity(this.arrow, arrowProperties);
|
Entities.editEntity(this.arrow, arrowProperties);
|
||||||
this.playShootArrowSound();
|
this.playShootArrowSound();
|
||||||
|
|
||||||
|
var backHand = this.hand === 'left' ? 1 : 0;
|
||||||
|
var haptic = Controller.triggerShortHapticPulse(1, backHand);
|
||||||
|
|
||||||
//clear the strings back to only the single straight one
|
//clear the strings back to only the single straight one
|
||||||
this.deleteStrings();
|
this.deleteStrings();
|
||||||
Entities.editEntity(this.preNotchString, {
|
Entities.editEntity(this.preNotchString, {
|
||||||
|
@ -526,4 +540,4 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Bow();
|
return new Bow();
|
||||||
});
|
});
|
|
@ -62,24 +62,35 @@ function makeBow() {
|
||||||
shapeType: 'compound',
|
shapeType: 'compound',
|
||||||
compoundShapeURL: COLLISION_HULL_URL,
|
compoundShapeURL: COLLISION_HULL_URL,
|
||||||
script: SCRIPT_URL,
|
script: SCRIPT_URL,
|
||||||
|
collidesWith: 'dynamic,kinematic,static',
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
grabbableKey: {
|
grabbableKey: {
|
||||||
invertSolidWhileHeld: true
|
invertSolidWhileHeld: true
|
||||||
},
|
},
|
||||||
wearable:{joints:{RightHand:[{x:0.03960523009300232,
|
wearable: {
|
||||||
y:0.01979270577430725,
|
joints: {
|
||||||
z:0.03294898942112923},
|
RightHand: [{
|
||||||
{x:-0.7257906794548035,
|
x: 0.03960523009300232,
|
||||||
y:-0.4611682891845703,
|
y: 0.01979270577430725,
|
||||||
z:0.4436084032058716,
|
z: 0.03294898942112923
|
||||||
w:-0.25251442193984985}],
|
}, {
|
||||||
LeftHand:[{x:0.0055799782276153564,
|
x: -0.7257906794548035,
|
||||||
y:0.04354757443070412,
|
y: -0.4611682891845703,
|
||||||
z:0.05119767785072327},
|
z: 0.4436084032058716,
|
||||||
{x:-0.14914104342460632,
|
w: -0.25251442193984985
|
||||||
y:0.6448180079460144,
|
}],
|
||||||
z:-0.2888556718826294,
|
LeftHand: [{
|
||||||
w:-0.6917579770088196}]}}
|
x: 0.0055799782276153564,
|
||||||
|
y: 0.04354757443070412,
|
||||||
|
z: 0.05119767785072327
|
||||||
|
}, {
|
||||||
|
x: -0.14914104342460632,
|
||||||
|
y: 0.6448180079460144,
|
||||||
|
z: -0.2888556718826294,
|
||||||
|
w: -0.6917579770088196
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -148,4 +159,4 @@ function cleanup() {
|
||||||
Entities.deleteEntity(preNotchString);
|
Entities.deleteEntity(preNotchString);
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(cleanup);
|
Script.scriptEnding.connect(cleanup);
|
Loading…
Reference in a new issue