Merge branch 'master' into modal_dialogs_async

This commit is contained in:
vladest 2017-09-16 22:06:49 +02:00
commit 5585265349
24 changed files with 283 additions and 197 deletions

View file

@ -486,9 +486,9 @@ ModalWindow {
model: filesModel model: filesModel
function updateSort() { function updateSort() {
model.sortOrder = sortIndicatorOrder; fileTableModel.sortOrder = sortIndicatorOrder;
model.sortColumn = sortIndicatorColumn; fileTableModel.sortColumn = sortIndicatorColumn;
model.update(); fileTableModel.update();
} }
onSortIndicatorColumnChanged: { updateSort(); } onSortIndicatorColumnChanged: { updateSort(); }

View file

@ -484,9 +484,9 @@ TabletModalWindow {
model: filesModel model: filesModel
function updateSort() { function updateSort() {
model.sortOrder = sortIndicatorOrder; fileTableModel.sortOrder = sortIndicatorOrder;
model.sortColumn = sortIndicatorColumn; fileTableModel.sortColumn = sortIndicatorColumn;
model.update(); fileTableModel.update();
} }
onSortIndicatorColumnChanged: { updateSort(); } onSortIndicatorColumnChanged: { updateSort(); }

View file

@ -14,6 +14,8 @@ import "../../windows" as Windows
import QtQuick 2.0 import QtQuick 2.0
import Hifi 1.0 import Hifi 1.0
import Qt.labs.settings 1.0
Windows.ScrollingWindow { Windows.ScrollingWindow {
id: tabletRoot id: tabletRoot
objectName: "tabletRoot" objectName: "tabletRoot"
@ -25,8 +27,32 @@ Windows.ScrollingWindow {
shown: false shown: false
resizable: false resizable: false
Settings {
id: settings
category: "WindowRoot.Windows"
property real width: 480
property real height: 706
}
onResizableChanged: {
if (!resizable) {
// restore default size
settings.width = tabletRoot.width
settings.height = tabletRoot.height
tabletRoot.width = 480
tabletRoot.height = 706
} else {
tabletRoot.width = settings.width
tabletRoot.height = settings.height
}
}
signal showDesktop(); signal showDesktop();
function setResizable(value) {
tabletRoot.resizable = value;
}
function setMenuProperties(rootMenu, subMenu) { function setMenuProperties(rootMenu, subMenu) {
tabletRoot.rootMenu = rootMenu; tabletRoot.rootMenu = rootMenu;
tabletRoot.subMenu = subMenu; tabletRoot.subMenu = subMenu;

View file

@ -36,6 +36,29 @@
static CollisionRenderMeshCache collisionMeshCache; static CollisionRenderMeshCache collisionMeshCache;
void ModelEntityWrapper::setModel(const ModelPointer& model) {
withWriteLock([&] {
if (_model != model) {
_model = model;
if (_model) {
_needsInitialSimulation = true;
}
}
});
}
ModelPointer ModelEntityWrapper::getModel() const {
return resultWithReadLock<ModelPointer>([&] {
return _model;
});
}
bool ModelEntityWrapper::isModelLoaded() const {
return resultWithReadLock<bool>([&] {
return _model.operator bool() && _model->isLoaded();
});
}
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer entity{ new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()) }; EntityItemPointer entity{ new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()) };
entity->setProperties(properties); entity->setProperties(properties);
@ -43,7 +66,7 @@ EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityI
} }
RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized) : RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized) :
ModelEntityItem(entityItemID), ModelEntityWrapper(entityItemID),
_dimensionsInitialized(dimensionsInitialized) { _dimensionsInitialized(dimensionsInitialized) {
} }
@ -83,41 +106,47 @@ QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextu
} }
void RenderableModelEntityItem::doInitialModelSimulation() { void RenderableModelEntityItem::doInitialModelSimulation() {
ModelPointer model = getModel();
if (!model) {
return;
}
// The machinery for updateModelBounds will give existing models the opportunity to fix their // The machinery for updateModelBounds will give existing models the opportunity to fix their
// translation/rotation/scale/registration. The first two are straightforward, but the latter two have guards to // translation/rotation/scale/registration. The first two are straightforward, but the latter two have guards to
// make sure they don't happen after they've already been set. Here we reset those guards. This doesn't cause the // make sure they don't happen after they've already been set. Here we reset those guards. This doesn't cause the
// entity values to change -- it just allows the model to match once it comes in. // entity values to change -- it just allows the model to match once it comes in.
_model->setScaleToFit(false, getDimensions()); model->setScaleToFit(false, getDimensions());
_model->setSnapModelToRegistrationPoint(false, getRegistrationPoint()); model->setSnapModelToRegistrationPoint(false, getRegistrationPoint());
// now recalculate the bounds and registration // now recalculate the bounds and registration
_model->setScaleToFit(true, getDimensions()); model->setScaleToFit(true, getDimensions());
_model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
_model->setRotation(getRotation()); model->setRotation(getRotation());
_model->setTranslation(getPosition()); model->setTranslation(getPosition());
{ {
PerformanceTimer perfTimer("_model->simulate"); PerformanceTimer perfTimer("model->simulate");
_model->simulate(0.0f); model->simulate(0.0f);
} }
_needsInitialSimulation = false; _needsInitialSimulation = false;
} }
void RenderableModelEntityItem::autoResizeJointArrays() { void RenderableModelEntityItem::autoResizeJointArrays() {
if (_model && _model->isLoaded() && !_needsInitialSimulation) { ModelPointer model = getModel();
resizeJointArrays(_model->getJointStateCount()); if (model && model->isLoaded() && !_needsInitialSimulation) {
resizeJointArrays(model->getJointStateCount());
} }
} }
bool RenderableModelEntityItem::needsUpdateModelBounds() const { bool RenderableModelEntityItem::needsUpdateModelBounds() const {
if (!hasModel() || !_model) { ModelPointer model = getModel();
if (!hasModel() || !model) {
return false; return false;
} }
if (!_dimensionsInitialized || !_model->isActive()) { if (!_dimensionsInitialized || !model->isActive()) {
return false; return false;
} }
if (_model->needsReload()) { if (model->needsReload()) {
return true; return true;
} }
@ -129,21 +158,21 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
return true; return true;
} }
if (_model->getScaleToFitDimensions() != getDimensions()) { if (model->getScaleToFitDimensions() != getDimensions()) {
return true; return true;
} }
if (_model->getRegistrationPoint() != getRegistrationPoint()) { if (model->getRegistrationPoint() != getRegistrationPoint()) {
return true; return true;
} }
bool success; bool success;
auto transform = getTransform(success); auto transform = getTransform(success);
if (success) { if (success) {
if (_model->getTranslation() != transform.getTranslation()) { if (model->getTranslation() != transform.getTranslation()) {
return true; return true;
} }
if (_model->getRotation() != transform.getRotation()) { if (model->getRotation() != transform.getRotation()) {
return true; return true;
} }
} }
@ -158,16 +187,6 @@ void RenderableModelEntityItem::updateModelBounds() {
} }
} }
void RenderableModelEntityItem::setModel(const ModelPointer& model) {
withWriteLock([&] {
if (_model != model) {
_model = model;
if (_model) {
_needsInitialSimulation = true;
}
}
});
}
EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
EntityItemProperties properties = ModelEntityItem::getProperties(desiredProperties); // get the properties from our base class EntityItemProperties properties = ModelEntityItem::getProperties(desiredProperties); // get the properties from our base class
@ -175,43 +194,44 @@ EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlag
properties.setTextureNames(_originalTextures); properties.setTextureNames(_originalTextures);
} }
if (_model) { ModelPointer model = getModel();
properties.setRenderInfoVertexCount(_model->getRenderInfoVertexCount()); if (model) {
properties.setRenderInfoTextureCount(_model->getRenderInfoTextureCount()); properties.setRenderInfoVertexCount(model->getRenderInfoVertexCount());
properties.setRenderInfoTextureSize(_model->getRenderInfoTextureSize()); properties.setRenderInfoTextureCount(model->getRenderInfoTextureCount());
properties.setRenderInfoDrawCalls(_model->getRenderInfoDrawCalls()); properties.setRenderInfoTextureSize(model->getRenderInfoTextureSize());
properties.setRenderInfoHasTransparent(_model->getRenderInfoHasTransparent()); properties.setRenderInfoDrawCalls(model->getRenderInfoDrawCalls());
} properties.setRenderInfoHasTransparent(model->getRenderInfoHasTransparent());
if (model->isLoaded()) {
if (_model && _model->isLoaded()) {
// TODO: improve naturalDimensions in the future, // TODO: improve naturalDimensions in the future,
// for now we've added this hack for setting natural dimensions of models // for now we've added this hack for setting natural dimensions of models
Extents meshExtents = _model->getFBXGeometry().getUnscaledMeshExtents(); Extents meshExtents = model->getFBXGeometry().getUnscaledMeshExtents();
properties.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); properties.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum);
properties.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); properties.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum);
} }
}
return properties; return properties;
} }
bool RenderableModelEntityItem::supportsDetailedRayIntersection() const { bool RenderableModelEntityItem::supportsDetailedRayIntersection() const {
return resultWithReadLock<bool>([&] { return isModelLoaded();
return _model && _model->isLoaded();
});
} }
bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const { glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const {
if (!_model) { auto model = getModel();
if (!model) {
return true; return true;
} }
// qCDebug(entitiesrenderer) << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" // qCDebug(entitiesrenderer) << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:"
// << precisionPicking; // << precisionPicking;
QString extraInfo; QString extraInfo;
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, return model->findRayIntersectionAgainstSubMeshes(origin, direction, distance,
face, surfaceNormal, extraInfo, precisionPicking, false); face, surfaceNormal, extraInfo, precisionPicking, false);
} }
@ -242,7 +262,7 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
// parse it twice. // parse it twice.
auto currentCompoundShapeURL = getCompoundShapeURL(); auto currentCompoundShapeURL = getCompoundShapeURL();
ModelEntityItem::setCompoundShapeURL(url); ModelEntityItem::setCompoundShapeURL(url);
if (getCompoundShapeURL() != currentCompoundShapeURL || !_model) { if (getCompoundShapeURL() != currentCompoundShapeURL || !getModel()) {
if (getShapeType() == SHAPE_TYPE_COMPOUND) { if (getShapeType() == SHAPE_TYPE_COMPOUND) {
getCollisionGeometryResource(); getCollisionGeometryResource();
} }
@ -252,17 +272,18 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
bool RenderableModelEntityItem::isReadyToComputeShape() const { bool RenderableModelEntityItem::isReadyToComputeShape() const {
ShapeType type = getShapeType(); ShapeType type = getShapeType();
auto model = getModel();
if (type == SHAPE_TYPE_COMPOUND) { if (type == SHAPE_TYPE_COMPOUND) {
if (!_model || getCompoundShapeURL().isEmpty()) { if (!model || getCompoundShapeURL().isEmpty()) {
return false; return false;
} }
if (_model->getURL().isEmpty()) { if (model->getURL().isEmpty()) {
// we need a render geometry with a scale to proceed, so give up. // we need a render geometry with a scale to proceed, so give up.
return false; return false;
} }
if (_model->isLoaded()) { if (model->isLoaded()) {
if (!getCompoundShapeURL().isEmpty() && !_compoundShapeResource) { if (!getCompoundShapeURL().isEmpty() && !_compoundShapeResource) {
const_cast<RenderableModelEntityItem*>(this)->getCollisionGeometryResource(); const_cast<RenderableModelEntityItem*>(this)->getCollisionGeometryResource();
} }
@ -281,7 +302,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const {
// the model is still being downloaded. // the model is still being downloaded.
return false; return false;
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
return (_model && _model->isLoaded()); return isModelLoaded();
} }
return true; return true;
} }
@ -292,6 +313,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
ShapeType type = getShapeType(); ShapeType type = getShapeType();
glm::vec3 dimensions = getDimensions(); glm::vec3 dimensions = getDimensions();
auto model = getModel();
if (type == SHAPE_TYPE_COMPOUND) { if (type == SHAPE_TYPE_COMPOUND) {
updateModelBounds(); updateModelBounds();
@ -373,14 +395,14 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
// to the visual model and apply them to the collision model (without regard for the // to the visual model and apply them to the collision model (without regard for the
// collision model's extents). // collision model's extents).
glm::vec3 scaleToFit = dimensions / _model->getFBXGeometry().getUnscaledMeshExtents().size(); glm::vec3 scaleToFit = dimensions / model->getFBXGeometry().getUnscaledMeshExtents().size();
// multiply each point by scale before handing the point-set off to the physics engine. // multiply each point by scale before handing the point-set off to the physics engine.
// also determine the extents of the collision model. // also determine the extents of the collision model.
glm::vec3 registrationOffset = dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()); glm::vec3 registrationOffset = dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint());
for (int32_t i = 0; i < pointCollection.size(); i++) { for (int32_t i = 0; i < pointCollection.size(); i++) {
for (int32_t j = 0; j < pointCollection[i].size(); j++) { for (int32_t j = 0; j < pointCollection[i].size(); j++) {
// back compensate for registration so we can apply that offset to the shapeInfo later // back compensate for registration so we can apply that offset to the shapeInfo later
pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + _model->getOffset()) - registrationOffset; pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + model->getOffset()) - registrationOffset;
} }
} }
shapeInfo.setParams(type, dimensions, getCompoundShapeURL()); shapeInfo.setParams(type, dimensions, getCompoundShapeURL());
@ -389,11 +411,11 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
assert(_model && _model->isLoaded()); assert(_model && _model->isLoaded());
updateModelBounds(); updateModelBounds();
_model->updateGeometry(); model->updateGeometry();
// compute meshPart local transforms // compute meshPart local transforms
QVector<glm::mat4> localTransforms; QVector<glm::mat4> localTransforms;
const FBXGeometry& fbxGeometry = _model->getFBXGeometry(); const FBXGeometry& fbxGeometry = model->getFBXGeometry();
int numFbxMeshes = fbxGeometry.meshes.size(); int numFbxMeshes = fbxGeometry.meshes.size();
int totalNumVertices = 0; int totalNumVertices = 0;
glm::mat4 invRegistraionOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT)); glm::mat4 invRegistraionOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
@ -401,7 +423,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
const FBXMesh& mesh = fbxGeometry.meshes.at(i); const FBXMesh& mesh = fbxGeometry.meshes.at(i);
if (mesh.clusters.size() > 0) { if (mesh.clusters.size() > 0) {
const FBXCluster& cluster = mesh.clusters.at(0); const FBXCluster& cluster = mesh.clusters.at(0);
auto jointMatrix = _model->getRig().getJointTransform(cluster.jointIndex); auto jointMatrix = model->getRig().getJointTransform(cluster.jointIndex);
// we backtranslate by the registration offset so we can apply that offset to the shapeInfo later // we backtranslate by the registration offset so we can apply that offset to the shapeInfo later
localTransforms.push_back(invRegistraionOffset * jointMatrix * cluster.inverseBindMatrix); localTransforms.push_back(invRegistraionOffset * jointMatrix * cluster.inverseBindMatrix);
} else { } else {
@ -417,7 +439,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
return; return;
} }
auto& meshes = _model->getGeometry()->getMeshes(); auto& meshes = model->getGeometry()->getMeshes();
int32_t numMeshes = (int32_t)(meshes.size()); int32_t numMeshes = (int32_t)(meshes.size());
const int MAX_ALLOWED_MESH_COUNT = 1000; const int MAX_ALLOWED_MESH_COUNT = 1000;
@ -631,7 +653,8 @@ void RenderableModelEntityItem::setCollisionShape(const btCollisionShape* shape)
} }
bool RenderableModelEntityItem::contains(const glm::vec3& point) const { bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
if (EntityItem::contains(point) && _model && _compoundShapeResource && _compoundShapeResource->isLoaded()) { auto model = getModel();
if (EntityItem::contains(point) && model && _compoundShapeResource && _compoundShapeResource->isLoaded()) {
return _compoundShapeResource->getFBXGeometry().convexHullContains(worldToEntity(point)); return _compoundShapeResource->getFBXGeometry().convexHullContains(worldToEntity(point));
} }
@ -639,11 +662,12 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
} }
bool RenderableModelEntityItem::shouldBePhysical() const { bool RenderableModelEntityItem::shouldBePhysical() const {
auto model = getModel();
// If we have a model, make sure it hasn't failed to download. // If we have a model, make sure it hasn't failed to download.
// If it has, we'll report back that we shouldn't be physical so that physics aren't held waiting for us to be ready. // If it has, we'll report back that we shouldn't be physical so that physics aren't held waiting for us to be ready.
if (_model && getShapeType() == SHAPE_TYPE_COMPOUND && _model->didCollisionGeometryRequestFail()) { if (model && getShapeType() == SHAPE_TYPE_COMPOUND && model->didCollisionGeometryRequestFail()) {
return false; return false;
} else if (_model && getShapeType() != SHAPE_TYPE_NONE && _model->didVisualGeometryRequestFail()) { } else if (model && getShapeType() != SHAPE_TYPE_NONE && model->didVisualGeometryRequestFail()) {
return false; return false;
} else { } else {
return ModelEntityItem::shouldBePhysical(); return ModelEntityItem::shouldBePhysical();
@ -651,9 +675,10 @@ bool RenderableModelEntityItem::shouldBePhysical() const {
} }
glm::quat RenderableModelEntityItem::getAbsoluteJointRotationInObjectFrame(int index) const { glm::quat RenderableModelEntityItem::getAbsoluteJointRotationInObjectFrame(int index) const {
if (_model) { auto model = getModel();
if (model) {
glm::quat result; glm::quat result;
if (_model->getAbsoluteJointRotationInRigFrame(index, result)) { if (model->getAbsoluteJointRotationInRigFrame(index, result)) {
return result; return result;
} }
} }
@ -661,9 +686,10 @@ glm::quat RenderableModelEntityItem::getAbsoluteJointRotationInObjectFrame(int i
} }
glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(int index) const { glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(int index) const {
if (_model) { auto model = getModel();
if (model) {
glm::vec3 result; glm::vec3 result;
if (_model->getAbsoluteJointTranslationInRigFrame(index, result)) { if (model->getAbsoluteJointTranslationInRigFrame(index, result)) {
return result; return result;
} }
} }
@ -671,10 +697,11 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in
} }
bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) {
if (!_model) { auto model = getModel();
if (!model) {
return false; return false;
} }
const Rig& rig = _model->getRig(); const Rig& rig = model->getRig();
int jointParentIndex = rig.getJointParentIndex(index); int jointParentIndex = rig.getJointParentIndex(index);
if (jointParentIndex == -1) { if (jointParentIndex == -1) {
return setLocalJointRotation(index, rotation); return setLocalJointRotation(index, rotation);
@ -700,10 +727,11 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index,
} }
bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) { bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) {
if (!_model) { auto model = getModel();
if (!model) {
return false; return false;
} }
const Rig& rig = _model->getRig(); const Rig& rig = model->getRig();
int jointParentIndex = rig.getJointParentIndex(index); int jointParentIndex = rig.getJointParentIndex(index);
if (jointParentIndex == -1) { if (jointParentIndex == -1) {
@ -730,9 +758,10 @@ bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int ind
} }
glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const { glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const {
if (_model) { auto model = getModel();
if (model) {
glm::quat result; glm::quat result;
if (_model->getJointRotation(index, result)) { if (model->getJointRotation(index, result)) {
return result; return result;
} }
} }
@ -740,9 +769,10 @@ glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const {
} }
glm::vec3 RenderableModelEntityItem::getLocalJointTranslation(int index) const { glm::vec3 RenderableModelEntityItem::getLocalJointTranslation(int index) const {
if (_model) { auto model = getModel();
if (model) {
glm::vec3 result; glm::vec3 result;
if (_model->getJointTranslation(index, result)) { if (model->getJointTranslation(index, result)) {
return result; return result;
} }
} }
@ -810,19 +840,22 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector<bool>& tra
void RenderableModelEntityItem::locationChanged(bool tellPhysics) { void RenderableModelEntityItem::locationChanged(bool tellPhysics) {
PerformanceTimer pertTimer("locationChanged"); PerformanceTimer pertTimer("locationChanged");
EntityItem::locationChanged(tellPhysics); EntityItem::locationChanged(tellPhysics);
if (_model && _model->isLoaded()) { auto model = getModel();
_model->updateRenderItems(); if (model && model->isLoaded()) {
model->updateRenderItems();
} }
} }
int RenderableModelEntityItem::getJointIndex(const QString& name) const { int RenderableModelEntityItem::getJointIndex(const QString& name) const {
return (_model && _model->isActive()) ? _model->getRig().indexOfJoint(name) : -1; auto model = getModel();
return (model && model->isActive()) ? model->getRig().indexOfJoint(name) : -1;
} }
QStringList RenderableModelEntityItem::getJointNames() const { QStringList RenderableModelEntityItem::getJointNames() const {
QStringList result; QStringList result;
if (_model && _model->isActive()) { auto model = getModel();
const Rig& rig = _model->getRig(); if (model && model->isActive()) {
const Rig& rig = model->getRig();
int jointCount = rig.getJointStateCount(); int jointCount = rig.getJointStateCount();
for (int jointIndex = 0; jointIndex < jointCount; jointIndex++) { for (int jointIndex = 0; jointIndex < jointCount; jointIndex++) {
result << rig.nameOfJoint(jointIndex); result << rig.nameOfJoint(jointIndex);
@ -832,19 +865,16 @@ QStringList RenderableModelEntityItem::getJointNames() const {
} }
bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) { bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) {
if (!_model || !_model->isLoaded()) { auto model = getModel();
if (!model || !model->isLoaded()) {
return false; return false;
} }
BLOCKING_INVOKE_METHOD(_model.get(), "getMeshes", Q_RETURN_ARG(MeshProxyList, result)); BLOCKING_INVOKE_METHOD(model.get(), "getMeshes", Q_RETURN_ARG(MeshProxyList, result));
return !result.isEmpty(); return !result.isEmpty();
} }
void RenderableModelEntityItem::copyAnimationJointDataToModel() { void RenderableModelEntityItem::copyAnimationJointDataToModel() {
ModelPointer model; auto model = getModel();
withReadLock([&] {
model = _model;
});
if (!model || !model->isLoaded()) { if (!model || !model->isLoaded()) {
return; return;
} }
@ -859,7 +889,7 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
jointData.rotationDirty = false; jointData.rotationDirty = false;
} }
if (jointData.translationDirty) { if (jointData.translationDirty) {
_model->setJointTranslation(index, true, jointData.joint.translation, 1.0f); model->setJointTranslation(index, true, jointData.joint.translation, 1.0f);
jointData.translationDirty = false; jointData.translationDirty = false;
} }
} }
@ -1192,7 +1222,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating // When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
// we will watch for that and ask the model to update it's render items // we will watch for that and ask the model to update it's render items
if (model->getRenderItemsNeedUpdate()) { if (model->getRenderItemsNeedUpdate()) {
qDebug() << "QQQ" << __FUNCTION__ << "Update model render items" << model->getURL();
model->updateRenderItems(); model->updateRenderItems();
} }

View file

@ -34,10 +34,24 @@ class ModelEntityRenderer;
} } } }
//#define MODEL_ENTITY_USE_FADE_EFFECT //#define MODEL_ENTITY_USE_FADE_EFFECT
class ModelEntityWrapper : public ModelEntityItem {
class RenderableModelEntityItem : public ModelEntityItem { using Parent = ModelEntityItem;
friend class render::entities::ModelEntityRenderer; friend class render::entities::ModelEntityRenderer;
protected:
ModelEntityWrapper(const EntityItemID& entityItemID) : Parent(entityItemID) {}
void setModel(const ModelPointer& model);
ModelPointer getModel() const;
bool isModelLoaded() const;
bool _needsInitialSimulation{ true };
private:
ModelPointer _model;
};
class RenderableModelEntityItem : public ModelEntityWrapper {
friend class render::entities::ModelEntityRenderer;
using Parent = ModelEntityWrapper;
public: public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
@ -97,14 +111,11 @@ private:
bool isAnimatingSomething() const; bool isAnimatingSomething() const;
void autoResizeJointArrays(); void autoResizeJointArrays();
void copyAnimationJointDataToModel(); void copyAnimationJointDataToModel();
void setModel(const ModelPointer& model);
void getCollisionGeometryResource(); void getCollisionGeometryResource();
GeometryResource::Pointer _compoundShapeResource; GeometryResource::Pointer _compoundShapeResource;
bool _originalTexturesRead { false }; bool _originalTexturesRead { false };
QVariantMap _originalTextures; QVariantMap _originalTextures;
ModelPointer _model;
bool _needsInitialSimulation { true };
bool _dimensionsInitialized { true }; bool _dimensionsInitialized { true };
bool _needsJointSimulation { false }; bool _needsJointSimulation { false };
bool _showCollisionGeometry { false }; bool _showCollisionGeometry { false };

View file

@ -425,6 +425,9 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) {
emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL)); emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL));
_currentPathLoaded = VRMENU_SOURCE_URL; _currentPathLoaded = VRMENU_SOURCE_URL;
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
if (_toolbarMode && _desktopWindow) {
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
}
} }
} }
@ -444,6 +447,9 @@ void TabletProxy::loadQMLOnTop(const QVariant& path) {
if (root) { if (root) {
QMetaObject::invokeMethod(root, "loadQMLOnTop", Q_ARG(const QVariant&, path)); QMetaObject::invokeMethod(root, "loadQMLOnTop", Q_ARG(const QVariant&, path));
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
if (_toolbarMode && _desktopWindow) {
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
}
} else { } else {
qCDebug(uiLogging) << "tablet cannot load QML because _qmlTabletRoot is null"; qCDebug(uiLogging) << "tablet cannot load QML because _qmlTabletRoot is null";
} }
@ -470,9 +476,9 @@ void TabletProxy::returnToPreviousApp() {
} }
} }
void TabletProxy::loadQMLSource(const QVariant& path) { void TabletProxy::loadQMLSource(const QVariant& path, bool resizable) {
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "loadQMLSource", Q_ARG(QVariant, path)); QMetaObject::invokeMethod(this, "loadQMLSource", Q_ARG(QVariant, path), Q_ARG(bool, resizable));
return; return;
} }
@ -492,6 +498,10 @@ void TabletProxy::loadQMLSource(const QVariant& path) {
} }
_currentPathLoaded = path; _currentPathLoaded = path;
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
if (_toolbarMode && _desktopWindow) {
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(resizable)));
}
} else { } else {
qCDebug(uiLogging) << "tablet cannot load QML because _qmlTabletRoot is null"; qCDebug(uiLogging) << "tablet cannot load QML because _qmlTabletRoot is null";
} }
@ -523,6 +533,9 @@ bool TabletProxy::pushOntoStack(const QVariant& path) {
} else { } else {
loadQMLSource(path); loadQMLSource(path);
} }
if (_toolbarMode && _desktopWindow) {
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
}
} else { } else {
qCDebug(uiLogging) << "tablet cannot push QML because _qmlTabletRoot or _desktopWindow is null"; qCDebug(uiLogging) << "tablet cannot push QML because _qmlTabletRoot or _desktopWindow is null";
} }
@ -599,6 +612,9 @@ void TabletProxy::loadWebScreenOnTop(const QVariant& url, const QString& injectJ
if (root) { if (root) {
QMetaObject::invokeMethod(root, "loadQMLOnTop", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL))); QMetaObject::invokeMethod(root, "loadQMLOnTop", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL)));
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
if (_toolbarMode && _desktopWindow) {
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
}
QMetaObject::invokeMethod(root, "loadWebOnTop", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectJavaScriptUrl))); QMetaObject::invokeMethod(root, "loadWebOnTop", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectJavaScriptUrl)));
} }
_state = State::Web; _state = State::Web;
@ -625,6 +641,9 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS
QMetaObject::invokeMethod(root, "loadWebBase"); QMetaObject::invokeMethod(root, "loadWebBase");
} }
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
if (_toolbarMode && _desktopWindow) {
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
}
QMetaObject::invokeMethod(root, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl))); QMetaObject::invokeMethod(root, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl)));
} }
_state = State::Web; _state = State::Web;

View file

@ -124,7 +124,7 @@ public:
Q_INVOKABLE void gotoWebScreen(const QString& url); Q_INVOKABLE void gotoWebScreen(const QString& url);
Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase = false); Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase = false);
Q_INVOKABLE void loadQMLSource(const QVariant& path); Q_INVOKABLE void loadQMLSource(const QVariant& path, bool resizable = false);
// FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success); // FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success);
// it should be initialized internally so it cannot fail // it should be initialized internally so it cannot fail
Q_INVOKABLE bool pushOntoStack(const QVariant& path); Q_INVOKABLE bool pushOntoStack(const QVariant& path);

View file

@ -1,15 +1,13 @@
"use strict"; "use strict";
// nearTrigger.js // disableOtherModule.js
// //
// 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 Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, /* global Script, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule,
enableDispatcherModule, disableDispatcherModule, getGrabbableData, Vec3, makeDispatcherModuleParameters, makeRunningValues, getEnabledModuleByName, Messages
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS,
getEnabledModuleByName
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");
@ -20,7 +18,9 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
this.disableModules = false; this.disableModules = false;
this.parameters = makeDispatcherModuleParameters( this.parameters = makeDispatcherModuleParameters(
90, 90,
this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"], this.hand === RIGHT_HAND ?
["rightHand", "rightHandEquip", "rightHandTrigger"] :
["leftHand", "leftHandEquip", "leftHandTrigger"],
[], [],
100); 100);
@ -37,11 +37,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
if (teleportModule) { if (teleportModule) {
var ready = teleportModule.isReady(controllerData); var ready = teleportModule.isReady(controllerData);
if (ready) { if (ready.active) {
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
} }
if (!this.disablemodules) { if (!this.disableModules) {
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
return makeRunningValues(true, [], []); return makeRunningValues(true, [], []);
@ -61,7 +61,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
} }
if (message === 'right') { if (message === 'right') {
rightDisableModules.disableModules = true; rightDisableModules.disableModules = true;
} }
if (message === 'both' || message === 'none') { if (message === 'both' || message === 'none') {
if (message === 'both') { if (message === 'both') {

View file

@ -602,11 +602,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
}; };
this.isTargetIDValid = function() { this.isTargetIDValid = function() {
var entityProperties = Entities.getEntityProperties(this.targetEntityID); var entityProperties = Entities.getEntityProperties(this.targetEntityID, ["type"]);
for (var propertry in entityProperties) { return "type" in entityProperties;
return true;
}
return false;
}; };
this.isReady = function (controllerData, deltaTime) { this.isReady = function (controllerData, deltaTime) {

View file

@ -13,7 +13,7 @@
makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
getControllerWorldLocation, projectOntoEntityXYPlane getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays
*/ */
@ -236,10 +236,10 @@ Script.include("/~/system/libraries/controllers.js");
this.actionID = null; this.actionID = null;
} }
// XXX if (this.actionID !== null) {
// if (this.actionID !== null) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
// this.callEntityMethodOnGrabbed("startDistanceGrab"); Entities.callEntityMethod(this.grabbedThingID, "startDistanceGrab", args);
// } }
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
this.previousRoomControllerPosition = roomControllerPosition; this.previousRoomControllerPosition = roomControllerPosition;
@ -271,8 +271,8 @@ Script.include("/~/system/libraries/controllers.js");
var handMoved = Vec3.multiply(worldHandDelta, radius); var handMoved = Vec3.multiply(worldHandDelta, radius);
this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, handMoved); this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, handMoved);
// XXX var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
// this.callEntityMethodOnGrabbed("continueDistantGrab"); Entities.callEntityMethod(this.grabbedThingID, "continueDistanceGrab", args);
// Update radialVelocity // Update radialVelocity
var lastVelocity = Vec3.multiply(worldHandDelta, 1.0 / deltaObjectTime); var lastVelocity = Vec3.multiply(worldHandDelta, 1.0 / deltaObjectTime);
@ -335,6 +335,10 @@ Script.include("/~/system/libraries/controllers.js");
this.distanceHolding = false; this.distanceHolding = false;
this.distanceRotating = false; this.distanceRotating = false;
Entities.deleteAction(this.grabbedThingID, this.actionID); Entities.deleteAction(this.grabbedThingID, this.actionID);
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
Entities.callEntityMethod(this.grabbedThingID, "releaseGrab", args);
this.actionID = null; this.actionID = null;
this.grabbedThingID = null; this.grabbedThingID = null;
}; };
@ -343,7 +347,8 @@ Script.include("/~/system/libraries/controllers.js");
var intersection = controllerData.rayPicks[this.hand]; var intersection = controllerData.rayPicks[this.hand];
var entityProperty = Entities.getEntityProperties(intersection.objectID); var entityProperty = Entities.getEntityProperties(intersection.objectID);
var entityType = entityProperty.type; var entityType = entityProperty.type;
if ((intersection.type === RayPick.INTERSECTED_ENTITY && entityType === "Web") || intersection.type === RayPick.INTERSECTED_OVERLAY) { if ((intersection.type === RayPick.INTERSECTED_ENTITY && entityType === "Web") ||
intersection.type === RayPick.INTERSECTED_OVERLAY) {
return true; return true;
} }
return false; return false;
@ -354,7 +359,8 @@ Script.include("/~/system/libraries/controllers.js");
this.distanceHolding = false; this.distanceHolding = false;
var worldControllerRotation = getControllerWorldLocation(this.handToController(), true).orientation; var worldControllerRotation = getControllerWorldLocation(this.handToController(), true).orientation;
var controllerRotationDelta = Quat.multiply(worldControllerRotation, Quat.inverse(this.previousWorldControllerRotation)); var controllerRotationDelta =
Quat.multiply(worldControllerRotation, Quat.inverse(this.previousWorldControllerRotation));
// Rotate entity by twice the delta rotation. // Rotate entity by twice the delta rotation.
controllerRotationDelta = Quat.multiply(controllerRotationDelta, controllerRotationDelta); controllerRotationDelta = Quat.multiply(controllerRotationDelta, controllerRotationDelta);
@ -426,7 +432,8 @@ Script.include("/~/system/libraries/controllers.js");
}; };
this.run = function (controllerData) { this.run = function (controllerData) {
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.notPointingAtEntity(controllerData) || this.isPointingAtUI(controllerData)) { if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE ||
this.notPointingAtEntity(controllerData) || this.isPointingAtUI(controllerData)) {
this.endNearGrabAction(); this.endNearGrabAction();
this.laserPointerOff(); this.laserPointerOff();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
@ -471,6 +478,7 @@ Script.include("/~/system/libraries/controllers.js");
for (var j = 0; j < nearGrabReadiness.length; j++) { for (var j = 0; j < nearGrabReadiness.length; j++) {
if (nearGrabReadiness[j].active) { if (nearGrabReadiness[j].active) {
this.laserPointerOff(); this.laserPointerOff();
this.endNearGrabAction();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
} }

View file

@ -6,14 +6,10 @@
// 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 Script, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, Mat4, MyAvatar, Vec3, Camera, Quat, /* global Script, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, MyAvatar, getGrabPointSphereOffset,
getGrabPointSphereOffset, getEnabledModuleByName, makeRunningValues, Entities, NULL_UUID, makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters,
enableDispatcherModule, disableDispatcherModule, entityIsDistanceGrabbable,
makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData
getControllerWorldLocation, projectOntoEntityXYPlane, getGrabbableData
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");

View file

@ -5,13 +5,12 @@
// 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 Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, /* jslint bitwise: true */
NULL_UUID, enableDispatcherModule, disableDispatcherModule, makeRunningValues,
Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, ZERO_VEC, /* global Script, Controller, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, makeRunningValues,
AVATAR_SELF_ID, HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset, Messages, makeDispatcherModuleParameters, AVATAR_SELF_ID, HMD, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE,
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE, TRIGGER_OFF_VALUE, getEnabledModuleByName, PICK_MAX_DISTANCE, getEnabledModuleByName, PICK_MAX_DISTANCE, isInEditMode, LaserPointers, RayPick
isInEditMode
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");

View file

@ -111,6 +111,9 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
grabbedEntity: this.targetEntityID, grabbedEntity: this.targetEntityID,
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
})); }));
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
Entities.callEntityMethod(this.targetEntityID, "startNearGrab", args);
}; };
// this is for when the action is going to time-out // this is for when the action is going to time-out
@ -149,7 +152,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand];
for (var i = 0; i < nearbyEntityProperties.length; i++) { for (var i = 0; i < nearbyEntityProperties.length; i++) {
var props = nearbyEntityProperties[i]; var props = nearbyEntityProperties[i];
var handPosition = controllerData.controllerLocations[this.hand].position;
if (props.distance > NEAR_GRAB_RADIUS) { if (props.distance > NEAR_GRAB_RADIUS) {
break; break;
} }
@ -173,7 +175,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
this.targetEntityID = null; this.targetEntityID = null;
var targetProps = this.getTargetProps(controllerData); var targetProps = this.getTargetProps(controllerData);
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE &&
controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) {
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
@ -192,7 +195,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
this.run = function (controllerData) { this.run = function (controllerData) {
if (this.actionID) { if (this.actionID) {
if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE &&
controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) {
this.endNearGrabAction(); this.endNearGrabAction();
this.hapticTargetID = null; this.hapticTargetID = null;
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);

View file

@ -6,11 +6,10 @@
// 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 Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, /* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, getControllerJointIndex, NULL_UUID,
getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule, enableDispatcherModule, disableDispatcherModule, propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent,
makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE
findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");
@ -176,7 +175,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
this.grabbing = false; this.grabbing = false;
var targetProps = this.getTargetProps(controllerData); var targetProps = this.getTargetProps(controllerData);
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE &&
controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) {
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
@ -195,7 +195,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
this.run = function (controllerData, deltaTime) { this.run = function (controllerData, deltaTime) {
if (this.grabbing) { if (this.grabbing) {
if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE &&
controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) {
this.endNearParentingGrabEntity(); this.endNearParentingGrabEntity();
this.hapticTargetID = null; this.hapticTargetID = null;
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);

View file

@ -6,10 +6,9 @@
// 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 Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, /* global Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, getControllerJointIndex, NULL_UUID,
getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule, enableDispatcherModule, disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, makeDispatcherModuleParameters, Overlays, makeRunningValues, Vec3
makeDispatcherModuleParameters, Overlays, makeRunningValues
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");

View file

@ -6,9 +6,8 @@
// 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 Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, /* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData,
enableDispatcherModule, disableDispatcherModule, getGrabbableData, Vec3, Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");
@ -63,7 +62,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
this.endNearTrigger = function (controllerData) { this.endNearTrigger = function (controllerData) {
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
Entities.callEntityMethod(this.targetEntityID, "endNearTrigger", args); Entities.callEntityMethod(this.targetEntityID, "stopNearTrigger", args);
}; };
this.isReady = function (controllerData) { this.isReady = function (controllerData) {

View file

@ -5,13 +5,11 @@
// 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 Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, /* global Script, Entities, Controller, RIGHT_HAND, LEFT_HAND, NULL_UUID, enableDispatcherModule, disableDispatcherModule,
NULL_UUID, enableDispatcherModule, disableDispatcherModule, makeRunningValues, makeRunningValues, Messages, Quat, Vec3, makeDispatcherModuleParameters, Overlays, ZERO_VEC, AVATAR_SELF_ID, HMD,
Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, ZERO_VEC, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
AVATAR_SELF_ID, HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE,
COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, TRIGGER_OFF_VALUE, getEnabledModuleByName, PICK_MAX_DISTANCE, LaserPointers, RayPick, ContextOverlay
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE, TRIGGER_OFF_VALUE, getEnabledModuleByName, PICK_MAX_DISTANCE,
DISPATCHER_PROPERTIES
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");

View file

@ -7,9 +7,7 @@
// 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 getEntityCustomData, flatten, Xform, Script, Quat, Vec3, MyAvatar, Entities, Overlays, Settings, /* global Script, Vec3, MyAvatar, RIGHT_HAND */
Reticle, Controller, Camera, Messages, Mat4, getControllerWorldLocation, getGrabPointSphereOffset,
setGrabCommunications, Menu, HMD, isInEditMode, AvatarList */
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
(function () { (function () {
@ -37,7 +35,8 @@
}; };
this.triggersPressed = function(controllerData) { this.triggersPressed = function(controllerData) {
if (controllerData.triggerClicks[this.hand] && controllerData.secondaryValues[this.hand] > dispatcherUtils.BUMPER_ON_VALUE) { if (controllerData.triggerClicks[this.hand] &&
controllerData.secondaryValues[this.hand] > dispatcherUtils.BUMPER_ON_VALUE) {
return true; return true;
} }
return false; return false;
@ -58,7 +57,8 @@
var otherModule = this.getOtherModule(); var otherModule = this.getOtherModule();
if (this.triggersPressed(controllerData) && otherModule.triggersPressed(controllerData)) { if (this.triggersPressed(controllerData) && otherModule.triggersPressed(controllerData)) {
if (this.hand === dispatcherUtils.RIGHT_HAND) { if (this.hand === dispatcherUtils.RIGHT_HAND) {
var scalingCurrentDistance = Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position, var scalingCurrentDistance =
Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position,
controllerData.controllerLocations[this.otherHand()].position)); controllerData.controllerLocations[this.otherHand()].position));
var newAvatarScale = (scalingCurrentDistance / this.scalingStartDistance) * this.scalingStartAvatarScale; var newAvatarScale = (scalingCurrentDistance / this.scalingStartDistance) * this.scalingStartAvatarScale;

View file

@ -8,7 +8,8 @@
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, /* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
NULL_UUID, enableDispatcherModule, disableDispatcherModule, makeRunningValues, NULL_UUID, enableDispatcherModule, disableDispatcherModule, makeRunningValues,
Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, ZERO_VEC, Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, ZERO_VEC,
AVATAR_SELF_ID, HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset AVATAR_SELF_ID, HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset,
getEnabledModuleByName
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");
@ -647,7 +648,8 @@ Script.include("/~/system/libraries/controllers.js");
}; };
this.overlayLaserActive = function(controllerData) { this.overlayLaserActive = function(controllerData) {
var overlayLaserModule = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightOverlayLaserInput" : "LeftOverlayLaserInput"); var overlayLaserModule =
getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightOverlayLaserInput" : "LeftOverlayLaserInput");
if (overlayLaserModule) { if (overlayLaserModule) {
return overlayLaserModule.isReady(controllerData).active; return overlayLaserModule.isReady(controllerData).active;
} }

View file

@ -8,11 +8,11 @@
// 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
/* jslint bitwise: true */
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, /* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, getControllerJointIndex, NULL_UUID,
getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule, enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, makeRunningValues, Vec3,
Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions, LaserPointers, RayPick, HMD, Uuid, AvatarList
Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic
*/ */
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
@ -111,7 +111,7 @@ var seatEnd = {
url: SEAT_MODEL_URL, url: SEAT_MODEL_URL,
dimensions: TARGET_MODEL_DIMENSIONS, dimensions: TARGET_MODEL_DIMENSIONS,
ignoreRayIntersection: true ignoreRayIntersection: true
} };
var teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd}, var teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd},
{name: "teleport", path: teleportPath, end: teleportEnd}, {name: "teleport", path: teleportPath, end: teleportEnd},
@ -228,7 +228,7 @@ function Teleporter(hand) {
this.buttonPress = function(value) { this.buttonPress = function(value) {
_this.buttonValue = value; _this.buttonValue = value;
} };
this.parameters = makeDispatcherModuleParameters( this.parameters = makeDispatcherModuleParameters(
80, 80,
@ -249,7 +249,6 @@ function Teleporter(hand) {
}, COOL_IN_DURATION); }, COOL_IN_DURATION);
}; };
this.isReady = function(controllerData, deltaTime) { this.isReady = function(controllerData, deltaTime) {
var otherModule = this.getOtherModule(); var otherModule = this.getOtherModule();
if (_this.buttonValue !== 0 && !otherModule.active) { if (_this.buttonValue !== 0 && !otherModule.active) {
@ -301,7 +300,6 @@ function Teleporter(hand) {
} else { } else {
result = LaserPointers.getPrevRayPickResult(_this.teleportRayHandVisible); result = LaserPointers.getPrevRayPickResult(_this.teleportRayHandVisible);
} }
teleportLocationType = getTeleportTargetType(result); teleportLocationType = getTeleportTargetType(result);
} }
@ -483,7 +481,7 @@ function Teleporter(hand) {
LaserPointers.setIgnoreEntities(teleporter.teleportRayLeftInvisible, ignoredEntities); LaserPointers.setIgnoreEntities(teleporter.teleportRayLeftInvisible, ignoredEntities);
LaserPointers.setIgnoreEntities(teleporter.teleportRayHeadVisible, ignoredEntities); LaserPointers.setIgnoreEntities(teleporter.teleportRayHeadVisible, ignoredEntities);
LaserPointers.setIgnoreEntities(teleporter.teleportRayHeadInvisible, ignoredEntities); LaserPointers.setIgnoreEntities(teleporter.teleportRayHeadInvisible, ignoredEntities);
} };
var isDisabled = false; var isDisabled = false;
var handleTeleportMessages = function(channel, message, sender) { var handleTeleportMessages = function(channel, message, sender) {
@ -501,7 +499,9 @@ function Teleporter(hand) {
if (message === 'none') { if (message === 'none') {
isDisabled = false; isDisabled = false;
} }
} else if (channel === 'Hifi-Teleport-Ignore-Add' && !Uuid.isNull(message) && ignoredEntities.indexOf(message) === -1) { } else if (channel === 'Hifi-Teleport-Ignore-Add' &&
!Uuid.isNull(message) &&
ignoredEntities.indexOf(message) === -1) {
ignoredEntities.push(message); ignoredEntities.push(message);
setIgnoreEntities(); setIgnoreEntities();
} else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) { } else if (channel === 'Hifi-Teleport-Ignore-Remove' && !Uuid.isNull(message)) {

View file

@ -7,13 +7,10 @@
/* jslint bitwise: true */ /* jslint bitwise: true */
/* global Script, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, Mat4, MyAvatar, Vec3, Camera, Quat, /* global Script, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, Vec3, Quat, getGrabPointSphereOffset,
getGrabPointSphereOffset, getEnabledModuleByName, makeRunningValues, Entities, NULL_UUID, makeRunningValues, Entities, NULL_UUID, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters,
enableDispatcherModule, disableDispatcherModule, entityIsDistanceGrabbable,
makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE, ZERO_VEC, Overlays
*/ */
Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllerDispatcherUtils.js");

View file

@ -646,7 +646,7 @@ var toolBar = (function () {
selectionDisplay.triggerMapping.disable(); selectionDisplay.triggerMapping.disable();
tablet.landscape = false; tablet.landscape = false;
} else { } else {
tablet.loadQMLSource("Edit.qml"); tablet.loadQMLSource("Edit.qml", true);
UserActivityLogger.enabledEdit(); UserActivityLogger.enabledEdit();
entityListTool.setVisible(true); entityListTool.setVisible(true);
gridTool.setVisible(true); gridTool.setVisible(true);

View file

@ -5,7 +5,8 @@
// 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 entityIsCloneable:true, getGrabbableData:true, cloneEntity:true propsAreCloneDynamic:true */ /* global entityIsCloneable:true, getGrabbableData:true, cloneEntity:true, propsAreCloneDynamic:true, Script,
propsAreCloneDynamic:true, Entities*/
Script.include("/~/system/controllers/controllerDispatcherUtils.js"); Script.include("/~/system/controllers/controllerDispatcherUtils.js");

View file

@ -39,7 +39,8 @@
projectOntoOverlayXYPlane:true, projectOntoOverlayXYPlane:true,
entityHasActions:true, entityHasActions:true,
ensureDynamic:true, ensureDynamic:true,
findGroupParent:true findGroupParent:true,
BUMPER_ON_VALUE:true
*/ */
MSECS_PER_SEC = 1000.0; MSECS_PER_SEC = 1000.0;